diff --git a/.env b/.env index 0e9798aa..2cac22b7 100755 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ -VITE_APP_VERSION="1.2.68" +VITE_APP_VERSION="1.2.69" VITE_LANG_DEFAULT="it" VITE_PAO_APP_ID="KKPPAA5KJK435J3KSS9F9D8S9F8SD98F9SDF" -VITE_SERVICE_WORKER_FILE="sw-1.2.68.js" +VITE_SERVICE_WORKER_FILE="sw-1.2.69.js" VITE_PROJECT_ID_MAIN="5cc0a13fe5c9d156728f400a" VITE_VUE_ROUTER_MODE="history" \ No newline at end of file diff --git a/index.html b/index.html index da1817f5..adb0b70a 100755 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@ - + diff --git a/package.json b/package.json index 62406772..862db299 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nuovomondo", - "version": "1.2.68", + "version": "1.2.69", "description": "Nuovo Mondo", "productName": "Nuovo Mondo", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8083 APP_VERSION='1.2.68' quasar dev", + "dev": "APP_VERSION='1.2.69' PORT=8083 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,117 +21,117 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", "postinstall": "quasar prepare" }, "dependencies": { - "@cubejs-client/core": "^1.2.26", - "@quasar/extras": "^1.16.17", + "@cubejs-client/core": "^1.3.21", + "@quasar/extras": "^1.17.0", "@quasar/quasar-ui-qcalendar": "^4.1.2", "@types/jsbarcode": "^3.11.4", - "@types/leaflet": "^1.9.17", - "@vue/compat": "^3.5.13", - "@vue/compiler-sfc": "^3.5.13", + "@types/leaflet": "^1.9.18", + "@vue/compat": "^3.5.16", + "@vue/compiler-sfc": "^3.5.16", "@vuelidate/core": "^2.0.3", "@vuelidate/validators": "^2.0.4", - "acorn": "^8.14.1", + "acorn": "^8.15.0", "animate.css": "^4.1.1", + "apexcharts": "^4.7.0", "autoprefixer": "^10.4.21", - "axios": "^1.8.4", + "axios": "^1.9.0", "bcryptjs": "^3.0.2", - "chart.js": "^4.4.8", - "core-js": "^3.41.0", + "chart.js": "^4.4.9", + "core-js": "^3.43.0", "crypto-browserify": "^3.12.1", "date-fns": "^4.1.0", "echarts": "5.6.0", - "eslint-plugin-n": "^17.16.2", + "eslint-plugin-n": "^17.19.0", "eslint-plugin-quasar": "^1.1.0", - "graphql": "^16.10.0", - "graphql-tag": "^2.12.6", - "gsap": "^3.12.7", + "gsap": "^3.13.0", "html2pdf.js": "^0.10.3", "jquery": "^3.7.1", "js-cookie": "^3.0.5", - "jsbarcode": "^3.11.6", + "jsbarcode": "^3.12.1", "leaflet": "^1.9.4", "leaflet-routing-machine": "^3.2.12", "leaflet.markercluster": "^1.5.3", "localforage": "^1.10.0", "lodash": "^4.17.21", + "mongoose-paginate-v2": "^1.9.1", "normalize.css": "^8.0.1", "nprogress": "^0.2.0", - "pinia": "^3.0.1", - "qrcode-vue3": "^1.7.1", + "pinia": "^3.0.3", "quasar": "^2.18.1", "quasar-extras": "^2.0.9", "register-service-worker": "^1.7.2", "scrollreveal": "^4.0.9", - "typescript-eslint": "^8.27.0", - "vee-validate": "^4.15.0", - "vue": "^3.5.13", + "typescript-eslint": "^8.34.0", + "vee-validate": "^4.15.1", + "vue": "^3.5.16", "vue-class-component": "^8.0.0-rc.1", "vue-country-code": "^1.1.3", "vue-echarts": "^7.0.3", - "vue-i18n": "^11.1.2", + "vue-i18n": "^11.1.5", "vue-idb": "^0.2.0", - "vue-image-zoomer": "^2.4.4", "vue-property-decorator": "^10.0.0-rc.3", - "vue-router": "^4.5.0", + "vue-router": "^4.5.1", "vue-scroll-reveal": "^2.1.0", "vue-social-sharing": "^4.0.0-alpha4", "vue-svgicon": "^4.0.0-alpha.3", "vue-timeago3": "^2.3.2", "vue2-dragula": "^2.5.5", - "vue3-pdf-app": "^1.0.3", + "vue3-apexcharts": "^1.8.0", "vue3-qr-reader": "^1.0.0", + "vuedraggable": "^4.1.0", "vuex": "^4.1.0", "vuex-router-sync": "^6.0.0-rc.1", "workbox-core": "^7.3.0", "workbox-precaching": "^7.3.0", "workbox-routing": "^7.3.0", "workbox-strategies": "^7.3.0", - "workbox-window": "^7.3.0" + "workbox-window": "^7.3.0", + "xlsx": "^0.18.5" }, "devDependencies": { - "@eslint/js": "^9.23.0", - "@intlify/unplugin-vue-i18n": "^6.0.5", - "@quasar/app-vite": "^2.1.4", + "@eslint/js": "^9.28.0", + "@intlify/unplugin-vue-i18n": "^6.0.8", + "@quasar/app-vite": "^2.2.1", "@types/google.maps": "^3.58.1", "@types/jest": "^29.5.14", "@types/js-cookie": "^3.0.6", - "@types/node": "^22.13.11", + "@types/node": "^24.0.1", "@types/nprogress": "^0.2.3", "@types/vue-tel-input": "^2.1.7", "@types/vuelidate": "^0.7.22", - "@vue/devtools": "^7.7.2", + "@vue/devtools": "^7.7.6", "@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-typescript": "^14.5.0", "autoprefixer": "^10.4.21", "eslint": "9", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-vue": "^10.0.0", + "eslint-plugin-vue": "^10.2.0", "file-loader": "^6.2.0", - "globals": "^16.0.0", - "http-proxy-middleware": "^3.0.3", - "jest": "^29.7.0", + "globals": "^16.2.0", + "http-proxy-middleware": "^3.0.5", + "jest": "^30.0.0", "json-loader": "^0.5.7", - "nodemon": "^3.1.9", - "npm-check-updates": "^17.1.16", - "parcel": "^2.14.1", - "postcss": "^8.5.3", + "nodemon": "^3.1.10", + "npm-check-updates": "^18.0.1", + "parcel": "^2.15.2", + "postcss": "^8.5.5", "postcss-loader": "^8.1.1", "prettier": "3", "strip-ansi": "=7.1.0", - "ts-jest": "^29.2.6", - "typescript": "5.7.3", - "vite-plugin-checker": "^0.9.1", + "ts-jest": "^29.4.0", + "typescript": "5.8.3", + "vite-plugin-checker": "^0.9.3", "vue-cli-plugin-element-ui": "^1.1.4", - "vue-eslint-parser": "^10.1.1", - "vue-tsc": "^2.2.8", + "vue-eslint-parser": "^10.1.3", + "vue-tsc": "^2.2.10", "vueify": "^9.4.1", "workbox-build": "^7.3.0" }, diff --git a/quasar.config.ts b/quasar.config.ts index 943c259e..e99ac3cb 100644 --- a/quasar.config.ts +++ b/quasar.config.ts @@ -238,7 +238,7 @@ export default defineConfig((ctx) => { port: parseInt(process.env.PORT, 10), vueDevtools: false, // automatically opening remote Vue Devtools open: false, // opens browser window automatically - hot: true, // Disable hot module replacement + hot: true, // Enable hot module replacement headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': '*', diff --git a/scripts/_ALL_SITES/comunitanuovomondo.app/package.json b/scripts/_ALL_SITES/comunitanuovomondo.app/package.json index c39b102b..371abe1c 100755 --- a/scripts/_ALL_SITES/comunitanuovomondo.app/package.json +++ b/scripts/_ALL_SITES/comunitanuovomondo.app/package.json @@ -1,6 +1,6 @@ { "name": "cnm", - "version": "1.2.68", + "version": "1.2.69", "description": "Comunita Nuovo Mondo", "productName": "ComunitaNuovoMondo", "author": "Surya", @@ -9,7 +9,7 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8083 APP_VERSION='1.2.68' quasar dev", + "dev": "PORT=8083 APP_VERSION='1.2.69' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", "buildpwa": "NODE_ENV=production quasar build -m pwa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/comunitanuovomondo.app/src/db/static_data.ts b/scripts/_ALL_SITES/comunitanuovomondo.app/src/db/static_data.ts index 0657e230..fb463534 100755 --- a/scripts/_ALL_SITES/comunitanuovomondo.app/src/db/static_data.ts +++ b/scripts/_ALL_SITES/comunitanuovomondo.app/src/db/static_data.ts @@ -47,7 +47,7 @@ function getDynamicPages(site: ISites): IListRoutes[] { const baseroutes: IListRoutes[] = [ { active: true, - order: 5, + order: -1, path: '/', materialIcon: 'home', name: 'pages.home', @@ -321,3 +321,5 @@ export const static_data = { preLoadImages, preloadedimages, } + + diff --git a/scripts/_ALL_SITES/freeplanet.app/package.json b/scripts/_ALL_SITES/freeplanet.app/package.json index a4266a93..b83b119f 100755 --- a/scripts/_ALL_SITES/freeplanet.app/package.json +++ b/scripts/_ALL_SITES/freeplanet.app/package.json @@ -1,6 +1,6 @@ { "name": "freeplanet", - "version": "1.2.68", + "version": "1.2.69", "description": "freeplanet", "productName": "freeplanet", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8087 APP_VERSION='1.2.68' quasar dev", + "dev": "PORT=8087 APP_VERSION='1.2.69' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8097 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8087 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8097 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8087 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/gruppomacro.app/package.json b/scripts/_ALL_SITES/gruppomacro.app/package.json index 2809c3c7..5f98d04f 100755 --- a/scripts/_ALL_SITES/gruppomacro.app/package.json +++ b/scripts/_ALL_SITES/gruppomacro.app/package.json @@ -1,6 +1,6 @@ { "name": "gruppomacro", - "version": "1.2.68", + "version": "1.2.69", "productName": "Gruppo Macro", "description": "Il Gruppo Editoriale Macro, attivo dal 1987, è leader europeo nella pubblicazione di libri per il benessere e la consapevolezza. Con oltre 1.500 titoli, promuove una visione armonica del mondo, offrendo opere di autori internazionali e italiani come Gregg Braden, Bruce Lipton, Joe Dispenza, Louise Hay, Eckhart Tolle e molti altri. Scopri un'editoria che abbraccia il corpo, la mente, lo spirito e l'ecologia.", "author": "Surya", @@ -9,20 +9,20 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8089 APP_VERSION='1.2.68' quasar dev", + "dev": "PORT=8089 APP_VERSION='1.2.69' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", - "buildspa": "APP_VERSION='1.2.68' quasar build -m spa", + "buildspa": "APP_VERSION='1.2.69' quasar build -m spa", "lint": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\"", "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/kolibrilab.it/package.json b/scripts/_ALL_SITES/kolibrilab.it/package.json index b30d76d2..314bf243 100755 --- a/scripts/_ALL_SITES/kolibrilab.it/package.json +++ b/scripts/_ALL_SITES/kolibrilab.it/package.json @@ -1,6 +1,6 @@ { "name": "kolibrilab", - "version": "1.2.68", + "version": "1.2.69", "description": "kolibrilab", "productName": "kolibrilab", "author": "Surya Paolo", @@ -8,11 +8,11 @@ "keywords": [], "license": "MIT", "scripts": { - "dev": "PORT=8083 APP_VERSION='1.2.68' quasar dev", + "dev": "PORT=8083 APP_VERSION='1.2.69' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -20,8 +20,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint --ext .ts,.vue --ignore-path .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.69' quasar dev", "spanorefresh": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m spa", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js" diff --git a/scripts/_ALL_SITES/nuovomondo.app/.env.production b/scripts/_ALL_SITES/nuovomondo.app/.env.production index a077b0bd..5e0af09a 100644 --- a/scripts/_ALL_SITES/nuovomondo.app/.env.production +++ b/scripts/_ALL_SITES/nuovomondo.app/.env.production @@ -1,11 +1,11 @@ -VITE_APP_ID="10" -VITE_APP_URL="https://test.nuovomondo.app" -VITE_MONGODB_HOST="https://testapi.nuovomondo.app" -VITE_LOGO_REG='cmn-logo-full.png' +VITE_APP_ID="13" +VITE_APP_URL="https://riso.app" +VITE_MONGODB_HOST="https://api.riso.app" +VITE_LOGO_REG='riso-logo-full.png' VITE_PUBLICKEY_PUSH="BGXRf1TgcqocqD6J7qnRgCG7AvM2lxAoW7peb7UEzB4SxBb6DxGRdJ0UvD9ewnrB9KrSrh0-aDCODXBm7sZ1DDs" -VITE_DEBUG="1" -VITE_VUE_APP_ISTEST=1 -DIRECTORY_LOCAL="myprojplanet_vite" -DIRECTORY_SERVER="/var/www/nodejs_test.riso_server" -SERVERDIR_WEBSITE="/var/www/test.nuovomondo.app" +VITE_DEBUG="0" +VITE_VUE_APP_ISTEST="0" +DIRECTORY_LOCAL=myprojplanet_vite +DIRECTORY_SERVER=/var/www/nodejs_riso_server +SERVERDIR_WEBSITE="/var/www/riso.app" SERVERPW_WEBSITE="pwdadmin@1AOK" \ No newline at end of file diff --git a/scripts/_ALL_SITES/nuovomondo.app/package.json b/scripts/_ALL_SITES/nuovomondo.app/package.json index 62406772..e7afb75a 100755 --- a/scripts/_ALL_SITES/nuovomondo.app/package.json +++ b/scripts/_ALL_SITES/nuovomondo.app/package.json @@ -1,6 +1,6 @@ { "name": "nuovomondo", - "version": "1.2.68", + "version": "1.2.69", "description": "Nuovo Mondo", "productName": "Nuovo Mondo", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8083 APP_VERSION='1.2.68' quasar dev", + "dev": "APP_VERSION='1.2.69' PORT=8083 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,74 +21,74 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", "postinstall": "quasar prepare" }, "dependencies": { - "@cubejs-client/core": "^1.2.26", - "@quasar/extras": "^1.16.17", + "@cubejs-client/core": "^1.3.21", + "@quasar/extras": "^1.17.0", "@quasar/quasar-ui-qcalendar": "^4.1.2", "@types/jsbarcode": "^3.11.4", - "@types/leaflet": "^1.9.17", - "@vue/compat": "^3.5.13", - "@vue/compiler-sfc": "^3.5.13", + "@types/leaflet": "^1.9.18", + "@vue/compat": "^3.5.16", + "@vue/compiler-sfc": "^3.5.16", "@vuelidate/core": "^2.0.3", "@vuelidate/validators": "^2.0.4", - "acorn": "^8.14.1", + "acorn": "^8.15.0", "animate.css": "^4.1.1", + "apexcharts": "^4.7.0", "autoprefixer": "^10.4.21", - "axios": "^1.8.4", + "axios": "^1.9.0", "bcryptjs": "^3.0.2", - "chart.js": "^4.4.8", - "core-js": "^3.41.0", + "chart.js": "^4.4.9", + "core-js": "^3.43.0", "crypto-browserify": "^3.12.1", "date-fns": "^4.1.0", "echarts": "5.6.0", - "eslint-plugin-n": "^17.16.2", + "eslint-plugin-n": "^17.19.0", "eslint-plugin-quasar": "^1.1.0", - "graphql": "^16.10.0", - "graphql-tag": "^2.12.6", - "gsap": "^3.12.7", + "gsap": "^3.13.0", "html2pdf.js": "^0.10.3", "jquery": "^3.7.1", "js-cookie": "^3.0.5", - "jsbarcode": "^3.11.6", + "jsbarcode": "^3.12.1", "leaflet": "^1.9.4", "leaflet-routing-machine": "^3.2.12", "leaflet.markercluster": "^1.5.3", "localforage": "^1.10.0", "lodash": "^4.17.21", + "mongoose-paginate-v2": "^1.9.1", "normalize.css": "^8.0.1", "nprogress": "^0.2.0", - "pinia": "^3.0.1", - "qrcode-vue3": "^1.7.1", + "pinia": "^3.0.3", "quasar": "^2.18.1", "quasar-extras": "^2.0.9", "register-service-worker": "^1.7.2", "scrollreveal": "^4.0.9", - "typescript-eslint": "^8.27.0", - "vee-validate": "^4.15.0", - "vue": "^3.5.13", + "typescript-eslint": "^8.34.0", + "vee-validate": "^4.15.1", + "vue": "^3.5.16", "vue-class-component": "^8.0.0-rc.1", "vue-country-code": "^1.1.3", "vue-echarts": "^7.0.3", - "vue-i18n": "^11.1.2", + "vue-i18n": "^11.1.5", "vue-idb": "^0.2.0", - "vue-image-zoomer": "^2.4.4", "vue-property-decorator": "^10.0.0-rc.3", - "vue-router": "^4.5.0", + "vue-router": "^4.5.1", "vue-scroll-reveal": "^2.1.0", "vue-social-sharing": "^4.0.0-alpha4", "vue-svgicon": "^4.0.0-alpha.3", "vue-timeago3": "^2.3.2", "vue2-dragula": "^2.5.5", - "vue3-pdf-app": "^1.0.3", + "vue3-apexcharts": "^1.8.0", "vue3-qr-reader": "^1.0.0", + "vuedraggable": "^4.1.0", "vuex": "^4.1.0", + "xlsx": "^0.18.5", "vuex-router-sync": "^6.0.0-rc.1", "workbox-core": "^7.3.0", "workbox-precaching": "^7.3.0", @@ -97,41 +97,41 @@ "workbox-window": "^7.3.0" }, "devDependencies": { - "@eslint/js": "^9.23.0", - "@intlify/unplugin-vue-i18n": "^6.0.5", - "@quasar/app-vite": "^2.1.4", + "@eslint/js": "^9.28.0", + "@intlify/unplugin-vue-i18n": "^6.0.8", + "@quasar/app-vite": "^2.2.1", "@types/google.maps": "^3.58.1", "@types/jest": "^29.5.14", "@types/js-cookie": "^3.0.6", - "@types/node": "^22.13.11", + "@types/node": "^24.0.1", "@types/nprogress": "^0.2.3", "@types/vue-tel-input": "^2.1.7", "@types/vuelidate": "^0.7.22", - "@vue/devtools": "^7.7.2", + "@vue/devtools": "^7.7.6", "@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-typescript": "^14.5.0", "autoprefixer": "^10.4.21", "eslint": "9", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-vue": "^10.0.0", + "eslint-plugin-vue": "^10.2.0", "file-loader": "^6.2.0", - "globals": "^16.0.0", - "http-proxy-middleware": "^3.0.3", - "jest": "^29.7.0", + "globals": "^16.2.0", + "http-proxy-middleware": "^3.0.5", + "jest": "^30.0.0", "json-loader": "^0.5.7", - "nodemon": "^3.1.9", - "npm-check-updates": "^17.1.16", - "parcel": "^2.14.1", - "postcss": "^8.5.3", + "nodemon": "^3.1.10", + "npm-check-updates": "^18.0.1", + "parcel": "^2.15.2", + "postcss": "^8.5.5", "postcss-loader": "^8.1.1", "prettier": "3", "strip-ansi": "=7.1.0", - "ts-jest": "^29.2.6", - "typescript": "5.7.3", - "vite-plugin-checker": "^0.9.1", + "ts-jest": "^29.4.0", + "typescript": "5.8.3", + "vite-plugin-checker": "^0.9.3", "vue-cli-plugin-element-ui": "^1.1.4", - "vue-eslint-parser": "^10.1.1", - "vue-tsc": "^2.2.8", + "vue-eslint-parser": "^10.1.3", + "vue-tsc": "^2.2.10", "vueify": "^9.4.1", "workbox-build": "^7.3.0" }, diff --git a/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json b/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json index 3c041ff4..ea9b4929 100755 --- a/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json +++ b/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json @@ -1,6 +1,6 @@ { "name": "nutriben", - "version": "1.2.68", + "version": "1.2.69", "description": "Nutriben", "productName": "Nutriben", "author": "Surya", @@ -9,20 +9,20 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8093 APP_VERSION='1.2.68' quasar dev", + "dev": "PORT=8093 APP_VERSION='1.2.69' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", - "buildspa": "APP_VERSION='1.2.68' quasar build -m spa", + "buildspa": "APP_VERSION='1.2.69' quasar build -m spa", "lint": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\"", "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/piuchebuono.app/package.json b/scripts/_ALL_SITES/piuchebuono.app/package.json index 969ef04c..f3876221 100755 --- a/scripts/_ALL_SITES/piuchebuono.app/package.json +++ b/scripts/_ALL_SITES/piuchebuono.app/package.json @@ -1,6 +1,6 @@ { "name": "piuchebuono", - "version": "1.2.68", + "version": "1.2.69", "description": "PiuCheBuono", "productName": "PiuCheBuono", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8085 APP_VERSION='1.2.68' quasar dev", + "dev": "PORT=8085 APP_VERSION='1.2.69' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/riso.app/package.json b/scripts/_ALL_SITES/riso.app/package.json index 305a8499..6b598026 100755 --- a/scripts/_ALL_SITES/riso.app/package.json +++ b/scripts/_ALL_SITES/riso.app/package.json @@ -1,6 +1,6 @@ { "name": "riso", - "version": "1.2.68", + "version": "1.2.69", "productName": "Riso 💚 - Rete Italiana Scambi Orizzontali", "description": "Progetto RISO (Rete Italiana Scambi Orizzontali) promuove una rete di comunità locali che favoriscono scambi di beni, servizi e ospitalità. Con l'App RISO, sviluppata per facilitare il baratto, il dono e l'uso di monete alternative come i RIS, il progetto crea legami autentici basati sulla fiducia e sostenibilità. Partecipa agli scambi e costruisci una comunità più consapevole e autosufficiente.", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "APP_VERSION='1.2.68' PORT=8084 quasar dev", + "dev": "APP_VERSION='1.2.69' PORT=8084 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.68' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.69' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.68' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.68' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.69' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.69' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/now.txt b/scripts/now.txt index ac64beb6..1e23559a 100644 --- a/scripts/now.txt +++ b/scripts/now.txt @@ -1 +1 @@ -TERMINA DI LAVORARE SU nuovomondo.app: (Sovrascrivo!) +TERMINA DI LAVORARE SU riso.app: (Sovrascrivo!) diff --git a/src-pwa/custom-service-worker.js b/src-pwa/custom-service-worker.js index d8b1d31d..a5ca5d8f 100755 --- a/src-pwa/custom-service-worker.js +++ b/src-pwa/custom-service-worker.js @@ -3,7 +3,7 @@ /* global workbox */ /* global cfgenv */ -const VITE_APP_VERSION = '1.2.68'; +const VITE_APP_VERSION = '1.2.69'; // Costanti di configurazione const DYNAMIC_CACHE = 'dynamic-cache-v2'; diff --git a/src/common/shared_vuejs.ts b/src/common/shared_vuejs.ts index 400d728b..0f483b48 100755 --- a/src/common/shared_vuejs.ts +++ b/src/common/shared_vuejs.ts @@ -174,6 +174,9 @@ export const shared_consts = { SEARCHPRODUCT: 430, RACCOLTE_CATALOGHI: 450, STAT_PAGES: 460, + SECTION: 1000, + ROW: 1100, + COLUMN: 1200, }, QUERYTYPE_MYGROUP: 1, @@ -2008,6 +2011,22 @@ export const shared_consts = { ], TypesElem: [ + { + value: 1000, //ELEMTYPE.SECTION, + label: 'Sezione', + icon: 'fas fa-th-large', + }, + { + value: 1100, //ELEMTYPE.ROW, + label: 'Riga', + icon: 'fas fa-th-large', + }, + { + value: 1200, // ELEMTYPE.COLUMN, + label: 'Colonna', + icon: 'fas fa-th-large', + }, + { value: 20, label: 'Testo', diff --git a/src/components/CCardDiscipline/CCardDiscipline.ts b/src/components/CCardDiscipline/CCardDiscipline.ts index 783b4dd7..8c6f3360 100755 --- a/src/components/CCardDiscipline/CCardDiscipline.ts +++ b/src/components/CCardDiscipline/CCardDiscipline.ts @@ -11,6 +11,7 @@ import { CMyTeacher } from '@src/components/CMyTeacher' // @ts-ignore import MixinOperator from '../../mixins/mixin-operator' import MixinUsers from '../../mixins/mixin-users' +import { useI18n } from 'vue-i18n'; export default defineComponent({ name: 'CCardDiscipline', diff --git a/src/components/CCart/CCart.ts b/src/components/CCart/CCart.ts index 2e0446d2..5814395e 100755 --- a/src/components/CCart/CCart.ts +++ b/src/components/CCart/CCart.ts @@ -357,7 +357,7 @@ export default defineComponent({ recOrderCart.value = rissconto.mycart }; } - } catch (error) { + } catch (error: any) { console.log('error ApplicaSconto', error); tools.showNegativeNotif($q, `Sconto Non Applicato! ${error?.message || ''}`); codice_sconto.value = ''; diff --git a/src/components/CColumn/CColumn.vue b/src/components/CColumn/CColumn.vue new file mode 100644 index 00000000..587b1ec4 --- /dev/null +++ b/src/components/CColumn/CColumn.vue @@ -0,0 +1,19 @@ + + + + + diff --git a/src/components/CGallery/CGallery.ts b/src/components/CGallery/CGallery.ts index 7d546013..f79c233f 100755 --- a/src/components/CGallery/CGallery.ts +++ b/src/components/CGallery/CGallery.ts @@ -426,6 +426,7 @@ export default defineComponent({ function isIMG() { return props.filetype === shared_consts.FILETYPE.IMG; } + /* const uploadFactory = async (files: readonly File[]) => { const userStore = useUserStore(); const url = getUrl(); @@ -451,11 +452,11 @@ export default defineComponent({ // usa la tua logica centralizzata Api.checkTokenScaduto( status, - /*evitaloop*/ false, + false, url, 'POST', null, - /*setAuthToken*/ true + true ); if (ret !== null) { // token aggiornato -> ritenta UNA volta @@ -475,7 +476,7 @@ export default defineComponent({ throw err2; } } - }; + }; */ onMounted(created); @@ -514,7 +515,6 @@ export default defineComponent({ isIMG, isPDF, upl, - uploadFactory, t, }; }, diff --git a/src/components/CMapUsers/CMapUsers.vue b/src/components/CMapUsers/CMapUsers.vue index 1bc2c8b7..efd9b081 100755 --- a/src/components/CMapUsers/CMapUsers.vue +++ b/src/components/CMapUsers/CMapUsers.vue @@ -1,44 +1,35 @@ - - diff --git a/src/components/CMyEditElem/CMyEditElem.ts b/src/components/CMyEditElem/CMyEditElem.ts index eb42d53f..16dbb255 100755 --- a/src/components/CMyEditElem/CMyEditElem.ts +++ b/src/components/CMyEditElem/CMyEditElem.ts @@ -628,6 +628,15 @@ export default defineComponent({ ); } + function isLayoutContainer() { + const t = myel.value?.type; + return ( + t === shared_consts.ELEMTYPE.SECTION || + t === shared_consts.ELEMTYPE.ROW || + t === shared_consts.ELEMTYPE.COLUMN + ); + } + /*function updateElem(myvalue: any) { console.log('updateElem', myvalue) if (myel.value.type === shared_consts.ELEMTYPE.IMGTITLE) { diff --git a/src/components/CMyElem/CMyElem.ts b/src/components/CMyElem/CMyElem.ts index 16729296..fcc7ae42 100755 --- a/src/components/CMyElem/CMyElem.ts +++ b/src/components/CMyElem/CMyElem.ts @@ -1,87 +1,122 @@ import type { PropType } from 'vue'; -import { - computed, - defineComponent, onMounted, ref, toRef, watch, nextTick, -} from 'vue' +import { computed, defineComponent, onMounted, ref, toRef, watch, nextTick } from 'vue'; import type { IOptCatalogo, ICoordGPS, IMyElem, ISocial } from '@src/model'; -import { IMyCard, IMyPage, IOperators } from '@src/model' -import { useGlobalStore } from '@store/globalStore' +import { IMyCard, IMyPage, IOperators } from '@src/model'; +import { useGlobalStore } from '@store/globalStore'; -import { CImgTitle } from '../CImgTitle/index' -import { CImgPoster } from '@src/components/CImgPoster' -import { CTitle } from '@src/components/CTitle/index' -import { CGridOriz } from '@src/components/CGridOriz/index' -import { ChatBot } from '@src/components/ChatBot/index' -import { CCatalogList } from '@src/components/CCatalogList/index' -import { CRaccoltaCataloghi } from '@src/components/CRaccoltaCataloghi/index' -import { tools } from '@tools' -import { shared_consts } from '@src/common/shared_vuejs' -import { LandingFooter } from '@src/components/LandingFooter' -import { CMyActivities } from '@src/components/CMyActivities' -import { CECommerce } from '@src/components/CECommerce' -import { CStatMacro } from '@src/components/CStatMacro' -import { CSearchProduct } from '@src/components/CSearchProduct' -import { CPageViewStats } from '@src/components/CPageViewStats' -import { CQRCode } from '@src/components/CQRCode' -import { CAITools } from '@src/components/CAITools' -import { CCatalogo } from '@src/components/CCatalogo' -import { CRaccolta } from '@src/components/CRaccolta' +import { CImgTitle } from '../CImgTitle/index'; +import { CImgPoster } from '@src/components/CImgPoster'; +import CSection from '@src/components/CSection/CSection.vue'; +import CRow from '@src/components/CRow/CRow.vue'; +import CColumn from '@src/components/CColumn/CColumn.vue'; +import { CTitle } from '@src/components/CTitle/index'; +import { CGridOriz } from '@src/components/CGridOriz/index'; +import { ChatBot } from '@src/components/ChatBot/index'; +import { CCatalogList } from '@src/components/CCatalogList/index'; +import { CRaccoltaCataloghi } from '@src/components/CRaccoltaCataloghi/index'; +import { tools } from '@tools'; +import { shared_consts } from '@src/common/shared_vuejs'; +import { LandingFooter } from '@src/components/LandingFooter'; +import { CMyActivities } from '@src/components/CMyActivities'; +import { CECommerce } from '@src/components/CECommerce'; +import { CStatMacro } from '@src/components/CStatMacro'; +import { CSearchProduct } from '@src/components/CSearchProduct'; +import { CPageViewStats } from '@src/components/CPageViewStats'; +import { CQRCode } from '@src/components/CQRCode'; +import { CAITools } from '@src/components/CAITools'; +import { CCatalogo } from '@src/components/CCatalogo'; +import { CRaccolta } from '@src/components/CRaccolta'; // import { CMapMarker } from '@src/components/CMapMarker.off' -import { CMapUsers } from '@src/components/CMapUsers' -import { CMapGetCoordinates } from '@src/components/CMapGetCoordinates' -import { CMapEditAddressByCoord } from '@src/components/CMapEditAddressByCoord' -import { CMapComuni } from '@src/components/CMapComuni' -import { COpenStreetMap } from '@src/components/COpenStreetMap' -import { CCardCarousel } from '@src/components/CCardCarousel' -import { CMyPage } from '@src/components/CMyPage' -import { CMyPageIntro } from '@src/components/CMyPageIntro' -import { CEventsCalendar } from '@src/components/CEventsCalendar' -import { CMyEditor } from '@src/components/CMyEditor' -import { CMyFieldRec } from '@src/components/CMyFieldRec' -import { CSelectColor } from '@src/components/CSelectColor' -import { CMainView } from '@src/components/CMainView' -import { CMyProfileTutorial } from '@src/components/CMyProfileTutorial' -import { CSendRISTo } from '@src/components/CSendRISTo' -import { CDashboard } from '@src/components/CDashboard' -import { CDashGroup } from '@src/components/CDashGroup' -import { CMovements } from '@src/components/CMovements' -import { CCheckAppRunning } from '@src/components/CCheckAppRunning' -import { CStatusReg } from '@src/components/CStatusReg' -import { CTitleBanner } from '@src/components/CTitleBanner' -import { CCheckIfIsLogged } from '@src/components/CCheckIfIsLogged' -import { CSelectFontSize } from '@src/components/CSelectFontSize' -import { CNotifAtTop } from '@src/components/CNotifAtTop' -import { CPresentazione } from '@src/components/CPresentazione' -import { CRegistration } from '@src/components/CRegistration' -import { CShareSocial } from '@src/components/CShareSocial' -import { CVisuVideoPromoAndPDF } from '@src/components/CVisuVideoPromoAndPDF' +import { CMapUsers } from '@src/components/CMapUsers'; +import { CMapGetCoordinates } from '@src/components/CMapGetCoordinates'; +import { CMapEditAddressByCoord } from '@src/components/CMapEditAddressByCoord'; +import { CMapComuni } from '@src/components/CMapComuni'; +import { COpenStreetMap } from '@src/components/COpenStreetMap'; +import { CCardCarousel } from '@src/components/CCardCarousel'; +import { CMyPage } from '@src/components/CMyPage'; +import { CMyPageIntro } from '@src/components/CMyPageIntro'; +import { CEventsCalendar } from '@src/components/CEventsCalendar'; +import { CMyEditor } from '@src/components/CMyEditor'; +import { CMyFieldRec } from '@src/components/CMyFieldRec'; +import { CSelectColor } from '@src/components/CSelectColor'; +import { CMainView } from '@src/components/CMainView'; +import { CMyProfileTutorial } from '@src/components/CMyProfileTutorial'; +import { CSendRISTo } from '@src/components/CSendRISTo'; +import { CDashboard } from '@src/components/CDashboard'; +import { CDashGroup } from '@src/components/CDashGroup'; +import { CMovements } from '@src/components/CMovements'; +import { CCheckAppRunning } from '@src/components/CCheckAppRunning'; +import { CStatusReg } from '@src/components/CStatusReg'; +import { CTitleBanner } from '@src/components/CTitleBanner'; +import { CCheckIfIsLogged } from '@src/components/CCheckIfIsLogged'; +import { CSelectFontSize } from '@src/components/CSelectFontSize'; +import { CNotifAtTop } from '@src/components/CNotifAtTop'; +import { CPresentazione } from '@src/components/CPresentazione'; +import { CRegistration } from '@src/components/CRegistration'; +import { CShareSocial } from '@src/components/CShareSocial'; +import { CVisuVideoPromoAndPDF } from '@src/components/CVisuVideoPromoAndPDF'; -import MixinMetaTags from '@src/mixins/mixin-metatags' -import MixinBase from '@src/mixins/mixin-base' -import { useQuasar } from 'quasar' -import { useI18n } from 'vue-i18n' -import { useRouter } from 'vue-router' -import { LatLng } from 'leaflet' - -import { costanti } from '@costanti' +import MixinMetaTags from '@src/mixins/mixin-metatags'; +import MixinBase from '@src/mixins/mixin-base'; +import { useQuasar } from 'quasar'; +import { useI18n } from 'vue-i18n'; +import { useRouter } from 'vue-router'; +import { LatLng } from 'leaflet'; +import { costanti } from '@costanti'; export default defineComponent({ name: 'CMyElem', components: { - CImgTitle, CTitle, LandingFooter, CEventsCalendar, - CCardCarousel, COpenStreetMap, CMyPage, CMyPageIntro, CMyEditor, CMyFieldRec, - CSelectColor, CSelectFontSize, CImgPoster, - CCheckIfIsLogged, CStatusReg, CDashboard, CMainView, CNotifAtTop, - CPresentazione, CMyActivities, - CMyProfileTutorial, CSendRISTo, - CTitleBanner, CShareSocial, CCheckAppRunning, CRegistration, - CVisuVideoPromoAndPDF, CECommerce, CCatalogo, CRaccolta, CAITools, CStatMacro, - CMapComuni, CMapUsers, CMapGetCoordinates, CMapEditAddressByCoord, - CDashGroup, CMovements, CGridOriz, CQRCode, CCatalogList, - CSearchProduct, CRaccoltaCataloghi, CPageViewStats, + CImgTitle, + CTitle, + LandingFooter, + CEventsCalendar, + CCardCarousel, + COpenStreetMap, + CMyPage, + CMyPageIntro, + CMyEditor, + CMyFieldRec, + CSelectColor, + CSelectFontSize, + CImgPoster, + CCheckIfIsLogged, + CStatusReg, + CDashboard, + CMainView, + CNotifAtTop, + CPresentazione, + CMyActivities, + CMyProfileTutorial, + CSendRISTo, + CTitleBanner, + CShareSocial, + CCheckAppRunning, + CRegistration, + CVisuVideoPromoAndPDF, + CECommerce, + CCatalogo, + CRaccolta, + CAITools, + CStatMacro, + CMapComuni, + CMapUsers, + CMapGetCoordinates, + CMapEditAddressByCoord, + CDashGroup, + CMovements, + CGridOriz, + CQRCode, + CCatalogList, + CSearchProduct, + CRaccoltaCataloghi, + CPageViewStats, ChatBot, + CSection, + CRow, + CColumn, // , //CMapMarker, }, emits: ['selElemClick'], @@ -116,205 +151,212 @@ export default defineComponent({ }, }, setup(props, { emit }) { - const globalStore = useGlobalStore() + const globalStore = useGlobalStore(); - const { setmeta, getsrcbyimg } = MixinMetaTags() - const { setValDb, getValDb } = MixinBase() + const { setmeta, getsrcbyimg } = MixinMetaTags(); + const { setValDb, getValDb } = MixinBase(); - const $router = useRouter() + const $router = useRouter(); - const $q = useQuasar() - const { t } = useI18n() + const $q = useQuasar(); + const { t } = useI18n(); - const animare = ref(0) - const animarecard = ref(0) - const slide = ref(0) - const slide2 = ref(0) - const disableSave = ref(true) - const enableEdit = ref(false) - const enableAdd = ref(true) - const visushare = ref(false) + const animare = ref(0); + const animarecard = ref(0); + const slide = ref(0); + const slide2 = ref(0); + const disableSave = ref(true); + const enableEdit = ref(false); + const enableAdd = ref(true); + const visushare = ref(false); - const tabcatalogo = ref('griglia') + const tabcatalogo = ref('griglia'); - const social = ref({}) + const social = ref({}); - const neworder = ref(0) + const neworder = ref(0); - const myel = ref({}) + const myel = ref({}); - const newtype = ref('') + const newtype = ref(''); - const isAppRunning = computed(() => globalStore.isAppRunning) + const isAppRunning = computed(() => globalStore.isAppRunning); const currentCardsPerSlide = computed(() => { - return myel.value.num2 ? myel.value.num2 : 2 // cardsPerSlide - }) + return myel.value.num2 ? myel.value.num2 : 2; // cardsPerSlide + }); // Raggruppa le card in base al numero di card per slide const cardGroups = computed(() => { - const cards = myel.value.listcards || [] - const groups = [] + const cards = myel.value.listcards || []; + const groups = []; for (let i = 0; i < cards.length; i += currentCardsPerSlide.value) { - groups.push(cards.slice(i, i + currentCardsPerSlide.value)) + groups.push(cards.slice(i, i + currentCardsPerSlide.value)); } - return groups - }) + return groups; + }); - const coordaddr = ref({ address: '', coordinates: [0, 0] }) + const coordaddr = ref({ address: '', coordinates: [0, 0] }); + const speedSafe = computed(() => (myel.value as any).speed ?? 0); - const carouselRef = ref(null) - const isAtStart = ref(true) - const isAtEnd = ref(false) - const activeIndex = ref(0) + const carouselRef = ref(null); + const isAtStart = ref(true); + const isAtEnd = ref(false); + const activeIndex = ref(0); - watch(() => myel.value.order, (value, oldval) => { - mounted() - }) + watch( + () => myel.value.order, + (value, oldval) => { + mounted(); + } + ); function getArrDisciplines() { - return globalStore.disciplines.filter((rec: any) => rec.showinhome) + return globalStore.disciplines.filter((rec: any) => rec.showinhome); } function getheightgallery() { - if (tools.isMobile()) - return '400px' - else - return '600px' + if (tools.isMobile()) return '400px'; + else return '600px'; } function saveElem(exit?: boolean) { // Save Elem record - const myelem = props.myelem - myelem.order = neworder.value + const myelem = props.myelem; + myelem.order = neworder.value; globalStore.saveMyElem($q, t, myelem).then((ris) => { if (ris) { // OK - disableSave.value = true - if (exit) - enableEdit.value = false + disableSave.value = true; + if (exit) enableEdit.value = false; } - }) + }); } function addNewElem(order?: number) { - - const newrec = globalStore.prepareAddNewElem(order, $q, t, props.myelem, newtype.value) + const newrec = globalStore.prepareAddNewElem( + order, + $q, + t, + props.myelem, + newtype.value + ); } function dupElem(order?: number) { + const newrec = props.myelem; - const newrec = props.myelem + newrec._id = undefined; + newrec.order = order ? order : newrec.order! + 10; - newrec._id = undefined - newrec.order = order ? order : (newrec.order! + 10) - - globalStore.addNewElem($q, t, newrec) + globalStore.addNewElem($q, t, newrec); } function modifElem() { - disableSave.value = false + disableSave.value = false; } const checkScrollPosition = () => { - const container = carouselRef.value - if (!container || !myel.value || !myel.value.listcards) return + const container = carouselRef.value; + if (!container || !myel.value || !myel.value.listcards) return; - isAtStart.value = container.scrollLeft <= 0 - isAtEnd.value = container.scrollLeft + container.clientWidth >= container.scrollWidth - 1 + isAtStart.value = container.scrollLeft <= 0; + isAtEnd.value = + container.scrollLeft + container.clientWidth >= container.scrollWidth - 1; - const cardWidth = container.scrollWidth / myel.value.listcards.length - activeIndex.value = Math.round(container.scrollLeft / cardWidth) - } + const cardWidth = container.scrollWidth / myel.value.listcards.length; + activeIndex.value = Math.round(container.scrollLeft / cardWidth); + }; function mounted() { - myel.value = props.myelem - neworder.value = props.myelem.order + myel.value = props.myelem; + neworder.value = props.myelem.order; - if (props.myelem) - newtype.value = props.myelem.type + if (props.myelem) newtype.value = props.myelem.type; nextTick(() => { - checkScrollPosition() - carouselRef.value?.addEventListener('scroll', checkScrollPosition) - }) + checkScrollPosition(); + carouselRef.value?.addEventListener('scroll', checkScrollPosition); + }); } function clickOnElem() { if (props.editOn) { - enableEdit.value = true + enableEdit.value = true; // console.log('selElemClick', props.myelem) - emit('selElemClick', props.myelem) + emit('selElemClick', props.myelem); } } function getClass() { - let mycl = '' + let mycl = ''; if (props.myelem.align === shared_consts.ALIGNTYPE.CEHTER) { - mycl += ' align_center' + mycl += ' align_center'; } else if (props.myelem.align === shared_consts.ALIGNTYPE.RIGHT) { - mycl += ' align_right' + mycl += ' align_right'; } else if (props.myelem.align === shared_consts.ALIGNTYPE.LEFT) { - mycl += ' align_left' + mycl += ' align_left'; } - if (props.myelem.class2) - mycl += ' ' + props.myelem.class2 + if (props.myelem.class2) mycl += ' ' + props.myelem.class2; if (props.selElem && props.editOn) { - if (props.myelem._id === props.selElem._id) - mycl += ' selectedElem' + if (props.myelem._id === props.selElem._id) mycl += ' selectedElem'; } - return mycl + return mycl; } function showFit() { if (props.myelem && props.myelem.type) - return [shared_consts.ELEMTYPE.TEXT].includes(props.myelem.type) - else - return false + return [shared_consts.ELEMTYPE.TEXT].includes(props.myelem.type); + else return false; } function PagLogin() { - $router.replace('/signin') + $router.replace('/signin'); } async function clickshare() { - tools.addToTemporaryLinkReg() + tools.addToTemporaryLinkReg(); const mytext = await tools.sendMsgTelegramCmd( $q, t, shared_consts.MsgTeleg.SHARE_MSGREG, true - ) + ); if (false) { - social.value.description = mytext - visushare.value = true + social.value.description = mytext; + visushare.value = true; } - } // Classe per le colonne delle card function cardColumnClass() { - const width = 12 / currentCardsPerSlide.value - return `col-${width}` + const width = 12 / currentCardsPerSlide.value; + return `col-${width}`; } - function updateCatalogoEmit(updatedCatalogo: IOptCatalogo) { - console.log('CMyElem: updateCatalogoEmit') - myel.value.catalogo = updatedCatalogo +function updateCatalogoEmit(updatedCatalogo?: IOptCatalogo) { + if (!updatedCatalogo) return; + console.log('CMyElem: updateCatalogoEmit'); + myel.value.catalogo = updatedCatalogo; +} + + function naviga(path?: string): void { + if (path) { + $router.push(path); + } else { + // default fallback route + $router.push('/'); + } } - function naviga(path: string) { - $router.push(path) - } - - onMounted(mounted) + onMounted(mounted); return { tools, @@ -359,8 +401,8 @@ export default defineComponent({ tabcatalogo, costanti, naviga, + speedSafe, t, - } + }; }, - -}) +}); diff --git a/src/components/CMyElem/CMyElem.vue b/src/components/CMyElem/CMyElem.vue index 6eef3c39..2316a410 100755 --- a/src/components/CMyElem/CMyElem.vue +++ b/src/components/CMyElem/CMyElem.vue @@ -10,6 +10,37 @@ " >
+
+ +
+
diff --git a/src/components/CMyPage/CMyPage.ts b/src/components/CMyPage/CMyPage.ts index f5fbc023..59bd0423 100755 --- a/src/components/CMyPage/CMyPage.ts +++ b/src/components/CMyPage/CMyPage.ts @@ -57,7 +57,6 @@ export default defineComponent({ const load = async (): Promise => { // console.log('load', mypath.value) if (mypath.value !== '') rec.value = await globalStore.loadPage('/' + mypath.value, 'cmypage') - } watch(() => props.mypath, async (to: string, from: string) => { diff --git a/src/components/CMyPageElem/CMyPageElem.ts b/src/components/CMyPageElem/CMyPageElem.ts index 23111a85..1af00606 100755 --- a/src/components/CMyPageElem/CMyPageElem.ts +++ b/src/components/CMyPageElem/CMyPageElem.ts @@ -78,7 +78,7 @@ export default defineComponent({ const { t } = useI18n(); const globalStore = useGlobalStore(); const $router = useRouter(); - const $route = useRoute() + const $route = useRoute(); const mywidthEditor = ref(400); @@ -125,6 +125,12 @@ export default defineComponent({ async function load() { console.log('load', mypathin.value, 'idapp', tools.getEnv('VITE_APP_ID')); + const query = $router.currentRoute.value.query + + if (query.edit === '1') { + globalStore.editOn = true; + } + if (mypathin.value !== '') { onloading.value = true; await globalStore.loadPage('/' + mypathin.value, 'cmypageelem').then((ris) => { diff --git a/src/components/CRow/CRow.vue b/src/components/CRow/CRow.vue new file mode 100644 index 00000000..b30163db --- /dev/null +++ b/src/components/CRow/CRow.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/src/components/CSection/CSection.vue b/src/components/CSection/CSection.vue new file mode 100644 index 00000000..b28e69b2 --- /dev/null +++ b/src/components/CSection/CSection.vue @@ -0,0 +1,19 @@ + + + + + diff --git a/src/components/CSingleCart/CSingleCart.ts b/src/components/CSingleCart/CSingleCart.ts index e5c042e7..9c9579f5 100755 --- a/src/components/CSingleCart/CSingleCart.ts +++ b/src/components/CSingleCart/CSingleCart.ts @@ -170,7 +170,7 @@ export default defineComponent({ function removeFromCard() { $q.dialog({ - title: order.value.product.productInfo.name, + title: order.value.product?.productInfo?.name, message: 'Sicuro di voler rimuovere il prodotto dal carrello?', ok: { label: 'Rimuovi', @@ -222,7 +222,7 @@ export default defineComponent({ function mounted() { endload.value = false; - weight.value = props.order.product?.productInfo.weight; + weight.value = props.order.product?.productInfo?.weight; price.value = props.order.price; if (props.order.quantity !== 0) { orderQuantity.value = props.order.quantity; diff --git a/src/components/IconPicker/IconPicker.ts b/src/components/IconPicker/IconPicker.ts index 804fea59..fd11c03a 100644 --- a/src/components/IconPicker/IconPicker.ts +++ b/src/components/IconPicker/IconPicker.ts @@ -1,10 +1,4 @@ -import { defineComponent, ref, computed, onMounted, watch, onBeforeUnmount } from 'vue' - -import { useUserStore } from '@store/UserStore' -import { useQuasar } from 'quasar' -import { useI18n } from 'vue-i18n' -import { tools } from '@tools' -import { useRouter } from 'vue-router' +import { defineComponent, ref, computed, watch } from 'vue' export default defineComponent({ name: 'IconPicker', @@ -12,49 +6,75 @@ export default defineComponent({ modelValue: { type: String, default: '' }, icons: { type: Array as () => string[], - default: () => ([ - // Estendi pure questo set - 'fas fa-house', + // SOLO Font Awesome 5 (free) + default: () => [ + 'fas fa-home', 'fas fa-book', 'fas fa-star', 'fas fa-heart', 'fas fa-user', - 'fas fa-gear', - 'fas fa-circle-info', - 'fas fa-newspaper', + 'fas fa-cog', + 'fas fa-info-circle', + 'far fa-newspaper', 'fas fa-list', 'fas fa-tags', 'fas fa-chart-line', 'fas fa-briefcase', 'fas fa-envelope', 'fas fa-phone', - 'fas fa-earth-europe', - ]) + 'fas fa-globe-europe' + ] } }, emits: ['update:modelValue', 'change'], setup (props, { emit }) { - const keyword = ref('') - const local = ref(props.modelValue) + const local = ref(props.modelValue) // testo inserito/valore corrente + const dialog = ref(false) // mostra/nasconde il picker + const keyword = ref('') // filtro dentro il dialog watch(() => props.modelValue, v => { local.value = v }) const filteredIcons = computed(() => { const k = keyword.value.trim().toLowerCase() if (!k) return props.icons - return props.icons.filter(i => i.toLowerCase().includes(k)) + return props.icons.filter(i => + i.toLowerCase().includes(k) || + // match anche sul nome “breve” (es: 'home') + i.toLowerCase().split(' ').some(cls => cls.startsWith('fa-') && cls.includes(k)) + ) }) function select (val: string) { - local.value = val - emit('update:modelValue', val) - emit('change', val) + // applica la stringa così com’è; nessun fallback + emit('update:modelValue', val || '') + emit('change', val || '') } - function onKeyword () { - // solo aggiorna la lista; il pulsante "Usa testo" applica + function choose (ic: string) { + local.value = ic || '' + select(local.value) + dialog.value = false } - return { keyword, local, filteredIcons, select, onKeyword } + function clear () { + local.value = '' + select('') + } + + function openPicker () { + keyword.value = '' + dialog.value = true + } + + return { + local, + dialog, + keyword, + filteredIcons, + select, + choose, + clear, + openPicker + } } }) diff --git a/src/components/IconPicker/IconPicker.vue b/src/components/IconPicker/IconPicker.vue index 515e84f5..dbecc4fc 100644 --- a/src/components/IconPicker/IconPicker.vue +++ b/src/components/IconPicker/IconPicker.vue @@ -1,67 +1,86 @@ diff --git a/src/components/MenuPageItem/MenuPageItem.scss b/src/components/MenuPageItem/MenuPageItem.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/components/MenuPageItem/MenuPageItem.ts b/src/components/MenuPageItem/MenuPageItem.ts new file mode 100644 index 00000000..17a3b540 --- /dev/null +++ b/src/components/MenuPageItem/MenuPageItem.ts @@ -0,0 +1,50 @@ +import { defineComponent, ref, computed, onMounted, watch, onBeforeUnmount } from 'vue'; +import { IMyPage } from 'app/src/model'; + +type PageWithKey = IMyPage & { __key?: string }; + +export default defineComponent({ + name: 'MenuPageItem', + props: { + item: { type: Object as () => PageWithKey, required: true }, + selected: { type: Boolean, default: false }, + active: { type: Boolean, default: false }, // v-model:active + variant: { type: String as () => 'menu' | 'off', default: 'menu' }, + showGrip: { type: Boolean, default: true }, + draggableHandleClass: { type: String, default: 'drag-handle' }, + depth: { type: Number, default: 0 }, + }, + emits: ['select', 'edit', 'delete', 'open', 'update:active', 'update:item'], + setup(props, { emit }) { + function displayPath(path?: string) { + if (!path) return '-'; + return path.startsWith('/') ? path : '/' + path; + } + function emitSelect() { + emit('select', props.item.__key); + } + function emitEdit() { + emit('edit', props.item.__key); + } + function emitDelete() { + emit('delete', props.item.__key); + } + function emitOpen() { + emit('open', props.item.__key); + } + + const indentSpacerStyle = computed(() => { + const px = Math.min(props.depth, 6) * 16; // max 6 livelli x 16px + return { width: `${px}px`, minWidth: `${px}px` }; + }); + + return { + displayPath, + emitSelect, + emitEdit, + emitDelete, + emitOpen, + indentSpacerStyle, + }; + }, +}); diff --git a/src/components/MenuPageItem/MenuPageItem.vue b/src/components/MenuPageItem/MenuPageItem.vue new file mode 100644 index 00000000..481856f7 --- /dev/null +++ b/src/components/MenuPageItem/MenuPageItem.vue @@ -0,0 +1,144 @@ + + + + diff --git a/src/components/MenuPageItem/index.ts b/src/components/MenuPageItem/index.ts new file mode 100755 index 00000000..e4ad5080 --- /dev/null +++ b/src/components/MenuPageItem/index.ts @@ -0,0 +1 @@ +export {default as MenuPageItem} from './MenuPageItem.vue' diff --git a/src/components/PageEditor/PageEditor.ts b/src/components/PageEditor/PageEditor.ts index feae10e0..6a630ad2 100644 --- a/src/components/PageEditor/PageEditor.ts +++ b/src/components/PageEditor/PageEditor.ts @@ -1,141 +1,167 @@ import { - defineComponent, - ref, - computed, - onMounted, - watch, - onBeforeUnmount, - toRaw, - nextTick, -} from 'vue'; + defineComponent, ref, computed, watch, reactive, toRaw, nextTick +} from 'vue' +import { useQuasar } from 'quasar' +import IconPicker from '../IconPicker/IconPicker.vue' +import { IMyPage } from 'app/src/model' +import { useGlobalStore } from 'app/src/store' +import { storeToRefs } from 'pinia' +import { useI18n } from 'vue-i18n' +import { costanti } from '@costanti' -import { useUserStore } from '@store/UserStore'; -import { useQuasar } from 'quasar'; -import { useI18n } from 'vue-i18n'; -import { tools } from '@tools'; -import { useRouter } from 'vue-router'; -import { reactive } from 'vue'; -import { IMyPage } from 'app/src/model'; -import IconPicker from '../IconPicker/IconPicker.vue'; -import { useGlobalStore } from 'app/src/store'; -import { storeToRefs } from 'pinia'; +import { CMyFieldRec } from '@src/components/CMyFieldRec' export default defineComponent({ name: 'PageEditor', - components: { IconPicker }, + components: { IconPicker, CMyFieldRec }, props: { - modelValue: { - type: Object as () => IMyPage, - required: true, - }, + modelValue: { type: Object as () => IMyPage, required: true }, + nuovaPagina: { type: Boolean, required: true } // <-- modalità "bozza" }, - emits: ['update:modelValue', 'apply'], - setup(props, { emit }) { - const $q = useQuasar(); - const globalStore = useGlobalStore(); - const { mypage } = storeToRefs(globalStore); + emits: ['update:modelValue', 'apply', 'hide'], + setup (props, { emit }) { + const $q = useQuasar() - // DRaft locale - const draft = reactive({ ...props.modelValue }); + const { t } = useI18n() + const globalStore = useGlobalStore() + const { mypage } = storeToRefs(globalStore) + + // Draft locale indipendente dal parent (specie in nuovaPagina) + const draft = reactive({ ...props.modelValue }) // UI helper: path mostrato con "/" iniziale - const ui = reactive({ - pathText: toUiPath(draft.path), - }); + const ui = reactive({ pathText: toUiPath(draft.path) }) const saving = ref(false) - const syncingFromProps = ref(false) // <-- FLAG anti-loop + const syncingFromProps = ref(false) // anti-loop - // --- Watch input esterno: ricarica draft e UI path - // --- Watch input esterno: ricarica draft e UI path (NO scritture nello store qui!) + // --- Sync IN: quando cambia il valore del parent, aggiorna solo il draft watch( () => props.modelValue, - async (v) => { - syncingFromProps.value = true; - Object.assign(draft, v || {}); - ui.pathText = toUiPath(draft.path); - await nextTick(); - syncingFromProps.value = false; + async v => { + syncingFromProps.value = true + Object.assign(draft, v || {}) + ui.pathText = toUiPath(draft.path) + await nextTick() + syncingFromProps.value = false }, { deep: false } - ); + ) - // --- Ogni modifica del draft: aggiorna store.mypage e emetti update:modelValue (solo se modifica nasce da UI) + // --- Modifiche live: SE NON è nuovaPagina, aggiorna store e v-model del parent watch( draft, (val) => { - if (syncingFromProps.value) return; // evita ricorsione - upsertIntoStore(val, mypage.value); - emit('update:modelValue', { ...val }); + if (syncingFromProps.value) return + if (props.nuovaPagina) return // <-- blocca ogni propagazione durante "nuova pagina" + upsertIntoStore(val, mypage.value) + emit('update:modelValue', { ...val }) }, { deep: true } - ); + ) // --- Helpers path - function toUiPath(storePath?: string) { - const p = (storePath || '').trim(); - if (!p) return '/'; - return p.startsWith('/') ? p : `/${p}`; + function toUiPath (storePath?: string) { + const p = (storePath || '').trim() + if (!p) return '/' + return p.startsWith('/') ? p : `/${p}` } - function toStorePath(uiPath?: string) { - const p = (uiPath || '').trim(); - if (!p) return ''; - return p.startsWith('/') ? p.slice(1) : p; + function toStorePath (uiPath?: string) { + const p = (uiPath || '').trim() + if (!p) return '' + return p.startsWith('/') ? p.slice(1) : p + } + function normalizeAndApplyPath () { + // normalizza: niente spazi → trattini + let p = (ui.pathText || '/').trim() + p = p.replace(/\s+/g, '-') + if (!p.startsWith('/')) p = '/' + p + ui.pathText = p + draft.path = toStorePath(p) // NB: scrive sul draft (watch sopra gestisce la propagazione) } - function normalizeAndApplyPath() { - // normalizza: niente spazi, minuscole, trattini - let p = (ui.pathText || '/').trim(); - p = p.replace(/\s+/g, '-'); - if (!p.startsWith('/')) p = '/' + p; - ui.pathText = p; - draft.path = toStorePath(p); + function pathRule (v: string) { + if (!v) return 'Percorso richiesto' + if (!v.startsWith('/')) return 'Deve iniziare con /' + if (/\s/.test(v)) return 'Nessuno spazio nel path' + return true } - function pathRule(v: string) { - if (!v) return 'Percorso richiesto'; - if (!v.startsWith('/')) return 'Deve iniziare con /'; - if (/\s/.test(v)) return 'Nessuno spazio nel path'; - return true; + // --- Upsert nello store.mypage (usato solo quando NON è nuovaPagina o dopo il save) + function upsertIntoStore (page: IMyPage, arr: IMyPage[]) { + if (!page) return + const keyId = page._id + const keyPath = page.path || '' + let idx = -1 + if (keyId) idx = arr.findIndex(p => p._id === keyId) + if (idx < 0 && keyPath) idx = arr.findIndex(p => (p.path || '') === keyPath) + if (idx >= 0) arr[idx] = { ...arr[idx], ...toRaw(page) } + else arr.push({ ...toRaw(page) }) } - // --- Upsert nello store.mypage - function upsertIntoStore(page: IMyPage, arr: IMyPage[]) { - if (!page) return; - // chiave di matching: prima _id, altrimenti path - const keyId = page._id; - const keyPath = page.path || ''; - let idx = -1; - if (keyId) { - idx = arr.findIndex((p) => p._id === keyId); + // --- VALIDAZIONE + COMMIT per nuova pagina (o anche per edit espliciti) + async function checkAndSave (payloadDraft?: IMyPage) { + const cur = payloadDraft || draft + + // validazioni base + if (!cur.title?.trim()) { + $q.notify({ message: 'Inserisci il titolo della pagina', type: 'warning' }) + return } - if (idx < 0 && keyPath) { - idx = arr.findIndex((p) => (p.path || '') === keyPath); + + const pathText = (ui.pathText || '').trim() + if (!pathText) { + $q.notify({ message: 'Inserisci il percorso della pagina', type: 'warning' }) + return } - if (idx >= 0) { - // merge preservando reattività - arr[idx] = { ...arr[idx], ...toRaw(page) }; - } else { - arr.push({ ...toRaw(page) }); + + const candidatePath = toStorePath(pathText).toLowerCase() + + // unicità PATH (ignora se stesso quando editing) + const existPath = globalStore.mypage.find( + (r) => (r.path || '').toLowerCase() === candidatePath && r._id !== cur._id + ) + if (existPath) { + $q.notify({ message: 'Esiste già un’altra pagina con questo percorso', type: 'warning' }) + return } + + // unicità TITOLO (ignora se stesso quando editing) + const candidateTitle = (cur.title || '').toLowerCase() + const existName = globalStore.mypage.find( + (r) => (r.title || '').toLowerCase() === candidateTitle && r._id !== cur._id + ) + if (existName) { + $q.notify({ message: 'Il nome della pagina esiste già', type: 'warning' }) + return + } + + await save() // esegue commit vero + emit('hide') // chiudi il dialog (se usi dialog) } -async function save () { + + // --- Salvataggio esplicito (commit). Qui propaghiamo SEMPRE al parent/store. + async function save () { try { saving.value = true normalizeAndApplyPath() // assicura path coerente const payload: IMyPage = { ...toRaw(draft), path: draft.path || '' } const saved = await globalStore.savePage(payload) + if (saved && typeof saved === 'object') { syncingFromProps.value = true Object.assign(draft, saved) - upsertIntoStore(draft, mypage.value) + upsertIntoStore(draft, mypage.value) // ora è lecito anche per nuovaPagina await nextTick() syncingFromProps.value = false } + + // IMPORTANTISSIMO: in nuovaPagina non abbiamo mai emesso prima → emettiamo ora + emit('update:modelValue', { ...draft }) emit('apply', { ...draft }) $q.notify({ type: 'positive', message: 'Pagina salvata' }) - } catch (err: any) { + } catch (err) { console.error(err) $q.notify({ type: 'negative', message: 'Errore nel salvataggio' }) } finally { @@ -143,7 +169,7 @@ async function save () { } } - // --- Ricarica da sorgente + // --- Ricarica (per editing). In modalità nuovaPagina non propaghiamo al parent. async function reloadFromStore () { try { const absolute = ui.pathText || '/' @@ -153,8 +179,7 @@ async function save () { Object.assign(draft, page) ui.pathText = toUiPath(draft.path) upsertIntoStore(draft, mypage.value) - console.log('page', draft) - emit('update:modelValue', { ...draft }) + if (!props.nuovaPagina) emit('update:modelValue', { ...draft }) // <-- no propagate in nuovaPagina await nextTick() syncingFromProps.value = false $q.notify({ type: 'info', message: 'Pagina ricaricata' }) @@ -167,16 +192,18 @@ async function save () { } } - function resetDraft() { - console.log('resetDraft') + function resetDraft () { syncingFromProps.value = true Object.assign(draft, props.modelValue || {}) ui.pathText = toUiPath(draft.path) - // aggiorna i componenti - emit('update:modelValue', { ...draft }) + if (!props.nuovaPagina) emit('update:modelValue', { ...draft }) // <-- no propagate in nuovaPagina nextTick(() => { syncingFromProps.value = false }) } + function modifElem() { + + } + const absolutePath = computed(() => toUiPath(draft.path)) return { @@ -189,6 +216,10 @@ async function save () { reloadFromStore, resetDraft, absolutePath, - }; - }, -}); + checkAndSave, + t, + costanti, + modifElem, + } + } +}) diff --git a/src/components/PageEditor/PageEditor.vue b/src/components/PageEditor/PageEditor.vue index 697a972c..0ace75b1 100644 --- a/src/components/PageEditor/PageEditor.vue +++ b/src/components/PageEditor/PageEditor.vue @@ -1,5 +1,9 @@ - + diff --git a/src/composables/useDnd.js b/src/composables/useDnd.js new file mode 100644 index 00000000..dca11b6e --- /dev/null +++ b/src/composables/useDnd.js @@ -0,0 +1,18 @@ +import { ref } from 'vue'; + +export const useDnd = () => { + const dragging = ref(false); + const draggedElement = ref(null); + + const startDrag = (element) => { + dragging.value = true; + draggedElement.value = element; + }; + + const endDrag = () => { + dragging.value = false; + draggedElement.value = null; + }; + + return { dragging, draggedElement, startDrag, endDrag }; +}; diff --git a/src/composables/useHistory.js b/src/composables/useHistory.js new file mode 100644 index 00000000..3345247f --- /dev/null +++ b/src/composables/useHistory.js @@ -0,0 +1,29 @@ +import { ref } from 'vue'; + +export const useHistory = () => { + const history = ref([]); + const currentIndex = ref(-1); + + const addToHistory = (state) => { + history.value.push(state); + currentIndex.value = history.value.length - 1; + }; + + const undo = () => { + if (currentIndex.value > 0) { + currentIndex.value--; + return history.value[currentIndex.value]; + } + return null; + }; + + const redo = () => { + if (currentIndex.value < history.value.length - 1) { + currentIndex.value++; + return history.value[currentIndex.value]; + } + return null; + }; + + return { history, addToHistory, undo, redo }; +}; diff --git a/src/layouts/menuone/menuOne.ts b/src/layouts/menuone/menuOne.ts index 890bc48d..c1c6fcfd 100755 --- a/src/layouts/menuone/menuOne.ts +++ b/src/layouts/menuone/menuOne.ts @@ -1,65 +1,86 @@ -import type { IListRoutes } from '@src/model' -import { useGlobalStore } from '@store/globalStore' -import { tools } from '@tools' -import { computed, defineComponent, ref, watch } from 'vue' -import { useRoute } from 'vue-router' -import { static_data } from '@src/db/static_data' -import { useUserStore } from '@store/UserStore' +import type { IListRoutes } from '@src/model'; +import { useGlobalStore } from '@store/globalStore'; +import { tools } from '@tools'; +import { computed, defineComponent, ref, watch } from 'vue'; +import { useRoute } from 'vue-router'; +import { static_data } from '@src/db/static_data'; +import { useUserStore } from '@store/UserStore'; -import { CMenuItem } from '../../components/CMenuItem' +import { CMenuItem } from '../../components/CMenuItem'; export default defineComponent({ name: 'MenuOne', components: { CMenuItem }, setup(props) { - const route = useRoute() - const userStore = useUserStore() - const globalStore = useGlobalStore() + const route = useRoute(); + const userStore = useUserStore(); + const globalStore = useGlobalStore(); - const finishLoading = computed(() => globalStore.finishLoading) + const finishLoading = computed(() => globalStore.finishLoading); + const updateMenu = computed(() => globalStore.updateMenu); - const path = computed(() => route.path) + const path = computed(() => route.path); - const getroutes = computed(() => static_data.routes) + const getroutes = computed(() => static_data.routes); - const myroutes = ref([]) + const myroutes = ref([]); - const getmenu = computed(() => globalStore.getmenu) + const getmenu = computed(() => globalStore.getmenu); - const islogged = computed(() => userStore.isLogged) + const islogged = computed(() => userStore.isLogged); - const clBase = ref('my-menu') + const clBase = ref('my-menu'); function setParentVisibilityBasedOnRoute(parent: any) { parent.routes.forEach((item: any) => { if (path.value === item.path) { - parent.show = true + parent.show = true; } - }) + }); } function updatemenu() { - const mymenu = globalStore.getmenu + console.log('*** updatemenu'); + const mymenu = globalStore.getmenu; Object.keys(mymenu).forEach((parentName: any) => { // @ts-ignore - setParentVisibilityBasedOnRoute(mymenu[parentName]) - }) - myroutes.value = [] - myroutes.value = static_data.routes + setParentVisibilityBasedOnRoute(mymenu[parentName]); + }); + myroutes.value = []; + myroutes.value = static_data.routes; + + globalStore.updateMenu = false; } - watch(() => islogged.value, (to, from) => { - updatemenu() - }) + watch( + () => islogged.value, + (to, from) => { + updatemenu(); + } + ); - watch(() => finishLoading.value, (to, from) => { - updatemenu() - }) + watch( + () => finishLoading.value, + (to, from) => { + updatemenu(); + } + ); - watch(() => path, (to, from) => { - updatemenu() - }) + watch( + () => updateMenu.value, + (newValue, oldValue) => { + if (newValue) updatemenu(); + }, + { deep: true } + ); + + watch( + () => path, + (to, from) => { + updatemenu(); + } + ); /* function replaceUnderlineToSpace(text: string) { while (text.indexOf('_') !== -1) { @@ -69,61 +90,56 @@ export default defineComponent({ } */ function getroute(elem: IListRoutes) { - let link = '' + let link = ''; if (elem.idelem) { - link = tools.getUrlByTipoProj(elem.urlroute ? elem.urlroute : '') + elem.idelem + link = tools.getUrlByTipoProj(elem.urlroute ? elem.urlroute : '') + elem.idelem; } - if (!link) - link = elem.path + if (!link) link = elem.path; // console.log('getroute LINK=', link) - return link + return link; } function getmymenuclass(elem: IListRoutes) { - let menu: string = clBase.value + let menu: string = clBase.value; if (elem.color) { - menu += ` ${elem.color}` + menu += ` ${elem.color}`; } else { - if (elem.onlyAdmin) menu += ' isAdmin' - if (elem.onlyManager) menu += ' isManager' - if (elem.onlySocioResidente) menu += ' isSocioResidente' - if (elem.onlyConsiglio) menu += ' isConsiglio' - if (elem.onlyDepartment) menu += ' isDepartment' - if (elem.onlyFacilitatore) menu += ' isFacilitatore' - if (elem.onlyEditor) menu += ' isEditor' - if (elem.onlyCommerciale) menu += ' isCommerciale' - if (elem.onlyCollaboratore) menu += ' isCollaboratore' - if (elem.onlyGrafico) menu += ' isGrafico' + if (elem.onlyAdmin) menu += ' isAdmin'; + if (elem.onlyManager) menu += ' isManager'; + if (elem.onlySocioResidente) menu += ' isSocioResidente'; + if (elem.onlyConsiglio) menu += ' isConsiglio'; + if (elem.onlyDepartment) menu += ' isDepartment'; + if (elem.onlyFacilitatore) menu += ' isFacilitatore'; + if (elem.onlyEditor) menu += ' isEditor'; + if (elem.onlyCommerciale) menu += ' isCommerciale'; + if (elem.onlyCollaboratore) menu += ' isCollaboratore'; + if (elem.onlyGrafico) menu += ' isGrafico'; } - if (elem.extraclass) menu += ` ${elem.extraclass}` + if (elem.extraclass) menu += ` ${elem.extraclass}`; // console.log('menu', menu) - return menu + return menu; } function getimgiconclass(elem: IListRoutes) { - if (elem.extraclass) - return elem.extraclass - else - return 'imgicon' + if (elem.extraclass) return elem.extraclass; + else return 'imgicon'; } function getimgiconclass2(elem: IListRoutes) { - if (elem.extraclass) - return elem.extraclass - else - return 'clBase' + if (elem.extraclass) return elem.extraclass; + else return 'clBase'; } function getmenuByPath(path: string) { - const mymenufind = static_data.routes.find((menu: any) => menu.path === '/' + path) + const mymenufind = static_data.routes.find((menu: any) => menu.path === '/' + path); - return mymenufind + return mymenufind; } - myroutes.value = static_data.routes + myroutes.value = static_data.routes; return { getmenu, @@ -138,6 +154,6 @@ export default defineComponent({ getimgiconclass2, getmenuByPath, clBase, - } + }; }, -}) +}); diff --git a/src/model/GlobalStore.ts b/src/model/GlobalStore.ts index 121157c6..d1d93717 100755 --- a/src/model/GlobalStore.ts +++ b/src/model/GlobalStore.ts @@ -194,6 +194,8 @@ export interface IMyElem { elemsText?: IElemText[] titleBanner?: string classBanner?: string + color?: string + children?: any[] } export interface IElemText { @@ -236,6 +238,7 @@ export interface IMyPage { elemsText?: IElemText[] onlyif_logged?: boolean only_residenti?: boolean + only_admin?: boolean only_consiglio?: boolean only_collab?: boolean submenu?: boolean @@ -479,6 +482,7 @@ export interface ISelector { } export interface IGlobalState { finishLoading: boolean + updateMenu: boolean showHeader?: boolean inStampa?: boolean conta: number diff --git a/src/rootgen/admin/editpages/editpages.ts b/src/rootgen/admin/editpages/editpages.ts index 43b85fe3..8506de35 100644 --- a/src/rootgen/admin/editpages/editpages.ts +++ b/src/rootgen/admin/editpages/editpages.ts @@ -1,103 +1,153 @@ -import { defineComponent, ref, watch, onMounted } from 'vue' -import { useQuasar } from 'quasar' -import { storeToRefs } from 'pinia' -import { IMyPage } from 'app/src/model' -import { useGlobalStore } from 'app/src/store' -import { PagesConfigurator } from '@src/components/PagesConfigurator' -import { useI18n } from 'vue-i18n' - +import { defineComponent, ref, watch, onMounted } from 'vue'; +import { useQuasar } from 'quasar'; +import { storeToRefs } from 'pinia'; +import { IMyPage } from 'app/src/model'; +import { useGlobalStore } from 'app/src/store'; +import { PagesConfigurator } from '@src/components/PagesConfigurator'; +import { useI18n } from 'vue-i18n'; +import { useRouter } from 'vue-router'; export default defineComponent({ name: 'PagesAdmin', components: { PagesConfigurator }, - setup () { - const $q = useQuasar() - const { t } = useI18n() + setup() { + const $q = useQuasar(); + const { t } = useI18n(); - const globalStore = useGlobalStore() - const { mypage } = storeToRefs(globalStore) + const globalStore = useGlobalStore(); + const { mypage } = storeToRefs(globalStore); + + const $router = useRouter() // Copia locale per l’editing tramite v-model - const pagesLocal = ref([]) - const savingAll = ref(false) + const pagesLocal = ref([]); + const savingAll = ref(false); // Mantieni pagesLocal <-> store allineati const syncFromStore = () => { - pagesLocal.value = (mypage.value || []).map(p => ({ ...p })) - } + pagesLocal.value = (mypage.value || []).map((p) => ({ ...p })); + }; - watch(mypage, syncFromStore, { deep: true }) + watch(mypage, syncFromStore, { deep: true }); onMounted(async () => { // Se hai una funzione per caricare tutte le pagine, chiamala qui // es. await globalStore.loadAllPages() - syncFromStore() - }) + syncFromStore(); + }); - // Salva singola pagina (chiamato da PagesConfigurator @save) - async function saveOne (page: IMyPage) { - try { - const saved = await globalStore.savePage({ ...page }) - if (saved && typeof saved === 'object') { - // rimpiazza nel local e nello store (lo store viene aggiornato da savePage) - const idx = pagesLocal.value.findIndex(p => - (p._id && p._id === saved._id) || (p.path && p.path === saved.path) - ) - if (idx >= 0) pagesLocal.value[idx] = { ...saved } - $q.notify({ type: 'positive', message: `Salvata: ${saved.title || saved.path}` }) - } else { - $q.notify({ type: 'positive', message: 'Salvataggio completato' }) - } - } catch (err) { - console.error(err) - $q.notify({ type: 'negative', message: 'Errore nel salvataggio della pagina' }) + const lastOrderSnapshot = ref>(new Map()); + const savingOrders = ref(false); + + // crea/ricostruisce lo snapshot (solo pagine con _id) + function initOrderSnapshot(arr: IMyPage[]) { + const m = new Map(); + for (const p of arr) { + if (p._id) m.set(p._id, p.order ?? 0); } + lastOrderSnapshot.value = m; } + // call una volta dopo aver caricato le pagine + onMounted(() => { + initOrderSnapshot(pagesLocal.value); // pagesLocal è il tuo array locale già usato + }); + + // quando salvi una pagina singola e ottieni l'_id, aggiorna lo snapshot + async function saveOne(p: IMyPage) { + try { + const saved = await globalStore.savePage({ ...p }); + if (saved && saved._id) { + // aggiorna la copia locale + const idx = pagesLocal.value.findIndex( + (x) => (x._id && x._id === saved._id) || (x.path && x.path === saved.path) + ); + if (idx >= 0) pagesLocal.value[idx] = { ...saved }; + // aggiorna lo snapshot dell'ordinamento persistito + lastOrderSnapshot.value.set( + saved._id, + saved.order ?? pagesLocal.value[idx]?.order ?? 0 + ); + $q.notify({ + type: 'positive', + message: `Salvata: ${saved.title || saved.path}`, + }); + } + } catch (e) { + console.error(e); + $q.notify({ type: 'negative', message: 'Errore nel salvataggio della pagina' }); + } + } // Salva l’ordinamento (fallback: batch di savePage per aggiornare order) - async function saveOrder (orders: { id?: string; order: number }[]) { + async function saveOrder(orders: { id?: string; order: number }[]) { try { - // Applica l'order nella copia locale - for (const { id, order } of orders) { - const p = pagesLocal.value.find(x => x._id === id) || - pagesLocal.value.find(x => !id && typeof x.order === 'number' && x.order === order) - if (p) p.order = order + if (savingOrders.value) return; + savingOrders.value = true; + + // 1) calcola solo i cambi VERI su pagine già persistite (_id presente) + const changedExisting = orders.filter((o) => { + if (!o.id) return false; // ignora nuovi senza id + const prev = lastOrderSnapshot.value.get(o.id); + return prev === undefined ? false : prev !== o.order; + }); + + // 2) se non è cambiato nulla di "persistito", esci silenziosamente + if (changedExisting.length === 0) { + // console.debug('[saveOrder] nessun cambiamento persistente') + return; } - // Fallback: se non hai un endpoint /reorder, salvi singolarmente + + // fallback: salva solo le pagine cambiate await Promise.all( - pagesLocal.value.map(p => globalStore.savePage({ ...p })) - ) - $q.notify({ type: 'positive', message: 'Ordinamento salvato' }) + changedExisting.map(({ id, order }) => { + const p = pagesLocal.value.find((x) => x._id === id); + if (!p) return Promise.resolve(); + // se il tuo savePage accetta payload parziale, meglio passare solo {_id, order} + // altrimenti manda l'oggetto intero con order aggiornato + return globalStore.savePage({ ...p, order }); + }) + ); + + // 4) aggiorna lo snapshot solo per gli elementi realmente salvati + for (const { id, order } of changedExisting) { + if (id) lastOrderSnapshot.value.set(id, order); + } + + $q.notify({ type: 'positive', message: 'Ordinamento aggiornato' }); + + globalStore.aggiornaMenu($router); } catch (err) { - console.error(err) - $q.notify({ type: 'negative', message: 'Errore nel salvataggio dell’ordinamento' }) + console.error(err); + $q.notify({ + type: 'negative', + message: 'Errore nel salvataggio dell’ordinamento', + }); + } finally { + savingOrders.value = false; } } - // Ricarica l’elenco (se disponibile una API globale; altrimenti rilegge dallo store) - async function reloadAll () { + async function reloadAll() { try { // Se esiste: await globalStore.loadAllPages() - syncFromStore() - $q.notify({ type: 'info', message: 'Elenco ricaricato' }) + syncFromStore(); + $q.notify({ type: 'info', message: 'Elenco ricaricato' }); } catch (err) { - console.error(err) - $q.notify({ type: 'negative', message: 'Errore nel ricaricare l’elenco' }) + console.error(err); + $q.notify({ type: 'negative', message: 'Errore nel ricaricare l’elenco' }); } } // Salva tutto (batch) - async function saveAll () { + async function saveAll() { try { - savingAll.value = true - await Promise.all( - pagesLocal.value.map(p => globalStore.savePage({ ...p })) - ) - $q.notify({ type: 'positive', message: 'Tutte le pagine salvate' }) + savingAll.value = true; + await Promise.all(pagesLocal.value.map((p) => globalStore.savePage({ ...p }))); + $q.notify({ type: 'positive', message: 'Tutte le pagine salvate' }); } catch (err) { - console.error(err) - $q.notify({ type: 'negative', message: 'Errore nel salvataggio massivo' }) + console.error(err); + $q.notify({ type: 'negative', message: 'Errore nel salvataggio massivo' }); } finally { - savingAll.value = false + savingAll.value = false; } } @@ -109,6 +159,6 @@ export default defineComponent({ saveAll, savingAll, t, - } - } -}) + }; + }, +}); diff --git a/src/rootgen/admin/editpages/editpages.vue b/src/rootgen/admin/editpages/editpages.vue index aa0d7279..4c62f191 100644 --- a/src/rootgen/admin/editpages/editpages.vue +++ b/src/rootgen/admin/editpages/editpages.vue @@ -1,7 +1,7 @@