diff --git a/DEV_GUIDELINES.md b/.dev/DEV_GUIDELINES.md similarity index 100% rename from DEV_GUIDELINES.md rename to .dev/DEV_GUIDELINES.md diff --git a/.dev/bookmarks_importer.py b/.dev/bookmarks_importer.py new file mode 100755 index 0000000..983e282 --- /dev/null +++ b/.dev/bookmarks_importer.py @@ -0,0 +1,166 @@ +import sqlite3 +from bs4 import BeautifulSoup +from PIL import Image, UnidentifiedImageError +from io import BytesIO +import re +import base64 +from datetime import datetime, timezone +import os +import argparse + + +""" +Imports html bookmarks file into Flame. +Tested only on Firefox html exports so far. + +Usage: +python3 bookmarks_importer.py --bookmarks --data + +""" + +parser = argparse.ArgumentParser() +parser.add_argument('--bookmarks', type=str, required=True) +parser.add_argument('--data', type=str, required=True) +args = parser.parse_args() + +bookmarks_path = args.bookmarks +data_path = args.data +created = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] + datetime.now().astimezone().strftime(" %z") +updated = created +if data_path[-1] != '/': + data_path = data_path + '/' + + + + +def Base64toPNG(codec, name): + + """ + Convert base64 encoded image to png file + Reference: https://github.com/python-pillow/Pillow/issues/3400#issuecomment-428104239 + + Parameters: + codec (str): icon in html bookmark format.e.g. 'data:image/png;base64,' + name (str): name for export file + + Returns: + icon_name(str): name of png output E.g. 1636473849374--mybookmark.png + None: if image not produced successfully + + """ + + try: + unix_t = str(int(datetime.now(tz=timezone.utc).timestamp() * 1000)) + icon_name = unix_t + '--' + re.sub(r'\W+', '', name).lower() + '.png' + image_path = data_path + 'uploads/' + icon_name + if os.path.exists(image_path): + return image_path + base64_data = re.sub('^data:image/.+;base64,', '', codec) + byte_data = base64.b64decode(base64_data) + image_data = BytesIO(byte_data) + img = Image.open(image_data) + img.save(image_path, "PNG") + return icon_name + except UnidentifiedImageError: + return None + + + + +def FlameBookmarkParser(bookmarks_path): + + """ + Parses HTML bookmarks file + Reference: https://stackoverflow.com/questions/68621107/extracting-bookmarks-and-folder-hierarchy-from-google-chrome-with-beautifulsoup + + Parameters: + bookmarks_path (str): path to bookmarks.html + + Returns: + None + + """ + + soup = BeautifulSoup() + with open(bookmarks_path) as f: + soup = BeautifulSoup(f.read(), 'lxml') + + dt = soup.find_all('dt') + folder_name ='' + for i in dt: + n = i.find_next() + if n.name == 'h3': + folder_name = n.text + continue + else: + url = n.get("href") + website_name = n.text + icon = n.get("icon") + if icon != None: + icon_name = Base64toPNG(icon, website_name) + cat_id = AddFlameCategory(folder_name) + AddFlameBookmark(website_name, url, cat_id, icon_name) + + + + +def AddFlameCategory(cat_name): + """ + Parses HTML bookmarks file + + Parameters: + cat_name (str): category name + + Returns: + cat_id (int): primary key id of cat_name + + """ + + + + con = sqlite3.connect(data_path + 'db.sqlite') + cur = con.cursor() + count_sql = ("SELECT count(*) FROM categories WHERE name = ?;") + cur.execute(count_sql, [cat_name]) + count = int(cur.fetchall()[0][0]) + if count > 0: + getid_sql = ("SELECT id FROM categories WHERE name = ?;") + cur.execute(getid_sql, [cat_name]) + cat_id = int(cur.fetchall()[0][0]) + return cat_id + + is_pinned = 1 + + insert_sql = "INSERT OR IGNORE INTO categories(name, isPinned, createdAt, updatedAt) VALUES (?, ?, ?, ?);" + cur.execute(insert_sql, (cat_name, is_pinned, created, updated)) + con.commit() + + getid_sql = ("SELECT id FROM categories WHERE name = ?;") + cur.execute(getid_sql, [cat_name]) + cat_id = int(cur.fetchall()[0][0]) + return cat_id + + + + +def AddFlameBookmark(website_name, url, cat_id, icon_name): + con = sqlite3.connect(data_path + 'db.sqlite') + cur = con.cursor() + if icon_name == None: + insert_sql = "INSERT OR IGNORE INTO bookmarks(name, url, categoryId, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?);" + cur.execute(insert_sql, (website_name, url, cat_id, created, updated)) + con.commit() + else: + insert_sql = "INSERT OR IGNORE INTO bookmarks(name, url, categoryId, icon, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?);" + cur.execute(insert_sql, (website_name, url, cat_id, icon_name, created, updated)) + con.commit() + + + + + + + + +if __name__ == "__main__": + FlameBookmarkParser(bookmarks_path) \ No newline at end of file diff --git a/.dev/getMdi.js b/.dev/getMdi.js new file mode 100644 index 0000000..19786a8 --- /dev/null +++ b/.dev/getMdi.js @@ -0,0 +1,9 @@ +// Script to get all icon names from materialdesignicons.com +const getMdi = () => { + const icons = document.querySelectorAll('#icons div span'); + const names = [...icons].map((icon) => icon.textContent.replace('mdi-', '')); + const output = names.map((name) => ({ name })); + output.pop(); + const json = JSON.stringify(output); + console.log(json); +}; diff --git a/.env b/.env index 5c6e879..52324f0 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ PORT=5005 NODE_ENV=development -VERSION=1.7.3 \ No newline at end of file +VERSION=1.7.4 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 98ec862..147804b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules data public +!client/public build.sh \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c870d1..d199acc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +### v1.7.4 (2021-11-08) +- Added option to set custom greetings and date ([#103](https://github.com/pawelmalak/flame/issues/103)) +- Fallback to web search if local search has zero results ([#129](https://github.com/pawelmalak/flame/issues/129)) +- Added iOS "Add to homescreen" icon ([#131](https://github.com/pawelmalak/flame/issues/131)) +- Added experimental script to import bookmarks ([#141](https://github.com/pawelmalak/flame/issues/141)) +- Added 3 new themes + ### v1.7.3 (2021-10-28) - Fixed bug with custom CSS not updating diff --git a/Dockerfile b/Dockerfile index fed0789..26b822b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,4 @@ -FROM node:14-alpine - -RUN apk update && apk add --no-cache nano curl +FROM node:14 as builder WORKDIR /app @@ -18,6 +16,12 @@ RUN mkdir -p ./public ./data \ && mv ./client/build/* ./public \ && rm -rf ./client +FROM node:14-alpine + +COPY --from=builder /app /app + +WORKDIR /app + EXPOSE 5005 ENV NODE_ENV=production diff --git a/Dockerfile.multiarch b/Dockerfile.multiarch index 20ff6c2..d0bf6ab 100644 --- a/Dockerfile.multiarch +++ b/Dockerfile.multiarch @@ -1,15 +1,12 @@ -FROM node:14-alpine - -RUN apk update && apk add --no-cache nano curl +FROM node:14 as builder WORKDIR /app COPY package*.json ./ -RUN apk --no-cache --virtual build-dependencies add python make g++ \ - && npm install --production +RUN npm install --production -COPY . . +COPY . . RUN mkdir -p ./public ./data \ && cd ./client \ @@ -17,11 +14,16 @@ RUN mkdir -p ./public ./data \ && npm run build \ && cd .. \ && mv ./client/build/* ./public \ - && rm -rf ./client \ - && apk del build-dependencies + && rm -rf ./client + +FROM node:14-alpine + +COPY --from=builder /app /app + +WORKDIR /app EXPOSE 5005 ENV NODE_ENV=production -CMD ["node", "server.js"] \ No newline at end of file +CMD ["node", "server.js"] diff --git a/README.md b/README.md index e3fd2d7..2a30fa9 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,10 @@ # Flame -[![JS Badge](https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)](https://shields.io/) -[![TS Badge](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)](https://shields.io/) -[![Node Badge](https://img.shields.io/badge/Node.js-43853D?style=for-the-badge&logo=node.js&logoColor=white)](https://shields.io/) -[![React Badge](https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB)](https://shields.io/) - ![Homescreen screenshot](./.github/_home.png) ## Description -Flame is self-hosted startpage for your server. Its design is inspired (heavily) by [SUI](https://github.com/jeroenpardon/sui). Flame is very easy to setup and use. With built-in editors it allows you to setup your very own appliaction hub in no time - no file editing necessary. +Flame is self-hosted startpage for your server. Its design is inspired (heavily) by [SUI](https://github.com/jeroenpardon/sui). Flame is very easy to setup and use. With built-in editors it allows you to setup your very own application hub in no time - no file editing necessary. ## Technology @@ -42,7 +37,15 @@ npm run dev ### With Docker (recommended) -[Docker Hub](https://hub.docker.com/r/pawelmalak/flame) +[Docker Hub link](https://hub.docker.com/r/pawelmalak/flame) + +```sh +docker pull pawelmalak/flame:latest + +# for ARM architecture (e.g. RaspberryPi) +docker pull pawelmalak/flame:multiarch +``` + #### Building images @@ -96,13 +99,14 @@ Follow instructions from wiki: [Installation without Docker](https://github.com/ - Applications - Create, update, delete and organize applications using GUI - - Pin your favourite apps to homescreen + - Pin your favourite apps to the homescreen ![Homescreen screenshot](./.github/_apps.png) - Bookmarks - Create, update, delete and organize bookmarks and categories using GUI - - Pin your favourite categories to homescreen + - Pin your favourite categories to the homescreen + - Import html bookmarks (experimental) ![Homescreen screenshot](./.github/_bookmarks.png) @@ -111,7 +115,7 @@ Follow instructions from wiki: [Installation without Docker](https://github.com/ - Get current temperature, cloud coverage and weather status with animated icons - Themes - - Customize your page by choosing from 12 color themes + - Customize your page by choosing from 15 color themes ![Homescreen screenshot](./.github/_themes.png) @@ -125,23 +129,7 @@ To use search bar you need to type your search query with selected prefix. For e > You can change where to open search results (same/new tab) in the settings -#### Supported search engines - -| Name | Prefix | Search URL | -| ---------- | ------ | ----------------------------------- | -| Disroot | /ds | http://search.disroot.org/search?q= | -| DuckDuckGo | /d | https://duckduckgo.com/?q= | -| Google | /g | https://www.google.com/search?q= | - -#### Supported services - -| Name | Prefix | Search URL | -| ------------------ | ------ | --------------------------------------------- | -| IMDb | /im | https://www.imdb.com/find?q= | -| Reddit | /r | https://www.reddit.com/search?q= | -| Spotify | /sp | https://open.spotify.com/search/ | -| The Movie Database | /mv | https://www.themoviedb.org/search?query= | -| Youtube | /yt | https://www.youtube.com/results?search_query= | +For list of supported search engines, shortcuts and more about searching functionality visit [project wiki](https://github.com/pawelmalak/flame/wiki/Search-bar). ### Setting up weather module @@ -159,13 +147,13 @@ labels: - flame.type=application # "app" works too - flame.name=My container - flame.url=https://example.com - - flame.icon=icon-name # Optional, default is "docker" + - flame.icon=icon-name # optional, default is "docker" # - flame.icon=custom to make changes in app. ie: custom icon upload ``` -And you must have activated the Docker sync option in the settings panel. +> "Use Docker API" option must be enabled for this to work. You can find it in Settings > Other > Docker section -You can set up different apps in the same label adding `;` between each one. +You can also set up different apps in the same label adding `;` between each one. ```yml labels: @@ -208,13 +196,27 @@ metadata: - flame.pawelmalak/type=application # "app" works too - flame.pawelmalak/name=My container - flame.pawelmalak/url=https://example.com - - flame.pawelmalak/icon=icon-name # Optional, default is "kubernetes" + - flame.pawelmalak/icon=icon-name # optional, default is "kubernetes" ``` -And you must have activated the Kubernetes sync option in the settings panel. +> "Use Kubernetes Ingress API" option must be enabled for this to work. You can find it in Settings > Other > Kubernetes section -### Custom CSS +### Import HTML Bookmarks (Experimental) -> This is an experimental feature. Its behaviour might change in the future. -> -> Follow instructions from wiki: [Custom CSS](https://github.com/pawelmalak/flame/wiki/Custom-CSS) \ No newline at end of file +- Requirements + - python3 + - pip packages: Pillow, beautifulsoup4 +- Backup your `db.sqlite` before running script! +- Known Issues: + - generated icons are sometimes incorrect + +```bash +pip3 install Pillow, beautifulsoup4 + +cd flame/.dev +python3 bookmarks_importer.py --bookmarks --data +``` + +### Custom CSS and themes + +See project wiki for [Custom CSS](https://github.com/pawelmalak/flame/wiki/Custom-CSS) and [Custom theme with CSS](https://github.com/pawelmalak/flame/wiki/Custom-theme-with-CSS). diff --git a/client/.env b/client/.env index 18bbaa3..78f7843 100644 --- a/client/.env +++ b/client/.env @@ -1 +1 @@ -REACT_APP_VERSION=1.7.3 \ No newline at end of file +REACT_APP_VERSION=1.7.4 \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 2717839..c693eec 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1806,9 +1806,9 @@ } }, "@mdi/js": { - "version": "5.9.55", - "resolved": "https://registry.npmjs.org/@mdi/js/-/js-5.9.55.tgz", - "integrity": "sha512-BbeHMgeK2/vjdJIRnx12wvQ6s8xAYfvMmEAVsUx9b+7GiQGQ9Za8jpwp17dMKr9CgKRvemlAM4S7S3QOtEbp4A==" + "version": "6.4.95", + "resolved": "https://registry.npmjs.org/@mdi/js/-/js-6.4.95.tgz", + "integrity": "sha512-b1/P//1D2KOzta8YRGyoSLGsAlWyUHfxzVBhV4e/ppnjM4DfBgay/vWz7Eg5Ee80JZ4zsQz8h54X+KOahtBk5Q==" }, "@mdi/react": { "version": "1.5.0", @@ -2047,20 +2047,45 @@ } }, "@testing-library/dom": { - "version": "7.30.4", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.30.4.tgz", - "integrity": "sha512-GObDVMaI4ARrZEXaRy4moolNAxWPKvEYNV/fa6Uc2eAzR/t4otS6A7EhrntPBIQLeehL9DbVhscvvv7gd6hWqA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.0.tgz", + "integrity": "sha512-8Ay4UDiMlB5YWy+ZvCeRyFFofs53ebxrWnOFvCoM1HpMAX4cHyuSrCuIM9l2lVuUWUt+Gr3loz/nCwdrnG6ShQ==", "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^4.2.0", - "aria-query": "^4.2.2", + "aria-query": "^5.0.0", "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.4", + "dom-accessibility-api": "^0.5.9", "lz-string": "^1.4.4", - "pretty-format": "^26.6.2" + "pretty-format": "^27.0.2" }, "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2069,10 +2094,15 @@ "color-convert": "^2.0.1" } }, + "aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==" + }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2096,6 +2126,29 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2107,9 +2160,9 @@ } }, "@testing-library/jest-dom": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.12.0.tgz", - "integrity": "sha512-N9Y82b2Z3j6wzIoAqajlKVF1Zt7sOH0pPee0sUHXHc5cv2Fdn23r+vpWm0MBBoGJtPOly5+Bdx1lnc3CD+A+ow==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.15.0.tgz", + "integrity": "sha512-lOMuQidnL1tWHLEWIhL6UvSZC1Qt3OkNe1khvi2h6xFiqpe5O8arYs46OU0qyUGq0cSTbroQyMktYNXu3a7sAA==", "requires": { "@babel/runtime": "^7.9.2", "@types/testing-library__jest-dom": "^5.9.1", @@ -2117,6 +2170,7 @@ "chalk": "^3.0.0", "css": "^3.0.0", "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", "lodash": "^4.17.15", "redent": "^3.0.0" }, @@ -2191,18 +2245,18 @@ } }, "@testing-library/react": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.6.tgz", - "integrity": "sha512-TXMCg0jT8xmuU8BkKMtp8l7Z50Ykew5WNX8UoIKTaLFwKkP2+1YDhOLA2Ga3wY4x29jyntk7EWfum0kjlYiSjQ==", + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.2.tgz", + "integrity": "sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g==", "requires": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^7.28.1" + "@testing-library/dom": "^8.0.0" } }, "@testing-library/user-event": { - "version": "12.8.3", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", - "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", + "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", "requires": { "@babel/runtime": "^7.12.5" } @@ -2213,9 +2267,9 @@ "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==" }, "@types/aria-query": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.1.tgz", - "integrity": "sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg==" + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" }, "@types/babel__core": { "version": "7.1.14", @@ -2286,9 +2340,9 @@ } }, "@types/history": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz", - "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==" + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz", + "integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==" }, "@types/hoist-non-react-statics": { "version": "3.3.1", @@ -2305,9 +2359,9 @@ "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==" }, "@types/http-proxy": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.6.tgz", - "integrity": "sha512-+qsjqR75S/ib0ig0R9WN+CDoZeOBU6F2XLewgC4KVgdXiNHiKKHFEMRHOrs5PbYE97D5vataw5wPj4KLYfUkuQ==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz", + "integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==", "requires": { "@types/node": "*" } @@ -2334,12 +2388,126 @@ } }, "@types/jest": { - "version": "26.0.23", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.23.tgz", - "integrity": "sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA==", + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.2.tgz", + "integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==", "requires": { - "jest-diff": "^26.0.0", - "pretty-format": "^26.0.0" + "jest-diff": "^27.0.0", + "pretty-format": "^27.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "diff-sequences": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-diff": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.3.1.tgz", + "integrity": "sha512-PCeuAH4AWUo2O5+ksW4pL9v5xJAcIKPUPfIhZBcG1RKv/0+dvaWTQK1Nrau8d67dp65fOqbeMdoil+6PedyEPQ==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.3.1", + "pretty-format": "^27.3.1" + } + }, + "jest-get-type": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.3.1.tgz", + "integrity": "sha512-+Ilqi8hgHSAdhlQ3s12CAVNd8H96ZkQBfYoXmArzZnOfAtVAJEiPDBirjByEblvG/4LPJmkL+nBqPO3A1YJAEg==" + }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, "@types/json-schema": { @@ -2358,9 +2526,9 @@ "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" }, "@types/node": { - "version": "12.20.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.12.tgz", - "integrity": "sha512-KQZ1al2hKOONAs2MFv+yTQP1LkDWMrRJ9YCVRalXltOfXsBmH5IownLxQaiq0lnAHwAViLnh2aTYqrPcRGEbgg==" + "version": "16.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", + "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -2378,9 +2546,9 @@ "integrity": "sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA==" }, "@types/prop-types": { - "version": "15.7.3", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", - "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" }, "@types/q": { "version": "1.5.4", @@ -2388,35 +2556,43 @@ "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" }, "@types/react": { - "version": "17.0.5", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.5.tgz", - "integrity": "sha512-bj4biDB9ZJmGAYTWSKJly6bMr4BLUiBrx9ujiJEoP9XIDY9CTaPGxE5QWN/1WjpPLzYF7/jRNnV2nNxNe970sw==", + "version": "17.0.34", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.34.tgz", + "integrity": "sha512-46FEGrMjc2+8XhHXILr+3+/sTe3OfzSPU9YGKILLrUYbQ1CLQC9Daqo1KzENGXAWwrFwiY0l4ZbF20gRvgpWTg==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, + "@types/react-autosuggest": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/@types/react-autosuggest/-/react-autosuggest-10.1.5.tgz", + "integrity": "sha512-qfMzrp6Is0VYRF5a97Bv/+P2F9ZtFY4YE2825yyWV4VxCpvcfvQHEqGNkDFIPme7t3B2BpQ784QBllYAxemERQ==", + "requires": { + "@types/react": "*" + } + }, "@types/react-beautiful-dnd": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz", - "integrity": "sha512-by80tJ8aTTDXT256Gl+RfLRtFjYbUWOnZuEigJgNsJrSEGxvFe5eY6k3g4VIvf0M/6+xoLgfYWoWonlOo6Wqdg==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz", + "integrity": "sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==", "requires": { "@types/react": "*" } }, "@types/react-dom": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.3.tgz", - "integrity": "sha512-4NnJbCeWE+8YBzupn/YrJxZ8VnjcJq5iR1laqQ1vkpQgBiA7bwk0Rp24fxsdNinzJY2U+HHS4dJJDPdoMjdJ7w==", + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", "requires": { "@types/react": "*" } }, "@types/react-redux": { - "version": "7.1.16", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.16.tgz", - "integrity": "sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz", + "integrity": "sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==", "requires": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -2425,9 +2601,9 @@ } }, "@types/react-router": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.14.tgz", - "integrity": "sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw==", + "version": "5.1.17", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.17.tgz", + "integrity": "sha512-RNSXOyb3VyRs/EOGmjBhhGKTbnN6fHWvy5FNLzWfOWOGjgVUKqJZXfpKzLmgoU8h6Hj8mpALj/mbXQASOb92wQ==", "requires": { "@types/history": "*", "@types/react": "*" @@ -2452,9 +2628,9 @@ } }, "@types/scheduler": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", - "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, "@types/source-list-map": { "version": "0.1.2", @@ -2472,9 +2648,9 @@ "integrity": "sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ==" }, "@types/testing-library__jest-dom": { - "version": "5.9.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.5.tgz", - "integrity": "sha512-ggn3ws+yRbOHog9GxnXiEZ/35Mow6YtPZpd7Z5mKDeZS/o7zx3yAle0ov/wjhVB5QT4N2Dt+GNoGCdqkBGCajQ==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.1.tgz", + "integrity": "sha512-Gk9vaXfbzc5zCXI9eYE9BI5BNHEp4D3FWjgqBE/ePGYElLAP+KvxBcsdkwfIVvezs605oiyd/VrpiHe3Oeg+Aw==", "requires": { "@types/jest": "*" } @@ -3159,11 +3335,18 @@ "integrity": "sha512-1uIESzroqpaTzt9uX48HO+6gfnKu3RwvWdCcWSrX4csMInJfCo1yvKPNXCwXFRpJqRW25tiASb6No0YH57PXqg==" }, "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", "requires": { - "follow-redirects": "^1.10.0" + "follow-redirects": "^1.14.4" + }, + "dependencies": { + "follow-redirects": { + "version": "1.14.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", + "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" + } } }, "axobject-query": { @@ -4906,9 +5089,9 @@ } }, "csstype": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", - "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz", + "integrity": "sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==" }, "cyclist": { "version": "1.0.1", @@ -5227,9 +5410,9 @@ } }, "dom-accessibility-api": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz", - "integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==" + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz", + "integrity": "sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g==" }, "dom-converter": { "version": "0.2.0", @@ -5577,6 +5760,11 @@ "es6-symbol": "^3.1.1" } }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, "es6-symbol": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", @@ -7481,9 +7669,9 @@ } }, "http-proxy-middleware": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.0.tgz", - "integrity": "sha512-S+RN5njuyvYV760aiVKnyuTXqUMcSIvYOsHA891DOVQyrdZOwaXtBHpt9FUVPEDAsOvsPArZp6VXQLs44yvkow==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz", + "integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==", "requires": { "@types/http-proxy": "^1.17.5", "http-proxy": "^1.18.1", @@ -12114,9 +12302,9 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, "prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", "dev": true }, "pretty-bytes": { @@ -12407,6 +12595,18 @@ "whatwg-fetch": "^3.4.1" } }, + "react-autosuggest": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-autosuggest/-/react-autosuggest-10.1.0.tgz", + "integrity": "sha512-/azBHmc6z/31s/lBf6irxPf/7eejQdR0IqnZUzjdSibtlS8+Rw/R79pgDAo6Ft5QqCUTyEQ+f0FhL+1olDQ8OA==", + "requires": { + "es6-promise": "^4.2.8", + "prop-types": "^15.7.2", + "react-themeable": "^1.1.0", + "section-iterator": "^2.0.0", + "shallow-equal": "^1.2.1" + } + }, "react-beautiful-dnd": { "version": "13.1.0", "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", @@ -12548,16 +12748,31 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "react-redux": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.4.tgz", - "integrity": "sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA==", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz", + "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==", "requires": { - "@babel/runtime": "^7.12.1", - "@types/react-redux": "^7.1.16", + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", "hoist-non-react-statics": "^3.3.2", "loose-envify": "^1.4.0", "prop-types": "^15.7.2", - "react-is": "^16.13.1" + "react-is": "^17.0.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.0.tgz", + "integrity": "sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } } }, "react-refresh": { @@ -12677,6 +12892,21 @@ "workbox-webpack-plugin": "5.1.4" } }, + "react-themeable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz", + "integrity": "sha1-fURm3ZsrX6dQWHJ4JenxUro3mg4=", + "requires": { + "object-assign": "^3.0.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + } + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -12793,9 +13023,9 @@ } }, "redux": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", - "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", "requires": { "@babel/runtime": "^7.9.2" } @@ -12806,9 +13036,9 @@ "integrity": "sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==" }, "redux-thunk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", - "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.0.tgz", + "integrity": "sha512-/y6ZKQNU/0u8Bm7ROLq9Pt/7lU93cT0IucYMrubo89ENjxPa7i8pqLKu6V4X7/TvYovQ6x01unTeyeZ9lgXiTA==" }, "regenerate": { "version": "1.4.2", @@ -13511,6 +13741,11 @@ "ajv-keywords": "^3.5.2" } }, + "section-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/section-iterator/-/section-iterator-2.0.0.tgz", + "integrity": "sha1-v0RNev7rlK1Dw5rS+yYVFifMuio=" + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -13685,6 +13920,11 @@ "safe-buffer": "^5.0.1" } }, + "shallow-equal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -14926,9 +15166,9 @@ } }, "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==" + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==" }, "unbox-primitive": { "version": "1.0.1", @@ -15525,9 +15765,9 @@ } }, "web-vitals": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.2.tgz", - "integrity": "sha512-PFMKIY+bRSXlMxVAQ+m2aw9c/ioUYfDgrYot0YUa+/xa0sakubWhSDyxAKwzymvXVdF4CZI71g06W+mqhzu6ig==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.2.tgz", + "integrity": "sha512-nZnEH8dj+vJFqCRYdvYv0a59iLXsb8jJkt+xvXfwgnkyPdsSLtKNlYmtTDiHmTNGXeSXtpjTTUcNvFtrAk6VMQ==" }, "webidl-conversions": { "version": "6.1.0", diff --git a/client/package.json b/client/package.json index 6e05667..1c4a25d 100644 --- a/client/package.json +++ b/client/package.json @@ -3,33 +3,35 @@ "version": "0.1.0", "private": true, "dependencies": { - "@mdi/js": "^5.9.55", + "@mdi/js": "^6.4.95", "@mdi/react": "^1.5.0", - "@testing-library/jest-dom": "^5.12.0", - "@testing-library/react": "^11.2.6", - "@testing-library/user-event": "^12.8.3", - "@types/jest": "^26.0.23", - "@types/node": "^12.20.12", - "@types/react": "^17.0.5", - "@types/react-beautiful-dnd": "^13.0.0", - "@types/react-dom": "^17.0.3", - "@types/react-redux": "^7.1.16", + "@testing-library/jest-dom": "^5.15.0", + "@testing-library/react": "^12.1.2", + "@testing-library/user-event": "^13.5.0", + "@types/jest": "^27.0.2", + "@types/node": "^16.11.6", + "@types/react": "^17.0.34", + "@types/react-autosuggest": "^10.1.5", + "@types/react-beautiful-dnd": "^13.1.2", + "@types/react-dom": "^17.0.11", + "@types/react-redux": "^7.1.20", "@types/react-router-dom": "^5.1.7", - "axios": "^0.21.1", + "axios": "^0.24.0", "external-svg-loader": "^1.3.4", - "http-proxy-middleware": "^2.0.0", + "http-proxy-middleware": "^2.0.1", "react": "^17.0.2", + "react-autosuggest": "^10.1.0", "react-beautiful-dnd": "^13.1.0", "react-dom": "^17.0.2", - "react-redux": "^7.2.4", + "react-redux": "^7.2.6", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", - "redux": "^4.1.0", + "redux": "^4.1.2", "redux-devtools-extension": "^2.13.9", - "redux-thunk": "^2.3.0", + "redux-thunk": "^2.4.0", "skycons-ts": "^0.2.0", - "typescript": "^4.2.4", - "web-vitals": "^1.1.2" + "typescript": "^4.4.4", + "web-vitals": "^2.1.2" }, "scripts": { "start": "react-scripts start", @@ -56,6 +58,6 @@ ] }, "devDependencies": { - "prettier": "^2.3.2" + "prettier": "^2.4.1" } } diff --git a/client/public/icons/apple-touch-icon-114x114.png b/client/public/icons/apple-touch-icon-114x114.png new file mode 100644 index 0000000..301cd25 Binary files /dev/null and b/client/public/icons/apple-touch-icon-114x114.png differ diff --git a/client/public/icons/apple-touch-icon-120x120.png b/client/public/icons/apple-touch-icon-120x120.png new file mode 100644 index 0000000..28ba56d Binary files /dev/null and b/client/public/icons/apple-touch-icon-120x120.png differ diff --git a/client/public/icons/apple-touch-icon-144x144.png b/client/public/icons/apple-touch-icon-144x144.png new file mode 100644 index 0000000..f13012b Binary files /dev/null and b/client/public/icons/apple-touch-icon-144x144.png differ diff --git a/client/public/icons/apple-touch-icon-152x152.png b/client/public/icons/apple-touch-icon-152x152.png new file mode 100644 index 0000000..e1a5b1d Binary files /dev/null and b/client/public/icons/apple-touch-icon-152x152.png differ diff --git a/client/public/icons/apple-touch-icon-180x180.png b/client/public/icons/apple-touch-icon-180x180.png new file mode 100644 index 0000000..33d6131 Binary files /dev/null and b/client/public/icons/apple-touch-icon-180x180.png differ diff --git a/client/public/icons/apple-touch-icon-57x57.png b/client/public/icons/apple-touch-icon-57x57.png new file mode 100644 index 0000000..b07d1da Binary files /dev/null and b/client/public/icons/apple-touch-icon-57x57.png differ diff --git a/client/public/icons/apple-touch-icon-72x72.png b/client/public/icons/apple-touch-icon-72x72.png new file mode 100644 index 0000000..0ebf2c8 Binary files /dev/null and b/client/public/icons/apple-touch-icon-72x72.png differ diff --git a/client/public/icons/apple-touch-icon-76x76.png b/client/public/icons/apple-touch-icon-76x76.png new file mode 100644 index 0000000..d636fe9 Binary files /dev/null and b/client/public/icons/apple-touch-icon-76x76.png differ diff --git a/client/public/icons/apple-touch-icon.png b/client/public/icons/apple-touch-icon.png new file mode 100644 index 0000000..b07d1da Binary files /dev/null and b/client/public/icons/apple-touch-icon.png differ diff --git a/client/public/favicon.ico b/client/public/icons/favicon.ico similarity index 100% rename from client/public/favicon.ico rename to client/public/icons/favicon.ico diff --git a/client/public/index.html b/client/public/index.html index c93d95e..32e17fe 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -2,7 +2,51 @@ - + + + + + + + + + + { + const [dateTime, setDateTime] = useState(getDateTime()); + const [greeting, setGreeting] = useState(greeter()); + + useEffect(() => { + let dateTimeInterval: NodeJS.Timeout; + + dateTimeInterval = setInterval(() => { + setDateTime(getDateTime()); + setGreeting(greeter()); + }, 1000); + + return () => window.clearInterval(dateTimeInterval); + }, []); + + return ( +
+

{dateTime}

+ + Go to Settings + + +

{greeting}

+ +
+
+ ); +}; + +const mapStateToProps = (state: GlobalState) => { + return { + config: state.config.config, + }; +}; + +export default connect(mapStateToProps)(Header); diff --git a/client/src/components/Home/functions/dateTime.ts b/client/src/components/Home/Header/functions/getDateTime.ts similarity index 78% rename from client/src/components/Home/functions/dateTime.ts rename to client/src/components/Home/Header/functions/getDateTime.ts index ddcfc70..db79c69 100644 --- a/client/src/components/Home/functions/dateTime.ts +++ b/client/src/components/Home/Header/functions/getDateTime.ts @@ -1,5 +1,5 @@ -export const dateTime = (): string => { - const days = [ +export const getDateTime = (): string => { + const days = localStorage.getItem('daySchema')?.split(';') || [ 'Sunday', 'Monday', 'Tuesday', @@ -8,7 +8,8 @@ export const dateTime = (): string => { 'Friday', 'Saturday', ]; - const months = [ + + const months = localStorage.getItem('monthSchema')?.split(';') || [ 'January', 'February', 'March', diff --git a/client/src/components/Home/Header/functions/greeter.ts b/client/src/components/Home/Header/functions/greeter.ts new file mode 100644 index 0000000..93b32b4 --- /dev/null +++ b/client/src/components/Home/Header/functions/greeter.ts @@ -0,0 +1,17 @@ +export const greeter = (): string => { + const now = new Date().getHours(); + let msg: string; + + const greetingsSchemaRaw = + localStorage.getItem('greetingsSchema') || + 'Good evening!;Good afternoon!;Good morning!;Good night!'; + const greetingsSchema = greetingsSchemaRaw.split(';'); + + if (now >= 18) msg = greetingsSchema[0]; + else if (now >= 12) msg = greetingsSchema[1]; + else if (now >= 6) msg = greetingsSchema[2]; + else if (now >= 0) msg = greetingsSchema[3]; + else msg = 'Hello!'; + + return msg; +}; diff --git a/client/src/components/Home/Home.module.css b/client/src/components/Home/Home.module.css index 652ca22..f425184 100644 --- a/client/src/components/Home/Home.module.css +++ b/client/src/components/Home/Home.module.css @@ -1,24 +1,3 @@ -.Header h1 { - color: var(--color-primary); - font-weight: 700; - font-size: 4em; - display: inline-block; -} - -.Header p { - color: var(--color-primary); - font-weight: 300; - text-transform: uppercase; - height: 30px; -} - -.HeaderMain { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 2.5rem; -} - .SettingsButton { width: 35px; height: 35px; @@ -40,21 +19,12 @@ opacity: 1; } -.SettingsLink { - visibility: visible; - color: var(--color-accent); -} - @media (min-width: 769px) { .SettingsButton { visibility: visible; } - - .SettingsLink { - visibility: hidden; - } } .HomeSpace { height: 20px; -} \ No newline at end of file +} diff --git a/client/src/components/Home/Home.tsx b/client/src/components/Home/Home.tsx index 4a0adbe..017df9c 100644 --- a/client/src/components/Home/Home.tsx +++ b/client/src/components/Home/Home.tsx @@ -21,12 +21,8 @@ import classes from './Home.module.css'; // Components import AppGrid from '../Apps/AppGrid/AppGrid'; import BookmarkGrid from '../Bookmarks/BookmarkGrid/BookmarkGrid'; -import WeatherWidget from '../Widgets/WeatherWidget/WeatherWidget'; import SearchBar from '../SearchBar/SearchBar'; - -// Functions -import { greeter } from './functions/greeter'; -import { dateTime } from './functions/dateTime'; +import Header from './Header/Header'; interface ComponentProps { getApps: Function; @@ -48,11 +44,6 @@ const Home = (props: ComponentProps): JSX.Element => { categoriesLoading, } = props; - const [header, setHeader] = useState({ - dateTime: dateTime(), - greeting: greeter(), - }); - // Local search query const [localSearch, setLocalSearch] = useState(null); const [appSearchResult, setAppSearchResult] = useState(null); @@ -74,23 +65,6 @@ const Home = (props: ComponentProps): JSX.Element => { } }, [getCategories]); - // Refresh greeter and time - useEffect(() => { - let interval: any; - - // Start interval only when hideHeader is false - if (!props.config.hideHeader) { - interval = setInterval(() => { - setHeader({ - dateTime: dateTime(), - greeting: greeter(), - }); - }, 1000); - } - - return () => clearInterval(interval); - }, []); - useEffect(() => { if (localSearch) { // Search through apps @@ -126,20 +100,7 @@ const Home = (props: ComponentProps): JSX.Element => {
)} - {!props.config.hideHeader ? ( -
-

{header.dateTime}

- - Go to Settings - - -

{header.greeting}

- -
-
- ) : ( -
- )} + {!props.config.hideHeader ?
:
} {!props.config.hideApps ? ( diff --git a/client/src/components/Home/functions/greeter.ts b/client/src/components/Home/functions/greeter.ts deleted file mode 100644 index 64cb2ea..0000000 --- a/client/src/components/Home/functions/greeter.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const greeter = (): string => { - const now = new Date().getHours(); - let msg: string; - - if (now >= 18) msg = 'Good evening!'; - else if (now >= 12) msg = 'Good afternoon!'; - else if (now >= 6) msg = 'Good morning!'; - else if (now >= 0) msg = 'Good night!'; - else msg = 'Hello!'; - - return msg; -} \ No newline at end of file diff --git a/client/src/components/SearchBar/SearchBar.tsx b/client/src/components/SearchBar/SearchBar.tsx index 7a91525..2dad112 100644 --- a/client/src/components/SearchBar/SearchBar.tsx +++ b/client/src/components/SearchBar/SearchBar.tsx @@ -91,8 +91,18 @@ const SearchBar = (props: ComponentProps): JSX.Element => { // Local query -> redirect if at least 1 result found if (appSearchResult?.length) { redirectUrl(appSearchResult[0].url, sameTab); - } else if (bookmarkSearchResult?.length) { + } else if (bookmarkSearchResult?.[0]?.bookmarks?.length) { redirectUrl(bookmarkSearchResult[0].bookmarks[0].url, sameTab); + } else { + // no local results -> search the internet with the default search provider + let template = query.template; + + if (query.prefix === 'l') { + template = 'https://duckduckgo.com/?q='; + } + + const url = `${template}${search}`; + redirectUrl(url, sameTab); } } else { // Valid query -> redirect to search results diff --git a/client/src/components/Settings/OtherSettings/OtherSettings.tsx b/client/src/components/Settings/OtherSettings/OtherSettings.tsx index 6610b65..c5b45ae 100644 --- a/client/src/components/Settings/OtherSettings/OtherSettings.tsx +++ b/client/src/components/Settings/OtherSettings/OtherSettings.tsx @@ -81,6 +81,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => {
formSubmitHandler(e)}> {/* OTHER OPTIONS */} + {/* PAGE TITLE */} { onChange={(e) => inputChangeHandler(e)} /> + + {/* DATE FORMAT */} + + {/* PIN CATEGORIES */} + + {/* SORT TYPE */} + + {/* APPS OPPENING */} + + {/* BOOKMARKS OPPENING */} { + + {/* CUSTOM GREETINGS */} + + + inputChangeHandler(e)} + /> + + Greetings must be separated with semicolon. Only 4 messages can be + used + + + + {/* CUSTOM DAYS */} + + + inputChangeHandler(e)} + /> + Names must be separated with semicolon + + + {/* CUSTOM MONTHS */} + + + inputChangeHandler(e)} + /> + Names must be separated with semicolon + + + {/* HIDE APPS */} + + {/* HIDE CATEGORIES */} { onChange={(e) => inputChangeHandler(e)} /> + + {/* USE DOCKER API */} + + {/* UNPIN DOCKER APPS */}