other components... (2)

This commit is contained in:
Paolo Arena
2021-09-16 21:08:02 +02:00
parent fcc4f61f07
commit f351673917
276 changed files with 17183 additions and 3371 deletions

28
.env.development Executable file
View File

@@ -0,0 +1,28 @@
APP_VERSION="0.0.63"
SERVICE_WORKER_FILE="service-worker.js"
APP_ID="1"
DIRECTORY_LOCAL="freeplanet"
DIRECTORY_SERVER="freeplanet_serverside"
SERVERDIR_WEBSITE=""
SERVERPW_WEBSITE=""
APP_URL="http://localhost"
URL_FACEBOOK="https://www.facebook.com/freeplanetapp"
PROVA_PAOLO="PROVA ENV FUNZIONA!"
LANG_DEFAULT="it"
PAO_APP_ID="KKPPAA5KJK435J3KSS9F9D8S9F8SD98F9SDF"
MASTER_KEY="KKPPSS5KJK435J3KSS9F9D8S9F8SD3CR3T"
MONGODB_HOST="http://localhost:3000"
LOGO_REG="freeplanet-logo-full.svg"
TEST_NAME="Paolo"
TEST_SURNAME="Arena"
TEST_EMAIL="paolo.arena77@gmail.com"
TEST_USERNAME=""
TEST_PASSWORD=""
TEST_APORTADOR=""
PUBLICKEY_PUSH='BGxRrFWnPoa_ImUaWXmeEOFVI9VNKVKaAPsvsM1XY6wn24yxp9MyOQ4crNYCJKxSXV65Y1GblW5_VLoamedcZ1I'
IN_CONSTRUCTION="0"
DEBUG="1"
TELEGRAM_SUPPORT=""
PROJECT_ID_MAIN="5cc0a13fe5c9d156728f400a"
TEST_CELL=""
ISTEST=true

28
.env.production Executable file
View File

@@ -0,0 +1,28 @@
APP_VERSION="0.0.63"
SERVICE_WORKER_FILE="service-worker.js"
APP_ID="1"
DIRECTORY_LOCAL=freeplanet
DIRECTORY_SERVER=freeplanet_serverside
SERVERDIR_WEBSITE=www.freeplanet.app
SERVERPW_WEBSITE=pwdadmin@1AOK
APP_URL="https://www.freeplanet.app"
URL_FACEBOOK="https://www.facebook.com/freeplanetapp"
PROVA_PAOLO="PROVA ENV FUNZIONA!"
LANG_DEFAULT="it"
PAO_APP_ID="KKPPAA5KJK435J3KSS9F9D8S9F8SD98F9SDF"
MASTER_KEY="KKPPSS5KJK435J3KSS9F9D8S9F8SD3CR3T"
MONGODB_HOST="https://www.freeplanet.app:3000"
LOGO_REG='freeplanet-logo-full.svg'
TEST_NAME=""
TEST_SURNAME=""
TEST_EMAIL=""
TEST_USERNAME=""
TEST_PASSWORD=""
TEST_APORTADOR="------"
PUBLICKEY_PUSH="BNM-cEpTbPVc_ujXf3QOC8ggf7b-X44P44esfJUWqNOFq1XhWCoZJpOi71_cbXC5SnfO9HassQ6OouAYgtBA9Pw"
IN_CONSTRUCTION="1"
DEBUG="1"
TELEGRAM_SUPPORT="https://t.me/freeplanet_supporto"
PROJECT_ID_MAIN="5cc0a13fe5c9d156728f400a"
TEST_CELL=""
ISTEST=false

View File

@@ -1,4 +1,4 @@
const { resolve } = require('path'); const { resolve } = require('path')
module.exports = { module.exports = {
// https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
// This option interrupts the configuration hierarchy at this file // This option interrupts the configuration hierarchy at this file
@@ -21,20 +21,20 @@ module.exports = {
}, },
env: { env: {
node: true,
browser: true, browser: true,
}, },
// Rules order is important, please avoid shuffling them // Rules order is important, please avoid shuffling them
extends: [ extends: [
'airbnb-typescript/base', // Base ESLint recommended rules
// Base ESLint recommended rules
// 'eslint:recommended', // 'eslint:recommended',
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage // https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage
// ESLint typescript rules // ESLint typescript rules
// 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
// consider disabling this class of rules if linting takes too long // consider disabling this class of rules if linting takes too long
// 'plugin:@typescript-eslint/recommended-requiring-type-checking', 'plugin:@typescript-eslint/recommended-requiring-type-checking',
// Uncomment any of the lines below to choose desired strictness, // Uncomment any of the lines below to choose desired strictness,
// but leave only one uncommented! // but leave only one uncommented!
@@ -43,6 +43,15 @@ module.exports = {
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
// https://github.com/prettier/eslint-config-prettier#installation
// usage with Prettier, provided by 'eslint-config-prettier'.
'prettier',
/*'eslint:recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'plugin:@typescript-eslint/recommended',
'plugin:vue/essential',*/
], ],
plugins: [ plugins: [
@@ -78,7 +87,8 @@ module.exports = {
'no-loop-func': 'off', 'no-loop-func': 'off',
'one-var': 'off', 'one-var': 'off',
'no-void': 'off', 'no-void': 'off',
'comma-dangle': [2, 'always-multiline'], 'comma-dangle': 'off',
// 'comma-dangle': [2, 'always-multiline'],
// 'multiline-ternary': 'off', // 'multiline-ternary': 'off',
'vue/max-attributes-per-line': [ 'vue/max-attributes-per-line': [
'error', { 'error', {
@@ -92,7 +102,7 @@ module.exports = {
}, },
}], }],
'import/first': 'off', 'import/first': 'off',
'import/named': 'error', 'import/named': 'off',
'import/namespace': 'error', 'import/namespace': 'error',
'import/default': 'error', 'import/default': 'error',
'import/export': 'error', 'import/export': 'error',
@@ -112,6 +122,7 @@ module.exports = {
'@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/semi': 'off', '@typescript-eslint/semi': 'off',
'@typescript-eslint/object-curly-spacing': 'off', '@typescript-eslint/object-curly-spacing': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
// allow debugger during development only // allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
@@ -126,6 +137,29 @@ module.exports = {
'@typescript-eslint/max-len': 'off', '@typescript-eslint/max-len': 'off',
'max-len': 'off', 'max-len': 'off',
'@typescript-eslint/naming-convention': 'off', '@typescript-eslint/naming-convention': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'no-underscore-dangle': 'off', 'no-underscore-dangle': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'prefer-const': 'off',
'no-extra-boolean-cast': 'off',
'max-attributes-per-line': 'off',
'vue/no-v-model-argument': 'off',
'@typescript-eslint/ban-types': [
'error',
{
'extendDefaults': true,
'types': {
'{}': false,
},
},
],
}, },
}; }

4
.prettierrc Normal file
View File

@@ -0,0 +1,4 @@
{
"singleQuote": true,
"semi": true
}

12
.vscode/extensions.json vendored Executable file
View File

@@ -0,0 +1,12 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"octref.vetur"
],
"unwantedRecommendations": [
"hookyqr.beautify",
"dbaeumer.jshint",
"ms-vscode.vscode-typescript-tslint-plugin"
]
}

7
.vscode/settings.json vendored Executable file
View File

@@ -0,0 +1,7 @@
{
"vetur.validation.template": false,
"vetur.format.enable": false,
"eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"],
"typescript.tsdk": "node_modules/typescript/lib",
"vetur.experimental.templateInterpolationService": true
}

54
docs/nuovo_comp2.ts.old Normal file
View File

@@ -0,0 +1,54 @@
import { defineComponent, ref, computed, PropType, onBeforeUpdate, reactive } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
export default defineComponent({
name: '',
props: {
mystr: {
type: String,
required: true,
default: '',
},
myval: {
type: Number,
required: true,
default: 0,
},
mybool: {
type: Boolean,
required: true,
default: false,
},
op: {
type: Object as PropType<IOperators>,
required: true,
},
},
components: {
},
setup(props, { emit, }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
// <div v-for="(item, i) in list" :ref="el => { divs[i] = el }">
// const list = reactive([1, 2, 3]);
// const divs = ref([]);
// Make sure to reset the refs before each update.
// onBeforeUpdate(() => {
// divs.value = [];
// });
const rec = ref<IMyPage | null>(null)
return {
}
}
})

69
docs/nuovo_comp3.ts.old Normal file
View File

@@ -0,0 +1,69 @@
import { defineComponent, ref, computed, PropType, onBeforeUpdate, reactive } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
export default defineComponent({
name: '',
// inheritAttrs: false,
props: {
// Basic type check (`null` and `undefined` values will pass any type validation)
propA: Number,
// Multiple possible types
propB: [String, Number],
// Required string
propC: {
type: String,
required: true
},
// Number with a default value
propD: {
type: Number,
default: 100
},
// Object with a default value
propE: {
type: Object,
// Object or array defaults must be returned from
// a factory function
default() {
return { message: 'hello' }
}
},
// Custom validator function
propF: {
validator(value) {
// The value must match one of these strings
return ['success', 'warning', 'danger'].includes(value)
}
},
// Function with a default value
propG: {
type: Function,
// Unlike object or array default, this is not a factory function - this is a function to serve as a default value
default() {
return 'Default function'
}
},
components: {},
setup(props, { emit, attrs, slots }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
// <div v-for="(item, i) in list" :ref="el => { divs[i] = el }">
// const list = reactive([1, 2, 3]);
// const divs = ref([]);
// Make sure to reset the refs before each update.
// onBeforeUpdate(() => {
// divs.value = [];
// });
const rec = ref<IMyPage | null>(null)
return {}
}
})

View File

@@ -1,7 +1,7 @@
import { defineComponent, PropType } from "vue" import { defineComponent, ref, computed } from 'vue'
import { useI18n } from '../src/boot/i18n' import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '../src/store/UserStore' import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '../src/store/globalStore' import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar' import { useQuasar } from 'quasar'
export default defineComponent({ export default defineComponent({
@@ -22,15 +22,14 @@ export default defineComponent({
required: true, required: true,
default: false, default: false,
}, },
op: {
type: Object as PropType<IOperators>,
required: true,
},
}, },
components: { setup(props, { emit }) {
// context.attrs
// context.slots
// context.emit
// context.parent
// context.root
},
setup() {
const $q = useQuasar() const $q = useQuasar()
const { t } = useI18n() const { t } = useI18n()
const userStore = useUserStore() const userStore = useUserStore()

12
file.out.txt Normal file
View File

@@ -0,0 +1,12 @@
/home/paolo/myproject/newfreeplanet/src-pwa/pwa-flag.d.ts
0:0 error Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src-pwa/pwa-flag.d.ts.
The file must be included in at least one of the projects provided
/home/paolo/myproject/newfreeplanet/src/components/CMySingleEvent/CMySingleEvent.ts
1:8 error No default export found in imported module "vue" import/default
37:18 error Unexpected empty setter 'mythis' @typescript-eslint/no-empty-function
✖ 3 problems (3 errors, 0 warnings)

View File

@@ -1,39 +1,43 @@
{ {
"name": "firstproj", "name": "freeplanet",
"version": "0.0.1", "version": "0.0.6",
"description": "A Quasar Framework app", "description": "FreePlanet",
"productName": "First Proj", "productName": "First Proj",
"author": "Paolo Arena <paolo.arena77@gmail.com>", "author": "Paolo Arena",
"private": true, "private": true,
"keywords": [
"freeplanet",
"free social"
],
"license": "MIT",
"scripts": { "scripts": {
"dev": "quasar dev", "dev": "quasar dev",
"build": "quasar build", "build": "quasar build",
"lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./", "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./",
"lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt",
"lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt",
"fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ --fix", "fix": "eslint --ext .ts,.vue --ignore-path .gitignore ./ --fix > file.out.txt",
"pwa": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m pwa", "pwa": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m pwa",
"test": "echo \"No test specified\" && exit 0", "test": "echo \"No test specified\" && exit 0",
"generate-sw": "workbox generateSW workbox-config.js" "generate-sw": "workbox generateSW workbox-config.js"
}, },
"dependencies": { "dependencies": {
"@quasar/extras": "^1.10.12", "@quasar/extras": "^1.10.12",
"@types/googlemaps": "^3.43.3", "@vue/compat": "^3.2.10",
"@types/vuelidate": "^0.7.15", "@vue/compiler-sfc": "^3.2.10",
"@vue/compat": "^3.2.8",
"@vue/compiler-sfc": "^3.2.8",
"@vue/eslint-config-standard": "^6.1.0", "@vue/eslint-config-standard": "^6.1.0",
"acorn": "^8.4.1", "@vuelidate/core": "^2.0.0-alpha.25",
"@vuelidate/validators": "^2.0.0-alpha.21",
"acorn": "^8.5.0",
"autoprefixer": "^10.3.4", "autoprefixer": "^10.3.4",
"axios": "^0.21.2", "axios": "^0.21.4",
"bcrypt-nodejs": "0.0.3",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"core-js": "^3.17.2", "core-js": "^3.17.2",
"crypto": "^1.0.1",
"date-fns": "^2.23.0", "date-fns": "^2.23.0",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"element-ui": "^2.15.6",
"eslint-plugin-quasar": "^1.0.0", "eslint-plugin-quasar": "^1.0.0",
"graphql": "^15.5.2", "graphql": "^15.5.3",
"graphql-tag": "^2.12.5", "graphql-tag": "^2.12.5",
"gsap": "^3.7.1", "gsap": "^3.7.1",
"jquery": "^3.6.0", "jquery": "^3.6.0",
@@ -48,48 +52,53 @@
"quasar": "^2.0.4", "quasar": "^2.0.4",
"quasar-extras": "^2.0.9", "quasar-extras": "^2.0.9",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"vee-validate": "^3.4.12", "vee-validate": "^4.4.10",
"vue": "^3.1.0", "vue": "^3.2.10",
"vue-class-component": "^8.0.0-rc.1", "vue-class-component": "^8.0.0-rc.1",
"vue-country-code": "^1.1.2",
"vue-i18n": "^9.1.7", "vue-i18n": "^9.1.7",
"vue-idb": "^0.2.0", "vue-idb": "^0.2.0",
"vue-loader": "^16.0.0", "vue-loader": "^16.0.0",
"vue-property-decorator": "^10.0.0-rc.3", "vue-property-decorator": "^10.0.0-rc.3",
"vue-router": "^4.0.11", "vue-router": "^4.0.11",
"vue-scroll-reveal": "^1.0.11", "vue-scroll-reveal": "^1.0.11",
"vue-svgicon": "^3.2.9", "vue-svgicon": "^4.0.0-alpha.3",
"vue2-dragula": "^2.5.5", "vue2-dragula": "^2.5.5",
"vuelidate": "^0.7.6", "vue3-tel-input": "^1.0.4",
"vuex": "^4.0.1", "vuex": "^4.0.1",
"vuex-module-decorators": "^1.0.1", "vuex-router-sync": "^6.0.0-rc.1",
"vuex-router-sync": "^5.0.0", "vuex-typex": "^3.1.9"
"vuex-typex": "^3.1.9",
"workbox": "0.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.15.4", "@babel/eslint-parser": "^7.15.4",
"@quasar/app": "^3.1.0", "@quasar/app": "^3.1.0",
"@types/bcryptjs": "^2.4.2",
"@types/googlemaps": "^3.43.3",
"@types/vue-tel-input": "^2.1.2",
"@types/vuelidate": "^0.7.15",
"@types/dotenv": "^8.2.0", "@types/dotenv": "^8.2.0",
"@types/jest": "^27.0.1", "@types/jest": "^27.0.1",
"@types/js-cookie": "^2.2.7", "@types/js-cookie": "^2.2.7",
"@types/node": "^16.7.10", "@types/node": "^16.7.13",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/eslint-plugin": "^4.31.0",
"@typescript-eslint/parser": "^4.30.0", "@typescript-eslint/parser": "^4.31.0",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1", "eslint-config-prettier": "^8.3.0",
"eslint-config-airbnb-typescript": "^14.0.0",
"eslint-plugin-import": "^2.24.2", "eslint-plugin-import": "^2.24.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-vue": "^7.17.0", "eslint-plugin-vue": "^7.17.0",
"eslint-webpack-plugin": "^3.0.1", "eslint-webpack-plugin": "^3.0.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.2", "html-webpack-plugin": "^5.3.2",
"http-proxy-middleware": "^2.0.1", "http-proxy-middleware": "^2.0.1",
"jest": "^27.1.0", "jest": "^27.1.1",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"node-sass": "^6.0.1", "node-sass": "^6.0.1",
"npm-check-updates": "^11.8.5", "npm-check-updates": "^11.8.5",
"optimize-css-assets-webpack-plugin": "^6.0.1", "optimize-css-assets-webpack-plugin": "^6.0.1",
"postcss": "^8.3.6",
"postcss-loader": "^6.1.1", "postcss-loader": "^6.1.1",
"sass-loader": "^12.1.0", "sass-loader": "^12.1.0",
"strip-ansi": "=7.0.0", "strip-ansi": "=7.0.0",
@@ -104,6 +113,9 @@
"workbox-cli": "^6.2.4", "workbox-cli": "^6.2.4",
"workbox-webpack-plugin": "^6.2.4" "workbox-webpack-plugin": "^6.2.4"
}, },
"browser": {
"crypto": false
},
"browserslist": [ "browserslist": [
"last 10 Chrome versions", "last 10 Chrome versions",
"last 10 Firefox versions", "last 10 Firefox versions",

View File

@@ -100,10 +100,15 @@ let idbKeyval = (() => {
}, },
async set(key, value) { async set(key, value) {
let req; let req;
await withStore('readwrite', 'keyval', store => { /*await withStore('readwrite', 'keyval', store => {
req = store.put(value, key); req = store.put(value, key);
}); });
return req.result;
*/
if (req)
return req.result;
else
return null
}, },
async setdata(table, value) { async setdata(table, value) {
let req; let req;

View File

@@ -35,7 +35,7 @@ module.exports = configure((ctx) => ({
// --> boot files are part of "main.js" // --> boot files are part of "main.js"
// https://v2.quasar.dev/quasar-cli/boot-files // https://v2.quasar.dev/quasar-cli/boot-files
// boot: ['vue-i18n', 'vue-meta', 'axios', 'vee-validate', 'myconfig', 'local-storage', 'error-handler', 'globalroutines', 'vue-idb', 'dragula', 'guard'], // boot: ['vue-i18n', 'vue-meta', 'axios', 'vee-validate', 'myconfig', 'local-storage', 'error-handler', 'globalroutines', 'vue-idb', 'dragula', 'guard'],
boot: ['i18n', 'axios', 'vee-validate', 'myconfig', 'local-storage', 'error-handler', 'globalroutines'], boot: ['i18n', 'axios', 'vee-validate', 'myconfig', 'local-storage', 'error-handler', 'globalroutines', 'vuetelinput'],
// https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css // https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css
css: [ css: [
@@ -90,6 +90,7 @@ module.exports = configure((ctx) => ({
chainWebpack(chain, { isServer, isClient }) { chainWebpack(chain, { isServer, isClient }) {
chain.resolve.alias chain.resolve.alias
// .set('myalias', path.resolve(__dirname, './src/somefolder')) // .set('myalias', path.resolve(__dirname, './src/somefolder'))
.set('@', helpers.root('src'))
.set('@components', helpers.root('src/components/index.ts')) .set('@components', helpers.root('src/components/index.ts'))
.set('@boot', helpers.root('src/boot/*')) .set('@boot', helpers.root('src/boot/*'))
.set('@costanti', helpers.root('src/store/Modules/costanti.ts')) .set('@costanti', helpers.root('src/store/Modules/costanti.ts'))

15
send_to_production.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
source ./.env.production
read -p "*** IN PRODUZIONE !!!!! SEI SICURO DI INVIARE GLI AGGIORNAMENTI SUL SERVER DI PRODUZIONE ?? $SERVERDIR_WEBSITE (Y/N) ? " risposta
if [[ $risposta == "Y" || $risposta == "y" ]]; then
echo "Sincronizzazione in remoto $SERVERDIR_WEBSITE ..."
sshpass -p $SERVERPW_WEBSITE rsync --port=8822 -a dist/pwa/ ftpadmin@servereng:/var/www/$SERVERDIR_WEBSITE/
echo "Finito $SERVERDIR_WEBSITE "
fi

7
send_to_test.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
source ./.env.test
echo "Sincronizzazione in remoto $SERVERDIR_WEBSITE ..."
sshpass -p $SERVERPW_WEBSITE rsync -a dist/pwa/ ftpadmin@servereng:/var/www/$SERVERDIR_WEBSITE/
echo "Finito $SERVERDIR_WEBSITE"

10
src-pwa/pwa-flag.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/* eslint-disable */
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
import "quasar/dist/types/feature-flag";
declare module "quasar/dist/types/feature-flag" {
interface QuasarFeatureFlags {
pwa: true;
}
}

10
src-pwa/pwa-flag.d.ts.off Normal file
View File

@@ -0,0 +1,10 @@
/* eslint-disable */
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
import "quasar/dist/types/feature-flag";
declare module "quasar/dist/types/feature-flag" {
interface QuasarFeatureFlags {
pwa: true;
}
}

View File

@@ -1,14 +1,19 @@
import { useRoute } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useQuasar } from 'quasar' import { useQuasar } from 'quasar'
import { BannerCookies } from '@components' import { BannerCookies } from '@/components/BannerCookies'
import { useI18n } from '@src/boot/i18n' import { useI18n } from '@src/boot/i18n'
import { useGlobalStore } from './store/globalStore' import { useGlobalStore } from '@store/globalStore'
import { useUserStore } from './store/UserStore' import { useUserStore } from '@store/UserStore'
import { Header } from './components/Header' import { Header } from '@/components/Header'
import { toolsext } from '@store/Modules/toolsext'
import globalroutines from './globalroutines/index'
import { computed } from 'vue'
import { CProvaPao } from '@/components/CProvaPao'
export default { export default {
components: { components: {
appHeader: Header, appHeader: Header,
CProvaPao,
BannerCookies, /* , CPreloadImages */ BannerCookies, /* , CPreloadImages */
}, },
setup() { setup() {
@@ -17,9 +22,12 @@ export default {
const backgroundColor = 'whitesmoke' const backgroundColor = 'whitesmoke'
const $q = useQuasar() const $q = useQuasar()
const userStore = useUserStore() const userStore = useUserStore()
const $router = useRouter()
const globalStore = useGlobalStore() const globalStore = useGlobalStore()
const { t } = useI18n(); const { t } = useI18n();
const finishLoading = computed(() => globalStore.finishLoading)
const listaRoutingNoLogin = ['/vreg?', '/offline'] const listaRoutingNoLogin = ['/vreg?', '/offline']
function meta() { function meta() {
@@ -54,28 +62,29 @@ export default {
if (chiamaautologin) { if (chiamaautologin) {
// console.log('CHIAMA autologin_FromLocalStorage') // console.log('CHIAMA autologin_FromLocalStorage')
userStore.autologin_FromLocalStorage() userStore.autologin_FromLocalStorage($router)
.then((loadstorage) => { .then((loadstorage) => {
if (loadstorage) { if (loadstorage) {
/*
if (toolsext.getLocale() !== '') { /*if (toolsext.getLocale() !== '') {
// console.log('SETLOCALE :', this.$i18n.locale) // console.log('SETLOCALE :', this.$i18n.locale)
this.$i18n.locale = toolsext.getLocale() // Set Lang $i18n.locale = toolsext.getLocale() // Set Lang
} else { } else {
userStore.setlang(this.$i18n.locale) userStore.setlang($router, this.$i18n.locale)
} }*/
*/
// console.log('lang CARICATO:', this.$i18n.locale) // console.log('lang CARICATO:', this.$i18n.locale)
// ++Todo: conv: globalroutines(this, 'loadapp', '') //++Todo PWA: globalroutines('loadapp', '')
// this.$router.replace('/')
// Create Subscription to Push Notification // Create Subscription to Push Notification
// ++Todo: conv: globalStore.createPushSubscription() globalStore.createPushSubscription()
} }
}) })
} else {
globalStore.finishLoading = true
} }
// Calling the Server for updates ? // Calling the Server for updates ?
@@ -85,7 +94,7 @@ export default {
created() created()
return { return {
finishLoading,
} }
}, },
} }

View File

@@ -1,25 +1,29 @@
<template> <template>
<div id="q-app"> <div>
<div> <q-layout view="hHh Lpr lff" class="shadow-2 rounded-borders">
<q-layout view="hHh Lpr lff" class="shadow-2 rounded-borders"> <app-header></app-header>
<app-header></app-header> <q-ajax-bar></q-ajax-bar>
<q-ajax-bar></q-ajax-bar>
<!--<CPreloadImages :arrimg="static_data.preLoadImages"> <!--<CPreloadImages :arrimg="static_data.preLoadImages">
</CPreloadImages>--> </CPreloadImages>-->
<q-page-container> <q-page-container id="mypage">
<transition name="fade" mode="out-in"> <div v-if="finishLoading">
<router-view/> <router-view/>
</transition>
</q-page-container>
</q-layout>
</div> </div>
<BannerCookies urlInfo="/policy"></BannerCookies> <q-inner-loading id="spinner" :showing="!finishLoading">
</div> <q-spinner-tail
color="primary"
size="4em">
</q-spinner-tail>
</q-inner-loading>
</q-page-container>
</q-layout>
</div>
<BannerCookies urlInfo="/policy"></BannerCookies>
</template> </template>
<script lang="ts" src="./App.ts"> <script lang="ts" src="./App.ts">
</script> </script>
<style lang="scss"> <style lang="scss">
@import './App.scss'; @import './App.scss';
</style> </style>

10
src/boot/vuetelinput.ts Executable file
View File

@@ -0,0 +1,10 @@
// @ts-ignore
import { VueTelInput } from 'vue3-tel-input'
import { boot } from 'quasar/wrappers'
// "async" is optional
export default boot( ({ app }) => {
// something to do
// @ts-ignore
app.use(VueTelInput)
})

View File

@@ -1,8 +0,0 @@
import VueTelInput from 'vue-tel-input'
import { boot } from "quasar/wrappers"
// "async" is optional
export default boot(async ({ app }) => {
// something to do
app.use(VueTelInput)
})

View File

@@ -1,41 +0,0 @@
/**
* A function that emits a side effect and does not return anything.
*/
export type Procedure = (...args: any[]) => void
export type Options = {
isImmediate: boolean
}
export function debounce<F extends Procedure>(
func: F,
waitMilliseconds = 50,
options: Options = {
isImmediate: false,
},
): F {
let timeoutId: NodeJS.Timeout | undefined
return function retA(this: any, ...args: any[]) {
const context = this
const doLater = function retB() {
timeoutId = undefined
if (!options.isImmediate) {
func.apply(context, args)
}
}
const shouldCallNow = options.isImmediate && timeoutId === undefined
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = <any>setTimeout(doLater, waitMilliseconds)
if (shouldCallNow) {
func.apply(context, args)
}
} as any
}

View File

@@ -13,6 +13,7 @@
* @api public * @api public
*/ */
// eslint-disable-next-line @typescript-eslint/ban-types
export function Debounce(func: Function, wait?: number, immediate?: boolean) { export function Debounce(func: Function, wait?: number, immediate?: boolean) {
// @ts-ignore // @ts-ignore
let timeout: any, let timeout: any,

66
src/components/CBook/CBook.scss Executable file
View File

@@ -0,0 +1,66 @@
$heightBtn: 100%;
$grayshadow: #555;
.text-subtitle-carica {
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .1rem .1rem .1rem $grayshadow;
}
.text-subtitle-certificato {
font-size: 0.75rem;
line-height: 1rem;
}
@media (max-width: 718px) {
// PER VERSIONE MOBILE
.text-subtitle-carica {
font-size: 1rem;
}
}
.op {
text-align: center !important;
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .1rem .1rem .1rem $grayshadow;
&__cell {
font-size: 1rem;
color: red;
}
&__email {
font-size: 1rem;
color: #3b5998;
}
&__email a {
text-decoration: none;
}
&__facebook a {
font-size: 1rem;
text-decoration: none;
}
&__storia {
margin-top: 1rem;
margin-bottom: 1rem;
text-align: justify;
}
}
.myimg {
border-radius: 300px !important;
}
.q-img {
&__image {
border-radius: 300px !important;
}
}

52
src/components/CBook/CBook.ts Executable file
View File

@@ -0,0 +1,52 @@
import { defineComponent, ref, computed, PropType, toRef } from 'vue'
import { IOperators } from 'model'
export default defineComponent({
name: 'CBook',
props: {
tab: {
type: String,
required: true,
},
op: {
type: Object as PropType<IOperators>,
required: true,
},
},
setup(props, { emit }) {
const mytab = toRef(props, 'tab')
function clicca() {
mytab.value = 'two'
}
function myop() {
if (!!props.op) {
return props.op
} else {
return {
index: 0,
tab: '',
name: '',
qualification: '',
sub2: '',
certifications: '',
img: '',
cell: '',
email: '',
paginaweb: '',
paginafb: '',
intro: '',
info: ''
}
}
}
return {
myop,
clicca,
mytab,
}
}
})

47
src/components/CBook/CBook.vue Executable file
View File

@@ -0,0 +1,47 @@
<template>
<q-card class="my-card text-center">
<q-img :src="myop.img" class="myimg" :alt="`${myop.name} ${myop.surname}`">
<div class="absolute-bottom text-spacetrans text-shadow">
<div class="text-h6 text-trans">{{myop.name}}</div>
<div class="text-subtitle-carica text-trans">{{myop.qualification}}</div>
</div>
</q-img>
<q-tabs v-model="mytab" class="text-teal">
<q-tab label="Info" name="one"></q-tab>
<q-tab label="Biografia" name="two"></q-tab>
</q-tabs>
<q-separator></q-separator>
<q-tab-panels v-model="mytab" animated>
<q-tab-panel name="one">
<div class="text-subtitle-carica">{{myop.disciplines}}</div>
<div v-if="myop.certifications" class="text-subtitle-certificato">{{myop.certifications}}</div>
<div class="op__cell">
<q-icon class="flex-icon" name="mobile_friendly"></q-icon>
{{myop.cell}}
</div>
<div class="op__storia" v-html="myop.intro"></div>
<q-btn rounded size="sm" color="secondary" @click="clicca()">Continua ...</q-btn>
</q-tab-panel>
<q-tab-panel name="two">
<div class="op__storia" v-html="myop.info"></div>
</q-tab-panel>
</q-tab-panels>
<!--<q-card-section>-->
<!--<div class="text-subtitle3">{{myop.disciplines}}</div>-->
<!--{{myop.info}}-->
<!--</q-card-section>-->
</q-card>
</template>
<script lang="ts" src="./CBook.ts">
</script>
<style lang="scss" scoped>
@import './CBook.scss';
</style>

1
src/components/CBook/index.ts Executable file
View File

@@ -0,0 +1 @@
export {default as CBook} from './CBook.vue'

View File

@@ -2,7 +2,7 @@
<div> <div>
<q-card class="my-card text-center"> <q-card class="my-card text-center">
<q-img :src="`statics/images/` + myop.img" class="myimg"> <q-img :src="`public/images/` + myop.img" class="myimg">
<div class="absolute-bottom text-spacetrans text-shadow"> <div class="absolute-bottom text-spacetrans text-shadow">
<div class="text-h6 text-trans">{{ myop.name }} {{ myop.surname }}</div> <div class="text-h6 text-trans">{{ myop.name }} {{ myop.surname }}</div>
<div class="text-subtitle-carica text-trans">{{ myop.qualification }}</div> <div class="text-subtitle-carica text-trans">{{ myop.qualification }}</div>

View File

@@ -2,7 +2,7 @@
background-repeat: no-repeat !important; background-repeat: no-repeat !important;
background-position: top; background-position: top;
background-size: contain !important; background-size: contain !important;
background-image: url(../../statics/images/landing_first_section.png) !important background-image: url(/public/images/landing_first_section.png) !important
} }
.landing__features { .landing__features {

View File

@@ -75,7 +75,7 @@ dark color="white" v-model="globalStore.autoplaydisc" label="Auto Play" class="s
:alt="myrec.label" :alt="myrec.label"
:name="index"> :name="index">
<div class="row q-ma-xs"> <div class="row q-ma-xs">
<CCardDiscipline :discipline="myrec" mystyle="height: 500px" v-model:autoplay="globalStore.autoplaydisc"> <CCardDiscipline :discipline="myrec" mystyle="height: 500px" autoplay.sync="globalStore.autoplaydisc">
</CCardDiscipline> </CCardDiscipline>
</div> </div>

View File

@@ -5,11 +5,11 @@ import { IDiscipline, IEvents } from 'model'
import { useCalendarStore } from '@store/CalendarStore' import { useCalendarStore } from '@store/CalendarStore'
import CMyTeacher from '@/components/CMyTeacher/CMyTeacher' import { CMyTeacher } from '@src/components/CMyTeacher'
// @ts-ignore // @ts-ignore
import MixinOperator from '../../mixins/mixin-operator' import MixinOperator from '../../mixins/mixin-operator'
import MixinUsers from '@/mixins/mixin-users' import MixinUsers from '../../mixins/mixin-users'
export default defineComponent({ export default defineComponent({
name: 'CCardDiscipline', name: 'CCardDiscipline',

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="my-card-shadow yes_shadow" style="opacity: 1 !important;"> <div class="my-card-shadow yes_shadow" style="opacity: 1 !important;">
<q-card class="my-card-discipline text-center inset-shadow" :style="mystyle"> <q-card class="my-card-discipline text-center inset-shadow" :style="mystyle">
<q-img :src="`statics/` + discipline.img_small" class="myimg" :alt="discipline.label"> <q-img :src="`public/` + discipline.img_small" class="myimg" :alt="discipline.label">
<div class="absolute-bottom text-spacetrans"> <div class="absolute-bottom text-spacetrans">
<q-btn rounded :to="discipline.linkpage"> <q-btn rounded :to="discipline.linkpage">
<div class="text-h5 disc__title shadow-max">{{ discipline.label }}</div> <div class="text-h5 disc__title shadow-max">{{ discipline.label }}</div>

View File

@@ -1,4 +1,4 @@
import { CCard } from '@components' import { CCard } from '@/components/CCard'
import MixinOperator from '../../mixins/mixin-operator' import MixinOperator from '../../mixins/mixin-operator'
import { defineComponent, ref } from 'vue' import { defineComponent, ref } from 'vue'

View File

@@ -1,6 +1,6 @@
import { tools } from '../../store/Modules/tools' import { tools } from '../../store/Modules/tools'
import { useQuasar } from 'quasar' import { useQuasar } from 'quasar'
import { useI18n } from '@/boot/i18n' import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore' import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore' import { useGlobalStore } from '@store/globalStore'
import { defineComponent } from 'vue' import { defineComponent } from 'vue'

View File

@@ -1,67 +1,114 @@
import Vue from 'vue' import { defineComponent, onMounted, PropType, ref, watch } from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools' import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { date } from 'quasar' import { date, useQuasar } from 'quasar'
@Component({ export default defineComponent({
name: 'CDate' name: 'CDate',
props: {
mydate: {
type: Object as PropType<Date>,
required: true,
},
label: {
type: String,
required: false,
default: '',
},
data_class: {
type: String,
required: false,
default: '',
},
readonly: {
type: Boolean,
required: false,
default: false,
},
disable: {
type: Boolean,
required: false,
default: false,
},
color: {
type: String,
required: false,
default: '',
},
rounded: {
type: Boolean,
required: false,
default: false,
},
outlined: {
type: Boolean,
required: false,
default: false,
},
dense: {
type: Boolean,
required: false,
default: false,
},
},
components: {},
setup(props, { emit }) {
const $q = useQuasar()
const valueInternal = ref(tools.getDateNull())
const datePicker = ref(null)
const mystyleicon = ref('font-size: 1.5rem;')
watch(() => props.mydate, (value, oldval) => {
valueInternal.value = value
})
function created() {
valueInternal.value = props.mydate
if (props.data_class !== '') {
mystyleicon.value = 'font-size: 1rem;'
}
}
function changedate(value: string) {
const datavalida = tools.convertstrtoDate(value)
if (!!datavalida) {
valueInternal.value = datavalida
console.log('EMIT: changedate', datavalida.toString())
emit('input', getDate())
} else {
console.log(' DATA NON VALIDAAAAAAAAAAAAA ', value, datavalida)
}
if (datePicker.value) {
// @ts-ignore
datePicker.value.hide()
}
}
function getdatestring() {
const mydate = tools.getstrDate(valueInternal.value)
console.log('getdatestring', mydate)
return mydate
}
function getdateyymmddstring() {
return tools.getstrYYMMDDDate(valueInternal.value)
}
function getDate() {
return valueInternal
}
onMounted(created)
return {
getdatestring,
getdateyymmddstring,
changedate,
datePicker,
}
},
}) })
export default class CDate extends Vue {
@Prop() public mydate!: Date
@Prop({ required: false, default: '' }) public label: string
@Prop({ required: false, default: '' }) public data_class!: string
@Prop({ required: false, default: false }) public readonly!: boolean
@Prop({ required: false, default: false }) public disable!: boolean
@Prop({ required: false, default: '' }) public color!: string
@Prop({ required: false, default: false }) public rounded!: boolean
@Prop({ required: false, default: false }) public outlined!: boolean
@Prop({ required: false, default: true }) public dense!: boolean
public mystyleicon: string = 'font-size: 1.5rem;'
@Watch('mydate')
public valchanged(value) {
this.valueInternal = value
}
public $refs: {
datePicker
}
private valueInternal: Date = tools.getDateNull()
public created() {
this.valueInternal = this.mydate
if (this.data_class !== '') {
this.mystyleicon = 'font-size: 1rem;'
}
}
public changedate(value) {
const datavalida = tools.convertstrtoDate(value)
if (!!datavalida) {
this.valueInternal = datavalida
console.log('EMIT: changedate', datavalida.toString())
this.$emit('input', this.getDate())
} else {
console.log(' DATA NON VALIDAAAAAAAAAAAAA ', value, datavalida)
}
this.$refs.datePicker.hide()
}
get getdatestring() {
const mydate = tools.getstrDate(this.valueInternal)
console.log('getdatestring', mydate)
return mydate
}
get getdateyymmddstring() {
return tools.getstrYYMMDDDate(this.valueInternal)
}
private getDate() {
return this.valueInternal
}
}

View File

@@ -1,9 +1,10 @@
<template> <template>
<q-input :class="data_class" :bg-color="color" :readonly="readonly" :disable="disable" debounce="1000" :dense="dense" <q-input
:value="getdatestring" stack-label :label="label" @input="changedate" :rounded="rounded" :class="data_class" :bg-color="color" :readonly="readonly" :disable="disable" debounce="1000" :dense="dense"
mask="##/##/####" :value="getdatestring" stack-label :label="label" @input="changedate" :rounded="rounded"
fill-mask mask="##/##/####"
:outlined="outlined"> fill-mask
:outlined="outlined">
<template v-slot:append> <template v-slot:append>
<q-icon name="event" class="cursor-pointer" :style="mystyleicon"> <q-icon name="event" class="cursor-pointer" :style="mystyleicon">
<q-popup-proxy v-if="!readonly" ref="datePicker"> <q-popup-proxy v-if="!readonly" ref="datePicker">

View File

@@ -1,130 +1,171 @@
import Vue from 'vue' import { defineComponent, onMounted, PropType, ref, toRef, watch } from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools' import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { date } from 'quasar' import { date, useQuasar } from 'quasar'
import { CalendarStore } from '../../store/Modules' import { useCalendarStore } from '@store/CalendarStore'
import MixinBase from '../../mixins/mixin-base' import { useI18n } from '@/boot/i18n'
import { toolsext } from '@store/Modules/toolsext'
@Component({ export default defineComponent({
name: 'CDateTime', name: 'CDate',
mixins: [MixinBase] props: {
value: {
type: Object as PropType<Date>,
required: false,
default: null,
},
valueDate: {
type: Object as PropType<Date>,
required: false,
default: null,
},
data_class: {
type: String,
required: false,
default: '',
},
canEdit: {
type: Boolean,
required: false,
default: true,
},
label: {
type: String,
required: true,
default: 'Val:',
},
disable: {
type: Boolean,
required: false,
default: false,
},
bgcolor: {
type: String,
required: false,
default: '',
},
dense: {
type: Boolean,
required: false,
default: false,
},
minuteinterval: {
type: String,
required: false,
default: '5',
},
view: {
type: String,
required: false,
default: 'date-time',
},
},
components: {},
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n();
const showDateTimeScroller = ref(false)
const saveit = ref(false)
const myvalue = ref(new Date())
const valueprec = ref(new Date())
const valueDate = toRef(props, 'valueDate')
function getclass() {
return 'calendar_comp ' + props.data_class
}
function Opening() {
// console.log('Opening', 'myvalue', myvalue, 'value', value)
saveit.value = false
valueprec.value = myvalue.value
if (myvalue.value === undefined) {
valueDate.value = new Date()
myvalue.value = tools.getstrYYMMDDDateTime(valueDate.value)
}
// console.log('Opening', valueDate, myvalue)
emit('show')
}
function Closing() {
// console.log('Closing')
if (!saveit.value) {
if (myvalue.value !== valueprec.value) {
myvalue.value = valueprec.value
tools.showNeutralNotif($q, t('db.reccanceled'))
}
}
}
watch(() => props.valueDate, (value, oldval) => {
if (props.valueDate)
myvalue.value = tools.getstrYYMMDDDateTime(props.valueDate)
})
function savetoclose() {
// console.log('Close')
saveit.value = true
showDateTimeScroller.value = false
emit('savetoclose', myvalue, valueprec)
}
function scrollerPopupStyle280() {
if ($q.screen.lt.sm) {
return {
width: '100vw',
height: '100vh',
}
} else {
return {
maxHeight: '400px',
height: '400px',
width: '280px',
}
}
}
function created() {
if (props.value !== null)
myvalue.value = props.value
else
myvalue.value = tools.getstrYYMMDDDateTime(valueDate.value)
// console.log('created myvalue', myvalue)
}
function changeval(newval: Date) {
// console.log('changeval', newval, 'value=', value, 'myvalue=', myvalue)
emit('update:value', newval)
}
function mystyle() {
if (props.label !== '')
return ''
else
return ''
}
function getstrDate(mydate: Date) {
if (props.view === 'date-time') {
return tools.getstrDateTime(mydate)
} else {
return tools.getstrDate(mydate)
}
}
created()
return {
toolsext,
changeval,
scrollerPopupStyle280,
mystyle,
getstrDate,
savetoclose,
Closing,
Opening,
getclass,
}
},
}) })
export default class CDateTime extends Vue {
public $q
public $t
@Prop({ required: false, default: null }) public value: Date
@Prop({ required: false, default: null }) public valueDate: Date
@Prop({ required: true, default: 'Val:' }) public label: string
@Prop({ required: false, default: '' }) public data_class!: string
@Prop({ required: false, default: true }) public canEdit!: boolean
@Prop({ required: false, default: false }) public disable!: boolean
@Prop({ required: false, default: '' }) public bgcolor!: string
@Prop({ required: false, default: false }) public dense: boolean
@Prop({ required: false, default: '5' }) public minuteinterval: boolean
@Prop({ required: false, default: 'date-time' }) public view: string
public mystyleicon: string = 'font-size: 1.5rem;'
public showDateTimeScroller: boolean = false
public saveit: boolean = false
public myvalue: Date = new Date()
public valueprec: Date = new Date()
get getclass() {
return 'calendar_comp ' + this.data_class
}
// @Watch('showDateTimeScroller')
public Opening() {
// console.log('Opening', 'myvalue', this.myvalue, 'value', this.value)
this.saveit = false
this.valueprec = this.myvalue
if (this.myvalue === undefined) {
this.valueDate = new Date()
this.myvalue = tools.getstrYYMMDDDateTime(this.valueDate)
}
// console.log('Opening', this.valueDate, this.myvalue)
this.$emit('show')
}
public Closing() {
// console.log('Closing')
if (!this.saveit) {
if (this.myvalue !== this.valueprec) {
this.myvalue = this.valueprec
tools.showNeutralNotif(this.$q, this.$t('db.reccanceled'))
}
}
}
@Watch('valueDate')
public changevalueDate() {
if (this.valueDate)
this.myvalue = tools.getstrYYMMDDDateTime(this.valueDate)
// console.log('changevalueDate myvalue', this.myvalue)
}
@Watch('value')
public changevalue() {
this.myvalue = this.value
// console.log('changevalue myvalue', this.myvalue)
}
public savetoclose() {
// console.log('Close')
this.saveit = true
this.showDateTimeScroller = false
this.$emit('savetoclose', this.myvalue, this.valueprec)
}
get scrollerPopupStyle280() {
if (this.$q.screen.lt.sm) {
return {
width: '100vw',
height: '100vh'
}
} else {
return {
maxHeight: '400px',
height: '400px',
width: '280px'
}
}
}
get locale() {
return CalendarStore.state.locale
}
public created() {
if (this.value !== null)
this.myvalue = this.value
else
this.myvalue = tools.getstrYYMMDDDateTime(this.valueDate)
// console.log('created myvalue', this.myvalue)
}
public changeval(newval) {
// console.log('changeval', newval, 'value=', this.value, 'myvalue=', this.myvalue)
this.$emit('update:value', newval)
}
public mystyle() {
if (this.label !== '')
return ''
else
return ''
}
public getstrDate(mydate) {
if (this.view === 'date-time') {
return tools.getstrDateTime(mydate)
} else {
return tools.getstrDate(mydate)
}
}
}

View File

@@ -1,6 +1,7 @@
<template> <template>
<div class="" :style="mystyle"> <div class="" :style="mystyle">
<q-input v-model="myvalue" <q-input
v-model="myvalue"
v-show="false" v-show="false"
color="blue-6" color="blue-6"
hide-bottom-space hide-bottom-space

View File

View File

@@ -0,0 +1,5 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: 'CECommerce',
})

View File

@@ -0,0 +1,14 @@
<template>
<div>
<ProductsList>
</ProductsList>
</div>
</template>
<script lang="ts" src="./CECommerce.ts">
</script>
<style lang="scss" scoped>
@import './CECommerce.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CECommerce} from './CECommerce.vue'

View File

@@ -0,0 +1,303 @@
$graytext: #555;
.calendar {
position: relative;
}
.my-event {
width: 100%;
position: absolute;
font-size: 12px;
}
.my-event-rel {
width: 100%;
font-size: 0.75rem;
line-height: 1.25rem;
text-align: center;
vertical-align: center;
margin-bottom: 5px;
cursor: pointer;
padding: 4px 2px 4px 2px !important;
}
.flex-container {
background-color: #ccc;
padding: 10px;
display: flex;
flex-direction: row;
align-items: stretch;
}
.flex-item {
background-color: #9f9f9f;
padding: 10px;
margin: 10px;
color: #fff;
font-size: 1rem;
}
.cal {
color: black;
font-size: 0.75rem;
font-weight: 400;
line-height: 1.25rem;
letter-spacing: 0.03333em;
&__title {
color: white;
font-weight: 700;
font-size: 1rem;
padding-bottom: 10px;
}
&__details {
color: black;
}
&__hours {
color: blue;
&-title {
color: $graytext;
}
&-content {
font-weight: 400;
}
}
&__where {
margin-top: 5px;
color: blue;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__when {
margin-top: 5px;
color: blue;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__teacher {
margin-top: 5px;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__quota {
margin-top: 5px;
&-title {
color: $graytext;
}
&-content {
}
}
&__img {
width: 100px;
height: 100px;
padding: 10px;
}
}
.listaev {
color: black;
font-size: 0.75rem;
font-weight: 400;
line-height: 1.25rem;
letter-spacing: 0.03333em;
&__date {
color: #061220;
font-size: 1rem;
}
&__title {
color: red;
font-weight: 700;
letter-spacing: 0.066em;
}
&__details {
color: black;
}
&__tdimg {
width: 150px;
height: 150px;
}
&__tdimg_small {
width: auto;
height: 50px !important;
@media (max-width: 800px) {
height: 40px !important;
}
}
&__table {
margin: 10px;
border: solid 1px #4198ef;
border-radius: 1rem;
padding: 2px;
}
&__table tr {
border: solid 1px #4198ef;
border-radius: 1rem;
}
&__table tr:hover {
background-color: #deecef;
}
&__align_center_mobile {
text-align: left;
@media (max-width: 718px) {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
}
&__align_chips {
text-align: left;
@media (max-width: 718px) {
text-align: center;
display: flex;
flex-direction: column-reverse;
align-items: center;
}
}
&__img {
padding: 0.25rem !important;
float: left;
width: 150px;
height: 150px;
border-radius: 1rem;
@media (max-width: 718px) {
// PER VERSIONE MOBILE
float: none;
text-align: center;
margin: 0 auto;
}
}
&__img:hover {
transition: transform .2s;
transform: scale(1.05);
border: inset;
border-color: blue;
border-width: 1px;
}
}
@media (max-width: 718px) {
.q-chip__content {
white-space: normal !important;
}
.q-chip > div {
white-space: normal !important;
}
.inline > div {
white-space: normal !important;
}
}
.mytoolbar {
padding: 0 2px !important;
}
.margin_avatar, .margin_avatar2, .margin_with {
margin-left: 0;
}
@media (max-width: 400px) {
.margin_avatar {
margin-left: 28px;
}
.margin_avatar2 {
margin-left: 38px;
}
.margin_with {
margin-left: 7px;
}
}
.chipbooked {
position: absolute;
left: 40px;
@media (max-width: 400px) {
left: initial;
position: initial;
}
}
.chipnews {
position: absolute;
right: 0;
@media (max-width: 400px) {
position: initial;
right: initial;
}
}
.chipmodif {
position: absolute;
margin-top: -10px;
overflow: hidden;
z-index: 1000;
box-sizing: border-box;
right: 0;
@media (max-width: 400px) {
position: initial;
right: initial;
}
}
.windowcol {
background-color: #ffffff;
// background: radial-gradient(circle, #ffffff 0%, #94dbfb 100%)
}
.mysel {
color: white;
}
.myflex {
display: flex;
flex: 1;
@media (max-width: 400px) {
flex-flow: column;
}
}
.itemprenota{
align-self: center;
color: blue;
}

View File

@@ -0,0 +1,891 @@
import { defineComponent, ref, computed, PropType, reactive, watch } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { colors, Screen, Platform, date } from 'quasar'
import { static_data } from '@src/db/static_data'
import translate from '@src/globalroutines/util'
import { lists } from '@store/Modules/lists'
import { EState, IBookedEvent, IBookedEventPage, IEvents, IMessage, IMessagePage, IOperators } from "model"
import { Logo } from '../logo'
import { Footer } from '../Footer'
import { CTitle } from '../CTitle'
import { CImgText } from '../CImgText'
import { CMyEditor } from '../CMyEditor'
import { CDateTime } from "@/components/CDateTime"
import { CMyAvatar } from '../CMyAvatar'
import { CMySingleEvent } from "@/components/CMySingleEvent"
import { CMyTeacher } from "@/components/CMyTeacher"
import { CMySelect } from '../CMySelect'
import { tools } from "@store/Modules/tools"
import { costanti } from "@costanti"
import MixinEvents from '../../mixins/mixin-events'
import { useCalendarStore } from '@store/CalendarStore'
import { toolsext } from "@store/Modules/toolsext"
export default defineComponent({
name: 'CEventsCalendar',
props: {
mysingleevent: {
type: Object as PropType<IEvents>,
required: false,
default: null,
},
showfirstN: {
type: Number,
required: false,
default: 0,
},
mybool: {
type: Boolean,
required: true,
default: false,
},
},
components: {
Logo,
Footer,
CTitle,
CImgText,
CMySelect,
CMyEditor,
CDateTime,
CMyAvatar,
CMySingleEvent,
CMyTeacher
},
setup(props, { emit, root }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
const calendarStore = useCalendarStore()
const calendarView = ref('month')
const selectedDate = ref('')
const tabeditor = ref('details')
const showPrev = ref(false)
const formDefault = ref(<IEvents> {
title: '',
details: '',
bodytext: '',
dateTimeStart: tools.getstrYYMMDDDateTime(tools.getDateNow()),
dateTimeEnd: tools.getstrYYMMDDDateTime(tools.getDateNow()),
icon: '',
bgcolor: '#839ff2'
})
const formbookEventDefault = ref(<IBookedEvent> {
userId: '',
msgbooking: '',
infoevent: '',
numpeople: 1,
numpeopleLunch: 0,
numpeopleDinner: 0,
numpeopleDinnerShared: 0,
datebooked: tools.getDateNow(),
booked: false,
modified: false
})
const formAskForDefault = ref(<IMessage> {
dest: {
idapp: process.env.APP_ID,
username: ''
},
origin: {
idapp: process.env.APP_ID,
username: ''
},
message: ''
})
const dateFormatter = ref('')
const titleFormatter: any = ref(null)
const keyValue = ref(0)
const direction = ref('forward')
const weekdays = reactive([1, 2, 3, 4, 5, 6, 0])
const viewOptions = reactive([
{ label: 'Day', value: 'day' },
{ label: '5 Day', value: '5day' },
{ label: 'Week', value: 'week' },
{ label: 'Month', value: 'month' }
])
const addEvent = ref(false)
const bookEventpage = ref(<IBookedEventPage> {
show: false,
bookedevent: {
userId: '',
numpeople: 0,
infoevent: '',
msgbooking: '',
modified: false,
booked: false
},
state: EState.None
})
const askInfopage = ref(<IMessagePage> {
show: false,
msg: {
message: ''
},
state: EState.None
})
const contextDay = ref(null)
const eventForm = ref(<IEvents> { ...formDefault })
const bookEventForm = ref({ ...formbookEventDefault })
const askInfoForm = ref(<IMessage> { ...formAskForDefault })
const displayEvent = ref(false)
const myevent = ref(null)
// const events = []
const gmt = ''
const dragging = ref(false)
const draggedEvent = ref(null)
const ignoreNextSwipe = ref(false)
const locale = computed(() => calendarStore.locale)
const { findEventIndex, UpdateDbByFields, isAlreadyBooked } = MixinEvents()
function visuAllCal() {
return props.mysingleevent === null
}
function title_cal() {
if (titleFormatter.value && locale) {
const mydate = new Date(selectedDate.value)
return titleFormatter.value.format(mydate)
}
return ''
}
function dayHeight() {
if (Screen.height < 410)
return 80
else if (Screen.height < 500)
return 100
if (Screen.height < 700)
return 110
else if (Screen.height < 800)
return 120
else
return 140
}
function theme() {
return calendarStore.theme
}
function intervalStart() {
return calendarStore.intervalRange.min * (1 / calendarStore.intervalRangeStep)
}
function intervalCount() {
return (calendarStore.intervalRange.max - calendarStore.intervalRange.min) * (1 / calendarStore.intervalRangeStep)
}
function containerStyle() {
const styles = { height: '' }
if (calendarView.value !== 'month' || (calendarView.value === 'month' && calendarStore.dayHeight === 0)) {
styles.height = `calc(100vh - ${calendarStore.titlebarHeight}px)`
}
return styles
}
// convert the events into a map of lists keyed by date
function eventsMap() {
// console.log('eventsMap')
const map = {}
calendarStore.eventlist.forEach((myevent: IEvents) => (map[tools.getstrDateTime(myevent.dateTimeStart)] = map[tools.getstrDateTime(myevent.dateTimeStart)] || []).push(myevent))
return map
}
function addOrUpdateEvent() {
if (contextDay.value && contextDay.value.bgcolor) {
return t('dialog.update')
}
return t('dialog.add')
}
function scrollerPopupStyle160() {
if ($q.screen.lt.sm) {
return {
width: '100vw',
height: '100vh'
}
} else {
return {
maxHeight: '400px',
height: '400px',
width: '160px'
}
}
}
function hasModifiedBooking() {
return (bookEventpage.value.bookedevent.numpeople !== bookEventForm.value.numpeople) ||
(bookEventpage.value.bookedevent.numpeopleLunch !== bookEventForm.value.numpeopleLunch) ||
(bookEventpage.value.bookedevent.numpeopleDinner !== bookEventForm.value.numpeopleDinner) ||
(bookEventpage.value.bookedevent.numpeopleDinnerShared !== bookEventForm.value.numpeopleDinnerShared) ||
(bookEventpage.value.bookedevent.msgbooking !== bookEventForm.value.msgbooking) ||
(bookEventpage.value.bookedevent.booked !== bookEventForm.value.booked)
}
function checkseinviaMsg() {
return (bookEventpage.value.state === EState.Creating) && (!bookEventForm.value.booked)
}
function getTitleBtnBooking() {
if (bookEventpage.value.state === EState.Creating) {
return t('dialog.book')
} else {
return t('dialog.update')
}
}
/*function $refs: {
calendar: any
}
*/
watch(locale, (val, oldval) => {
updateFormatters()
})
function mounted() {
root.$on('calendar:next', calendarNext)
root.$on('calendar:prev', calendarPrev)
root.$on('calendar:today', calendarToday)
SetToday()
// calendarStore.eventlist = events
updateFormatters()
}
function beforeMount() {
// console.log('mounted')
selectedDate.value = formatDate(tools.getDateNow())
// console.log('selectedDate', selectedDate)
calendarStore.locale = toolsext.getLocale()
updateFormatters()
}
function beforeDestroy() {
root.$off('calendar:next', calendarNext)
root.$off('calendar:prev', calendarPrev)
root.$off('calendar:today', calendarToday)
}
function showEvent(eventparam: IEvents) {
// console.log('showEvent - INIZIO')
myevent.value = eventparam
displayEvent.value = true
// console.log('showEvent - FINE ' + myevent)
}
function selectEvent(eventparam: IEvents) {
if (myevent.value === eventparam)
myevent.value = null
else
myevent.value = eventparam
}
function onDateChanged(mydate: any) {
calendarView.value = 'day'
}
function resourceClicked(resource: any) {
console.log('resource clicked:', resource)
}
function resourceDayClicked(resource: any) {
console.log('resource:day clicked:', resource)
}
function resetForm() {
eventForm.value = { ...formDefault }
}
function addEventMenu(day: any) {
console.log('addeventmenu', day)
if (calendarView.value === 'scheduler' || calendarView.value === 'week-scheduler' || calendarView.value === 'month-scheduler' || !editable.value) {
return
}
resetForm()
contextDay.value = { ...day.scope }
eventForm.value.dateTimeStart.value = tools.getstrYYMMDDDateTime(day.scope.timestamp.date + ' 21:00:00')
eventForm.value.dateTimeEnd.value = tools.getstrYYMMDDDateTime(day.scope.timestamp.date + ' 22:00:00')
console.log('eventForm', eventForm)
addEvent.value = true // show dialog
}
function addBookEventMenu(eventparam: IEvents) {
if (!userStore.isLogged || !userStore.my.verified_email) {
// Visu right Toolbar to make SignIn
globalStore.rightDrawerOpen = true
tools.showNeutralNotif($q, t('login.needlogin'))
tools.scrollToTop()
// window.scrollTo(0, 0)
// $router.push('/signin')
} else {
console.log('addBookEventMenu')
resetForm()
myevent.value = eventparam
bookEventForm.value.msgbooking = ''
bookEventForm.value.numpeople = 1
bookEventForm.value.numpeopleLunch = 0
bookEventForm.value.numpeopleDinner = 0
bookEventForm.value.numpeopleDinnerShared = 0
bookEventForm.value.booked = true
bookEventpage = EState.Creating
displayEvent = false
bookEventpage.value.show = true // show dialog
}
}
function askForInfoEventMenu(eventparam) {
if (!userStore.isLogged || !userStore.my.verified_email) {
// Visu right Toolbar to make SignIn
globalStore.rightDrawerOpen = true
tools.showNeutralNotif($q, t('login.needlogin'))
tools.scrollToTop()
// $router.push('/signin')
} else {
console.log('askForInfoEventMenu')
askInfoForm.value = { ...formAskForDefault }
myevent.value = eventparam
askInfoForm.value = {
message: ''
}
askInfopage.value = EState.Creating
displayEvent.value = false
askInfopage.value.show = true // show dialog
}
}
function clEvent(event: IEvents) {
return (isAlreadyBooked(event) ? 'text-left bg-light-green-1' : 'text-left')
}
function checkFieldUndef() {
if (eventForm.value.bodytext === undefined)
eventForm.value.bodytext = ''
if (eventForm.value.details === undefined)
eventForm.value.details = ''
}
function editEvent(eventparam: IEvents) {
console.log('editEvent - INIZIO')
resetForm()
contextDay.value = { ...eventparam }
eventForm.value = { ...eventparam }
checkFieldUndef()
eventForm.value.dateTimeStart = tools.getstrYYMMDDDateTime(eventparam.dateTimeStart)
eventForm.value.dateTimeEnd = tools.getstrYYMMDDDateTime(eventparam.dateTimeEnd)
addEvent.value = true // show dialog
}
function deleteEvent(eventparam: IEvents) {
tools.CancelEvent($q, eventparam)
}
function duplicateEvent(eventparam, numgg, numev = 1) {
for (let i = 0; i < numev; ++i) {
globalStore.DuplicateRec({ table: tools.TABEVENTS, id: eventparam._id }).then((rec) => {
if (rec) {
rec.dateTimeStart = tools.addDays(new Date(rec.dateTimeStart), numgg * (i + 1))
rec.dateTimeEnd = tools.addDays(new Date(rec.dateTimeEnd), numgg * (i + 1))
calendarStore.eventlist.push(rec)
editEvent(rec)
}
})
}
// tools.ActionRecTable(this, lists.MenuAction.DUPLICATE_RECTABLE, tools.TABEVENTS, eventparam._id, eventparam, 'db.duplicatedrecord')
}
function formatDate(mydate: any) {
let d = void 0
if (mydate !== void 0) {
d = new Date(mydate)
} else {
d = new Date()
}
const month = '' + (d.getMonth() + 1)
const day = '' + d.getDate()
const year = d.getFullYear()
return [year, tools.padTime(month), tools.padTime(day)].join('-')
}
function formatTime(mydate) {
const d = mydate !== void 0 ? new Date(mydate) : new Date(),
hours = '' + d.getHours(),
minutes = '' + d.getMinutes()
return [tools.padTime(hours), tools.padTime(minutes)].join(':')
}
function getDuration(dateTimeStart, dateTimeEnd, unit) {
const start = new Date(dateTimeStart)
const end = new Date(dateTimeEnd)
const diff = date.getDateDiff(end, start, unit)
return diff
}
function saveEvent() {
const self = this
// ++Todo VALIDATE $refs.myevent
if (true) {
// close the dialog
self.addEvent = false
const form = { ...self.eventForm }
let update = false
if (self.contextDay._id) {
// an update
update = true
} else {
// an add
}
const data = { ...form }
// ++Save into the Database
const mydatatosave = {
id: data._id,
table: tools.TABEVENTS,
fieldsvalue: data
}
if (update === true) {
UpdateDbByFields($q, data, true, contextDay.value)
} else {
const mydataadd = {
table: tools.TABEVENTS,
data
}
globalStore.saveTable(mydataadd).then((record) => {
if (record) {
tools.showPositiveNotif($q, t('db.recupdated'))
if (update === true) {
const index = self.findEventIndex(self.contextDay)
if (index >= 0) {
// @ts-ignore
calendarStore.eventlist.splice(index, 1, { ...data })
}
} else {
data._id = record._id
// add to events array
// @ts-ignore
calendarStore.eventlist.push(data)
}
} else {
tools.showNegativeNotif($q, t('db.recfailed'))
// Undo...
const index = self.findEventIndex(self.contextDay)
if (index >= 0) {
// @ts-ignore
calendarStore.eventlist.splice(index, 1, { ...self.contextDay })
}
}
})
}
self.contextDay = null
}
}
function EditBookEvent(myevent: IEvents) {
myevent = myevent
const bookedevent = calendarStore.getters.findEventBooked(myevent, false)
console.log('bookedevent', bookedevent)
if (bookedevent) {
bookEventForm.value._id = bookedevent._id
bookEventForm.value.numpeople = bookedevent.numpeople
bookEventForm.value.numpeopleLunch = bookedevent.numpeopleLunch
bookEventForm.value.numpeopleDinner = bookedevent.numpeopleDinner
bookEventForm.value.numpeopleDinnerShared = bookedevent.numpeopleDinnerShared
bookEventForm.value.infoevent = bookedevent.infoevent
bookEventForm.value.msgbooking = bookedevent.msgbooking
bookEventForm.value.booked = bookedevent.booked
bookEventForm.value.datebooked = bookedevent.datebooked
}
bookEventpage = EState.Modifying
bookEventpage.value.bookedevent = bookedevent
bookEventpage.value.show = true
}
function sendMsg(myevent: IEvents) {
const self = this
askInfopage.show = false
const data: IMessage = {
source: {
event_id: myevent._id,
infoevent: tools.gettextevent(this, myevent)
},
dest: {
idapp: process.env.APP_ID,
username: myevent.teacher
},
message: askInfoForm.message
}
MessageStore.SendMsgEvent(data).then((ris) => {
self.contextDay = null
if (ris)
tools.showPositiveNotif(self.$q, self.t('cal.sendmsg_sent'))
else
tools.showNegativeNotif(self.$q, self.t('cal.sendmsg_error'))
})
}
function saveBookEvent(myevent: IEvents) {
// ++Todo VALIDATE $refs.myevent
if (true) {
// close the dialog
bookEventpage.value.show = false
// bookEventForm.value.booked = bookEventForm.value.bookedcheck
const data: IBookedEvent = {
userId: userStore.my._id,
id_bookedevent: myevent._id,
numpeople: bookEventForm.value.numpeople,
numpeopleLunch: bookEventForm.value.numpeopleLunch,
numpeopleDinner: bookEventForm.value.numpeopleDinner,
numpeopleDinnerShared: bookEventForm.value.numpeopleDinnerShared,
infoevent: tools.gettextevent(myevent),
msgbooking: bookEventForm.value.msgbooking,
booked: bookEventForm.value.booked,
datebooked: tools.getDateNow(),
modified: (bookEventpage.value !== EState.Creating)
}
BookEvent(data).then((ris) => {
console.log('ris uscita di BookEvent', ris)
if (ris)
tools.showPositiveNotif($q, t('cal.booked') + ' ' + t('cal.event') + ' "' + myevent.title + '"')
else
tools.showNegativeNotif($q, t('cal.booked_error'))
})
contextDay.value = null
}
}
function adjustTimestamp(day: any) {
day.minute = day.minute < 15 || day.minute >= 45 ? 0 : 30
return day
}
// function getTimestamp(day) {
// return day.date + ' ' + tools.padTime(day.hour) + ':' + tools.padTime(day.minute) + ':00.000'
// }
function updateFormatters() {
try {
// console.log('tools.getLocale() =', tools.getLocale())
// console.log('Calendar', calendarStore.locale)
dateFormatter.value = new Intl.DateTimeFormat(tools.getLocale() || void 0, {
weekday: calendarStore.shortWeekdayLabel ? 'short' : 'long',
month: calendarStore.shortMonthLabel ? 'short' : 'long',
day: 'numeric',
year: 'numeric',
timeZone: 'UTC'
})
titleFormatter.value = new Intl.DateTimeFormat(locale.value || void 0, {
month: calendarStore.shortMonthLabel ? 'short' : 'long',
year: 'numeric',
timeZone: 'UTC'
})
} catch (e) {
console.error('Intl.DateTimeFormat not supported')
dateFormatter.value = void 0
}
}
function handleSwipe({ evt, ...info }) {
if (dragging.value === false) {
if (info.dur >= 30 && ignoreNextSwipe.value === false) {
if (info.direction === 'right') {
calendarPrev()
} else if (info.direction === 'left') {
calendarNext()
}
} else {
ignoreNextSwipe.value = false
}
}
stopAndPrevent(evt)
}
function onDragEnter(ev: any, eventparam) {
prevent(ev)
}
function onDragStart(ev, eventparam) {
dragging.value = true
draggedEvent.value = eventparam
stop(ev)
}
function onDragEnd(ev, eventparam) {
stopAndPrevent(ev)
resetDrag()
}
function onDragOver(ev, day, type) {
if (type === 'day') {
stopAndPrevent(ev)
return draggedEvent.value.dateTimeStart !== day.dateTimeStart
} else if (type === 'interval') {
stopAndPrevent(ev)
// return draggedEvent.value.date !== day.date && draggedEvent.value.time !== day.time
return draggedEvent.value.dateTimeStart !== day.dateTimeStart
}
}
function onDrop(ev, day, type) {
ev.preventDefault()
ev.stopPropagation()
console.log('day.dateTimeStart', day.dateTimeStart, day.date, 'day.time', day.time)
if (type === 'day') {
draggedEvent.value.dateTimeStart = day.date + ' ' + tools.getstrTime(draggedEvent.value.dateTimeStart)
draggedEvent.value.dateTimeEnd = day.date + ' ' + tools.getstrTime(draggedEvent.value.dateTimeEnd)
draggedEvent.value.side = void 0
} else if (type === 'interval') {
const mins = date.getDateDiff(draggedEvent.value.dateTimeEnd, draggedEvent.value.dateTimeStart, 'minutes')
draggedEvent.value.dateTimeStart = day.date + ' ' + day.time
const mystart = new Date(draggedEvent.value.dateTimeStart)
draggedEvent.value.dateTimeEnd = tools.addMinutes(mystart, mins)
// draggedEvent.value.dateTimeEnd = day.dateTimeEnd
// draggedEvent.value.time = day.time
draggedEvent.value.side = void 0
}
// console.log('Start', draggedEvent.value.dateTimeStart, 'End', draggedEvent.value.dateTimeEnd)
// Save Date
UpdateDbByFields($q, {
_id: draggedEvent.value._id,
dateTimeStart: draggedEvent.value.dateTimeStart,
dateTimeEnd: draggedEvent.value.dateTimeEnd
}, true, contextDay.value)
}
function resetDrag() {
draggedEvent.value = void 0
dragging.value = false
if (Platform.is.desktop) {
ignoreNextSwipe = true
}
}
async function BookEvent(eventparam: IBookedEvent)
{
return await calendarStore.BookEvent(eventparam)
}
function createContribType(value) {
console.log('createContribType', value)
tools.createNewRecord(this, 'contribtype', { label: value }).then((myrec) => {
// console.log('myrec')
calendarStore.contribtype.push(myrec)
})
}
function getEventDate(eventparam) {
const parts = eventparam.dateTimeStart.split('-')
const mydate = new Date(parts[0], parts[1] - 1, parts[2])
return dateFormatter.format(mydate)
}
function badgeClasses(eventparam, type) {
const cssColor = tools.isCssColor(eventparam.bgcolor)
const isHeader = type === 'header'
return {
[`text-white bg-${eventparam.bgcolor}`]: !cssColor,
'full-width': !isHeader && (!eventparam.side || eventparam.side === 'full'),
'left-side': !isHeader && eventparam.side === 'left',
'right-side': !isHeader && eventparam.side === 'right'
}
}
function badgeStyles(eventparam, type, timeStartPos, timeDurationHeight) {
const s = { color: '', top: '', height: '', opacity: 1 }
if (tools.isCssColor(eventparam.bgcolor)) {
s['background-color'] = eventparam.bgcolor
s.color = colors.luminosity(eventparam.bgcolor) > 0.5 ? 'black' : 'white'
}
if (timeStartPos) {
s.top = timeStartPos(tools.getstrTime(eventparam.dateTimeStart)) + 'px'
}
if (timeDurationHeight) {
s.height = timeDurationHeight(func_tools.getMinutesDuration(eventparam.dateTimeStart, eventparam.dateTimeEnd)) + 'px'
}
if (!isEventEnabled(eventparam)) {
s.opacity = 0.5
}
s['align-items'] = 'flex-start'
return s
}
function calendarNext() {
$refs.calendar.next()
}
function calendarPrev() {
$refs.calendar.prev()
}
function calendarToday(today) {
selectedDate = today
}
function SetToday() {
root.$emit('calendar:today', formatDate(tools.getDateNow()))
}
function onChanged(data) {
// uncomment to see data in console
// let { start, end } = data
// console.log('onChanged:', start, end)
}
function onMoved(moved) {
// uncomment to see data in console
// console.log('onMoved:', moved)
}
function getEventList() {
const mylist = calendarStore.eventlist.filter((rec) => (new Date(rec.dateTimeEnd) >= tools.getDateNowEvent()))
if (props.showfirstN > 0)
return mylist.slice(0, props.showfirstN)
else
return mylist
}
function getEvents(dt: any) {
const eventsloc = []
// console.log('dt', dt)
for (let i = 0; i < calendarStore.eventlist.length; ++i) {
let added = false
if (tools.getstrYYMMDDDate(calendarStore.eventlist[i].dateTimeStart) === dt) {
if (eventsloc.length > 0) {
// check for overlapping times
const startTime = calendarStore.eventlist[i].dateTimeStart
const endTime = calendarStore.eventlist[i].dateTimeEnd
for (const item of eventsloc) {
const startTime2 = item.dateTimeStart
const endTime2 = item.dateTimeEnd
if (date.isBetweenDates(startTime, startTime2, endTime2) || date.isBetweenDates(endTime, startTime2, endTime2)) {
item.side = 'left'
eventsloc.push(calendarStore.eventlist[i])
added = true
break
}
}
}
// }
if (!added) {
// calendarStore.eventlist[i].side = void 0
eventsloc.push(calendarStore.eventlist[i])
}
} else if (tools.hasManyDays(calendarStore.eventlist[i].dateTimeStart, calendarStore.eventlist[i].dateTimeEnd)) {
// check for overlapping dates
if (date.isBetweenDates(dt, calendarStore.eventlist[i].dateTimeStart, calendarStore.eventlist[i].dateTimeEnd)) {
eventsloc.push(calendarStore.eventlist[i])
added = true
}
}
}
// if (eventsloc.length > 0)
// console.log('eventsloc', eventsloc)
return eventsloc
}
function isEventEnabled(myevent: IEvents) {
// check if event is in the past
const datenow = tools.addDays(tools.getDateNow(), -1)
// console.log('datenow', datenow, 'end', myevent.dateTimeEnd)
return (new Date(myevent.dateTimeEnd) >= datenow)
}
function getTitleEv(event: IEvents) {
return (!!event.short_tit) ? event.short_tit : event.title
}
function getLongTitleEv(event: IEvents) {
return event.title
}
return {
calendarView,
selectedDate,
tabeditor,
showPrev,
keyValue,
weekdays,
addEvent,
bookEventpage,
askInfopage,
contextDay,
eventForm,
bookEventForm,
askInfoForm,
displayEvent,
myevent,
dragging,
UpdateDbByFields,
visuAllCal,
title_cal,
calendarStore,
}
}
})

View File

@@ -0,0 +1,937 @@
<template>
<div class="landing">
<!-- <div v-if="!tools.IsLogged() && (!mysingleevent)">
<div class="centermydiv">
<q-banner class="bg-secondary text-white">
Il Calendario sarà visibile solo dopo aver effettuato l'accesso
</q-banner>
</div>
</div>-->
<div>
<!-- display an myevent -->
<q-dialog v-model="displayEvent">
<q-card v-if="myevent" :style="`min-width: ` + tools.myheight_dialog() + `px;`">
<q-toolbar class="bg-primary text-white">
<!--<q-toolbar :class="tools.displayClasses(myevent)"-->
<!--:style="tools.displayStyles(myevent) + ` min-width: `+ tools.myheight_dialog() + `px;`">-->
<q-toolbar-title>
{{ $t('cal.event') }}
</q-toolbar-title>
<q-btn v-if="editable" flat round color="white" icon="fas fa-copy">
<q-menu
transition-show="flip-right"
transition-hide="flip-left">
<q-list style="min-width: 100px">
<q-item clickable @click="duplicateEvent(myevent, 7)">
<q-item-section>Tra 1 Settimana</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 14)">
<q-item-section>Tra 2 Settimane</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 7, 4)">
<q-item-section>4 Eventi ogni Settimana</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
<q-btn
v-if="editable" flat round color="white" icon="delete" v-close-popup
@click="deleteEvent(myevent)"></q-btn>
<q-btn
v-if="editable" flat round color="white" icon="edit" v-close-popup
@click="editEvent(myevent)"></q-btn>
<q-btn
flat round color="white" icon="cancel" v-close-popup
@click="myevent = null; displayEvent = false"></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-img
:src="getImgEvent(myevent)"
class="absolute-top"
style="height: 150px;"
:alt="myevent.title">
</q-img>
<div style="margin-top: 150px;">
<!--<div v-if="myevent.allday" class="text-caption">{{ getEventDate(myevent) }}</div>-->
<q-chip
:style="`background-color: ${myevent.bgcolor} !important; color: white !important;`"
text-color="white"
class="shadow-5 q-mb-md" dense>
{{ myevent.title }}
</q-chip>
<div class="cal__details" v-html="myevent.details"></div>
<div v-if="myevent.teacher" class="cal__teacher">
<span class="cal__teacher-title">{{ $t('cal.teacher') }}: <span
class="margin_with"></span></span>
<!--<span class="cal__teacher-content">{{myevent.teacher}}</span>-->
<CMyTeacher :username="myevent.teacher"></CMyTeacher>
<CMyTeacher :username="myevent.teacher2"></CMyTeacher>
<CMyTeacher :username="myevent.teacher3"></CMyTeacher>
<CMyTeacher :username="myevent.teacher4"></CMyTeacher>
</div>
<div v-if="myevent.wherecode" class="cal__where">
<!--<span v-if="tools.isMobile()"><br/></span>-->
<span class="cal__where-title">{{ $t('cal.where') }}: </span>
<span class="cal__where-content">
<q-chip>
<q-avatar v-if="getWhereIcon(myevent.wherecode)">
<img
:src="`../../statics/images/avatar/` + getWhereIcon(myevent.wherecode)"
alt="Località">
</q-avatar>
<q-avatar v-else color="blue" font-size="20px" text-color="white" icon="home">
</q-avatar>
<span class="cal__teacher-content">{{ getWhereName(myevent.wherecode) }}</span>
</q-chip>
</span>
</div>
<div v-if="myevent.price && isShowPrice(myevent)" class="cal__quota">
<span class="cal__quota-title">{{ $t('event.price') }}:</span>
<q-chip>
<span class="cal__quota-content">{{ getPrice(myevent) }}</span>
</q-chip>
</div>
<div v-if="myevent.dateTimeStart" class="cal__when">
<span class="cal__where-title">{{ $t('cal.when') }}:
<span v-html="tools.getstrDateTimeEvent(mythis, myevent, true)"></span>
</span>
</div>
<p v-if="myevent.linkpdf" style="margin-top: 10px; text-align: center">
<q-btn
size="md" type="a" :href="`../../statics/` + myevent.linkpdf"
target="_blank" rounded color="primary" icon="info" :label="$t('cal.showpdf')">
</q-btn>
</p>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
rounded v-if="!myevent.nobookable && static_data.functionality.BOOKING_EVENTS"
color="primary" @click="addBookEventMenu(myevent)" :disable="!isEventEnabled(myevent)"
:label="$t('cal.booking')">
</q-btn>
<q-btn v-else :label="$t('dialog.ok')" color="primary" v-close-popup></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<!-- id_bookedeventadd/edit an myevent -->
<q-dialog v-model="addEvent" no-backdrop-dismiss persistent>
<q-card v-if="addEvent" :style="`min-width: `+ tools.myheight_dialog() + `px;`">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ addOrUpdateEvent }} {{ $t('cal.event') }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-form
v-if="contextDay"
ref='myevent'
class="q-gutter-sm">
<CMySelect
:label="$t('event.typol')" v-model:value="eventForm.typol" optval="typol_code"
optlab="label"
:options="calendarStore.disciplines" :useinput="false">
</CMySelect>
<div>
<q-input
color="grey-1" v-model="eventForm.short_tit" autofocus
debounce="1000"
:input-style="`background-color: ${eventForm.bgcolor} !important; color: white !important; font-weight: bold; `"
borderless rounded dense :label="$t('event.short_tit')"
></q-input>
<q-input
color="grey-1" v-model="eventForm.title" autofocus
debounce="1000"
:input-style="`background-color: ${eventForm.bgcolor} !important; color: white !important; font-weight: bold; `"
borderless rounded dense :label="$t('event.title')"
:rules="[v => v && v.length > 0 || $t('event.notempty')]"></q-input>
</div>
<q-tabs
v-model="tabeditor"
dense
class="text-grey"
active-color="primary"
indicator-color="primary"
align="justify"
narrow-indicator
>
<q-tab name="details" label="Descrizione Breve" icon="fas fa-pencil-alt"/>
<q-tab name="container" label="Dettaglio Pagina" icon="fas fa-book"/>
<q-tab name="settings" label="Impostazioni" icon="fas fa-calendar-day"/>
</q-tabs>
<q-tab-panels v-model="tabeditor" animated>
<q-tab-panel name="details">
<div class="q-gutter-sm myflex">
<q-input
class="myflex" dense v-model="eventForm.img"
:label="$t('event.img')"></q-input>
<q-input
class="myflex" dense v-model="eventForm.img_small"
:label="$t('event.img_small')"></q-input>
</div>
<div class="q-gutter-sm myflex">
<q-input
class="myflex"
:style="`background-color: ${eventForm.bgcolor} !important; color: white !important;`"
filled
color="white"
dense
:label="$t('event.bgcolor')"
v-model="eventForm.bgcolor">
<template #append>
<q-icon name="colorize" class="cursor-pointer" color="white">
<q-popup-proxy>
<q-color format-model="hex" v-model="eventForm.bgcolor"></q-color>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-input
class="myflex" dense v-model="eventForm.icon"
:label="$t('event.icon')"></q-input>
</div>
<CMyEditor v-model:value="eventForm.details" :showButtons="false">
</CMyEditor>
</q-tab-panel>
<q-tab-panel name="container">
<CMyEditor v-model:value="eventForm.bodytext" :showButtons="false">
</CMyEditor>
</q-tab-panel>
<q-tab-panel name="settings" class="q-gutter-sm">
<!--<q-checkbox v-model="eventForm.allday" :label="$t('cal.alldayevent')"></q-checkbox>-->
<div class="q-gutter-sm row myflex">
<CDateTime
v-model:value="eventForm.dateTimeStart"
:label="$t('cal.eventstartdatetime')"
:readonly="false">
</CDateTime>
<CDateTime
v-model:value="eventForm.dateTimeEnd"
:label="$t('cal.enterEndDateTime')"
:readonly="false">
</CDateTime>
<q-input dense v-model="eventForm.infoextra" :label="$t('cal.infoextra')"></q-input>
</div>
<div class="q-gutter-sm myflex">
<CMySelect
myclass="myflex" :label="$t('cal.teacher') + ' 1°'"
v-model:value="eventForm.teacher"
optval="username" :optlab="(item) => item.name + ' ' + item.surname"
:options="calendarStore.operators" :useinput="false">
</CMySelect>
<CMySelect
myclass="myflex" :label="$t('cal.teacher') + ' 2°'"
v-model:value="eventForm.teacher2"
optval="username" :optlab="(item) => item.name + ' ' + item.surname"
:options="calendarStore.operators" :useinput="false">
</CMySelect>
<CMySelect
myclass="myflex" :label="$t('cal.teacher') + ' 3°'"
v-model:value="eventForm.teacher3"
optval="username" :optlab="(item) => item.name + ' ' + item.surname"
:options="calendarStore.operators" :useinput="false">
</CMySelect>
<CMySelect
myclass="myflex" :label="$t('cal.teacher') + ' 4°'"
v-model:value="eventForm.teacher4"
optval="username" :optlab="(item) => item.name + ' ' + item.surname"
:options="calendarStore.operators" :useinput="false">
</CMySelect>
<CMySelect
:label="$t('cal.where')" v-model:value="eventForm.wherecode" optval="code"
optlab="placename"
:options="calendarStore.wheres" :useinput="false">
</CMySelect>
</div>
<div class="q-gutter-sm myflex wrap">
<q-checkbox
class="myflex wrap" dense v-model="eventForm.internal"
:label="$t('event.internal')"></q-checkbox>
<q-checkbox
class="myflex wrap" dense v-model="eventForm.lunchAvailable"
:label="$t('event.lunchAvailable')"></q-checkbox>
<q-checkbox
class="myflex wrap" dense v-model="eventForm.dinnerAvailable"
:label="$t('event.dinnerAvailable')"></q-checkbox>
<q-checkbox
class="myflex wrap" dense v-model="eventForm.dinnerSharedAvailable"
:label="$t('event.dinnerSharedAvailable')"></q-checkbox>
<q-checkbox
class="myflex wrap" dense v-model="eventForm.news"
:label="$t('event.news')"></q-checkbox>
<q-checkbox
class="myflex wrap" dense v-model="eventForm.nobookable"
:label="$t('event.nobookable')"></q-checkbox>
<q-checkbox
class="myflex wrap" dense v-model="eventForm.canceled"
:label="$t('event.canceled')"></q-checkbox>
</div>
<div class="q-gutter-sm row items-start">
</div>
<div class="q-gutter-sm myflex">
<CMySelect
:label="$t('event.contribtype')" v-model:value="eventForm.contribtype"
optval="_id" optlab="label"
:useinput="false"
:newvaluefunc="createContribType" :options="calendarStore.contribtype">
</CMySelect>
<div v-if="isShowPrice(eventForm)">
<q-input
dense type="number" v-model="eventForm.price"
:label="$t('event.price')"></q-input>
<q-input
dense v-model="eventForm.infoafterprice"
:label="$t('event.infoafterprice')"></q-input>
</div>
</div>
<div class="q-gutter-sm myflex">
<CMySelect
myclass="myflex" :label="$t('event.pagefooter') + ' 1°'"
v-model:value="eventForm.pagefooter"
style="min-width: 300px;"
:multiple="true"
optval="path" optlab="title"
:options="calendarStore.internalpages" :useinput="false">
</CMySelect>
<br>
<q-input
class="myflex" dense v-model="eventForm.linkpage"
:label="$t('event.linkpage')"></q-input>
<q-input
class="myflex" dense v-model="eventForm.linkpdf"
:label="$t('event.linkpdf')"></q-input>
<q-input
class="myflex" dense v-model="eventForm.facebook"
:label="$t('event.facebook')"></q-input>
</div>
</q-tab-panel>
</q-tab-panels>
</q-form>
</q-card-section>
<q-card-actions align="right">
<q-btn flat :label="$t('dialog.ok')" color="primary" @click="saveEvent"></q-btn>
<q-btn flat :label="$t('dialog.cancel')" color="primary" v-close-popup></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="bookEventpage.show" no-backdrop-dismiss>
<q-card v-if="bookEventpage.show" :style="`min-width: `+ tools.myheight_dialog() + `px;`">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ $t('cal.booking') }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-img
:src="getImgEvent(myevent)"
class="absolute-top"
style="height: 200px;"
:alt="myevent.title">
</q-img>
<div style="margin-top: 150px;">
<q-chip
:style="`background-color: ${myevent.bgcolor} !important; color: white !important;`"
text-color="white"
class="shadow-5 q-mb-md" dense>
{{ myevent.title }}
</q-chip>
<div v-if="myevent.dateTimeStart" class="cal__when">
<span class="cal__where-title">{{ $t('cal.when') }}:
<span v-html="tools.getstrDateTimeEvent(mythis, myevent, true)"></span>
</span>
</div>
<div class="q-pa-xs">
<q-card class="text-white windowcol" style="display: block; ">
<q-card-section class="q-pa-xs">
<div style="display: inline-flex; " class="q-px-xs centermydiv">
<q-checkbox
:disable="((bookEventpage.bookedevent && bookEventpage.bookedevent.booked) || (bookEventpage.bookedevent === undefined)) || !isEventEnabled(myevent)"
style="color: black;" v-model="bookEventForm.booked"
:label="$t('cal.bookingtextdefault')" color="green">
</q-checkbox>
<div
v-if="bookEventForm.booked" class="q-gutter-xs q-mx-xs"
style="min-width: 140px;">
<q-select
rounded outlined v-model="bookEventForm.numpeople"
:options="tools.SelectListNumPeople"
:label="$t('cal.selnumpeople')" emit-value map-options>
</q-select>
</div>
</div>
<div v-if="myevent.lunchAvailable" class="q-px-xs centermydiv" style="display: inline-flex; ">
<div style="display: inline-flex; " class="q-px-xs centermydiv">
<div class="itemprenota">{{ $t('cal.selnumpeopleLunch') }}</div>
<div
class="q-gutter-xs"
style="min-width: 140px; margin-left: 10px;">
<q-select
rounded outlined v-model="bookEventForm.numpeopleLunch"
:options="tools.SelectListNumPeople"
:label="$t('cal.Lunch')" emit-value map-options>
</q-select>
</div>
</div>
</div>
<br>
<div v-if="myevent.dinnerAvailable" class="q-px-xs centermydiv" style="display: inline-flex; ">
<div style="display: inline-flex; " class="q-px-xs centermydiv">
<div class="itemprenota">{{ $t('cal.selnumpeopleDinner') }}</div>
<div class="q-gutter-xs " style="min-width: 180px; margin-left: 10px;">
<q-select
rounded outlined v-model="bookEventForm.numpeopleDinner"
:options="tools.SelectListNumPeople"
:label="$t('cal.Dinner')" emit-value map-options>
</q-select>
</div>
</div>
</div>
<div
v-if="myevent.dinnerSharedAvailable" class="q-px-xs centermydiv"
style="display: inline-flex; ">
<div style="display: inline-flex; " class="q-px-xs centermydiv">
<div class="itemprenota">{{ $t('cal.selnumpeopleDinnerShared') }}</div>
<div class="q-gutter-xs " style="min-width: 180px; margin-left: 10px;">
<q-select
rounded outlined v-model="bookEventForm.numpeopleDinnerShared"
:options="tools.SelectListNumPeople"
:label="$t('cal.DinnerShared')" emit-value map-options>
</q-select>
</div>
</div>
</div>
<q-input
v-model="bookEventForm.msgbooking" :label="$t('cal.writemsg')+':'"
type="textarea" debounce="500"
input-class="myinput-area"
>
</q-input>
</q-card-section>
</q-card>
</div>
<p v-if="myevent.linkpdf" style="margin-top: 10px; text-align: center">
<q-btn
size="md" type="a" :href="`../../statics/` + myevent.linkpdf"
target="_blank" rounded color="primary" icon="info" :label="$t('cal.showpdf')">
</q-btn>
</p>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
v-if="bookEventpage.state === EState.Modifying" flat :label="$t('cal.cancelbooking')"
color="negative"
@click="tools.CancelBookingEvent($q, myevent, bookEventForm._id, true)"></q-btn>
<q-btn
v-if="checkseinviaMsg" flat :label="$t('dialog.sendonlymsg')" color="primary"
@click="sendMsg(myevent)"></q-btn>
<q-btn
v-else :label="getTitleBtnBooking" color="primary" @click="saveBookEvent(myevent)"
:disable="!(bookEventpage.state === EState.Creating || hasModifiedBooking)"></q-btn>
<q-btn flat :label="$t('dialog.cancel')" color="primary" v-close-popup></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="askInfopage.show" no-backdrop-dismiss>
<q-card v-if="askInfopage.show" :style="`min-width: `+ tools.myheight_dialog() + `px;`">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ $t('cal.booking') }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-img
:src="getImgEvent(myevent)"
class="absolute-top"
style="height: 150px;"
:alt="myevent.title">
</q-img>
<div style="margin-top: 150px;">
<q-chip
:style="`background-color: ${myevent.bgcolor} !important; color: white !important;`"
text-color="white"
class="shadow-5 q-mb-md" dense>
{{ myevent.title }}
</q-chip>
<div v-if="myevent.dateTimeStart" class="cal__when">
<span class="cal__where-title">{{ $t('cal.when') }}:
<span v-html="tools.getstrDateTimeEvent(mythis, myevent, true)"></span>
</span>
</div>
<div class="q-pa-xs">
<q-card class="text-white windowcol">
<q-card-section>
<q-input
v-model="askInfoForm.message" :label="$t('cal.writemsg')+':'"
autofocus debounce="500" type="textarea"
input-class="myinput-area">
</q-input>
</q-card-section>
</q-card>
</div>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
flat :label="$t('dialog.sendmsg')" color="primary"
@click="sendMsg(myevent)"></q-btn>
<q-btn flat :label="$t('dialog.cancel')" color="primary" v-close-popup></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<!--v-touch-swipe.mouse.left.right="handleSwipe" -->
<!-- the calendar -->
<q-page v-if="visuAllCal && showfirstN === 0" class="column" style="min-height: 200px !important;">
<div>
<q-toolbar class="mytoolbar">
<q-btn color="primary" round icon="keyboard_arrow_left" @click="calendarPrev"/>
<q-btn color="primary" round icon="keyboard_arrow_right" @click="calendarNext"/>
<q-separator vertical/>
<!--<q-btn color="primary" :label="$t('dialog.today')" class="q-mx-md" @click="SetToday"></q-btn>-->
<q-separator vertical/>
<!--<q-btn label="GG" color="primary" @click="calendarView = 'day'"/>
<q-btn label="Set" color="primary" @click="calendarView = 'week'"/>-->
<q-btn label="5 GG" color="primary" @click="calendarView = '5day-agenda'"/>
<q-btn label="Sett" color="primary" @click="calendarView = 'week-agenda'"/>
<q-btn label="Mese" color="primary" @click="calendarView = 'month'"/>
<q-space/>
</q-toolbar>
<q-separator/>
<div class="text-center"><span
class="q-mr-xl q-toolbar__title nowrap text-blue">{{ title_cal }}</span>
</div>
<!--
:theme="theme"
:enable-themes="enableThemes === true"
-->
<q-calendar
v-if="visuAllCal"
ref="calendar"
class="calendar"
:key="keyValue"
v-model="selectedDate"
:locale="calendarStore.locale"
:maxDays="calendarStore.maxDays"
animated
transition-prev="slide-right"
transition-next="slide-left"
:dragOverFunc="onDragOver"
:dropFunc="onDrop"
:view="calendarView"
:weekdays="weekdays"
:interval-minutes="60 * calendarStore.intervalRangeStep"
:interval-start="calendarStore.intervalStart"
:interval-count="calendarStore.intervalCount"
:hour24-format="calendarStore.hour24Format"
:short-month-label="calendarStore.shortMonthLabel"
:show-day-of-year-label="calendarStore.showDayOfYearLabel"
:hide-header="calendarStore.hideHeader"
:no-scroll="calendarStore.noScroll"
:short-weekday-label="calendarStore.shortWeekdayLabel"
:short-interval-label="calendarStore.shortIntervalLabel"
:interval-height="calendarStore.intervalHeight"
:resource-height="calendarStore.resourceHeight"
:resource-width="calendarStore.resourceWidth"
:day-height="dayHeight"
:show-month-label="calendarStore.showMonthLabel"
:show-work-weeks="calendarStore.showWorkWeeks"
:resources="resources"
@change="onChanged"
@moved="onMoved"
@click:date="onDateChanged"
@click:interval="addEventMenu"
@click:time="addEventMenu"
@click:day="addEventMenu"
@click:week="addEventMenu"
@click:resource="resourceClicked"
@click:resource:day="resourceDayClicked"
dayPadding="35px 2px"
>
<template #day="{ timestamp }">
<template v-for="(event, index) in getEvents(timestamp.date)">
<q-badge
style="width: 100%; cursor: pointer;"
:class="badgeClasses(event, 'day')"
:style="badgeStyles(event, 'day')"
@click.stop.prevent="showEvent(event)"
:draggable="tools.isManager()"
@dragstart.native="(e) => onDragStart(e, event)"
@dragend.native="(e) => onDragEnd(e, event)"
@dragenter.native="(e) => onDragEnter(e, event)"
@touchmove.native="(e) => {}"
>
<span class="">{{ getTitleEv(event) }}</span>
</q-badge>
<div class="text-center"><img
:src="getImgEvent(event)"
class="text-center listaev__tdimg_small" :alt="event.title">
</div>
</template>
</template>
<template #day-header="{ timestamp }">
<div class="row justify-center">
<template v-for="(event, index) in eventsMap[timestamp.date]">
<q-badge
class="q-ma-xs"
:class="badgeClasses(event, 'header')"
:style="badgeStyles(event, 'header')"
style="width: 10px; max-width: 10px; height: 10px; max-height: 10px"
></q-badge>
</template>
</div>
</template>
<template #day-body="{ timestamp, timeStartPos, timeDurationHeight }">
<template v-for="(event, index) in getEvents(timestamp.date)">
<div
:label="tools.getstrTime(event.dateTimeStart)"
class="justify-start q-ma-sm shadow-5 bg-blue-grey-6"
>
<div
v-if="getImgEvent(event)" class="row justify-center"
style="margin-top: 30px; width: 100%;">
<q-avatar
style="margin-top: -25px; margin-bottom: 10px; font-size: 60px; max-height: 50px;">
<img :src="getImgEvent(event)" style="border: #a4edf6 solid 5px;">
</q-avatar>
</div>
<div class="col-12 q-px-xs text-white">
<strong>{{ tools.getstrTime(event.dateTimeStart) }}</strong>
</div>
<div
v-if="getTitleEv(event)" class="col-12 q-px-xs text-white"
style="font-size: 0.75rem;">
<q-badge
:key="index"
multi-line
class="my-event-rel justify-center rounded-borders"
:class="badgeClasses(event, 'body')"
:style="badgeStyles(event, 'body', timeStartPos, timeDurationHeight)"
@click.stop.prevent="showEvent(event)"
:draggable="tools.isManager()"
@dragstart.native="(e) => onDragStart(e, event)"
@dragend.native="(e) => onDragEnd(e, event)"
@dragenter.native="(e) => onDragEnter(e, event)"
@touchmove.native="(e) => {}"
>
<span class="">{{ getTitleEv(event) }}</span> <br>
</q-badge>
</div>
</div>
<!--
<q-badge
:key="index"
class="my-event justify-center"
:class="badgeClasses(event, 'body')"
:style="badgeStyles(event, 'body', timeStartPos, timeDurationHeight)"
@click.stop.prevent="showEvent(event)"
:draggable="tools.isManager()"
@dragstart.native="(e) => onDragStart(e, event)"
@dragend.native="(e) => onDragEnd(e, event)"
@dragenter.native="(e) => onDragEnter(e, event)"
@touchmove.native="(e) => {}"
>
<q-icon v-if="event.icon" :name="event.icon" class="q-mr-xs"></q-icon>
<p class="">{{ getTitleEv(event) }}</p> <br>
<div class="text-center"><img :src="getImgEvent(event)"
class="text-center listaev__tdimg_small"
:alt="event.title">
</div>
</q-badge> -->
</template>
</template>
</q-calendar>
</div>
</q-page>
<div class="q-mt-md">
<div v-if="!mysingleevent">
<p class="text-subtitle1 text-red bg-amber text-center ">LISTA PROSSIMI <span
v-if="showfirstN > 0">{{ showfirstN }}</span>
EVENTI:</p>
<!--<q-toggle v-model="showPrev" :val="lists.MenuAction.SHOW_PREV_REC"
:label="$t('grid.showprevedit')"></q-toggle>-->
<q-markup-table wrap-cells bordered separator="horizontal" class="listaev__table">
<tbody>
<tr v-for="(event, index) in getEventList()" class="listaev listaev__table">
<td :class="clEvent(event)">
<div class="listaev__align_chips">
<img
:src="getImgEvent(event)"
@click="selectEvent(event)"
class="text-left padding_cell listaev__tdimg listaev__img cursor-pointer q-mx-sm"
:style="getStyleByEvent(event, event === myevent)"
:alt="event.title">
<q-chip
dense v-if="isAlreadyBooked(event)" class="cltexth4 chipbooked shadow-5 q-mb-md"
color="green" text-color="white"
icon="event_available">{{ $t('cal.booked') }}
</q-chip>
<q-chip
v-if="event === myevent && !displayEvent && editable"
class="text-center shadow-5 glossy bg-blue chipmodif">
<q-btn v-if="editable" flat round color="white" icon="fas fa-copy">
<q-menu
transition-show="flip-right"
transition-hide="flip-left">
<q-list style="min-width: 100px">
<q-item clickable @click="duplicateEvent(myevent, 7)">
<q-item-section>Tra 1 Settimana</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 14)">
<q-item-section>Tra 2 Settimane</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 7, 4)">
<q-item-section>4 Eventi ogni Settimana</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
<q-btn
v-if="editable" flat round color="white" icon="delete" v-close-popup
@click="deleteEvent(myevent)"></q-btn>
<q-btn
v-if="editable" flat round color="white" icon="edit" v-close-popup
@click="editEvent(myevent)"></q-btn>
<q-btn
v-if="editable" flat round color="white" icon="cancel"
@click="selectEvent(null)"></q-btn>
</q-chip>
<q-chip
v-if="event.news" class="cltexth4 chipnews shadow-5 glossy text-right"
color="red"
text-color="white" icon-right="star" icon="star" dense
style="">
{{ $t('event.news') }}
</q-chip>
</div>
<div class="listaev__date listaev__align_center_mobile text-center">
<span v-html="tools.getstrDateTimeEvent(mythis, event, true)"></span>
</div>
<div class="listaev__align_center_mobile">
<div style="margin: 10px;"></div>
<div v-if="event.internal">
<q-chip color="blue" text-color="white">Evento Interno:</q-chip>
</div>
<div class="text-center">
<!-- Se c'è un link, allora -->
<q-btn
size="md" type="a"
class="text-center boldhigh"
:to="`/event/${event.typol}/${event._id}`"
target="_blank"
:style="`background-color: ${event.bgcolor} !important; color: white !important;`"
ripple
rounded
:label="getTitleEv(event)"
:color="event.bgcolor" text-color="white" glossy>
</q-btn>
<!--<div v-if="tools.isMobile()" class="cltexth3 text-center"-->
<!--:style="`background-color: ${event.bgcolor} !important; color: white !important;`">-->
<!--{{event.title}}-->
<!--</div>-->
<!--<q-chip v-else class="cltexth3 text-center"-->
<!--:style="`background-color: ${event.bgcolor} !important; color: white !important;`"-->
<!--text-color="white"-->
<!--:icon="event.icon"-->
<!--dense>{{event.title}}-->
<!--</q-chip>-->
</div>
<div style="margin: 10px;"></div>
<p class="listaev__details" v-html="event.details"></p>
<div v-if="event.teacher" class="">
<span class="cal__teacher-title">{{ $t('cal.teacher') }}: <span
class="margin_with"></span></span>
<CMyTeacher :username="event.teacher"></CMyTeacher>
<CMyTeacher :username="event.teacher2"></CMyTeacher>
<CMyTeacher :username="event.teacher3"></CMyTeacher>
<CMyTeacher :username="event.teacher4"></CMyTeacher>
<span v-if="event.wherecode" class="">
<span v-if="tools.isMobile()"><br/></span>
<span class="cal__where-title">{{ $t('cal.where') }}: </span>
<q-chip>
<q-avatar v-if="getWhereIcon(event.wherecode)">
<img
:src="`../../statics/images/avatar/` + getWhereIcon(event.wherecode)"
:alt="event.wherecode">
</q-avatar>
<q-avatar color="blue" font-size="20px" text-color="white" icon="home">
</q-avatar>
<span
class="cal__teacher-content">{{ getWhereName(event.wherecode) }}</span>
</q-chip>
</span>
</div>
<div v-if="event.contribtype" class="">
<span class="cal__quota-title">{{ $t('event.price') }}:<span
class="margin_with"></span></span>
<span v-if="!isShowPrice(event)" class="">
<q-chip class="glossy" color="orange" text-color="white">
<span
class="cal__quota-content">{{ getContribtypeById(event.contribtype) }}</span>
</q-chip>
</span>
<q-chip
v-if="event.price && isShowPrice(event)" class="glossy" color="orange"
text-color="white" icon-right="star">
<span class="cal__quota-content">{{ getPrice(event) }}</span>
</q-chip>
</div>
<div class="row centeritems">
<q-btn
v-if="event.linkpdf" size="md" type="a"
:href="`../../statics/` + event.linkpdf"
target="_blank" rounded color="primary" icon="info"
class="q-ma-sm"
:label="$t('cal.showpdf')">
</q-btn>
<q-btn
rounded
class="q-ma-sm"
color="primary"
:to="`/event/${event.typol}/${event._id}`"
:label="$t('event.openpage')">
</q-btn>
<q-btn
rounded outline class="q-ma-sm"
color="primary" @click="askForInfoEventMenu(event)"
:label="$t('event.askinfo')">
</q-btn>
<!--<q-btn rounded outline class="q-ma-sm"
v-if="!event.nobookable && !isAlreadyBooked(event) && static_data.functionality.BOOKING_EVENTS"
color="primary" @click="addBookEventMenu(event)"
:label="$t('cal.booking')" :disable="!isEventEnabled(event)">
</q-btn>-->
<q-btn
rounded outline class="q-ma-sm"
v-if="!event.nobookable && isAlreadyBooked(event) && static_data.functionality.BOOKING_EVENTS"
text-color="red"
@click.native="EditBookEvent(event)"
:label="$t('cal.modifybooking')">
</q-btn>
<!--
<q-btn push rounded v-if="!event.nobookable && isAlreadyBooked(event)" color="positive" @click="BookEvent(event)"
:label="$t('cal.booked')">
</q-btn>
-->
</div>
</div>
</td>
</tr>
</tbody>
</q-markup-table>
<div class="q-ma-lg text-center">
<q-btn
rounded type="a" to="/calendario-eventi" color="primary" icon="event" size="lg"
:label="$t('cal.showlastschedule')">
</q-btn>
</div>
</div>
<div v-else>
<CMySingleEvent
:myevent="mysingleevent" calendarView="month" :iseditable="editable"
@duplicateEvent="duplicateEvent"
@askForInfoEventMenu="askForInfoEventMenu"
@deleteEvent="deleteEvent"
@editEvent="editEvent"
@addBookEventMenu="addBookEventMenu"
@EditBookEvent="EditBookEvent">
</CMySingleEvent>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" src="./CEventsCalendar.ts">
</script>
<style lang="scss" scoped>
@import './CEventsCalendar.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CEventsCalendar} from './CEventsCalendar.vue'

View File

@@ -0,0 +1,58 @@
import { defineComponent, PropType, onBeforeUpdate, reactive } from 'vue'
import { useI18n } from '@/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import MixinBase from '../../mixins/mixin-base'
import { tools } from '@store/Modules/tools'
export default defineComponent({
name: 'CFacebookFrame',
props: {
urlfbpage: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
fbimage: {
type: String,
required: true,
},
myclass: {
type: String,
required: false,
default: '',
},
},
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
function geturlfbpageEncoded() {
return encodeURIComponent(props.urlfbpage)
}
function mywidth() {
let myw = 340
if (tools.getwidth($q) < 410)
return myw
if ((tools.getwidth($q) > 410) && (tools.getwidth($q) < 1100))
return Math.round((tools.getwidth($q) / 3) - 30)
else
return myw
}
return {
geturlfbpageEncoded,
mywidth,
tools,
}
}
})

View File

@@ -0,0 +1,29 @@
<template>
<div v-if="urlfbpage && fbimage" :class="myclass">
<!--<div class="fb-page" :data-href="urlfbpage" data-tabs="timeline"-->
<!--data-width="" data-height="" data-small-header="false" data-adapt-container-width="true"-->
<!--data-hide-cover="false" data-show-facepile="true">-->
<!--<blockquote :cite="urlfbpage" class="fb-xfbml-parse-ignore"><a-->
<!--:href="urlfbpage">{{title}}</a>-->
<!--</blockquote>-->
<!--</div>-->
<a :href="urlfbpage" target="_blank">
<q-img :src="`statics/` + fbimage" class="imgautosize" alt="facebook page">
</q-img>
</a>
<!--
<iframe :src="`https://www.facebook.com/plugins/page.php?href=`+geturlfbpageEncoded()+`&tabs=timeline&width=`+mywidth+`&height=500&small_header=false&adapt_container_width=true&hide_cover=false&show_facepile=true&appId=164292303671962`"
width="340" height="500" style="border:none;overflow:hidden" scrolling="no" frameborder="0"
allowTransparency="true" allow="encrypted-media"></iframe>
-->
</div>
</template>
<script lang="ts" src="./CFacebookFrame.ts">
</script>
<style lang="scss" scoped>
@import './CFacebookFrame.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CFacebookFrame} from './CFacebookFrame.vue'

View File

@@ -0,0 +1,47 @@
$heightBtn: 100%;
$grayshadow: #555;
.text-subtitle-gallery {
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .1rem .1rem .1rem $grayshadow;
}
@media (max-width: 718px) {
// PER VERSIONE MOBILE
.text-subtitle-gallery {
font-size: 1rem;
}
}
.myimg {
border-radius: 10px !important;
height: 200px;
}
.myimg-view {
border-radius: 5px !important;
height: 80px;
}
.q-img {
&__image {
border-radius: 10px !important;
}
}
.my-card-gallery {
width: 100%;
max-width: 300px;
min-width: 200px;
padding: 1rem 1rem;
height: 350px;
}
.my-card-gallery-view {
width: 100px;
height: 100px;
padding: 0.5rem 0.5rem;
}

View File

@@ -0,0 +1,242 @@
import { defineComponent, ref, PropType, watch } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useQuasar } from 'quasar'
import { IGallery, IImgGallery } from 'model'
import { CMyPage } from '@/components/CMyPage'
import { tools } from '@store/Modules/tools'
import { useGlobalStore } from '@store/globalStore'
export default defineComponent({
name: 'CGallery',
props: {
edit: {
type: Boolean,
required: true,
},
gall: {
type: Object as PropType<IGallery>,
required: true,
},
listimages: {
type: Object as PropType<IImgGallery[]>,
required: true,
},
},
components: { CMyPage },
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
const mygall = ref(<IGallery>{})
const mylistimages = ref(<IImgGallery[]>[])
watch(() => props.gall, (newval, oldval) => {
mygall.value = props.gall
})
watch(() => props.listimages, (newval, oldval) => {
mylistimages.value = props.listimages
})
function created() {
mygall.value = props.gall
mylistimages.value = props.listimages
}
function getlistimages() {
if (mylistimages.value)
return mylistimages.value.slice().sort((a, b) => a.order! - b.order!)
else
return null
}
function onDragStart(e: any) {
console.log('onDragStart')
e.dataTransfer.setData('text', e.target.id)
e.dataTransfer.dropEffect = 'move'
}
function onDragEnter(e: any) {
// don't drop on other draggables
if (e.target.draggable !== true) {
e.target.classList.add('drag-enter')
}
}
function onDragLeave(e: any) {
e.target.classList.remove('drag-enter')
}
function onDragOver(e: any) {
e.preventDefault()
}
function onDrop(e: any) {
console.log('onDrop', e)
e.preventDefault()
// don't drop on other draggables
if (e.target.draggable === true) {
return
}
const draggedId = e.dataTransfer.getData('text')
let dragout = ''
try {
dragout = e.target.parentNode.parentNode.id
} catch (e) {
dragout = ''
}
const draggedEl = document.getElementById(draggedId)
console.log('draggedId', draggedId, 'draggedEl', draggedEl)
console.log('dragout', dragout)
// check if original parent node
if (draggedEl!.parentNode === e.target) {
e.target.classList.remove('drag-enter')
return
}
const myindex = mylistimages.value.findIndex((rec) => rec._id === draggedId)
const myrec: IImgGallery = mylistimages.value[myindex]
let myrecprec: IImgGallery
let myrecout: IImgGallery
const myindexout = mylistimages.value.findIndex((rec) => rec._id === dragout)
myrecout = mylistimages.value[myindexout]
let myindexprec = myindexout - 1
if (myindexprec < 0)
myindexprec = 0
if (myindex === myindexout)
return
myrecprec = mylistimages.value[myindexprec]
console.log('myrec', myrec, 'myrecprec', myrecout)
if (myrec && myrecout)
console.log('myrec', myrec, 'myrecprec', myrecout, 'ord1', myrec.order, 'myrecout', myrecout.order)
if (myrecout) {
let diff = 0
const ord2 = myrecprec.order
const ord1 = myrecout.order
diff = Math.round((ord1! - ord2!) / 2)
if (diff <= 0)
diff++
console.log('diff', diff)
let mynum = 0
mynum = myrecprec.order! + diff
console.log('mynum', mynum)
myrec.order = mynum
} else {
myrec.order = Math.round(myrec.order!) - 1
}
console.log('myrec.order', myrec.order)
// make the exchange
// draggedEl.parentNode.removeChild(draggedEl)
// e.target.appendChild(draggedEl)
e.target.classList.remove('drag-enter')
save()
}
function getclass() {
return (props.edit) ? 'my-card-gallery' : 'my-card-gallery-view' + ' text-center'
}
function getclimg() {
return (props.edit) ? 'myimg' : 'myimg-view'
}
function getlastord() {
let myord = 0
for (const file of mylistimages.value) {
if (file.order! > myord)
myord = file.order!
}
return myord + 10
}
function uploaded(info: any) {
console.log(info)
for (const file of info.files) {
mylistimages.value.push({ imagefile: file.name, order: getlastord() })
}
save()
}
function deleted(rec: any) {
// console.table(mylistimages)
const index = mylistimages.value.findIndex((elem) => elem.imagefile === rec.imagefile)
if (index > -1) {
mylistimages.value.splice(index, 1)
}
// mylistimages = mylistimages.pop((elem) => elem.imagefile !== rec.imagefile)
// console.table(mylistimages)
save()
}
function getfullname(rec: any) {
return 'statics/upload/' + mygall.value.directory + '/' + rec.imagefile
}
function copytoclipboard(rec: any) {
const filename = getfullname(rec)
tools.copyStringToClipboard(filename, true)
}
async function deleteFile(rec: any)
{
const filename = getfullname(rec)
// Delete File on server:
const ris = await globalStore.DeleteFile({ filename })
if (ris)
deleted(rec)
}
function save() {
emit('showandsave', mylistimages)
}
function getsrcimg(mygallery: any) {
if (tools.getextfile(mygallery.imagefile) === 'pdf')
return 'statics/images/images/pdf.jpg'
else
return 'statics/upload/' + mygall.value.directory + '/' + mygallery.imagefile
}
created()
return {
getlistimages,
onDragStart,
onDragEnter,
onDragLeave,
onDragOver,
onDrop,
getclass,
getclimg,
getlastord,
copytoclipboard,
deleteFile,
getsrcimg,
}
}
})

View File

@@ -0,0 +1,136 @@
<template>
<!--<div class="q-pa-md items-start " style="display: inline-flex; width: 800px;"> -->
<div>
<div v-if="!edit">
<div v-for="(mygallery, index) in getlistimages" :key="index">
<div v-if="index === 0">
<div class="q-pa-md q-gutter-md">
<q-card :class="getclass">
<q-img
:src="getsrcimg(mygallery)" :class="getclimg"
:alt="mygallery.alt">
<div class="absolute-bottom text-shadow">
{{ listimages.length }} files
</div>
</q-img>
</q-card>
</div>
</div>
</div>
</div>
<div v-else>
<div class=" row">
<!--<q-draggable-rows
v-model="order">-->
<div v-for="(mygallery, index) in getlistimages" :key="index">
<div
class="q-pa-sm q-gutter-sm"
@dragenter="onDragEnter"
@dragleave="onDragLeave"
@dragover="onDragOver">
<q-card
:id="mygallery._id" :class="getclass"
draggable="true"
@dragstart="onDragStart"
@drop="onDrop"
>
<q-img
:src="getsrcimg(mygallery)"
:class="getclimg"
:alt="mygallery.alt">
<div class="absolute-bottom text-shadow">
<!-- <div class="text-h6 text-trans">{{ mygallery.description }} </div> -->
<div class="text-subtitle-carica text-trans">{{ mygallery.description }}</div>
</div>
</q-img>
<!--
<q-input v-model="mygallery._id"
label="Id"
dense
@keyup.enter.stop
@input="save"
debounce="1000"
autofocus>
</q-input>
-->
<q-field
stack-label
dense
label="FileName">
<template v-slot:control>
<div class="self-center full-width no-outline" tabindex="0">{{ mygallery.imagefile }}</div>
</template>
</q-field>
<!--<q-input v-model="mygallery.order"
:label="$t('disc.order')"
dense
@keyup.enter.stop
@input="save"
debounce="1000"
autofocus>
</q-input>-->
<!--<q-input v-model="mygallery.alt"
label="Alt"
dense
@keyup.enter.stop
@input="save"
debounce="1000"
autofocus>
</q-input>-->
<q-input
v-model="mygallery.description"
dense
:label="$t('proj.longdescr')"
@keyup.enter.stop
@input="save"
debounce="1000"
autofocus>
</q-input>
<q-card-actions align="center">
<q-btn
flat round color="blue" icon="fas fa-copy" size="sm"
@click="copytoclipboard(mygallery)"></q-btn>
<q-btn
flat round color="red" icon="fas fa-trash-alt" size="sm"
@click="deleteFile(mygallery)"></q-btn>
</q-card-actions>
</q-card>
</div>
</div>
<div class="q-pa-sm">
<div v-if="edit" class="q-gutter-sm " style="max-height: 200px; width: 208px;">
<q-uploader
label="Aggiungi Immagine o PDF"
accept=".jpg, image/*, .pdf"
:url="tools.geturlupload()+`/` + gall.directory"
:headers="tools.getheaders()"
:max-file-size="2000000"
multiple
auto-upload
hide-upload-btn
no-thumbnails
@uploaded="uploaded"
style="width: 208px"
></q-uploader>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" src="./CGallery.ts">
</script>
<style lang="scss" scoped>
@import './CGallery.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CGallery} from './CGallery.vue'

View File

@@ -0,0 +1,22 @@
.colmodif {
cursor: pointer;
}
.coldate {
max-width: 250px;
min-width: 200px;
}
.tdclass, .trclass{
height: 20px !important;
}
.q-table td {
padding-left: 1px;
padding-right: 2px;
padding-top: 0;
padding-bottom: 0;
&__title {
font-size: 1rem;
}
}

View File

@@ -0,0 +1,778 @@
import { defineComponent, PropType, ref, watch, toRef, onMounted } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { tools } from '../../store/Modules/tools'
import { IColGridTable, IFilter, ITableRec, IPagination } from '../../model'
import { lists } from '../../store/Modules/lists'
import { IParamsQuery } from '../../model/GlobalStore'
import { CMyPopupEdit } from '../CMyPopupEdit'
import { CTitleBanner } from '../CTitleBanner'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { costanti } from '@costanti'
export default defineComponent({
name: 'CGridTableRec',
props: {
prop_mytitle: {
type: String,
required: true,
},
prop_mytable: {
type: String,
required: false,
default: '',
},
prop_mycolumns: {
type: Object as PropType<[]>,
required: false,
default: null,
},
prop_colkey: {
type: String,
required: false,
default: '',
},
prop_codeId: {
type: String,
required: false,
default: '',
},
nodataLabel: {
type: String,
required: false,
default: '',
},
labelBtnAddRow: {
type: String,
required: false,
default: 'Aggiungi',
},
noresultLabel: {
type: String,
required: false,
default: '',
},
tablesList: {
type: Object as PropType<ITableRec[]>,
required: false,
default: null,
},
arrfilters: {
type: Object as PropType<IFilter[]>,
required: false,
default: null,
},
filterdef: {
type: Array,
required: false,
default: () => {
return []
}
},
extraparams: {
required: false,
default: {},
},
pagination: {
type: Object as PropType<IPagination>,
required: false,
default: () => {
return { sortBy: '', descending: false, page: 1, rowsNumber: 10, rowsPerPage: 10 }
},
},
defaultnewrec: {
type: Function,
required: true,
},
},
components: { CMyPopupEdit, CTitleBanner },
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
const addRow = ref('Aggiungi')
const newRecordBool = ref(false)
const newRecord: any = ref({})
const savenewRec = ref(false)
const mytable = ref('')
const mytitle = ref('')
const mycolumns = ref([])
const colkey = ref('')
const search = ref('')
const tablesel = ref('')
const loading = ref(false)
const serverData: any = ref([])
const spinner_visible = ref(false)
let idsel = ''
let colsel = ref(<IColGridTable | null>{ name: '', field: '' })
let valPrec = ''
let separator: 'horizontal'
const myfilter = ref('')
const myfilterand: any = ref([])
let rowsel: any = {}
let dark = true
const canEdit = ref(false)
let returnedData: any = ref([])
let returnedCount = 0
const colVisib: any = ref([])
const colExtra: any = ref([])
const rowclicksel = ref(<any>null)
const colclicksel = ref(null)
const selected: any = ref([])
const mycodeid = toRef(props, 'prop_codeId')
const mypag = toRef(props, 'pagination')
// emulate 'SELECT count(*) FROM ...WHERE...'
function getRowsNumberCount(myfilter?: any) {
// if (!myfilter) {
// return original.length
// }
// let count = 0
// original.forEach((treat) => {
// if (treat['name'].includes(myfilter)) {
// ++count
// }
// })
// return count
return returnedCount
}
// emulate ajax call
// SELECT * FROM ... WHERE...LIMIT...
async function fetchFromServer(startRow: any, endRow: any, myfilter: any, myfilterand: any, sortBy: any, descending: any) {
let myobj = null
if (sortBy) {
myobj = {}
if (descending) { // @ts-ignore
myobj[sortBy] = -1
} else { // @ts-ignore
myobj[sortBy] = 1
}
}
let params: IParamsQuery = {
table: mytable.value,
startRow,
endRow,
filter: myfilter,
filterand: myfilterand,
sortBy: myobj,
descending,
userId: userStore.my._id,
codeId: '',
}
params.codeId = mycodeid.value
params = { ...params, ...props.extraparams }
const data = await globalStore.loadTable(params)
if (data) {
returnedData.value = data.rows
returnedCount = data.count
} else {
returnedData.value = []
returnedCount = 0
}
return true
}
function savefilter() {
// console.log('Close')
emit('savefilter', myfilterand)
}
function onRequest(myprops: any) {
// console.log('onRequest', 'myfilter = ', myfilter)
const { page, rowsPerPage, rowsNumber, sortBy, descending } = myprops.pagination
const myfilternow = myfilter.value
const myfilterandnow = myfilterand.value
savefilter()
if (!mytable.value)
return
loading.value = true
spinner_visible.value = true
// update rowsCount with appropriate value
// function all rows if "All" (0) is rowsel
const fetchCount = rowsPerPage === 0 ? rowsNumber : rowsPerPage
// calculate starting row of data
const startRow = (page - 1) * rowsPerPage
const endRow = startRow + fetchCount
// console.log('startRow', startRow, 'endRow', endRow)
serverData.value = []
// fetch data from "server"
fetchFromServer(startRow, endRow, myfilternow, myfilterandnow, sortBy, descending).then((ris: any) => {
myprops.pagination.rowsNumber = getRowsNumberCount(myfilter)
// clear out existing data and add new
if (returnedData.value === []) {
serverData.value = []
} else {
// if (serverData.length > 0)
// serverData.splice(0, serverData.length, ...returnedData)
// else
serverData.value = [...returnedData.value]
}
// console.log('serverData', serverData)
// don't forfunction to update local pagination object
myprops.pagination.page = page
myprops.pagination.rowsPerPage = rowsPerPage
myprops.pagination.sortBy = sortBy
myprops.pagination.descending = descending
// console.log('pagination', pagination)
// ...and turn of loading indicator
loading.value = false
spinner_visible.value = false
})
}
function refresh_table() {
onRequest({
pagination: props.pagination
})
rowclicksel.value = null
}
function refresh() {
serverData.value = []
search.value = search.value.trim()
// console.log('refresh')
// console.log('search', search)
if (!!search.value && search.value !== '')
myfilter.value = search.value
else
myfilter.value = ''
// console.log('myfilter', myfilter)
refresh_table()
}
watch(() => mycodeid.value, (newval, oldval) => {
refresh()
})
watch(() => myfilterand.value, (newval, oldval) => {
refresh()
})
function isTutor() {
return userStore.isTutor
}
function disabilita() {
if ((mytable.value === 'users') && (isTutor)) {
return true
}
return false
}
function tableClass() {
if (dark) {
return 'bg-black'
}
}
function selItem(item: any, col: IColGridTable) {
// console.log('selItem', item)
rowsel = item
idsel = item._id
colsel.value = col
}
function undoVal() {
console.log('undoVal', 'colsel', colsel, 'valprec', valPrec, 'colkey', colkey, 'selected', rowsel)
// console.table(serverData)
if (colsel.value) {
if (colsel.value.subfield !== '') {
if (rowsel[colsel.value.field!] === undefined)
rowsel[colsel.value.field!] = {}
rowsel[colsel.value.field!][colsel.value.subfield!] = valPrec
} else {
rowsel[colsel.value.field!] = valPrec
}
}
// serverData[colsel] = valPrec
}
function SaveValdb(newVal: any, valinitial: any) {
// console.log('SaveValdb', newVal)
// console.log('SaveValue', newVal, 'rowsel', rowsel)
colsel.value = colclicksel.value
// console.log('colsel', colsel)
SaveValue(newVal, valinitial)
colsel.value = { name: '', field: '' }
}
function showandsel(row: any, col: any, newval: any, valinitial: any) {
// console.log('showandsel', row, col, newval)
rowsel = row
colsel = col
idsel = row._id
SaveValue(newval, valinitial)
// rowclicksel = null
}
function annulla(val: any) {
console.log('annulla')
globalStore.DeleteRec({ table: mytable.value, id: newRecord.value._id })
.then((ris) => {
return true
})
}
function SaveValue(newVal: any, valinitial: any) {
// console.log('SaveValue', newVal, 'rowsel', rowsel)
if (colsel.value) {
// Update value in table memory
if (colsel.value.subfield !== '') {
if (rowsel[colsel.value.field!] === undefined)
rowsel[colsel.value.field!] = {}
rowsel[colsel.value.field!][colsel.value.subfield!] = newVal
} else {
rowsel[colsel.value.field!] = newVal
}
}
const mydata = <any>{
id: idsel,
table: mytable,
fieldsvalue: {}
}
if (colsel.value) {
if (colsel.value.subfield !== '') {
if (mydata.fieldsvalue[colsel.value.field!] === undefined) {
mydata.fieldsvalue[colsel.value.field! + '.' + colsel.value.subfield!] = newVal
}
// mydata.fieldsvalue[colsel.value.field][colsel.subfield] = newVal
} else {
if (colsel.value) {
mydata.fieldsvalue[colsel.value.field!] = newVal
}
}
}
valPrec = valinitial
saveFieldValue(mydata)
}
function created() {
console.log('created')
// serverData = mylist.slice() // [{ chiave: 'chiave1', valore: 'valore 1' }]
mytable.value = props.prop_mytable
mytitle.value = props.prop_mytitle
mycolumns.value = props.prop_mycolumns
colkey.value = props.prop_colkey
changeTable(false)
}
function updatedcol() {
// console.log('updatedcol')
if (mycolumns.value) {
colVisib.value = []
colExtra.value = []
mycolumns.value.forEach((elem: IColGridTable) => {
const mysub = elem.subfield ? elem.subfield : ''
if (elem) {
if (elem.field !== costanti.NOFIELD) {
colVisib.value.push(elem.field + mysub)
}
if (elem.visible && elem.field === costanti.NOFIELD) {
colExtra.value.push(elem.name)
}
}
})
}
}
function getrows() {
return props.pagination.rowsNumber
}
async function createNewRecordDialog() {
const mydata: any = {
table: mytable,
data: function () {
return {}
}
}
mydata.data = props.defaultnewrec
// const mykey = fieldsTable.getKeyByTable(mytable)
// mydata.data[mykey] = ''
console.log('mydata', mydata)
newRecord.value = await globalStore.saveTable(mydata)
newRecordBool.value = true
}
async function createNewRecord() {
loading.value = true
const mydata = {
table: mytable,
data: {}
}
mydata.data = props.defaultnewrec
// const mykey = fieldsTable.getKeyByTable(mytable)
// mydata.data[mykey] = ''
console.log('mydata', mydata)
const data = await globalStore.saveTable(mydata)
serverData.value.push(data)
mypag.value.rowsNumber++
loading.value = false
}
function saveFieldValue(mydata: any) {
// console.log('saveFieldValue', mydata)
// Save on Server
globalStore.saveFieldValue(mydata).then((esito) => {
if (esito) {
tools.showPositiveNotif($q, t('db.recupdated'))
} else {
tools.showNegativeNotif($q, t('db.recfailed'))
undoVal()
}
})
}
function mounted() {
console.log('GridTable mounted', tablesel)
if (!!props.tablesList) {
canEdit.value = tools.getCookie(tools.CAN_EDIT, canEdit) === 'true'
tablesel.value = tools.getCookie('tablesel', tablesel)
}
myfilterand.value = props.filterdef
console.log('tablesel', tablesel)
if (tablesel.value === '') {
if (!!props.tablesList)
tablesel.value = props.tablesList[0].value
else
tablesel.value = mytable.value
}
console.log('2) tablesel', tablesel)
changeTable(false)
}
function clickFunz(item: any, col: IColGridTable) {
if (col.action) {
tools.ActionRecTable(null, col.action, mytable.value, item._id, item, col.askaction)
}
}
function ActionAfterYes(action: number, item: any, data?: any) {
if (action === lists.MenuAction.DELETE_RECTABLE) {
if ((serverData.value.length > 0) && item) {
serverData.value.splice(serverData.value.indexOf(item), 1)
refresh_table()
}
} else if (action === lists.MenuAction.DUPLICATE_RECTABLE) {
// Add record duplicated
// serverData.push(data)
refresh()
}
}
function visCol(col: IColGridTable) {
if (col.visuonlyEditVal) {
if (canEdit.value) {
return col.visuonlyEditVal
} else {
return false
}
} else {
return true
}
}
function changeCol(newval: any) {
console.log('changecol', mytable)
if (!!mytable.value) {
tools.setCookie(mytable, colVisib.value.join('|'))
}
}
function changeTable(mysel: any) {
if (tablesel.value === undefined || tablesel.value === '')
return
// console.log('changeTable mysel=', mysel, 'tablesel', tablesel)
// console.log('tablesList=')
// console.table(tablesList)
let mytab = null
if (props.tablesList) {
mytab = props.tablesList.find((rec: any) => rec.value === tablesel.value)
}
if (mytab === undefined) {
tablesel.value = props.tablesList[0].value
if (props.tablesList) {
mytab = props.tablesList.find((rec: any) => rec.value === tablesel.value)
}
}
// console.log('tablesel', tablesel, 'mytab', mytab)
if (mytab) {
mytitle.value = mytab.label
colkey.value = mytab.colkey
// @ts-ignore
mycolumns.value = [...mytab.columns]
}
// console.log('mycolumns')
// console.log(mycolumns)
// console.log('tablesList:')
// console.table(tablesList)
if (!!mycolumns.value) {
mycolumns.value.forEach((rec: IColGridTable) => {
if (rec.label_trans)
rec.label = t(rec.label_trans)
})
}
if (mytab) {
mytable.value = mytab.value
}
if (!!props.tablesList) {
tools.setCookie('tablesel', tablesel.value)
}
updatedcol()
if (!!mytable.value) {
const myselcol = tools.getCookie(mytable, '')
if (!!myselcol && myselcol.length > 0) {
colVisib.value = myselcol.split('|')
} else {
mycolumns.value.forEach((elem: any) => {
if (elem.field !== costanti.NOFIELD)
colVisib.value.push(elem.field + elem.subfield)
})
}
}
refresh()
}
function doSearch() {
refresh()
}
function changefuncAct(newval: any) {
if (!disabilita) {
tools.setCookie(tools.CAN_EDIT, newval)
}
}
function clickrowcol(row: any, col: any) {
if (!canEdit.value) {
if (!selected.value[0]) {
const uguali = rowclicksel.value!._id === row._id
console.log('id', rowclicksel.value!._id, 'id2', row._id)
rowclicksel.value = null
colclicksel.value = null
} else {
rowclicksel.value = row
colclicksel.value = col
}
}
}
function getclrow(myrow: any) {
if (rowclicksel.value === myrow)
return 'colsel'
else
return ''
}
function getSelectedString() {
return selected.value.length === 0 ? '' : `${selected.value.length} record${selected.value.length > 1 ? 's' : ''} selected of ${serverData.value.length}`
}
function selectionclick(details: any) {
// console.log('selectionclick selected', selected, 'details', details)
if (details.added) {
rowclicksel.value = details.rows[0]
colclicksel.value = details.keys[0]
} else {
rowclicksel.value = null
colclicksel.value = null
}
// console.log('rowclicksel', rowclicksel)
}
function getusernamesel() {
try {
if (rowclicksel.value) {
return rowclicksel.value.username
}
} catch (e) {
return ''
}
}
async function saveNewRecord() {
console.log('saveNewRecord')
savenewRec.value = true
const mydata = {
table: mytable,
data: {}
}
mydata.data = newRecord
const data = await globalStore.saveTable(mydata)
.then((ris) => {
if (ris) {
// console.log('ris', ris)
newRecordBool.value = false
refresh()
}
})
}
function hidewindow() {
console.log('hidewindow')
if (!savenewRec.value) {
annulla(0)
}
}
function isfinishLoading() {
return globalStore.finishLoading
}
function getlabelAddRow() {
return props.labelBtnAddRow
}
function visButtRow() {
return props.labelBtnAddRow !== addRow.value
}
onMounted(mounted)
created()
return {
selItem,
SaveValdb,
showandsel,
annulla,
SaveValue,
updatedcol,
getrows,
createNewRecordDialog,
createNewRecord,
saveFieldValue,
clickFunz,
visCol,
changeCol,
changeTable,
doSearch,
changefuncAct,
clickrowcol,
getclrow,
getSelectedString,
selectionclick,
getusernamesel,
saveNewRecord,
hidewindow,
isfinishLoading,
getlabelAddRow,
visButtRow,
mytable,
mytitle,
mycolumns,
colkey,
search,
canEdit,
rowclicksel,
colVisib,
colExtra,
colclicksel,
selected,
}
}
})

View File

@@ -0,0 +1,264 @@
<template>
<div class="q-pa-xs" v-if="isfinishLoading()">
<div class="centermydiv q-ma-sm" style="text-align: center">
<q-btn
v-if="mytable && visButtRow()" rounded dense color="primary"
size="lg"
:label="getlabelAddRow"
@click="createNewRecordDialog"></q-btn>
</div>
<q-table
flat
bordered
class="my-sticky-header-table"
:data="serverData"
:columns="mycolumns"
:filter="myfilter"
v-model:pagination="pagination"
:row-key="colkey"
:loading="loading"
@request="onRequest"
@selection="selectionclick"
binary-state-sort
:visible-columns="colVisib"
:no-data-label="nodataLabel"
:no-results-label="noresultLabel"
:selected-rows-label="getSelectedString"
selection="single"
v-model:selected="selected">
<template v-slot:header="props">
<q-tr :props="props">
<q-th>
</q-th>
<q-th
v-for="col in props.cols" :key="col.name">
<div
v-if="colVisib.includes(col.field + col.subfield)"
:props="props"
class="text-italic text-weight-bold"
>
{{ col.label }}
</div>
</q-th>
</q-tr>
</template>
<template>
<div class="q-table__title" style="min-width: 150px;">{{ mytitle }}</div>
<!--<p style="color:red"> Rows: {{ getrows }}</p>-->
<q-input
v-model="search" filled dense type="search" debounce="500" hint="Search"
v-on:keyup.enter="doSearch">
<template v-slot:after>
<q-btn v-if="mytable" label="" color="primary" @click="refresh()" icon="search"></q-btn>
</template>
</q-input>
<q-toggle
v-if="mytable" v-model="canEdit" :disable="disabilita()" :val="lists.MenuAction.CAN_EDIT_TABLE"
class="q-mx-sm"
:label="$t('grid.editvalues')" @input="changefuncAct">
</q-toggle>
<q-btn
v-if="mytable" flat dense color="primary" :disable="loading || !canEdit"
:label="$t('grid.addrecord')"
@click="createNewRecord">
</q-btn>
<q-space/>
<!--<q-toggle v-for="(mycol, index) in mycolumns" v-model="colVisib" :val="rec.field" :label="mycol.label"></q-toggle>-->
<q-select
v-if="mytable"
v-model="colVisib"
rounded
outlined
multiple
dense
options-dense
:display-value="$t('grid.columns')"
emit-value
map-options
:options="mycolumns"
option-value="name"
º
@input="changeCol">
</q-select>
<q-select
v-if="tablesList"
v-model="tablesel"
rounded
outlined
dense
:options="tablesList"
:display-value="mytitle"
emit-value
@input="changeTable"
>
</q-select>
<q-inner-loading :showing="spinner_visible">
<q-spinner-tail size="2em" color="primary"/>
</q-inner-loading>
<div class="row">
<q-toggle
v-for="(filter, index) of arrfilters"
:key="index"
v-model="myfilterand" :disable="filter.hide"
:val="filter.value"
:label="filter.label">
</q-toggle>
</div>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="trclass">
<q-td auto-width class="tdclass">
<q-checkbox dense v-model="props.selected"></q-checkbox>
</q-td>
<q-td
v-for="col in mycolumns" :key="col.name" :props="props">
<div
v-if="colVisib.includes(col.field + col.subfield)" class="tdclass">
<div :class="getclrow(props.row)">
<CMyPopupEdit
:canEdit="canEdit"
:disable="disabilita"
:col="col"
v-model:row="props.row"
:field="col.field"
:subfield="col.subfield"
minuteinterval="1"
@save="SaveValue"
@show="selItem(props.row, col)"
@showandsave="showandsel">
</CMyPopupEdit>
</div>
</div>
</q-td>
<q-td
v-for="col in mycolumns" :key="col.name" :props="props">
<div
v-if="colExtra.includes(col.name)"
class="tdclass">
<div v-if="col.action && visCol(col)">
<q-btn
flat round color="red" :icon="col.icon" size="sm"
@click="clickFunz(props.row, col)"></q-btn>
</div>
</div>
</q-td>
</q-tr>
</template>
<!--
<q-btn
flat round dense
:icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'"
@click="props.toggleFullscreen"
class="q-ml-md">
</q-btn>
-->
<!---->
</q-table>
<div v-if="rowclicksel">
<CTitleBanner title="Record:"></CTitleBanner>
<div
class="q-ma-xs q-pa-xs text-center rounded-borders q-list--bordered"
v-for="mycol in mycolumns" :key="mycol.name">
<div v-if="colVisib.includes(mycol.field + mycol.subfield)">
<div class="row items-center justify-center q-gutter-md q-ma-xs">
<div class="q-ma-xs">
<q-field rounded outlined bg-color="orange-3" dense>
<template v-slot:control>
<div class="self-center full-width no-outline" tabindex="0">{{ mycol.label }}</div>
</template>
</q-field>
</div>
<div
class="q-ma-sm q-pa-sm colmodif col-grow rounded-borders " style="border: 1px solid #bbb"
@click="colclicksel = mycol">
<CMyPopupEdit
:canEdit="true"
:disable="disabilita"
view="field"
:col="mycol"
:showall="true"
:row="rowclicksel"
:field="mycol.field"
:subfield="mycol.subfield"
@save="SaveValdb"
@show="selItem(rowclicksel, mycol)"
@showandsave="showandsel"
@annulla="annulla">
</CMyPopupEdit>
</div>
</div>
</div>
</div>
</div>
<q-dialog v-model="newRecordBool" @hide="hidewindow">
<q-card :style="`min-width: `+ tools.myheight_dialog() + `px;`">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ mytitle }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<div
v-for="col in mycolumns" :key="col.name">
<div
v-if="colVisib.includes(col.field + col.subfield)">
<div>
<CMyPopupEdit
:canEdit="true"
:col="col"
v-model:row="newRecord"
:field="col.field"
:subfield="col.subfield"
minuteinterval="1"
:visulabel="true"
@save="SaveValue"
@show="selItem(newRecord, col)"
@showandsave="showandsel">
</CMyPopupEdit>
</div>
</div>
</div>
</q-card-section>
<q-card-actions align="center">
<q-btn flat :label="$t('dialog.ok')" color="primary" @click="saveNewRecord"></q-btn>
<q-btn flat :label="$t('dialog.cancel')" color="primary" v-close-popup @click="annulla"></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
</div>
</template>
<script lang="ts" src="./CGridTableRec.ts">
</script>
<style lang="scss">
@import './CGridTableRec.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CGridTableRec} from './CGridTableRec.vue'

View File

100
src/components/CHours/CHours.ts Executable file
View File

@@ -0,0 +1,100 @@
import { colTableHours } from '@src/store/Modules/fieldsTable'
import { shared_consts } from '@src/common/shared_vuejs'
import { defineComponent, ref } from 'vue'
import { IPagination } from 'model'
import { CImgText } from '@/components/CImgText'
import { CCard } from '../CCard'
import { CMyPage } from '@/components/CMyPage'
import { CTitleBanner } from '@/components/CTitleBanner'
import { CGridTableRec } from '@/components/CGridTableRec'
import { useUserStore } from '@store/UserStore'
export default defineComponent({
name: 'CHours',
components: { CImgText, CCard, CMyPage, CTitleBanner, CGridTableRec },
props: {
todoId: {
type: String,
required: true,
},
},
setup(props){
const userStore = useUserStore()
const pagination = ref(<IPagination> {
sortBy: 'descr',
descending: false,
page: 2,
rowsPerPage: 5
// rowsNumber: xx if getting data from a server
})
function extraparams() {
return {
lk_tab: 'users',
lk_LF: 'userId',
lk_FF: '_id',
lk_as: 'user',
af_objId_tab: 'myId',
lk_proj: {
todoId: 1, userId: 1, descr: 1, date: 1, time_start: 1, time_end: 1, hours: 1,
username: 1, name: 1, surname: 1
}
}
}
const arrfilterand = [
{
label: 'Tutte le ore',
value: shared_consts.FILTER_HOURS_ALL
}
]
function myfilterdef() {
return [shared_consts.FILTER_HOURS_MYLIST]
}
function myarrfilterand() {
const myfiltrodef = {
label: 'Mie Ore',
value: shared_consts.FILTER_HOURS_MYLIST,
hide: true,
default: true
}
let myarr = []
myarr.push(myfiltrodef)
if (arrfilterand)
myarr = [...myarr, ...arrfilterand]
return myarr
}
// const selected = []
function getcolHours() {
return colTableHours
}
function getdefaultnewrec() {
const myrec: any = {
todoId: props.todoId,
userId: userStore.my._id,
descr: ''
}
return myrec
}
return {
myfilterdef,
myarrfilterand,
extraparams,
getcolHours,
getdefaultnewrec,
pagination,
}
},
})

View File

@@ -0,0 +1,27 @@
<template>
<div>
<div class="q-ma-sm q-gutter-sm q-pa-xs">
<CGridTableRec
prop_mytable="hours"
prop_mytitle="Lista Ore"
:prop_mycolumns="getcolHours"
prop_colkey="descr"
nodataLabel="Nessuna Lista Ore"
noresultLabel="Il filtro selezionato non ha trovato nessun risultato"
:arrfilters="myarrfilterand"
:filterdef="myfilterdef"
:prop_codeId="todoId"
:defaultnewrec="getdefaultnewrec"
:extraparams="extraparams"
labeladd="Aggiungi Ora">
</CGridTableRec>
</div>
</div>
</template>
<script lang="ts" src="./CHours.ts">
</script>
<style lang="scss" scoped>
@import 'CHours.scss';
</style>

1
src/components/CHours/index.ts Executable file
View File

@@ -0,0 +1 @@
export {default as CHours} from './CHours.vue'

View File

@@ -1,4 +1,4 @@
import { defineComponent, onMounted, ref, watch } from 'vue' import { defineComponent, onMounted, ref, toRef, watch } from 'vue'
import { useUserStore } from '@store/UserStore' import { useUserStore } from '@store/UserStore'
export default defineComponent({ export default defineComponent({
@@ -23,6 +23,7 @@ export default defineComponent({
const userStore = useUserStore() const userStore = useUserStore()
const imgprofile = ref(userStore.my.profile.img) const imgprofile = ref(userStore.my.profile.img)
const myimgvar = toRef(props, 'myimg')
function refresh() { function refresh() {
if (!props.myimg) { if (!props.myimg) {
@@ -44,10 +45,7 @@ export default defineComponent({
watch( watch(
// @ts-ignore myimgvar, (value: string, oldValue: string) => {
props.myimg,
// @ts-ignore
(value: string, oldValue: string) => {
myimgint.value = '' myimgint.value = ''
refresh() refresh()
}, },
@@ -57,6 +55,7 @@ export default defineComponent({
return { return {
myimgint, myimgint,
myicon,
} }
}, },
}) })

View File

@@ -3,9 +3,11 @@ import { CCardState } from '../CCardState'
import { computed, defineComponent } from 'vue' import { computed, defineComponent } from 'vue'
import { useGlobalStore } from '@store/globalStore' import { useGlobalStore } from '@store/globalStore'
import { useProducts } from '@store/Products' import { useProducts } from '@store/Products'
import CCopyBtn from '@/components/CCopyBtn/CCopyBtn' import { CCopyBtn } from '@/components/CCopyBtn'
import CSingleCart from '@/components/CSingleCart/CSingleCart' import { CSingleCart } from '@/components/CSingleCart'
import CTitleBanner from '@/components/CTitleBanner/CTitleBanner' import { CTitleBanner } from '@/components/CTitleBanner'
import MixinUsers from '../../mixins/mixin-users'
export default defineComponent({ export default defineComponent({
name: 'CMyCart', name: 'CMyCart',
@@ -16,6 +18,8 @@ export default defineComponent({
const globalStore = useGlobalStore() const globalStore = useGlobalStore()
const products = useProducts() const products = useProducts()
const { getnumItemsCart } = MixinUsers()
const myCart = computed(() => products.cart) const myCart = computed(() => products.cart)
const myTotalPrice = computed(() => { const myTotalPrice = computed(() => {
if (products.cart) { if (products.cart) {
@@ -52,6 +56,7 @@ export default defineComponent({
ordersCart, ordersCart,
numOrders, numOrders,
closecart, closecart,
getnumItemsCart,
} }
}, },
}) })

View File

@@ -1,12 +1,13 @@
<template> <template>
<div> <div>
MyCart:<br>
<div id="mycontainer"> <div id="mycontainer">
<div class="myheader row justify-between"> <div class="myheader row justify-between">
<div class="col-6"> <div class="col-6">
<q-btn class="q-mx-xs" round dense flat icon="fas fa-shopping-cart"> <q-btn class="q-mx-xs" round dense flat icon="fas fa-shopping-cart">
<q-badge v-if="getnumItemsCart > 0" color="red" floating transparent> <q-badge v-if="getnumItemsCart() > 0" color="red" floating transparent>
{{ getnumItemsCart }} {{ getnumItemsCart() }}
</q-badge> </q-badge>
</q-btn> </q-btn>
</div> </div>

View File

@@ -0,0 +1,6 @@
.clchip{
display: flex;
justify-content: center;
//flex: 1;
//flex-direction: column;
}

View File

@@ -0,0 +1,157 @@
import { defineComponent, ref, watch, toRef, onMounted } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useQuasar } from 'quasar'
import { tools } from '@store/Modules/tools'
import { costanti } from '@costanti'
export default defineComponent({
name: 'CMyChipList',
props: {
options: {
type: Array,
required: true,
},
value: [String, Number, Array],
type: {
type: Number,
required: true,
},
optlab: {
type: String,
required: true,
},
optval: {
type: String,
required: true,
},
myclass: {
type: String,
required: false,
default: ''
},
opticon: {
type: String,
required: false,
default: ''
},
optcolor: {
type: String,
required: false,
default: ''
},
},
components: {},
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const myval = toRef(props, 'value')
const myarrvalues = ref(<any>[])
watch(() => myval.value, (newval, oldval) => {
refreshval()
})
function refreshval() {
myarrvalues.value = []
// console.table(options)
if (props.options) {
props.options.forEach((rec: any, index) => {
if (props.type === costanti.FieldType.multiselect) {
if (!!myval.value) {
// @ts-ignore
if (myval.value.includes(rec[props.optval])) {
const mydata: any = {
label: null,
value: rec[props.optval],
// myris = mylist.filter((myrec) => arrval.includes(myrec[key]))
valbool: true,
icon: '',
color: tools.getColorByIndexBest(index)
}
if (tools.isObject(props.optlab)) {
// @ts-ignore
mydata.label = props.options.filter((myrec: any) => myrec[props.optval] === mydata.value).map(props.optlab)
if (mydata.label)
mydata.label = mydata.label[0]
} else {
mydata.label = rec[props.optlab]
}
if (props.opticon)
mydata.icon = rec[props.opticon]
if (props.optcolor)
mydata.color = rec[props.optcolor]
myarrvalues.value.push(mydata)
}
}
} else if (props.type === costanti.FieldType.select) {
if (myval.value === rec[props.optval]) {
const mydata: any = {
value: myval.value,
valbool: true,
icon: '',
color: tools.getColorByIndexBest(index)
}
// console.log('mydata', mydata, 'optlab', optlab, 'myval.value', myval.value)
if (tools.isObject(props.optlab)) {
// @ts-ignore
mydata.label = props.options.filter((myrec: any) => myrec[props.optval] === mydata.value).map(props.optlab)
if (mydata.label)
mydata.label = mydata.label[0]
} else {
mydata.label = rec[props.optlab]
}
if (props.opticon)
mydata.icon = rec[props.opticon]
if (props.optcolor)
mydata.color = rec[props.optcolor]
myarrvalues.value.push(mydata)
}
} else {
if (tools.isBitActive(myval.value, rec[props.optval])) {
const mydata = {
label: t(rec[props.optlab]),
value: rec[props.optval],
valbool: tools.isBitActive(myval.value, rec[props.optval]),
icon: '',
color: tools.getColorByIndexBest(index)
}
if (props.opticon)
mydata.icon = rec[props.opticon]
if (props.optcolor)
mydata.color = rec[props.optcolor]
myarrvalues.value.push(mydata)
}
}
})
}
if (myarrvalues.value.length === 0)
myarrvalues.value.push({ label: t('otherpages.manage.nessuno'), color: 'gray' })
// console.log('arrvalues=', myarrvalues)
}
function mounted() {
refreshval()
}
onMounted(mounted)
return {
myarrvalues,
}
}
})

View File

@@ -0,0 +1,27 @@
<template>
<div class="row clchip">
<div v-for="(rec, index) in myarrvalues" :key="index">
<q-chip
v-if="rec.icon"
dense
:color="rec.color"
text-color="white"
:icon="rec.icon">
{{ rec.label }}
</q-chip>
<q-chip
dense
:color="rec.color"
text-color="white">
{{ rec.label }}
</q-chip>
</div>
</div>
</template>
<script lang="ts" src="./CMyChipList.ts">
</script>
<style lang="scss" scoped>
@import './CMyChipList.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CMyChipList} from './CMyChipList.vue'

View File

@@ -0,0 +1,4 @@
.myflex{
display: flex;
flex: 1;
}

View File

@@ -0,0 +1,175 @@
import { tools } from '@store/Modules/tools'
import { CTitleBanner } from '../CTitleBanner'
import { defineComponent, ref, toRef } from 'vue'
import { useQuasar } from 'quasar'
export default defineComponent({
name: 'CMyEditor',
components: { CTitleBanner },
props: {
title: {
type: String,
required: false,
default: '',
},
value: {
type: String,
required: true,
},
myclass: {
type: String,
required: false,
default: '',
},
showButtons: {
type: Boolean,
required: false,
default: true,
},
},
setup(props, { emit }) {
const $q = useQuasar()
const editor = ref(null)
const myvalue = toRef(props, 'value')
const mycolor = ref('')
const showeditor= ref(true)
const myfonts = ref({
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana'
})
const toolbarcomp = ref([
['left', 'center', 'right', 'justify'],
['bold', 'italic', 'underline', 'strike'],
[
{
label: $q.lang.editor.formatting,
icon: $q.iconSet.editor.formatting,
list: 'no-icons',
options: [
'p',
'h4',
'h5',
'h6',
'code'
]
},
{
label: $q.lang.editor.fontSize,
icon: $q.iconSet.editor.fontSize,
fixedLabel: true,
fixedIcon: true,
list: 'no-icons',
options: [
'size-1',
'size-2',
'size-3',
'size-4',
'size-5',
'size-6',
'size-7'
]
},
{
label: $q.lang.editor.defaultFont,
icon: $q.iconSet.editor.font,
fixedIcon: true,
list: 'no-icons',
options: [
'default_font',
'arial',
'arial_black',
'comic_sans',
'courier_new',
'impact',
'lucida_grande',
'times_new_roman',
'verdana'
]
},
'removeFormat'
],
['quote', 'unordered', 'ordered', 'outdent', 'indent'],
['undo', 'redo', 'viewsource'],
])
function changeval(newval: any) {
// console.log('changeval', newval)
emit('update:value', newval)
}
function annulla() {
emit('annulla', true)
}
function saveval() {
// Converti i <b> in <strong>
myvalue.value = tools.convertiTagHTMLPerBOT(myvalue.value)
console.log('saveval', myvalue)
emit('showandsave', myvalue)
// emit('update:value', myvalue)
showeditor.value = false
}
function setcolor() {
document.execCommand('foreColor', false, mycolor.value)
}
/**
* Capture the <CTL-V> paste event, only allow plain-text, no images.
*
* see: https://stackoverflow.com/a/28213320
*
* @param {object} evt - array of files
* @author Daniel Thompson-Yvetot
* @license MIT
*/
function pasteCapture(evt: any) {
// let text, onPasteStripFormattingIEPaste
// evt.preventDefault()
// if (evt.originalEvent && evt.originalEvent.clipboardData.getData) {
// text = evt.originalEvent.clipboardData.getData('text/plain')
// $refs.editor_ref.runCmd('insertText', text)
// }
// else if (evt.clipboardData && evt.clipboardData.getData) {
// text = evt.clipboardData.getData('text/plain')
// $refs.editor_ref.runCmd('insertText', text)
// }
// else if (window.clipboardData && window.clipboardData.getData) {
// if (!onPasteStripFormattingIEPaste) {
// onPasteStripFormattingIEPaste = true
// $refs.editor_ref.runCmd('ms-pasteTextOnly', text)
// }
// onPasteStripFormattingIEPaste = false
// }
}
return {
myfonts,
toolbarcomp,
editor,
myvalue,
mycolor,
changeval,
annulla,
saveval,
setcolor,
pasteCapture,
tools,
}
}
})

View File

@@ -0,0 +1,54 @@
<template>
<div>
<q-card :style="`min-width: `+ tools.myheight_dialog() + `px;` ">
<q-toolbar class="bg-primary text-white" style="min-height: 30px;">
<q-toolbar-title>
Editor
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup @click="showeditor=false"></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow" style="padding: 4px !important;">
<CTitleBanner :title="title"></CTitleBanner>
<form
autocapitalize="off"
autocomplete="off"
spellcheck="false">
<q-btn rounded size="sm" color="primary">
<q-icon name="colorize" class="cursor-pointer">
<q-popup-proxy>
<q-color v-model="mycolor" @change="setcolor"></q-color>
</q-popup-proxy>
</q-icon>
</q-btn>
<q-editor
ref="editor"
toolbar-text-color="white"
toolbar-toggle-color="yellow-8"
toolbar-bg="primary"
:toolbar="toolbarcomp"
debounce="500"
:fonts="myfonts"
@input="changeval"
@paste="evt => pasteCapture(evt)"
@keyup.enter.stop
v-model="myvalue">
</q-editor>
</form>
</q-card-section>
<q-card-actions v-if="showButtons" align="center">
<q-btn flat :label="$t('dialog.ok')" color="primary" @click="saveval"></q-btn>
<q-btn flat :label="$t('dialog.cancel')" color="primary" v-close-popup @click="annulla"></q-btn>
</q-card-actions>
</q-card>
</div>
</template>
<script lang="ts" src="./CMyEditor.ts">
</script>
<style lang="scss" scoped>
@import './CMyEditor.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CMyEditor} from './CMyEditor.vue'

View File

@@ -1,164 +1,226 @@
import { Component, Prop, Watch } from 'vue-property-decorator' import { defineComponent, PropType, ref, watch } from 'vue'
import { useQuasar } from 'quasar'
import { tools } from '../../store/Modules/tools' import { useI18n } from '@/boot/i18n'
import { toolsext } from '@src/store/Modules/toolsext' import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { QEditor } from 'quasar' import { IColGridTable } from 'model'
import { CMyEditor } from '../CMyEditor' import { fieldsTable } from '@store/Modules/fieldsTable'
import { tools } from '@store/Modules/tools'
import { toolsext } from '@store/Modules/toolsext'
import { costanti } from '@costanti'
import MixinBase from '../../mixins/mixin-base' import MixinBase from '../../mixins/mixin-base'
import { fieldsTable } from '../../store/Modules/fieldsTable'
import { IColGridTable } from '../../model'
import { CMySelect } from '../CMySelect'
import { GlobalStore, UserStore } from '../../store/Modules'
import { CMyChipList } from '../CMyChipList'
import { CMyToggleList } from '../CMyToggleList'
import translate from '@src/globalroutines/util'
import { CDateTime } from '../CDateTime'
@Component({ export default defineComponent({
name: 'CMyFieldDb', name: 'CMyFieldDb',
components: { CMyEditor, CMySelect, CMyChipList, CMyToggleList, CDateTime } props: {
title: {
type: String,
required: true,
},
mykey: {
type: String,
required: true,
},
mysubkey: {
type: String,
required: false,
default: '',
},
type: {
type: Number,
required: true,
},
serv: {
type: Boolean,
required: false,
default: false,
},
disable: {
type: Boolean,
required: false,
default: false,
},
jointable: {
type: String,
required: false,
default: '',
},
table: {
type: String,
required: false,
default: 'settings',
},
myimg: {
type: String,
required: false,
default: '',
},
id: {
type: String,
required: false,
default: '',
},
idmain: {
type: String,
required: false,
default: '',
},
},
// components: { CMyEditor, CMySelect, CMyChipList, CMyToggleList, CDateTime },
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const globalStore = useGlobalStore()
const myvalue = ref('')
const col: IColGridTable = { name: 'test' }
const canEdit = ref(true)
const countryname = ref('')
const { setValDb, getValDb } = MixinBase()
function crea() {
myvalue.value = getValDb(props.mykey, props.serv, '', props.table, props.mysubkey, props.id, props.idmain)
col.jointable = props.jointable
col.fieldtype = props.type
col.label = props.title
// console.log('CMyFieldDb crea', myvalue)
}
watch(() => props.id, (newval, oldval) => {
crea()
})
function getclassCol(col: any) {
if (col) {
let mycl = (props.disable || col.disable) ? '' : 'colmodif '
mycl += ((col.fieldtype === costanti.FieldType.date) || (col.fieldtype === costanti.FieldType.onlydate)) ? ' coldate flex flex-container ' : ''
return mycl
} else {
return ''
}
}
function visuValByType(val: any) {
if (col.fieldtype === costanti.FieldType.date) {
if (val === undefined) {
return '[]'
} else {
return tools.getstrDateTime(val)
}
} else if (col.fieldtype === costanti.FieldType.onlydate) {
if (val === undefined) {
return '[]'
} else {
return tools.getstrDate(val)
}
} else if (col.fieldtype === costanti.FieldType.boolean) {
return (val) ? t('dialog.yes') : t('dialog.no')
} else if (col.fieldtype === costanti.FieldType.binary) {
if (val === undefined)
return '[---]'
else
return globalStore.getArrStrByValueBinary(col, val)
} else if (col.fieldtype === costanti.FieldType.select) {
if (val === undefined)
return '[---]'
else
return globalStore.getValueByTable(col, val)
} else if (col.fieldtype === costanti.FieldType.multiselect) {
if (val === undefined)
return '[---]'
else
return globalStore.getMultiValueByTable(col, val)
} else if (col.fieldtype === costanti.FieldType.multioption) {
if (val === undefined)
return '[---]'
else
return globalStore.getMultiValueByTable(col, val)
} else if (col.fieldtype === costanti.FieldType.password) {
if (val === undefined)
return '[---]'
else
return '***************'
} else {
if (val === undefined)
return ' <span class="text-grey">(' + t('reg.select') + ')</span> '
else if (val === '') {
return ' <span class="text-grey">(' + t('reg.select') + ')</span> '
} else {
let mystr = tools.firstchars(val, 5000)
if (val) {
if (val.length > 5000)
mystr += '...'
} else {
return val
}
return mystr
}
}
}
function mycl() {
if (props.disable) {
return 'cldisable'
}
}
function myvalprinted() {
return visuValByType(myvalue)
}
function savefield(value: any, initialval: any) {
myvalue.value = value
setValDb(props.mykey, myvalue.value, props.type, props.serv, props.table, props.mysubkey, props.id)
}
function savefieldboolean(value: any) {
if (myvalue.value === undefined)
myvalue.value = 'true'
else
myvalue.value = value
setValDb(props.mykey, myvalue, props.type, props.serv, props.table, props.mysubkey, props.id)
}
function selectcountry({ name, iso2, dialCode }: { name: string, iso2: string, dialCode: string }) {
// console.log(name, iso2, dialCode)
myvalue.value = iso2
countryname.value = name
}
function intcode_change(coderec: any) {
myvalue.value = '+' + coderec.dialCode
}
function onInput(phone: any, phoneObject: any, input: any) {
if (phoneObject?.formatted) {
myvalue.value = phoneObject.formatted
}
}
crea()
return {
mycl,
intcode_change,
selectcountry,
savefieldboolean,
savefield,
myvalprinted,
getclassCol,
canEdit,
myvalue,
col,
countryname,
onInput,
}
},
}) })
export default class CMyFieldDb extends MixinBase {
@Prop({ required: true }) public title
@Prop({ required: true }) public mykey: string
@Prop({ required: false, default: '' }) public mysubkey: string
@Prop({ required: true }) public type: number
@Prop({ required: false, default: false }) public serv: boolean
@Prop({ required: false, default: false }) public disable: boolean
@Prop({ required: false, default: '' }) public jointable: string
@Prop({ required: false, default: 'settings' }) public table: string
@Prop({ required: false, default: '' }) public myimg: string
@Prop({ required: false, default: '' }) public id: string
@Prop({ required: false, default: '' }) public idmain: string
public $t
public myvalue = ''
public col: IColGridTable = { name: 'test' }
public canEdit: boolean = true
public countryname = ''
public created() {
this.crea()
}
public crea() {
this.myvalue = this.getValDb(this.mykey, this.serv, '', this.table, this.mysubkey, this.id, this.idmain)
this.col.jointable = this.jointable
this.col.fieldtype = this.type
this.col.label = this.title
// console.log('CMyFieldDb crea', this.myvalue)
}
@Watch('id')
public idchanged(value) {
this.crea()
}
public getclassCol(col) {
if (col) {
let mycl = (this.disable || col.disable) ? '' : 'colmodif '
mycl += ((col.fieldtype === tools.FieldType.date) || (col.fieldtype === tools.FieldType.onlydate)) ? ' coldate flex flex-container ' : ''
return mycl
} else {
return ''
}
}
public visuValByType(val) {
if (this.col.fieldtype === tools.FieldType.date) {
if (val === undefined) {
return '[]'
} else {
return tools.getstrDateTime(val)
}
} else if (this.col.fieldtype === tools.FieldType.onlydate) {
if (val === undefined) {
return '[]'
} else {
return tools.getstrDate(val)
}
} else if (this.col.fieldtype === tools.FieldType.boolean) {
return (val) ? this.$t('dialog.yes') : this.$t('dialog.no')
} else if (this.col.fieldtype === tools.FieldType.binary) {
if (val === undefined)
return '[---]'
else
return fieldsTable.getArrStrByValueBinary(this, this.col, val)
} else if (this.col.fieldtype === tools.FieldType.select) {
if (val === undefined)
return '[---]'
else
return fieldsTable.getValueByTable(this.col, val)
} else if (this.col.fieldtype === tools.FieldType.multiselect) {
if (val === undefined)
return '[---]'
else
return fieldsTable.getMultiValueByTable(this.col, val)
} else if (this.col.fieldtype === tools.FieldType.multioption) {
if (val === undefined)
return '[---]'
else
return fieldsTable.getMultiValueByTable(this.col, val)
} else if (this.col.fieldtype === tools.FieldType.password) {
if (val === undefined)
return '[---]'
else
return '***************'
} else {
if (val === undefined)
return ' <span class="text-grey">(' + translate('reg.select') + ')</span> '
else if (val === '') {
return ' <span class="text-grey">(' + translate('reg.select') + ')</span> '
} else {
let mystr = tools.firstchars(val, 5000)
if (val) {
if (val.length > 5000)
mystr += '...'
} else {
return val
}
return mystr
}
}
}
get mycl() {
if (this.disable) {
return 'cldisable'
}
}
get myvalprinted() {
return this.visuValByType(this.myvalue)
}
public savefield(value, initialval) {
this.myvalue = value
this.setValDb(this.mykey, this.myvalue, this.type, this.serv, this.table, this.mysubkey, this.id)
}
public savefieldboolean(value) {
if (this.myvalue === undefined)
this.myvalue = 'true'
else
this.myvalue = value
this.setValDb(this.mykey, this.myvalue, this.type, this.serv, this.table, this.mysubkey, this.id)
}
public selectcountry({ name, iso2, dialCode }) {
// console.log(name, iso2, dialCode)
this.myvalue = iso2
this.countryname = name
}
public intcode_change(coderec) {
this.myvalue = '+' + coderec.dialCode
}
}

View File

@@ -24,7 +24,7 @@
<CDateTime <CDateTime
:label="col.label" :label="col.label"
class="cursor-pointer" class="cursor-pointer"
:value.sync="myvalue" v-model:value="myvalue"
:readonly="false" :readonly="false"
:dense="true" :dense="true"
:canEdit="canEdit" :canEdit="canEdit"
@@ -35,7 +35,7 @@
<CDateTime <CDateTime
:label="col.label" :label="col.label"
class="cursor-pointer" class="cursor-pointer"
:value.sync="myvalue" v-model:value="myvalue"
:readonly="false" :readonly="false"
:dense="true" :dense="true"
:canEdit="canEdit" :canEdit="canEdit"
@@ -107,7 +107,8 @@
</div> </div>
</div> </div>
<div v-else-if="type === tools.FieldType.boolean"> <div v-else-if="type === tools.FieldType.boolean">
<q-toggle dark color="green" v-model="myvalue" :label="col.title" <q-toggle
dark color="green" v-model="myvalue" :label="col.title"
@input="savefieldboolean"></q-toggle> @input="savefieldboolean"></q-toggle>
</div> </div>
<div v-else> <div v-else>
@@ -130,7 +131,8 @@
</div> </div>
</div> </div>
<div v-else-if="type === tools.FieldType.string"> <div v-else-if="type === tools.FieldType.string">
<q-input v-model="myvalue" <q-input
v-model="myvalue"
autogrow autogrow
@keyup.enter.stop @keyup.enter.stop
@@ -139,7 +141,8 @@
</q-input> </q-input>
</div> </div>
<div v-else-if="type === tools.FieldType.password"> <div v-else-if="type === tools.FieldType.password">
<q-input v-model="myvalue" <q-input
v-model="myvalue"
type="password" type="password"
@keyup.enter.stop @keyup.enter.stop
autofocus> autofocus>
@@ -147,34 +150,38 @@
</q-input> </q-input>
</div> </div>
<div v-else-if="type === tools.FieldType.number"> <div v-else-if="type === tools.FieldType.number">
<q-input v-model="myvalue" type="number" <q-input
v-model="myvalue" type="number"
autofocus> autofocus>
</q-input> </q-input>
</div> </div>
<div v-else-if="type === tools.FieldType.hours"> <div v-else-if="type === tools.FieldType.hours">
<CMySelect label="Ore" :value.sync="myvalue" <CMySelect
label="Ore" v-model:value="myvalue"
optval="_id" optlab="label" optval="_id" optlab="label"
:useinput="false" :useinput="false"
o :options="tools.SelectHours"> o :options="tools.SelectHours">
</CMySelect> </CMySelect>
</div> </div>
<div v-else-if="type === tools.FieldType.binary"> <div v-else-if="type === tools.FieldType.binary">
<CMyToggleList :label="col.title" <CMyToggleList
:label="col.title"
:options="db_fieldsTable.getTableJoinByName(col.jointable)" :options="db_fieldsTable.getTableJoinByName(col.jointable)"
:value.sync="myvalue" v-model:value="myvalue"
:optval="db_fieldsTable.getKeyByTable(col.jointable)" :optval="db_fieldsTable.getKeyByTable(col.jointable)"
:optlab="db_fieldsTable.getLabelByTable(col.jointable)"> :optlab="db_fieldsTable.getLabelByTable(col.jointable)">
</CMyToggleList> </CMyToggleList>
</div> </div>
<div v-else-if="type === tools.FieldType.html"> <div v-else-if="type === tools.FieldType.html">
<CMyEditor :value.sync="myvalue" :title="title" @keyup.enter.stop> <CMyEditor v-model:value="myvalue" :title="title" @keyup.enter.stop>
</CMyEditor> </CMyEditor>
</div> </div>
<div v-else-if="type === tools.FieldType.select"> <div v-else-if="type === tools.FieldType.select">
<CMySelect :label="col.title" <CMySelect
:value.sync="myvalue" :label="col.title"
v-model:value="myvalue"
:optval="db_fieldsTable.getKeyByTable(col.jointable)" :optval="db_fieldsTable.getKeyByTable(col.jointable)"
:optlab="db_fieldsTable.getLabelByTable(col.jointable)" :optlab="db_fieldsTable.getLabelByTable(col.jointable)"
:options="db_fieldsTable.getTableJoinByName(col.jointable)" :options="db_fieldsTable.getTableJoinByName(col.jointable)"
@@ -213,7 +220,8 @@
<div class="justify-center q-gutter-sm clgutter q-mt-sm"> <div class="justify-center q-gutter-sm clgutter q-mt-sm">
<vue-tel-input <vue-tel-input
@country-changed="intcode_change" @country-changed="intcode_change"
v-model="myvalue" :value="myvalue"
@input="onInput"
:disabledFetchingCountry="true" :disabledFetchingCountry="true"
:preferredCountries="tools.getprefCountries" :preferredCountries="tools.getprefCountries"
:placeholder="$t('reg.cell')" :placeholder="$t('reg.cell')"
@@ -228,9 +236,10 @@
</div> </div>
<div v-else-if="col.fieldtype === tools.FieldType.multiselect"> <div v-else-if="col.fieldtype === tools.FieldType.multiselect">
<CMyToggleList :label="col.title" <CMyToggleList
:label="col.title"
:options="db_fieldsTable.getTableJoinByName(col.jointable)" :options="db_fieldsTable.getTableJoinByName(col.jointable)"
:value.sync="myvalue" v-model:value="myvalue"
:optval="db_fieldsTable.getKeyByTable(col.jointable)" :optval="db_fieldsTable.getKeyByTable(col.jointable)"
:optlab="db_fieldsTable.getLabelByTable(col.jointable)" :optlab="db_fieldsTable.getLabelByTable(col.jointable)"
:isarray="true"> :isarray="true">

View File

@@ -0,0 +1,3 @@
.climg {
border-radius: 5px;
}

52
src/components/CMyImg/CMyImg.ts Executable file
View File

@@ -0,0 +1,52 @@
import { defineComponent, ref, onMounted } from 'vue'
import { tools } from '@store/Modules/tools'
export default defineComponent({
name: 'CMyImg',
props: {
src: {
type: String,
required: true,
},
alt: {
type: String,
required: true,
default: '',
},
width: {
type: String,
required: true,
default: '',
},
},
components: {},
setup(props) {
const mystyle = ref('')
function mounted() {
console.log('mounted')
console.log(props.src)
if (props.width)
mystyle.value = 'max-width: ' + props.width + 'px; '
else
mystyle.value = ''
}
function getalt() {
if (props.alt) {
return props.alt
} else {
return tools.getimgFullpathbysize(props.src)
}
}
onMounted(mounted)
return {
mystyle,
getalt,
}
}
})

View File

@@ -0,0 +1,12 @@
<template>
<div v-if="src" class="text-center">
<q-img :src="src" class="myimg" :style="mystyle" :alt="getalt">
</q-img>
</div>
</template>
<script lang="ts" src="./CMyImg.ts">
</script>
<style lang="scss" scoped>
@import './CMyImg.scss';
</style>

1
src/components/CMyImg/index.ts Executable file
View File

@@ -0,0 +1 @@
export {default as CMyImg} from './CMyImg.vue'

View File

View File

@@ -0,0 +1,37 @@
import { defineComponent, ref, onMounted } from 'vue'
import { IMyPage } from 'model'
import { useGlobalStore } from '@store/globalStore'
import { CImgText } from '@/components/CImgText'
import { CCard } from '@/components/CCard'
import { CMyPage } from '@/components/CMyPage'
import { CTitleBanner } from '@/components/CTitleBanner'
export default defineComponent({
name: 'CMyInnerPage',
props: {
path: {
type: String,
required: true,
},
},
components: { CImgText, CCard, CMyPage, CTitleBanner },
setup(props) {
// const heightimg
// const imgback
const rec = ref(<IMyPage | undefined>{})
const globalStore = useGlobalStore()
function mounted() {
// console.log('$route.path', $route.path)
rec.value = globalStore.getPage(props.path)
console.log(rec)
}
onMounted(mounted)
return {
rec,
}
},
})

View File

@@ -0,0 +1,22 @@
<template>
<div>
<div v-if="rec">
<!--<CMyPage :title="rec.title" :imgbackground="`statics/` + rec.imgback" :sizes="`max-height: ` + rec.heightimg + `px`">-->
<div class="q-ma-sm q-gutter-sm q-pa-xs">
<div v-if="rec.content" v-html="rec.content">
</div>
</div>
<!--</CMyPage>-->
</div>
<div v-else>
<slot></slot>
</div>
</div>
</template>
<script lang="ts" src="./CMyInnerPage.ts">
</script>
<style lang="scss" scoped>
@import 'CMyInnerPage.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CMyInnerPage} from './CMyInnerPage.vue'

View File

@@ -3,9 +3,8 @@ import {
} from 'vue' } from 'vue'
import { IMyPage } from '@src/model' import { IMyPage } from '@src/model'
import { useQuasar } from 'quasar'
import { useGlobalStore } from '@store/globalStore' import { useGlobalStore } from '@store/globalStore'
import { Footer } from '../Footer' import { Footer } from '@/components/Footer'
import { CImgTitle } from '../CImgTitle/index' import { CImgTitle } from '../CImgTitle/index'
import { CTitle } from '../CTitle/index' import { CTitle } from '../CTitle/index'
@@ -50,7 +49,6 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
const $q = useQuasar()
const rec = ref<IMyPage | null>(null) const rec = ref<IMyPage | null>(null)
const mypath = toRef(props, 'mypath') const mypath = toRef(props, 'mypath')

View File

View File

@@ -0,0 +1,338 @@
import { defineComponent, onMounted, ref, toRef } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { IColGridTable } from 'model'
import { CMyChipList } from '../CMyChipList'
import { CDate } from '../CDate'
import { CDateTime } from '../CDateTime'
import { CMyToggleList } from '../CMyToggleList'
import { CMySelect } from '../CMySelect'
import { CMyEditor } from '../CMyEditor'
import { CGallery } from '../CGallery'
import { tools } from '@store/Modules/tools'
import { costanti } from '@costanti'
import { fieldsTable } from '@store/Modules/fieldsTable'
export default defineComponent({
name: 'CMyPopupEdit',
props: {
row: {
type: Object,
required: true,
},
col: {
type: Object,
required: true,
},
canEdit: {
type: Boolean,
required: false,
default: false,
},
field: {
type: String,
required: false,
default: '',
},
subfield: {
type: String,
required: false,
default: '',
},
showall: {
type: Boolean,
required: false,
default: false,
},
view: {
type: String,
required: false,
default: 'row',
},
minuteinterval: {
type: String,
required: false,
default: '5',
},
disable: {
type: Boolean,
required: false,
default: false,
},
visulabel: {
type: Boolean,
required: false,
default: false,
},
},
components: { CMyChipList, CDateTime, CDate, CMyToggleList, CMySelect, CMyEditor, CGallery },
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
const myvalue = ref('')
const myvalueprec = ref('false')
const countryname = ref('')
const visueditor = ref(false)
const showeditor = ref(true)
const myrow = toRef(props, 'row')
function isviewfield() {
return props.view === 'field'
}
function changeval(newval: any) {
console.log('changeval update:row', newval)
emit('update:row', newval)
}
function getrealval(newval: any) {
if (props.col.fieldtype === costanti.FieldType.hours) {
newval = newval.value
}
}
function changevalRec(newval: any) {
console.log('row', props.row, 'col', props.col, 'newval', newval)
console.log('row[col.name]', props.row[props.col.name])
myrow.value[props.col.name] = newval
console.log('changevalRec update:row', newval)
emit('update:row', props.row)
}
function changevalRecHours(newval: any) {
if (props.col.fieldtype === costanti.FieldType.hours) {
newval = newval.value
}
changevalRec(newval)
myvalue.value = newval
}
function updatedata() {
mounted()
}
function mounted() {
// console.log('mounted')
if ((props.subfield !== '') && (props.subfield !== '')) {
if (props.row[props.field] === undefined) {
myrow.value[props.field] = {}
myvalue.value = ''
} else {
myvalue.value = myrow.value[props.field][props.subfield]
}
} else {
if (props.field !== '')
myvalue.value = myrow.value[props.field]
else {
// @ts-ignore
myvalue.value = myrow.value
}
}
myvalueprec.value = myvalue.value
// console.log('myvalueprec', myvalueprec)
}
function OpenEdit() {
// console.log('OpenEdit')
emit('show')
}
function getval() {
let myval: any = 'false'
if ((props.subfield !== '') && (props.subfield !== '')) {
if (myrow.value[props.field] === undefined) {
myrow.value[props.field] = {}
myval = ''
} else {
myval = myrow.value[props.field][props.subfield]
}
} else {
if (props.field !== '')
myval = myrow.value[props.field]
else
myval = myrow.value
}
return myval
}
function SaveValueInt(newVal: any, valinitial: any) {
// console.log('SaveValueInt', newVal, valinitial)
// Update value in table memory
if (props.subfield !== '') {
if (myrow.value[props.field] === undefined)
myrow.value[props.field] = {}
myrow.value[props.field][props.subfield] = newVal
} else {
if (props.field !== '')
myrow.value[props.field] = newVal
else
myrow.value = newVal
}
emit('save', newVal, valinitial)
}
function annulla(val: any) {
emit('annulla', true)
}
function Savedb(newVal: any, valinitial: any) {
if (props.col.fieldtype === costanti.FieldType.boolean) {
// console.log('myvalue', myvalue, newVal, myvalueprec)
if (myvalueprec.value === undefined) {
newVal = true
myvalueprec.value = myvalue.value
myvalue.value = newVal
}
// console.log('DOPO myvalue', myvalue, newVal, myvalueprec)
}
// console.log('Savedb', newVal)
emit('showandsave', props.row, props.col, newVal, valinitial)
visueditor.value = false
}
function visuValByType(val: any, col: IColGridTable, row: any) {
if (col === undefined || row === undefined)
return
// let val = ''
// if (props.col.subfield !== '') {
// if (row[props.col.field] === undefined)
// row[props.col.field] = {}
//
// val = row[props.col.field][props.col.subfield]
// } else {
// val = row[props.col.field]
// }
//
if (props.col.fieldtype === costanti.FieldType.date) {
if (val === undefined) {
return '[]'
} else {
return tools.getstrDateTime(val)
}
} else if (props.col.fieldtype === costanti.FieldType.onlydate) {
if (val === undefined) {
return '[]'
} else {
return tools.getstrDate(val)
}
} else if (props.col.fieldtype === costanti.FieldType.boolean) {
return (val) ? t('dialog.yes') : t('dialog.no')
} else if (props.col.fieldtype === costanti.FieldType.binary) {
if (val === undefined)
return '[---]'
else
return globalStore.getArrStrByValueBinary(col, val)
} else if (props.col.fieldtype === costanti.FieldType.select) {
if (val === undefined)
return '[---]'
else
return globalStore.getValueByTable(col, val)
} else if (props.col.fieldtype === costanti.FieldType.multiselect) {
if (val === undefined)
return '[---]'
else
return globalStore.getMultiValueByTable(col, val)
} else {
if (val === undefined || val === null)
return '[]'
else if (val === '') {
return '[]'
} else {
let mystr = ''
if (props.showall) {
return val
} else {
mystr = tools.firstchars(val, tools.MAX_CHARACTERS)
}
if (val) {
if (val.length > tools.MAX_CHARACTERS)
mystr += '...'
} else {
return val
}
return mystr
}
}
}
function visInNewRec(col: any) {
return !props.col.notShowInNewRec
}
function getclassCol(col: any) {
if (col) {
let mycl = (props.col.disable || isviewfield) ? '' : 'colmodif'
mycl += ((props.col.fieldtype === costanti.FieldType.date) || (props.col.fieldtype === costanti.FieldType.onlydate)) ? ' coldate flex flex-container' : ''
return mycl
} else {
return ''
}
}
function selectcountry({ name, iso2, dialCode }: { name: string, iso2: string, dialCode: string}) {
// console.log(name, iso2, dialCode)
myvalueprec.value = myvalue.value
myvalue.value = iso2
countryname.value = name
}
function intcode_change(coderec: any) {
myvalueprec.value = myvalue.value
myvalue.value = '+' + coderec.dialCode
}
function onInput(phone: any, phoneObject: any, input: any) {
if (phoneObject?.formatted) {
myvalue.value = phoneObject.formatted
}
}
onMounted(mounted)
return {
myvalue,
countryname,
visueditor,
showeditor,
isviewfield,
changeval,
changevalRec,
changevalRecHours,
updatedata,
OpenEdit,
getval,
SaveValueInt,
annulla,
Savedb,
visuValByType,
visInNewRec,
getclassCol,
selectcountry,
intcode_change,
tools,
fieldsTable,
onInput,
}
}
})

View File

@@ -0,0 +1,398 @@
<template>
<div :class="getclassCol(col)">
<div v-if="visulabel" class="flex">
<div v-if="visInNewRec(col)" style="flex-grow: 1;">
<div v-if="col.fieldtype === tools.FieldType.string">
<q-input
v-model="myvalue"
autogrow
@keyup.enter.stop
@input="changevalRec"
autofocus
:label="col.label">
</q-input>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.date">
<CDateTime
:label="col.label"
class="cursor-pointer"
:valueDate="myvalue"
:readonly="false"
:minuteinterval="minuteinterval"
:dense="true"
@input="changevalRec"
canEdit="true"
@savetoclose="SaveValueInt"
@show="OpenEdit">
</CDateTime>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.onlydate">
<CDateTime
:label="col.label"
class="cursor-pointer"
:valueDate="myvalue"
:readonly="false"
:minuteinterval="minuteinterval"
:dense="true"
@input="changevalRec"
canEdit="true"
@savetoclose="SaveValueInt"
@show="OpenEdit"
view="date">
</CDateTime>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.number">
<q-input
v-model="myvalue" type="number"
autofocus
@input="changevalRec"
:label="col.label"
>
</q-input>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.hours">
<div class="row">
<q-input
v-model="myvalue" type="number"
autofocus
@input="changevalRec"
style="max-width: 100px;"
:label="col.label"
>
</q-input>
<CMySelect
label="Ore" v-model:value="myvalue"
optval="value" optlab="label"
:dense="false"
:use-input="false"
@changeval="changevalRecHours"
style="max-width: 100px;"
:options="tools.SelectHours">
</CMySelect>
</div>
<!--<q-input v-model="myvalue" type="number"
autofocus
@input="changevalRec"
:label="col.label">
</q-input>
-->
</div>
<div v-else-if="col.fieldtype === tools.FieldType.listimages">
<CGallery
:gall="row" :listimages="myvalue" :edit="isviewfield"
@showandsave="Savedb"
@input="changevalRec"
>
</CGallery>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.image">
<CGallery
:gall="row" :listimages="myvalue" :edit="isviewfield"
@input="changevalRec"
@showandsave="Savedb">
</CGallery>
</div>
<div v-if="col.fieldtype === tools.FieldType.binary">
<CMyChipList
:type="tools.FieldType.binary"
:value="myvalue"
@input="changevalRec"
:options="fieldsTable.getTableJoinByName(col.jointable)"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)"
:opticon="fieldsTable.getIconByTable(col.jointable)"></CMyChipList>
</div>
<!-- Show Value -->
<div v-else-if="col.fieldtype === tools.FieldType.multiselect">
<CMyChipList
@input="changevalRec"
:type="tools.FieldType.multiselect"
:value="myvalue"
:options="fieldsTable.getTableJoinByName(col.jointable)"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)"
:opticon="fieldsTable.getIconByTable(col.jointable)"></CMyChipList>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.select">
<CMyChipList
@input="changevalRec"
myclass="text-center"
:type="tools.FieldType.select"
:value="myvalue"
:options="fieldsTable.getTableJoinByName(col.jointable)"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)"
:opticon="fieldsTable.getIconByTable(col.jointable)"></CMyChipList>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.boolean">
<q-toggle
dark color="green" v-model="myvalue" :label="col.title"
:disable="disable && col.name !== 'profile.saw_zoom_presentation'"
@input="changevalRec"></q-toggle>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.html">
<div v-html="visuValByType(myvalue, col, row)" @click="visueditor = true">
</div>
</div>
</div>
</div>
<div v-else>
<div v-if="col.fieldtype === tools.FieldType.listimages">
<CGallery
:gall="row" :listimages="myvalue" :edit="isviewfield"
@showandsave="Savedb">
</CGallery>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.image">
<CGallery
:gall="row" :listimages="myvalue" :edit="isviewfield"
@showandsave="Savedb">
</CGallery>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.nationality">
<div>
{{ myvalue }}
</div>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.intcode">
<div>
{{ myvalue }}
</div>
</div>
<div v-else>
<!-- Edit Value -->
<span v-if="col.fieldtype === tools.FieldType.date">
<CDateTime
:label="col.label"
class="cursor-pointer"
:valueDate="myvalue"
:readonly="false"
:minuteinterval="minuteinterval"
:dense="true"
:canEdit="canEdit"
@savetoclose="SaveValueInt"
@show="OpenEdit">
</CDateTime>
</span>
<span v-else-if="col.fieldtype === tools.FieldType.onlydate">
<CDateTime
:label="col.label"
class="cursor-pointer"
:valueDate="myvalue"
:readonly="false"
:minuteinterval="minuteinterval"
:dense="true"
:canEdit="canEdit"
@savetoclose="SaveValueInt"
@show="OpenEdit"
view="date">
</CDateTime>
</span>
<div v-else>
<div>
<div v-if="col.fieldtype === tools.FieldType.binary">
<CMyChipList
:type="tools.FieldType.binary"
:value="myvalue"
:options="fieldsTable.getTableJoinByName(col.jointable)"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)"
:opticon="fieldsTable.getIconByTable(col.jointable)"></CMyChipList>
</div>
<!-- Show Value -->
<div v-else-if="col.fieldtype === tools.FieldType.multiselect">
<CMyChipList
:type="tools.FieldType.multiselect"
:value="myvalue"
:options="fieldsTable.getTableJoinByName(col.jointable)"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)"
:opticon="fieldsTable.getIconByTable(col.jointable)"></CMyChipList>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.select">
<CMyChipList
myclass="text-center"
:type="tools.FieldType.select"
:value="myvalue"
:options="fieldsTable.getTableJoinByName(col.jointable)"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)"
:opticon="fieldsTable.getIconByTable(col.jointable)"></CMyChipList>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.boolean">
<q-toggle
dark color="green" v-model="myvalue" :label="col.title"
:disable="disable && col.name !== 'profile.saw_zoom_presentation'"
@input="Savedb"></q-toggle>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.html">
<div v-html="visuValByType(myvalue, col, row)" @click="visueditor = true">
</div>
</div>
<div v-else>
{{ visuValByType(myvalue, col, row) }}
</div>
<div v-if="col.fieldtype === tools.FieldType.html">
<!--<q-dialog v-model="showeditor">-->
<CMyEditor
v-if="visueditor" v-model:value="myvalue" :title="col.title" @keyup.enter.stop
@showandsave="Savedb" @annulla="visueditor=false">
</CMyEditor>
<!--</q-dialog>-->
</div>
<q-popup-edit
v-if="canEdit && col.fieldtype !== tools.FieldType.html"
v-model="myvalue"
:disable="col.disable"
:title="col.title"
buttons
persistent
@save="SaveValueInt"
@show="OpenEdit">
<div v-if="col.fieldtype === tools.FieldType.boolean">
<q-checkbox v-model="myvalue" :label="col.title">
</q-checkbox>
{{ visuValByType(myvalue, col, row) }}
</div>
<div v-else-if="col.fieldtype === tools.FieldType.string">
<q-input
v-model="myvalue"
autogrow
@keyup.enter.stop
autofocus>
</q-input>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.password">
<q-input
v-model="myvalue"
type="password"
@keyup.enter.stop
autofocus>
</q-input>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.number">
<q-input
v-model="myvalue" type="number"
autofocus>
</q-input>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.hours">
<q-input
v-model="myvalue" type="number"
autofocus>
</q-input>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.binary">
<CMyToggleList
:label="col.title"
:options="fieldsTable.getTableJoinByName(col.jointable)"
v-model:value="myvalue"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)">
</CMyToggleList>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.select">
<CMySelect
:label="col.title"
v-model:value="myvalue"
:optval="fieldsTable.getKeyByTable(col.jointable)"
:optlab="fieldsTable.getLabelByTable(col.jointable)"
:options="fieldsTable.getTableJoinByName(col.jointable)"
:useinput="false">
</CMySelect>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.nationality">
<div class="justify-center q-gutter-sm clgutter q-mt-sm">
<q-input
v-model="countryname"
:readonly="true"
rounded dense
debounce="1000"
>
<template v-slot:prepend>
<div style="font-size: 1rem;">
<vue-country-code
:defaultCountry="myvalue"
:disabledFetchingCountry="true"
@onSelect="selectcountry"
:preferredCountries="tools.getprefCountries"
:dropdownOptions="{ disabledDialCode: true }">
</vue-country-code>
</div>
</template>
</q-input>
<div style="height: 180px;">
</div>
</div>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.intcode">
<vue-tel-input
@country-changed="intcode_change"
:value="myvalue"
@input="oninput"
:placeholder="$t('reg.cell')"
:enabledCountryCode="true"
inputClasses="clCell"
wrapperClasses="clCellCode">
</vue-tel-input>
</div>
<div v-else-if="col.fieldtype === tools.FieldType.multiselect">
<div>join: {{ col.jointable }}</div>
<q-select
v-model="myvalue"
rounded
outlined
multiple
dense
options-dense
:display-value="fieldsTable.getTitleByTable(col.jointable)"
emit-value
map-options
:options="fieldsTable.getTableJoinByName(col.jointable)"
:option-label="fieldsTable.getLabelByTable(col.jointable)"
:option-value="fieldsTable.getKeyByTable(col.jointable)"
style="min-width: 150px"
@input="changeCol">
</q-select>
</div>
</q-popup-edit>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" src="./CMyPopupEdit.ts">
</script>
<style lang="scss" scoped>
@import './CMyPopupEdit.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CMyPopupEdit} from './CMyPopupEdit.vue'

View File

@@ -0,0 +1,4 @@
.myflex{
display: flex;
flex: 1;
}

View File

@@ -0,0 +1,100 @@
import { defineComponent, onMounted, ref } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
export default defineComponent({
name: 'CMySelect',
props: {
options: {
type: Array,
required: true,
},
value: [String, Number, Array],
type: {
type: Number,
required: true,
},
label: {
type: String,
required: true,
},
myclass: {
type: String,
required: false,
default: ''
},
optlab: {
type: String,
required: true,
},
optval: {
type: String,
required: true,
},
useinput: {
type: Boolean,
required: false,
default: true
},
dense: {
type: Boolean,
required: false,
default: true
},
multiple: {
type: Boolean,
required: false,
default: false
},
newvaluefunc: {
type: Function,
required: true,
},
funcgetvaluebyid: {
type: Function,
required: true,
},
},
components: {},
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
const myvalue = ref('')
function changeval(newval: any) {
console.log('changeval', newval)
emit('update:value', newval)
emit('changeval', newval)
}
function mounted() {
const rec: any = props.options.find((myrec: any) => myrec[`${props.optval}`] === props.value)
// console.log('rec', rec)
if (!props.useinput) {
myvalue.value = props.value!.toString()
} else {
if (rec) {
if (props.funcgetvaluebyid)
myvalue.value = props.funcgetvaluebyid(rec[`${props.optval}`])
else
myvalue.value = rec[`${props.optlab}`]
// console.log('myvalue', myvalue, 'optval', optval, 'rec', rec[`${optval}`])
}
}
}
onMounted(mounted)
return {
changeval,
myvalue,
}
}
})

View File

@@ -0,0 +1,51 @@
<template>
<div class="text-center">
<div v-if="useinput">
<q-select
:multiple="multiple"
rounded
outlined
:input-class="myclass"
v-model="myvalue"
:use-input="useinput"
input-debounce="0"
@new-value="newvaluefunc"
new-value-mode="add-unique"
:options="options"
:option-value="optval"
:option-label="optlab"
@input="changeval"
:label="label"
:dense="dense"
>
</q-select>
</div>
<div v-else>
<q-select
:multiple="multiple"
rounded
outlined
:dense="dense"
:input-class="myclass"
v-model="myvalue"
:options="options"
:option-value="optval"
:option-label="optlab"
@input="changeval"
:label="label"
emit-value
map-options
style="min-width: 170px; max-width: 400px;"
>
</q-select>
</div>
</div>
</template>
<script lang="ts" src="./CMySelect.ts">
</script>
<style lang="scss" scoped>
@import './CMySelect.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CMySelect} from './CMySelect.vue'

View File

@@ -0,0 +1,171 @@
$graytext: #555;
.listaev {
color: black;
font-size: 0.75rem;
font-weight: 400;
line-height: 1.25rem;
letter-spacing: 0.03333em;
&__date {
color: #061220;
font-size: 1rem;
}
&__title {
color: red;
font-weight: 700;
letter-spacing: 0.066em;
}
&__details {
color: black;
}
&__tdimg {
width: 150px;
height: 150px;
}
&__tdimg_small {
width: auto;
height: 50px !important;
@media (max-width: 800px) {
height: 40px !important;
}
}
&__table {
margin: 10px;
border: solid 1px #4198ef;
border-radius: 1rem;
padding: 2px;
}
&__table tr {
border: solid 1px #4198ef;
border-radius: 1rem;
}
&__align_center_mobile {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
&__align_chips {
text-align: center;
display: flex;
flex-direction: column-reverse;
align-items: center;
}
&__singleevimg {
padding: 0.25rem !important;
float: left;
width: 250px;
height: 250px;
border-radius: 1rem;
@media (max-width: 718px) {
// PER VERSIONE MOBILE
float: none;
text-align: center;
margin: 0 auto;
width: 200px;
height: 200px;
}
}
&__img:hover {
transition: transform .2s;
transform: scale(1.05);
border: inset;
border-color: blue;
border-width: 1px;
}
}
.cal {
color: black;
font-size: 0.75rem;
font-weight: 400;
line-height: 1.25rem;
letter-spacing: 0.03333em;
&__title {
color: white;
font-weight: 700;
font-size: 1rem;
padding-bottom: 10px;
}
&__details {
color: black;
}
&__hours {
color: blue;
&-title {
color: $graytext;
}
&-content {
font-weight: 400;
}
}
&__where {
margin-top: 5px;
color: blue;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__when {
margin-top: 5px;
color: blue;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__teacher {
margin-top: 5px;
&-title {
color: $graytext;
}
&-content {
color: darkblue;
}
}
&__quota {
margin-top: 5px;
&-title {
color: $graytext;
}
&-content {
}
}
&__img {
width: 100px;
height: 100px;
padding: 10px;
}
}

View File

@@ -0,0 +1,85 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { CalendarStore, GlobalStore, UserStore } from '@store'
import { Logo } from '../../components/logo/index'
import { Footer } from '../../components/Footer/index'
import { tools } from '../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { static_data } from '@src/db/static_data'
import { Screen } from 'quasar'
import { CImgText } from '../../components/CImgText/index'
import { CCard, CMyAvatar, CMyTeacher, CMyPage } from '@components'
import MixinOperator from '@src/mixins/mixin-operator'
import MixinEvents from '../../mixins/mixin-events'
import { IEvents } from '@src/model'
import MixinBase from '@src/mixins/mixin-base'
import MixinUsers from '@src/mixins/mixin-users'
@Component({
name: 'CMySingleEvent',
mixins: [MixinOperator, MixinBase, MixinEvents, MixinUsers],
components: { Logo, Footer, CImgText, CCard, CMyPage, CMyAvatar, CMyTeacher }
})
export default class CMySingleEvent extends MixinEvents {
@Prop({ required: true }) public myevent: IEvents
public $q
public $t
public selected: boolean = false
get mythis() {
return this
}
set mythis(aa) {
}
public selectEvent(eventparam: IEvents) {
this.selected = !this.selected
}
public getTextEvent(myevent: IEvents) {
if (myevent.bodytext === '') {
return myevent.details
} else {
return myevent.bodytext
}
}
public mounted() {
// console.log('MYSINGLEEVENT: myevent', this.myevent)
}
get static_data() {
return static_data
}
public duplicateEvent(event, numgg) {
this.$emit('duplicateEvent', event, numgg)
}
public askForInfoEventMenu(event) {
this.$emit('askForInfoEventMenu', event)
}
public deleteEvent(event) {
this.$emit('deleteEvent', event)
}
public editEvent(event) {
this.$emit('editEvent', event)
}
public addBookEventMenu(event) {
this.$emit('addBookEventMenu', event)
}
public EditBookEvent(event) {
this.$emit('EditBookEvent', event)
}
}

View File

@@ -0,0 +1,203 @@
<template>
<div>
<CMyPage
v-if="myevent" :imgbackground="myevent.img" :title="myevent.title" keywords="" description=""
nofooter="true">
<div class="q-mx-md">
<div class="listaev__align_chips q-ma-md">
<img
:src="getImgEvent(myevent)"
@click="selectEvent(myevent)"
class="text-left padding_cell listaev__tdimg listaev__singleevimg cursor-pointer"
:style="getStyleByEvent(myevent, true)"
:alt="myevent.title">
<q-chip
dense v-if="isAlreadyBooked(myevent)" class="cltexth4 chipbooked shadow-5 q-mb-md"
color="green" text-color="white"
icon="event_available">{{ $t('cal.booked') }}
</q-chip>
<div v-if="selected">
<q-chip v-if="editable" class="text-center shadow-5 glossy bg-blue chipmodif">
<q-btn v-if="editable" flat round color="white" icon="fas fa-copy">
<q-menu
transition-show="flip-right"
transition-hide="flip-left">
<q-list style="min-width: 100px">
<q-item clickable @click="duplicateEvent(myevent, 7)">
<q-item-section>Tra 1 Settimana</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 14)">
<q-item-section>Tra 2 Settimane</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 7, 4)">
<q-item-section>4 Eventi ogni Settimana</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
<q-btn
v-if="editable" flat round color="white" icon="delete" v-close-popup
@click="deleteEvent(myevent)"></q-btn>
<q-btn
v-if="editable" flat round color="white" icon="edit" v-close-popup
@click="editEvent(myevent)"></q-btn>
<q-btn
v-if="editable" flat round color="white" icon="cancel"
@click="selectEvent(null)"></q-btn>
</q-chip>
</div>
<q-chip
v-if="myevent.news" class="cltexth4 chipnews shadow-5 glossy text-right" color="red"
text-color="white" icon-right="star" icon="star" dense
style="">
{{ $t('event.news') }}
</q-chip>
</div>
<div class="listaev__date listaev__align_center_mobile">
<span v-html="tools.getstrDateTimeEvent(mythis, myevent, true)"></span>
</div>
<div class="listaev__align_center_mobile">
<div style="margin: 10px;"></div>
<div class="q-pa-sm q-gutter-md text-center">
<!-- Se c'è un link, allora -->
<q-btn
class="text-center boldhigh" v-if="myevent.linkpdf" size="md" type="a"
:href="`../../statics/` + myevent.linkpdf"
target="_blank"
ripple rounded :label="myevent.title"
:color="myevent.bgcolor" text-color="white" glossy>
</q-btn>
<!-- altrimenti mostra solo Chip -->
<div
v-else-if="tools.isMobile()" class="cltexth3 text-center boldhigh"
:style="`background-color: ${myevent.bgcolor} !important; color: white !important;`">
{{ myevent.title }}
</div>
<q-chip
v-else class="cltexth3 text-center boldhigh"
icon="bookmark"
:style="`background-color: ${myevent.bgcolor} !important; color: white !important;`"
text-color="white"
dense>{{ myevent.title }}
</q-chip>
</div>
<div style="margin: 10px;"></div>
<p v-if="myevent.bodytext" class="listaev__details text-left q-mb-md" v-html="myevent.bodytext"></p>
<p v-else class="listaev__details" v-html="myevent.details"></p>
<div v-for="(mypage, index) in myevent.pagefooter" :key="index">
<CMyPage v-if="!!mypage" :mypath="`/`+ mypage">
</CMyPage>
</div>
<div v-if="myevent.teacher" class="">
<span class="cal__teacher-title">{{ $t('cal.teacher') }}: <span
class="margin_with"></span></span>
<CMyTeacher :username="myevent.teacher"></CMyTeacher>
<CMyTeacher :username="myevent.teacher2"></CMyTeacher>
<CMyTeacher :username="myevent.teacher3"></CMyTeacher>
<CMyTeacher :username="myevent.teacher4"></CMyTeacher>
<span v-if="myevent.wherecode" class="q-ma-md">
<span v-if="tools.isMobile()"><br/></span>
<span class="cal__where-title">{{ $t('cal.where') }}: </span>
<q-chip>
<q-avatar v-if="getWhereIcon(myevent.wherecode)">
<img
:src="`../../statics/images/avatar/` + getWhereIcon(myevent.wherecode)"
alt="località">
</q-avatar>
<q-avatar
v-else color="blue" font-size="20px" text-color="white"
icon="home">
</q-avatar>
<span
class="cal__teacher-content">{{ getWhereName(myevent.wherecode) }}</span>
</q-chip>
</span>
</div>
<div v-if="myevent.contribtype" class="q-ma-sm">
<span class="cal__quota-title">{{ $t('event.price') }}:<span
class="margin_with"></span></span>
<span v-if="!isShowPrice(myevent)" class="">
<q-chip class="glossy" color="orange" text-color="white">
<span
class="cal__quota-content">{{
getContribtypeById(myevent.contribtype)
}}</span>
</q-chip>
</span>
<q-chip
v-if="myevent.price && isShowPrice(myevent)" class="glossy" color="orange"
text-color="white" icon-right="star">
<span class="cal__quota-content">{{ getPrice(myevent) }}</span>
</q-chip>
</div>
<div class="row justify-start q-ma-md">
<q-btn
v-if="myevent.linkpdf"
size="md" type="a" :href="`../../statics/` + myevent.linkpdf"
target="_blank" rounded outline
color="primary" icon="info"
:label="$t('cal.showpdf')">
</q-btn>
<!--<q-btn v-if="myevent.bodytext" rounded outline class="q-mx-sm"
color="primary"
:to="`/event/${myevent.typol}/${myevent._id}`"
:label="$t('event.showpage')">
</q-btn>-->
</div>
<div class="row text-center">
<q-btn
rounded outline class="q-mx-sm"
color="primary" @click="askForInfoEventMenu(myevent)"
:label="$t('event.askinfo')">
</q-btn>
<q-btn
rounded class="q-mx-sm"
v-if="!myevent.nobookable && !isAlreadyBooked(myevent) && static_data.functionality.BOOKING_EVENTS"
color="primary" @click="addBookEventMenu(myevent)"
:label="$t('cal.booking')" :disable="!isEventEnabled(myevent)">
</q-btn>
<q-btn
rounded outline class="q-mx-sm"
v-if="!myevent.nobookable && isAlreadyBooked(myevent) && static_data.functionality.BOOKING_EVENTS"
text-color="red"
@click="EditBookEvent(myevent)"
:label="$t('cal.modifybooking')">
</q-btn>
<br>
<!--
<q-btn push rounded v-if="!myevent.nobookable && isAlreadyBooked(myevent)" color="positive" @click="BookEvent(myevent)"
:label="$t('cal.booked')">
</q-btn>
-->
</div>
</div>
</div>
</CMyPage>
</div>
</template>
<script lang="ts" src="./CMySingleEvent.ts">
</script>
<style lang="scss" scoped>
@import './CMySingleEvent.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CMySingleEvent} from './CMySingleEvent.vue'

View File

@@ -10,7 +10,7 @@
</q-toolbar> </q-toolbar>
<q-card-section class="text-center inset-shadow"> <q-card-section class="text-center inset-shadow">
<div style="width: 200px; float: left;"> <div style="width: 200px; float: left;">
<q-img :src="`statics/images/` + myop.img" class="myimg" :alt="`${myop.name} ${myop.surname}`"> <q-img :src="`public/images/` + myop.img" class="myimg" :alt="`${myop.name} ${myop.surname}`">
</q-img> </q-img>
</div> </div>

View File

@@ -0,0 +1,5 @@
.cltoggle{
display: flex;
flex: 1;
flex-direction: column;
}

View File

@@ -0,0 +1,119 @@
import { defineComponent, onMounted, ref } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { tools } from '@store/Modules/tools'
export default defineComponent({
name: 'CMyToggleList',
props: {
options: {
type: Array,
required: true,
},
value: [String, Number, Array],
label: {
type: String,
required: true,
},
myclass: {
type: String,
required: false,
default: ''
},
optlab: {
type: String,
required: true,
},
optval: {
type: String,
required: true,
},
isarray: {
type: Boolean,
required: false,
default: false,
},
},
components: {},
setup(props, { emit }) {
const { t } = useI18n()
const myvalue = ref('')
const myarrvalues = ref(<any>[])
function changeval(newval: any) {
// Update value
let totale: any = null
if (props.isarray) {
totale = myarrvalues.value.filter((rec: any) => rec.valbool).map((a: any) => a.value)
} else {
totale = myarrvalues.value.filter((rec: any) => rec.valbool).reduce((sum: number, rec: any) => sum + rec.value, 0)
}
console.log('totale', totale)
myvalue.value = totale
// Refresh value
emit('update:value', myvalue.value)
}
function mounted() {
console.log('mounted')
myarrvalues.value = []
// console.log('value', value)
// console.log('optval', optval)
// console.log('optlab', optlab)
if (props.isarray) {
// console.table(options)
props.options.forEach((rec: any) => {
console.log('rec: ', rec, 'optval', props.optval, 'optlab', props.optlab)
const mydata = {
label: '',
value: rec[props.optval],
valbool: false
}
const lab = rec[`${props.optlab}`]
console.log('lab', lab)
if (tools.isObject(props.optlab)) {
// @ts-ignore
const arr = props.options.filter((myrec: any) => myrec[props.optval] === mydata.value).map(props.optlab)
if (arr) {
// @ts-ignore
mydata.label = arr[0]
}
} else {
mydata.label = t(rec[props.optlab])
}
if (props.value) {
// @ts-ignore
mydata.valbool = props.value.includes(rec[props.optval])
}
console.log('mydata ', mydata)
myarrvalues.value.push(mydata)
})
} else {
// console.table(options)
props.options.forEach((rec: any) => {
const mydata: any = {
label: t(rec[props.optlab]),
value: rec[props.optval],
valbool: tools.isBitActive(props.value, rec[props.optval])
}
myarrvalues.value.push(mydata)
})
}
}
onMounted(mounted)
return {
tools,
myarrvalues,
changeval,
}
}
})

View File

@@ -0,0 +1,20 @@
<template>
<div>
<div class="cltoggle" v-for="(rec, index) in myarrvalues" :key="index">
<q-toggle
v-model="rec.valbool"
:label="rec.label"
:color="tools.getColorByIndexBest(index)"
keep-color
@input="changeval">
</q-toggle>
</div>
</div>
</template>
<script lang="ts" src="./CMyToggleList.ts">
</script>
<style lang="scss" scoped>
@import './CMyToggleList.scss';
</style>

Some files were not shown because too many files have changed in this diff Show More