diff --git a/.env b/.env index 64337e5b..9e258ee4 100755 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ -VITE_APP_VERSION="1.2.42" +VITE_APP_VERSION="1.2.44" VITE_LANG_DEFAULT="it" VITE_PAO_APP_ID="KKPPAA5KJK435J3KSS9F9D8S9F8SD98F9SDF" -VITE_SERVICE_WORKER_FILE="sw-1.2.42.js" +VITE_SERVICE_WORKER_FILE="sw-1.2.44.js" VITE_PROJECT_ID_MAIN="5cc0a13fe5c9d156728f400a" VITE_VUE_ROUTER_MODE="history" \ No newline at end of file diff --git a/.env.production b/.env.production index 0413ced6..2a577413 100644 --- a/.env.production +++ b/.env.production @@ -1,13 +1,11 @@ VITE_APP_ID="18" -VITE_APP_URL="https://gruppomacro.app" -VITE_MONGODB_HOST="https://api.gruppomacro.app" -VITE_LOGO_REG='gruppomacro-logo-full.png' +VITE_APP_URL="https://test.gruppomacro.app" +VITE_MONGODB_HOST="https://testapi.gruppomacro.app" +VITE_LOGO_REG="gruppomacro-logo-full.png" VITE_PUBLICKEY_PUSH="BJgo8XR_upbnbMLWgCAUELo6DK7dRXffYAnFOxbaMMz5favBgcQBKT-eISqouO-jRad4Sw8l5nd2wCF6KorGiTc" -VITE_DEBUG="0" -VITE_VUE_APP_ISTEST="0" +VITE_DEBUG="1" +VITE_VUE_APP_ISTEST="1" DIRECTORY_LOCAL="myprojplanet_vite" -DIRECTORY_SERVER="/var/www/nodejs_piuchebuono_server" -SERVERDIR_WEBSITE="/var/www/gruppomacro.app" -SERVERPW_WEBSITE="pwdadmin@1AOK" -PORT_SPA="8092" -PORT_PWA="8099" \ No newline at end of file +DIRECTORY_SERVER="/var/www/nodejs_test.piuchebuono_server" +SERVERDIR_WEBSITE="/var/www/test.gruppomacro.app" +SERVERPW_WEBSITE="pwdadmin@1AOK" \ No newline at end of file diff --git a/index.html b/index.html index 7473ed21..4762d9e9 100755 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@ - + diff --git a/package.json b/package.json index 8c6064f3..dc2e1253 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gruppomacro", - "version": "1.2.42", + "version": "1.2.44", "description": "Gruppo Macro", "productName": "Gruppo Macro", "author": "Surya", @@ -9,20 +9,20 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8089 APP_VERSION='1.2.42' quasar dev", + "dev": "PORT=8089 APP_VERSION='1.2.44' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", - "buildspa": "APP_VERSION='1.2.42' quasar build -m spa", + "buildspa": "APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.44' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/public/js/fetch.js b/public/js/fetch.js new file mode 100755 index 00000000..5516b6e6 --- /dev/null +++ b/public/js/fetch.js @@ -0,0 +1,457 @@ +(function (self) { + if (self.fetch) { + return + } + + const support = { + searchParams: 'URLSearchParams' in self, + iterable: 'Symbol' in self && 'iterator' in Symbol, + blob: 'FileReader' in self && 'Blob' in self && (function () { + try { + new Blob() + return true + } catch (e) { + return false + } + }()), + formData: 'FormData' in self, + arrayBuffer: 'ArrayBuffer' in self, + } + + if (support.arrayBuffer) { + const viewClasses = [ + '[object Int8Array]', + '[object Uint8Array]', + '[object Uint8ClampedArray]', + '[object Int16Array]', + '[object Uint16Array]', + '[object Int32Array]', + '[object Uint32Array]', + '[object Float32Array]', + '[object Float64Array]', + ] + + var isDataView = function (obj) { + return obj && DataView.prototype.isPrototypeOf(obj) + } + + var isArrayBufferView = ArrayBuffer.isView || function (obj) { + return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 + } + } + + function normalizeName(name) { + if (typeof name !== 'string') { + name = String(name) + } + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field nametranslate') + } + return name.toLowerCase() + } + + function normalizeValue(value) { + if (typeof value !== 'string') { + value = String(value) + } + return value + } + + // Build a destructive iterator for the value list + function iteratorFor(items) { + const iterator = { + next() { + const value = items.shift() + return { done: value === undefined, value } + }, + } + + if (support.iterable) { + iterator[Symbol.iterator] = function () { + return iterator + } + } + + return iterator + } + + function Headers(headers) { + this.map = {} + + if (headers instanceof Headers) { + headers.forEach(function (value, name) { + this.append(name, value) + }, this) + } else if (Array.isArray(headers)) { + headers.forEach(function (header) { + this.append(header[0], header[1]) + }, this) + } else if (headers) { + Object.getOwnPropertyNames(headers).forEach(function (name) { + this.append(name, headers[name]) + }, this) + } + } + + Headers.prototype.append = function (name, value) { + name = normalizeName(name) + value = normalizeValue(value) + const oldValue = this.map[name] + this.map[name] = oldValue ? `${oldValue},${value}` : value + } + + Headers.prototype.delete = function (name) { + delete this.map[normalizeName(name)] + } + + Headers.prototype.get = function (name) { + name = normalizeName(name) + return this.has(name) ? this.map[name] : null + } + + Headers.prototype.has = function (name) { + return this.map.hasOwnProperty(normalizeName(name)) + } + + Headers.prototype.set = function (name, value) { + this.map[normalizeName(name)] = normalizeValue(value) + } + + Headers.prototype.forEach = function (callback, thisArg) { + for (const name in this.map) { + if (this.map.hasOwnProperty(name)) { + callback.call(thisArg, this.map[name], name, this) + } + } + } + + Headers.prototype.keys = function () { + const items = [] + this.forEach((value, name) => { items.push(name) }) + return iteratorFor(items) + } + + Headers.prototype.values = function () { + const items = [] + this.forEach((value) => { items.push(value) }) + return iteratorFor(items) + } + + Headers.prototype.entries = function () { + const items = [] + this.forEach((value, name) => { items.push([name, value]) }) + return iteratorFor(items) + } + + if (support.iterable) { + Headers.prototype[Symbol.iterator] = Headers.prototype.entries + } + + function consumed(body) { + if (body.bodyUsed) { + return Promise.reject(new TypeError('Already read')) + } + body.bodyUsed = true + } + + function fileReaderReady(reader) { + return new Promise((resolve, reject) => { + reader.onload = function () { + resolve(reader.result) + } + reader.onerror = function () { + reject(reader.error) + } + }) + } + + function readBlobAsArrayBuffer(blob) { + const reader = new FileReader() + const promise = fileReaderReady(reader) + reader.readAsArrayBuffer(blob) + return promise + } + + function readBlobAsText(blob) { + const reader = new FileReader() + const promise = fileReaderReady(reader) + reader.readAsText(blob) + return promise + } + + function readArrayBufferAsText(buf) { + const view = new Uint8Array(buf) + const chars = new Array(view.length) + + for (let i = 0; i < view.length; i++) { + chars[i] = String.fromCharCode(view[i]) + } + return chars.join('') + } + + function bufferClone(buf) { + if (buf.slice) { + return buf.slice(0) + } + const view = new Uint8Array(buf.byteLength) + view.set(new Uint8Array(buf)) + return view.buffer + } + + function Body() { + this.bodyUsed = false + + this._initBody = function (body) { + this._bodyInit = body + if (!body) { + this._bodyText = '' + } else if (typeof body === 'string') { + this._bodyText = body + } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { + this._bodyBlob = body + } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { + this._bodyFormData = body + } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { + this._bodyText = body.toString() + } else if (support.arrayBuffer && support.blob && isDataView(body)) { + this._bodyArrayBuffer = bufferClone(body.buffer) + // IE 10-11 can't handle a DataView body. + this._bodyInit = new Blob([this._bodyArrayBuffer]) + } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { + this._bodyArrayBuffer = bufferClone(body) + } else { + throw new Error('unsupported BodyInit type') + } + + if (!this.headers.get('content-type')) { + if (typeof body === 'string') { + this.headers.set('content-type', 'text/plain;charset=UTF-8') + } else if (this._bodyBlob && this._bodyBlob.type) { + this.headers.set('content-type', this._bodyBlob.type) + } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { + this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8') + } + } + } + + if (support.blob) { + this.blob = function () { + const rejected = consumed(this) + if (rejected) { + return rejected + } + + if (this._bodyBlob) { + return Promise.resolve(this._bodyBlob) + } if (this._bodyArrayBuffer) { + return Promise.resolve(new Blob([this._bodyArrayBuffer])) + } if (this._bodyFormData) { + throw new Error('could not read FormData body as blob') + } else { + return Promise.resolve(new Blob([this._bodyText])) + } + } + + this.arrayBuffer = function () { + if (this._bodyArrayBuffer) { + return consumed(this) || Promise.resolve(this._bodyArrayBuffer) + } + return this.blob().then(readBlobAsArrayBuffer) + } + } + + this.text = function () { + const rejected = consumed(this) + if (rejected) { + return rejected + } + + if (this._bodyBlob) { + return readBlobAsText(this._bodyBlob) + } if (this._bodyArrayBuffer) { + return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) + } if (this._bodyFormData) { + throw new Error('could not read FormData body as text') + } else { + return Promise.resolve(this._bodyText) + } + } + + if (support.formData) { + this.formData = function () { + return this.text().then(decode) + } + } + + this.json = function () { + return this.text().then(JSON.parse) + } + + return this + } + + // HTTP methods whose capitalization should be normalized + const methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] + + function normalizeMethod(method) { + const upcased = method.toUpperCase() + return (methods.indexOf(upcased) > -1) ? upcased : method + } + + function Request(input, options) { + options = options || {} + let { body } = options + + if (input instanceof Request) { + if (input.bodyUsed) { + throw new TypeError('Already read') + } + this.url = input.url + this.credentials = input.credentials + if (!options.headers) { + this.headers = new Headers(input.headers) + } + this.method = input.method + this.mode = input.mode + if (!body && input._bodyInit != null) { + body = input._bodyInit + input.bodyUsed = true + } + } else { + this.url = String(input) + } + + this.credentials = options.credentials || this.credentials || 'omit' + if (options.headers || !this.headers) { + this.headers = new Headers(options.headers) + } + this.method = normalizeMethod(options.method || this.method || 'GET') + this.mode = options.mode || this.mode || null + this.referrer = null + + if ((this.method === 'GET' || this.method === 'HEAD') && body) { + throw new TypeError('Body not allowed for GET or HEAD requests') + } + this._initBody(body) + } + + Request.prototype.clone = function () { + return new Request(this, { body: this._bodyInit }) + } + + function decode(body) { + const form = new FormData() + body.trim().split('&').forEach((bytes) => { + if (bytes) { + const split = bytes.split('=') + const name = split.shift().replace(/\+/g, ' ') + const value = split.join('=').replace(/\+/g, ' ') + form.append(decodeURIComponent(name), decodeURIComponent(value)) + } + }) + return form + } + + function parseHeaders(rawHeaders) { + const headers = new Headers() + rawHeaders.split(/\r?\n/).forEach((line) => { + const parts = line.split(':') + const key = parts.shift().trim() + if (key) { + const value = parts.join(':').trim() + headers.append(key, value) + } + }) + return headers + } + + Body.call(Request.prototype) + + function Response(bodyInit, options) { + if (!options) { + options = {} + } + + this.type = 'default' + this.status = 'status' in options ? options.status : 200 + this.ok = this.status >= 200 && this.status < 300 + this.statusText = 'statusText' in options ? options.statusText : 'OK' + this.headers = new Headers(options.headers) + this.url = options.url || '' + this._initBody(bodyInit) + } + + Body.call(Response.prototype) + + Response.prototype.clone = function () { + return new Response(this._bodyInit, { + status: this.status, + statusText: this.statusText, + headers: new Headers(this.headers), + url: this.url, + }) + } + + Response.error = function () { + const response = new Response(null, { status: 0, statusText: '' }) + response.type = 'error' + return response + } + + const redirectStatuses = [301, 302, 303, 307, 308] + + Response.redirect = function (url, status) { + if (redirectStatuses.indexOf(status) === -1) { + throw new RangeError('Invalid status code') + } + + return new Response(null, { status, headers: { location: url } }) + } + + self.Headers = Headers + self.Request = Request + self.Response = Response + + self.fetch = function (input, init) { + return new Promise((resolve, reject) => { + const request = new Request(input, init) + const xhr = new XMLHttpRequest() + + xhr.onload = function () { + const options = { + status: xhr.status, + statusText: xhr.statusText, + headers: parseHeaders(xhr.getAllResponseHeaders() || ''), + } + options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL') + const body = 'response' in xhr ? xhr.response : xhr.responseText + resolve(new Response(body, options)) + } + + xhr.onerror = function () { + reject(new TypeError('Network request failed')) + } + + xhr.ontimeout = function () { + reject(new TypeError('Network request failed')) + } + + xhr.open(request.method, request.url, true) + + if (request.credentials === 'include') { + xhr.withCredentials = true + } + + if ('responseType' in xhr && support.blob) { + xhr.responseType = 'blob' + } + + request.headers.forEach((value, name) => { + xhr.setRequestHeader(name, value) + }) + + xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) + }) + } + self.fetch.polyfill = true +}(typeof self !== 'undefined' ? self : this)); diff --git a/public/js/globalenv.js b/public/js/globalenv.js new file mode 100755 index 00000000..f88f9996 --- /dev/null +++ b/public/js/globalenv.js @@ -0,0 +1,25 @@ +// importScripts('/public/js/immortal-db.min.js'); + +/* +const cfgenv = { + website: 'http://localhost:8081', + serverweb: 'http://localhost:3000', + dbname: 'mydb3', + dbversion: 10, +} +*/ + +/* +async function clearAllDataImmortal(table) { + console.log('clearAllDataImmortal', table) + const db = ImmortalDB.ImmortalDB + await db.remove(table) +} + +async function writeDataImmortal(table, datavalue) { + console.log('writeDataImmortal', table, datavalue) + const db = ImmortalDB.ImmortalDB + await db.set(table, datavalue) +} + +*/ diff --git a/public/js/idb.js b/public/js/idb.js new file mode 100755 index 00000000..6dfbd1d7 --- /dev/null +++ b/public/js/idb.js @@ -0,0 +1,307 @@ +(function () { + // console.log('LOADING IDB.JS .....') + function toArray(arr) { + return Array.prototype.slice.call(arr); + } + + function promisifyRequest(request) { + return new Promise((resolve, reject) => { + request.onsuccess = function () { + resolve(request.result); + }; + + request.onerror = function () { + reject(request.error); + }; + }); + } + + function promisifyRequestCall(obj, method, args) { + let request; + const p = new Promise((resolve, reject) => { + request = obj[method].apply(obj, args); + promisifyRequest(request).then(resolve, reject); + }); + + p.request = request; + return p; + } + + function promisifyCursorRequestCall(obj, method, args) { + const p = promisifyRequestCall(obj, method, args); + return p.then((value) => { + if (!value) return; + return new Cursor(value, p.request); + }); + } + + function proxyProperties(ProxyClass, targetProp, properties) { + properties.forEach((prop) => { + Object.defineProperty(ProxyClass.prototype, prop, { + get() { + return this[targetProp][prop]; + }, + set(val) { + this[targetProp][prop] = val; + }, + }); + }); + } + + function proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach((prop) => { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function () { + return promisifyRequestCall(this[targetProp], prop, arguments); + }; + }); + } + + function proxyMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach((prop) => { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function () { + return this[targetProp][prop].apply(this[targetProp], arguments); + }; + }); + } + + function proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach((prop) => { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function () { + return promisifyCursorRequestCall(this[targetProp], prop, arguments); + }; + }); + } + + function Index(index) { + this._index = index; + } + + proxyProperties(Index, '_index', [ + 'name', + 'keyPath', + 'multiEntry', + 'unique', + ]); + + proxyRequestMethods(Index, '_index', IDBIndex, [ + 'get', + 'getKey', + 'getAll', + 'getAllKeys', + 'count', + ]); + + proxyCursorRequestMethods(Index, '_index', IDBIndex, [ + 'openCursor', + 'openKeyCursor', + ]); + + function Cursor(cursor, request) { + this._cursor = cursor; + this._request = request; + } + + proxyProperties(Cursor, '_cursor', [ + 'direction', + 'key', + 'primaryKey', + 'value', + ]); + + proxyRequestMethods(Cursor, '_cursor', IDBCursor, [ + 'update', + 'delete', + ]); + + // proxy 'next' methods + ['advance', 'continue', 'continuePrimaryKey'].forEach((methodName) => { + if (!(methodName in IDBCursor.prototype)) return; + Cursor.prototype[methodName] = function () { + const cursor = this; + const args = arguments; + return Promise.resolve().then(() => { + cursor._cursor[methodName].apply(cursor._cursor, args); + return promisifyRequest(cursor._request).then((value) => { + if (!value) return; + return new Cursor(value, cursor._request); + }); + }); + }; + }); + + function ObjectStore(store) { + this._store = store; + } + + ObjectStore.prototype.createIndex = function () { + return new Index(this._store.createIndex.apply(this._store, arguments)); + }; + + ObjectStore.prototype.index = function () { + return new Index(this._store.index.apply(this._store, arguments)); + }; + + proxyProperties(ObjectStore, '_store', [ + 'name', + 'keyPath', + 'indexNames', + 'autoIncrement', + ]); + + proxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [ + 'put', + 'add', + 'delete', + 'clear', + 'get', + 'getAll', + 'getKey', + 'getAllKeys', + 'count', + ]); + + proxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [ + 'openCursor', + 'openKeyCursor', + ]); + + proxyMethods(ObjectStore, '_store', IDBObjectStore, [ + 'deleteIndex', + ]); + + function Transaction(idbTransaction) { + this._tx = idbTransaction; + this.complete = new Promise((resolve, reject) => { + idbTransaction.oncomplete = function () { + resolve(); + }; + idbTransaction.onerror = function () { + reject(idbTransaction.error); + }; + idbTransaction.onabort = function () { + reject(idbTransaction.error); + }; + }); + } + + Transaction.prototype.objectStore = function () { + return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments)); + }; + + proxyProperties(Transaction, '_tx', [ + 'objectStoreNames', + 'mode', + ]); + + proxyMethods(Transaction, '_tx', IDBTransaction, [ + 'abort', + ]); + + function UpgradeDB(db, oldVersion, transaction) { + this._db = db; + this.oldVersion = oldVersion; + this.transaction = new Transaction(transaction); + } + + UpgradeDB.prototype.createObjectStore = function () { + return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments)); + }; + + proxyProperties(UpgradeDB, '_db', [ + 'name', + 'version', + 'objectStoreNames', + ]); + + proxyMethods(UpgradeDB, '_db', IDBDatabase, [ + 'deleteObjectStore', + 'close', + ]); + + function DB(db) { + this._db = db; + } + + DB.prototype.transaction = function () { + return new Transaction(this._db.transaction.apply(this._db, arguments)); + }; + + proxyProperties(DB, '_db', [ + 'name', + 'version', + 'objectStoreNames', + ]); + + proxyMethods(DB, '_db', IDBDatabase, [ + 'close', + ]); + + // Add cursor iterators + // TODO: remove this once browsers do the right thing with promises + ['openCursor', 'openKeyCursor'].forEach((funcName) => { + [ObjectStore, Index].forEach((Constructor) => { + Constructor.prototype[funcName.replace('open', 'iterate')] = function () { + const args = toArray(arguments); + const callback = args[args.length - 1]; + const nativeObject = this._store || this._index; + const request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1)); + request.onsuccess = function () { + callback(request.result); + }; + }; + }); + }); + + // polyfill getAll + [Index, ObjectStore].forEach((Constructor) => { + if (Constructor.prototype.getAll) return; + Constructor.prototype.getAll = function (query, count) { + const instance = this; + const items = []; + + return new Promise((resolve) => { + instance.iterateCursor(query, (cursor) => { + if (!cursor) { + resolve(items); + return; + } + items.push(cursor.value); + + if (!!count && items.length == count) { + resolve(items); + return; + } + cursor.continue(); + }); + }); + }; + }); + + const exp = { + open(name, version, upgradeCallback) { + const p = promisifyRequestCall(indexedDB, 'open', [name, version]); + const { request } = p; + + request.onupgradeneeded = function (event) { + if (upgradeCallback) { + upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction)); + } + }; + + return p.then((db) => new DB(db)); + }, + delete(name) { + return promisifyRequestCall(indexedDB, 'deleteDatabase', [name]); + }, + }; + + if (typeof module !== 'undefined') { + module.exports = exp; + module.exports.default = module.exports; + } else { + self.idb = exp; + } +}()); diff --git a/public/js/material.min.js b/public/js/material.min.js new file mode 100755 index 00000000..46524fbc --- /dev/null +++ b/public/js/material.min.js @@ -0,0 +1,10 @@ +/** + * material-design-lite - Material Design Components in CSS, JS and HTML + * @version v1.3.0 + * @license Apache-2.0 + * @copyright 2015 Google, Inc. + * @link https://github.com/google/material-design-lite + */ +!function(){"use strict";function e(e,t){if(e){if(t.element_.classList.contains(t.CssClasses_.MDL_JS_RIPPLE_EFFECT)){var s=document.createElement("span");s.classList.add(t.CssClasses_.MDL_RIPPLE_CONTAINER),s.classList.add(t.CssClasses_.MDL_JS_RIPPLE_EFFECT);var i=document.createElement("span");i.classList.add(t.CssClasses_.MDL_RIPPLE),s.appendChild(i),e.appendChild(s)}e.addEventListener("click",function(s){if("#"===e.getAttribute("href").charAt(0)){s.preventDefault();var i=e.href.split("#")[1],n=t.element_.querySelector("#"+i);t.resetTabState_(),t.resetPanelState_(),e.classList.add(t.CssClasses_.ACTIVE_CLASS),n.classList.add(t.CssClasses_.ACTIVE_CLASS)}})}}function t(e,t,s,i){function n(){var n=e.href.split("#")[1],a=i.content_.querySelector("#"+n);i.resetTabState_(t),i.resetPanelState_(s),e.classList.add(i.CssClasses_.IS_ACTIVE),a.classList.add(i.CssClasses_.IS_ACTIVE)}if(i.tabBar_.classList.contains(i.CssClasses_.JS_RIPPLE_EFFECT)){var a=document.createElement("span");a.classList.add(i.CssClasses_.RIPPLE_CONTAINER),a.classList.add(i.CssClasses_.JS_RIPPLE_EFFECT);var l=document.createElement("span");l.classList.add(i.CssClasses_.RIPPLE),a.appendChild(l),e.appendChild(a)}i.tabBar_.classList.contains(i.CssClasses_.TAB_MANUAL_SWITCH)||e.addEventListener("click",function(t){"#"===e.getAttribute("href").charAt(0)&&(t.preventDefault(),n())}),e.show=n}var s={upgradeDom:function(e,t){},upgradeElement:function(e,t){},upgradeElements:function(e){},upgradeAllRegistered:function(){},registerUpgradedCallback:function(e,t){},register:function(e){},downgradeElements:function(e){}};s=function(){function e(e,t){for(var s=0;s0&&l(t.children))}function o(t){var s="undefined"==typeof t.widget&&"undefined"==typeof t.widget,i=!0;s||(i=t.widget||t.widget);var n={classConstructor:t.constructor||t.constructor,className:t.classAsString||t.classAsString,cssClass:t.cssClass||t.cssClass,widget:i,callbacks:[]};if(c.forEach(function(e){if(e.cssClass===n.cssClass)throw new Error("The provided cssClass has already been registered: "+e.cssClass);if(e.className===n.className)throw new Error("The provided className has already been registered")}),t.constructor.prototype.hasOwnProperty(C))throw new Error("MDL component classes must not have "+C+" defined as a property.");var a=e(t.classAsString,n);a||c.push(n)}function r(t,s){var i=e(t);i&&i.callbacks.push(s)}function _(){for(var e=0;e0&&this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)&&(e.keyCode===this.Keycodes_.UP_ARROW?(e.preventDefault(),t[t.length-1].focus()):e.keyCode===this.Keycodes_.DOWN_ARROW&&(e.preventDefault(),t[0].focus()))}},d.prototype.handleItemKeyboardEvent_=function(e){if(this.element_&&this.container_){var t=this.element_.querySelectorAll("."+this.CssClasses_.ITEM+":not([disabled])");if(t&&t.length>0&&this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)){var s=Array.prototype.slice.call(t).indexOf(e.target);if(e.keyCode===this.Keycodes_.UP_ARROW)e.preventDefault(),s>0?t[s-1].focus():t[t.length-1].focus();else if(e.keyCode===this.Keycodes_.DOWN_ARROW)e.preventDefault(),t.length>s+1?t[s+1].focus():t[0].focus();else if(e.keyCode===this.Keycodes_.SPACE||e.keyCode===this.Keycodes_.ENTER){e.preventDefault();var i=new MouseEvent("mousedown");e.target.dispatchEvent(i),i=new MouseEvent("mouseup"),e.target.dispatchEvent(i),e.target.click()}else e.keyCode===this.Keycodes_.ESCAPE&&(e.preventDefault(),this.hide())}}},d.prototype.handleItemClick_=function(e){e.target.hasAttribute("disabled")?e.stopPropagation():(this.closing_=!0,window.setTimeout(function(e){this.hide(),this.closing_=!1}.bind(this),this.Constant_.CLOSE_TIMEOUT))},d.prototype.applyClip_=function(e,t){this.element_.classList.contains(this.CssClasses_.UNALIGNED)?this.element_.style.clip="":this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)?this.element_.style.clip="rect(0 "+t+"px 0 "+t+"px)":this.element_.classList.contains(this.CssClasses_.TOP_LEFT)?this.element_.style.clip="rect("+e+"px 0 "+e+"px 0)":this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)?this.element_.style.clip="rect("+e+"px "+t+"px "+e+"px "+t+"px)":this.element_.style.clip=""},d.prototype.removeAnimationEndListener_=function(e){e.target.classList.remove(d.prototype.CssClasses_.IS_ANIMATING)},d.prototype.addAnimationEndListener_=function(){this.element_.addEventListener("transitionend",this.removeAnimationEndListener_),this.element_.addEventListener("webkitTransitionEnd",this.removeAnimationEndListener_)},d.prototype.show=function(e){if(this.element_&&this.container_&&this.outline_){var t=this.element_.getBoundingClientRect().height,s=this.element_.getBoundingClientRect().width;this.container_.style.width=s+"px",this.container_.style.height=t+"px",this.outline_.style.width=s+"px",this.outline_.style.height=t+"px";for(var i=this.Constant_.TRANSITION_DURATION_SECONDS*this.Constant_.TRANSITION_DURATION_FRACTION,n=this.element_.querySelectorAll("."+this.CssClasses_.ITEM),a=0;a0&&this.showSnackbar(this.queuedNotifications_.shift())},C.prototype.cleanup_=function(){this.element_.classList.remove(this.cssClasses_.ACTIVE),setTimeout(function(){this.element_.setAttribute("aria-hidden","true"),this.textElement_.textContent="",Boolean(this.actionElement_.getAttribute("aria-hidden"))||(this.setActionHidden_(!0),this.actionElement_.textContent="",this.actionElement_.removeEventListener("click",this.actionHandler_)),this.actionHandler_=void 0,this.message_=void 0,this.actionText_=void 0,this.active=!1,this.checkQueue_()}.bind(this),this.Constant_.ANIMATION_LENGTH)},C.prototype.setActionHidden_=function(e){e?this.actionElement_.setAttribute("aria-hidden","true"):this.actionElement_.removeAttribute("aria-hidden")},s.register({constructor:C,classAsString:"MaterialSnackbar",cssClass:"mdl-js-snackbar",widget:!0});var u=function(e){this.element_=e,this.init()};window.MaterialSpinner=u,u.prototype.Constant_={MDL_SPINNER_LAYER_COUNT:4},u.prototype.CssClasses_={MDL_SPINNER_LAYER:"mdl-spinner__layer",MDL_SPINNER_CIRCLE_CLIPPER:"mdl-spinner__circle-clipper",MDL_SPINNER_CIRCLE:"mdl-spinner__circle",MDL_SPINNER_GAP_PATCH:"mdl-spinner__gap-patch",MDL_SPINNER_LEFT:"mdl-spinner__left",MDL_SPINNER_RIGHT:"mdl-spinner__right"},u.prototype.createLayer=function(e){var t=document.createElement("div");t.classList.add(this.CssClasses_.MDL_SPINNER_LAYER),t.classList.add(this.CssClasses_.MDL_SPINNER_LAYER+"-"+e);var s=document.createElement("div");s.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER),s.classList.add(this.CssClasses_.MDL_SPINNER_LEFT);var i=document.createElement("div");i.classList.add(this.CssClasses_.MDL_SPINNER_GAP_PATCH);var n=document.createElement("div");n.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER),n.classList.add(this.CssClasses_.MDL_SPINNER_RIGHT);for(var a=[s,i,n],l=0;l=this.maxRows&&e.preventDefault()},L.prototype.onFocus_=function(e){this.element_.classList.add(this.CssClasses_.IS_FOCUSED)},L.prototype.onBlur_=function(e){this.element_.classList.remove(this.CssClasses_.IS_FOCUSED)},L.prototype.onReset_=function(e){this.updateClasses_()},L.prototype.updateClasses_=function(){this.checkDisabled(),this.checkValidity(),this.checkDirty(),this.checkFocus()},L.prototype.checkDisabled=function(){this.input_.disabled?this.element_.classList.add(this.CssClasses_.IS_DISABLED):this.element_.classList.remove(this.CssClasses_.IS_DISABLED)},L.prototype.checkDisabled=L.prototype.checkDisabled,L.prototype.checkFocus=function(){Boolean(this.element_.querySelector(":focus"))?this.element_.classList.add(this.CssClasses_.IS_FOCUSED):this.element_.classList.remove(this.CssClasses_.IS_FOCUSED)},L.prototype.checkFocus=L.prototype.checkFocus,L.prototype.checkValidity=function(){this.input_.validity&&(this.input_.validity.valid?this.element_.classList.remove(this.CssClasses_.IS_INVALID):this.element_.classList.add(this.CssClasses_.IS_INVALID))},L.prototype.checkValidity=L.prototype.checkValidity,L.prototype.checkDirty=function(){this.input_.value&&this.input_.value.length>0?this.element_.classList.add(this.CssClasses_.IS_DIRTY):this.element_.classList.remove(this.CssClasses_.IS_DIRTY)},L.prototype.checkDirty=L.prototype.checkDirty,L.prototype.disable=function(){this.input_.disabled=!0,this.updateClasses_()},L.prototype.disable=L.prototype.disable,L.prototype.enable=function(){this.input_.disabled=!1,this.updateClasses_()},L.prototype.enable=L.prototype.enable,L.prototype.change=function(e){this.input_.value=e||"",this.updateClasses_()},L.prototype.change=L.prototype.change,L.prototype.init=function(){if(this.element_&&(this.label_=this.element_.querySelector("."+this.CssClasses_.LABEL),this.input_=this.element_.querySelector("."+this.CssClasses_.INPUT),this.input_)){this.input_.hasAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE)&&(this.maxRows=parseInt(this.input_.getAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE),10),isNaN(this.maxRows)&&(this.maxRows=this.Constant_.NO_MAX_ROWS)),this.input_.hasAttribute("placeholder")&&this.element_.classList.add(this.CssClasses_.HAS_PLACEHOLDER),this.boundUpdateClassesHandler=this.updateClasses_.bind(this),this.boundFocusHandler=this.onFocus_.bind(this),this.boundBlurHandler=this.onBlur_.bind(this),this.boundResetHandler=this.onReset_.bind(this),this.input_.addEventListener("input",this.boundUpdateClassesHandler),this.input_.addEventListener("focus",this.boundFocusHandler),this.input_.addEventListener("blur",this.boundBlurHandler),this.input_.addEventListener("reset",this.boundResetHandler),this.maxRows!==this.Constant_.NO_MAX_ROWS&&(this.boundKeyDownHandler=this.onKeyDown_.bind(this),this.input_.addEventListener("keydown",this.boundKeyDownHandler));var e=this.element_.classList.contains(this.CssClasses_.IS_INVALID);this.updateClasses_(),this.element_.classList.add(this.CssClasses_.IS_UPGRADED),e&&this.element_.classList.add(this.CssClasses_.IS_INVALID),this.input_.hasAttribute("autofocus")&&(this.element_.focus(),this.checkFocus())}},s.register({constructor:L,classAsString:"MaterialTextfield",cssClass:"mdl-js-textfield",widget:!0});var I=function(e){this.element_=e,this.init()};window.MaterialTooltip=I,I.prototype.Constant_={},I.prototype.CssClasses_={IS_ACTIVE:"is-active",BOTTOM:"mdl-tooltip--bottom",LEFT:"mdl-tooltip--left",RIGHT:"mdl-tooltip--right",TOP:"mdl-tooltip--top"},I.prototype.handleMouseEnter_=function(e){var t=e.target.getBoundingClientRect(),s=t.left+t.width/2,i=t.top+t.height/2,n=-1*(this.element_.offsetWidth/2),a=-1*(this.element_.offsetHeight/2);this.element_.classList.contains(this.CssClasses_.LEFT)||this.element_.classList.contains(this.CssClasses_.RIGHT)?(s=t.width/2,i+a<0?(this.element_.style.top="0",this.element_.style.marginTop="0"):(this.element_.style.top=i+"px",this.element_.style.marginTop=a+"px")):s+n<0?(this.element_.style.left="0",this.element_.style.marginLeft="0"):(this.element_.style.left=s+"px",this.element_.style.marginLeft=n+"px"),this.element_.classList.contains(this.CssClasses_.TOP)?this.element_.style.top=t.top-this.element_.offsetHeight-10+"px":this.element_.classList.contains(this.CssClasses_.RIGHT)?this.element_.style.left=t.left+t.width+10+"px":this.element_.classList.contains(this.CssClasses_.LEFT)?this.element_.style.left=t.left-this.element_.offsetWidth-10+"px":this.element_.style.top=t.top+t.height+10+"px",this.element_.classList.add(this.CssClasses_.IS_ACTIVE)},I.prototype.hideTooltip_=function(){this.element_.classList.remove(this.CssClasses_.IS_ACTIVE)},I.prototype.init=function(){if(this.element_){var e=this.element_.getAttribute("for")||this.element_.getAttribute("data-mdl-for");e&&(this.forElement_=document.getElementById(e)),this.forElement_&&(this.forElement_.hasAttribute("tabindex")||this.forElement_.setAttribute("tabindex","0"),this.boundMouseEnterHandler=this.handleMouseEnter_.bind(this),this.boundMouseLeaveAndScrollHandler=this.hideTooltip_.bind(this),this.forElement_.addEventListener("mouseenter",this.boundMouseEnterHandler,!1),this.forElement_.addEventListener("touchend",this.boundMouseEnterHandler,!1),this.forElement_.addEventListener("mouseleave",this.boundMouseLeaveAndScrollHandler,!1),window.addEventListener("scroll",this.boundMouseLeaveAndScrollHandler,!0),window.addEventListener("touchstart",this.boundMouseLeaveAndScrollHandler))}},s.register({constructor:I,classAsString:"MaterialTooltip",cssClass:"mdl-tooltip"});var f=function(e){this.element_=e,this.init()};window.MaterialLayout=f,f.prototype.Constant_={MAX_WIDTH:"(max-width: 1024px)",TAB_SCROLL_PIXELS:100,RESIZE_TIMEOUT:100,MENU_ICON:"",CHEVRON_LEFT:"chevron_left",CHEVRON_RIGHT:"chevron_right"},f.prototype.Keycodes_={ENTER:13,ESCAPE:27,SPACE:32},f.prototype.Mode_={STANDARD:0,SEAMED:1,WATERFALL:2,SCROLL:3},f.prototype.CssClasses_={CONTAINER:"mdl-layout__container",HEADER:"mdl-layout__header",DRAWER:"mdl-layout__drawer",CONTENT:"mdl-layout__content",DRAWER_BTN:"mdl-layout__drawer-button",ICON:"material-icons",JS_RIPPLE_EFFECT:"mdl-js-ripple-effect",RIPPLE_CONTAINER:"mdl-layout__tab-ripple-container",RIPPLE:"mdl-ripple",RIPPLE_IGNORE_EVENTS:"mdl-js-ripple-effect--ignore-events",HEADER_SEAMED:"mdl-layout__header--seamed",HEADER_WATERFALL:"mdl-layout__header--waterfall",HEADER_SCROLL:"mdl-layout__header--scroll",FIXED_HEADER:"mdl-layout--fixed-header",OBFUSCATOR:"mdl-layout__obfuscator",TAB_BAR:"mdl-layout__tab-bar",TAB_CONTAINER:"mdl-layout__tab-bar-container",TAB:"mdl-layout__tab",TAB_BAR_BUTTON:"mdl-layout__tab-bar-button",TAB_BAR_LEFT_BUTTON:"mdl-layout__tab-bar-left-button",TAB_BAR_RIGHT_BUTTON:"mdl-layout__tab-bar-right-button",TAB_MANUAL_SWITCH:"mdl-layout__tab-manual-switch",PANEL:"mdl-layout__tab-panel",HAS_DRAWER:"has-drawer",HAS_TABS:"has-tabs",HAS_SCROLLING_HEADER:"has-scrolling-header",CASTING_SHADOW:"is-casting-shadow",IS_COMPACT:"is-compact",IS_SMALL_SCREEN:"is-small-screen",IS_DRAWER_OPEN:"is-visible",IS_ACTIVE:"is-active",IS_UPGRADED:"is-upgraded",IS_ANIMATING:"is-animating",ON_LARGE_SCREEN:"mdl-layout--large-screen-only",ON_SMALL_SCREEN:"mdl-layout--small-screen-only"},f.prototype.contentScrollHandler_=function(){if(!this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)){var e=!this.element_.classList.contains(this.CssClasses_.IS_SMALL_SCREEN)||this.element_.classList.contains(this.CssClasses_.FIXED_HEADER);this.content_.scrollTop>0&&!this.header_.classList.contains(this.CssClasses_.IS_COMPACT)?(this.header_.classList.add(this.CssClasses_.CASTING_SHADOW),this.header_.classList.add(this.CssClasses_.IS_COMPACT),e&&this.header_.classList.add(this.CssClasses_.IS_ANIMATING)):this.content_.scrollTop<=0&&this.header_.classList.contains(this.CssClasses_.IS_COMPACT)&&(this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW),this.header_.classList.remove(this.CssClasses_.IS_COMPACT),e&&this.header_.classList.add(this.CssClasses_.IS_ANIMATING))}},f.prototype.keyboardEventHandler_=function(e){e.keyCode===this.Keycodes_.ESCAPE&&this.drawer_.classList.contains(this.CssClasses_.IS_DRAWER_OPEN)&&this.toggleDrawer()},f.prototype.screenSizeHandler_=function(){this.screenSizeMediaQuery_.matches?this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN):(this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN),this.drawer_&&(this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN),this.obfuscator_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN)))},f.prototype.drawerToggleHandler_=function(e){if(e&&"keydown"===e.type){if(e.keyCode!==this.Keycodes_.SPACE&&e.keyCode!==this.Keycodes_.ENTER)return;e.preventDefault()}this.toggleDrawer()},f.prototype.headerTransitionEndHandler_=function(){this.header_.classList.remove(this.CssClasses_.IS_ANIMATING)},f.prototype.headerClickHandler_=function(){this.header_.classList.contains(this.CssClasses_.IS_COMPACT)&&(this.header_.classList.remove(this.CssClasses_.IS_COMPACT),this.header_.classList.add(this.CssClasses_.IS_ANIMATING))},f.prototype.resetTabState_=function(e){for(var t=0;t0?c.classList.add(this.CssClasses_.IS_ACTIVE):c.classList.remove(this.CssClasses_.IS_ACTIVE),this.tabBar_.scrollLeft0)return;this.setFrameCount(1);var i,n,a=e.currentTarget.getBoundingClientRect();if(0===e.clientX&&0===e.clientY)i=Math.round(a.width/2),n=Math.round(a.height/2);else{var l=void 0!==e.clientX?e.clientX:e.touches[0].clientX,o=void 0!==e.clientY?e.clientY:e.touches[0].clientY;i=Math.round(l-a.left),n=Math.round(o-a.top)}this.setRippleXY(i,n),this.setRippleStyles(!0),window.requestAnimationFrame(this.animFrameHandler.bind(this))}},S.prototype.upHandler_=function(e){e&&2!==e.detail&&window.setTimeout(function(){this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE)}.bind(this),0)},S.prototype.init=function(){if(this.element_){var e=this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER);this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)||(this.rippleElement_=this.element_.querySelector("."+this.CssClasses_.RIPPLE),this.frameCount_=0,this.rippleSize_=0,this.x_=0,this.y_=0,this.ignoringMouseDown_=!1,this.boundDownHandler=this.downHandler_.bind(this),this.element_.addEventListener("mousedown",this.boundDownHandler),this.element_.addEventListener("touchstart",this.boundDownHandler),this.boundUpHandler=this.upHandler_.bind(this),this.element_.addEventListener("mouseup",this.boundUpHandler),this.element_.addEventListener("mouseleave",this.boundUpHandler),this.element_.addEventListener("touchend",this.boundUpHandler),this.element_.addEventListener("blur",this.boundUpHandler),this.getFrameCount=function(){return this.frameCount_},this.setFrameCount=function(e){this.frameCount_=e},this.getRippleElement=function(){return this.rippleElement_},this.setRippleXY=function(e,t){this.x_=e,this.y_=t},this.setRippleStyles=function(t){if(null!==this.rippleElement_){var s,i,n,a="translate("+this.x_+"px, "+this.y_+"px)";t?(i=this.Constant_.INITIAL_SCALE,n=this.Constant_.INITIAL_SIZE):(i=this.Constant_.FINAL_SCALE,n=this.rippleSize_+"px",e&&(a="translate("+this.boundWidth/2+"px, "+this.boundHeight/2+"px)")),s="translate(-50%, -50%) "+a+i,this.rippleElement_.style.webkitTransform=s,this.rippleElement_.style.msTransform=s,this.rippleElement_.style.transform=s,t?this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING):this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING)}},this.animFrameHandler=function(){this.frameCount_-- >0?window.requestAnimationFrame(this.animFrameHandler.bind(this)):this.setRippleStyles(!1)})}},s.register({constructor:S,classAsString:"MaterialRipple",cssClass:"mdl-js-ripple-effect",widget:!1})}(); +//# sourceMappingURL=material.min.js.map diff --git a/public/js/promise.js b/public/js/promise.js new file mode 100755 index 00000000..b90788a6 --- /dev/null +++ b/public/js/promise.js @@ -0,0 +1,368 @@ +/** + * setImmediate polyfill v1.0.1, supports IE9+ + * © 2014–2015 Dmitry Korobkin + * Released under the MIT license + * github.com/Octane/setImmediate + */ +window.setImmediate || (function () { + let uid = 0; + const storage = {}; + let firstCall = true; + const { slice } = Array.prototype; + const message = 'setImmediatePolyfillMessage'; + + function fastApply(args) { + const func = args[0]; + switch (args.length) { + case 1: + return func(); + case 2: + return func(args[1]); + case 3: + return func(args[1], args[2]); + } + return func.apply(window, slice.call(args, 1)); + } + + function callback(event) { + const key = event.data; + let data; + if (typeof key === 'string' && key.indexOf(message) == 0) { + data = storage[key]; + if (data) { + delete storage[key]; + fastApply(data); + } + } + } + + window.setImmediate = function setImmediate() { + const id = uid++; + const key = message + id; + let i = arguments.length; + const args = new Array(i); + while (i--) { + args[i] = arguments[i]; + } + storage[key] = args; + if (firstCall) { + firstCall = false; + window.addEventListener('message', callback); + } + window.postMessage(key, '*'); + return id; + }; + + window.clearImmediate = function clearImmediate(id) { + delete storage[message + id]; + }; +}()); + +/** + * Promise polyfill v1.0.10 + * requires setImmediate + * + * © 2014–2015 Dmitry Korobkin + * Released under the MIT license + * github.com/Octane/Promise + */ +(function (global) { + const STATUS = '[[PromiseStatus]]'; + const VALUE = '[[PromiseValue]]'; + const ON_FUlFILLED = '[[OnFulfilled]]'; + const ON_REJECTED = '[[OnRejected]]'; + const ORIGINAL_ERROR = '[[OriginalError]]'; + const PENDING = 'pending'; + const INTERNAL_PENDING = 'internal pending'; + const FULFILLED = 'fulfilled'; + const REJECTED = 'rejected'; + const NOT_ARRAY = 'not an array.'; + const REQUIRES_NEW = 'constructor Promise requires "new".'; + const CHAINING_CYCLE = 'then() cannot return same Promise that it resolves.'; + + const setImmediate = global.setImmediate || require('timers').setImmediate; + const isArray = Array.isArray || function (anything) { + return Object.prototype.toString.call(anything) == '[object Array]'; + }; + + function InternalError(originalError) { + this[ORIGINAL_ERROR] = originalError; + } + + function isInternalError(anything) { + return anything instanceof InternalError; + } + + function isObject(anything) { + // Object.create(null) instanceof Object → false + return Object(anything) === anything; + } + + function isCallable(anything) { + return typeof anything === 'function'; + } + + function isPromise(anything) { + return anything instanceof Promise; + } + + function identity(value) { + return value; + } + + function thrower(reason) { + throw reason; + } + + function enqueue(promise, onFulfilled, onRejected) { + if (!promise[ON_FUlFILLED]) { + promise[ON_FUlFILLED] = []; + promise[ON_REJECTED] = []; + } + promise[ON_FUlFILLED].push(onFulfilled); + promise[ON_REJECTED].push(onRejected); + } + + function clearAllQueues(promise) { + delete promise[ON_FUlFILLED]; + delete promise[ON_REJECTED]; + } + + function callEach(queue) { + let i; + const { length } = queue; + for (i = 0; i < length; i++) { + queue[i](); + } + } + + function call(resolve, reject, value) { + const anything = toPromise(value); + if (isPromise(anything)) { + anything.then(resolve, reject); + } else if (isInternalError(anything)) { + reject(anything[ORIGINAL_ERROR]); + } else { + resolve(value); + } + } + + function toPromise(anything) { + let then; + if (isPromise(anything)) { + return anything; + } + if (isObject(anything)) { + try { + then = anything.then; + } catch (error) { + return new InternalError(error); + } + if (isCallable(then)) { + return new Promise((resolve, reject) => { + setImmediate(() => { + try { + then.call(anything, resolve, reject); + } catch (error) { + reject(error); + } + }); + }); + } + } + return null; + } + + function resolvePromise(promise, resolver) { + function resolve(value) { + if (promise[STATUS] == PENDING) { + fulfillPromise(promise, value); + } + } + function reject(reason) { + if (promise[STATUS] == PENDING) { + rejectPromise(promise, reason); + } + } + try { + resolver(resolve, reject); + } catch (error) { + reject(error); + } + } + + function fulfillPromise(promise, value) { + let queue; + const anything = toPromise(value); + if (isPromise(anything)) { + promise[STATUS] = INTERNAL_PENDING; + anything.then( + (value) => { + fulfillPromise(promise, value); + }, + (reason) => { + rejectPromise(promise, reason); + }, + ); + } else if (isInternalError(anything)) { + rejectPromise(promise, anything[ORIGINAL_ERROR]); + } else { + promise[STATUS] = FULFILLED; + promise[VALUE] = value; + queue = promise[ON_FUlFILLED]; + if (queue && queue.length) { + clearAllQueues(promise); + callEach(queue); + } + } + } + + function rejectPromise(promise, reason) { + const queue = promise[ON_REJECTED]; + promise[STATUS] = REJECTED; + promise[VALUE] = reason; + if (queue && queue.length) { + clearAllQueues(promise); + callEach(queue); + } + } + + function Promise(resolver) { + const promise = this; + if (!isPromise(promise)) { + throw new TypeError(REQUIRES_NEW); + } + promise[STATUS] = PENDING; + promise[VALUE] = undefined; + resolvePromise(promise, resolver); + } + + Promise.prototype.then = function (onFulfilled, onRejected) { + const promise = this; + let nextPromise; + onFulfilled = isCallable(onFulfilled) ? onFulfilled : identity; + onRejected = isCallable(onRejected) ? onRejected : thrower; + nextPromise = new Promise((resolve, reject) => { + function tryCall(func) { + let value; + try { + value = func(promise[VALUE]); + } catch (error) { + reject(error); + return; + } + if (value === nextPromise) { + reject(new TypeError(CHAINING_CYCLE)); + } else { + call(resolve, reject, value); + } + } + function asyncOnFulfilled() { + setImmediate(tryCall, onFulfilled); + } + function asyncOnRejected() { + setImmediate(tryCall, onRejected); + } + switch (promise[STATUS]) { + case FULFILLED: + asyncOnFulfilled(); + break; + case REJECTED: + asyncOnRejected(); + break; + default: + enqueue(promise, asyncOnFulfilled, asyncOnRejected); + } + }); + return nextPromise; + }; + + Promise.prototype.catch = function (onRejected) { + return this.then(identity, onRejected); + }; + + Promise.resolve = function (value) { + const anything = toPromise(value); + if (isPromise(anything)) { + return anything; + } + return new Promise((resolve, reject) => { + if (isInternalError(anything)) { + reject(anything[ORIGINAL_ERROR]); + } else { + resolve(value); + } + }); + }; + + Promise.reject = function (reason) { + return new Promise((resolve, reject) => { + reject(reason); + }); + }; + + Promise.race = function (values) { + return new Promise((resolve, reject) => { + let i; + let length; + if (isArray(values)) { + length = values.length; + for (i = 0; i < length; i++) { + call(resolve, reject, values[i]); + } + } else { + reject(new TypeError(NOT_ARRAY)); + } + }); + }; + + Promise.all = function (values) { + return new Promise((resolve, reject) => { + let fulfilledCount = 0; + let promiseCount = 0; + let anything; + let length; + let value; + let i; + if (isArray(values)) { + values = values.slice(0); + length = values.length; + for (i = 0; i < length; i++) { + value = values[i]; + anything = toPromise(value); + if (isPromise(anything)) { + promiseCount++; + anything.then( + (function (index) { + return function (value) { + values[index] = value; + fulfilledCount++; + if (fulfilledCount == promiseCount) { + resolve(values); + } + }; + }(i)), + reject, + ); + } else if (isInternalError(anything)) { + reject(anything[ORIGINAL_ERROR]); + } else { + // [1, , 3] → [1, undefined, 3] + values[i] = value; + } + } + if (!promiseCount) { + resolve(values); + } + } else { + reject(new TypeError(NOT_ARRAY)); + } + }); + }; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = global.Promise || Promise; + } else if (!global.Promise) { + global.Promise = Promise; + } +}(this)); diff --git a/public/js/storage.js b/public/js/storage.js new file mode 100755 index 00000000..1900f2d5 --- /dev/null +++ b/public/js/storage.js @@ -0,0 +1,156 @@ +const OtherTables = ['categories', 'config', 'swmsg', 'notifications'] +const MainTables = ['todos', 'projects'] +const allMethod = ['sync_post_', 'sync_patch_', 'delete_'] + +// ------------------------------------- + +let idbKeyval = (() => { + let db; + + // console.log('idbKeyval...') + + function getDB() { + if (!db) { + // console.log('CREO DB STORAGE JS !') + db = new Promise((resolve, reject) => { + const openreq = indexedDB.open('mydb3', 13); + + openreq.onerror = () => { + reject(openreq.error); + }; + + openreq.onupgradeneeded = () => { + // First time setup: create an empty object store + for (const mytab of MainTables) { + openreq.result.createObjectStore(mytab, { keyPath: '_id' }); + for (const mymeth of allMethod) { + const tab = mymeth + mytab + openreq.result.createObjectStore(tab, { keyPath: '_id' }); + } + } + for (const mytab of OtherTables) { + openreq.result.createObjectStore(mytab, { keyPath: '_id' }); + } + }; + + openreq.onsuccess = () => { + resolve(openreq.result); + }; + }); + } + return db; + } + + async function withStore(type, table, callback) { + const db = await getDB(); + return new Promise((resolve, reject) => { + const transaction = db.transaction(table, type); + transaction.oncomplete = () => resolve(); + transaction.onerror = () => reject(transaction.error); + callback(transaction.objectStore(table)); + }); + } + + return { + getArrayByTable(nametable, data) { + if (nametable === 'todos') { + return data.todos + } if (nametable === 'projects') { + return data.projects + } + }, + + async get(key) { + let req; + await withStore('readonly', 'keyval', store => { + req = store.get(key); + }); + return req.result; + }, + + // jsonCopy(src) { + // return JSON.parse(JSON.stringify(src)); + // }, + + // contains(a, b) { + // // array matches + // if (Array.isArray(b)) { + // return b.some(x => a.indexOf(x) > -1); + // } + // // string match + // return a.indexOf(b) > -1; + // }, + + async getdata(table, key) { + let req; + + console.log('getdata', table, key) + + await withStore('readonly', table, store => { + // console.log('store', store, 'key', key) + req = store.get(key); + // console.log(' req', req) + }); + + if (req) { + return req.result; + } else { + return null; + } + }, + async getalldata(table) { + let req; + await withStore('readonly', table, store => { + req = store.getAll(); + }); + return req.result; + }, + set(key, value) { + let req; + /*await withStore('readwrite', 'keyval', store => { + req = store.put(value, key); + }); + + */ + if (req) + return req.result; + else + return null + }, + async setdata(table, value) { + let req; + // console.log('setdata', table, value) + + await withStore('readwrite', table, store => { + req = store.put(value); + }); + return req.result; + }, + async delete(key) { + return withStore('readwrite', 'keyval', store => { + store.delete(key); + }); + }, + async deletedata(table, key) { + return withStore('readwrite', table, store => { + store.delete(key); + }); + }, + async clearalldata(table) { + // console.log('clearalldata', table) + return withStore('readwrite', table, store => { + store.clear(); + }); + }, + }; +})(); + +// iOS add-to-homescreen is missing IDB, or at least it used to. +// I haven't tested this in a while. +if (!self.indexedDB) { + idbKeyval = { + get: key => Promise.resolve(localStorage.getItem(key)), + set: (key, val) => Promise.resolve(localStorage.setItem(key, val)), + delete: key => Promise.resolve(localStorage.removeItem(key)), + }; +} diff --git a/public/js/track.js b/public/js/track.js new file mode 100755 index 00000000..da706b55 --- /dev/null +++ b/public/js/track.js @@ -0,0 +1,34 @@ +function geturl() { + const miaurl = document.location.href + + if (miaurl.includes('localhost')) { + return 'https://127.0.0.1:8084' + } + return '' +} + +function getidtrack() { + const miaurl = document.location.href + + if (miaurl.includes('test.') || miaurl.includes('localhost')) { + return '4c40a07bc88a9c50c9b70dc9c5cd8e2e' + } + return 'ccfd6c90e17b6809f9717675764c3f5d' // Associazione Shen +} + +let owa_baseUrl = `${geturl()}owa/`; +if (owa_cmds) var owa_cmds = []; +else var owa_cmds = owa_cmds || []; +owa_cmds.push(['setSiteId', getidtrack()]); +owa_cmds.push(['trackPageView']); +// owa_cmds.push(['trackClicks']); + +(function () { + const _owa = document.createElement('script'); + _owa.type = 'text/javascript'; + _owa.async = true; + owa_baseUrl = (document.location.protocol == 'https:' ? window.owa_baseSecUrl || owa_baseUrl.replace(/http:/, 'https:') : owa_baseUrl); + _owa.src = `${owa_baseUrl}modules/base/js/owa.tracker-combined-min.js`; + const _owa_s = document.getElementsByTagName('script')[0]; + _owa_s.parentNode.insertBefore(_owa, _owa_s); +}()); diff --git a/public/js/workbox-sw-6-1.js b/public/js/workbox-sw-6-1.js new file mode 100755 index 00000000..eceac39e --- /dev/null +++ b/public/js/workbox-sw-6-1.js @@ -0,0 +1,2 @@ +!function(){'use strict';try{self['workbox:sw:6.1.0']&&_()}catch(t){}const t={backgroundSync:'background-sync',broadcastUpdate:'broadcast-update',cacheableResponse:'cacheable-response',core:'core',expiration:'expiration',googleAnalytics:'offline-ga',navigationPreload:'navigation-preload',precaching:'precaching',rangeRequests:'range-requests',routing:'routing',strategies:'strategies',streams:'streams',recipes:'recipes'};self.workbox=new class{constructor(){return this.v={},this.Pt={debug:'localhost'===self.location.hostname,modulePathPrefix:null,modulePathCb:null},this.$t=this.Pt.debug?'dev':'prod',this.jt=!1,new Proxy(this,{get(e,s){if(e[s])return e[s];const o=t[s];return o&&e.loadModule('workbox-'+o),e[s]}})}setConfig(t={}){if(this.jt)throw new Error('Config must be set before accessing workbox.* modules');Object.assign(this.Pt,t),this.$t=this.Pt.debug?'dev':'prod'}loadModule(t){const e=this.St(t);try{importScripts(e),this.jt=!0}catch(s){throw console.error(`Unable to import module '${t}' from '${e}'.`),s}}St(t){if(this.Pt.modulePathCb)return this.Pt.modulePathCb(t,this.Pt.debug);let e=['https://storage.googleapis.com/workbox-cdn/releases/6.1.0'];const s=`${t}.${this.$t}.js`,o=this.Pt.modulePathPrefix;return o&&(e=o.split('/'),''===e[e.length-1]&&e.splice(e.length-1,1)),e.push(s),e.join('/')}}}(); +//# sourceMappingURL=workbox-sw.js.map diff --git a/public/js/workbox-sw.js b/public/js/workbox-sw.js new file mode 100644 index 00000000..f9a60efc --- /dev/null +++ b/public/js/workbox-sw.js @@ -0,0 +1,2 @@ +!function(){"use strict";try{self["workbox:sw:5.1.4"]&&_()}catch(t){}const t={backgroundSync:"background-sync",broadcastUpdate:"broadcast-update",cacheableResponse:"cacheable-response",core:"core",expiration:"expiration",googleAnalytics:"offline-ga",navigationPreload:"navigation-preload",precaching:"precaching",rangeRequests:"range-requests",routing:"routing",strategies:"strategies",streams:"streams"};self.workbox=new class{constructor(){return this.v={},this.t={debug:"localhost"===self.location.hostname,modulePathPrefix:null,modulePathCb:null},this.s=this.t.debug?"dev":"prod",this.o=!1,new Proxy(this,{get(e,s){if(e[s])return e[s];const o=t[s];return o&&e.loadModule("workbox-"+o),e[s]}})}setConfig(t={}){if(this.o)throw new Error("Config must be set before accessing workbox.* modules");Object.assign(this.t,t),this.s=this.t.debug?"dev":"prod"}loadModule(t){const e=this.i(t);try{importScripts(e),this.o=!0}catch(s){throw console.error(`Unable to import module '${t}' from '${e}'.`),s}}i(t){if(this.t.modulePathCb)return this.t.modulePathCb(t,this.t.debug);let e=["https://storage.googleapis.com/workbox-cdn/releases/5.1.4"];const s=`${t}.${this.s}.js`,o=this.t.modulePathPrefix;return o&&(e=o.split("/"),""===e[e.length-1]&&e.splice(e.length-1,1)),e.push(s),e.join("/")}}}(); +//# sourceMappingURL=workbox-sw.js.map diff --git a/scripts/_ALL_SITES/comunitanuovomondo.app/package.json b/scripts/_ALL_SITES/comunitanuovomondo.app/package.json index c46062e9..3641351b 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.42", + "version": "1.2.44", "description": "Comunita Nuovo Mondo", "productName": "ComunitaNuovoMondo", "author": "Surya", @@ -9,7 +9,7 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8083 APP_VERSION='1.2.42' quasar dev", + "dev": "PORT=8083 APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.44' 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/freeplanet.app/package.json b/scripts/_ALL_SITES/freeplanet.app/package.json index 562f28b6..3ecfa5d0 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.42", + "version": "1.2.44", "description": "freeplanet", "productName": "freeplanet", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8087 APP_VERSION='1.2.42' quasar dev", + "dev": "PORT=8087 APP_VERSION='1.2.44' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8087 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8097 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8087 APP_VERSION='1.2.44' 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 8c6064f3..dc2e1253 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.42", + "version": "1.2.44", "description": "Gruppo Macro", "productName": "Gruppo Macro", "author": "Surya", @@ -9,20 +9,20 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8089 APP_VERSION='1.2.42' quasar dev", + "dev": "PORT=8089 APP_VERSION='1.2.44' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", - "buildspa": "APP_VERSION='1.2.42' quasar build -m spa", + "buildspa": "APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.44' 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 73ce9ab3..26abe9b6 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.42", + "version": "1.2.44", "description": "kolibrilab", "productName": "kolibrilab", "author": "Surya Paolo", @@ -8,11 +8,11 @@ "keywords": [], "license": "MIT", "scripts": { - "dev": "PORT=8083 APP_VERSION='1.2.42' quasar dev", + "dev": "PORT=8083 APP_VERSION='1.2.44' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.44' 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/nutriben-naturopatia.it/package.json b/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json index 8e5574bc..14f6ac94 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.42", + "version": "1.2.44", "description": "Nutriben", "productName": "Nutriben", "author": "Surya", @@ -9,20 +9,20 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8093 APP_VERSION='1.2.42' quasar dev", + "dev": "PORT=8093 APP_VERSION='1.2.44' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", - "buildspa": "APP_VERSION='1.2.42' quasar build -m spa", + "buildspa": "APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.44' 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 4261e0a0..c6a9d5c1 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.42", + "version": "1.2.44", "description": "PiuCheBuono", "productName": "PiuCheBuono", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8085 APP_VERSION='1.2.42' quasar dev", + "dev": "PORT=8085 APP_VERSION='1.2.44' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.44' 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 83622df0..faac8f43 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.42", + "version": "1.2.44", "description": "Siamo la Rete Italiana di Scambio Orizzontale, abbiamo creato questa piattaforma per metterla al servizio di chi vuole riscoprire il valore della condivisione e della cooperazione. Valori semplici e profondi che ci aiutano a ritrovare il Senso della Vita, perduto in questa società consumista, e riporti quei Sani Pricìpi Naturali ed Umani di Fratellanza che intere popolazioni antiche conoscevano bene.", "productName": "Riso", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "APP_VERSION='1.2.42' PORT=8084 quasar dev", + "dev": "APP_VERSION='1.2.44' PORT=8084 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.42' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.44' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.44' 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.42' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.42' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.44' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.44' 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/deploy_on_prod_gruppomacro.app.sh b/scripts/deploy_on_prod_gruppomacro.app.sh index 6c07024b..f573baa0 100755 --- a/scripts/deploy_on_prod_gruppomacro.app.sh +++ b/scripts/deploy_on_prod_gruppomacro.app.sh @@ -19,12 +19,10 @@ fi if [[ $risposta == "Y" || $risposta == "y" ]]; then mv public/upload/products ../../ - mv public/upload/profile ../../ npm run buildpwa mv ../../products public/upload/ - mv ../../profile public/upload/ echo "Sincronizzazione in remoto $SERVERDIR_WEBSITE ..." rsync -e 'ssh -p 8822' -a dist/pwa/ pcbuser@pcb:$SERVERDIR_WEBSITE diff --git a/scripts/deploy_on_test_gruppomacro.app.sh b/scripts/deploy_on_test_gruppomacro.app.sh index 30294651..f47247a6 100755 --- a/scripts/deploy_on_test_gruppomacro.app.sh +++ b/scripts/deploy_on_test_gruppomacro.app.sh @@ -17,12 +17,10 @@ cp .env.test.gruppomacro .env.production sleep 1 mv public/upload/products ../../ - mv public/upload/profile ../../ npm run buildpwatest mv ../../products public/upload/ - mv ../../profile public/upload/ echo "Sincronizzazione $SERVERDIR_WEBSITE in remoto..." rsync -e 'ssh -p 8822' -a --exclude 'upload' dist/pwa/ pcbuser@pcb:$SERVERDIR_WEBSITE diff --git a/src-pwa/custom-service-worker.js b/src-pwa/custom-service-worker.js index 7db0c3c8..0a9e3fa4 100755 --- a/src-pwa/custom-service-worker.js +++ b/src-pwa/custom-service-worker.js @@ -3,12 +3,15 @@ /* global workbox */ /* global cfgenv */ -const VITE_APP_VERSION = "1.2.42"; +const VITE_APP_VERSION = '1.2.44'; // Costanti di configurazione const DYNAMIC_CACHE = 'dynamic-cache-v2'; const baseUrl = self.location.origin; +const CACHE_VERSION = VITE_APP_VERSION; +const CACHE_PREFIX = self.location.hostname || 'app'; + function extractDomain(url) { return url.replace(/^https?:\/\//, ''); } @@ -32,38 +35,30 @@ console.log('API_DOMAIN', API_DOMAIN); const CACHE_NAME = 'pwa-cache-' + VITE_APP_VERSION; // Nome della cache -importScripts('workbox/workbox-sw.js') +importScripts('workbox/workbox-sw.js'); -import { clientsClaim } from 'workbox-core' +import { clientsClaim } from 'workbox-core'; import { precacheAndRoute, cleanupOutdatedCaches, createHandlerBoundToURL } from 'workbox-precaching'; import { registerRoute, NavigationRoute } from 'workbox-routing'; import { setCacheNameDetails } from 'workbox-core'; -import { - NetworkOnly, - NetworkFirst, - StaleWhileRevalidate, - CacheFirst, -} from 'workbox-strategies'; +import { NetworkOnly, NetworkFirst, StaleWhileRevalidate, CacheFirst } from 'workbox-strategies'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; import { ExpirationPlugin } from 'workbox-expiration'; -const debug = false; //process.env.NODE_ENV !== 'production'; +const debug = false; //process.env.NODE_ENV !== 'production'; if (workbox) { - // Imposta configurazione prima di tutto workbox.setConfig({ debug }); workbox.loadModule('workbox-strategies'); console.log('Workbox ESISTE ✅ '); - } else { console.error('Workbox NON CARICATO ! ❌'); } - setCacheNameDetails({ prefix: self.location.hostname, suffix: 'v2', @@ -71,7 +66,7 @@ setCacheNameDetails({ runtime: 'runtime', }); -const precacheList = (self.__WB_MANIFEST || []).filter(entry => { +const precacheList = (self.__WB_MANIFEST || []).filter((entry) => { // Esclude tutto ciò che si trova nella cartella 'upload' if (entry.url.includes('/upload/')) { return false; @@ -82,13 +77,12 @@ const precacheList = (self.__WB_MANIFEST || []).filter(entry => { // Precache solo i file filtrati precacheAndRoute(precacheList); -cleanupOutdatedCaches() - +cleanupOutdatedCaches(); // Installazione del Service Worker self.addEventListener('install', () => { console.log('[Service Worker] Installing ...'); - self.skipWaiting() + self.skipWaiting(); clientsClaim(); }); @@ -98,15 +92,12 @@ self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( - cacheNames - .filter(name => name !== CACHE_NAME && name !== DYNAMIC_CACHE) - .map((name) => caches.delete(name)) + cacheNames.filter((name) => name !== CACHE_NAME && name !== DYNAMIC_CACHE).map((name) => caches.delete(name)) ); }) ); }); - console.log(' [ VER-' + VITE_APP_VERSION + ' ] _---------________------ PAO: this is my custom service worker: '); try { @@ -121,7 +112,6 @@ let ISTEST = self.location.hostname.startsWith('test'); let ISLOCALE = self.location.hostname.startsWith('localhost'); console.log('SW- app ver ' + VITE_APP_VERSION); - // Function helpers async function writeData(table, data) { console.log('writeData', table, data); @@ -141,8 +131,6 @@ async function deleteItemFromData(table, id) { } if (workbox) { - - /*if (process.env.MODE !== 'ssr' || process.env.PROD) { registerRoute( new NavigationRoute( @@ -152,101 +140,76 @@ if (workbox) { ) }*/ - // Gestione richieste statiche + // Static assets (JS, CSS, Fonts) - CacheFirst: caricamento rapidissimo registerRoute( - ({ request }) => request.destination === 'document' || request.destination === 'script' || request.destination === 'style', - new StaleWhileRevalidate({ cacheName: CACHE_NAME }) - ); - - // Cache strategy registrations - registerRoute( - new RegExp(/\.(?:png|gif|jpg|jpeg)$/), + ({ request }) => ['script', 'style', 'font'].includes(request.destination), new CacheFirst({ - cacheName: `images-upload-${VITE_APP_VERSION}`, + cacheName: `${CACHE_PREFIX}-static-assets-${CACHE_VERSION}`, plugins: [ - new CacheableResponsePlugin({ statuses: [200] }), - new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 Days + new CacheableResponsePlugin({ statuses: [0, 200] }), + new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 giorni ], }) ); + // Immagini - CacheFirst con scadenza e limite registerRoute( - new RegExp(/\.(?:svg)$/), + ({ request }) => request.destination === 'image', new CacheFirst({ - cacheName: `svg-${VITE_APP_VERSION}`, + cacheName: `${CACHE_PREFIX}-images-${CACHE_VERSION}`, plugins: [ - new CacheableResponsePlugin({ statuses: [200] }), - new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 Days + new CacheableResponsePlugin({ statuses: [0, 200] }), + new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 giorni ], }) ); + // Google Fonts - StaleWhileRevalidate per aggiornamenti trasparenti registerRoute( - new RegExp(/.*(?:googleapis|gstatic)\.com.*$/), + /^https:\/\/fonts\.(?:googleapis|gstatic)\.com/, new StaleWhileRevalidate({ - cacheName: `google-fonts-${VITE_APP_VERSION}`, - plugins: [ - new CacheableResponsePlugin({ statuses: [200] }), - new ExpirationPlugin({ maxEntries: 30 }), - ], + cacheName: `${CACHE_PREFIX}-google-fonts-${CACHE_VERSION}`, + plugins: [new CacheableResponsePlugin({ statuses: [0, 200] }), new ExpirationPlugin({ maxEntries: 30 })], }) ); - /*registerRoute( - new RegExp('^/myicons/.*$'), // Corrisponde a percorsi come "/icons/miaicona.ico" - new CacheFirst({ - cacheName: `icon-cache-${VITE_APP_VERSION}`, - plugins: [ - new CacheableResponsePlugin({ statuses: [200] }), - new ExpirationPlugin({ maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 Days - ], - }) - );*/ - + // HTML documents - NetworkFirst: garantisce contenuti aggiornati e fallback cache registerRoute( - new RegExp(/\.(?:js|css|font)$/), - new StaleWhileRevalidate({ - cacheName: `js-css-fonts-${VITE_APP_VERSION}`, + ({ request }) => request.destination === 'document', + new NetworkFirst({ + cacheName: `${CACHE_PREFIX}-html-cache-${CACHE_VERSION}`, + networkTimeoutSeconds: 5, // timeout rapido plugins: [ - new CacheableResponsePlugin({ statuses: [200] }), + new CacheableResponsePlugin({ statuses: [0, 200] }), + new ExpirationPlugin({ maxEntries: 20, maxAgeSeconds: 24 * 60 * 60 }), // 1 giorno ], }) ); - // Gestione API + // API calls - NetworkFirst con fallback cache e timeout veloce registerRoute( ({ url }) => url.hostname === API_DOMAIN, - new NetworkFirst({ fetchOptions: { credentials: 'include' } }) + new NetworkFirst({ + cacheName: `${CACHE_PREFIX}-api-cache-${CACHE_VERSION}`, + networkTimeoutSeconds: 5, + fetchOptions: { credentials: 'include' }, + plugins: [ + new CacheableResponsePlugin({ statuses: [0, 200] }), + new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 5 * 60 }), // 5 minuti + ], + }) ); - /*registerRoute( - (routeData) => routeData.event.request.headers.get('accept').includes('text/html'), - async (args) => { - let response = await caches.match(args.event.request); - if (response) return response; - - try { - response = await fetch(args.event.request); - const cache = await caches.open('dynamic'); - cache.put(args.event.request.url, response.clone()); - return response; - } catch (err) { - return caches.match('/offline'); - } - } - );*/ - registerRoute(new RegExp('/admin/'), new NetworkOnly()); function generateUUID() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => + (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) ); } - const syncStore = {}; - self.addEventListener('message', event => { + self.addEventListener('message', (event) => { if (event.data && (event.data.type === 'SKIP_WAITING' || event.data.action === 'skipWaiting')) { self.skipWaiting(); } @@ -259,8 +222,6 @@ if (workbox) { console.log(event.data); }); - - // Funzione per gestire richieste API async function handleApiRequest(request) { try { @@ -269,10 +230,13 @@ if (workbox) { // Se la risposta non è valida, restituisci un errore personalizzato if (!response.ok) { console.warn('[SW] API Response Error:', response.status, response.statusText); - return new Response(JSON.stringify({ - error: 'API error', - message: `❌ Invalid response from API: ${response.status} ${response.statusText}`, - }), { status: response.status, headers: { 'Content-Type': 'application/json' } }); + return new Response( + JSON.stringify({ + error: 'API error', + message: `❌ Invalid response from API: ${response.status} ${response.statusText}`, + }), + { status: response.status, headers: { 'Content-Type': 'application/json' } } + ); } return response; @@ -280,10 +244,13 @@ if (workbox) { console.error('[Service Worker] API request error ❌:', error); // Restituisci una risposta di errore personalizzata - return new Response(JSON.stringify({ - error: 'Network error', - message: '❌ Unable to fetch from API: ' + error.message, - }), { status: 503, headers: { 'Content-Type': 'application/json' } }); + return new Response( + JSON.stringify({ + error: 'Network error', + message: '❌ Unable to fetch from API: ' + error.message, + }), + { status: 503, headers: { 'Content-Type': 'application/json' } } + ); } } @@ -314,9 +281,11 @@ if (workbox) { const cachedResponse = await cache.match(request); if (cachedResponse) { // Aggiorna in background mentre restituisci la risposta in cache - event.waitUntil(fetchAndCache(request).catch((error) => { - console.error('[SW] Background fetch and cache error ❌:', error); - })); + event.waitUntil( + fetchAndCache(request).catch((error) => { + console.error('[SW] Background fetch and cache error ❌:', error); + }) + ); return cachedResponse; } @@ -327,10 +296,13 @@ if (workbox) { console.error('[SW] Cache miss and network error ❌:', error); // Restituisci una risposta di fallback personalizzata - return new Response(JSON.stringify({ - error: 'Network error', - message: 'Unable to fetch resource from network or cache.', - }), { status: 503, headers: { 'Content-Type': 'application/json' } }); + return new Response( + JSON.stringify({ + error: 'Network error', + message: 'Unable to fetch resource from network or cache.', + }), + { status: 503, headers: { 'Content-Type': 'application/json' } } + ); } } @@ -339,7 +311,6 @@ if (workbox) { const { request } = event; const url = new URL(request.url); try { - // Ignora richieste non gestibili if (request.method !== 'GET' || url.protocol !== 'https:') { return; @@ -352,13 +323,13 @@ if (workbox) { // Gestione richieste API if (url.hostname === API_DOMAIN) { - if (debug) console.log('E\' una RICHIESTA API!'); + if (debug) console.log("E' una RICHIESTA API!"); event.respondWith(handleApiRequest(request)); return; } // Gestione risorse statiche e altre richieste - if (debug) console.log('E\' una RICHIESTA statica...'); + if (debug) console.log("E' una RICHIESTA statica..."); event.respondWith(cacheWithStaleWhileRevalidate(request, event)); } catch (error) { console.error('[Service Worker] Fetch error ❌:', error); @@ -366,12 +337,12 @@ if (workbox) { }); // Gestione degli errori non catturati - self.addEventListener('unhandledrejection', event => { + self.addEventListener('unhandledrejection', (event) => { console.error('[Service Worker] Unhandled rejection ❌:', event.reason); }); // Gestione degli errori globali - self.addEventListener('error', event => { + self.addEventListener('error', (event) => { console.error('[Service Worker] Global error ❌:', event.error); }); @@ -382,8 +353,7 @@ if (workbox) { // console.log('Request mode:', request.mode); // } - - self.addEventListener('sync', event => { + self.addEventListener('sync', (event) => { console.log('[Service Worker V5] Background syncing', event); let mystrparam = event.tag; @@ -401,7 +371,7 @@ if (workbox) { headers.append('x-refrtok', refreshToken); event.waitUntil( - readAllData(table).then(alldata => { + readAllData(table).then((alldata) => { const myrecs = [...alldata]; let errorfromserver = false; @@ -420,11 +390,12 @@ if (workbox) { cache: 'no-cache', mode: 'cors', body: JSON.stringify(rec), - }).then(() => { - deleteItemFromData(table, rec._id); - deleteItemFromData('swmsg', mystrparam); }) - .catch(err => { + .then(() => { + deleteItemFromData(table, rec._id); + deleteItemFromData('swmsg', mystrparam); + }) + .catch((err) => { if (err.message === 'Failed to fetch') { errorfromserver = true; } @@ -461,7 +432,7 @@ if (workbox) { self.clients.openWindow(notification.data.url); } notification.close(); - }), + }) ); } }); diff --git a/src/assets/quasar-logo-vertical.svg b/src/assets/quasar-logo-vertical.svg deleted file mode 100755 index 82108310..00000000 --- a/src/assets/quasar-logo-vertical.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/components/CCatalogoCard/CCatalogoCard.vue b/src/components/CCatalogoCard/CCatalogoCard.vue index c663a742..64accc30 100755 --- a/src/components/CCatalogoCard/CCatalogoCard.vue +++ b/src/components/CCatalogoCard/CCatalogoCard.vue @@ -77,8 +77,8 @@ 'book-image-fixed': complete, 'cursor-pointer': !complete, 'shadow-4': !optcatalogo.pdf, - 'border-box': optcatalogo.pdf, }" + :img-class="optcatalogo.pdf ? 'border-box' : ''" :style="{ zIndex: 2, width: @@ -99,7 +99,7 @@
--> - - props.modelValue, (newVal) => { optcatalogo.value = { ...newVal }; // updateCatalogoPadre() - }, { deep: true }); + }, { deep: false }); function updateCatalogoPadre() { emit('update:modelValue', optcatalogo.value); diff --git a/src/components/CJSONViewer/CJSONViewer.scss b/src/components/CJSONViewer/CJSONViewer.scss new file mode 100755 index 00000000..8bd29de3 --- /dev/null +++ b/src/components/CJSONViewer/CJSONViewer.scss @@ -0,0 +1,27 @@ +.json-container { + background-color: #f8f8f8; + padding: 15px; + border-radius: 6px; + font-family: monospace; + white-space: pre-wrap; + word-break: break-word; + } + + .json-key { + color: brown; + } + .json-string { + color: green; + } + .json-boolean { + color: blue; + } + .json-number { + color: darkorange; + } + .json-null { + color: magenta; + } + .json-error { + color: red; + } \ No newline at end of file diff --git a/src/components/CJSONViewer/CJSONViewer.ts b/src/components/CJSONViewer/CJSONViewer.ts new file mode 100755 index 00000000..64cbe477 --- /dev/null +++ b/src/components/CJSONViewer/CJSONViewer.ts @@ -0,0 +1,57 @@ +import { computed, defineComponent, onBeforeMount, onBeforeUnmount, onMounted, ref, toRef, toRefs, watch } from 'vue'; + +import { tools } from '@tools'; +import { costanti } from '@costanti'; +import { useGlobalStore } from '@store/globalStore'; +import { useUserStore } from '@store/UserStore'; +import { useI18n } from 'vue-i18n'; + +export default defineComponent({ + name: 'CJSONViewer', + props: { + json: { + type: [Object, Array, String, null], + required: true, + }, + }, + setup(props) { + const { t } = useI18n(); + + // Funzione di highlight della sintassi JSON + function syntaxHighlight(json: string): string { + return json + .replace(/&/g, '&') + .replace(//g, '>') + .replace( + /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, + (match) => { + let cls = 'json-value'; + if (/^"/.test(match)) { + if (/:$/.test(match)) cls = 'json-key'; + else cls = 'json-string'; + } else if (/true|false/.test(match)) cls = 'json-boolean'; + else if (/null/.test(match)) cls = 'json-null'; + else if (/^-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?$/.test(match)) cls = 'json-number'; + return `${match}`; + } + ); + } + + // Formatta e applica la colorazione + const highlightedJson = () => { + try { + const data = typeof props.json === 'string' ? JSON.parse(props.json) : props.json; + const jsonString = JSON.stringify(data, null, 2); + return syntaxHighlight(jsonString); + } catch (e) { + return `${t('invalid_json')}`; + } + }; + + return { + highlightedJson, + t, + }; + }, +}); diff --git a/src/components/CJSONViewer/CJSONViewer.vue b/src/components/CJSONViewer/CJSONViewer.vue new file mode 100755 index 00000000..a73e4004 --- /dev/null +++ b/src/components/CJSONViewer/CJSONViewer.vue @@ -0,0 +1,9 @@ + + + + diff --git a/src/components/CJSONViewer/index.ts b/src/components/CJSONViewer/index.ts new file mode 100755 index 00000000..ceaa6397 --- /dev/null +++ b/src/components/CJSONViewer/index.ts @@ -0,0 +1 @@ +export { default as CJSONViewer } from './CJSONViewer.vue' diff --git a/src/components/CMyEditElem/CMyEditElem.ts b/src/components/CMyEditElem/CMyEditElem.ts index ca35112c..f5afc8c4 100755 --- a/src/components/CMyEditElem/CMyEditElem.ts +++ b/src/components/CMyEditElem/CMyEditElem.ts @@ -366,7 +366,7 @@ export default defineComponent({ ); } - console.log('Area di stampa MOUNTED... ',myel.value.catalogo.areadistampa) + // console.log('Area di stampa MOUNTED... ',myel.value.catalogo.areadistampa) } catch (error) { console.log(error); } diff --git a/src/components/CTestLungo/CTestLungo.scss b/src/components/CTestLungo/CTestLungo.scss new file mode 100755 index 00000000..2800084f --- /dev/null +++ b/src/components/CTestLungo/CTestLungo.scss @@ -0,0 +1,38 @@ + +.cltitlebg{ + +} + +.titletext { + color: white; + font-size: 3rem; + font-weight: 500; + line-height: 3rem; + text-shadow: .25rem .25rem .5rem black; + letter-spacing: .00937em; + opacity: 0.9; +} + +@media (max-width: 718px) { + // PER VERSIONE MOBILE + .titletext { + color: white; + font-size: 2rem; + font-weight: 500; + line-height: 2rem; + text-shadow: .25rem .25rem .5rem black; + } +} + +.q-img__content > div{ + background: rgba(0,0,0,0.17) !important; +} + + +pre { + background: #f4f4f4; + padding: 10px; + border-radius: 5px; + max-width: 100%; + overflow-x: auto; +} \ No newline at end of file diff --git a/src/components/CTestLungo/CTestLungo.ts b/src/components/CTestLungo/CTestLungo.ts new file mode 100755 index 00000000..ceaa0690 --- /dev/null +++ b/src/components/CTestLungo/CTestLungo.ts @@ -0,0 +1,106 @@ +import { computed, defineComponent, onBeforeMount, onBeforeUnmount, onMounted, ref, toRef, toRefs, watch } from 'vue'; + +import { tools } from '@tools'; +import { costanti } from '@costanti'; +import { useGlobalStore } from '@store/globalStore'; +import { useUserStore } from '@store/UserStore'; +import { useI18n } from 'vue-i18n'; +import { CJSONViewer } from '@src/components/CJSONViewer'; + +export default defineComponent({ + name: 'CTestLungo', + props: {}, + components: { CJSONViewer}, + setup(props, { attrs, slots, emit }) { + const { t } = useI18n(); + const globalStore = useGlobalStore(); + const userStore = useUserStore(); + + const testServer = ref({}); + + const serverhost = ref(''); + + const loading = ref(false); + const error = ref(''); + + const callLog = ref([]); + + const myrecfiltertoggle = ref(0); + + const SERVER_TEST = ref([ + { key: 1, label: 'Test (FreePlanet)', host: 'https://test.freeplanet.app:3001' }, + { key: 2, label: 'Produzione', host: tools.getServerHost() }, + { key: 3, label: 'Locale', host: 'https://localhost:3000' }, + { key: 4, label: 'Host IP', host: globalStore.site.host_ip }, + { key: 5, label: 'Host', host: globalStore.site.host }, + { key: 6, label: 'Host Api', host: globalStore.site.host_api }, + { key: 7, label: 'Host Api IP', host: globalStore.site.host_api_ip }, + ]); + + watch( + () => myrecfiltertoggle.value, + (value: any, oldValue: any) => { + if (value) { + const trovato = SERVER_TEST.value.find((rec: any) => rec.key === value); + if (trovato) { + globalStore.serverHost = trovato.host; + ricarica(); + } + } + } + ); + const getoptions = computed(() => { + const arr = []; + for (const rec of SERVER_TEST.value) { + arr.push({ label: rec.label, value: rec.key }); + } + + return arr; + }); + + function mounted() { + // ricarica(); + + // globalStore.getStatSite(); + } + + async function ricarica(timeout?: number = 60000) { + loading.value = true; + error.value = null; + + try { + testServer.value = {}; + callLog.value.push(`${new Date().toISOString()}: Eseguo Chiamata... timeout: ${timeout}`); + testServer.value = await globalStore.loadPageTestLungo(timeout); + callLog.value.push(`${new Date().toISOString()}: Success: Called loadPageTestLungo (${timeout})`); + } catch (err) { + console.error('Errore nella richiesta:', err.message || err); + if (err.code === 'ECONNABORTED') { + error.value = 'Timeout: la richiesta ha superato il tempo massimo consentito.'; + } else { + error.value = 'Errore nella comunicazione col server. Controlla la connessione.'; + } + callLog.value.push(`${new Date().toISOString()}: Error: ${err instanceof Error ? err.message : JSON.stringify(err)}`); + } finally { + loading.value = false; + } + + } + + onMounted(mounted); + + return { + t, + tools, + getoptions, + costanti, + testServer, + ricarica, + myrecfiltertoggle, + loading, + error, + serverhost, + callLog, + }; + }, +}); diff --git a/src/components/CTestLungo/CTestLungo.vue b/src/components/CTestLungo/CTestLungo.vue new file mode 100755 index 00000000..f4e2e47a --- /dev/null +++ b/src/components/CTestLungo/CTestLungo.vue @@ -0,0 +1,76 @@ + + + + diff --git a/src/components/CTestLungo/index.ts b/src/components/CTestLungo/index.ts new file mode 100755 index 00000000..21f05c53 --- /dev/null +++ b/src/components/CTestLungo/index.ts @@ -0,0 +1 @@ +export { default as CTestLungo } from './CTestLungo.vue' diff --git a/src/db/static_data.ts b/src/db/static_data.ts index 1577b9f4..46f49f29 100755 --- a/src/db/static_data.ts +++ b/src/db/static_data.ts @@ -69,6 +69,16 @@ function getDynamicPages(site: ISites): IListRoutes[] { inmenu: false, infooter: false, }, + { + active: true, + order: 400, + path: '/test-lungo', + materialIcon: 'fas fa-test', + name: 'mypages.test_lungo', + component: () => import('@src/views/testLungo/testLungo.vue'), + inmenu: false, + infooter: false, + }, { active: true, order: 15, diff --git a/src/root/hosp/hosp.ts b/src/root/hosp/hosp.ts index 24342e1b..1dc535b3 100755 --- a/src/root/hosp/hosp.ts +++ b/src/root/hosp/hosp.ts @@ -12,7 +12,7 @@ import { CNotifAtTop } from '@src/components/CNotifAtTop' import { CUserNonVerif } from '@src/components/CUserNonVerif' import { CTitlePage } from '@src/components/CTitlePage' -import { CMapsEsempio } from '@src/components/CMapsEsempio' +// import { CMapsEsempio } from '@src/components/CMapsEsempio' import { CVerifyEmail } from '@src/components/CVerifyEmail' import { CVerifyTelegram } from '@src/components/CVerifyTelegram' import { useGlobalStore } from '@store/globalStore' @@ -27,7 +27,7 @@ import { shared_consts } from '@src/common/shared_vuejs' export default defineComponent({ name: 'hosp', - components: { CSkill, CMapsEsempio, CNotifAtTop, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitlePage, LandingFooter }, + components: { CSkill, CNotifAtTop, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitlePage, LandingFooter }, setup() { return { colmyHosp, diff --git a/src/root/mainview/mainview.ts b/src/root/mainview/mainview.ts index 75250d3a..65232a25 100755 --- a/src/root/mainview/mainview.ts +++ b/src/root/mainview/mainview.ts @@ -11,7 +11,7 @@ import { CUserNonVerif } from '@src/components/CUserNonVerif' import { CStatusReg } from '@src/components/CStatusReg' import { CCopyBtn } from '@src/components/CCopyBtn' import { CCheckIfIsLogged } from '@src/components/CCheckIfIsLogged' -import { CMapsEsempio } from '@src/components/CMapsEsempio' +// import { CMapsEsempio } from '@src/components/CMapsEsempio' import { CEventsCalendar } from '@src/components/CEventsCalendar' import { useGlobalStore } from '@store/globalStore' import { useUserStore } from '@store/UserStore' @@ -28,7 +28,7 @@ import MixinMetaTags from '@src/mixins/mixin-metatags' export default defineComponent({ name: 'mainview', components: { - CSkill, CMapsEsempio, CDashboard, CUserNonVerif, CMainView, CCopyBtn, + CSkill, CDashboard, CUserNonVerif, CMainView, CCopyBtn, CNotifAtTop, LandingFooter, CCheckIfIsLogged, CStatusReg, CEventsCalendar, CPresentazione, CMyPageElem }, diff --git a/src/root/mobility/mobility.ts b/src/root/mobility/mobility.ts index 9f620854..5a6c6efd 100755 --- a/src/root/mobility/mobility.ts +++ b/src/root/mobility/mobility.ts @@ -8,7 +8,7 @@ import { CFinder } from '@src/components/CFinder' import { CDashboard } from '@src/components/CDashboard' import { CTitleBanner } from '@src/components/CTitleBanner' import { CUserNonVerif } from '@src/components/CUserNonVerif' -import { CMapsEsempio } from '@src/components/CMapsEsempio' +// import { CMapsEsempio } from '@src/components/CMapsEsempio' import { CVerifyEmail } from '@src/components/CVerifyEmail' import { CVerifyTelegram } from '@src/components/CVerifyTelegram' import { useGlobalStore } from '@store/globalStore' @@ -20,7 +20,7 @@ import MixinUsers from '@src/mixins/mixin-users' export default defineComponent({ name: 'mobility', - components: { CSkill, CMapsEsempio, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitleBanner }, + components: { CSkill, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitleBanner }, setup() { return { tools, diff --git a/src/root/provapao/provapao.ts b/src/root/provapao/provapao.ts index be96ac8a..b81ae85f 100755 --- a/src/root/provapao/provapao.ts +++ b/src/root/provapao/provapao.ts @@ -9,7 +9,7 @@ import { CFinder } from '@src/components/CFinder' import { CDashboard } from '@src/components/CDashboard' import { CTitlePage } from '@src/components/CTitlePage' import { CUserNonVerif } from '@src/components/CUserNonVerif' -import { CMapsEsempio } from '@src/components/CMapsEsempio' +// import { CMapsEsempio } from '@src/components/CMapsEsempio' import { CVerifyEmail } from '@src/components/CVerifyEmail' import { CVerifyTelegram } from '@src/components/CVerifyTelegram' import { LandingFooter } from '@src/components/LandingFooter' @@ -22,7 +22,7 @@ import { costanti } from '@costanti' export default defineComponent({ name: 'ProvaPao', - components: { CSkill, CMapsEsempio, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitlePage, LandingFooter }, + components: { CSkill, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitlePage, LandingFooter }, setup() { diff --git a/src/root/scuola/scuola.ts b/src/root/scuola/scuola.ts index 5f7ce29d..2f18ed2a 100755 --- a/src/root/scuola/scuola.ts +++ b/src/root/scuola/scuola.ts @@ -8,7 +8,7 @@ import { CFinder } from '@src/components/CFinder' import { CDashboard } from '@src/components/CDashboard' import { CTitleBanner } from '@src/components/CTitleBanner' import { CUserNonVerif } from '@src/components/CUserNonVerif' -import { CMapsEsempio } from '@src/components/CMapsEsempio' +// import { CMapsEsempio } from '@src/components/CMapsEsempio' import { CVerifyEmail } from '@src/components/CVerifyEmail' import { CVerifyTelegram } from '@src/components/CVerifyTelegram' import { useGlobalStore } from '@store/globalStore' @@ -20,7 +20,7 @@ import MixinUsers from '@src/mixins/mixin-users' export default defineComponent({ name: 'work', - components: { CSkill, CMapsEsempio, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitleBanner }, + components: { CSkill, CFinder, CVerifyEmail, CVerifyTelegram, CDashboard, CUserNonVerif, CTitleBanner }, setup() { return { diff --git a/src/store/Api/Instance.ts b/src/store/Api/Instance.ts index 2900ef26..0777328f 100755 --- a/src/store/Api/Instance.ts +++ b/src/store/Api/Instance.ts @@ -131,6 +131,11 @@ async function Request(type, path, payload, responsedata = {}, options = {}) { ...responsedata, }; + // ✅ AGGIUNGI IL TIMEOUT DALLE OPTIONS + if (options?.timeout) { + config.timeout = options.timeout; // in millisecondi (es. 300000 = 5 minuti) + } + if (options?.stream) config.responseType = 'stream'; let response; diff --git a/src/store/UserStore.ts b/src/store/UserStore.ts index 5c224303..171a704f 100755 --- a/src/store/UserStore.ts +++ b/src/store/UserStore.ts @@ -1050,7 +1050,7 @@ export const useUserStore = defineStore('UserStore', { }, async execDbOp(paramquery: any) { - return Api.SendReq('/users/dbop', 'POST', paramquery) + return Api.SendReq('/users/dbop', 'POST', paramquery, false, false, 0, 5000, null, null, {timeout: 300000}) .then((res) => { return res.data diff --git a/src/store/globalStore.ts b/src/store/globalStore.ts index 0ee5a77e..e379c409 100644 --- a/src/store/globalStore.ts +++ b/src/store/globalStore.ts @@ -237,9 +237,8 @@ export const useGlobalStore = defineStore('GlobalStore', { return null; }, - sovrascriviPaginaDefaultFromTemplate: + sovrascriviPaginaDefaultFromTemplate: (state: IGlobalState) => (idTemplate: string, origDimensioni: IDimensioni) => { - const myfindelem = state.myelems.find((myelem: IMyElem) => myelem._id === idTemplate); const linkIdTemplate = origDimensioni.linkIdTemplate; @@ -261,27 +260,25 @@ export const useGlobalStore = defineStore('GlobalStore', { return null; }, - sovrascriviAreadistampaFromTemplate: - (state: IGlobalState) => (idTemplate: string, optCatalogo: IOptCatalogo) => { + sovrascriviAreadistampaFromTemplate: (state: IGlobalState) => (idTemplate: string, optCatalogo: IOptCatalogo) => { + const myfindelem = state.myelems.find((myelem: IMyElem) => myelem._id === idTemplate); - const myfindelem = state.myelems.find((myelem: IMyElem) => myelem._id === idTemplate); + const linkIdTemplate = optCatalogo.print_linkIdTemplate; - const linkIdTemplate = optCatalogo.print_linkIdTemplate; + if (myfindelem) { + const myelemtocopy = tools.jsonCopy(myfindelem); - if (myfindelem) { - const myelemtocopy = tools.jsonCopy(myfindelem); + if (myelemtocopy) { + // myelemtocopy.scheda._id = origScheda.scheda?._id; + myelemtocopy.catalogo.print_isTemplate = false; + myelemtocopy.catalogo.print_linkIdTemplate = linkIdTemplate; - if (myelemtocopy) { - // myelemtocopy.scheda._id = origScheda.scheda?._id; - myelemtocopy.catalogo.print_isTemplate = false; - myelemtocopy.catalogo.print_linkIdTemplate = linkIdTemplate; - - return myelemtocopy.catalogo; - } + return myelemtocopy.catalogo; } + } - return null; - }, + return null; + }, // conta: (state: IGlobalState) => { state.conta }, // listatodo: (state: IGlobalState) => { state.listatodo }, @@ -1451,6 +1448,19 @@ export const useGlobalStore = defineStore('GlobalStore', { return error; }); }, + async loadPageTestLungo(timeout) { + console.log('loadPageTestLungo'); + + const obj = { test: 'OK! Versione Client: ' + tools.getvers(), timeout }; + + return Api.SendReq('/api/test-lungo', 'POST', obj, false, false, 0, 5000, null, null, { timeout }) + .then((res) => { + return res; + }) + .catch((error) => { + throw error; + }); + }, async saveTable(mydata: any) { // console.log('saveTable', mydata) @@ -2523,7 +2533,6 @@ export const useGlobalStore = defineStore('GlobalStore', { areadistampa: tools.resetRecIAreaDiStampa(null), print_isTemplate: false, print_linkIdTemplate: '', - }; }, createRaccoltaCataloghiVuoto(): IOptCatalogo { diff --git a/src/views/testLungo/testLungo.scss b/src/views/testLungo/testLungo.scss new file mode 100755 index 00000000..e69de29b diff --git a/src/views/testLungo/testLungo.ts b/src/views/testLungo/testLungo.ts new file mode 100755 index 00000000..1d66a2db --- /dev/null +++ b/src/views/testLungo/testLungo.ts @@ -0,0 +1,15 @@ +import { + defineComponent, ref, computed, +} from 'vue' + +import { CTestLungo } from '../../components/CTestLungo' + +export default defineComponent({ + name: 'testLungo', + components: { CTestLungo }, + setup() { + + return { + } + }, +}) diff --git a/src/views/testLungo/testLungo.vue b/src/views/testLungo/testLungo.vue new file mode 100755 index 00000000..a5467919 --- /dev/null +++ b/src/views/testLungo/testLungo.vue @@ -0,0 +1,13 @@ + + + diff --git a/statics/upload/circuits/risviterbo/raduno_riso.jpg b/statics/upload/circuits/risviterbo/raduno_riso.jpg deleted file mode 100644 index 477055fe..00000000 Binary files a/statics/upload/circuits/risviterbo/raduno_riso.jpg and /dev/null differ diff --git a/statics/upload/gallery/cupole_geodetiche.jpg b/statics/upload/gallery/cupole_geodetiche.jpg deleted file mode 100644 index a694803d..00000000 Binary files a/statics/upload/gallery/cupole_geodetiche.jpg and /dev/null differ diff --git a/statics/upload/gallery/fuoco.jpg b/statics/upload/gallery/fuoco.jpg deleted file mode 100644 index 033d8d41..00000000 Binary files a/statics/upload/gallery/fuoco.jpg and /dev/null differ diff --git a/statics/upload/pages/home/_LEM9173.jpg b/statics/upload/pages/home/_LEM9173.jpg deleted file mode 100644 index f961c719..00000000 Binary files a/statics/upload/pages/home/_LEM9173.jpg and /dev/null differ diff --git a/statics/upload/pages/home/_LEM9212.jpg b/statics/upload/pages/home/_LEM9212.jpg deleted file mode 100644 index 1bae93ed..00000000 Binary files a/statics/upload/pages/home/_LEM9212.jpg and /dev/null differ diff --git a/statics/upload/pages/home/sm__LEM9173.jpg b/statics/upload/pages/home/sm__LEM9173.jpg deleted file mode 100644 index 7b6e6490..00000000 Binary files a/statics/upload/pages/home/sm__LEM9173.jpg and /dev/null differ diff --git a/statics/upload/profile/beachpao.jpg b/statics/upload/profile/beachpao.jpg deleted file mode 100644 index 0bcedaa3..00000000 Binary files a/statics/upload/profile/beachpao.jpg and /dev/null differ