From 42a13b6320d2933336c60a41cfd667cee240bd0e Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Sun, 6 Oct 2024 15:16:31 +0700 Subject: [PATCH 01/41] feat: setup dockerized vue widget dev server --- ops/deployment/docker-compose.yml | 20 +- protected/views/adminProject/_form.php | 25 +- up.sh | 3 + vite/.dockerignore | 6 + vite/.gitignore | 24 + vite/Dockerfile | 9 + vite/README.md | 30 + vite/package-lock.json | 1409 ++++++++++++++++++++++++ vite/package.json | 20 + vite/src/App.vue | 21 + vite/src/main.ts | 4 + vite/src/vite-env.d.ts | 1 + vite/tsconfig.app.json | 24 + vite/tsconfig.json | 7 + vite/tsconfig.node.json | 22 + vite/vite.config.ts | 13 + 16 files changed, 1629 insertions(+), 9 deletions(-) create mode 100644 vite/.dockerignore create mode 100644 vite/.gitignore create mode 100644 vite/Dockerfile create mode 100644 vite/README.md create mode 100644 vite/package-lock.json create mode 100644 vite/package.json create mode 100644 vite/src/App.vue create mode 100644 vite/src/main.ts create mode 100644 vite/src/vite-env.d.ts create mode 100644 vite/tsconfig.app.json create mode 100644 vite/tsconfig.json create mode 100644 vite/tsconfig.node.json create mode 100644 vite/vite.config.ts diff --git a/ops/deployment/docker-compose.yml b/ops/deployment/docker-compose.yml index 83ea8d4214..5f29133589 100644 --- a/ops/deployment/docker-compose.yml +++ b/ops/deployment/docker-compose.yml @@ -705,6 +705,23 @@ services: - le_config:/ca command: --domains '*.gigasciencejournal.com' + # Vite dev server for project image location + vite-project-image-location-dev: + build: + context: ${APPLICATION}/vite + args: + - NODE_VERSION=$NODE_VERSION + volumes: + # share host source code with the container to allow hot-reloading + - ${APPLICATION}/vite:/app:delegated + # node_modules within the container + - vite-project-image-location-node-modules:/app/node_modules + shm_size: '1gb' # to avoid a known issue + ports: + - 5173:5173 + command: > + sh -c "npm install && npm run dev" + networks: web-tier: driver: bridge @@ -717,4 +734,5 @@ networks: volumes: le_config: le_webrootpath: - portainer_data: \ No newline at end of file + portainer_data: + vite-project-image-location-node-modules: \ No newline at end of file diff --git a/protected/views/adminProject/_form.php b/protected/views/adminProject/_form.php index 45b65af3e5..65c8cb7d27 100644 --- a/protected/views/adminProject/_form.php +++ b/protected/views/adminProject/_form.php @@ -32,16 +32,25 @@ 'maxlength' => 255 ] ]); - $this->widget('application.components.controls.TextField', [ - 'form' => $form, - 'model' => $model, - 'attributeName' => 'image_location', - 'inputOptions' => [ - 'maxlength' => 100 - ] - ]); + // field replaced by vue widget + // $this->widget('application.components.controls.TextField', [ + // 'form' => $form, + // 'model' => $model, + // 'attributeName' => 'image_location', + // 'inputOptions' => [ + // 'maxlength' => 100 + // ] + // ]); ?> +
+ display here vue widget +
+
+ + +
+
Cancel isNewRecord ? 'Create' : 'Save', array('class' => 'btn background-btn')); ?> diff --git a/up.sh b/up.sh index e6afeb10e9..74f89e6a0b 100755 --- a/up.sh +++ b/up.sh @@ -64,6 +64,9 @@ docker-compose run --rm js bash -c "cd /var/www/ops/scripts/ && npm install" # Build and deploy the Javascript application docker-compose run --rm js +# Build and deploy the vite-project-image-location dev server +docker-compose up -d --build vite-project-image-location-dev + # Start Chome web driver container services for acceptance testing docker-compose up -d chrome diff --git a/vite/.dockerignore b/vite/.dockerignore new file mode 100644 index 0000000000..4f7ea7ba40 --- /dev/null +++ b/vite/.dockerignore @@ -0,0 +1,6 @@ +node_modules +README.md +LICENSE +dist +.vscode +index.html \ No newline at end of file diff --git a/vite/.gitignore b/vite/.gitignore new file mode 100644 index 0000000000..a547bf36d8 --- /dev/null +++ b/vite/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/vite/Dockerfile b/vite/Dockerfile new file mode 100644 index 0000000000..923d7f10fb --- /dev/null +++ b/vite/Dockerfile @@ -0,0 +1,9 @@ +# Using npm. An alternative would be to use bun (a faster bundler). +ARG NODE_VERSION +FROM node:${NODE_VERSION}-bullseye-slim +WORKDIR /app +COPY package*.json . +RUN npm ci +COPY . . +EXPOSE 5173 +CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/vite/README.md b/vite/README.md new file mode 100644 index 0000000000..346028f46c --- /dev/null +++ b/vite/README.md @@ -0,0 +1,30 @@ +# Vue client for project image location + +## Tasks + +- [ ] install node_modules in volume + +## Usage + +### Dev + +Run `./up.sh` script from root. This should build and run the docker container with the vite dev server and hot reloading + +Alternatively, run and build isolated from command line: + +Useful docker commands: + +```bash +# (re)build and run container (e.g. if Dockerfile changed) +NODE_VERSION=20.11.0 APPLICATION=../.. docker-compose -f ops/deployment/docker-compose.yml up --build vite-project-image-location-dev -d +# run container +NODE_VERSION=20.11.0 APPLICATION=../.. docker-compose -f ops/deployment/docker-compose.yml up vite-project-image-location-dev -d +# stop container +docker-compose down vite-project-image-location-dev +# remove dangling images after building +docker image prune -f +# remove dangling volumes +docker volume prune -f +# Full cleanup +docker system prune -a -f --volumes +``` diff --git a/vite/package-lock.json b/vite/package-lock.json new file mode 100644 index 0000000000..c6c4b53c15 --- /dev/null +++ b/vite/package-lock.json @@ -0,0 +1,1409 @@ +{ + "name": "vite", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vite", + "version": "0.0.0", + "dependencies": { + "vue": "^3.5.10" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.1.4", + "typescript": "^5.5.3", + "vite": "^5.4.8", + "vue-tsc": "^2.1.6" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "dependencies": { + "@babel/types": "^7.25.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", + "integrity": "sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.5.tgz", + "integrity": "sha512-F4tA0DCO5Q1F5mScHmca0umsi2ufKULAnMOVBfMsZdT4myhVl4WdKRwCaKcfOkIEuyrAVvtq1ESBdZ+rSyLVww==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.5" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.5.tgz", + "integrity": "sha512-varwD7RaKE2J/Z+Zu6j3mNNJbNT394qIxXwdvz/4ao/vxOfyClZpSDtLKkwWmecinkOVos5+PWkWraelfMLfpw==", + "dev": true + }, + "node_modules/@volar/typescript": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.5.tgz", + "integrity": "sha512-mcT1mHvLljAEtHviVcBuOyAwwMKz1ibXTi5uYtP/pf4XxoAzpdkQ+Br2IC0NPCvLCbjPZmbf3I0udndkfB1CDg==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.5", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.11.tgz", + "integrity": "sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.11", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.11.tgz", + "integrity": "sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==", + "dependencies": { + "@vue/compiler-core": "3.5.11", + "@vue/shared": "3.5.11" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.11.tgz", + "integrity": "sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.11", + "@vue/compiler-dom": "3.5.11", + "@vue/compiler-ssr": "3.5.11", + "@vue/shared": "3.5.11", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.47", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.11.tgz", + "integrity": "sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==", + "dependencies": { + "@vue/compiler-dom": "3.5.11", + "@vue/shared": "3.5.11" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/language-core": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.6.tgz", + "integrity": "sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==", + "dev": true, + "dependencies": { + "@volar/language-core": "~2.4.1", + "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.4.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.11.tgz", + "integrity": "sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==", + "dependencies": { + "@vue/shared": "3.5.11" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.11.tgz", + "integrity": "sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==", + "dependencies": { + "@vue/reactivity": "3.5.11", + "@vue/shared": "3.5.11" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.11.tgz", + "integrity": "sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==", + "dependencies": { + "@vue/reactivity": "3.5.11", + "@vue/runtime-core": "3.5.11", + "@vue/shared": "3.5.11", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.11.tgz", + "integrity": "sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==", + "dependencies": { + "@vue/compiler-ssr": "3.5.11", + "@vue/shared": "3.5.11" + }, + "peerDependencies": { + "vue": "3.5.11" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.11.tgz", + "integrity": "sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/less": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", + "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/needle": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", + "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/rollup": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/vue": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.11.tgz", + "integrity": "sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==", + "dependencies": { + "@vue/compiler-dom": "3.5.11", + "@vue/compiler-sfc": "3.5.11", + "@vue/runtime-dom": "3.5.11", + "@vue/server-renderer": "3.5.11", + "@vue/shared": "3.5.11" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-tsc": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.1.6.tgz", + "integrity": "sha512-f98dyZp5FOukcYmbFpuSCJ4Z0vHSOSmxGttZJCsFeX0M4w/Rsq0s4uKXjcSRsZqsRgQa6z7SfuO+y0HVICE57Q==", + "dev": true, + "dependencies": { + "@volar/typescript": "~2.4.1", + "@vue/language-core": "2.1.6", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + } + } +} diff --git a/vite/package.json b/vite/package.json new file mode 100644 index 0000000000..7516a704eb --- /dev/null +++ b/vite/package.json @@ -0,0 +1,20 @@ +{ + "name": "vite", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.5.10" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.1.4", + "typescript": "^5.5.3", + "vite": "^5.4.8", + "vue-tsc": "^2.1.6" + } +} diff --git a/vite/src/App.vue b/vite/src/App.vue new file mode 100644 index 0000000000..0f78e2020c --- /dev/null +++ b/vite/src/App.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/vite/src/main.ts b/vite/src/main.ts new file mode 100644 index 0000000000..0c8b20acbf --- /dev/null +++ b/vite/src/main.ts @@ -0,0 +1,4 @@ +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#vue-client_project-image-location') diff --git a/vite/src/vite-env.d.ts b/vite/src/vite-env.d.ts new file mode 100644 index 0000000000..11f02fe2a0 --- /dev/null +++ b/vite/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/vite/tsconfig.app.json b/vite/tsconfig.app.json new file mode 100644 index 0000000000..c54e60234b --- /dev/null +++ b/vite/tsconfig.app.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "preserve", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/vite/tsconfig.json b/vite/tsconfig.json new file mode 100644 index 0000000000..1ffef600d9 --- /dev/null +++ b/vite/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/vite/tsconfig.node.json b/vite/tsconfig.node.json new file mode 100644 index 0000000000..0d3d71446a --- /dev/null +++ b/vite/tsconfig.node.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite/vite.config.ts b/vite/vite.config.ts new file mode 100644 index 0000000000..fb719d92c1 --- /dev/null +++ b/vite/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + server: { + port: 5173, + origin: 'http://localhost:5173', + strictPort: true, + host: true + } +}) From a257ae40e6fd99b2f70f8b8f8fe203ec96e74b6b Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Wed, 23 Oct 2024 19:23:13 +0700 Subject: [PATCH 02/41] feat: mock image upload --- .../controllers/AdminProjectController.php | 24 +++- protected/models/Project.php | 124 ++++++++++++++---- protected/views/adminProject/_form.php | 9 +- 3 files changed, 129 insertions(+), 28 deletions(-) diff --git a/protected/controllers/AdminProjectController.php b/protected/controllers/AdminProjectController.php index 2fb95acae8..24339f3fa4 100644 --- a/protected/controllers/AdminProjectController.php +++ b/protected/controllers/AdminProjectController.php @@ -49,16 +49,34 @@ public function actionView($id) */ public function actionCreate() { - $model=new Project; + $model = new Project; // Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model); if(isset($_POST['Project'])) { - $model->attributes=$_POST['Project']; - if($model->save()) + Yii::log("action Create: project form data exists", "warning"); + $model->attributes = $_POST['Project']; + + $uploadedFile = CUploadedFile::getInstance($model, 'image'); + + Yii::log("action Create: uploaded file - " . $uploadedFile, "warning"); + + if ($uploadedFile) { + Yii::log("action Create: image form data exists", "warning"); + if ($model->writeLogo(Yii::$app->cloudStore, $uploadedFile)) { + Yii::log("action Create: logo uploaded successfully", "warning"); + // Logo uploaded successfully + } else { + Yii::log("Failed to write logo to storage for project " . $model->id, "error"); + } + } + + if($model->save()) { $this->redirect(array('view','id'=>$model->id)); + } + } $this->render('create',array( diff --git a/protected/models/Project.php b/protected/models/Project.php index 1d41414d95..f85c95044c 100644 --- a/protected/models/Project.php +++ b/protected/models/Project.php @@ -1,5 +1,9 @@ 'Please check the URL format'), + array('url', 'url','message'=>'Please check the URL format'), array('url', 'length', 'max'=>128), array('name', 'length', 'max'=>255), array('image_location', 'length', 'max'=>100), - array('url','check_duplicate'), + array('url','check_duplicate'), + array('image', 'file', 'types' => 'jpg, jpeg, png', 'allowEmpty' => true), // The following rule is used by search(). // Please remove those attributes that should not be searched. array('id, url, name, image_location', 'safe', 'on'=>'search'), @@ -100,28 +112,92 @@ public function search() } public static function getListProjects(){ - $models=Species::model()->findAll(); - $list=array(); - foreach (array_values($models) as $model){ - $list[$model->id] = $model->common_name; - } - return $list; - } - - function check_duplicate(){ - - - $db_url= Project::model()->findBySql("select name from project where url='$this->url'"); - - if($db_url !=null){ - $this->addError('url','Duplicate URL');} - - $db_name= Project::model()->findBySql("select url from project where name='$this->name'"); - - if($db_name !=null){ - $this->addError('name','Duplicate Project Name');} - - + $models=Species::model()->findAll(); + $list=array(); + foreach (array_values($models) as $model){ + $list[$model->id] = $model->common_name; + } + return $list; + } + + function check_duplicate(){ + + + $db_url= Project::model()->findBySql("select name from project where url='$this->url'"); + + if($db_url !=null){ + $this->addError('url','Duplicate URL');} + + $db_name= Project::model()->findBySql("select url from project where name='$this->name'"); + + if($db_name !=null){ + $this->addError('name','Duplicate Project Name');} + + + } + + /** + * write a logo image to the desired (Flysystem managed) storage mechanism and update url property with the location + * + * @param Filesystem $targetStorage + * @param string $enclosingDirectory + * @param CUploadedFile $uploadedFile + * @return bool + */ + public function writeLogo(Filesystem $targetStorage, CUploadedFile $uploadedFile): bool + { + Yii::log("writeLogo: Starting to process the uploaded file", "info"); + + $slugger = new \Symfony\Component\String\Slugger\AsciiSlugger(); + $info = pathinfo($uploadedFile->getName()); + $fileName = $slugger->slug($info['filename'])->toString(); + + Yii::log("writeLogo: Generated file name - " . $fileName, "info"); + $uuid = $this->getUuid(); + + Yii::log("writeLogo: Generated UUID - " . $uuid, "info"); + + $imagePath = sprintf("%s/images/projects/%s/%s.%s", Yii::$app->params['environment'], $uuid, $fileName, $info['extension'] ); + + Yii::log("writeLogo: Generated image path - " . $imagePath, "info"); + + // I expected YII_ENV_DEV to be true but it's not defined, so using a hardcoded temporary approach for now + $isLocalDev = true; + $hasBucketAccess = false; + if ($isLocalDev && !$hasBucketAccess) { + Yii::log("writeLogo: Local dev environment, skipping actual storage", "info"); + + // Mock URL for local development + $this->image_location = "https://assets.gigadb-cdn.net/live/images/projects/genome_10k/G10Klogo.jpg"; + + return true; + } + + if ($targetStorage->put( + $imagePath, file_get_contents($uploadedFile->getTempName()), + ['visibility' => AdapterInterface::VISIBILITY_PUBLIC] + )) { + // $this->logo = sprintf("%s.%s", $fileName, $info['extension']); + $this->image_location = sprintf("https://%s/%s", self::BUCKET, $imagePath); + + Yii::log("writeLogo: Image successfully written to storage", "info"); + + return true; + } + + Yii::log("Error attempting to write image to the storage","error"); + + return false; + } + + /** + * Return a UUID based on the project id + * + * @return string + */ + public function getUuid() + { + return Uuid::uuid5(Uuid::NAMESPACE_URL, self::NAMESPACE."/id/".$this->id); } } diff --git a/protected/views/adminProject/_form.php b/protected/views/adminProject/_form.php index 65c8cb7d27..ef827970f0 100644 --- a/protected/views/adminProject/_form.php +++ b/protected/views/adminProject/_form.php @@ -4,6 +4,7 @@ beginWidget('CActiveForm', array( 'id' => 'project-form', 'enableAjaxValidation' => false, + 'htmlOptions' => array('enctype' => 'multipart/form-data'), )); ?>

Fields with * are required.

@@ -43,8 +44,14 @@ // ]); ?> +
+ labelEx($model, 'image'); ?> + fileField($model, 'image'); ?> + error($model, 'image'); ?> +
+
- display here vue widget + you should not see this text
From d10ab9307f250ed1caeabaa8d79ed1372be68476 Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Fri, 25 Oct 2024 10:42:00 +0700 Subject: [PATCH 03/41] uppy widget is displayed in the ui --- node_modules/.package-lock.json | 6 + ops/deployment/docker-compose.yml | 31 +- package-lock.json | 6 + protected/views/adminProject/_form.php | 4 +- vite/.gitignore | 2 + vite/README.md | 14 +- vite/package-lock.json | 1772 ++++++++++++++---------- vite/package.json | 6 + vite/src/App.vue | 5 +- vite/src/components/LogoUpload.vue | 79 ++ vite/src/components/UppyDashboard.vue | 103 ++ vite/src/style.css | 29 + vite/tsconfig.app.json | 3 +- 13 files changed, 1284 insertions(+), 776 deletions(-) create mode 100644 node_modules/.package-lock.json create mode 100644 package-lock.json create mode 100644 vite/src/components/LogoUpload.vue create mode 100644 vite/src/components/UppyDashboard.vue create mode 100644 vite/src/style.css diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000000..ffc356c016 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "gigadb-website", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/ops/deployment/docker-compose.yml b/ops/deployment/docker-compose.yml index c1587f3be2..610a8c352d 100644 --- a/ops/deployment/docker-compose.yml +++ b/ops/deployment/docker-compose.yml @@ -93,7 +93,7 @@ services: - ${APPLICATION}/less:/var/www/less - ${APPLICATION}/css:/var/www/css - ${APPLICATION}/sql:/var/www/sql - - ${APPLICATION}/style-guide:/var/www/style-guide + - ${APPLICATION}/style-guide:/var/www/style-guide - ${APPLICATION}/index.php:/var/www/index.php - ${APPLICATION}/composer.json:/var/www/composer.json - ${APPLICATION}/composer.lock:/var/www/composer.lock @@ -101,7 +101,7 @@ services: - ${APPLICATION}/ops/configuration/php-conf/gigadb.pool.conf:/usr/local/etc/php-fpm.d/gigadb.pool.conf - ${APPLICATION}/ops/configuration/php-conf/opcache.ini:/usr/local/etc/php/conf.d/opcache.ini # access to File Upload Wizard model classes - - ../../fuw/app:/app + - ../../fuw/app:/app - ../../gigadb:/gigadb expose: - "9000" @@ -348,7 +348,7 @@ services: ipv4_address: 172.16.238.11 extra_hosts: - "gigadb.test:172.16.238.10" - - "fuw-admin-api:172.16.238.10" + - "fuw-admin-api:172.16.238.10" environment: # to run headless, set false and comment out port 5900 above and make sure to pass --headless arg in acceptance.suite.yml START_XVFB: "false" @@ -356,7 +356,7 @@ services: <<: *logging environment: GIGADB_ENV: $GIGADB_ENV - DOCKER_HOST: "tcp://host.docker.internal:2375" + DOCKER_HOST: "tcp://host.docker.internal:2375" build: context: ../../fuw/app dockerfile: common/Dockerfile @@ -465,7 +465,7 @@ services: - ~/.composer/cache:/root/.composer/cache:delegated # Mount source-code for development - ../../fuw/app:/app - - ../../gigadb/app:/gigadb-apps + - ../../gigadb/app:/gigadb-apps # php config - ../../fuw/app/php-conf/fuw.ini:/usr/local/etc/php/conf.d/fuw.ini - ../../fuw/app/php-conf/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini @@ -480,7 +480,7 @@ services: # volume mount the location of public ftp directory - /tmp:/var/ftp/public # access to files and reference data - - ../../files:/var/www/files + - ../../files:/var/www/files depends_on: - database - beanstalkd @@ -509,7 +509,7 @@ services: - ~/.composer/cache:/root/.composer/cache:delegated # Mount source-code for development - ../../fuw/app:/app - - ../../gigadb/app:/gigadb-apps + - ../../gigadb/app:/gigadb-apps # php config - ../../fuw/app/php-conf/fuw.ini:/usr/local/etc/php/conf.d/fuw.ini - ../../fuw/app/php-conf/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini @@ -524,7 +524,7 @@ services: # volume mount the location of public ftp directory - /tmp:/var/ftp/public # access to files and reference data - - ../../files:/var/www/files + - ../../files:/var/www/files depends_on: - database - beanstalkd @@ -565,7 +565,7 @@ services: - ~/.composer/cache:/root/.composer/cache:delegated # Mount source-code for development - ../../fuw/app:/app - - ../../gigadb/app:/gigadb-apps + - ../../gigadb/app:/gigadb-apps - ../../vendor:/gigadb-website/vendor - ../../sql:/gigadb-website/sql - ../../protected:/gigadb-website @@ -587,7 +587,7 @@ services: # to run tests that interact with containers # - /var/run/docker.sock:/var/run/docker.sock:ro # volume mount the location of public ftp directory - - /tmp:/var/ftp/public + - /tmp:/var/ftp/public networks: - web-tier - db-tier @@ -634,7 +634,7 @@ services: - ${DATA_SAVE_PATH}/fuw/repo:/var/repo/ - ${DATA_SAVE_PATH}/fuw/flags:/var/tmp/processing_flag # access to the ftp tokens so the upload's location attribute can be populated - - ${DATA_SAVE_PATH}/fuw/credentials:/var/private:ro + - ${DATA_SAVE_PATH}/fuw/credentials:/var/private:ro # access to the fuw/console so tusd hooks can trigger upload update - ../../fuw/app:/fuw/app # access to data feeds @@ -657,7 +657,7 @@ services: - ${DATA_SAVE_PATH}/fuw/incoming/tusd:/var/inbox/ - ${DATA_SAVE_PATH}/fuw/repo:/var/repo/ # access to the ftp tokens so the upload's location attribute can be populated - - ${DATA_SAVE_PATH}/fuw/credentials:/var/private + - ${DATA_SAVE_PATH}/fuw/credentials:/var/private # access to the fuw/console so tusd hooks can trigger upload update - ../../fuw/app:/app # access to data feeds @@ -714,8 +714,8 @@ services: volumes: # share host source code with the container to allow hot-reloading - ${APPLICATION}/vite:/app:delegated - # node_modules within the container - - vite-project-image-location-node-modules:/app/node_modules + # use local node_modules + - /app/node_modules shm_size: '1gb' # to avoid a known issue ports: - 5173:5173 @@ -734,5 +734,4 @@ networks: volumes: le_config: le_webrootpath: - portainer_data: - vite-project-image-location-node-modules: \ No newline at end of file + portainer_data: \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..ffc356c016 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "gigadb-website", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/protected/views/adminProject/_form.php b/protected/views/adminProject/_form.php index ef827970f0..a434584e87 100644 --- a/protected/views/adminProject/_form.php +++ b/protected/views/adminProject/_form.php @@ -44,14 +44,16 @@ // ]); ?> +
- you should not see this text +

You should not see this text. If you see this text, the Vue app is crashing.

diff --git a/vite/.gitignore b/vite/.gitignore index a547bf36d8..2798dced6b 100644 --- a/vite/.gitignore +++ b/vite/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +mock-files diff --git a/vite/README.md b/vite/README.md index 346028f46c..e8ed87251e 100644 --- a/vite/README.md +++ b/vite/README.md @@ -2,7 +2,10 @@ ## Tasks -- [ ] install node_modules in volume +- [ ] add sr-only text to browse files button: upload logo, please upload one file as logo. maximum height, etc +- [ ] adapt style to match gigadb theme, in the style.css file or in the component itself, or even better use directly the gigadb styles +- [ ] the hidden file input should have a specific id for the backend controller (maybe with the metafields option?) +- [ ] make the upload button displayed after adding file responsive (there's something apparent happening after user clicks it) or remove it (what does it do?) ## Usage @@ -28,3 +31,12 @@ docker volume prune -f # Full cleanup docker system prune -a -f --volumes ``` + +Dependencies are installed within the container. To install a new dependency: + +```bash +# access the container (run from root folder) +docker-compose exec vite-project-image-location-dev sh +# install new dependency +npm install +``` diff --git a/vite/package-lock.json b/vite/package-lock.json index c6c4b53c15..af26d92084 100644 --- a/vite/package-lock.json +++ b/vite/package-lock.json @@ -8,6 +8,12 @@ "name": "vite", "version": "0.0.0", "dependencies": { + "@uppy/dashboard": "^4.1.1", + "@uppy/drag-drop": "^4.0.3", + "@uppy/file-input": "^4.0.2", + "@uppy/image-editor": "^3.1.0", + "@uppy/progress-bar": "^4.0.0", + "@uppy/vue": "^2.0.1", "vue": "^3.5.10" }, "devDependencies": { @@ -17,28 +23,351 @@ "vue-tsc": "^2.1.6" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "node_modules/@transloadit/prettier-bytes": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.4.tgz", + "integrity": "sha512-8/SnIF9Q2k52mbjRVAYLranwkaDTLb+O9r4Z/uo8uNw//SjygKvvbF4BHSOuReufaAyum1q13602VcNud25Dfg==" + }, + "node_modules/@uppy/core": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-4.2.2.tgz", + "integrity": "sha512-TfTXngDLHK+gNwbpt1tgKfQ0vQwa7V5ilAnD/VNT+6AGW+/dqGFLZbA6q8xKvVTZ2sUbwDMSWFtqem+G04AhNQ==", + "peer": true, + "dependencies": { + "@transloadit/prettier-bytes": "^0.3.4", + "@uppy/store-default": "^4.1.0", + "@uppy/utils": "^6.0.3", + "lodash": "^4.17.21", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^5.0.0", + "preact": "^10.5.13" + } + }, + "node_modules/@uppy/core/node_modules/@uppy/store-default": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-4.1.0.tgz", + "integrity": "sha512-z5VSc4PNXpAtrrUPg5hdKJO5Ul7u4ZYLyK+tYzvEgzgR4nLVZmpGzj/d4N90jXpUqEibWKXvevODEB5VlTLHzg==", + "peer": true + }, + "node_modules/@uppy/core/node_modules/mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==", + "peer": true, + "dependencies": { + "wildcard": "^1.1.0" + } + }, + "node_modules/@uppy/core/node_modules/wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==", + "peer": true + }, + "node_modules/@uppy/dashboard": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-4.1.1.tgz", + "integrity": "sha512-LGABotHj7zXAu1sATBN6pljF6ACtrRM/Kh32uWbwSbD5E8mIu8WUjIQ0K45OieS8KmzCDmQy7djkUOhVx8tMYg==", + "dependencies": { + "@transloadit/prettier-bytes": "^0.3.4", + "@uppy/informer": "^4.1.0", + "@uppy/provider-views": "^4.0.1", + "@uppy/status-bar": "^4.0.3", + "@uppy/thumbnail-generator": "^4.0.0", + "@uppy/utils": "^6.0.3", + "classnames": "^2.2.6", + "lodash": "^4.17.21", + "memoize-one": "^6.0.0", + "nanoid": "^5.0.0", + "preact": "^10.5.13", + "shallow-equal": "^3.0.0" + }, + "peerDependencies": { + "@uppy/core": "^4.2.2" + } + }, + "node_modules/@uppy/drag-drop": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@uppy/drag-drop/-/drag-drop-4.0.3.tgz", + "integrity": "sha512-k9CySaCNgRge0bZrntmLGNFi2qGVFbprP0oibK3k4FOjrCvbJyN+nNppHwpEbBOPfuh76H94j9zL0OplQVZhZA==", + "dependencies": { + "@uppy/utils": "^6.0.3", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "^4.2.2" + } + }, + "node_modules/@uppy/file-input": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@uppy/file-input/-/file-input-4.0.2.tgz", + "integrity": "sha512-vZ6576Hyum7BYvIc+KCrsp/qPDsS/+qP4d7g8FC5Da8r0BPsNke95T3pqdr9uQiNGPOAG+etw9UvnnTo93zxqg==", + "dependencies": { + "@uppy/utils": "^6.0.3", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "^4.2.2" + } + }, + "node_modules/@uppy/image-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@uppy/image-editor/-/image-editor-3.1.0.tgz", + "integrity": "sha512-Ijgn18td1yR9YeZbEbmdRq8e7ZcYoRunGjgkl/O9milHFHYVkt6F5o1sVgP0I7WczYWKtWha9mbhV6HJF5LUjg==", + "dependencies": { + "@uppy/utils": "^6.0.2", + "cropperjs": "1.5.7", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "^4.2.0" + } + }, + "node_modules/@uppy/informer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-4.1.0.tgz", + "integrity": "sha512-Dzq7bEnUUePd7Syy6bDgzwSc16Re1tDYqP/sivtvPDrqINz8gUIST6IxN0GxRoSH732EjGiMlSf3OjwV/N18xQ==", + "dependencies": { + "@uppy/utils": "^6.0.2", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "^4.2.0" + } + }, + "node_modules/@uppy/progress-bar": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@uppy/progress-bar/-/progress-bar-4.0.0.tgz", + "integrity": "sha512-hCUjlfGWHlvBPQDO5YBH/8HEr+3+ZEobTblBg0Wbn3ecJSiKkSRi0GkDVp3OMnwfqgK2wm8Ve+tR/5Gds7vE0A==", + "dependencies": { + "@uppy/utils": "^6.0.0", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "^4.0.0" + } + }, + "node_modules/@uppy/provider-views": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-4.0.1.tgz", + "integrity": "sha512-oAOIVdCSPIpDZJXwU83o+13+qWYrIfRzJaXom7ZsJpj+WDbtFjML5iF3evDmqt22V3HwOC0N187lZvcO/9RwFA==", + "dependencies": { + "@uppy/utils": "^6.0.2", + "classnames": "^2.2.6", + "nanoid": "^5.0.0", + "p-queue": "^8.0.0", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "^4.1.1" + } + }, + "node_modules/@uppy/provider-views/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/@uppy/provider-views/node_modules/p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@uppy/provider-views/node_modules/p-timeout": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.3.tgz", + "integrity": "sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@uppy/status-bar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-4.0.3.tgz", + "integrity": "sha512-ckujiEQwHgpJGa5Q6OZF+hJ+3JSMgs/7vyl4aeBvV0zSWoPSg/W10TpyGeNvMaaAsbAs4UB+0LuUjVu/vSmFcw==", + "dependencies": { + "@transloadit/prettier-bytes": "^0.3.4", + "@uppy/utils": "^6.0.2", + "classnames": "^2.2.6", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "^4.1.2" + } + }, + "node_modules/@uppy/thumbnail-generator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-4.0.0.tgz", + "integrity": "sha512-nwgRO/LHLzUqzyB1TDl6g8LNmqtkswXpvRNcPij0gOrPTTWjGY6ULv+ywXYiF5baWF2aGS+K62jJSUGBWonx0w==", + "dependencies": { + "@uppy/utils": "^6.0.0", + "exifr": "^7.0.0" + }, + "peerDependencies": { + "@uppy/core": "^4.0.0" + } + }, + "node_modules/@uppy/thumbnail-generator/node_modules/exifr": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz", + "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==" + }, + "node_modules/@uppy/utils": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-6.0.3.tgz", + "integrity": "sha512-GBVzyAIeVKNe/F3TT63rXR80MSL9ov/FG3BbApO+4wbIt4vai7xpOxGCeTXpW2JjEeOwEb50n1fn92zMCdV9Dg==", + "dependencies": { + "lodash": "^4.17.21", + "preact": "^10.5.13" + } + }, + "node_modules/@uppy/vue": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-2.0.1.tgz", + "integrity": "sha512-JmU1WzisdRxw5WlEgZpIl8D2Q2AZgbvsmQyzHZwmGUuttBxKoBr4abguG95cT5qBA8raJzJhlxYRVwao2sbWBA==", + "dependencies": { + "shallow-equal": "^3.0.0" + }, + "peerDependencies": { + "@uppy/core": "^4.1.1", + "@uppy/dashboard": "^4.0.3", + "@uppy/drag-drop": "^4.0.2", + "@uppy/file-input": "^4.0.1", + "@uppy/progress-bar": "^4.0.0", + "@uppy/status-bar": "^4.0.2", + "vue": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@uppy/dashboard": { + "optional": true + }, + "@uppy/drag-drop": { + "optional": true + }, + "@uppy/file-input": { + "optional": true + }, + "@uppy/progress-bar": { + "optional": true + }, + "@uppy/status-bar": { + "optional": true + } + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", + "integrity": "sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/typescript": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.6.tgz", + "integrity": "sha512-NMIrA7y5OOqddL9VtngPWYmdQU03htNKFtAYidbYfWA0TOhyGVd9tfcP4TsLWQ+RBWDZCbBqsr8xzU0ZOxYTCQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.6", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@volar/typescript/node_modules/@volar/language-core": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.6.tgz", + "integrity": "sha512-FxUfxaB8sCqvY46YjyAAV6c3mMIq/NWQMVvJ+uS4yxr1KzOvyg61gAuOnNvgCvO4TZ7HcLExBEsWcDu4+K4E8A==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.6" + } + }, + "node_modules/@volar/typescript/node_modules/@volar/source-map": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.6.tgz", + "integrity": "sha512-Nsh7UW2ruK+uURIPzjJgF0YRGP5CX9nQHypA2OMqdM2FKy7rh+uv3XgPnWPw30JADbKvZ5HuBzG4gSbVDYVtiw==", + "dev": true + }, + "node_modules/@volar/typescript/node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/@volar/typescript/node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/@vue/language-core": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.6.tgz", + "integrity": "sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==", + "dev": true, + "dependencies": { + "@volar/language-core": "~2.4.1", + "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.4.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core/node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "node_modules/@vue/language-core/node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", - "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "node_modules/@vue/language-core/node_modules/@babel/parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", + "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", + "dev": true, "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.25.9" }, "bin": { "parser": "bin/babel-parser.js" @@ -47,20 +376,305 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/types": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", - "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "node_modules/@vue/language-core/node_modules/@babel/types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", + "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@vue/language-core/node_modules/@volar/language-core": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.6.tgz", + "integrity": "sha512-FxUfxaB8sCqvY46YjyAAV6c3mMIq/NWQMVvJ+uS4yxr1KzOvyg61gAuOnNvgCvO4TZ7HcLExBEsWcDu4+K4E8A==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.6" + } + }, + "node_modules/@vue/language-core/node_modules/@volar/source-map": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.6.tgz", + "integrity": "sha512-Nsh7UW2ruK+uURIPzjJgF0YRGP5CX9nQHypA2OMqdM2FKy7rh+uv3XgPnWPw30JADbKvZ5HuBzG4gSbVDYVtiw==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/@vue/compiler-core": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz", + "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.12", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/language-core/node_modules/@vue/compiler-dom": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz", + "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==", + "dev": true, + "dependencies": { + "@vue/compiler-core": "3.5.12", + "@vue/shared": "3.5.12" + } + }, + "node_modules/@vue/language-core/node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/language-core/node_modules/@vue/shared": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz", + "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vue/language-core/node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@vue/language-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/@vue/language-core/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vue/language-core/node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/@vue/language-core/node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, + "node_modules/cropperjs": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.7.tgz", + "integrity": "sha512-sGj+G/ofKh+f6A4BtXLJwtcKJgMUsXYVUubfTo9grERiDGXncttefmue/fyQFvn8wfdyoD1KhDRYLfjkJFl0yw==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==", + "peer": true + }, + "node_modules/nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/preact": { + "version": "10.24.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", + "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shallow-equal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz", + "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==" + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "5.4.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", + "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" }, "engines": { - "node": ">=6.9.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/@esbuild/aix-ppc64": { + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", @@ -76,7 +690,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/android-arm": { + "node_modules/vite/node_modules/@esbuild/android-arm": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", @@ -92,7 +706,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/android-arm64": { + "node_modules/vite/node_modules/@esbuild/android-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", @@ -108,7 +722,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/android-x64": { + "node_modules/vite/node_modules/@esbuild/android-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", @@ -124,7 +738,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/darwin-arm64": { + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", @@ -140,7 +754,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/darwin-x64": { + "node_modules/vite/node_modules/@esbuild/darwin-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", @@ -156,7 +770,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/freebsd-arm64": { + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", @@ -172,7 +786,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/freebsd-x64": { + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", @@ -188,7 +802,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-arm": { + "node_modules/vite/node_modules/@esbuild/linux-arm": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", @@ -204,7 +818,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-arm64": { + "node_modules/vite/node_modules/@esbuild/linux-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", @@ -220,7 +834,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-ia32": { + "node_modules/vite/node_modules/@esbuild/linux-ia32": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", @@ -236,7 +850,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-loong64": { + "node_modules/vite/node_modules/@esbuild/linux-loong64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", @@ -252,7 +866,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-mips64el": { + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", @@ -268,7 +882,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-ppc64": { + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", @@ -284,7 +898,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-riscv64": { + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", @@ -300,7 +914,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-s390x": { + "node_modules/vite/node_modules/@esbuild/linux-s390x": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", @@ -316,7 +930,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-x64": { + "node_modules/vite/node_modules/@esbuild/linux-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", @@ -332,7 +946,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/netbsd-x64": { + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", @@ -348,7 +962,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/openbsd-x64": { + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", @@ -364,7 +978,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/sunos-x64": { + "node_modules/vite/node_modules/@esbuild/sunos-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", @@ -380,7 +994,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/win32-arm64": { + "node_modules/vite/node_modules/@esbuild/win32-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", @@ -396,7 +1010,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/win32-ia32": { + "node_modules/vite/node_modules/@esbuild/win32-ia32": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", @@ -412,7 +1026,7 @@ "node": ">=12" } }, - "node_modules/@esbuild/win32-x64": { + "node_modules/vite/node_modules/@esbuild/win32-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", @@ -428,12 +1042,7 @@ "node": ">=12" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { + "node_modules/vite/node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", @@ -446,7 +1055,7 @@ "android" ] }, - "node_modules/@rollup/rollup-android-arm64": { + "node_modules/vite/node_modules/@rollup/rollup-android-arm64": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", @@ -459,7 +1068,7 @@ "android" ] }, - "node_modules/@rollup/rollup-darwin-arm64": { + "node_modules/vite/node_modules/@rollup/rollup-darwin-arm64": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", @@ -472,7 +1081,7 @@ "darwin" ] }, - "node_modules/@rollup/rollup-darwin-x64": { + "node_modules/vite/node_modules/@rollup/rollup-darwin-x64": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", @@ -485,7 +1094,7 @@ "darwin" ] }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "node_modules/vite/node_modules/@rollup/rollup-linux-arm-gnueabihf": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", @@ -498,7 +1107,7 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "node_modules/vite/node_modules/@rollup/rollup-linux-arm-musleabihf": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", @@ -511,7 +1120,7 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { + "node_modules/vite/node_modules/@rollup/rollup-linux-arm64-gnu": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", @@ -524,7 +1133,7 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm64-musl": { + "node_modules/vite/node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", @@ -537,352 +1146,117 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { + "node_modules/vite/node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@vitejs/plugin-vue": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", - "integrity": "sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==", - "dev": true, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "vite": "^5.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@volar/language-core": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.5.tgz", - "integrity": "sha512-F4tA0DCO5Q1F5mScHmca0umsi2ufKULAnMOVBfMsZdT4myhVl4WdKRwCaKcfOkIEuyrAVvtq1ESBdZ+rSyLVww==", - "dev": true, - "dependencies": { - "@volar/source-map": "2.4.5" - } - }, - "node_modules/@volar/source-map": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.5.tgz", - "integrity": "sha512-varwD7RaKE2J/Z+Zu6j3mNNJbNT394qIxXwdvz/4ao/vxOfyClZpSDtLKkwWmecinkOVos5+PWkWraelfMLfpw==", - "dev": true - }, - "node_modules/@volar/typescript": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.5.tgz", - "integrity": "sha512-mcT1mHvLljAEtHviVcBuOyAwwMKz1ibXTi5uYtP/pf4XxoAzpdkQ+Br2IC0NPCvLCbjPZmbf3I0udndkfB1CDg==", - "dev": true, - "dependencies": { - "@volar/language-core": "2.4.5", - "path-browserify": "^1.0.1", - "vscode-uri": "^3.0.8" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.11.tgz", - "integrity": "sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.11", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.11.tgz", - "integrity": "sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==", - "dependencies": { - "@vue/compiler-core": "3.5.11", - "@vue/shared": "3.5.11" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.11.tgz", - "integrity": "sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.11", - "@vue/compiler-dom": "3.5.11", - "@vue/compiler-ssr": "3.5.11", - "@vue/shared": "3.5.11", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.11", - "postcss": "^8.4.47", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.11.tgz", - "integrity": "sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==", - "dependencies": { - "@vue/compiler-dom": "3.5.11", - "@vue/shared": "3.5.11" - } - }, - "node_modules/@vue/compiler-vue2": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", - "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", - "dev": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, - "node_modules/@vue/language-core": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.6.tgz", - "integrity": "sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==", - "dev": true, - "dependencies": { - "@volar/language-core": "~2.4.1", - "@vue/compiler-dom": "^3.4.0", - "@vue/compiler-vue2": "^2.7.16", - "@vue/shared": "^3.4.0", - "computeds": "^0.0.1", - "minimatch": "^9.0.3", - "muggle-string": "^0.4.1", - "path-browserify": "^1.0.1" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@vue/reactivity": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.11.tgz", - "integrity": "sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==", - "dependencies": { - "@vue/shared": "3.5.11" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.11.tgz", - "integrity": "sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==", - "dependencies": { - "@vue/reactivity": "3.5.11", - "@vue/shared": "3.5.11" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.11.tgz", - "integrity": "sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==", - "dependencies": { - "@vue/reactivity": "3.5.11", - "@vue/runtime-core": "3.5.11", - "@vue/shared": "3.5.11", - "csstype": "^3.1.3" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.11.tgz", - "integrity": "sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==", - "dependencies": { - "@vue/compiler-ssr": "3.5.11", - "@vue/shared": "3.5.11" - }, - "peerDependencies": { - "vue": "3.5.11" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.11.tgz", - "integrity": "sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/vite/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/computeds": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", - "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", - "dev": true + "node_modules/vite/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "node_modules/vite/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], "dev": true, "optional": true, - "peer": true, - "dependencies": { - "is-what": "^3.14.1" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } + "os": [ + "linux" + ] }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "node_modules/vite/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "dev": true + "node_modules/vite/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } + "node_modules/vite/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "node_modules/vite/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], "dev": true, "optional": true, - "peer": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } + "os": [ + "win32" + ] + }, + "node_modules/vite/node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true }, - "node_modules/esbuild": { + "node_modules/vite/node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", @@ -920,12 +1294,7 @@ "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/fsevents": { + "node_modules/vite/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", @@ -939,228 +1308,35 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/muggle-string": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", - "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", - "dev": true - }, - "node_modules/nanoid": { + "node_modules/vite/node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/needle": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", - "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true, - "peer": true, + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/postcss": { + "node_modules/vite/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/vite/node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -1184,15 +1360,7 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/rollup": { + "node_modules/vite/node_modules/rollup": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", @@ -1227,182 +1395,274 @@ "fsevents": "~2.3.2" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/vite/node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "optional": true, - "peer": true + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "dev": true, - "optional": true, - "peer": true + "node_modules/vue": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz", + "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==", + "dependencies": { + "@vue/compiler-dom": "3.5.12", + "@vue/compiler-sfc": "3.5.12", + "@vue/runtime-dom": "3.5.12", + "@vue/server-renderer": "3.5.12", + "@vue/shared": "3.5.12" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/vue-tsc": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.1.6.tgz", + "integrity": "sha512-f98dyZp5FOukcYmbFpuSCJ4Z0vHSOSmxGttZJCsFeX0M4w/Rsq0s4uKXjcSRsZqsRgQa6z7SfuO+y0HVICE57Q==", "dev": true, + "dependencies": { + "@volar/typescript": "~2.4.1", + "@vue/language-core": "2.1.6", + "semver": "^7.5.4" + }, "bin": { - "semver": "bin/semver.js" + "vue-tsc": "bin/vue-tsc.js" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "typescript": ">=5.0.0" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "peer": true, + "node_modules/vue/node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/vue/node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/vue/node_modules/@babel/parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", + "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/vue/node_modules/@babel/types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", + "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { - "node": ">=14.17" + "node": ">=6.9.0" } }, - "node_modules/vite": { - "version": "5.4.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", - "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", - "dev": true, + "node_modules/vue/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/vue/node_modules/@vue/compiler-core": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz", + "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.12", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/vue/node_modules/@vue/compiler-dom": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz", + "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==", + "dependencies": { + "@vue/compiler-core": "3.5.12", + "@vue/shared": "3.5.12" + } + }, + "node_modules/vue/node_modules/@vue/compiler-sfc": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz", + "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.12", + "@vue/compiler-dom": "3.5.12", + "@vue/compiler-ssr": "3.5.12", + "@vue/shared": "3.5.12", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.47", + "source-map-js": "^1.2.0" + } + }, + "node_modules/vue/node_modules/@vue/compiler-ssr": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz", + "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==", + "dependencies": { + "@vue/compiler-dom": "3.5.12", + "@vue/shared": "3.5.12" + } + }, + "node_modules/vue/node_modules/@vue/reactivity": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz", + "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==", + "dependencies": { + "@vue/shared": "3.5.12" + } + }, + "node_modules/vue/node_modules/@vue/runtime-core": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz", + "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==", + "dependencies": { + "@vue/reactivity": "3.5.12", + "@vue/shared": "3.5.12" + } + }, + "node_modules/vue/node_modules/@vue/runtime-dom": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz", + "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==", + "dependencies": { + "@vue/reactivity": "3.5.12", + "@vue/runtime-core": "3.5.12", + "@vue/shared": "3.5.12", + "csstype": "^3.1.3" + } + }, + "node_modules/vue/node_modules/@vue/server-renderer": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz", + "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==", + "dependencies": { + "@vue/compiler-ssr": "3.5.12", + "@vue/shared": "3.5.12" }, + "peerDependencies": { + "vue": "3.5.12" + } + }, + "node_modules/vue/node_modules/@vue/shared": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz", + "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==" + }, + "node_modules/vue/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/vue/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", - "dev": true + "node_modules/vue/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, - "node_modules/vue": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.11.tgz", - "integrity": "sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==", + "node_modules/vue/node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dependencies": { - "@vue/compiler-dom": "3.5.11", - "@vue/compiler-sfc": "3.5.11", - "@vue/runtime-dom": "3.5.11", - "@vue/server-renderer": "3.5.11", - "@vue/shared": "3.5.11" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/vue/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/vue-tsc": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.1.6.tgz", - "integrity": "sha512-f98dyZp5FOukcYmbFpuSCJ4Z0vHSOSmxGttZJCsFeX0M4w/Rsq0s4uKXjcSRsZqsRgQa6z7SfuO+y0HVICE57Q==", - "dev": true, + "node_modules/vue/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/vue/node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "@volar/typescript": "~2.4.1", - "@vue/language-core": "2.1.6", - "semver": "^7.5.4" - }, - "bin": { - "vue-tsc": "bin/vue-tsc.js" + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, - "peerDependencies": { - "typescript": ">=5.0.0" + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/vue/node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" } } } diff --git a/vite/package.json b/vite/package.json index 7516a704eb..022064c811 100644 --- a/vite/package.json +++ b/vite/package.json @@ -9,6 +9,12 @@ "preview": "vite preview" }, "dependencies": { + "@uppy/dashboard": "^4.1.1", + "@uppy/drag-drop": "^4.0.3", + "@uppy/file-input": "^4.0.2", + "@uppy/image-editor": "^3.1.0", + "@uppy/progress-bar": "^4.0.0", + "@uppy/vue": "^2.0.1", "vue": "^3.5.10" }, "devDependencies": { diff --git a/vite/src/App.vue b/vite/src/App.vue index 0f78e2020c..569a7a05f2 100644 --- a/vite/src/App.vue +++ b/vite/src/App.vue @@ -1,8 +1,11 @@ + + diff --git a/vite/src/components/UppyDashboard.vue b/vite/src/components/UppyDashboard.vue new file mode 100644 index 0000000000..336a7a88e1 --- /dev/null +++ b/vite/src/components/UppyDashboard.vue @@ -0,0 +1,103 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/vite/src/style.css b/vite/src/style.css new file mode 100644 index 0000000000..81eb8064bc --- /dev/null +++ b/vite/src/style.css @@ -0,0 +1,29 @@ +.error-message { + color: rgb(121, 0, 0); + margin-top: 10px; +} + +.uppy-Dashboard-inner { + background-color: #f8f9fa; /* Light grey background to match the theme */ +} + +.uppy-Dashboard-AddFiles { + background-color: #007bff; /* Bootstrap primary blue */ + color: #fff; /* White text */ +} + +.uppy-Dashboard-AddFiles:hover { + background-color: #0056b3; /* Darker blue on hover */ +} + +.uppy-Dashboard-note { + color: #6c757d; /* Bootstrap secondary text color */ +} + +.uppy-DashboardItem-name { + color: #343a40; /* Dark grey text to match the theme */ +} + +.uppy-DashboardItem-status { + color: #6c757d; /* Bootstrap secondary text color */ +} \ No newline at end of file diff --git a/vite/tsconfig.app.json b/vite/tsconfig.app.json index c54e60234b..26fa139969 100644 --- a/vite/tsconfig.app.json +++ b/vite/tsconfig.app.json @@ -5,6 +5,7 @@ "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], "skipLibCheck": true, + "allowJs": true, /* Bundler mode */ "moduleResolution": "bundler", @@ -20,5 +21,5 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] + "include": ["src/**/*.ts", "src/**/*.vue"] } From f5f8ee9f223431863c494a27e821b3fce2fd5d09 Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Fri, 25 Oct 2024 10:42:43 +0700 Subject: [PATCH 04/41] display spinner while scripts load --- less/index.less | 3 ++- less/modules/spinner.less | 13 +++++++++++++ protected/views/adminProject/_form.php | 3 +-- vite/src/App.vue | 3 +-- vite/src/components/LogoUpload.vue | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 less/modules/spinner.less diff --git a/less/index.less b/less/index.less index 0e17270e2d..a0ac382455 100644 --- a/less/index.less +++ b/less/index.less @@ -64,4 +64,5 @@ @import "modules/team-grid.less"; @import "modules/map.less"; @import "modules/lists.less"; -@import "modules/tooltip.less"; \ No newline at end of file +@import "modules/tooltip.less"; +@import "modules/spinner.less"; \ No newline at end of file diff --git a/less/modules/spinner.less b/less/modules/spinner.less new file mode 100644 index 0000000000..3d9d7381db --- /dev/null +++ b/less/modules/spinner.less @@ -0,0 +1,13 @@ +.spinner { + border: 4px solid @color-gigadb-green; + border-top: 4px solid transparent; + border-radius: 50%; + width: 1.5rem; + height: 1.5rem; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} \ No newline at end of file diff --git a/protected/views/adminProject/_form.php b/protected/views/adminProject/_form.php index a434584e87..d6554a0d5d 100644 --- a/protected/views/adminProject/_form.php +++ b/protected/views/adminProject/_form.php @@ -51,9 +51,8 @@ error($model, 'image'); ?>
--> -
-

You should not see this text. If you see this text, the Vue app is crashing.

+
diff --git a/vite/src/App.vue b/vite/src/App.vue index 569a7a05f2..b896b8f850 100644 --- a/vite/src/App.vue +++ b/vite/src/App.vue @@ -1,11 +1,10 @@ diff --git a/vite/src/components/LogoUpload.vue b/vite/src/components/LogoUpload.vue index bb7aa4b6f2..e515d5d3bb 100644 --- a/vite/src/components/LogoUpload.vue +++ b/vite/src/components/LogoUpload.vue @@ -1,42 +1,62 @@ - diff --git a/vite/src/components/UppyDashboard.vue b/vite/src/components/UppyDashboard.vue deleted file mode 100644 index 336a7a88e1..0000000000 --- a/vite/src/components/UppyDashboard.vue +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/vite/src/main.ts b/vite/src/main.ts index 0c8b20acbf..d82feb831e 100644 --- a/vite/src/main.ts +++ b/vite/src/main.ts @@ -1,4 +1,4 @@ import { createApp } from 'vue' import App from './App.vue' -createApp(App).mount('#vue-client_project-image-location') +createApp(App).mount('#vue-client_project-image-logo') diff --git a/vite/src/style.css b/vite/src/style.css deleted file mode 100644 index 81eb8064bc..0000000000 --- a/vite/src/style.css +++ /dev/null @@ -1,29 +0,0 @@ -.error-message { - color: rgb(121, 0, 0); - margin-top: 10px; -} - -.uppy-Dashboard-inner { - background-color: #f8f9fa; /* Light grey background to match the theme */ -} - -.uppy-Dashboard-AddFiles { - background-color: #007bff; /* Bootstrap primary blue */ - color: #fff; /* White text */ -} - -.uppy-Dashboard-AddFiles:hover { - background-color: #0056b3; /* Darker blue on hover */ -} - -.uppy-Dashboard-note { - color: #6c757d; /* Bootstrap secondary text color */ -} - -.uppy-DashboardItem-name { - color: #343a40; /* Dark grey text to match the theme */ -} - -.uppy-DashboardItem-status { - color: #6c757d; /* Bootstrap secondary text color */ -} \ No newline at end of file From 5d2e114a4208732dc27e9c8c88ccd6d9fa843a35 Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Fri, 25 Oct 2024 18:08:17 +0700 Subject: [PATCH 07/41] feat: native inplementation --- vite/src/components/LogoUpload.vue | 249 ++++++------------------- vite/src/components/LogoUploadUppy.vue | 235 +++++++++++++++++++++++ 2 files changed, 294 insertions(+), 190 deletions(-) create mode 100644 vite/src/components/LogoUploadUppy.vue diff --git a/vite/src/components/LogoUpload.vue b/vite/src/components/LogoUpload.vue index e515d5d3bb..79125a4eff 100644 --- a/vite/src/components/LogoUpload.vue +++ b/vite/src/components/LogoUpload.vue @@ -1,211 +1,80 @@ - - - - + \ No newline at end of file diff --git a/vite/src/components/LogoUploadUppy.vue b/vite/src/components/LogoUploadUppy.vue new file mode 100644 index 0000000000..11d3879945 --- /dev/null +++ b/vite/src/components/LogoUploadUppy.vue @@ -0,0 +1,235 @@ + + + + + + + From f87f9b72ec42c31efc0f76a4698d9487c1fde67b Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Tue, 29 Oct 2024 15:12:50 +0700 Subject: [PATCH 08/41] feat: custom image editor --- vite/package-lock.json | 1 + vite/src/App.vue | 4 +- vite/src/components/LogoUploadUppy.vue | 166 +++++++++++++++++++++---- 3 files changed, 142 insertions(+), 29 deletions(-) diff --git a/vite/package-lock.json b/vite/package-lock.json index c79941db7f..7cd75b53df 100644 --- a/vite/package-lock.json +++ b/vite/package-lock.json @@ -116,6 +116,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@uppy/image-editor/-/image-editor-3.1.0.tgz", "integrity": "sha512-Ijgn18td1yR9YeZbEbmdRq8e7ZcYoRunGjgkl/O9milHFHYVkt6F5o1sVgP0I7WczYWKtWha9mbhV6HJF5LUjg==", + "license": "MIT", "dependencies": { "@uppy/utils": "^6.0.2", "cropperjs": "1.5.7", diff --git a/vite/src/App.vue b/vite/src/App.vue index 5225a2e42b..0bb3794a5a 100644 --- a/vite/src/App.vue +++ b/vite/src/App.vue @@ -1,7 +1,7 @@ diff --git a/vite/src/components/LogoUploadUppy.vue b/vite/src/components/LogoUploadUppy.vue index 11d3879945..16b320fbb6 100644 --- a/vite/src/components/LogoUploadUppy.vue +++ b/vite/src/components/LogoUploadUppy.vue @@ -1,22 +1,47 @@ \ No newline at end of file diff --git a/vite/package-lock.json b/vite/package-lock.json index 7cd75b53df..45986a8322 100644 --- a/vite/package-lock.json +++ b/vite/package-lock.json @@ -14,6 +14,7 @@ "@uppy/image-editor": "^3.1.0", "@uppy/progress-bar": "^4.0.0", "@uppy/vue": "^2.0.1", + "@uppy/xhr-upload": "^4.2.1", "vue": "^3.5.10" }, "devDependencies": { @@ -29,6 +30,26 @@ "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.4.tgz", "integrity": "sha512-8/SnIF9Q2k52mbjRVAYLranwkaDTLb+O9r4Z/uo8uNw//SjygKvvbF4BHSOuReufaAyum1q13602VcNud25Dfg==" }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "license": "MIT" + }, + "node_modules/@uppy/companion-client": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-4.1.0.tgz", + "integrity": "sha512-nQ8CQfZcYVBNtFQ6ePj7FDIq38DXlH0YpzP/91LR9gnDVISJKKUuvWfr6tPktj1lRw9FZV8jLmlMKT2ituVKiw==", + "license": "MIT", + "dependencies": { + "@uppy/utils": "^6.0.2", + "namespace-emitter": "^2.0.1", + "p-retry": "^6.1.0" + }, + "peerDependencies": { + "@uppy/core": "^4.2.0" + } + }, "node_modules/@uppy/core": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@uppy/core/-/core-4.2.2.tgz", @@ -270,6 +291,19 @@ } } }, + "node_modules/@uppy/xhr-upload": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-4.2.1.tgz", + "integrity": "sha512-pafgk0vLr+FKDHo+xmBMwNncj68oRNoaTnj0por7LPND0QGXV7xwBZnGGkQhiHLooV2MNBEhFQtx93A76cEINg==", + "license": "MIT", + "dependencies": { + "@uppy/companion-client": "^4.1.0", + "@uppy/utils": "^6.0.3" + }, + "peerDependencies": { + "@uppy/core": "^4.2.2" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", @@ -608,6 +642,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-what": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", @@ -695,8 +741,7 @@ "node_modules/namespace-emitter": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", - "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==", - "peer": true + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==" }, "node_modules/nanoid": { "version": "5.0.7", @@ -733,6 +778,23 @@ "node": ">= 4.4.x" } }, + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -771,6 +833,15 @@ "license": "MIT", "optional": true }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", diff --git a/vite/package.json b/vite/package.json index 9195eb666f..31bdbd6b4a 100644 --- a/vite/package.json +++ b/vite/package.json @@ -15,6 +15,7 @@ "@uppy/image-editor": "^3.1.0", "@uppy/progress-bar": "^4.0.0", "@uppy/vue": "^2.0.1", + "@uppy/xhr-upload": "^4.2.1", "vue": "^3.5.10" }, "devDependencies": { diff --git a/vite/src/components/LogoUploadUppy.vue b/vite/src/components/LogoUploadUppy.vue index 290c63b78a..b2a81200d9 100644 --- a/vite/src/components/LogoUploadUppy.vue +++ b/vite/src/components/LogoUploadUppy.vue @@ -6,13 +6,13 @@ import { Dashboard } from '@uppy/vue'; import ImageEditor from '@uppy/image-editor'; +import XHR from '@uppy/xhr-upload'; import '@uppy/core/dist/style.css'; import '@uppy/dashboard/dist/style.css'; import '@uppy/image-editor/dist/style.min.css'; /** - flow - user drops or loads file in widget @@ -22,13 +22,10 @@ flow - user resizes image in editor and saves - dynamically show image dimensions - while image height is > 60px, show warning message and keep "save" button disabled - - show "autocrop" button. On press: --> this feature is way too complicated for what it's worth - - if image height > 60px, auto resize height to 60px keeping image proportions - - if image height <= 60px, do nothing - user clicks upload button -> server endpoint uploads file to S3 and returns url - widget props - - server endpoint url + - server endpoint url (?) */ // constants @@ -89,10 +86,17 @@ uppy.use(ImageEditor, { } }); +uppy.use(XHR, { + endpoint: `/adminProject/uploadLogo`, + formData: true, + fieldName: 'logo_image', + withCredentials: true +}); + function openFileEditor(file: UppyFile>) { const dashboard = uppy.getPlugin('Dashboard'); if (dashboard) { - // TODO fix typescript error, avoid using any + // TODO fix typescript error, avoid using `any` (dashboard as any).openFileEditor(file); } } @@ -116,15 +120,12 @@ async function getImgDimension(imgFile: UppyFile>): // file events uppy.on('file-added', async (file: UppyFile>) => { - console.log('file-added', file); - isWrapperFocusable.value = false; errorMessage.value = null; try { const { height } = await getImgDimension(file); if (height > maxHeight) { - // Show warning but don't remove file errorMessage.value = `Image height (${height}px) exceeds ${maxHeight}px - please resize using the editor`; srOnlyErrorMessage.value = `Image height of ${height} pixels exceeds maximum of ${maxHeight} pixels. Please use the editor to resize.`; // Auto-open editor when height exceeds limit @@ -139,14 +140,45 @@ uppy.on('file-removed', () => { isWrapperFocusable.value = true; }); +uppy.on('upload-success', (file, response) => { + console.log('Upload successful', response.body); + + if (response.body?.success) { + const customEvent = new CustomEvent('logo-uploaded', { + detail: { + imageLocation: response.body.image_location + }, + bubbles: true + }); + document.dispatchEvent(customEvent); + } +}); + +uppy.on('upload-error', (file, error, response) => { + if (typeof response === 'string') { + try { + const errorData = JSON.parse(response); + errorMessage.value = errorData.message; + } catch { + errorMessage.value = 'Failed to upload file. Please try again.'; + } + } else { + errorMessage.value = 'Failed to upload file. Please try again.'; + } +}); + +uppy.on('upload-start', () => { + errorMessage.value = ''; +}); + // file-editor events uppy.on('file-editor:complete', async (file: UppyFile>) => { try { const { height } = await getImgDimension(file); if (height > maxHeight) { - errorMessage.value = `Image still exceeds ${maxHeight}px height - please resize further`; - srOnlyErrorMessage.value = `Image height still exceeds ${maxHeight} pixels. Please resize further.`; + errorMessage.value = `Image still exceeds ${maxHeight}px height - please crop further`; + srOnlyErrorMessage.value = `Image height still exceeds ${maxHeight} pixels. Please crop further.`; } else { errorMessage.value = null; srOnlyErrorMessage.value = null; @@ -221,9 +253,8 @@ function triggerUppyButton() { border-radius: 4px; } +/* uppy styles overrides */ :deep(.uppy-Dashboard-inner) { - - /* overrides */ .uppy-Dashboard-browse { /* duplicating less variable here, would be better to reuse already defined color from variables.less */ color: #08893e; @@ -256,10 +287,12 @@ function triggerUppyButton() { .uppy-DashboardContent-save { color: #08893e; + &:focus { background: #08893e; color: #fff; } + &:hover { background: #08893e; color: #fff; @@ -267,13 +300,8 @@ function triggerUppyButton() { } .uppy-Dashboard-Item-action { - - // color: white; - // background: black; - // border: 1px #08893e solid; &:hover { color: #08893e; - // background: #08893e; } &:focus { @@ -290,7 +318,6 @@ function triggerUppyButton() { border: 1px #08893e solid; &:hover { - // color: #fff; background: #0d6e36; } @@ -330,5 +357,3 @@ function triggerUppyButton() { border: 1px solid #feb2b2; } - - From c04e70e7b1610c7c50e3bd74bf5ca8d5236170fa Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Tue, 29 Oct 2024 19:12:38 +0700 Subject: [PATCH 12/41] chore: restores actioncreate method to original functionality --- .../controllers/AdminProjectController.php | 29 ++----------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/protected/controllers/AdminProjectController.php b/protected/controllers/AdminProjectController.php index bd74ae3765..97fe361cd7 100644 --- a/protected/controllers/AdminProjectController.php +++ b/protected/controllers/AdminProjectController.php @@ -49,39 +49,16 @@ public function actionView($id) */ public function actionCreate() { - $model = new Project; + $model=new Project; // Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model); if(isset($_POST['Project'])) { - Yii::log("action Create: project form data exists", "warning"); - $model->attributes = $_POST['Project']; - - Yii::log("action Create: project form data - " . print_r($model->attributes, true), "warning"); - - Yii::log("action Create: image_logo - " . print_r($model->image_logo, true), "warning"); - - $uploadedLogo = CUploadedFile::getInstance($model, 'image_logo'); - - Yii::log("action Create: uploaded file - " . $uploadedLogo, "warning"); - - if ($uploadedLogo) { - Yii::log("action Create: image form data exists", "warning"); - if ($model->writeLogo(Yii::$app->cloudStore, $uploadedLogo)) { - Yii::log("action Create: logo uploaded successfully", "warning"); - // Logo uploaded successfully - } else { - Yii::log("action Create: Failed to write logo to storage for project " . $model->id, "error"); - } - } - // $this->redirect(array('create')); - - if($model->save()) { + $model->attributes=$_POST['Project']; + if($model->save()) $this->redirect(array('view','id'=>$model->id)); - } - } $this->render('create',array( From 1edd8c09dd5afa5d998c35bfb22ccbfd47756096 Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Wed, 30 Oct 2024 10:24:29 +0700 Subject: [PATCH 13/41] feat: use write logo in project controller --- .../controllers/AdminProjectController.php | 88 ++++++------------- protected/models/Project.php | 18 ++-- 2 files changed, 35 insertions(+), 71 deletions(-) diff --git a/protected/controllers/AdminProjectController.php b/protected/controllers/AdminProjectController.php index 97fe361cd7..c47643dd27 100644 --- a/protected/controllers/AdminProjectController.php +++ b/protected/controllers/AdminProjectController.php @@ -66,77 +66,43 @@ public function actionCreate() )); } - private function validateFileSize($file, $maxSizeInBytes) { - return $file->getSize() <= $maxSizeInBytes; + private function makeResponse($code, $message, $payload = []) { + $success = $code < 400; + header('Content-Type: application/json'); + http_response_code($code); + echo CJSON::encode([ + 'success' => $success, + 'message' => $message, + ...$payload, + ]); + Yii::app()->end(); } // this method should be called by the uploader public function actionUploadLogo() { if (!isset($_FILES['logo_image'])) { - Yii::log("No logo_image file received in upload request", "warning"); - - // TODO research if this is the actual way to respond with 400 - header('Content-Type: application/json'); - http_response_code(400); - echo CJSON::encode([ - 'success' => false, - 'message' => 'No file was uploaded', - ]); - Yii::app()->end(); + $this->makeResponse(400, 'Invalid request. No file was uploaded.'); } $uploadedLogo = CUploadedFile::getInstanceByName('logo_image'); - // Yii::log("action UploadLogo: uploaded file - " . print_r($uploadedLogo, true), "warning"); - // action UploadLogo: uploaded file - CUploadedFile Object - // ( - // [_name:CUploadedFile:private] => G10Klogo_renamed.jpg - // [_tempName:CUploadedFile:private] => /tmp/phpe2H3JK - // [_type:CUploadedFile:private] => image/jpeg - // [_size:CUploadedFile:private] => 7702 - // [_error:CUploadedFile:private] => 0 - // [_e:CComponent:private] => - // [_m:CComponent:private] => - // ) - - // TODO validate file size server side (file size < 1MB) - if (!$this->validateFileSize($uploadedLogo, 1_000_000)) { - Yii::log("action UploadLogo: file size is greater than 1MB", "warning"); - header('Content-Type: application/json'); - http_response_code(400); - echo CJSON::encode([ - 'success' => false, - 'message' => 'File size should be less than 1MB', - ]); - Yii::app()->end(); + if ($uploadedLogo->getSize() > 1_000_000) { + $message = 'Invalid request. Logo image size should be less than 1MB'; + Yii::app()->user->setFlash('updateError', $message); + $this->makeResponse(400, $message); } - // TODO store file in S3 bucket - // TODO if a new file is uploaded, delete the old one - // Yii::log(print_r($_FILES['logo_image'], true), "warning"); - /** - * ( - * [name] => G10Klogo_renamed.jpg - * [type] => image/jpeg - * [tmp_name] => /tmp/php4humoH - * [error] => 0 - * [size] => 7702 - * ) - */ - - // Mock async process - sleep(1); // Simulate 1 second processing delay - - // Mock response for now - $response = [ - 'success' => true, - 'image_location' => 'https://assets.gigadb-cdn.net/assets/images/' . $_FILES['logo_image']['name'] - ]; - // TODO call writeLogo method that writes image to S3 bucket - - // Send JSON response - header('Content-Type: application/json'); - echo CJSON::encode($response); - Yii::app()->end(); + + $image_location = Project::writeLogo(Yii::$app->cloudStore, $uploadedLogo); + + if (!$image_location) { + $message = 'Failed to save your logo image'; + Yii::app()->user->setFlash('updateError', $message); + $this->makeResponse(500, $message); + } + + $this->makeResponse(200, 'Logo uploaded successfully', [ + 'image_location' => $image_location + ]); } /** diff --git a/protected/models/Project.php b/protected/models/Project.php index 13677f0d04..f392bb1521 100644 --- a/protected/models/Project.php +++ b/protected/models/Project.php @@ -145,9 +145,9 @@ function check_duplicate(){ * @param Filesystem $targetStorage * @param string $enclosingDirectory * @param CUploadedFile $uploadedLogo - * @return bool + * @return bool|string */ - public function writeLogo(Filesystem $targetStorage, CUploadedFile $uploadedLogo): bool + public static function writeLogo(Filesystem $targetStorage, CUploadedFile $uploadedLogo) { Yii::log("writeLogo: Starting to process the uploaded file", "info"); @@ -156,7 +156,7 @@ public function writeLogo(Filesystem $targetStorage, CUploadedFile $uploadedLogo $fileName = $slugger->slug($info['filename'])->toString(); Yii::log("writeLogo: Generated file name - " . $fileName, "info"); - $uuid = $this->getUuid(); + $uuid = Uuid::uuid4()->toString(); Yii::log("writeLogo: Generated UUID - " . $uuid, "info"); @@ -164,29 +164,27 @@ public function writeLogo(Filesystem $targetStorage, CUploadedFile $uploadedLogo Yii::log("writeLogo: Generated image path - " . $imagePath, "info"); - // I expected YII_ENV_DEV to be true but it's not defined, so using a hardcoded temporary approach for now + // I expected YII_ENV_DEV to be true but it's not defined, so using a hardcoded temporary approach for now so app does not crash each time $isLocalDev = true; $hasBucketAccess = false; if ($isLocalDev && !$hasBucketAccess) { Yii::log("writeLogo: Local dev environment, skipping actual storage", "info"); // Mock URL for local development - $this->image_location = "https://assets.gigadb-cdn.net/live/images/projects/genome_10k/G10Klogo.jpg"; + $image_location = "https://assets.gigadb-cdn.net/" . Yii::$app->params['environment'] . "/images/projects/" . $uuid . "/" . $fileName . "." . $info['extension']; - return true; + return $image_location; } if ($targetStorage->put( $imagePath, file_get_contents($uploadedLogo->getTempName()), ['visibility' => AdapterInterface::VISIBILITY_PUBLIC] )) { - // $this->logo = sprintf("%s.%s", $fileName, $info['extension']); - $this->image_logo = sprintf("%s.%s", $fileName, $info['extension']); - $this->image_location = sprintf("https://%s/%s", self::BUCKET, $imagePath); + $image_location = sprintf("https://%s/%s", self::BUCKET, $imagePath); Yii::log("writeLogo: Image successfully written to storage", "info"); - return true; + return $image_location; } Yii::log("writeLogo: Error attempting to write image to the storage","error"); From 010344266872884821c5da2581f3ba0d89cfc39c Mon Sep 17 00:00:00 2001 From: luis-toptal Date: Wed, 30 Oct 2024 14:47:39 +0700 Subject: [PATCH 14/41] feat: setup logo cleanup on project delete and on logo upload --- .../controllers/AdminProjectController.php | 34 ++++++-- protected/models/Project.php | 28 +++++-- protected/views/adminProject/_form.php | 25 +++--- vite/src/App.vue | 7 -- vite/src/components/DebugDisplay.vue | 35 ++++++++ vite/src/components/LogoUpload.vue | 80 ------------------- vite/src/components/LogoUploadUppy.vue | 58 +++++++++----- vite/src/composables/useLifecycleLogger.ts | 15 ++++ vite/src/main.ts | 12 ++- 9 files changed, 158 insertions(+), 136 deletions(-) delete mode 100644 vite/src/App.vue create mode 100644 vite/src/components/DebugDisplay.vue delete mode 100644 vite/src/components/LogoUpload.vue create mode 100644 vite/src/composables/useLifecycleLogger.ts diff --git a/protected/controllers/AdminProjectController.php b/protected/controllers/AdminProjectController.php index c47643dd27..42eeeb06a1 100644 --- a/protected/controllers/AdminProjectController.php +++ b/protected/controllers/AdminProjectController.php @@ -70,16 +70,16 @@ private function makeResponse($code, $message, $payload = []) { $success = $code < 400; header('Content-Type: application/json'); http_response_code($code); - echo CJSON::encode([ + echo CJSON::encode(array_merge([ 'success' => $success, 'message' => $message, - ...$payload, - ]); + ], $payload)); Yii::app()->end(); } - // this method should be called by the uploader - public function actionUploadLogo() { + public function actionUploadLogo($existingLogoUrl = null) { + $existingLogoUrl = Yii::app()->request->getQuery('existingLogoUrl'); + Yii::log("uploadLogo: existingLogoUrl = " . $existingLogoUrl, "info"); if (!isset($_FILES['logo_image'])) { $this->makeResponse(400, 'Invalid request. No file was uploaded.'); } @@ -92,7 +92,7 @@ public function actionUploadLogo() { $this->makeResponse(400, $message); } - $image_location = Project::writeLogo(Yii::$app->cloudStore, $uploadedLogo); + $image_location = Project::writeLogo(Yii::$app->cloudStore, $uploadedLogo, $existingLogoUrl); if (!$image_location) { $message = 'Failed to save your logo image'; @@ -102,7 +102,7 @@ public function actionUploadLogo() { $this->makeResponse(200, 'Logo uploaded successfully', [ 'image_location' => $image_location - ]); + ]); } /** @@ -136,10 +136,28 @@ public function actionUpdate($id) */ public function actionDelete($id) { + Yii::log("delete: $id"); if(Yii::app()->request->isPostRequest) { // we only allow deletion via POST request - $this->loadModel($id)->delete(); + $model = $this->loadModel($id); + $logoUrl = $model->image_location; + $logoPath = str_replace('https://' . Project::BUCKET . '/', '', $logoUrl); + Yii::log("delete: $id, logoUrl = $logoUrl", "info"); + + // I expected YII_ENV_DEV to be true but it's not defined, so using a hardcoded temporary approach for now so app does not crash each time + $isLocalDev = true; + $hasStorageAccess = false; + if ($isLocalDev && !$hasStorageAccess) { + Yii::log("actionDelete: Local dev environment, skipping actual delete", "info"); + } else { + if (Yii::$app->cloudStore->delete($logoPath)) { + Yii::log("actionDelete: Deleted logo image" . $logoPath . " for project ". $id, "info"); + } else { + Yii::log("actionDelete: Failed to delete logo image" . $logoPath . " for project ". $id, "error"); + } + } + $model->delete(); // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser if(!isset($_GET['ajax'])) diff --git a/protected/models/Project.php b/protected/models/Project.php index f392bb1521..99fc6c3f80 100644 --- a/protected/models/Project.php +++ b/protected/models/Project.php @@ -57,7 +57,7 @@ public function rules() array('url', 'url','message'=>'Please check the URL format'), array('url', 'length', 'max'=>128), array('name', 'length', 'max'=>255), - array('image_location', 'length', 'max'=>100), + array('image_location', 'length', 'max'=>255), array('url','check_duplicate'), // array('image', 'file', 'types' => 'jpg, jpeg, png', 'allowEmpty' => true), array('image_logo', 'file', 'types' => 'jpg, jpeg, png', 'allowEmpty' => true), @@ -143,11 +143,11 @@ function check_duplicate(){ * write a logo image to the desired (Flysystem managed) storage mechanism and update url property with the location * * @param Filesystem $targetStorage - * @param string $enclosingDirectory * @param CUploadedFile $uploadedLogo + * @param string|null $existingLogoUrl * @return bool|string */ - public static function writeLogo(Filesystem $targetStorage, CUploadedFile $uploadedLogo) + public static function writeLogo(Filesystem $targetStorage, CUploadedFile $uploadedLogo, $existingLogoUrl = null) { Yii::log("writeLogo: Starting to process the uploaded file", "info"); @@ -163,15 +163,18 @@ public static function writeLogo(Filesystem $targetStorage, CUploadedFile $uploa $imagePath = sprintf("%s/images/projects/%s/%s.%s", Yii::$app->params['environment'], $uuid, $fileName, $info['extension'] ); Yii::log("writeLogo: Generated image path - " . $imagePath, "info"); + $image_location = sprintf("https://%s/%s", self::BUCKET, $imagePath); // I expected YII_ENV_DEV to be true but it's not defined, so using a hardcoded temporary approach for now so app does not crash each time $isLocalDev = true; - $hasBucketAccess = false; - if ($isLocalDev && !$hasBucketAccess) { + $hasStorageAccess = false; + if ($isLocalDev && !$hasStorageAccess) { Yii::log("writeLogo: Local dev environment, skipping actual storage", "info"); - // Mock URL for local development - $image_location = "https://assets.gigadb-cdn.net/" . Yii::$app->params['environment'] . "/images/projects/" . $uuid . "/" . $fileName . "." . $info['extension']; + if ($existingLogoUrl !== null) { + $existingLogoPath = str_replace('https://' . self::BUCKET . '/', '', $existingLogoUrl); + Yii::log("writeLogo: Mocking deleting existing logo image with path " . $existingLogoPath, "info"); + } return $image_location; } @@ -180,7 +183,16 @@ public static function writeLogo(Filesystem $targetStorage, CUploadedFile $uploa $imagePath, file_get_contents($uploadedLogo->getTempName()), ['visibility' => AdapterInterface::VISIBILITY_PUBLIC] )) { - $image_location = sprintf("https://%s/%s", self::BUCKET, $imagePath); + if ($existingLogoUrl !== null) { + $existingLogoPath = str_replace('https://' . self::BUCKET . '/', '', $existingLogoUrl); + Yii::log("writeLogo: Deleting existing logo image with path " . $existingLogoPath, "info"); + + if ($targetStorage->delete($existingLogoPath)) { + Yii::log("writeLogo: Deleted existing logo image" . $existingLogoPath, "info"); + } else { + Yii::log("writeLogo: Failed to delete existing logo image" . $existingLogoUrl, "error"); + } + } Yii::log("writeLogo: Image successfully written to storage", "info"); diff --git a/protected/views/adminProject/_form.php b/protected/views/adminProject/_form.php index 0da35a9a10..0af4e4cd3a 100644 --- a/protected/views/adminProject/_form.php +++ b/protected/views/adminProject/_form.php @@ -34,18 +34,22 @@ ] ]); // TODO field replaced by vue widget, should remove / replace by thumbnail - $this->widget('application.components.controls.TextField', [ - 'form' => $form, - 'model' => $model, - 'attributeName' => 'image_location', - 'inputOptions' => [ - 'maxlength' => 100, - 'readonly' => true - ] - ]); + // $this->widget('application.components.controls.TextField', [ + // 'form' => $form, + // 'model' => $model, + // 'attributeName' => 'image_location', + // 'inputOptions' => [ + // 'maxlength' => 100, + // 'readonly' => true + // ] + // ]); + + // current image location in case user uploaded one already + $imageLocation = $model->image_location ?: null; + $endpoint = Yii::app()->createUrl('/adminProject/uploadLogo'); ?> - \ No newline at end of file diff --git a/vite/src/components/HiddenInput.vue b/vite/src/components/HiddenInput.vue index e9c3a607f1..4efa14e523 100644 --- a/vite/src/components/HiddenInput.vue +++ b/vite/src/components/HiddenInput.vue @@ -1,9 +1,10 @@ \ No newline at end of file + + diff --git a/vite/src/components/LogoUploadUppy.vue b/vite/src/components/LogoUploadUppy.vue index 4218c6bbd5..eed1c86091 100644 --- a/vite/src/components/LogoUploadUppy.vue +++ b/vite/src/components/LogoUploadUppy.vue @@ -24,6 +24,7 @@ const { maxHeight, maxSize, maxSizeMb } = config; const props = defineProps<{ endpoint: string; imageLocation: string | null; + hiddenInputName?: string; }>(); const constraintsMessage = `Please upload one image file (max height ${maxHeight}px, max size ${maxSizeMb} MB)` @@ -41,7 +42,6 @@ const endpoint = computed(() => { return `${props.endpoint}${uploadedImageLocation.value ? `?existingLogoUrl=${uploadedImageLocation.value}` : ''}`; }) -// initialize uppy here to avoid complexity const uppy = new Uppy({ autoProceed: false, debug: true, @@ -85,8 +85,7 @@ uppy.use(XHR, { withCredentials: true }); -// file events - +// uppy file events uppy.on('file-added', async (file: UppyFile>) => { isWrapperFocusable.value = false; errorMessage.value = null; @@ -111,23 +110,15 @@ uppy.on('file-removed', () => { isWrapperFocusable.value = true; }); +// uppy upload events uppy.on('upload-success', (file, response) => { - console.log('Upload successful', response.body); - if (response.body?.success) { const { image_location } = response.body; - // allows to communicate with parent PHP view - const customEvent = new CustomEvent('logo-uploaded', { - detail: { - imageLocation: image_location - }, - bubbles: true - }); - document.dispatchEvent(customEvent); uploadedImageLocation.value = image_location; } }); +// parse response from upload server endpoint uppy.on('upload-error', (file, error, response) => { if (typeof response === 'string') { try { @@ -145,7 +136,7 @@ uppy.on('upload-start', () => { errorMessage.value = ''; }); -// file-editor events +// file-editor plugin events uppy.on('file-editor:complete', async (file: UppyFile>) => { try { @@ -165,14 +156,10 @@ uppy.on('file-editor:complete', async (file: UppyFile