diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..db36dec --- /dev/null +++ b/.metadata @@ -0,0 +1,36 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: android + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: ios + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: web + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/Dockerfile b/Dockerfile index 02ad197..736e6fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,5 @@ -FROM archlinux -WORKDIR /app -RUN pacman --noconfirm -Syu -ARG FIREBASE_KEY -ARG FIREBASE_MESSAGING -ARG FIREBASE_STORAGE -ARG FIREBASE_APPID -ARG FIREBASE_AUTH -ARG FIREBASE_ID -ENV FIREBASE_KEY=$FIREBASE_KEY -ENV FIREBASE_MESSAGING=$FIREBASE_MESSAGING -ENV FIREBASE_STORAGE=$FIREBASE_STORAGE -ENV FIREBASE_APPID=$FIREBASE_APPID -ENV FIREBASE_AUTH=$FIREBASE_AUTH -ENV FIREBASE_ID=$FIREBASE_ID +FROM passsy/flutterw:base-latest COPY . . -RUN pacman --noconfirm -S nodejs npm git base-devel unzip -RUN npm i -g pnpm RUN ./flutterw config --no-analytics -RUN cd api && pnpm i && pnpm run build -ENTRYPOINT PORT=80 node /app/api/build/index.js +ENTRYPOINT ./flutterw run --release --web-port=80 --web-hostname 0.0.0.0 -d web-server EXPOSE 80 \ No newline at end of file diff --git a/README.md b/README.md index a607d33..7571ac9 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Vydáno pod licencí AGPL verze 3 1. Clone 2. Build -## Obrázky (verze 1.x) +## Obrázky ![Screenshot přihlašovací obrazovky](images/01.png) ![Screenshot přihlašovací obrazovky](images/02.png) ![Screenshot přihlašovací obrazovky](images/03.png) diff --git a/api/.eslintrc.json b/api/.eslintrc.json deleted file mode 100644 index 58ce467..0000000 --- a/api/.eslintrc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "env": { - "es2021": true, - "node": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended" - ], - "overrides": [ - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint" - ], - "rules": { - }, - "ignorePatterns":[ - "src/public" - ] -} diff --git a/api/.gitignore b/api/.gitignore deleted file mode 100644 index 181500d..0000000 --- a/api/.gitignore +++ /dev/null @@ -1,181 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/linux,visualstudiocode,node -# Edit at https://www.toptal.com/developers/gitignore?templates=linux,visualstudiocode,node - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* - -### Node Patch ### -# Serverless Webpack directories -.webpack/ - -# Optional stylelint cache - -# SvelteKit build / generate output -.svelte-kit - -### VisualStudioCode ### -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -!.vscode/*.code-snippets - -# Local History for Visual Studio Code -.history/ - -# Built Visual Studio Code Extensions -*.vsix - -### VisualStudioCode Patch ### -# Ignore all local history of files -.history -.ionide - -# End of https://www.toptal.com/developers/gitignore/api/linux,visualstudiocode,node -build -src/public/* -!src/public/.gitkeep \ No newline at end of file diff --git a/api/README.md b/api/README.md deleted file mode 100644 index 8526b27..0000000 --- a/api/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Tourdeappka NodeJS API server -(c) 2023 Matyáš Caras a Richard Pavlikán - -## Požadavky -- [NodeJS](https://nodejs.org) LTS verze (16+) -- [pnpm](https://pnpm.io) - -## Jak spustit -1. Nainstaluj NodeJS -2. Nainstaluj pNPM -3. Stáhni repozitář -4. Nainstaluj závislosti (`pnpm i`) -### K vývoji -5. Vytvoř soubor `.env`: -```js -FIREBASE_KEY=klic -FIREBASE_AUTH=nejakaurl -FIREBASE_ID=idcko -FIREBASE_STORAGE=nejakaurl -FIREBASE_MESSAGING=idcko -FIREBASE_APPID=idcko -``` -6. Spusť pomocí `pnpm run dev` -### Live server -5. Ulož proměnné dle předchozí struktury jako systémové proměnné -6. Spusť pomocí `pnpm start` \ No newline at end of file diff --git a/api/package.json b/api/package.json deleted file mode 100644 index 2e6650a..0000000 --- a/api/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "api", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "dev": "NODE_DEBUG=true ts-node ./src", - "build": "pnpm run clean && pnpm run flutter && tsc -p tsconfig.json && cp -r ./src/public ./build/public", - "clean": "rm -rf ./build", - "start": "pnpm run build && node ./build", - "flutter": "cd .. && ./flutterw clean && ./flutterw pub get && ./flutterw build web --release && rm -rf ./api/src/public/* && mv ./build/web/* ./api/src/public" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "@types/node": "^18.14.0", - "@typescript-eslint/eslint-plugin": "^5.52.0", - "@typescript-eslint/parser": "^5.52.0", - "dotenv": "^16.0.3", - "eslint": "^8.34.0", - "ts-node": "^10.9.1", - "typescript": "^4.9.5" - }, - "dependencies": { - "@fastify/static": "^6.9.0", - "fastify": "^4.13.0", - "firebase": "^9.17.1" - } -} diff --git a/api/pnpm-lock.yaml b/api/pnpm-lock.yaml deleted file mode 100644 index 4930812..0000000 --- a/api/pnpm-lock.yaml +++ /dev/null @@ -1,2209 +0,0 @@ -lockfileVersion: 5.4 - -specifiers: - '@fastify/static': ^6.9.0 - '@types/node': ^18.14.0 - '@typescript-eslint/eslint-plugin': ^5.52.0 - '@typescript-eslint/parser': ^5.52.0 - dotenv: ^16.0.3 - eslint: ^8.34.0 - fastify: ^4.13.0 - firebase: ^9.17.1 - ts-node: ^10.9.1 - typescript: ^4.9.5 - -dependencies: - '@fastify/static': 6.9.0 - fastify: 4.13.0 - firebase: 9.17.1 - -devDependencies: - '@types/node': 18.14.0 - '@typescript-eslint/eslint-plugin': 5.52.0_6cfvjsbua5ptj65675bqcn6oza - '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm - dotenv: 16.0.3 - eslint: 8.34.0 - ts-node: 10.9.1_tncu2ai53lzgmizdedur7lbibe - typescript: 4.9.5 - -packages: - - /@cspotcode/source-map-support/0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@eslint/eslintrc/1.4.1: - resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.4.1 - globals: 13.20.0 - ignore: 5.2.4 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@fastify/accept-negotiator/1.1.0: - resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} - engines: {node: '>=14'} - dev: false - - /@fastify/ajv-compiler/3.5.0: - resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} - dependencies: - ajv: 8.12.0 - ajv-formats: 2.1.1 - fast-uri: 2.2.0 - dev: false - - /@fastify/deepmerge/1.3.0: - resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==} - dev: false - - /@fastify/error/3.2.0: - resolution: {integrity: sha512-KAfcLa+CnknwVi5fWogrLXgidLic+GXnLjijXdpl8pvkvbXU5BGa37iZO9FGvsh9ZL4y+oFi5cbHBm5UOG+dmQ==} - dev: false - - /@fastify/fast-json-stringify-compiler/4.2.0: - resolution: {integrity: sha512-ypZynRvXA3dibfPykQN3RB5wBdEUgSGgny8Qc6k163wYPLD4mEGEDkACp+00YmqkGvIm8D/xYoHajwyEdWD/eg==} - dependencies: - fast-json-stringify: 5.5.0 - dev: false - - /@fastify/send/2.0.1: - resolution: {integrity: sha512-8jdouu0o5d0FMq1+zCKeKXc1tmOQ5tTGYdQP3MpyF9+WWrZT1KCBdh6hvoEYxOm3oJG/akdE9BpehLiJgYRvGw==} - dependencies: - '@lukeed/ms': 2.0.1 - escape-html: 1.0.3 - fast-decode-uri-component: 1.0.1 - http-errors: 2.0.0 - mime: 3.0.0 - dev: false - - /@fastify/static/6.9.0: - resolution: {integrity: sha512-9SBVNJi2+KTnfiW1WjiVXDsmUxliNI54OF1eOiaop264dh8FwXSuLmO62JXvx7+VD0vQXEqsyRbFCYUJ9aJxng==} - dependencies: - '@fastify/accept-negotiator': 1.1.0 - '@fastify/send': 2.0.1 - content-disposition: 0.5.4 - fastify-plugin: 4.5.0 - glob: 8.1.0 - p-limit: 3.1.0 - readable-stream: 4.3.0 - dev: false - - /@firebase/analytics-compat/0.2.3_5qoz5voa527ucsvtk67mpz25ru: - resolution: {integrity: sha512-HmvbB4GMgh8AUlIDIo/OuFENLCGRXxMvtOueK+m8+DcfqBvG+mkii0Mi9ovo0TnMM62cy3oBYG7PHdjIQNLSLA==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/analytics': 0.9.3_@firebase+app@0.9.3 - '@firebase/analytics-types': 0.8.0 - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/analytics-types/0.8.0: - resolution: {integrity: sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==} - dev: false - - /@firebase/analytics/0.9.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-XdYHBi6RvHYVAHGyLxXX0uRPwZmGeqw1JuWS1rMEeRF/jvbxnrL81kcFAHZVRkEvG9bXAJgL2fX9wmDo3e622w==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/installations': 0.6.3_@firebase+app@0.9.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - dev: false - - /@firebase/app-check-compat/0.3.3_5qoz5voa527ucsvtk67mpz25ru: - resolution: {integrity: sha512-25AQ4W7WUL8OWas40GsABuNU622Dm1ojbfeZ03uKtLj5Af7FerJ25u7zkgm+11pc6rpr5v8E5oxEG9vmNRndEA==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-check': 0.6.3_@firebase+app@0.9.3 - '@firebase/app-check-types': 0.5.0 - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/app-check-interop-types/0.2.0: - resolution: {integrity: sha512-+3PQIeX6/eiVK+x/yg8r6xTNR97fN7MahFDm+jiQmDjcyvSefoGuTTNQuuMScGyx3vYUBeZn+Cp9kC0yY/9uxQ==} - dev: false - - /@firebase/app-check-types/0.5.0: - resolution: {integrity: sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==} - dev: false - - /@firebase/app-check/0.6.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-T9f9ceFLs7x4D2T6whu5a6j7B3qPuYHiZHZxW6DkMh/FoMmRA4/q/HVyu01i9+LyJJx2Xdo6eCcj6ofs9YZjqA==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - dev: false - - /@firebase/app-compat/0.2.3: - resolution: {integrity: sha512-sX6rD1KFX6K2CuCnQvc9jZLOgAFZ+sv2jKKahIl4SbTM561D682B8n4Jtx/SgDrvcTVTdb05g4NhZOws9hxYxA==} - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - dev: false - - /@firebase/app-types/0.9.0: - resolution: {integrity: sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==} - dev: false - - /@firebase/app/0.9.3: - resolution: {integrity: sha512-G79JUceVDaHRZ4WkA11GyVldVXhdyRJRwWVQFFvAAVfQJLvy2TA6lQjeUn28F6FmeUWxDGwPC30bxCRWq7Op8Q==} - dependencies: - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - idb: 7.0.1 - tslib: 2.5.0 - dev: false - - /@firebase/auth-compat/0.3.3_2nquphbz2k7fjevr4yz5c7cjmi: - resolution: {integrity: sha512-9asUuGtkzUVELH3LYXdiom1nVVV9bqEPqzHohanoofHL/oVTNcHZ4AQ5CXjNATfb6c1WH32U+nEuPiYg26UUIw==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/auth': 0.21.3_@firebase+app@0.9.3 - '@firebase/auth-types': 0.12.0_rls6ojzmqtv4do6kouxcb5gfn4 - '@firebase/component': 0.6.3 - '@firebase/util': 1.9.2 - node-fetch: 2.6.7 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/auth-interop-types/0.2.1: - resolution: {integrity: sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==} - dev: false - - /@firebase/auth-types/0.12.0_rls6ojzmqtv4do6kouxcb5gfn4: - resolution: {integrity: sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==} - peerDependencies: - '@firebase/app-types': 0.x - '@firebase/util': 1.x - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.9.2 - dev: false - - /@firebase/auth/0.21.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-HPbcwgArLBVTowFcn4qaQr6LCx7BidI9yrQ5MRbQNv4PsgK/3UGpzCYaNPPbvgr9fe+0jNdJO+uC0+dk4xIzCQ==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - node-fetch: 2.6.7 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: false - - /@firebase/component/0.6.3: - resolution: {integrity: sha512-rnhq5SOsB5nuJphZF50iwqnBiuuyg9kdnlUn1rBrKfu7/cUVJZF5IG1cWrL0rXXyiZW1WBI/J2pmTvVO8dStGQ==} - dependencies: - '@firebase/util': 1.9.2 - tslib: 2.5.0 - dev: false - - /@firebase/database-compat/0.3.3: - resolution: {integrity: sha512-r+L9jTbvsnb7sD+xz6UKU39DgBWqB2pyjzPNdBeriGC9Ssa2MAZe0bIqjCQg51RRXYc/aa/zK1Q2/4uesZeVgQ==} - dependencies: - '@firebase/component': 0.6.3 - '@firebase/database': 0.14.3 - '@firebase/database-types': 0.10.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - dev: false - - /@firebase/database-types/0.10.3: - resolution: {integrity: sha512-Hu34CDhHYZsd2eielr0jeaWrTJk8Hz0nd7WsnYDnXtQX4i49ppgPesUzPdXVBdIBLJmT0ZZRvT7qWHknkOT+zg==} - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.9.2 - dev: false - - /@firebase/database/0.14.3: - resolution: {integrity: sha512-J76W6N7JiVkLaAtPyjaGRkrsIu9pi6iZikuGGtGjqvV19vkn7oiL4Hbo5uTYCMd4waTUWoL9iI08eX184W+5GQ==} - dependencies: - '@firebase/auth-interop-types': 0.2.1 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - faye-websocket: 0.11.4 - tslib: 2.5.0 - dev: false - - /@firebase/firestore-compat/0.3.3_2nquphbz2k7fjevr4yz5c7cjmi: - resolution: {integrity: sha512-fMTsSC0s2cF5w2+JoB0dWD/o4kXtLrUCPGnZPuz4S0bqTN2t0vHr3gdAsQLtnadgwB78ACtinYmf4Udwx7TzDg==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/firestore': 3.8.3_@firebase+app@0.9.3 - '@firebase/firestore-types': 2.5.1_rls6ojzmqtv4do6kouxcb5gfn4 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/firestore-types/2.5.1_rls6ojzmqtv4do6kouxcb5gfn4: - resolution: {integrity: sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw==} - peerDependencies: - '@firebase/app-types': 0.x - '@firebase/util': 1.x - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.9.2 - dev: false - - /@firebase/firestore/3.8.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-4xR3Mqj95bxHg3hZnz0O+LQrHkjq+siT2y+B9da6u68qJ8bzzT42JaFgd1vifhbBpVbBzpFaS2RuCq2E+kGv9g==} - engines: {node: '>=10.10.0'} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - '@firebase/webchannel-wrapper': 0.9.0 - '@grpc/grpc-js': 1.7.3 - '@grpc/proto-loader': 0.6.13 - node-fetch: 2.6.7 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: false - - /@firebase/functions-compat/0.3.3_5qoz5voa527ucsvtk67mpz25ru: - resolution: {integrity: sha512-UIAJ2gzNq0p/61cXqkpi9DnlQt0hdlGqgmL5an7KuJth2Iv5uGpKg/+OapAZxPuiUNZgTEyZDB7kNBHvnxWq5w==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/functions': 0.9.3_@firebase+app@0.9.3 - '@firebase/functions-types': 0.6.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - - encoding - dev: false - - /@firebase/functions-types/0.6.0: - resolution: {integrity: sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==} - dev: false - - /@firebase/functions/0.9.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-tPJgYY2ROQSYuzvgxZRoHeDj+Ic07/bWHwaftgTriawtupmFOkt5iikuhJSJUhaOpFh9TB335OvCXJw1N+BIlQ==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/app-check-interop-types': 0.2.0 - '@firebase/auth-interop-types': 0.2.1 - '@firebase/component': 0.6.3 - '@firebase/messaging-interop-types': 0.2.0 - '@firebase/util': 1.9.2 - node-fetch: 2.6.7 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: false - - /@firebase/installations-compat/0.2.3_2nquphbz2k7fjevr4yz5c7cjmi: - resolution: {integrity: sha512-K9rKM/ym06lkpaKz7bMLxzHK/HEk65XfLJBV+dJkIuWeO0EqqC9VFGrpWAo0QmgC4BqbU58T6VBbzoJjb0gaFw==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/installations': 0.6.3_@firebase+app@0.9.3 - '@firebase/installations-types': 0.5.0_@firebase+app-types@0.9.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - dev: false - - /@firebase/installations-types/0.5.0_@firebase+app-types@0.9.0: - resolution: {integrity: sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==} - peerDependencies: - '@firebase/app-types': 0.x - dependencies: - '@firebase/app-types': 0.9.0 - dev: false - - /@firebase/installations/0.6.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-20JFWm+tweNoRjRbz8/Y4I7O5pUJGZsFKCkLl1qNxfNYECSfrZUuozIDJDZC/MeVn5+kB9CwjThDlgQEPrfLdg==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/util': 1.9.2 - idb: 7.0.1 - tslib: 2.5.0 - dev: false - - /@firebase/logger/0.4.0: - resolution: {integrity: sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==} - dependencies: - tslib: 2.5.0 - dev: false - - /@firebase/messaging-compat/0.2.3_5qoz5voa527ucsvtk67mpz25ru: - resolution: {integrity: sha512-MmuuohXV2YRzIoJmDngI5qqO/cF2q7SdAaw7k4r61W3ReJy7x4/rtqrIvwNVhM6X/X8NFGBbsYKsCfRHWjFdkg==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/messaging': 0.12.3_@firebase+app@0.9.3 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/messaging-interop-types/0.2.0: - resolution: {integrity: sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==} - dev: false - - /@firebase/messaging/0.12.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-a3ZKcGDiV2sKmQDB56PpgL1yjFxXCtff2+v1grnAZZ4GnfNQ74t2EHCbmgY7xRX7ThzMqug54oxhuk4ur0MIoA==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/installations': 0.6.3_@firebase+app@0.9.3 - '@firebase/messaging-interop-types': 0.2.0 - '@firebase/util': 1.9.2 - idb: 7.0.1 - tslib: 2.5.0 - dev: false - - /@firebase/performance-compat/0.2.3_5qoz5voa527ucsvtk67mpz25ru: - resolution: {integrity: sha512-I3rqZsIhauXn4iApfj1ttKQdlti/r8OZBG4YK10vxKSdhAzTIDWDKEsdoCXvvKLwplcMv36sM3WPAPGQLqY5MQ==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/performance': 0.6.3_@firebase+app@0.9.3 - '@firebase/performance-types': 0.2.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/performance-types/0.2.0: - resolution: {integrity: sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==} - dev: false - - /@firebase/performance/0.6.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-NQmQN6Ete7i9jz1mzULJZEGvsOmwwdUy6vpqnhUxSFMYPnlBKjX+yypCUUJDDN5zff5+kfwSD1qCyUAaS0xWUA==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/installations': 0.6.3_@firebase+app@0.9.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - dev: false - - /@firebase/remote-config-compat/0.2.3_5qoz5voa527ucsvtk67mpz25ru: - resolution: {integrity: sha512-w/ZL03YgYaXq03xIRyJ5oPhXZi6iDsY/v0J9Y7I7SqxCYytEnHVrL9nvBqd9R94y5LRAVNPCLokJeeizaUz4VQ==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/logger': 0.4.0 - '@firebase/remote-config': 0.4.3_@firebase+app@0.9.3 - '@firebase/remote-config-types': 0.3.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/remote-config-types/0.3.0: - resolution: {integrity: sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==} - dev: false - - /@firebase/remote-config/0.4.3_@firebase+app@0.9.3: - resolution: {integrity: sha512-Q6d4jBWZoNt6SYq87bjtDGUHFkKwAmGnNjWyRjl14AZqE1ilgd9NZHmutharlYJ3LvxMsid80HdK5SgGEpIPfg==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/installations': 0.6.3_@firebase+app@0.9.3 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - dev: false - - /@firebase/storage-compat/0.3.1_2nquphbz2k7fjevr4yz5c7cjmi: - resolution: {integrity: sha512-6HaTvWsT5Yy3j4UpCZpMcFUYEkJ2XYWukdyTl02u6VjSBRLvkhOXPzEfMvgVWqhnF/rYVfPdjrZ904wk5OxtmQ==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.3 - '@firebase/component': 0.6.3 - '@firebase/storage': 0.11.1_@firebase+app@0.9.3 - '@firebase/storage-types': 0.8.0_rls6ojzmqtv4do6kouxcb5gfn4 - '@firebase/util': 1.9.2 - tslib: 2.5.0 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/storage-types/0.8.0_rls6ojzmqtv4do6kouxcb5gfn4: - resolution: {integrity: sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==} - peerDependencies: - '@firebase/app-types': 0.x - '@firebase/util': 1.x - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.9.2 - dev: false - - /@firebase/storage/0.11.1_@firebase+app@0.9.3: - resolution: {integrity: sha512-Xv8EG2j52ugF2xayBz26U9J0VBXHXPMVxSN+ph3R3BSoHxvMLaPu+qUYKHavSt+zbcgPH2GyBhrCdJK6SaDFPA==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.3 - '@firebase/component': 0.6.3 - '@firebase/util': 1.9.2 - node-fetch: 2.6.7 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: false - - /@firebase/util/1.9.2: - resolution: {integrity: sha512-9l0uMGPGw3GsoD5khjMmYCCcMq/OR/OOSViiWMN+s2Q0pxM+fYzrii1H+r8qC/uoMjSVXomjLZt0vZIyryCqtQ==} - dependencies: - tslib: 2.5.0 - dev: false - - /@firebase/webchannel-wrapper/0.9.0: - resolution: {integrity: sha512-BpiZLBWdLFw+qFel9p3Zs1jD6QmH7Ii4aTDu6+vx8ShdidChZUXqDhYJly4ZjSgQh54miXbBgBrk0S+jTIh/Qg==} - dev: false - - /@grpc/grpc-js/1.7.3: - resolution: {integrity: sha512-H9l79u4kJ2PVSxUNA08HMYAnUBLj9v6KjYQ7SQ71hOZcEXhShE/y5iQCesP8+6/Ik/7i2O0a10bPquIcYfufog==} - engines: {node: ^8.13.0 || >=10.10.0} - dependencies: - '@grpc/proto-loader': 0.7.5 - '@types/node': 18.14.0 - dev: false - - /@grpc/proto-loader/0.6.13: - resolution: {integrity: sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==} - engines: {node: '>=6'} - hasBin: true - dependencies: - '@types/long': 4.0.2 - lodash.camelcase: 4.3.0 - long: 4.0.0 - protobufjs: 6.11.3 - yargs: 16.2.0 - dev: false - - /@grpc/proto-loader/0.7.5: - resolution: {integrity: sha512-mfcTuMbFowq1wh/Rn5KQl6qb95M21Prej3bewD9dUQMurYGVckGO/Pbe2Ocwto6sD05b/mxZLspvqwx60xO2Rg==} - engines: {node: '>=6'} - hasBin: true - dependencies: - '@types/long': 4.0.2 - lodash.camelcase: 4.3.0 - long: 4.0.0 - protobufjs: 7.2.2 - yargs: 16.2.0 - dev: false - - /@humanwhocodes/config-array/0.11.8: - resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer/1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema/1.2.1: - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - dev: true - - /@jridgewell/resolve-uri/3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec/1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - dev: true - - /@jridgewell/trace-mapping/0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@lukeed/ms/2.0.1: - resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==} - engines: {node: '>=8'} - dev: false - - /@nodelib/fs.scandir/2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat/2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk/1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 - dev: true - - /@protobufjs/aspromise/1.1.2: - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - dev: false - - /@protobufjs/base64/1.1.2: - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - dev: false - - /@protobufjs/codegen/2.0.4: - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - dev: false - - /@protobufjs/eventemitter/1.1.0: - resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - dev: false - - /@protobufjs/fetch/1.1.0: - resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 - dev: false - - /@protobufjs/float/1.0.2: - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - dev: false - - /@protobufjs/inquire/1.1.0: - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - dev: false - - /@protobufjs/path/1.1.2: - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - dev: false - - /@protobufjs/pool/1.1.0: - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - dev: false - - /@protobufjs/utf8/1.1.0: - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - dev: false - - /@tsconfig/node10/1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true - - /@tsconfig/node12/1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14/1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16/1.0.3: - resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} - dev: true - - /@types/json-schema/7.0.11: - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - dev: true - - /@types/long/4.0.2: - resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} - dev: false - - /@types/node/18.14.0: - resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==} - - /@types/semver/7.3.13: - resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} - dev: true - - /@typescript-eslint/eslint-plugin/5.52.0_6cfvjsbua5ptj65675bqcn6oza: - resolution: {integrity: sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm - '@typescript-eslint/scope-manager': 5.52.0 - '@typescript-eslint/type-utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm - '@typescript-eslint/utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm - debug: 4.3.4 - eslint: 8.34.0 - grapheme-splitter: 1.0.4 - ignore: 5.2.4 - natural-compare-lite: 1.4.0 - regexpp: 3.2.0 - semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm: - resolution: {integrity: sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 5.52.0 - '@typescript-eslint/types': 5.52.0 - '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5 - debug: 4.3.4 - eslint: 8.34.0 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager/5.52.0: - resolution: {integrity: sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.52.0 - '@typescript-eslint/visitor-keys': 5.52.0 - dev: true - - /@typescript-eslint/type-utils/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm: - resolution: {integrity: sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5 - '@typescript-eslint/utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm - debug: 4.3.4 - eslint: 8.34.0 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types/5.52.0: - resolution: {integrity: sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/typescript-estree/5.52.0_typescript@4.9.5: - resolution: {integrity: sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.52.0 - '@typescript-eslint/visitor-keys': 5.52.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm: - resolution: {integrity: sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@types/json-schema': 7.0.11 - '@types/semver': 7.3.13 - '@typescript-eslint/scope-manager': 5.52.0 - '@typescript-eslint/types': 5.52.0 - '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5 - eslint: 8.34.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.34.0 - semver: 7.3.8 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys/5.52.0: - resolution: {integrity: sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.52.0 - eslint-visitor-keys: 3.3.0 - dev: true - - /abort-controller/3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - dependencies: - event-target-shim: 5.0.1 - dev: false - - /abstract-logging/2.0.1: - resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} - dev: false - - /acorn-jsx/5.3.2_acorn@8.8.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.8.2 - dev: true - - /acorn-walk/8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn/8.8.2: - resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /ajv-formats/2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependenciesMeta: - ajv: - optional: true - dependencies: - ajv: 8.12.0 - dev: false - - /ajv/6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv/8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: false - - /ansi-regex/5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-styles/4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /archy/1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - dev: false - - /arg/4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /argparse/2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /array-union/2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /atomic-sleep/1.0.0: - resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} - engines: {node: '>=8.0.0'} - dev: false - - /avvio/8.2.1: - resolution: {integrity: sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==} - dependencies: - archy: 1.0.0 - debug: 4.3.4 - fastq: 1.15.0 - transitivePeerDependencies: - - supports-color - dev: false - - /balanced-match/1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /base64-js/1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: false - - /brace-expansion/1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion/2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: false - - /braces/3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /buffer/6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: false - - /callsites/3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /chalk/4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /cliui/7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - - /color-convert/2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name/1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /concat-map/0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /content-disposition/0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /cookie/0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: false - - /create-require/1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn/7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /deep-is/0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /depd/2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: false - - /diff/4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /dir-glob/3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine/3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dotenv/16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /emoji-regex/8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false - - /escalade/3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: false - - /escape-html/1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false - - /escape-string-regexp/4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /eslint-scope/5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope/7.1.1: - resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-utils/3.0.0_eslint@8.34.0: - resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} - engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} - peerDependencies: - eslint: '>=5' - dependencies: - eslint: 8.34.0 - eslint-visitor-keys: 2.1.0 - dev: true - - /eslint-visitor-keys/2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys/3.3.0: - resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint/8.34.0: - resolution: {integrity: sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint/eslintrc': 1.4.1 - '@humanwhocodes/config-array': 0.11.8 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.34.0 - eslint-visitor-keys: 3.3.0 - espree: 9.4.1 - esquery: 1.4.2 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.20.0 - grapheme-splitter: 1.0.4 - ignore: 5.2.4 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-sdsl: 4.3.0 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.1 - regexpp: 3.2.0 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree/9.4.1: - resolution: {integrity: sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.8.2 - acorn-jsx: 5.3.2_acorn@8.8.2 - eslint-visitor-keys: 3.3.0 - dev: true - - /esquery/1.4.2: - resolution: {integrity: sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse/4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse/4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse/5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils/2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /event-target-shim/5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - dev: false - - /events/3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: false - - /fast-content-type-parse/1.0.0: - resolution: {integrity: sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA==} - dev: false - - /fast-decode-uri-component/1.0.1: - resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} - dev: false - - /fast-deep-equal/3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - /fast-glob/3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify/2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-json-stringify/5.5.0: - resolution: {integrity: sha512-rmw2Z8/mLkND8zI+3KTYIkNPEoF5v6GqDP/o+g7H3vjdWjBwuKpgAYFHIzL6ORRB+iqDjjtJnLIW9Mzxn5szOA==} - dependencies: - '@fastify/deepmerge': 1.3.0 - ajv: 8.12.0 - ajv-formats: 2.1.1 - fast-deep-equal: 3.1.3 - fast-uri: 2.2.0 - rfdc: 1.3.0 - dev: false - - /fast-levenshtein/2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fast-querystring/1.1.1: - resolution: {integrity: sha512-qR2r+e3HvhEFmpdHMv//U8FnFlnYjaC6QKDuaXALDkw2kvHO8WDjxH+f/rHGR4Me4pnk8p9JAkRNTjYHAKRn2Q==} - dependencies: - fast-decode-uri-component: 1.0.1 - dev: false - - /fast-redact/3.1.2: - resolution: {integrity: sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==} - engines: {node: '>=6'} - dev: false - - /fast-uri/2.2.0: - resolution: {integrity: sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg==} - dev: false - - /fastify-plugin/4.5.0: - resolution: {integrity: sha512-79ak0JxddO0utAXAQ5ccKhvs6vX2MGyHHMMsmZkBANrq3hXc1CHzvNPHOcvTsVMEPl5I+NT+RO4YKMGehOfSIg==} - dev: false - - /fastify/4.13.0: - resolution: {integrity: sha512-p9ibdFWH3pZ7KPgmfHPKGUy2W4EWU2TEpwlcu58w4CwGyU3ARFfh2kwq6zpZ5W2ZGVbufi4tZbqHIHAlX/9Z/A==} - dependencies: - '@fastify/ajv-compiler': 3.5.0 - '@fastify/error': 3.2.0 - '@fastify/fast-json-stringify-compiler': 4.2.0 - abstract-logging: 2.0.1 - avvio: 8.2.1 - fast-content-type-parse: 1.0.0 - find-my-way: 7.4.0 - light-my-request: 5.9.1 - pino: 8.10.0 - process-warning: 2.1.0 - proxy-addr: 2.0.7 - rfdc: 1.3.0 - secure-json-parse: 2.7.0 - semver: 7.3.8 - tiny-lru: 10.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /fastq/1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - dependencies: - reusify: 1.0.4 - - /faye-websocket/0.11.4: - resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} - engines: {node: '>=0.8.0'} - dependencies: - websocket-driver: 0.7.4 - dev: false - - /file-entry-cache/6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.0.4 - dev: true - - /fill-range/7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-my-way/7.4.0: - resolution: {integrity: sha512-JFT7eURLU5FumlZ3VBGnveId82cZz7UR7OUu+THQJOwdQXxmS/g8v0KLoFhv97HreycOrmAbqjXD/4VG2j0uMQ==} - engines: {node: '>=14'} - dependencies: - fast-deep-equal: 3.1.3 - fast-querystring: 1.1.1 - safe-regex2: 2.0.0 - dev: false - - /find-up/5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /firebase/9.17.1: - resolution: {integrity: sha512-MSZaTRaaRLgDFLqoEnoPYK8zkLwQNvYeLZ3YSKdcQxG8hDifNO22ywS1cSA1ZCGHlQeOsDtfDwBejKcANf/RQw==} - dependencies: - '@firebase/analytics': 0.9.3_@firebase+app@0.9.3 - '@firebase/analytics-compat': 0.2.3_5qoz5voa527ucsvtk67mpz25ru - '@firebase/app': 0.9.3 - '@firebase/app-check': 0.6.3_@firebase+app@0.9.3 - '@firebase/app-check-compat': 0.3.3_5qoz5voa527ucsvtk67mpz25ru - '@firebase/app-compat': 0.2.3 - '@firebase/app-types': 0.9.0 - '@firebase/auth': 0.21.3_@firebase+app@0.9.3 - '@firebase/auth-compat': 0.3.3_2nquphbz2k7fjevr4yz5c7cjmi - '@firebase/database': 0.14.3 - '@firebase/database-compat': 0.3.3 - '@firebase/firestore': 3.8.3_@firebase+app@0.9.3 - '@firebase/firestore-compat': 0.3.3_2nquphbz2k7fjevr4yz5c7cjmi - '@firebase/functions': 0.9.3_@firebase+app@0.9.3 - '@firebase/functions-compat': 0.3.3_5qoz5voa527ucsvtk67mpz25ru - '@firebase/installations': 0.6.3_@firebase+app@0.9.3 - '@firebase/installations-compat': 0.2.3_2nquphbz2k7fjevr4yz5c7cjmi - '@firebase/messaging': 0.12.3_@firebase+app@0.9.3 - '@firebase/messaging-compat': 0.2.3_5qoz5voa527ucsvtk67mpz25ru - '@firebase/performance': 0.6.3_@firebase+app@0.9.3 - '@firebase/performance-compat': 0.2.3_5qoz5voa527ucsvtk67mpz25ru - '@firebase/remote-config': 0.4.3_@firebase+app@0.9.3 - '@firebase/remote-config-compat': 0.2.3_5qoz5voa527ucsvtk67mpz25ru - '@firebase/storage': 0.11.1_@firebase+app@0.9.3 - '@firebase/storage-compat': 0.3.1_2nquphbz2k7fjevr4yz5c7cjmi - '@firebase/util': 1.9.2 - transitivePeerDependencies: - - encoding - dev: false - - /flat-cache/3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.2.7 - rimraf: 3.0.2 - dev: true - - /flatted/3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} - dev: true - - /forwarded/0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: false - - /fs.realpath/1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - /get-caller-file/2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false - - /glob-parent/5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent/6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob/7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob/8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - dev: false - - /globals/13.20.0: - resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globby/11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.2.12 - ignore: 5.2.4 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /grapheme-splitter/1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true - - /has-flag/4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /http-errors/2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: false - - /http-parser-js/0.5.8: - resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} - dev: false - - /idb/7.0.1: - resolution: {integrity: sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==} - dev: false - - /ieee754/1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: false - - /ignore/5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - dev: true - - /import-fresh/3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash/0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /inflight/1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - /inherits/2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /ipaddr.js/1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: false - - /is-extglob/2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point/3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false - - /is-glob/4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside/3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /isexe/2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /js-sdsl/4.3.0: - resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==} - dev: true - - /js-yaml/4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /json-schema-traverse/0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse/1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: false - - /json-stable-stringify-without-jsonify/1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /levn/0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /light-my-request/5.9.1: - resolution: {integrity: sha512-UT7pUk8jNCR1wR7w3iWfIjx32DiB2f3hFdQSOwy3/EPQ3n3VocyipUxcyRZR0ahoev+fky69uA+GejPa9KuHKg==} - dependencies: - cookie: 0.5.0 - process-warning: 2.1.0 - set-cookie-parser: 2.5.1 - dev: false - - /locate-path/6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.camelcase/4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: false - - /lodash.merge/4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /long/4.0.0: - resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - dev: false - - /long/5.2.1: - resolution: {integrity: sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==} - dev: false - - /lru-cache/6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - - /make-error/1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /merge2/1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch/4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime/3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true - dev: false - - /minimatch/3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch/5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: false - - /ms/2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /natural-compare-lite/1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - dev: true - - /natural-compare/1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /node-fetch/2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: false - - /on-exit-leak-free/2.1.0: - resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==} - dev: false - - /once/1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - - /optionator/0.9.1: - resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.3 - dev: true - - /p-limit/3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - - /p-locate/5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /parent-module/1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /path-exists/4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute/1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key/3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-type/4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /picomatch/2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pino-abstract-transport/1.0.0: - resolution: {integrity: sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==} - dependencies: - readable-stream: 4.3.0 - split2: 4.1.0 - dev: false - - /pino-std-serializers/6.1.0: - resolution: {integrity: sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g==} - dev: false - - /pino/8.10.0: - resolution: {integrity: sha512-ODfIe+giJtQGsvNAEj5/sHHpL3TFBg161JBH4W62Hc0l0PJjsDFD1R7meLI4PZ2aoHDJznxFNShkJcaG/qJToQ==} - hasBin: true - dependencies: - atomic-sleep: 1.0.0 - fast-redact: 3.1.2 - on-exit-leak-free: 2.1.0 - pino-abstract-transport: 1.0.0 - pino-std-serializers: 6.1.0 - process-warning: 2.1.0 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.4.2 - sonic-boom: 3.2.1 - thread-stream: 2.3.0 - dev: false - - /prelude-ls/1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /process-warning/2.1.0: - resolution: {integrity: sha512-9C20RLxrZU/rFnxWncDkuF6O999NdIf3E1ws4B0ZeY3sRVPzWBMsYDE2lxjxhiXxg464cQTgKUGm8/i6y2YGXg==} - dev: false - - /process/0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: false - - /protobufjs/6.11.3: - resolution: {integrity: sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==} - hasBin: true - requiresBuild: true - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/long': 4.0.2 - '@types/node': 18.14.0 - long: 4.0.0 - dev: false - - /protobufjs/7.2.2: - resolution: {integrity: sha512-++PrQIjrom+bFDPpfmqXfAGSQs40116JRrqqyf53dymUMvvb5d/LMRyicRoF1AUKoXVS1/IgJXlEgcpr4gTF3Q==} - engines: {node: '>=12.0.0'} - requiresBuild: true - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/node': 18.14.0 - long: 5.2.1 - dev: false - - /proxy-addr/2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: false - - /punycode/2.3.0: - resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} - engines: {node: '>=6'} - - /queue-microtask/1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /quick-format-unescaped/4.0.4: - resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - dev: false - - /readable-stream/4.3.0: - resolution: {integrity: sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - dev: false - - /real-require/0.2.0: - resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} - engines: {node: '>= 12.13.0'} - dev: false - - /regexpp/3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - dev: true - - /require-directory/2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: false - - /require-from-string/2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: false - - /resolve-from/4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /ret/0.2.2: - resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} - engines: {node: '>=4'} - dev: false - - /reusify/1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - /rfdc/1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - dev: false - - /rimraf/3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /run-parallel/1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /safe-buffer/5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false - - /safe-regex2/2.0.0: - resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==} - dependencies: - ret: 0.2.2 - dev: false - - /safe-stable-stringify/2.4.2: - resolution: {integrity: sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==} - engines: {node: '>=10'} - dev: false - - /secure-json-parse/2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - dev: false - - /semver/7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - - /set-cookie-parser/2.5.1: - resolution: {integrity: sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==} - dev: false - - /setprototypeof/1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false - - /shebang-command/2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex/3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /slash/3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /sonic-boom/3.2.1: - resolution: {integrity: sha512-iITeTHxy3B9FGu8aVdiDXUVAcHMF9Ss0cCsAOo2HfCrmVGT3/DT5oYaeu0M/YKZDlKTvChEyPq0zI9Hf33EX6A==} - dependencies: - atomic-sleep: 1.0.0 - dev: false - - /split2/4.1.0: - resolution: {integrity: sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==} - engines: {node: '>= 10.x'} - dev: false - - /statuses/2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: false - - /string-width/4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: false - - /strip-ansi/6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-json-comments/3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /supports-color/7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /text-table/0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /thread-stream/2.3.0: - resolution: {integrity: sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==} - dependencies: - real-require: 0.2.0 - dev: false - - /tiny-lru/10.0.1: - resolution: {integrity: sha512-Vst+6kEsWvb17Zpz14sRJV/f8bUWKhqm6Dc+v08iShmIJ/WxqWytHzCTd6m88pS33rE2zpX34TRmOpAJPloNCA==} - engines: {node: '>=6'} - dev: false - - /to-regex-range/5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier/1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: false - - /tr46/0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false - - /ts-node/10.9.1_tncu2ai53lzgmizdedur7lbibe: - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 - '@types/node': 18.14.0 - acorn: 8.8.2 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 4.9.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /tslib/1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib/2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - dev: false - - /tsutils/3.21.0_typescript@4.9.5: - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 4.9.5 - dev: true - - /type-check/0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest/0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /typescript/4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} - hasBin: true - dev: true - - /uri-js/4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.0 - - /v8-compile-cache-lib/3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /webidl-conversions/3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false - - /websocket-driver/0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} - engines: {node: '>=0.8.0'} - dependencies: - http-parser-js: 0.5.8 - safe-buffer: 5.2.1 - websocket-extensions: 0.1.4 - dev: false - - /websocket-extensions/0.1.4: - resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} - engines: {node: '>=0.8.0'} - dev: false - - /whatwg-url/5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: false - - /which/2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /word-wrap/1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - dev: true - - /wrap-ansi/7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: false - - /wrappy/1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /y18n/5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: false - - /yallist/4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - /yargs-parser/20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: false - - /yargs/16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: false - - /yn/3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - - /yocto-queue/0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} diff --git a/api/src/firebase.ts b/api/src/firebase.ts deleted file mode 100644 index 8f9919b..0000000 --- a/api/src/firebase.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { collection, getDocs, Firestore, doc, getDoc, addDoc, deleteDoc, updateDoc } from 'firebase/firestore/lite'; -import { Record } from "./models/record" -import { RawData } from "./models/rawdb" -import { NewRecord } from "./models/new_record" - -export async function getUserRecord(db: Firestore, user: string, record: string): Promise { - const recordDoc = await getDoc(doc(db, `users`, user, "records", record)) - if (recordDoc.exists()) { - const d = recordDoc.data() as RawData - return { "programming_language": d['programming_language'].jazyk, id: recordDoc.id, date: new Date(d.date.seconds), "time_spent": d['time_spent'], rating: d.rating, description: d.descriptionRaw } - } - else { - return null; - } -} - -export async function getAllUserRecords(db: Firestore, user: string): Promise { - const userDoc = await getDoc(doc(db, `users`, user)) - if (!userDoc.exists()) return null; - const records = (await getDocs(collection(db, "users", user, "records"))) - const recordArr: Record[] = [] - records.forEach(r => { - const d = r.data() as RawData - recordArr.push({ - date: d.date.toDate(), - "time_spent": d['time_spent'], - "programming_language": d['programming_language'].jazyk, - rating: d.rating, - description: d.descriptionRaw, - id: r.id - }) - }) - return recordArr -} - -export async function createRecord(db: Firestore, user: string, data: NewRecord): Promise { - const userDoc = await getDoc(doc(db, "users", user)) - if (userDoc.exists()) { - const docRef = await addDoc(collection(db, "users", user, "records"), { ...data,"time_spentRaw":textToSec(data.time_spent), "description": null }) - return docRef.id; - } - else { - return null; - } -} - -export async function updateRecord(db: Firestore, user: string, id: string, data: NewRecord): Promise { - const userDoc = await getDoc(doc(db, "users", user)) - if (userDoc.exists()) { - const docRef = await getDoc(doc(db, "users", user, "records", id)) - if (!docRef.exists()) return false; - await updateDoc(docRef.ref, {...data,"time_spentRaw":textToSec(data.time_spent)}) - return true; - } - else { - return null; - } -} - -export async function deleteRecord(db: Firestore, user: string, rec: string): Promise { - const userDoc = await getDoc(doc(db, "users", user)) - if (!userDoc.exists()) return null; - const recordDoc = await getDoc(doc(db, "users", user, "records", rec)) - if (!recordDoc.exists()) return false - await deleteDoc(recordDoc.ref) - return true; -} - -function textToSec(vstup: string):number|undefined { - const regex = /(\d+) hodin(?: |y |a )(\d+) minut(?:$|a$|y$)/gm - let s:number|undefined = 0; - let m; - - while ((m = regex.exec(vstup)) !== null) { - // This is necessary to avoid infinite loops with zero-width matches - if (m.index === regex.lastIndex) { - regex.lastIndex++; - } - - // The result can be accessed through the `m`-variable. - let ok = true; - m.forEach((match, groupIndex) => { - try { - switch (groupIndex) { - case 1: - if(s == undefined){ - ok = false; - break; - } - s += parseInt(match) * 3600 - break; - case 2: - if(s == undefined){ - ok = false; - break; - } - s += parseInt(match) * 60 - break; - default: - break; - } - } catch (error) { - ok = false; - } - }); - if(!ok) { - s = undefined; - break; - } - } - return s; -} \ No newline at end of file diff --git a/api/src/index.ts b/api/src/index.ts deleted file mode 100644 index 09a9491..0000000 --- a/api/src/index.ts +++ /dev/null @@ -1,234 +0,0 @@ -import fastify from 'fastify' -import { initializeApp } from 'firebase/app'; -import { getFirestore } from 'firebase/firestore/lite'; -import { Record } from "./models/record" -import path from 'path'; -import { createRecord, deleteRecord, getAllUserRecords, getUserRecord, updateRecord } from './firebase'; -import { Params } from './models/params'; -import { fastifyStatic } from "@fastify/static" -import { NewRecord, NewRecordRaw } from './models/new_record'; - -/* - Copyright (C) 2022 Matyáš Caras a Richard Pavlikán - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -debugme().then(() => { - - // Zkontrolovat proměnné - ["FIREBASE_KEY", "FIREBASE_AUTH", "FIREBASE_ID", "FIREBASE_STORAGE", "FIREBASE_MESSAGING", "FIREBASE_APPID"].forEach(v => { - if (!Object.keys(process.env).includes(v)) { - throw new Error(`Chybí systémová proměnná '${v}'`) - } - }) - - const server = fastify() - server.register(fastifyStatic, { - root: path.join(__dirname, "public") - }) - - // Konfigurace pro napojení na Firebase - const firebaseConfig = { - - apiKey: process.env["FIREBASE_KEY"], - - authDomain: process.env["FIREBASE_AUTH"], - - projectId: process.env["FIREBASE_ID"], - - storageBucket: process.env["FIREBASE_STORAGE"], - - messagingSenderId: process.env["FIREBASE_MESSAGING"], - - appId: process.env["FIREBASE_APPID"] - - }; - - // Připojit se na Firebase - const firebaseApp = initializeApp(firebaseConfig); - const db = getFirestore(firebaseApp); - - // Registrovat routy - - server.get("/", (req, res) => { - res.sendFile("index.html") - }) - - // API routy - - // Získat jeden záznam uživatele ID - server.get('/users/:userid/records/:recordid', async (req, res) => { - - if ((req.params as Params).userid == "" || (req.params as Params).recordid == "") return res.status(400).type("application/json").send(JSON.stringify({ "error": "Parametry nesmí být prázdné", "status": "error" })) - const record: Record | null = await getUserRecord(db, (req.params as Params).userid as string, (req.params as Params).recordid as string) - if (!record) return res.status(404).type("application/json").send(JSON.stringify({ "error": "Uživatel neexistuje", "status": "error" })) - - return res.type("application/json").send(JSON.stringify(record)) - }) - - // Smazat jeden záznam - server.delete("/users/:userid/records/:recordid", async (req, res) => { - if ((req.params as Params).userid == "" || (req.params as Params).recordid == "") return res.status(400).type("application/json").send(JSON.stringify({ "error": "Parametry nesmí být prázdné", "status": "error" })) - const r = await deleteRecord(db, (req.params as Params).userid as string, (req.params as Params).recordid as string) - if (r == null) { - return res.status(404).type("application/json").send(JSON.stringify({ "status": "error", "message": "Uživatel neexistuje" })) - } - else if (r == false) { - return res.status(404).type("application/json").send(JSON.stringify({ "status": "error", "message": "Záznam neexistuje" })) - } - return res.status(200).type("application/json").send(JSON.stringify({ "status": "OK" })) - }) - - // Upravit jeden záznam - server.put("/users/:userid/records/:recordid", { - schema: { - body: { - type: 'object', - properties: { - "date": { type: 'string' }, - "time_spent": { type: 'string' }, - "programming_language": { type: 'string' }, - "description": { type: 'string' }, - "rating": { type: 'number' } - } - } - } - }, async (req, res) => { - if ((req.params as Params).userid == "" || (req.params as Params).recordid == "") return res.status(400).type("application/json").send(JSON.stringify({ "error": "Parametry nesmí být prázdné", "status": "error" })) - try { - const data = req.body as NewRecordRaw - if (data.rating > 5 || data.rating < 0) return res.status(400).type("application/json").send(JSON.stringify({ "error": "'rating' je mimo interval 0-5", "status": "error" })) - const regex = /(\d+) hodin(?: |y |a )(\d+) minut(?:$|a$|y$)/gm - if(!regex.test(data.time_spent)){ - return res.status(400).type("application/json").send(JSON.stringify({ "error": "time_spent není ve správném formátu", "status": "error" })) - } - const jazyky: { jazyk: string, barva: number }[] = [ - { "jazyk": "C#", "barva": 0xff8200f3 }, - { "jazyk": "JavaScript", "barva": 0xfffdd700 }, - { "jazyk": "Python", "barva": 0xff0080ee }, - { "jazyk": "PHP", "barva": 0xff00abff }, - { "jazyk": "C++", "barva": 0xff1626ff }, - { "jazyk": "Kotlin", "barva": 0xffe34b7c }, - { "jazyk": "Java", "barva": 0xfff58219 }, - { "jazyk": "Dart", "barva": 0xff40c4ff }, - { "jazyk": "F#", "barva": 0xff85ddf3 }, - { "jazyk": "Elixir", "barva": 0xff543465 }, - { "jazyk": "Carbon", "barva": 0xff606060 }, - - ]; - - const j: { jazyk: string, barva: number } = (jazyky.filter((v) => v.jazyk.toLowerCase() == data['programming_language'].toLowerCase()).length > 0) ? jazyky.filter((v) => v.jazyk == data['programming_language'])[0] : { "jazyk": data["programming_language"], "barva": 0xffffffff } - - const record: NewRecord = { - date: new Date(data.date), "programming_language": j, "time_spent": data['time_spent'], rating: data.rating, - descriptionRaw: data.description, programmer: (req.params as Params).userid as string - } - const r = await updateRecord(db, (req.params as Params).userid as string, (req.params as Params).recordid as string, record) - if (r == null) { - return res.status(404).type("application/json").send(JSON.stringify({ "status": "error", "message": "Uživatel neexistuje" })) - } - else if(r == false){ - return res.status(404).type("application/json").send(JSON.stringify({ "status": "error", "message": "Záznam neexistuje" })) - } - return res.status(200).type("application/json").send(JSON.stringify({ "status": "OK" })) - } catch (error) { - if (process.env["NODE_DEBUG"] == "true") console.log(error) - return res.status(400).type("application/json").send(JSON.stringify({ "error": "Zaslaná data nejsou v platném formátu JSON", "status": "error" })) - } - }) - - // Získat všechny záznamy uživatele - server.get("/users/:userid/records", async (req, res) => { - if ((req.params as Params).userid == "") return res.status(400).type("application/json").send(JSON.stringify({ "error": "Parametry nesmí být prázdné", "status": "error" })) - const r: Record[] | null = await getAllUserRecords(db, (req.params as Params).userid as string) - if (!r) return res.status(404).type("application/json").send(JSON.stringify({ "status": "error", "message": "Uživatel neexistuje" })) - - return res.type("application/json").send(JSON.stringify( - r - )) - }) - - // Vytvořit nový záznam - server.post("/users/:userid/records", { - schema: { - body: { - type: 'object', - properties: { - "date": { type: 'string' }, - "time_spent": { type: 'string' }, - "programming_language": { type: 'string' }, - "description": { type: 'string' }, - "rating": { type: 'number' } - } - } - } - }, async (req, res) => { - if ((req.params as Params).userid == "") return res.status(400).type("application/json").send(JSON.stringify({ "error": "Parametry nesmí být prázdné", "status": "error" })) - try { - const data = req.body as NewRecordRaw - if (data.rating > 5 || data.rating < 0) return res.status(400).type("application/json").send(JSON.stringify({ "error": "'rating' je mimo interval 0-5", "status": "error" })) - const regex = /(\d+) hodin(?: |y |a )(\d+) minut(?:$|a$|y$)/gm - if(!regex.test(data.time_spent)){ - return res.status(400).type("application/json").send(JSON.stringify({ "error": "time_spent není ve správném formátu", "status": "error" })) - } - const jazyky: { jazyk: string, barva: number }[] = [ - { "jazyk": "C#", "barva": 0xff8200f3 }, - { "jazyk": "JavaScript", "barva": 0xfffdd700 }, - { "jazyk": "Python", "barva": 0xff0080ee }, - { "jazyk": "PHP", "barva": 0xff00abff }, - { "jazyk": "C++", "barva": 0xff1626ff }, - { "jazyk": "Kotlin", "barva": 0xffe34b7c }, - { "jazyk": "Java", "barva": 0xfff58219 }, - { "jazyk": "Dart", "barva": 0xff40c4ff }, - { "jazyk": "F#", "barva": 0xff85ddf3 }, - { "jazyk": "Elixir", "barva": 0xff543465 }, - { "jazyk": "Carbon", "barva": 0xff606060 }, - - ]; - - const j: { jazyk: string, barva: number } = (jazyky.filter((v) => v.jazyk.toLowerCase() == data['programming_language'].toLowerCase()).length > 0) ? jazyky.filter((v) => v.jazyk == data['programming_language'])[0] : { "jazyk": data["programming_language"], "barva": 0xffffffff } - - const record: NewRecord = { - date: new Date(data.date), "programming_language": j, "time_spent": data['time_spent'], rating: data.rating, - descriptionRaw: data.description, programmer: (req.params as Params).userid as string - } - const r:string|null = await createRecord(db, (req.params as Params).userid as string, record) - if (r == null) { - return res.status(404).type("application/json").send(JSON.stringify({ "status": "error", "message": "Uživatel neexistuje" })) - } - return res.status(201).type("application/json").send(JSON.stringify({"date":record.date,"programming_language":record.programming_language.jazyk,"time_spent":record.time_spent,rating:record.rating,description:record.descriptionRaw,id:r} as Record)) - } catch (error) { - if (process.env["NODE_DEBUG"] == "true") console.log(error) - return res.status(400).type("application/json").send(JSON.stringify({ "error": "Zaslaná data nejsou v platném formátu JSON", "status": "error" })) - } - }) - - server.listen({ port: (!process.env["PORT"]) ? 8080 : parseInt(process.env["PORT"]), host: "0.0.0.0" }, (err, address) => { - if (err) { - console.error(err) - process.exit(1) - } - console.log(`Server listening at ${address}`) - }) -}) - - -async function debugme() { - if (process.env["NODE_DEBUG"] == "true") { - const dotenv = await import("dotenv"); - dotenv.config() - } - return true; -} \ No newline at end of file diff --git a/api/src/models/new_record.ts b/api/src/models/new_record.ts deleted file mode 100644 index c1f4402..0000000 --- a/api/src/models/new_record.ts +++ /dev/null @@ -1,16 +0,0 @@ -export type NewRecord={ - date:Date, - "time_spent":string, - "programming_language":{jazyk:string,barva:number}, - rating:number, - descriptionRaw:string, - programmer:string -} - -export type NewRecordRaw={ - date:string, - "time_spent":string, - "programming_language":string, - rating:number, - description:string -} \ No newline at end of file diff --git a/api/src/models/params.ts b/api/src/models/params.ts deleted file mode 100644 index 7388834..0000000 --- a/api/src/models/params.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type Params={ - userid?:string, - recordid?:string -} \ No newline at end of file diff --git a/api/src/models/rawdb.ts b/api/src/models/rawdb.ts deleted file mode 100644 index 4d22c9b..0000000 --- a/api/src/models/rawdb.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Timestamp } from "firebase/firestore/lite" - -export type RawData = { - "programming_language": {jazyk:string,barva:number}, - rating:number, - descriptionRaw: string, - description:unknown[], - date:Timestamp, - programmer:string, - toDate:Timestamp, - "time_spent":string -} \ No newline at end of file diff --git a/api/src/models/record.ts b/api/src/models/record.ts deleted file mode 100644 index 4c2f189..0000000 --- a/api/src/models/record.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type Record={ - date:Date, - "time_spent":string, - "programming_language":string, - rating:number, - description:string, - id:string -} \ No newline at end of file diff --git a/api/src/public/.gitkeep b/api/src/public/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/api/tsconfig.json b/api/tsconfig.json deleted file mode 100644 index 75e9a25..0000000 --- a/api/tsconfig.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "CommonJS", /* Specify what module code is generated. */ - "rootDir": "./src", /* Specify the root folder within your source files. */ - "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./build", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, - "include": [ - "src/*", - ] -} diff --git a/lib/main.dart b/lib/main.dart index 0c0f79f..04f0eb7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:responsive_sizer/responsive_sizer.dart'; -import 'firebase_options.dart'; +import 'firebase_options.dart'; //TODO: Přidejte si vlastní firebase nastavení /* Copyright (C) 2022 Matyáš Caras a Richard Pavlikán @@ -27,7 +27,8 @@ import 'firebase_options.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( - options: DefaultFirebaseOptions.currentPlatform, + options: DefaultFirebaseOptions + .currentPlatform, //TODO: Přidejte si vlastní firebase nastavení ); runApp(const MyApp()); } @@ -39,7 +40,7 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return ResponsiveSizer( builder: (p0, p1, p2) => MaterialApp( - title: 'Kodelog', + title: 'Deník Programátora', theme: ThemeData( primarySwatch: Colors.blue, scaffoldBackgroundColor: Vzhled.backgroundColor, diff --git a/lib/okna/all_records.dart b/lib/okna/all_records.dart index 1701048..bd4a208 100644 --- a/lib/okna/all_records.dart +++ b/lib/okna/all_records.dart @@ -2,20 +2,40 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:denikprogramatora/okna/app.dart'; import 'package:denikprogramatora/okna/settings.dart'; import 'package:denikprogramatora/okna/signin_page.dart'; -import 'package:denikprogramatora/utils/datum_cas.dart'; import 'package:denikprogramatora/utils/devicecontainer.dart'; +import 'package:denikprogramatora/utils/input_decoration.dart'; import 'package:denikprogramatora/utils/loading_widget.dart'; import 'package:denikprogramatora/utils/months.dart'; +import 'package:denikprogramatora/utils/my_category.dart'; import 'package:denikprogramatora/utils/my_container.dart'; import 'package:denikprogramatora/utils/new_record_dialog.dart'; +import 'package:denikprogramatora/utils/programmer.dart'; import 'package:denikprogramatora/utils/show_info_dialog.dart'; import 'package:denikprogramatora/utils/vzhled.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:responsive_sizer/responsive_sizer.dart'; import 'package:url_launcher/url_launcher_string.dart'; +/* + Copyright (C) 2022 Matyáš Caras a Richard Pavlikán + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + class AllRecordsPage extends StatefulWidget { const AllRecordsPage({super.key}); @@ -29,7 +49,30 @@ class _AllRecordsPageState extends State { int selectedDay = DateTime.now().day; int year = DateTime.now().year; + List categories = [MyCategory("Nic", "nic")]; + List programmers = [ + const Programmer("Nic", "nic"), + Programmer(name, userUid) + ]; + List filterJazyky = [ + {"jazyk": "Nic", "barva": 0xff8200f3}, + ]; + + late String selectedCategory; + late String selectedProgrammer; bool newestToOldest = true; + late String selectedJazyk; + DateTime fromDate = + DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day); + DateTime toDate = + DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day); + + bool searchByFromDate = false; + bool searchByToDate = false; + + int timeHour = 0; + int timeMinute = 0; + int review = 0; @override void initState() { @@ -43,14 +86,29 @@ class _AllRecordsPageState extends State { return; } - ref.get().then((value) { - setState(() { - name = FirebaseAuth.instance.currentUser!.displayName ?? - value[ - "name"]; // fallback když uživatel je vytvořen skrz firebase admin - }); + name = FirebaseAuth.instance.currentUser!.displayName!; + + ref.collection("programmers").get().then((value) { + for (var snap in value.docs) { + var data = snap.data(); + + programmers.add(Programmer(data["name"], snap.id)); + } }); + ref.collection("categories").get().then((value) { + for (var snap in value.docs) { + var data = snap.data(); + categories.add(MyCategory(data["name"], snap.id)); + } + }); + + filterJazyky.addAll(jazyky); + + selectedCategory = categories[0].id; + selectedProgrammer = programmers[0].id; + selectedJazyk = "Nic"; + mesic = months[DateTime.now().month - 1]; setState(() { @@ -90,7 +148,7 @@ class _AllRecordsPageState extends State { onPressed: () => showAboutDialog( context: context, applicationName: "Kodelog", - applicationVersion: "2.0.1", + applicationVersion: "1.1.0", applicationLegalese: "©️ 2023 Matyáš Caras a Richard Pavlikán,\n vydáno pod licencí AGPLv3", children: [ @@ -190,115 +248,465 @@ class _AllRecordsPageState extends State { Expanded( child: MyContainer( width: 90.w, - child: Center( - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.center, + child: DeviceContainer( + mainAxisAlignmentDesktop: + MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + width: + (Device.screenType == ScreenType.mobile) + ? 80.w + : 40.w, + child: Column( children: [ - Text( - "Záznamy seřazené \nod ${newestToOldest ? "nejnovějších po nejstarší" : "nejstarších po nejnovější"}"), - TextButton( - onPressed: () { - setState(() { - newestToOldest = !newestToOldest; - }); - }, - child: const Text( - "Změnit", - style: Vzhled.textBtn, - ), - ) + const Text("Filtr", + style: Vzhled.nadpis), + const SizedBox(height: 15), + Row( + children: [ + Flexible( + child: Text( + "Záznamy seřazené od ${newestToOldest ? "nejnovějších po nejstarší" : "nejstarších po nejnovější"}"), + ), + TextButton( + onPressed: () { + setState(() { + newestToOldest = + !newestToOldest; + }); + }, + child: const Text( + "Změnit", + style: Vzhled.textBtn, + ), + ) + ], + ), + const SizedBox(height: 15), + DeviceContainer( + children: [ + const Text("Kategorie"), + const SizedBox(width: 15), + DropdownButton( + value: selectedCategory, + items: categories.map((e) { + return DropdownMenuItem( + value: e.id, + child: Text(e.name)); + }).toList(), + onChanged: (value) { + setState(() { + selectedCategory = value!; + }); + }, + ), + ], + ), + const SizedBox(height: 15), + DeviceContainer( + children: [ + const Text("Jazyk"), + const SizedBox(width: 15), + DropdownButton( + value: selectedJazyk, + dropdownColor: + Vzhled.backgroundColor, + items: filterJazyky + .map( + (e) => DropdownMenuItem( + value: e["jazyk"], + child: Text(e["jazyk"]), + ), + ) + .toList(), + onChanged: (value) { + setState(() { + selectedJazyk = + (value as String?)!; + }); + }, + ), + ], + ), + const SizedBox(height: 15), + DeviceContainer( + children: [ + const Text("Programátor"), + const SizedBox(width: 15), + DropdownButton( + value: selectedProgrammer, + items: programmers.map((e) { + return DropdownMenuItem( + value: e.id, + child: Text(e.name)); + }).toList(), + onChanged: (value) { + setState(() { + selectedProgrammer = value!; + }); + }, + ), + ], + ), + const SizedBox(height: 15), + DeviceContainer( + children: [ + const Text("Strávený čas"), + const SizedBox(width: 15), + SizedBox( + width: 75, + child: TextField( + decoration: + inputDecoration("Hodin"), + onChanged: (value) { + setState(() { + timeHour = + value.trim().isEmpty + ? 0 + : int.parse(value); + }); + }, + keyboardType: + TextInputType.number, + inputFormatters: < + TextInputFormatter>[ + FilteringTextInputFormatter + .digitsOnly + ], + ), + ), + const SizedBox(width: 15), + SizedBox( + width: 75, + child: TextField( + decoration: + inputDecoration("Minut"), + onChanged: (value) { + setState(() { + timeMinute = + value.trim().isEmpty + ? 0 + : int.parse(value); + }); + }, + keyboardType: + TextInputType.number, + inputFormatters: < + TextInputFormatter>[ + FilteringTextInputFormatter + .digitsOnly + ], + ), + ), + const SizedBox(width: 15), + if (timeMinute != 0 || + timeHour != 0) + TextButton( + onPressed: () { + setState(() { + timeMinute = 0; + timeHour = 0; + }); + }, + child: const Text( + "Zrušit filtr", + style: Vzhled.textBtn, + ), + ) + ], + ), + const SizedBox(height: 15), + DeviceContainer( + children: [ + const Text("Hodnocení"), + const SizedBox(width: 15), + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: List.generate( + 5, + (index) { + return IconButton( + onPressed: () { + setState(() { + review = index + 1; + }); + }, + icon: Icon(Icons.star, + color: (index + 1) <= + review + ? Colors.yellow + : Colors.grey), + ); + }, + ), + ), + if (review != 0) + TextButton( + onPressed: () { + setState(() { + review = 0; + }); + }, + child: const Text( + "Zrušit filtr", + style: Vzhled.textBtn, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + children: [ + const Text("Od: "), + const SizedBox(width: 15), + TextButton( + onPressed: () { + showDatePicker( + context: context, + initialDate: fromDate, + firstDate: DateTime( + DateTime.now() + .year - + 5), + lastDate: DateTime( + DateTime.now() + .year + + 5)) + .then((value) { + setState(() { + fromDate = value!; + searchByFromDate = true; + }); + }).onError( + (error, stackTrace) => + null); + }, + child: Text(searchByFromDate + ? "${fromDate.day}.${fromDate.month}.${fromDate.year}" + : "Vybrat den"), + ), + const SizedBox(width: 15), + if (searchByFromDate) + TextButton( + onPressed: () { + setState(() { + searchByFromDate = false; + }); + }, + child: const Text( + ("Zrušit filtr"), + style: Vzhled.textBtn, + ), + ), + ], + ), + const SizedBox(height: 5), + Row( + children: [ + const Text("Do: "), + const SizedBox(width: 15), + TextButton( + onPressed: () { + showDatePicker( + context: context, + initialDate: toDate, + firstDate: DateTime( + DateTime.now() + .year - + 5), + lastDate: DateTime( + DateTime.now() + .year + + 5)) + .then((value) { + setState(() { + toDate = value!; + searchByToDate = true; + }); + }).onError( + (error, stackTrace) => + null); + }, + child: Text(searchByToDate + ? "${toDate.day}.${toDate.month}.${toDate.year}" + : "Vybrat den"), + ), + const SizedBox(width: 15), + if (searchByToDate) + TextButton( + onPressed: () { + setState(() { + searchByToDate = false; + }); + }, + child: const Text( + ("Zrušit filtr"), + style: Vzhled.textBtn, + ), + ), + ], + ), ], ), - const SizedBox(height: 5), - SizedBox( - width: (Device.screenType == - ScreenType.mobile) - ? 80.w - : 40.w, - child: StreamBuilder( - stream: ref - .collection("records") - .orderBy("date", - descending: newestToOldest) - .snapshots(), - builder: (context, snapshot) { - if (snapshot.hasData) { - var docs = snapshot.data!.docs; + ), + SizedBox( + width: + (Device.screenType == ScreenType.mobile) + ? 80.w + : 40.w, + child: StreamBuilder( + stream: ref + .collection("records") + .orderBy("fromDate", + descending: newestToOldest) + .snapshots(), + builder: (context, snapshot) { + if (snapshot.hasData) { + var docs = snapshot.data!.docs; - return Column( - children: List.generate( - docs.length, - (index) { - var data = docs[index].data(); + if (selectedProgrammer != "nic") { + docs = docs + .where((element) => + element + .data()["programmer"] == + selectedProgrammer) + .toList(); + } - return Padding( - padding: - const EdgeInsets.all( - 8.0), - child: Container( - decoration: BoxDecoration( - borderRadius: - const BorderRadius - .all( - Radius.circular(4), - ), - color: Color(data[ - "programming_language"] - ["barva"]), + if (selectedCategory != "nic") { + docs = docs + .where((element) => (element + .data()[ + "categories"] as List) + .contains(selectedCategory)) + .toList(); + } + + if (selectedJazyk != "Nic") { + docs = docs + .where((element) => + element.data()["language"] + ["jazyk"] == + selectedJazyk) + .toList(); + } + + if (searchByFromDate) { + docs = docs + .where((d) => + (d.data()["fromDate"] + as Timestamp) + .toDate() + .compareTo( + fromDate) == + 1 || + (d.data()["fromDate"] + as Timestamp) + .toDate() + .compareTo( + fromDate) == + 0) + .toList(); + } + + if (searchByToDate) { + docs = docs + .where((d) => + (d.data()["toDate"] + as Timestamp) + .toDate() + .compareTo( + toDate) == + -1 || + (d.data()["toDate"] + as Timestamp) + .toDate() + .compareTo( + toDate) == + 0) + .toList(); + } + + if (timeHour != 0 || + timeMinute != 0) { + if (kDebugMode) { + print( + "${timeHour == 0 ? "" : (timeHour == 1 ? "$timeHour hodina" : "$timeHour hodin")}${timeMinute == 0 ? "" : (timeMinute == 1 ? "a $timeMinute minuta" : " a $timeMinute minut")}"); + } + docs = docs + .where((element) => (element + .data()["codingTime"] == + "${timeHour == 0 ? "" : (timeHour == 1 ? "$timeHour hodina" : "$timeHour hodin")}${timeMinute == 0 ? "" : (timeMinute == 1 ? "a $timeMinute minuta" : " a $timeMinute minut")}")) + .toList(); + } + + if (review != 0) { + docs = docs + .where((element) => + element.data()["review"] == + review) + .toList(); + } + + return Column( + children: List.generate( + docs.length, + (index) { + var data = docs[index].data(); + + return Padding( + padding: + const EdgeInsets.all(8.0), + child: Container( + decoration: BoxDecoration( + borderRadius: + const BorderRadius + .all( + Radius.circular(4), ), - child: Material( - color: - Colors.transparent, - child: InkWell( - onTap: () => - showInfoDialog( - context, - data, - docs[index] - .id, - name), - child: Padding( - padding: - const EdgeInsets - .all(8.0), - child: Row( - children: [ - Text((data["date"] - as Timestamp) - .toDate() - .dateString), - const SizedBox( - width: 20, - ), - Text( - "${data["programming_language"]["jazyk"]}", - style: const TextStyle( - fontWeight: - FontWeight - .bold), - ), - Text( - " - ${data["time_spent"]}") - ], - ), + color: Color( + data["language"] + ["barva"]), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => + showInfoDialog( + context, + data, + docs[index].id), + child: Padding( + padding: + const EdgeInsets + .all(8.0), + child: Row( + children: [ + Text( + "${(data["fromDate"] as Timestamp).toDate().year}.${(data["fromDate"] as Timestamp).toDate().month}.${(data["fromDate"] as Timestamp).toDate().day} ${(data["fromDate"] as Timestamp).toDate().hour < 10 ? "0${(data["fromDate"] as Timestamp).toDate().hour}" : (data["fromDate"] as Timestamp).toDate().hour}:${(data["fromDate"] as Timestamp).toDate().minute < 10 ? "0${(data["fromDate"] as Timestamp).toDate().minute}" : (data["fromDate"] as Timestamp).toDate().minute}"), + const SizedBox( + width: 20, + ), + Text( + " - ${data["language"]["jazyk"]}") + ], ), ), ), ), - ); - }, - ), - ); - } - return const LoadingWidget(); - }, - ), + ), + ); + }, + ), + ); + } + return const LoadingWidget(); + }, ), - ], - ), + ), + ], ), ), ), diff --git a/lib/okna/app.dart b/lib/okna/app.dart index eb1db74..095e49d 100644 --- a/lib/okna/app.dart +++ b/lib/okna/app.dart @@ -66,15 +66,10 @@ class _HlavniOknoState extends State { (route) => false); return; } - userUid = FirebaseAuth.instance.currentUser!.uid; - ref.get().then((value) { - setState(() { - name = FirebaseAuth.instance.currentUser!.displayName ?? - value[ - "name"]; // fallback když uživatel je vytvořen skrz firebase admin - }); - }); + userUid = FirebaseAuth.instance.currentUser!.uid; + name = FirebaseAuth.instance.currentUser!.displayName!; + mesic = months[DateTime.now().month - 1]; setState(() { @@ -113,9 +108,9 @@ class _HlavniOknoState extends State { onPressed: () => showAboutDialog( context: context, applicationName: "Kodelog", - applicationVersion: "2.0.1", + applicationVersion: "1.1.0", applicationLegalese: - "©️ 2023 Matyáš Caras a Richard Pavlikán" /*+",\n vydáno pod licencí AGPLv3"*/, + "©️ 2023 Matyáš Caras a Richard Pavlikán,\n vydáno pod licencí AGPLv3", children: [ TextButton( child: const Text("Zdrojový kód"), @@ -149,8 +144,8 @@ class _HlavniOknoState extends State { ), MyContainer( width: (Device.screenType == ScreenType.mobile) - ? 90.w - : 40.w, + ? 95.w + : 45.w, child: DeviceContainer( mainAxisAlignmentDesktop: MainAxisAlignment.spaceBetween, @@ -225,12 +220,19 @@ class _HlavniOknoState extends State { if (snapshot.hasData) { var docs = snapshot.data!.docs; var jenMesic = docs - .where((d) => DateTime.parse( - "$year-${(mesic.position + 1 < 10) ? "0${mesic.position + 1}" : mesic.position + 1}-${selectedDay < 10 ? "0$selectedDay" : selectedDay} 00:00:00") - .isAtSameMomentAs( - (d.data()["date"] - as Timestamp) - .toDate())) + .where((d) => + DateTime.parse( + "$year-${(mesic.position + 1 < 10) ? "0${mesic.position + 1}" : mesic.position + 1}-${selectedDay < 10 ? "0$selectedDay" : selectedDay} 00:00:00") + .isBefore( + (d.data()["toDate"] + as Timestamp) + .toDate()) && + DateTime.parse( + "$year-${(mesic.position + 1 < 10) ? "0${mesic.position + 1}" : mesic.position + 1}-${selectedDay < 10 ? "0$selectedDay" : selectedDay} 23:59:59") + .isAfter( + (d.data()["fromDate"] + as Timestamp) + .toDate())) .toList() // vybere pouze záznamy, které probíhají ve vybraný den ..sort( razeni[vybraneRazeni], @@ -260,9 +262,9 @@ class _HlavniOknoState extends State { .all( Radius.circular(4), ), - color: Color(data[ - "programming_language"] - ["barva"]), + color: Color( + data["language"] + ["barva"]), ), child: Material( color: Colors.transparent, @@ -272,8 +274,7 @@ class _HlavniOknoState extends State { context, data, jenMesic[index] - .id, - name), + .id), child: Padding( padding: const EdgeInsets @@ -281,14 +282,12 @@ class _HlavniOknoState extends State { child: Row( children: [ Text( - "${data["programming_language"]["jazyk"]}", - style: const TextStyle( - fontWeight: - FontWeight - .bold), + "${(data["fromDate"] as Timestamp).toDate().hour < 10 ? "0${(data["fromDate"] as Timestamp).toDate().hour}" : (data["fromDate"] as Timestamp).toDate().hour}:${(data["fromDate"] as Timestamp).toDate().minute < 10 ? "0${(data["fromDate"] as Timestamp).toDate().minute}" : (data["fromDate"] as Timestamp).toDate().minute}"), + const SizedBox( + width: 20, ), Text( - " - ${data["time_spent"]}") + " - ${data["language"]["jazyk"]}") ], ), ), @@ -309,10 +308,7 @@ class _HlavniOknoState extends State { height: 50, ), SizedBox( - width: - (Device.screenType == ScreenType.mobile) - ? 60.w - : 40.w, + width: 45.w, child: Column( children: [ DeviceContainer( @@ -508,10 +504,9 @@ class _HlavniOknoState extends State { : 5), (index) { return Row( - mainAxisAlignment: MainAxisAlignment.center, - // (Device.screenType == ScreenType.mobile) - // ? MainAxisAlignment.center - // : MainAxisAlignment.start, + mainAxisAlignment: (Device.screenType == ScreenType.mobile) + ? MainAxisAlignment.center + : MainAxisAlignment.start, children: List.generate( (Device.screenType == ScreenType.mobile) ? 3 : 7, (index) { diff --git a/lib/okna/settings.dart b/lib/okna/settings.dart index c1420dd..d7ac392 100644 --- a/lib/okna/settings.dart +++ b/lib/okna/settings.dart @@ -1,21 +1,34 @@ import 'package:denikprogramatora/okna/app.dart'; import 'package:denikprogramatora/okna/signin_page.dart'; -import 'package:denikprogramatora/okna/users_page.dart'; import 'package:denikprogramatora/utils/devicecontainer.dart'; import 'package:denikprogramatora/utils/loading_widget.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:responsive_sizer/responsive_sizer.dart'; import 'package:url_launcher/url_launcher_string.dart'; -// ignore: avoid_web_libraries_in_flutter -import 'dart:html' as html; -import '../utils/csv.dart'; import '../utils/my_container.dart'; import '../utils/new_record_dialog.dart'; import '../utils/vzhled.dart'; import 'all_records.dart'; +/* + Copyright (C) 2022 Matyáš Caras a Richard Pavlikán + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + class NastaveniOkno extends StatefulWidget { const NastaveniOkno({super.key}); @@ -26,8 +39,6 @@ class NastaveniOkno extends StatefulWidget { class _NastaveniOknoState extends State { var _loading = true; var name = "error"; - bool isAdmin = false; - @override void initState() { super.initState(); @@ -38,16 +49,7 @@ class _NastaveniOknoState extends State { (route) => false); return; } - - ref.get().then((value) { - setState(() { - name = FirebaseAuth.instance.currentUser!.displayName ?? - value[ - "name"]; // fallback když uživatel je vytvořen skrz firebase admin - - isAdmin = value["isAdmin"]; - }); - }); + name = FirebaseAuth.instance.currentUser!.displayName!; setState(() { _loading = false; @@ -58,380 +60,247 @@ class _NastaveniOknoState extends State { Widget build(BuildContext context) { return Scaffold( body: SingleChildScrollView( - child: Center( - child: SizedBox( - width: 90.w, - height: 100.h, - child: (_loading) - ? const LoadingWidget() - : Column( + child: Center( + child: SizedBox( + width: 90.w, + height: 100.h, + child: (_loading) + ? const LoadingWidget() + : Column(children: [ + DeviceContainer( + mainAxisAlignmentDesktop: MainAxisAlignment.spaceBetween, children: [ - DeviceContainer( - mainAxisAlignmentDesktop: - MainAxisAlignment.spaceBetween, - children: [ - MyContainer( - width: (Device.screenType == ScreenType.mobile) - ? 90.w - : 35.w, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (name != "error") Text("Ahoj $name"), - TextButton( - onPressed: () => showAboutDialog( - context: context, - applicationName: "Kodelog", - applicationVersion: "2.0.1", - applicationLegalese: - "©️ 2023 Matyáš Caras a Richard Pavlikán,\n vydáno pod licencí AGPLv3", - children: [ - TextButton( - child: const Text("Zdrojový kód"), - onPressed: () => launchUrlString( - "https://github.com/Royal-Buccaneers/kodelog"), - ) - ]), - child: const Text( - "Licence", - style: Vzhled.textBtn, - ), - ), - TextButton( - onPressed: () async { - await FirebaseAuth.instance.signOut(); - if (!mounted) return; - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute( - builder: (c) => const SignInPage()), - (route) => false); - }, - child: const Text( - "Odhlásit se", - style: Vzhled.textBtn, - ), - ) - ], + MyContainer( + width: (Device.screenType == ScreenType.mobile) + ? 90.w + : 35.w, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (name != "error") Text("Ahoj $name"), + TextButton( + onPressed: () => showAboutDialog( + context: context, + applicationName: "Kodelog", + applicationVersion: "1.1.0", + applicationLegalese: + "©️ 2023 Matyáš Caras a Richard Pavlikán,\n vydáno pod licencí AGPLv3", + children: [ + TextButton( + child: const Text("Zdrojový kód"), + onPressed: () => launchUrlString( + "https://github.com/Royal-Buccaneers/kodelog"), + ) + ]), + child: const Text( + "Licence", + style: Vzhled.textBtn, + ), ), - ), - MyContainer( - width: (Device.screenType == ScreenType.mobile) - ? 90.w - : 40.w, - child: DeviceContainer( - mainAxisAlignmentDesktop: - MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () => Navigator.of(context) - .pushReplacement(MaterialPageRoute( - builder: (context) => - const HlavniOkno())), - child: const Text( - "Denní přehled", - style: TextStyle(color: Vzhled.textColor), - ), - ), - const SizedBox(height: 5), - TextButton( - onPressed: () { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => - const AllRecordsPage())); - }, - child: const Text( - "Všechny\nzáznamy", - style: TextStyle(color: Vzhled.textColor), - ), - ), - const SizedBox(height: 5), - TextButton( - onPressed: () {}, - child: const Text( - "Nastavení", - style: TextStyle( - color: Vzhled.textColor, - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(height: 5), - OutlinedButton( - onPressed: () => - showCreateItemDialog(context), - style: Vzhled.orangeCudlik, - child: const Text( - "Přidat záznam", - ), - ) - ], - ), - ), - ], - ), - const SizedBox(height: 5), - Expanded( - child: MyContainer( - width: 90.w, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular( - 10, - ), - ), - color: Vzhled.purple), - width: 400, - child: InkWell( - onTap: () => showEditJazyk(), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: const [ - Text( - "Oblíbený jazyk", - style: Vzhled.nadpis, - ) - ], - ), - ), - ), + TextButton( + onPressed: () async { + await FirebaseAuth.instance.signOut(); + if (!mounted) return; + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (c) => const SignInPage()), + (route) => false); + }, + child: const Text( + "Odhlásit se", + style: Vzhled.textBtn, ), - const SizedBox( - height: 15, - ), - Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular( - 10, - ), - ), - color: Vzhled.purple), - width: 400, - child: InkWell( - onTap: () => showCategoriesDialog(context, [], - jenMenit: true), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: const [ - Text( - "Upravit kategorie", - style: Vzhled.nadpis, - ) - ], - ), - ), - ), - ), - const SizedBox( - height: 15, - ), - DeviceContainer( - mainAxisAlignmentDesktop: - MainAxisAlignment.center, - mainAxisAlignmentMobile: - MainAxisAlignment.center, - children: [ - Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular( - 10, - ), - ), - color: Vzhled.purple), - width: 400, - child: InkWell( - onTap: () async { - var csv = await exportCsv(); - var blob = html.Blob([csv]); - var url = - html.Url.createObjectUrlFromBlob( - blob); - var anchor = html.document - .createElement('a') - as html.AnchorElement - ..href = url - ..style.display = 'none' - ..download = - 'db_${name.replaceAll(" ", "_")}.csv'; - html.document.body!.children - .add(anchor); - - anchor.click(); - - html.document.body!.children - .remove(anchor); - html.Url.revokeObjectUrl(url); - }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: const [ - Text( - "Exportovat CSV", - style: Vzhled.nadpis, - ) - ], - ), - ), - ), - ), - const SizedBox( - width: 10, - height: 10, - ), - Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular( - 10, - ), - ), - color: Vzhled.purple), - width: 400, - child: InkWell( - onTap: () async { - try { - var p = await importCsv(name); - if (p != -1) { - if (!mounted) return; - showDialog( - context: context, - builder: (c) => AlertDialog( - title: const Text("Úspěch!"), - content: Text( - "Importováno $p záznamů"), - actions: [ - TextButton( - onPressed: () => - Navigator.of(c).pop(), - child: const Text("Ok")) - ], - ), - ); - } - } catch (e) { - showDialog( - context: context, - builder: (c) => AlertDialog( - title: const Text( - "Při importování nastala chyba!"), - content: Text(e.toString()), - ), - ); - } - }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: const [ - Text( - "Importovat CSV", - style: Vzhled.nadpis, - ) - ], - ), - ), - ), - ), - ], - ), - const SizedBox( - height: 15, - ), - if (isAdmin) - Container( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular( - 10, - ), - ), - color: Vzhled.purple), - width: 400, - child: InkWell( - onTap: () => Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => const UsersPage(), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: const [ - Text( - "Správa uživatelů", - style: Vzhled.nadpis, - ) - ], - ), - ), - ), - ), - ], - ), + ) + ], ), - ) + ), + MyContainer( + width: (Device.screenType == ScreenType.mobile) + ? 90.w + : 40.w, + child: DeviceContainer( + mainAxisAlignmentDesktop: + MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () => Navigator.of(context) + .pushReplacement(MaterialPageRoute( + builder: (context) => + const HlavniOkno())), + child: const Text( + "Denní přehled", + style: TextStyle(color: Vzhled.textColor), + ), + ), + const SizedBox(height: 5), + TextButton( + onPressed: () { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => + const AllRecordsPage())); + }, + child: const Text( + "Všechny\nzáznamy", + style: TextStyle(color: Vzhled.textColor), + ), + ), + const SizedBox(height: 5), + TextButton( + onPressed: () {}, + child: const Text( + "Nastavení", + style: TextStyle( + color: Vzhled.textColor, + fontWeight: FontWeight.bold, + ), + ), + ), + const SizedBox(height: 5), + OutlinedButton( + onPressed: () => showCreateItemDialog(context), + style: Vzhled.orangeCudlik, + child: const Text( + "Přidat záznam", + ), + ) + ], + ), + ), ], ), - ), + const SizedBox(height: 5), + Expanded( + child: MyContainer( + width: 90.w, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular( + 10, + ), + ), + color: Vzhled.purple, + ), + width: 400, + child: InkWell( + onTap: () => showProgrammersDialog(context, + jenMenit: true), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Text( + "Upravit programátory", + style: Vzhled.nadpis, + ) + ], + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular( + 10, + ), + ), + color: Vzhled.purple), + width: 400, + child: InkWell( + onTap: () => showCategoriesDialog(context, [], + jenMenit: true), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Text( + "Upravit kategorie", + style: Vzhled.nadpis, + ) + ], + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular( + 10, + ), + ), + color: Vzhled.purple), + width: 400, + child: InkWell( + onTap: () => showEditJazyk(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Text( + "Oblíbený jazyk", + style: Vzhled.nadpis, + ) + ], + ), + ), + ), + ), + ]), + )) + ]), ), - ), + )), ); } showEditJazyk() { showDialog( - context: context, - builder: (_) => AlertDialog( - title: const Text("Oblíbený jazyk", style: Vzhled.velkyText), - scrollable: true, - content: SizedBox( - width: 20.w, - child: StreamBuilder( - stream: ref.snapshots(), - builder: (context, snapshot) { - if (snapshot.hasData) { - return DropdownButton( - value: snapshot.data!.data()!["favourite"], - dropdownColor: Vzhled.backgroundColor, - items: jazyky - .map( - (e) => DropdownMenuItem( - value: e["jazyk"], - child: SizedBox( - width: 17.w, child: Text(e["jazyk"])), - ), - ) - .toList(), - onChanged: (value) { - ref.update({"favourite": value!}); - }); - } - return const LoadingWidget(); - }), - ), - ), - ); + context: context, + builder: (_) => AlertDialog( + title: const Text("Oblíbený jazyk", style: Vzhled.velkyText), + scrollable: true, + content: SizedBox( + width: 20.w, + child: StreamBuilder( + stream: ref.snapshots(), + builder: (context, snapshot) { + if (snapshot.hasData) { + return DropdownButton( + value: snapshot.data!.data()!["favourite"], + dropdownColor: Vzhled.backgroundColor, + items: jazyky + .map( + (e) => DropdownMenuItem( + value: e["jazyk"], + child: SizedBox( + width: 17.w, child: Text(e["jazyk"])), + ), + ) + .toList(), + onChanged: (value) { + ref.update({"favourite": value!}); + }); + } + return const LoadingWidget(); + }), + ), + )); } } diff --git a/lib/okna/signin_page.dart b/lib/okna/signin_page.dart index bc34204..cdfbace 100644 --- a/lib/okna/signin_page.dart +++ b/lib/okna/signin_page.dart @@ -9,6 +9,23 @@ import 'package:flutter/scheduler.dart'; import 'package:responsive_sizer/responsive_sizer.dart'; import 'package:url_launcher/url_launcher_string.dart'; +/* + Copyright (C) 2022 Matyáš Caras a Richard Pavlikán + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + class SignInPage extends StatefulWidget { const SignInPage({super.key}); @@ -17,10 +34,8 @@ class SignInPage extends StatefulWidget { } class _SignInPageState extends State { + bool showSignIn = true; bool isLoading = true; - bool isSignInWidget = true; - bool showEmailPage = true; - String oldDocId = ""; TextEditingController emailCon = TextEditingController(); TextEditingController passwordCon = TextEditingController(); @@ -55,7 +70,7 @@ class _SignInPageState extends State { : Stack( children: [ Center( - child: isSignInWidget ? signInWidget() : registerWidget(), + child: showSignIn ? signInWidget() : registerWidget(), ), Positioned( bottom: 10, @@ -64,7 +79,7 @@ class _SignInPageState extends State { onPressed: () => showAboutDialog( context: context, applicationName: "Kodelog", - applicationVersion: "2.0.1", + applicationVersion: "1.1.0", applicationLegalese: "©️ 2023 Matyáš Caras a Richard Pavlikán,\n vydáno pod licencí AGPLv3", children: [ @@ -106,7 +121,7 @@ class _SignInPageState extends State { SizedBox( width: (Device.screenType == ScreenType.mobile) ? 60.w : 30.w, child: TextFormField( - decoration: Vzhled.inputDecoration("E-mail nebo Username"), + decoration: Vzhled.inputDecoration("E-mail"), cursorColor: Vzhled.textColor, keyboardType: TextInputType.emailAddress, autocorrect: false, @@ -119,6 +134,9 @@ class _SignInPageState extends State { validator: (value) { if (value!.trim().isEmpty) { return "Toto pole je povinné!"; + } else if (!RegExp(r'[\w\.]+@[a-z0-9]+\.[a-z]{1,3}') + .hasMatch(value)) { + return "Neplatný e-mail!"; } return null; }, @@ -170,15 +188,11 @@ class _SignInPageState extends State { TextButton( onPressed: () { setState(() { - isSignInWidget = false; - showEmailPage = true; + showSignIn = false; }); }, - child: const Text( - "Přihlašuji se poprvé", - style: Vzhled.textBtn, - ), - ), + child: const Text("Registrovat se", style: Vzhled.textBtn), + ) ], ), ), @@ -187,9 +201,7 @@ class _SignInPageState extends State { Widget registerWidget() { GlobalKey form = GlobalKey(); - return MyContainer( - height: 70.h, width: (Device.screenType == ScreenType.mobile) ? 80.w : 40.w, child: Form( key: form, @@ -204,142 +216,119 @@ class _SignInPageState extends State { const SizedBox( height: 30, ), - showEmailPage - ? SizedBox( - width: - (Device.screenType == ScreenType.mobile) ? 60.w : 30.w, - child: TextFormField( - decoration: Vzhled.inputDecoration("Váš e-mail"), - cursorColor: Vzhled.textColor, - keyboardType: TextInputType.emailAddress, - autocorrect: false, - controller: emailCon, - validator: (value) { - if (value!.trim().isEmpty) { - return "Toto pole je povinné!"; - } - return null; - }, - ), - ) - : SizedBox( - width: - (Device.screenType == ScreenType.mobile) ? 60.w : 30.w, - child: TextFormField( - decoration: Vzhled.inputDecoration("Váš nové heslo"), - cursorColor: Vzhled.textColor, - autocorrect: false, - obscureText: true, - controller: passwordCon, - validator: (value) { - if (value!.trim().isEmpty) { - return "Toto pole je povinné!"; - } - return null; - }, - ), - ), + SizedBox( + width: (Device.screenType == ScreenType.mobile) ? 60.w : 30.w, + child: TextFormField( + decoration: Vzhled.inputDecoration("Jméno"), + cursorColor: Vzhled.textColor, + controller: nameCon, + onFieldSubmitted: (_) { + if (form.currentState!.validate()) { + signUp(); + } + }, + validator: (value) { + if (value!.trim().isEmpty) { + return "Toto pole je povinné!"; + } + return null; + }, + ), + ), const SizedBox( height: 20, ), - showEmailPage - ? OutlinedButton( - style: Vzhled.orangeCudlik, - onPressed: () async { - if (form.currentState!.validate()) { - var emailRef = await FirebaseFirestore.instance - .collection("users") - .where("email", isEqualTo: emailCon.text) - .get(); - - if (emailRef.docs.isEmpty) { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text( - "Účet s tímto emailem neexistuje. Pro přístup do aplikace musí váš email přidat admin aplikace."), - ), - ); - return; - } - - setState(() { - oldDocId = emailRef.docs.first.id; - showEmailPage = false; - }); - } - }, - child: const Text("Pokračovat"), - ) - : OutlinedButton( - onPressed: () async { - if (form.currentState!.validate()) { - await FirebaseAuth.instance - .createUserWithEmailAndPassword( - email: emailCon.text, - password: passwordCon.text) - .then((value) async { - await FirebaseFirestore.instance - .collection("users") - .doc(oldDocId) - .get() - .then((value) { - FirebaseFirestore.instance - .collection("users") - .doc(FirebaseAuth.instance.currentUser!.uid) - .set({ - "name": value["name"], - "favourite": value["favourite"], - "isAdmin": value["isAdmin"], - "username": value["username"], - "email": value["email"], - }); - }).then((value) { - FirebaseFirestore.instance - .collection("users") - .doc(oldDocId) - .delete(); - }); - - // ignore: use_build_context_synchronously - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => const HlavniOkno(), - ), - ); - }).onError((e, st) { - if (e - .toString() - .contains("firebase_auth/email-already-in-use")) { - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text( - "Váš účet už existuje, prosím přihlaste se"), - ), - ); - } else if (e - .toString() - .contains("firebase_auth/wrong-password")) { - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text("Zadáváte špatné heslo!"), - ), - ); - } - - return; - }); - } - }, - style: Vzhled.orangeCudlik, - child: const Text("Pokračovat")), + SizedBox( + width: (Device.screenType == ScreenType.mobile) ? 60.w : 30.w, + child: TextFormField( + decoration: Vzhled.inputDecoration("E-mail"), + cursorColor: Vzhled.textColor, + controller: emailCon, + keyboardType: TextInputType.emailAddress, + autocorrect: false, + onFieldSubmitted: (_) { + if (form.currentState!.validate()) { + signUp(); + } + }, + validator: (value) { + if (value!.trim().isEmpty) { + return "Toto pole je povinné!"; + } else if (!RegExp(r'[\w\.]+@[a-z0-9]+\.[a-z]{1,3}') + .hasMatch(value)) { + return "Neplatný e-mail!"; + } + return null; + }, + ), + ), + const SizedBox( + height: 20, + ), + SizedBox( + width: (Device.screenType == ScreenType.mobile) ? 60.w : 30.w, + child: TextFormField( + decoration: Vzhled.inputDecoration("Heslo"), + cursorColor: Vzhled.textColor, + obscureText: true, + controller: passwordCon, + onFieldSubmitted: (_) { + if (form.currentState!.validate()) { + signUp(); + } + }, + validator: (value) { + if (value!.trim().isEmpty) { + return "Toto pole je povinné!"; + } + return null; + }, + ), + ), + const SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + "Oblíbený jazyk:", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 5), + DropdownButton( + value: jazyk, + dropdownColor: Vzhled.backgroundColor, + items: jazyky + .map( + (e) => DropdownMenuItem( + value: e["jazyk"], + child: Text(e["jazyk"]), + ), + ) + .toList(), + onChanged: (value) { + setState(() { + jazyk = (value as String?)!; + }); + }, + ), + ], + ), + const SizedBox( + height: 20, + ), + OutlinedButton( + style: Vzhled.orangeCudlik, + onPressed: () async { + if (form.currentState!.validate()) { + signUp(); + } + }, + child: const Text("Registrovat se"), + ), const SizedBox( height: 10, ), @@ -350,54 +339,21 @@ class _SignInPageState extends State { TextButton( onPressed: () { setState(() { - isSignInWidget = true; + showSignIn = true; }); }, - child: const Text( - "Účet mám vytvořen, chci se přihlásit", - style: Vzhled.textBtn, - ), - ), + child: const Text("Přihlásit se", style: Vzhled.textBtn), + ) ], ), ), ); } - void signIn() async { - setState(() { - isLoading = true; - }); - - String email = emailCon.text; - - if (!emailCon.text.contains("@")) { - var usernameRef = await FirebaseFirestore.instance - .collection("users") - .where("username", isEqualTo: emailCon.text) - .get(); - - if (usernameRef.docs.isEmpty) { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text("Účet s tímto jménem neexistuje"), - ), - ); - - setState(() { - isLoading = false; - }); - return; - } - - email = usernameRef.docs.single.data()["email"]; - } - + void signIn() { FirebaseAuth.instance - .signInWithEmailAndPassword(email: email, password: passwordCon.text) + .signInWithEmailAndPassword( + email: emailCon.text, password: passwordCon.text) .then( (value) => Navigator.pushReplacement( context, @@ -432,11 +388,49 @@ class _SignInPageState extends State { debugPrint(e.toString()); } }); + } - if (mounted) { - setState(() { - isLoading = false; - }); - } + void signUp() { + FirebaseAuth.instance + .createUserWithEmailAndPassword( + email: emailCon.text, password: passwordCon.text) + .then( + (value) async { + await FirebaseFirestore.instance + .collection("users") + .doc(FirebaseAuth.instance.currentUser!.uid) + .set({ + "name": nameCon.text, + "email": emailCon.text, + "favourite": jazyk, + }); + value.user?.updateDisplayName(nameCon.text); + + if (!mounted) return; + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (c) => const HlavniOkno()), + ); + }, + ).onError((error, stackTrace) { + if (error.toString().contains("firebase_auth/email-already-in-use")) { + showDialog( + context: context, + builder: (c) => const AlertDialog( + title: Text("Chyba"), + content: Text("E-mail je již zaregistrovaný"), + ), + ); + } else { + showDialog( + context: context, + builder: (c) => const AlertDialog( + title: Text("Chyba"), + content: Text("Nastala neznámá chyba."), + ), + ); + debugPrint(error.toString()); + } + }); } } diff --git a/lib/okna/users_page.dart b/lib/okna/users_page.dart deleted file mode 100644 index 16518fe..0000000 --- a/lib/okna/users_page.dart +++ /dev/null @@ -1,633 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:denikprogramatora/okna/all_records.dart'; -import 'package:denikprogramatora/okna/signin_page.dart'; -import 'package:denikprogramatora/utils/devicecontainer.dart'; -import 'package:denikprogramatora/utils/loading_widget.dart'; -import 'package:denikprogramatora/utils/my_container.dart'; -import 'package:denikprogramatora/utils/new_record_dialog.dart'; -import 'package:denikprogramatora/utils/really_delete.dart'; -import 'package:denikprogramatora/utils/vzhled.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/material.dart'; -import 'package:responsive_sizer/responsive_sizer.dart'; -import 'package:url_launcher/url_launcher_string.dart'; - -import 'app.dart'; - -class UsersPage extends StatefulWidget { - const UsersPage({super.key}); - - @override - State createState() => _UsersPageState(); -} - -class _UsersPageState extends State { - var _loading = true; - var name = "error"; - @override - void initState() { - super.initState(); - if (FirebaseAuth.instance.currentUser == null) { - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (c) => const SignInPage()), - (route) => false); - return; - } - - ref.get().then((value) { - setState(() { - name = FirebaseAuth.instance.currentUser!.displayName ?? - value[ - "name"]; // fallback když uživatel je vytvořen skrz firebase admin - }); - }); - - setState(() { - _loading = false; - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SingleChildScrollView( - child: Center( - child: SizedBox( - width: 90.w, - height: 100.h, - child: (_loading) - ? const LoadingWidget() - : Column( - children: [ - DeviceContainer( - mainAxisAlignmentDesktop: - MainAxisAlignment.spaceBetween, - children: [ - MyContainer( - width: (Device.screenType == ScreenType.mobile) - ? 90.w - : 35.w, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (name != "error") Text("Ahoj $name"), - TextButton( - onPressed: () => showAboutDialog( - context: context, - applicationName: "Kodelog", - applicationVersion: "2.0.1", - applicationLegalese: - "©️ 2023 Matyáš Caras a Richard Pavlikán,\n vydáno pod licencí AGPLv3", - children: [ - TextButton( - child: const Text("Zdrojový kód"), - onPressed: () => launchUrlString( - "https://github.com/Royal-Buccaneers/kodelog"), - ) - ]), - child: const Text( - "Licence", - style: Vzhled.textBtn, - ), - ), - TextButton( - onPressed: () async { - await FirebaseAuth.instance.signOut(); - if (!mounted) return; - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute( - builder: (c) => const SignInPage()), - (route) => false); - }, - child: const Text( - "Odhlásit se", - style: Vzhled.textBtn, - ), - ) - ], - ), - ), - MyContainer( - width: (Device.screenType == ScreenType.mobile) - ? 90.w - : 40.w, - child: DeviceContainer( - mainAxisAlignmentDesktop: - MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () => Navigator.of(context) - .pushReplacement(MaterialPageRoute( - builder: (context) => - const HlavniOkno())), - child: const Text( - "Denní přehled", - style: TextStyle(color: Vzhled.textColor), - ), - ), - const SizedBox(height: 5), - TextButton( - onPressed: () { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => - const AllRecordsPage())); - }, - child: const Text( - "Všechny\nzáznamy", - style: TextStyle(color: Vzhled.textColor), - ), - ), - const SizedBox(height: 5), - TextButton( - onPressed: () {}, - child: const Text( - "Nastavení", - style: TextStyle( - color: Vzhled.textColor, - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(height: 5), - OutlinedButton( - onPressed: () => - showCreateItemDialog(context), - style: Vzhled.orangeCudlik, - child: const Text( - "Přidat záznam", - ), - ) - ], - ), - ), - ], - ), - const SizedBox(height: 5), - Expanded( - child: MyContainer( - width: 90.w, - child: SingleChildScrollView( - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, - children: [ - const Text("Uživatelé", - style: Vzhled.mensiAleVelkyText), - OutlinedButton( - onPressed: () => showNewUser(), - style: Vzhled.orangeCudlik, - child: const Text( - "Přidat uživatele", - ), - ), - ], - ), - const SizedBox(height: 40), - const Padding( - padding: EdgeInsets.only(right: 8.0, left: 8), - child: DeviceContainer( - mainAxisAlignmentDesktop: - MainAxisAlignment.spaceBetween, - mainAxisAlignmentMobile: - MainAxisAlignment.center, - children: [ - SizedBox( - width: 100, - child: Text( - "Jméno", - ), - ), - SizedBox( - width: 150, - child: Text( - "Email", - ), - ), - SizedBox( - width: 150, - child: Text("Username"), - ), - SizedBox( - width: 50, - child: Text("Admin"), - ), - Text("Nastavení") - ], - ), - ), - const SizedBox(height: 10), - SizedBox( - width: 80.w, - child: const Divider(color: Vzhled.purple), - ), - const SizedBox(height: 20), - SingleChildScrollView( - child: StreamBuilder( - stream: FirebaseFirestore.instance - .collection("users") - .snapshots(), - builder: (context, snapshot) { - if (snapshot.hasError) { - return const Text( - "Nastal error :C..."); - } else if (snapshot.hasData) { - var docs = snapshot.data!.docs; - return Column( - children: List.generate( - docs.length, - (index) { - var data = docs[index].data(); - - return Padding( - padding: - const EdgeInsets.all(8.0), - child: DeviceContainer( - mainAxisAlignmentDesktop: - MainAxisAlignment - .spaceBetween, - mainAxisAlignmentMobile: - MainAxisAlignment - .center, - children: [ - SizedBox( - width: 100, - child: Text( - data["name"], - style: const TextStyle( - fontWeight: - FontWeight - .bold), - ), - ), - SizedBox( - width: 150, - child: Text( - data["email"], - ), - ), - SizedBox( - width: 150, - child: Text( - data["username"] ?? - "Prozatím nic"), - ), - SizedBox( - width: 50, - child: Icon( - data["isAdmin"] ?? - false - ? Icons.done - : Icons - .do_disturb), - ), - (data["username"] != - "admin") - ? PopupMenuButton( - onSelected: - (value) { - switch (value) { - case 'Změnit práva': - showPrava( - docs[index] - .id, - data[ - "isAdmin"]); - break; - case "Upravit username": - showUpravitUsername( - docs[index] - .id, - data[ - "username"]); - break; - case 'Odstranit': - showOdstranit( - docs[index] - .id); - break; - } - }, - itemBuilder: - (BuildContext - context) { - return { - 'Změnit práva', - "Upravit username", - 'Odstranit' - }.map((String - choice) { - return PopupMenuItem< - String>( - value: - choice, - child: Text( - choice), - ); - }).toList(); - }, - ) - : const SizedBox( - width: 40) - ], - ), - ); - }, - ), - ); - } - return const LoadingWidget(); - }), - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - ), - ); - } - - showNewUser() async { - GlobalKey key = GlobalKey(); - String jmeno = ""; - String email = ""; - String username = ""; - bool isAdmin = false; - - showDialog( - context: context, - builder: (_) => AlertDialog( - title: const Text("Nový uživatel", style: Vzhled.velkyText), - scrollable: true, - content: StatefulBuilder( - builder: (context, setState) { - return SizedBox( - width: 50.w, - child: Form( - key: key, - child: Column( - children: [ - TextFormField( - decoration: Vzhled.inputDecoration("Jméno"), - validator: (value) { - if (value!.trim().isEmpty) { - return "Toto pole je povinné!"; - } - return null; - }, - onChanged: (value) { - jmeno = value; - }, - ), - const SizedBox(height: 10), - TextFormField( - decoration: Vzhled.inputDecoration("Username"), - validator: (value) { - if (value!.trim().isEmpty) { - return "Toto pole je povinné!"; - } - return null; - }, - onChanged: (value) { - username = value; - }, - ), - const SizedBox(height: 10), - TextFormField( - decoration: Vzhled.inputDecoration("Email"), - validator: (value) { - if (value!.trim().isEmpty) { - return "Toto pole je povinné!"; - } else if (!RegExp(r'[\w\.]+@[a-z0-9]+\.[a-z]{1,3}') - .hasMatch(value)) { - return "Neplatný e-mail!"; - } - return null; - }, - onChanged: (value) { - email = value; - }, - ), - const SizedBox(height: 10), - DropdownButton( - value: isAdmin, - items: ["Admin", "Uživatel"] - .map((e) => DropdownMenuItem( - value: e == "Admin" ? true : false, - child: Text(e))) - .toList(), - onChanged: (value) { - setState(() { - isAdmin = value!; - }); - }, - ), - const SizedBox(height: 20), - OutlinedButton( - style: Vzhled.orangeCudlik, - onPressed: () async { - if (key.currentState!.validate()) { - // kontrola ci niekto nevyuziva username - var usernameRef = await FirebaseFirestore.instance - .collection("users") - .where("username", isEqualTo: username) - .get(); - - if (usernameRef.docs.isNotEmpty) { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text( - "Toto username patří jinému uživateli, prosím napište nové username."), - ), - ); - - return; - } - - // kontrola ci niekto nevyuziva email - var emailRef = await FirebaseFirestore.instance - .collection("users") - .where("email", isEqualTo: email) - .get(); - - if (emailRef.docs.isNotEmpty) { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text( - "Tento email patří jinému uživateli, prosím jiný email."), - ), - ); - - return; - } - - FirebaseFirestore.instance.collection("users").add({ - "email": email, - "name": jmeno, - "isAdmin": isAdmin, - "favourite": "Dart", - "username": username - }).then((value) { - Navigator.of(context, rootNavigator: true) - .pop("dialog"); - - showDialog( - context: context, - builder: (_) => const AlertDialog( - scrollable: true, - content: Text("Uživatel vytvořen")), - ); - }); - } - }, - child: const Text("Přidat"), - ), - const SizedBox(height: 20), - const Text( - "Uživatel si při prvním přihlášení vytvoří heslo sám", - textAlign: TextAlign.center, - ), - ], - ), - ), - ); - }, - ), - ), - ); - } - - showUpravitUsername(id, oldUsername) async { - GlobalKey key = GlobalKey(); - String newUsername = oldUsername; - - showDialog( - context: context, - builder: (_) => AlertDialog( - title: const Text("Username", style: Vzhled.velkyText), - scrollable: true, - content: SizedBox( - width: 50.w, - child: Form( - key: key, - child: Column( - children: [ - TextFormField( - initialValue: oldUsername, - decoration: Vzhled.inputDecoration("Nové username"), - validator: (value) { - if (value!.trim().isEmpty) { - return "Toto pole je povinné!"; - } - return null; - }, - onChanged: (value) { - newUsername = value; - }, - ), - const SizedBox(height: 15), - OutlinedButton( - style: Vzhled.orangeCudlik, - onPressed: () async { - if (key.currentState!.validate()) { - // kontrola ci niekto nevyuziva username - var usernameRef = await FirebaseFirestore.instance - .collection("users") - .where("username", isEqualTo: newUsername) - .get(); - - if (newUsername.isEmpty) { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text("Toto pole je povinné!"), - ), - ); - - return; - } - - if (usernameRef.docs.isNotEmpty && - oldUsername != newUsername) { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: (c) => const AlertDialog( - title: Text("Chyba"), - content: Text( - "Toto username patří jinému uživateli, prosím napište nové username."), - ), - ); - - return; - } - - FirebaseFirestore.instance - .collection("users") - .doc(id) - .update({"username": newUsername}).then((value) => - Navigator.of(context, rootNavigator: true) - .pop("dialog")); - } - }, - child: const Text("Uložit")) - ], - ), - ), - ), - ), - ); - } - - showPrava(id, isAdmin) async { - showDialog( - context: context, - builder: (_) => AlertDialog( - title: const Text("Práva uživatele", style: Vzhled.velkyText), - scrollable: true, - content: SizedBox( - width: 20.w, - child: DropdownButton( - value: isAdmin, - items: ["Admin", "Uživatel"] - .map((e) => DropdownMenuItem( - value: e == "Admin" ? true : false, child: Text(e))) - .toList(), - onChanged: (value) { - FirebaseFirestore.instance - .collection("users") - .doc(id) - .update({"isAdmin": value}); - - Navigator.of(context, rootNavigator: true).pop("dialog"); - }, - )), - ), - ); - } - - showOdstranit(id) async { - showReallyDelete(context, () { - FirebaseFirestore.instance.collection("users").doc(id).delete(); - Navigator.of(context, rootNavigator: true).pop("dialog"); - }, doNavigatorPop: false); - } -} diff --git a/lib/utils/csv.dart b/lib/utils/csv.dart deleted file mode 100644 index b905a4d..0000000 --- a/lib/utils/csv.dart +++ /dev/null @@ -1,152 +0,0 @@ -import 'dart:convert'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:csv/csv.dart'; -import 'package:denikprogramatora/utils/datum_cas.dart'; -import 'package:denikprogramatora/utils/loading_widget.dart'; -import 'package:file_picker/file_picker.dart'; -import 'package:firebase_auth/firebase_auth.dart'; - -final csvHeader = "id,date,time_spent,language,rating,description".split(","); - -Future importCsv(String name) async { - FilePickerResult? result = await FilePicker.platform.pickFiles( - dialogTitle: "Vyberte CSV soubor s databází", - type: FileType.custom, - allowedExtensions: ['csv']); - if (result == null) return -1; - var content = const CsvToListConverter(eol: "\n").convert( - String.fromCharCodes( - result.files.first.bytes!)); // načíst a rozdělit na řádky - - // Zkontrolovat počet sloupců - if (content.first.length != csvHeader.length) { - throw "CSV soubor není v platném formátu: neplatný počet sloupců"; - } - - Map> csv = {}; - var nazvySloupcu = []; - for (var radek in content) { - if (nazvySloupcu.isEmpty) { - // získat názvy sloupců - nazvySloupcu = radek; - if (nazvySloupcu.any((element) => !csvHeader.contains(element))) { - throw "CSV soubor není v platném formátu: neznámý název sloupce"; - } - for (var nazevSloupce in nazvySloupcu) { - csv[nazevSloupce] = []; - } - continue; - } - if (radek.length != nazvySloupcu.length) continue; - - // zkontrolovat, že máme všechny potřebné údaje v řádku - var j = 0; - var neplatny = false; - for (var sloupec in radek) { - if ((nazvySloupcu[j] != "description") && sloupec == "") { - neplatny = true; - break; - } - j++; - } - if (neplatny) continue; - - // přiřadit hodnotu sloupce do mapy - var i = 0; - for (var sloupec in radek) { - csv[nazvySloupcu[i]]!.add(sloupec); - i++; - } - } - - var userDoc = await FirebaseFirestore.instance - .collection("users/${FirebaseAuth.instance.currentUser!.uid}/records") - .get(); - var p = 0; - var pouzitaId = []; - for (var i = 0; i < csv[nazvySloupcu[0]]!.length; i++) { - var id = csv[nazvySloupcu[nazvySloupcu.indexOf("id")]]![i]; - if (pouzitaId.contains(id)) continue; - pouzitaId.add(id); - if (userDoc.docs.any((element) => element.id == id)) { - continue; - } // přeskočit dokumenty se stejným ID - - var date = csv[nazvySloupcu[nazvySloupcu.indexOf("date")]]![i].split("-"); - - var timeToSec = textToSec( - csv[nazvySloupcu[nazvySloupcu.indexOf("time_spent")]]![i] as String); - if (timeToSec == null) continue; - var timeSpent = Duration(seconds: timeToSec); - - var lang = csv[nazvySloupcu[nazvySloupcu.indexOf("language")]]![i]; - Map jazyk = {}; - if (jazyky.any((element) => element["jazyk"] == lang)) { - jazyk = jazyky.where((element) => element["jazyk"] == lang).toList()[0]; - } else { - jazyk = {"jazyk": lang, "barva": 0xffffffff}; - } - - var rating = csv[nazvySloupcu[nazvySloupcu.indexOf("rating")]]![i]; - if (rating > 5 || rating < 0) rating = 0; - - var desc = csv[nazvySloupcu[nazvySloupcu.indexOf("description")]]![i]; - DateTime? d; - try { - d = DateTime.parse( - "${date[2]}-${int.parse(date[1]) < 10 ? '0${date[1]}' : date[1]}-${int.parse(date[0]) < 10 ? "0${date[0]}" : date[0]}"); - } catch (e) { - continue; - } - - await FirebaseFirestore.instance - .collection("users/${FirebaseAuth.instance.currentUser!.uid}/records") - .doc(id) - .set({ - "date": d, - "time_spent": timeSpent.durationText, - "time_spentRaw": timeSpent.inSeconds, - "programming_language": jazyk, - "rating": rating, - "descriptionRaw": desc, - "description": null, - "programmer": FirebaseAuth.instance.currentUser!.uid, - "categories": [] - }); - p++; - } - return p; -} - -Future> exportCsv() async { - List> csv = [csvHeader]; - var records = await FirebaseFirestore.instance - .collection("users/${FirebaseAuth.instance.currentUser!.uid}/records") - .get(); - for (var rec in records.docs) { - var data = rec.data(); - csv.add([ - rec.id, - (data['date'] as Timestamp).toDate().rawDateString, - Duration(seconds: data['time_spentRaw']).durationText, - data['programming_language']['jazyk'], - data['rating'], - data['descriptionRaw'] - ]); - } - return utf8.encode(const ListToCsvConverter(eol: "\n").convert(csv)); -} - -/// Převede `40 hodin 50 minut` na sekundy -int? textToSec(String vstup) { - var match = - RegExp(r'(\d+) hodin(?: |y |a )(\d+) minut(?:$|a$|y$)').firstMatch(vstup); - if (match == null) return null; - print(match.group(1)); - print(match.group(2)); - var h = int.tryParse(match.group(1)!); - var m = int.tryParse(match.group(2)!); - if (h == null || m == null) return null; - return h * 3600 + m * 60; -} diff --git a/lib/utils/datum.dart b/lib/utils/datum.dart new file mode 100644 index 0000000..582635e --- /dev/null +++ b/lib/utils/datum.dart @@ -0,0 +1,5 @@ +extension DateString on DateTime { + String get dateString => "$day. $month. $year"; + String get dateTimeString => + "$day. $month. $year $hour:${minute < 10 ? "0$minute" : minute}"; +} diff --git a/lib/utils/datum_cas.dart b/lib/utils/datum_cas.dart deleted file mode 100644 index 5347277..0000000 --- a/lib/utils/datum_cas.dart +++ /dev/null @@ -1,11 +0,0 @@ -extension DateString on DateTime { - String get dateString => "$day. $month. $year"; - String get dateTimeString => - "$day. $month. $year $hour:${minute < 10 ? "0$minute" : minute}"; - String get rawDateString => "$day-$month-$year"; -} - -extension TextDuration on Duration { - String get durationText => - "$inHours hodin${(inHours < 5 && inHours > 1) ? "y" : (inHours == 1) ? "a" : ""} ${inMinutes - inHours * 60} minut${(inMinutes - inHours * 60) < 5 && (inMinutes - inHours * 60) > 1 ? "y" : (inMinutes - inHours * 60) == 1 ? "a" : ""}"; -} diff --git a/lib/utils/loading_widget.dart b/lib/utils/loading_widget.dart index 58cf5b9..865d7f9 100644 --- a/lib/utils/loading_widget.dart +++ b/lib/utils/loading_widget.dart @@ -18,7 +18,7 @@ final jazyky = >[ {"jazyk": "C#", "barva": 0xff8200f3}, {"jazyk": "JavaScript", "barva": 0xfffdd700}, {"jazyk": "Python", "barva": 0xff0080ee}, - {"jazyk": "PHP", "barva": 0xff00abff}, + {"jazyk": "PHP🤢", "barva": 0xff00abff}, {"jazyk": "C++", "barva": 0xff1626ff}, {"jazyk": "Kotlin", "barva": 0xffe34b7c}, {"jazyk": "Java", "barva": 0xfff58219}, diff --git a/lib/utils/new_record_dialog.dart b/lib/utils/new_record_dialog.dart index 779efee..01a5dff 100644 --- a/lib/utils/new_record_dialog.dart +++ b/lib/utils/new_record_dialog.dart @@ -1,12 +1,12 @@ import 'package:denikprogramatora/okna/app.dart'; -import 'package:denikprogramatora/utils/datum_cas.dart'; +import 'package:denikprogramatora/utils/datum.dart'; import 'package:denikprogramatora/utils/devicecontainer.dart'; import 'package:denikprogramatora/utils/dokument.dart'; import 'package:denikprogramatora/utils/loading_widget.dart'; import 'package:denikprogramatora/utils/programmer.dart'; import 'package:denikprogramatora/utils/really_delete.dart'; import 'package:denikprogramatora/utils/vzhled.dart'; -import 'package:duration_picker/duration_picker.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:fleather/fleather.dart'; import 'package:flutter/material.dart'; import 'package:responsive_sizer/responsive_sizer.dart'; @@ -15,33 +15,37 @@ import 'package:uuid/uuid.dart'; import '../utils/my_category.dart'; Future showCreateItemDialog(context, - {DateTime? originDate, - Duration? timeSpent, + {DateTime? from, + DateTime? to, String? j, int hvezdicky = 0, String? p, List? k, String? originalId, ParchmentDocument? doc}) async { - DateTime date = originDate ?? + DateTime fromDate = from ?? DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, DateTime.now().hour - 1); + DateTime toDate = to ?? + DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, + DateTime.now().hour); // nastavení jazyka na oblíbený jazyk String jazyk = "C#"; if (j == null) { await ref.get().then((value) { - jazyk = value["favourite"] ?? "Dart"; + jazyk = value["favourite"]; }); } else { jazyk = j; } - timeSpent = timeSpent ?? const Duration(hours: 0, minutes: 0); - int review = hvezdicky; - Programmer programmer = Programmer(name, "pK8iCAtMFiUUhK9FJd6HpWdwA3I3"); + Programmer programmer = p == null + ? Programmer(name, userUid) + : await Programmer.ziskatProgramatora( + FirebaseAuth.instance.currentUser!, p); List categories = k ?? []; @@ -79,25 +83,39 @@ Future showCreateItemDialog(context, const SizedBox(height: 15), Row( children: [ - Text( - "Datum ${date.day}. ${date.month}. ${date.year}"), + Text("Od ${toDate.dateTimeString}"), const SizedBox(width: 15), TextButton( onPressed: () { showDatePicker( context: context, - initialDate: date, + initialDate: fromDate, firstDate: DateTime(DateTime.now().year - 5), lastDate: DateTime(DateTime.now().year + 5)) .then((value) { - setState(() { - date = DateTime( - value!.year, - value.month, - value.day, - ); + showTimePicker( + context: context, + initialTime: + TimeOfDay.fromDateTime(fromDate)) + .then((time) { + if (value!.day == toDate.day && + value.month == toDate.month && + value.year == toDate.year && + (time!.hour > toDate.hour || + (time.hour <= toDate.hour && + time.minute > toDate.minute))) { + return; + } + setState(() { + fromDate = DateTime( + value.year, + value.month, + value.day, + time!.hour, + time.minute); + }); }); }); }, @@ -108,45 +126,89 @@ Future showCreateItemDialog(context, ) ], ), - const SizedBox(height: 30), + const SizedBox(height: 5), Row( children: [ - Text( - "Strávený čas ${timeSpent!.inHours} hodin ${timeSpent!.inMinutes - timeSpent!.inHours * 60} minut"), + Text("Do ${toDate.dateTimeString}"), const SizedBox(width: 15), TextButton( - onPressed: () async { - await showDurationPicker( + onPressed: () { + showDatePicker( context: context, - baseUnit: BaseUnit.hour, - initialTime: - timeSpent ?? const Duration()) - .then((hours) { - showDurationPicker( + initialDate: toDate, + firstDate: + DateTime(DateTime.now().year - 5), + lastDate: + DateTime(DateTime.now().year + 5)) + .then((value) { + showTimePicker( context: context, - baseUnit: BaseUnit.minute, - initialTime: Duration( - minutes: (timeSpent ?? - const Duration()) - .inMinutes - - (timeSpent ?? - const Duration()) - .inHours * - 60)) - .then((minutes) => setState(() { - timeSpent = Duration( - hours: hours!.inHours, - minutes: minutes!.inMinutes); - })); + initialTime: + TimeOfDay.fromDateTime(toDate)) + .then((time) { + if (value!.day == fromDate.day && + value.month == fromDate.month && + value.year == fromDate.year && + (time!.hour < fromDate.hour || + (time.hour >= fromDate.hour && + time.minute < + fromDate.minute))) { + return; + } + setState(() { + toDate = DateTime(value.year, value.month, + value.day, time!.hour, time.minute); + }); + }); }); }, child: const Text( - "Změnit", + ("Změnit"), style: Vzhled.textBtn, ), ) ], ), + const SizedBox(height: 30), + const Align( + alignment: Alignment.centerLeft, + child: Text( + "Strávený čas", + style: Vzhled.nadpis, + ), + ), + const SizedBox(height: 15), + Align( + alignment: Alignment.centerLeft, + child: Text( + "${toDate.difference(fromDate).inHours} ${toDate.difference(fromDate).inHours == 1 ? "hodina" : toDate.difference(fromDate).inHours > 1 && toDate.difference(fromDate).inHours < 5 ? "hodiny" : "hodin"}${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60 == 0) ? "" : " a ${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60)} ${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) == 1 ? "minuta" : (toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) > 1 && (toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) < 5 ? "minuty" : "minut"}"}"), + ), + const SizedBox(height: 30), + const Align( + alignment: Alignment.centerLeft, + child: Text( + "Programátor", + style: Vzhled.nadpis, + ), + ), + const SizedBox(height: 15), + Align( + alignment: Alignment.centerLeft, + child: TextButton( + onPressed: () async { + await showProgrammersDialog(context, doc: doc) + .then((value) { + setState(() { + programmer = value; + }); + }); + }, + child: Text( + programmer.name, + style: Vzhled.textBtn, + ), + ), + ), ], ), ), @@ -288,33 +350,35 @@ Future showCreateItemDialog(context, onPressed: () { if (originalId == null) { ref.collection("records").add({ - "date": DateTime(date.year, date.month, date.day), - "time_spent": timeSpent!.durationText, - "time_spentRaw": timeSpent!.inSeconds, + "fromDate": fromDate, + "toDate": toDate, + "codingTime": + "${toDate.difference(fromDate).inHours} ${toDate.difference(fromDate).inHours == 1 ? "hodina" : toDate.difference(fromDate).inHours > 1 && toDate.difference(fromDate).inHours < 5 ? "hodiny" : "hodin"}${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60 == 0) ? "" : " a ${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60)} ${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) == 1 ? "minuta" : (toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) > 1 && (toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) < 5 ? "minuty" : "minut"}"}", "programmer": programmer.id, - "programming_language": jazyky + "programmerName": programmer.name, + "language": jazyky .where((element) => element["jazyk"] == jazyk) .toList()[0], - "rating": review, + "review": review, "categories": categories.map((e) => e.id).toList(), "description": controller.document.toActualJson(), - "descriptionRaw": controller.document.toPlainText() }).then((value) => Navigator.of(context, rootNavigator: true) .pop("dialog")); return; } ref.collection("records").doc(originalId).update({ - "date": DateTime(date.year, date.month, date.day), - "time_spentRaw": timeSpent!.inSeconds, - "time_spent": timeSpent!.durationText, + "fromDate": fromDate, + "toDate": toDate, + "codingTime": + "${toDate.difference(fromDate).inHours} ${toDate.difference(fromDate).inHours == 1 ? "hodina" : toDate.difference(fromDate).inHours > 1 && toDate.difference(fromDate).inHours < 5 ? "hodiny" : "hodin"}${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60 == 0) ? "" : " a ${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60)} ${(toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) == 1 ? "minuta" : (toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) > 1 && (toDate.difference(fromDate).inMinutes - toDate.difference(fromDate).inHours * 60) < 5 ? "minuty" : "minut"}"}", "programmer": programmer.id, - "programming_language": jazyky + "programmerName": programmer.name, + "language": jazyky .where((element) => element["jazyk"] == jazyk) .toList()[0], - "rating": review, + "review": review, "categories": categories.map((e) => e.id).toList(), - "descriptionRaw": controller.document.toPlainText(), "description": controller.document.toActualJson(), }).then((value) => Navigator.of(context, rootNavigator: true).pop("dialog")); @@ -334,6 +398,277 @@ Future showCreateItemDialog(context, ); } +Future showProgrammersDialog(context, + {ParchmentDocument? doc, bool jenMenit = false}) async { + bool showAddProgrammer = false; + bool editing = false; + GlobalKey key = GlobalKey(); + TextEditingController nameCon = TextEditingController(); + late String editId; + + Programmer programmer = Programmer(name, userUid); + + await showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text("Programátoři", style: Vzhled.velkyText), + scrollable: true, + content: SizedBox( + width: 50.w, + child: StatefulBuilder( + builder: (context, setState) { + return showAddProgrammer + ? Form( + key: key, + child: Column( + children: [ + Row( + children: [ + Expanded( + child: TextFormField( + controller: nameCon, + decoration: Vzhled.inputDecoration("Jméno"), + validator: (value) { + if (value!.trim().isEmpty) { + return "Toto pole je povinné!"; + } + return null; + }, + ), + ), + const SizedBox(width: 5), + TextButton( + onPressed: () { + if (key.currentState!.validate()) { + if (editing) { + ref + .collection("programmers") + .doc(editId) + .update({"name": nameCon.text}); + } else { + var uuid = const Uuid(); + String id = uuid.v1(); + + ref + .collection("programmers") + .doc(id) + .set({"name": nameCon.text, "id": id}); + } + nameCon.text = ""; + + setState(() { + editing = false; + showAddProgrammer = false; + }); + } + }, + child: Text( + editing ? "Uložit" : "Přidat", + style: Vzhled.textBtn, + ), + ), + ], + ), + const SizedBox(height: 5), + TextButton( + onPressed: () { + setState(() { + showAddProgrammer = false; + }); + }, + child: const Text( + "Zpátky", + style: Vzhled.textBtn, + ), + ), + ], + ), + ) + : Column( + children: [ + Material( + color: Vzhled.dialogColor, + child: InkWell( + splashColor: (jenMenit) ? Colors.transparent : null, + onTap: () { + if (jenMenit) return; + programmer = Programmer(name, userUid); + Navigator.of(context, rootNavigator: true) + .pop("dialog"); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(name), + if (!jenMenit) + TextButton( + onPressed: () { + programmer = Programmer(name, userUid); + Navigator.of(context, rootNavigator: true) + .pop("dialog"); + }, + child: const Text( + "Vybrat", + style: Vzhled.textBtn, + ), + ), + ], + ), + ), + ), + ), + StreamBuilder( + stream: ref.collection("programmers").snapshots(), + builder: (context, snapshot) { + if (snapshot.hasData) { + var docs = snapshot.data!.docs; + + return Column( + children: List.generate(docs.length, (index) { + var data = docs[index].data(); + return Material( + color: Vzhled.dialogColor, + child: InkWell( + splashColor: (jenMenit) + ? Colors.transparent + : null, + onTap: () { + if (jenMenit) return; + programmer = Programmer( + data["name"], data["id"]); + Navigator.of(context, + rootNavigator: true) + .pop("dialog"); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text(data["name"]), + Row( + children: [ + if (!jenMenit) + TextButton( + onPressed: () { + programmer = Programmer( + data["name"], + data["id"]); + Navigator.of(context, + rootNavigator: + true) + .pop("dialog"); + }, + child: const Text( + "Vybrat", + style: Vzhled.textBtn, + ), + ), + IconButton( + onPressed: () { + editId = data["id"]; + + setState(() { + showAddProgrammer = true; + editing = true; + nameCon = + TextEditingController( + text: + data["name"]); + }); + }, + icon: const Icon(Icons.edit, + color: Vzhled.textColor), + ), + IconButton( + onPressed: () { + showReallyDelete(context, + () async { + Navigator.of(context, + rootNavigator: + true) + .pop("dialog"); + Navigator.of(context, + rootNavigator: + true) + .pop("dialog"); + if (doc != null) { + Navigator.of(context, + rootNavigator: + true) + .pop("dialog"); + } + + // deleting all records + await ref + .collection("records") + .where("programmer", + isEqualTo: + data["id"]) + .get() + .then((value) { + for (var snap + in value.docs) { + ref + .collection( + "records") + .doc(snap.id) + .delete(); + } + }); + + // deleting + await ref + .collection( + "programmers") + .doc(data["id"]) + .delete(); + }, + doNavigatorPop: false, + text: + "Odstranit programátora a všechny jeho záznamy?"); + }, + icon: const Icon(Icons.delete, + color: Vzhled.textColor), + ), + ], + ) + ], + ), + ), + ), + ); + }), + ); + } + return const LoadingWidget(); + }), + const SizedBox(height: 5), + TextButton( + onPressed: () { + setState(() { + showAddProgrammer = true; + }); + }, + child: const Text( + "Přidat nového programátora", + style: Vzhled.textBtn, + ), + ), + ], + ); + }, + ), + ), + ), + ); + + return programmer; +} + Future> showCategoriesDialog( context, List categories, {bool jenMenit = false}) async { diff --git a/lib/utils/razeni.dart b/lib/utils/razeni.dart index 418ba32..3be7eae 100644 --- a/lib/utils/razeni.dart +++ b/lib/utils/razeni.dart @@ -4,29 +4,29 @@ var razeni = [ // VZESTUPNĚ ČAS (QueryDocumentSnapshot> a, QueryDocumentSnapshot> b) => - ((a.data()["date"] as Timestamp).toDate().hour == - (b.data()["date"] as Timestamp).toDate().hour) - ? (a.data()["date"] as Timestamp) + ((a.data()["fromDate"] as Timestamp).toDate().hour == + (b.data()["fromDate"] as Timestamp).toDate().hour) + ? (a.data()["fromDate"] as Timestamp) .toDate() .minute - .compareTo((b.data()["date"] as Timestamp).toDate().minute) - : (a.data()["date"] as Timestamp) + .compareTo((b.data()["fromDate"] as Timestamp).toDate().minute) + : (a.data()["fromDate"] as Timestamp) .toDate() .hour - .compareTo((b.data()["date"] as Timestamp).toDate().hour), + .compareTo((b.data()["fromDate"] as Timestamp).toDate().hour), // SESTUPNĚ ČAS (QueryDocumentSnapshot> a, QueryDocumentSnapshot> b) => - ((b.data()["date"] as Timestamp).toDate().hour == - (a.data()["date"] as Timestamp).toDate().hour) - ? (b.data()["date"] as Timestamp) + ((b.data()["fromDate"] as Timestamp).toDate().hour == + (a.data()["fromDate"] as Timestamp).toDate().hour) + ? (b.data()["fromDate"] as Timestamp) .toDate() .minute - .compareTo((a.data()["date"] as Timestamp).toDate().minute) - : (b.data()["date"] as Timestamp) + .compareTo((a.data()["fromDate"] as Timestamp).toDate().minute) + : (b.data()["fromDate"] as Timestamp) .toDate() .hour - .compareTo((a.data()["date"] as Timestamp).toDate().hour), + .compareTo((a.data()["fromDate"] as Timestamp).toDate().hour), // VZESTUPNĚ HODNOCENÍ (QueryDocumentSnapshot> a, QueryDocumentSnapshot> b) => diff --git a/lib/utils/show_info_dialog.dart b/lib/utils/show_info_dialog.dart index efbe073..d7b3290 100644 --- a/lib/utils/show_info_dialog.dart +++ b/lib/utils/show_info_dialog.dart @@ -1,6 +1,6 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:denikprogramatora/okna/app.dart'; -import 'package:denikprogramatora/utils/datum_cas.dart'; +import 'package:denikprogramatora/utils/datum.dart'; import 'package:denikprogramatora/utils/devicecontainer.dart'; import 'package:denikprogramatora/utils/my_category.dart'; import 'package:denikprogramatora/utils/new_record_dialog.dart'; @@ -12,11 +12,12 @@ import 'package:flutter/material.dart'; import 'package:responsive_sizer/responsive_sizer.dart'; void showInfoDialog( - context, Map data, String originalId, String jmeno) async { - var date = (data["date"] as Timestamp).toDate().toLocal(); + context, Map data, String originalId) async { + var denOd = (data["fromDate"] as Timestamp).toDate().toLocal(); + var denDo = (data["toDate"] as Timestamp).toDate().toLocal(); List categories = []; - if (((data["categories"] ?? []) as List).isNotEmpty) { + if ((data["categories"] as List).isNotEmpty) { for (var category in data["categories"]) { await ref.collection("categories").doc(category).get().then((value) { var data = value.data(); @@ -29,9 +30,7 @@ void showInfoDialog( showDialog( context: context, builder: (_) { - var document = (data["description"] != null && data["description"] != "") - ? ParchmentDocument.fromJson(data["description"]) - : (ParchmentDocument()..insert(0, data["descriptionRaw"])); + var document = ParchmentDocument.fromJson(data["description"]); var controller = FleatherController(document); return AlertDialog( @@ -52,13 +51,13 @@ void showInfoDialog( style: Vzhled.purpleCudlik, onPressed: () { showCreateItemDialog(context, - originDate: date, - timeSpent: Duration(seconds: data["time_spentRaw"]), + from: denOd, + to: denDo, k: categories, p: data["programmer"], - hvezdicky: data["rating"], + hvezdicky: data["review"], originalId: originalId, - j: data["programming_language"]["jazyk"], + j: data["language"]["jazyk"], doc: document) .then((_) => Navigator.of(context).pop()); }, @@ -70,7 +69,7 @@ void showInfoDialog( ), ], title: Text( - "Záznam ze dne ${date.dateString}", + "Záznam ze dne ${denOd.dateString}", style: Vzhled.dialogNadpis, ), scrollable: true, @@ -98,7 +97,9 @@ void showInfoDialog( style: Vzhled.nadpis, ), Text( - "${date.dateString} (${data["time_spent"]})", + (Device.screenType == ScreenType.mobile) + ? "od ${denOd.dateTimeString}\ndo ${denDo.dateTimeString} (${data["codingTime"]})" + : "od ${denOd.dateTimeString} do ${denDo.dateTimeString} (${data["codingTime"]})", ) ], ), @@ -112,10 +113,9 @@ void showInfoDialog( style: Vzhled.nadpis, ), Text( - data["programming_language"]["jazyk"], + data["language"]["jazyk"], style: TextStyle( - color: Color( - data["programming_language"]["barva"])), + color: Color(data["language"]["barva"])), ) ], ), @@ -138,9 +138,7 @@ void showInfoDialog( style: Vzhled.nadpis, ), Text( - FirebaseAuth - .instance.currentUser!.displayName ?? - jmeno, + data["programmerName"], ) ], ), @@ -158,7 +156,7 @@ void showInfoDialog( 5, (index) { return Icon(Icons.star, - color: (index + 1) <= data["rating"] + color: (index + 1) <= data["review"] ? Colors.yellow : Colors.grey); }, diff --git a/pubspec.lock b/pubspec.lock index 2b69643..740401c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "64fcb0dbca4386356386c085142fa6e79c00a3326ceaa778a2d25f5d9ba61441" + sha256: "6215ac7d00ed98300b72f45ed2b38c2ca841f9f4e6965fab33cbd591e45e4473" url: "https://pub.dev" source: hosted - version: "1.0.16" + version: "1.0.13" async: dependency: transitive description: @@ -45,26 +45,26 @@ packages: dependency: "direct main" description: name: cloud_firestore - sha256: "65f148d9f5b4f389320abb45847120cf5e46094c1a8cbc64934ffc1e29688596" + sha256: "9e775f9df26a165444bd5240f70bfee6f11b35c5e913e93ed4b06bf50b231325" url: "https://pub.dev" source: hosted - version: "4.4.3" + version: "4.3.2" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface - sha256: "43ccae09f7e0c82752e69c251c6dc5efcdff4ddcfc09564175a28657bbd74188" + sha256: ab35c068896ff769ce7e8de8198228d512e7f056fc8f26b2ff53ea3f97c8545f url: "https://pub.dev" source: hosted - version: "5.11.3" + version: "5.10.2" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web - sha256: e054c007217e28e07179bbae0564c2a4f6338a60bddb0c139e4834e953f4b95c + sha256: b7b52c2ad50d1105f2e0585a34288da415cf9d1037470985c7c57cce7b06d95f url: "https://pub.dev" source: hosted - version: "3.3.3" + version: "3.2.2" collection: dependency: transitive description: @@ -89,14 +89,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.17.2" - csv: + cupertino_icons: dependency: "direct main" description: - name: csv - sha256: "18aef53ab72181a0b5384562d18c8cbd57e941e24cb8e54eb41409d3d8abdc6d" + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "1.0.5" diff_match_patch: dependency: transitive description: @@ -105,14 +105,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.1" - duration_picker: - dependency: "direct main" - description: - name: duration_picker - sha256: "052b34dac04c29f3849bb3817a26c5aebe9e5f0697c3a374be87db2b84d75753" - url: "https://pub.dev" - source: hosted - version: "1.1.1" fake_async: dependency: transitive description: @@ -121,54 +113,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" - ffi: - dependency: transitive - description: - name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 - url: "https://pub.dev" - source: hosted - version: "2.0.1" - file_picker: - dependency: "direct main" - description: - name: file_picker - sha256: d090ae03df98b0247b82e5928f44d1b959867049d18d73635e2e0bc3f49542b9 - url: "https://pub.dev" - source: hosted - version: "5.2.5" firebase_auth: dependency: "direct main" description: name: firebase_auth - sha256: "9907d80446466e638dad31c195150b305dffd145dc57610fcd12c72289432143" + sha256: "843e307e9b7faa026dd9970e584b5d53265fb5a0c4323883fecdce89ec05d56a" url: "https://pub.dev" source: hosted - version: "4.2.9" + version: "4.2.6" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface - sha256: c645fec50b0391aa878288f58fa4fe9762c271380c457aedf5c7c9b718604f68 + sha256: "8702baa08ad5aa6daa023082d612ca168bf3f7de81e3d56e1df18321f76d675f" url: "https://pub.dev" source: hosted - version: "6.11.11" + version: "6.11.8" firebase_auth_web: dependency: transitive description: name: firebase_auth_web - sha256: "2dcf2a36852b9091741b4a4047a02e1f2c43a62c6cacec7df573a793a6543e6d" + sha256: "0c01b9c772ee730df03ac92102e538873558f908d6e42602f6ff9c61dead8d58" url: "https://pub.dev" source: hosted - version: "5.2.8" + version: "5.2.5" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: fe30ac230f12f8836bb97e6e09197340d3c584526825b1746ea362a82e1e43f7 + sha256: be13e431c0c950f0fc66bdb67b41b8059121d7e7d8bbbc21fb59164892d561f8 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.5.0" firebase_core_platform_interface: dependency: transitive description: @@ -181,10 +157,10 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: "291fbcace608aca6c860652e1358ef89752be8cc3ef227f8bbcd1e62775b833a" + sha256: "4b3a41410f3313bb95fd560aa5eb761b6ad65c185de772c72231e8b4aeed6d18" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.1.1" fleather: dependency: "direct main" description: @@ -211,14 +187,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2" - url: "https://pub.dev" - source: hosted - version: "2.0.8" flutter_test: dependency: "direct dev" description: flutter @@ -321,10 +289,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.3" quill_delta: dependency: transitive description: @@ -414,66 +382,66 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: e8f2efc804810c0f2f5b485f49e7942179f56eabcfe81dce3387fec4bb55876b url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.1.9" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "1f4d9ebe86f333c15d318f81dcdc08b01d45da44af74552608455ebdc08d9732" + sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" url: "https://pub.dev" source: hosted - version: "6.0.24" + version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: c9cd648d2f7ab56968e049d4e9116f96a85517f1dd806b96a86ea1018a3a82e5 + sha256: "0a5af0aefdd8cf820dd739886efb1637f1f24489900204f50984634c07a54815" url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.0" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682 + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "2dddb3291a57b074dade66b5e07e64401dd2487caefd4e9e2f467138d8c7eb06" + sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b" + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b" + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.3" uuid: dependency: "direct main" description: @@ -490,14 +458,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - win32: - dependency: transitive - description: - name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 - url: "https://pub.dev" - source: hosted - version: "3.1.3" sdks: dart: ">=2.18.5 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index af92597..6210485 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,6 +37,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 firebase_core: ^2.4.0 responsive_sizer: ^3.1.1 firebase_auth: ^4.2.1 @@ -45,9 +46,6 @@ dependencies: multi_select_flutter: ^4.1.3 fleather: ^1.4.0 url_launcher: ^6.1.8 - file_picker: ^5.2.5 - csv: ^5.0.1 - duration_picker: ^1.1.1 dev_dependencies: flutter_test: diff --git a/web/manifest.json b/web/manifest.json index 339b4f1..e4b342c 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -1,6 +1,6 @@ { - "name": "Kodelog", - "short_name": "Kodelog", + "name": "denikprogramatora", + "short_name": "denikprogramatora", "start_url": ".", "display": "standalone", "background_color": "#0175C2",