Merge pull request #20 from paoloar77/FunzProjects

Funz projects
This commit is contained in:
Paolo Arena
2019-04-07 21:28:00 +02:00
committed by GitHub
136 changed files with 6485 additions and 16675 deletions

34
.babelrc Normal file
View File

@@ -0,0 +1,34 @@
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"loose": false
}
]
],
"plugins": [
[
"@babel/transform-runtime",
{
"regenerator": false
}
],
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings",
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions"
],
"comments": false
}

View File

@@ -0,0 +1,115 @@
const path = require('path');
const helpers = require('./helpers');
const webpack = require('webpack')
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const autoprefixer = require('autoprefixer');
const cssNext = require('postcss-cssnext');
const postcssImport = require('postcss-import');
const baseConfig = {
entry: {
'bundle': helpers.root('/src/main.ts'),
},
output: {
filename: '[nametranslate].js',
publicPath: '/',
path: helpers.root('dist'),
},
resolve: {
extensions: [
'.ts', '.js', '.vue',
],
alias: {
'@components': helpers.root('src/components/index.ts'),
'@components': helpers.root('src/components'),
'@views': helpers.root('src/views/index.ts'),
'@views': helpers.root('src/views'),
'@src': helpers.root('src'),
'@icons': helpers.root('src/assets/icons'),
'@images': helpers.root('src/assets/images'),
'@classes': helpers.root('src/classes/index.ts'),
'@fonts': helpers.root('src/assets/fonts'),
'@utils': helpers.root('src/utils/index.ts'),
'@utils': helpers.root('src/utils'),
'@css': helpers.root('src/styles/variables.scss'),
'@router': helpers.root('src/router/index.ts'),
'@validators': helpers.root('src/utils/validators.ts'),
'@methods': helpers.root('src/utils/methods.ts'),
'@filters': helpers.root('src/utils/filters.ts'),
'@api': helpers.root('src/store/Api/index.ts'),
'@paths': helpers.root('src/store/Api/ApiRoutes.ts'),
'@types': helpers.root('src/typings/index.ts'),
'@store': helpers.root('src/store/index.ts'),
'@modules': helpers.root('src/store/Modules/index.ts'),
}
},
module: {
rules: [{
test: /\.vue$/,
use: {
loader: 'vue-loader',
options: {
postcss: {
plugins: [cssNext()],
options: {
sourceMap: true,
}
},
cssSourceMap: true,
loaders: {
scss: ['vue-style-loader', 'css-loader','sass-loader', {
loader: 'sass-resources-loader',
options: {
resources: helpers.root('src/styles/variables.scss'),
esModule: true,
}
}],
ts: 'ts-loader',
}
},
}
}, {
test: /\.ts$/,
exclude: /node_modules/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/]
}
}, {
test: /\.(jpe?g|png|ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/,
use: 'base64-inline-loader?limit=1000&nametranslate=[nametranslate].[ext]'
},{
test: /\.(svg)(\?[a-z0-9=&.]+)?$/,
use: 'base64-inline-loader?limit=4000&nametranslate=[nametranslate].[ext]'
}
]
},
plugins: [
new FaviconsWebpackPlugin({
logo: helpers.root('src/assets/images/logo_M.png'),
persistentCache: true,
inject: true,
background: '#fff',
icons: {
android: false,
appleIcon: false,
appleStartup: false,
coast: false,
favicons: true,
firefox: false,
opengraph: false,
twitter: false,
yandex: false,
windows: false
}
}),
new CopyWebpackPlugin([{
from: helpers.root('src/assets')
}])
],
};
module.exports = baseConfig;

View File

@@ -0,0 +1,90 @@
const webpackBaseConfig = require('./webpack.config.base');
const env = require('../environment/dev.env');
const webpack = require('webpack')
const path = require('path');
const helpers = require('./helpers');
const merge = require('webpack-merge')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const webpackDashboard = require('webpack-dashboard/plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const autoprefixer = require('autoprefixer');
const webpackDevConfig = {
module: {
rules: [{
test: /\.s?css$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: true,
importLoaders: 2
}
}, {
loader: 'postcss-loader',
options: {
plugins: () => [autoprefixer],
sourceMap: true
}
}, {
loader: 'sass-loader',
options: {
outputStyle: 'expanded',
sourceMap: true,
sourceMapContents: true
}
}],
}]
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: helpers.root('/src/index.html'),
filename: 'index.html',
favicon: helpers.root('/src/assets/images/logo_M.png')
}),
new DefinePlugin({
'process.env': env
}),
new webpackDashboard(),
new FriendlyErrorsPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
],
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 5000,
historyApiFallback: true,
disableHostCheck: true,
host: "0.0.0.0",
hot: true,
open: true,
quiet: true,
inline: true,
noInfo: true,
stats: {
colors: true,
hash: false,
version: false,
timings: false,
assets: false,
chunks: false,
modules: false,
reasons: false,
children: false,
source: false,
errors: true,
errorDetails: true,
warnings: false,
publicPath: false
}
},
devtool: 'cheap-module-eval-source-map'
}
const devExport = merge(webpackBaseConfig, webpackDevConfig);
module.exports = devExport;

67
package.json Normal file → Executable file
View File

@@ -1,6 +1,6 @@
{ {
"name": "freeplanet", "name": "freeplanet",
"version": "0.0.4", "version": "0.0.5",
"private": true, "private": true,
"keywords": [ "keywords": [
"freeplanet", "freeplanet",
@@ -12,6 +12,7 @@
"lint": "tslint --project tsconfig.json", "lint": "tslint --project tsconfig.json",
"lint:fix": "tslint --project tsconfig.json --fix", "lint:fix": "tslint --project tsconfig.json --fix",
"dev": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m pwa", "dev": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m pwa",
"dev2": "webpack-dev-server --inline --progress",
"dev:ssr": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m ssr", "dev:ssr": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m ssr",
"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:unit": "jest", "test:unit": "jest",
@@ -25,15 +26,20 @@
"generate-sw": "workbox generateSW workbox-config.js" "generate-sw": "workbox generateSW workbox-config.js"
}, },
"dependencies": { "dependencies": {
"@babel/plugin-transform-runtime": "^7.4.0",
"@babel/runtime": "^7.0.0",
"@quasar/extras": "^1.1.0", "@quasar/extras": "^1.1.0",
"@types/vuelidate": "^0.7.0", "@types/vuelidate": "^0.7.0",
"@vue/eslint-config-standard": "^4.0.0",
"acorn": "^6.0.0", "acorn": "^6.0.0",
"autoprefixer": "^9.5.0",
"axios": "^0.18.0", "axios": "^0.18.0",
"babel-runtime": "^6.26.0", "babel-eslint": "^10.0.1",
"bcrypt-nodejs": "0.0.3", "bcrypt-nodejs": "0.0.3",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"dotenv": "^6.1.0", "dotenv": "^6.1.0",
"element-ui": "^2.3.6", "element-ui": "^2.3.6",
"eslint-plugin-vue": "^5.2.2",
"google-translate-api": "^2.3.0", "google-translate-api": "^2.3.0",
"graphql": "^0.13.2", "graphql": "^0.13.2",
"graphql-tag": "^2.8.0", "graphql-tag": "^2.8.0",
@@ -42,13 +48,13 @@
"js-cookie": "^2.2.0", "js-cookie": "^2.2.0",
"localforage": "^1.7.3", "localforage": "^1.7.3",
"normalize.css": "^8.0.0", "normalize.css": "^8.0.0",
"npm": "^6.4.1", "npm": "^6.9.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"quasar": "^1.0.0-beta.10", "quasar": "^1.0.0-beta.11",
"quasar-extras": "^2.0.8", "quasar-extras": "^2.0.8",
"register-service-worker": "^1.0.0", "register-service-worker": "^1.0.0",
"vee-validate": "^2.1.2", "vee-validate": "^2.1.2",
"vue": "^2.5.17", "vue": "^2.6.10",
"vue-class-component": "^6.3.2", "vue-class-component": "^6.3.2",
"vue-i18n": "^8.1.0", "vue-i18n": "^8.1.0",
"vue-idb": "^0.2.0", "vue-idb": "^0.2.0",
@@ -62,26 +68,29 @@
"vuex-class": "^0.3.1", "vuex-class": "^0.3.1",
"vuex-module-decorators": "^0.4.3", "vuex-module-decorators": "^0.4.3",
"vuex-router-sync": "^5.0.0", "vuex-router-sync": "^5.0.0",
"vuex-typex": "^3.0.1" "vuex-typex": "^3.0.1",
"webpack-cli": "^3.3.0",
"workbox": "0.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/code-frame": "7.0.0-beta.54", "@babel/cli": "^7.2.3",
"@babel/core": "7.0.0-beta.50", "@babel/core": "^7.4.0",
"@babel/generator": "7.0.0-beta.54", "@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/helpers": "7.0.0-beta.54", "@babel/plugin-proposal-decorators": "^7.0.0",
"@babel/parser": "7.0.0-beta.54", "@babel/plugin-proposal-export-namespace-from": "^7.0.0",
"@babel/preset-env": "7.0.0-beta.54", "@babel/plugin-proposal-function-sent": "^7.0.0",
"@babel/preset-react": "7.0.0", "@babel/plugin-proposal-json-strings": "^7.0.0",
"@babel/runtime": "7.0.0-beta.54", "@babel/plugin-proposal-numeric-separator": "^7.0.0",
"@babel/template": "7.0.0-beta.54", "@babel/plugin-proposal-throw-expressions": "^7.0.0",
"@babel/traverse": "7.0.0-beta.54", "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/types": "7.0.0-beta.54", "@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.4.2",
"@quasar/app": "^1.0.0-beta.11", "@quasar/app": "^1.0.0-beta.11",
"@quasar/quasar-app-extension-typescript": "^1.0.0-alpha.11", "@quasar/quasar-app-extension-typescript": "^1.0.0-alpha.11",
"@types/dotenv": "^4.0.3", "@types/dotenv": "^4.0.3",
"@types/jest": "^23.1.4", "@types/jest": "^23.1.4",
"@types/js-cookie": "^2.1.0", "@types/js-cookie": "^2.1.0",
"@types/node": "11.9.5", "@types/node": "^11.9.5",
"@types/nprogress": "^0.0.29", "@types/nprogress": "^0.0.29",
"@types/webpack-env": "^1.13.6", "@types/webpack-env": "^1.13.6",
"@vue/babel-preset-app": "3.1.1", "@vue/babel-preset-app": "3.1.1",
@@ -89,15 +98,18 @@
"@vue/cli-plugin-e2e-cypress": "^3.0.1", "@vue/cli-plugin-e2e-cypress": "^3.0.1",
"@vue/cli-plugin-pwa": "^3.0.1", "@vue/cli-plugin-pwa": "^3.0.1",
"@vue/cli-plugin-typescript": "^3.0.1", "@vue/cli-plugin-typescript": "^3.0.1",
"@vue/cli-plugin-unit-jest": "^3.0.1", "@vue/cli-plugin-unit-jest": "^3.5.3",
"@vue/cli-service": "^3.0.1", "@vue/cli-service": "^3.0.1",
"@vue/test-utils": "^1.0.0-beta.20", "@vue/test-utils": "^1.0.0-beta.20",
"babel-loader": "^8.0.0-beta.2", "babel-core": "^7.0.0-bridge.0",
"babel-jest": "^24.5.0",
"babel-loader": "8.0.0-beta.2",
"babel-plugin-transform-imports": "1.5.1", "babel-plugin-transform-imports": "1.5.1",
"eslint": "^5.5.0", "eslint": "^5.5.0",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^2.8.1", "html-webpack-plugin": "^2.8.1",
"http-proxy-middleware": "^0.17.0", "http-proxy-middleware": "^0.19.1",
"jest": "^23.6.0", "jest": "^24.5.0",
"json-loader": "^0.5.4", "json-loader": "^0.5.4",
"node-sass": "^4.11.0", "node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^5.0.1", "optimize-css-assets-webpack-plugin": "^5.0.1",
@@ -105,13 +117,13 @@
"sass-loader": "^7.1.0", "sass-loader": "^7.1.0",
"strip-ansi": "=3.0.1", "strip-ansi": "=3.0.1",
"ts-jest": "^23.0.0", "ts-jest": "^23.0.0",
"ts-loader": "^5.3.0", "ts-loader": "^5.3.3",
"tslint": "^5.11.0", "tslint": "^5.11.0",
"tslint-config-standard": "^8.0.1", "tslint-config-standard": "^8.0.1",
"tslint-loader": "^3.4.3", "tslint-loader": "^3.4.3",
"typescript": "^3.1.6", "typescript": "^3.3.3333",
"vue-cli-plugin-element-ui": "^1.1.2", "vue-cli-plugin-element-ui": "^1.1.2",
"vue-template-compiler": "^2.5.17", "vue-template-compiler": "^2.6.10",
"vueify": "^9.4.1", "vueify": "^9.4.1",
"webpack": "^4.29.6", "webpack": "^4.29.6",
"webpack-dev-middleware": "^3.2.0", "webpack-dev-middleware": "^3.2.0",
@@ -128,5 +140,8 @@
"> 1%", "> 1%",
"last 2 versions", "last 2 versions",
"not ie <= 10" "not ie <= 10"
] ],
"resolutions": {
"ajv": "6.8.1"
}
} }

23
pwa-mat/service-worker.js Normal file
View File

@@ -0,0 +1,23 @@
/**
* Welcome to your Workbox-powered service worker!
*
* You'll need to register this file in your web app and you should
* disable HTTP caching for this file too.
* See https://goo.gl/nhQhGp
*
* The rest of the code is auto-generated. Please don't update this file
* directly; instead, make changes to your Workbox build configuration
* and re-run your build process.
* See https://goo.gl/2aRDsh
*/
importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js");
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See https://goo.gl/S9QRab
*/
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});

View File

@@ -14,10 +14,10 @@ const extendTypescriptToWebpack = (config) => {
.alias .alias
.set('@components', helpers.root('src/components/index.ts')) .set('@components', helpers.root('src/components/index.ts'))
// .set('@components', helpers.root('src/components')) // .set('@components', helpers.root('src/components'))
.set('@views', helpers.root('src/components/views/index.ts')) .set('@views', helpers.root('src/views/index.ts'))
// .set('@views', helpers.root('src/components/views')) // .set('@views', helpers.root('src/components/views'))
.set('@src', helpers.root('src')) .set('@src', helpers.root('src'))
.set('@css', helpers.root('src/statics/css/*')) .set('@css', helpers.root('src/statics/css/variables.scss'))
.set('@icons', helpers.root('src/statics/icons/*')) .set('@icons', helpers.root('src/statics/icons/*'))
.set('@images', helpers.root('src/statics/images/*')) .set('@images', helpers.root('src/statics/images/*'))
.set('@classes', helpers.root('src/classes/index.ts')) .set('@classes', helpers.root('src/classes/index.ts'))
@@ -25,6 +25,7 @@ const extendTypescriptToWebpack = (config) => {
.set('@utils', helpers.root('src/utils/*')) .set('@utils', helpers.root('src/utils/*'))
.set('@router', helpers.root('src/router/index.ts')) .set('@router', helpers.root('src/router/index.ts'))
.set('@validators', helpers.root('src/utils/validators.ts')) .set('@validators', helpers.root('src/utils/validators.ts'))
.set('@methods', helpers.root('src/utils/methods.ts'))
.set('@api', helpers.root('src/store/Api/index.ts')) .set('@api', helpers.root('src/store/Api/index.ts'))
.set('@paths', helpers.root('src/store/Api/ApiRoutes.ts')) .set('@paths', helpers.root('src/store/Api/ApiRoutes.ts'))
.set('@types', helpers.root('src/typings/index.ts')) .set('@types', helpers.root('src/typings/index.ts'))
@@ -169,10 +170,13 @@ module.exports = function (ctx) {
'QPageScroller', 'QPageScroller',
'QAvatar', 'QAvatar',
'QImg', 'QImg',
'QSplitter',
'QSeparator',
'QCarouselSlide' 'QCarouselSlide'
], ],
directives: [ directives: [
'Ripple', 'Ripple',
'ClosePopup'
], ],
// Quasar plugins // Quasar plugins
plugins: [ plugins: [

View File

@@ -1,6 +0,0 @@
{
"@quasar/typescript": {
"webpack": "plugin",
"rename": true
}
}

View File

@@ -26,12 +26,12 @@ const cfgenv = {
// console.log('serverweb', cfgenv.serverweb) // console.log('serverweb', cfgenv.serverweb)
async function writeData(table, data) { async function writeData(table, data) {
// console.log('writeData', table, data); // console.log('writeData', table, data);
await idbKeyval.setdata(table, data); await idbKeyval.setdata(table, data);
} }
async function readAllData(table) { async function readAllData(table) {
// console.log('readAllData', table); // console.log('readAllData', table);
return await idbKeyval.getalldata(table); return await idbKeyval.getalldata(table);
@@ -123,59 +123,73 @@ if (workbox) {
// console.log(' routing.registerRoute function declaration:') // console.log(' routing.registerRoute function declaration:')
workbox.routing.registerRoute( function Execute_Fetch(table, args) {
new RegExp(cfgenv.serverweb + '/todos/'), console.log('Execute_Fetch registerRoute! ', cfgenv.serverweb + '/' + table + '/')
function (args) {
console.log('registerRoute! ', cfgenv.serverweb + '/todos/')
// console.log('DATABODY:', args.event.request.body) // console.log('DATABODY:', args.event.request.body)
let myres = null let myres = null
// return fetch(args.event.request, args.event.headers) // return fetch(args.event.request, args.event.headers)
return fetch(args.event.request, args.event.headers) return fetch(args.event.request, args.event.headers)
.then(function (res) { .then(function (res) {
myres = res myres = res
// console.log('1° ******* [[[ SERVICE-WORKER ]]] registerRoute fetch: -> ', args.event.request, res)
// LOAD FROM SERVER , AND SAVE INTO INDEXEDDB
// console.log('res.status', res.status)
if (res.status === 200) { if (res.status === 200) {
const clonedRes = res.clone(); const clonedRes = res.clone();
// console.log('1) clearAllData(categories)') let secondatab = ''
return clearAllData('categories') if (table === 'todos') {
secondatab = 'categories'
}
console.log('1) clearAllData: ', table)
return clearAllData(table)
.then(() => { .then(() => {
if (secondatab !== '') {
// console.log('2) clearAllData(todos)') // console.log('2) clearAllData(todos)')
return clearAllData('todos') return clearAllData(secondatab)
.then(() => { .then(() => {
// console.log('3) ....return clonedRes') // console.log('3) ....return clonedRes')
return clonedRes return clonedRes
}) })
} else {
return clonedRes
}
}) })
} }
}) })
.then((clonedRes) => { .then((clonedRes) => {
// console.log(' 3) ') // console.log(' 3) ')
if (clonedRes !== undefined) if (!!clonedRes)
return clonedRes.json(); return clonedRes.json();
return null return null
}) })
.then(data => { .then(data => {
// console.log(' 4) data = ', data) // console.log(' 4) data = ', data)
if (data) { if (data) {
if (data.todos) {
myarr = idbKeyval.getArrayByTable(table, data)
if (myarr) {
let promiseChain = Promise.resolve(); let promiseChain = Promise.resolve();
console.log('*********+++++++++++++++++********** Records TODOS Received from Server [', data.todos.length, 'record]', data.todos) console.log('*********+++++++++++++++++********** Records ', table + ' Received from Server [', myarr.length, 'record]', myarr)
for (let cat in data.categories) { if (table === 'todos') {
for (const cat in data.categories) {
promiseChain = promiseChain.then(() => { promiseChain = promiseChain.then(() => {
return writeData('categories', { _id: cat, valore: data.categories[cat] } ) return writeData('categories', { _id: cat, valore: data.categories[cat] })
}) })
} }
for (let indrecCat in data.todos) { for (const arrsing of myarr) {
for (let indrec in data.todos[indrecCat]) { for (const rec of arrsing) {
promiseChain = promiseChain.then(() => { promiseChain = promiseChain.then(() => {
return writeData('todos', data.todos[indrecCat][indrec]) return writeData(table, rec)
})
}
}
} else {
// Others tables
for (const rec of myarr) {
promiseChain = promiseChain.then(() => {
return writeData(table, rec)
}) })
} }
} }
@@ -193,8 +207,16 @@ if (workbox) {
console.log('ERROR registerRoute FETCH:', err) console.log('ERROR registerRoute FETCH:', err)
return myres return myres
}) })
}
for (let table of MainTables) {
workbox.routing.registerRoute(
new RegExp(cfgenv.serverweb + '/' + table + '/'),
function (args) {
Execute_Fetch(table, args)
}) })
}
workbox.routing.registerRoute(function (routeData) { workbox.routing.registerRoute(function (routeData) {
return (routeData.event.request.headers.get('accept').includes('text/html')); return (routeData.event.request.headers.get('accept').includes('text/html'));
@@ -236,12 +258,12 @@ if (workbox) {
workbox.routing.registerRoute( workbox.routing.registerRoute(
new RegExp(/\.(?:js|css|font)$/), new RegExp(/\.(?:js|css|font)$/),
new workbox.strategies.StaleWhileRevalidate( { new workbox.strategies.StaleWhileRevalidate({
cacheName: 'js-css-fonts', cacheName: 'js-css-fonts',
}), }),
); );
/* /*
workbox.routing.registerRoute( workbox.routing.registerRoute(
new RegExp('https://cdnjs.coudflare.com/ajax/libs/material-design-lite/1.3.0/material.indigo-pink.min.css'), new RegExp('https://cdnjs.coudflare.com/ajax/libs/material-design-lite/1.3.0/material.indigo-pink.min.css'),
workbox.strategies.staleWhileRevalidate({ workbox.strategies.staleWhileRevalidate({
@@ -253,7 +275,7 @@ if (workbox) {
] ]
}) })
); );
*/ */
// Storage // Storage
workbox.routing.registerRoute( workbox.routing.registerRoute(
@@ -283,7 +305,7 @@ if (workbox) {
}) })
); );
/* /*
workbox.routing.registerRoute( workbox.routing.registerRoute(
new RegExp(/^http/), new RegExp(/^http/),
workbox.strategies.networkFirst({ workbox.strategies.networkFirst({
@@ -296,7 +318,7 @@ if (workbox) {
] ]
}) })
); );
*/ */
workbox.routing.registerRoute( workbox.routing.registerRoute(
@@ -514,7 +536,7 @@ self.addEventListener('notificationclick', function (event) {
return c.visibilityState === 'visible'; return c.visibilityState === 'visible';
}); });
if (client !== undefined) { if (!!client) {
client.navigate(notification.data.url); client.navigate(notification.data.url);
client.focus(); client.focus();
} else { } else {

View File

@@ -50,3 +50,26 @@
font-size: 1.1rem; font-size: 1.1rem;
text-align: center; text-align: center;
} }
.lowperc {
color: red;
}
.medperc {
color: blue;
}
.highperc {
color: green;
}
.hide-if-small {
@media (max-width: 600px) {
display: none;
}
}
.thiny-if-small {
@media (max-width: 600px) {
max-width: 22px;
}
}

View File

@@ -1,5 +1,11 @@
// import something here // import something here
import { IMyRoute } from '@src/router/route-config'
// import { isEqual } from 'lodash'
import { ProgressBar } from '@src/store/Modules/Interface'
import { UserStore } from "@store"
export default ({ app, router, store, Vue }) => { export default ({ app, router, store, Vue }) => {
// ****************************************** // ******************************************
// *** Per non permettere di accedere alle pagine in cui è necessario essere Loggati ! *** // *** Per non permettere di accedere alle pagine in cui è necessario essere Loggati ! ***
@@ -8,42 +14,6 @@ export default ({ app, router, store, Vue }) => {
// Creates a `nextMiddleware()` function which not only // Creates a `nextMiddleware()` function which not only
// runs the default `next()` callback but also triggers // runs the default `next()` callback but also triggers
// the subsequent Middleware function. // the subsequent Middleware function.
function nextFactory(context, middleware, index) {
const subsequentMiddleware = middleware[index]
// If no subsequent Middleware exists,
// the default `next()` callback is returned.
if (!subsequentMiddleware) { return context.next }
return (...parameters) => {
// Run the default Vue Router `next()` callback first.
context.next(...parameters)
// Then run the subsequent Middleware with a new
// `nextMiddleware()` callback.
const nextMiddleware = nextFactory(context, middleware, index + 1)
subsequentMiddleware({ ...context, next: nextMiddleware })
}
}
router.beforeEach((to, from, next) => {
if (to.meta.middleware) {
const middleware = Array.isArray(to.meta.middleware)
? to.meta.middleware
: [to.meta.middleware];
const context = {
from,
next,
router,
to,
};
const nextMiddleware = nextFactory(context, middleware, 1)
return middleware[0]({ ...context, next: nextMiddleware })
}
return next()
})
/*router.beforeEach((to, from, next) => { /*router.beforeEach((to, from, next) => {
var accessToken = store.state.session.userSession.accessToken var accessToken = store.state.session.userSession.accessToken

View File

@@ -29,7 +29,7 @@ export function debounce<F extends Procedure>(
const shouldCallNow = options.isImmediate && timeoutId === undefined const shouldCallNow = options.isImmediate && timeoutId === undefined
if (timeoutId !== undefined) { if (!!timeoutId) {
clearTimeout(timeoutId) clearTimeout(timeoutId)
} }

View File

@@ -10,9 +10,11 @@ export async function askConfirm($q: any, mytitle, mytext, ok, cancel) {
push: true push: true
}, },
title: mytitle title: mytitle
}).then((ris) => { }).onOk(() => {
return ris console.log('OK')
}).catch(() => { return true
}).onCancel(() => {
console.log('CANCEL')
return false return false
}) })
} catch (e) { } catch (e) {

View File

@@ -0,0 +1,48 @@
$heightBtn: 100%;
.flex-item{
// background-color: #d5e2eb;
display: flex;
padding: 2px;
margin: 2px;
margin-left: 3px;
margin-right: 3px;
color: #000;
font-size: 1rem;
height: $heightBtn;
line-height: $heightBtn;
vertical-align: middle;
//flex: 0 0 100%;
}
.progress-item {
margin: 1px;
padding: 2px;
padding-top: 4px;
padding-bottom: 4px;
flex: 1;
flex-direction: column;
order: 1;
}
.cpr-progrbar-item {
//height: 10px
padding-top: 7px;
height:15px;
}
.cpr-percProgress {
padding-top: 3px;
color: #888;
vertical-align: middle;
text-align: center;
//line-height: $heightitem;
}
.data_string {
font-size: 0.85rem;
@media (max-width: 600px) {
max-width: 22px;
// display: none;
}
}

View File

@@ -0,0 +1,61 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools'
import { date } from 'quasar'
@Component({
name: 'CDate'
})
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
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)
this.$emit('input', this.getDate())
} else {
console.log(' DATA NON VALIDAAAAAAAAAAAAA ', value, datavalida)
}
this.$refs.datePicker.hide()
}
get getdatestring() {
return tools.getstrDate(this.valueInternal)
}
get getdateyymmddstring() {
return tools.getstrYYMMDDDate(this.valueInternal)
}
private getDate() {
return this.valueInternal
}
}

View File

@@ -0,0 +1,18 @@
<template>
<q-input :class="data_class" :bg-color="color" :readonly="readonly" :disable="disable" debounce="1000" dense :value="getdatestring" stack-label :label="label" @input="changedate">
<template v-slot:append>
<q-icon name="event" class="cursor-pointer" :style="mystyleicon">
<q-popup-proxy v-if="!readonly" ref="datePicker">
<q-date :value="getdateyymmddstring" today-btn @input="changedate"></q-date>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</template>
<script lang="ts" src="./CDate.ts">
</script>
<style lang="scss" scoped>
@import './CDate.scss';
</style>

View File

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

View File

@@ -0,0 +1,45 @@
$heightBtn: 100%;
.flex-item{
// background-color: #d5e2eb;
display: flex;
padding: 2px;
margin: 2px;
margin-left: 3px;
margin-right: 3px;
color: #000;
font-size: 1rem;
height: $heightBtn;
line-height: $heightBtn;
vertical-align: middle;
//flex: 0 0 100%;
}
.progress-item {
margin: 1px;
padding: 2px;
padding-top: 4px;
padding-bottom: 4px;
flex: 1;
flex-direction: column;
order: 1;
}
.cpr-progrbar-item {
//height: 10px
margin-top: 11px;
margin-bottom: 11px;
height:15px;
}
.cpr-slider-item {
//height: 10px
}
.cpr-percProgress {
padding-top: 3px;
color: #888;
vertical-align: middle;
text-align: center;
//line-height: $heightitem;
}

View File

@@ -0,0 +1,49 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools'
@Component({
name: 'CProgress'
})
export default class CProgress extends Vue {
public cpr_colProgress: string = 'blue'
public cpr_percProgress: string = 'cpr-percProgress'
public progressvalinternal: number = 0
@Watch('progressval')
public changeprogress() {
this.updateclasses()
}
@Prop({ required: true }) public progressval: number
@Prop() public descr: string
@Prop({ default: false }) public slider: boolean
@Watch('progressval')
public valchanged(value) {
this.progressvalinternal = value
}
public updateclasses() {
this.cpr_colProgress = tools.getProgressColor(this.progressvalinternal)
}
public setchange(value) {
this.progressvalinternal = value
console.log('setchange', this.progressvalinternal)
this.$emit('input', this.progressvalinternal)
}
get getdescr() {
if (!!this.descr) {
return this.descr + ' : '
}
}
public create() {
this.updateclasses()
}
}

View File

@@ -0,0 +1,33 @@
<template>
<div>
<div class="flex-item progress-item shadow-1">
<q-slider v-if="slider" label
class="cpr-slider-item"
:value="progressval"
:min="0"
:max="100"
@change="setchange"
:step="5">
</q-slider>
<q-linear-progress
v-else
stripe
rounded
:value="progressval / 100"
class="cpr-progrbar-item"
:color="cpr_colProgress">
</q-linear-progress>
<div :class="cpr_percProgress">
{{getdescr}} {{progressval}}%
</div>
</div>
</div>
</template>
<script lang="ts" src="./CProgress.ts">
</script>
<style lang="scss" scoped>
@import './CProgress.scss';
</style>

View File

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

View File

@@ -155,7 +155,7 @@ export default class Header extends Vue {
const color = (value === 'online') ? 'positive' : 'warning' const color = (value === 'online') ? 'positive' : 'warning'
if (oldValue !== undefined) { if (!!oldValue) {
tools.showNotif(this.$q, this.$t('connection') + ` ${value}`, { tools.showNotif(this.$q, this.$t('connection') + ` ${value}`, {
color, color,
icon: 'wifi' icon: 'wifi'
@@ -262,12 +262,12 @@ export default class Header extends Vue {
function updateOnlineStatus(event) { function updateOnlineStatus(event) {
if (navigator.onLine) { if (navigator.onLine) {
// console.log('EVENT ONLINE!') console.log('EVENT ONLINE!')
// handle online status // handle online status
GlobalStore.mutations.setStateConnection('online') GlobalStore.mutations.setStateConnection('online')
mythis.changeIconConn() mythis.changeIconConn()
} else { } else {
// console.log('EVENT OFFLINE!') console.log('EVENT OFFLINE!')
// handle offline status // handle offline status
GlobalStore.mutations.setStateConnection('offline') GlobalStore.mutations.setStateConnection('offline')
mythis.changeIconConn() mythis.changeIconConn()

View File

@@ -47,11 +47,11 @@
<!-- <!--
<div v-if="isAdmin"> <div v-if="isAdmin">
<q-btn flat dense round aria-label=""> <q-btn flat dense round aria-label="">
<q-icon :class="clCloudUpload" name="cloud_upload"></q-icon> <q-icon :class="clCloudUpload" nametranslate="cloud_upload"></q-icon>
</q-btn> </q-btn>
<q-btn flat dense round aria-label=""> <q-btn flat dense round aria-label="">
<q-icon :class="clCloudUp_Indexeddb" name="arrow_upward"></q-icon> <q-icon :class="clCloudUp_Indexeddb" nametranslate="arrow_upward"></q-icon>
</q-btn> </q-btn>
</div> </div>

View File

@@ -0,0 +1,49 @@
<template>
<transition name='fade'>
<div class="progress" v-if="progressState.show"
:style="{
width: progressState.percent+'%',
height: progressState.height,
backgroundColor: progressState.canSuccess? progressState.color : progressState.failedColor,
}"
></div>
</transition>
</template>
<script lang='ts'>
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
import { ProgressBar } from '../../store/Modules/Interface'
@Component({})
export default class ProgressBarComponent extends Vue {
get progressState() {
return ProgressBar.state
}
}
</script>
<style scoped>
.progress {
position: fixed;
top: 0px;
left: 0px;
right: 0px;
height: 2px;
width: 0%;
transition: width 0.2s linear;
z-index: 999999;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.4s ease-out;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
export * from './categories' export * from '../views/categories'
export * from './todos' export * from './todos'
export * from './logo' export * from './logo'
export * from './CProgress'
export * from './CDate'

View File

@@ -1,52 +1,11 @@
import Vue from 'vue' import Vue from 'vue'
import { Component } from 'vue-property-decorator' import { Component } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools'
import { TimelineLite, Back } from 'gsap'
import $ from 'jquery'
import Timeout = NodeJS.Timeout
import { tools } from "@src/store/Modules/tools"
@Component({ @Component({
}) })
export default class Logo extends Vue { export default class Logo extends Vue {
public logoimg: string = '' get logoimg() {
return '../../' + tools.getimglogo()
public created() {
this.logoimg = '../../' + tools.getimglogo()
this.animate()
} }
public animate() {
const timeline = new TimelineLite()
/*
let mysmile = $('#smile')
mysmile.attr('class', 'smile_hide')
setTimeout(() => {
mysmile.removeClass('smilevisible')
mysmile.addClass('smile_hide')
}, 1000)
setTimeout(() => {
mysmile.addClass('smilevisible')
mysmile.removeClass('smile_hide')
}, 10000)
*/
/*
timeline.to('#smile', 5, {
cy: 20,
cx: 60,
ease: Back.easeInOut // Specify an ease
})
*/
}
} }

View File

@@ -1,53 +0,0 @@
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
import { TimelineLite, Back } from 'gsap'
import $ from 'jquery'
import Timeout = NodeJS.Timeout
@Component({
})
export default class Offline extends Vue {
logoimg: string = ''
created() {
this.logoimg = '/statics/images/' + process.env.LOGO_REG
this.animate()
}
animate () {
const timeline = new TimelineLite()
/*
let mysmile = $('#smile')
mysmile.attr('class', 'smile_hide')
setTimeout(() => {
mysmile.removeClass('smilevisible')
mysmile.addClass('smile_hide')
}, 1000)
setTimeout(() => {
mysmile.addClass('smilevisible')
mysmile.removeClass('smile_hide')
}, 10000)
*/
/*
timeline.to('#smile', 5, {
cy: 20,
cx: 60,
ease: Back.easeInOut // Specify an ease
})
*/
}
}

View File

@@ -0,0 +1,404 @@
$colcompleted: #a2a2a2;
$heightitem: 32px;
$heightothers: 32px;
$heightBtn: 100%;
$heightcounter: 26px;
$heightdescr: 20px;
.flex-item{
// background-color: #d5e2eb;
padding: 2px;
margin: 2px;
margin-left: 3px;
margin-right: 3px;
color: #000;
font-size: 1rem;
height: $heightBtn;
line-height: $heightBtn;
vertical-align: middle;
//flex: 0 0 100%;
}
.flex-container2 {
flex-flow: row wrap;
justify-content: space-between;
margin: 0px 1px 0px 1px; // top right bottom left
}
// Set visibility: visible to the icon menu of pos-item-popover
.flex-container2:hover .pos-item-popover, .flex-container2:hover .priority-item-popover{
//.flex-container2:hover .pos-item-popover {
background-color: rgba(230, 230, 230, 0.8);
display: inline-block;
transition: all ease-in-out .3s;
}
.comp_selected {
display: inline-block !important;
}
.flex-container2:hover{
background-color: rgba(230, 230, 230, 0.8);
}
.rowselected {
border-width: 1px 0px 1px 0px;
border-style: solid;
border-color: rgba(49, 68, 240, 0.6);
background-color: rgba(160, 174, 255, 0.35) !important;
}
.btn-item {
max-width: 24px;
}
.counter-item {
margin: auto auto auto 2px;
padding: 2px;
vertical-align: middle;
text-align: left;
font-size: 1.10rem;
//color: blue !important;
//order: 2;
//height: 24px;
//line-height: 24px; /* same as height! */
}
.pos-item {
max-width: 24px;
min-width: 26px;
margin-left: 1px;
margin-right: 1px;
padding-left: 1px;
padding-right: 1px;
margin: 0px;
padding-top: 0px;
padding-bottom: 0px;
//height: $heightitem;
line-height: $heightitem;
min-height: $heightitem;
text-align: center;
// background-color: #ff4081;
font-size: 1rem;
order: 2;
flex: 1;
}
.titleLista-item {
max-width: 92px;
min-width: 92px;
margin: 0 auto;
height: $heightitem;
line-height: $heightitem;
text-align: center;
// background-color: #ff4081;
font-size: 1rem;
font-weight: bold;
}
.pos-item-popover{
max-width: 24px;
min-width: 24px;
padding: 0px;
text-align: center;
vertical-align: middle;
display: block;
@media screen and (min-width: 600px) {
display: none;
}
color: #939393;
height: $heightitem;
line-height: $heightitem;
//visibility: hidden;
}
//.q-menu.animate-scale {
// animation: none;
//}
.pos-item:hover, .pos-item-popover_cursor:hover {
cursor: grab;
}
.priority-item-popover {
max-width: 24px;
min-width: 24px;
padding: 0px;
text-align: center;
vertical-align: middle;
display: none;
height: 100%;
color: #777;
}
.completed-item-popover {
max-width: 24px;
min-width: 24px;
padding: 0px;
text-align: center;
vertical-align: middle;
display: inline-block;
height: $heightitem;
line-height: $heightitem;
color: #777;
}
.priority-item {
max-width: 24px;
min-width: 24px;
}
.completed-item {
max-width: 24px;
min-width: 24px;
height: $heightitem;
line-height: $heightitem;
}
.progress-item {
margin: 1px;
padding: 2px;
padding-top: 4px;
padding-bottom: 4px;
max-width: 36px;
min-width: 32px;
flex: 1;
order: 1;
}
.progrbar-item {
//height: 10px
padding-top: 7px;
}
.percProgress {
padding-top: 3px;
color: #888;
vertical-align: middle;
text-align: center;
//line-height: $heightitem;
}
.editProgress{
//height: 20px;
}
.colProgress {
}
.percompleted {
color: $colcompleted
}
.myexpired {
padding-top: 5px;
padding-bottom: 3px;
font-size: 0.85rem;
vertical-align: middle;
}
.data-item {
font-size: 0.85rem;
max-width: 100px;
@media (max-width: 600px) {
max-width: 22px;
}
//min-width: 100px;
//display: flex;
//visibility: initial;
margin-right: 3px;
color: #585858;
order: 1;
flex: 1;
height: $heightitem;
line-height: $heightitem;
padding-left: 2px;
padding-right: 0px;
//height: $heightBtn;
//line-height: $heightBtn;
}
.data_string {
@media (max-width: 600px) {
display: none;
}
}
.data-item .q-input-target{
color:red !important;
}
/*
@media screen and (max-width: 600px) {
.data-item {
display: none;
visibility: hidden;
content: "";
}
}
*/
.divdescrTot, .divdescrTot > div > div > div > div > textarea {
font-size: 1rem;
cursor: pointer;
}
.divdescrTot {
font-size: 1rem;
display: table;
flex: 1;
height: $heightitem;
vertical-align: middle;
}
.div_descr, .div_descr_edit {
margin: auto auto auto 0px;
//padding: 2px;
min-width: 100px;
text-align: left;
color: blue !important;
overflow: hidden;
align-items: center;
vertical-align: middle;
line-height: 120%;
//background-color: #d50000;
//order: 2;
&.hide {
display: none !important;
visibility: hidden;
}
&.show {
visibility: visible;
}
}
.div_descr {
display: -webkit-box;
max-height: 45px;
}
.div_descr_edit {
//display: block;
max-height: 90px;
//line-height: 120%;
//max-height: 90px;
line-height: $heightitem;
}
.div_descr:hover {
//border-width: 1px 0px 1px 0px;
border-color: rgba(125, 255, 125, 0.5);
//padding: 1px;
}
.mycols{
margin: 1px;
padding: 2px;
//width: 40px;
// border-color: #8a8484;
// border-style: outset;
margin: auto;
// flex-grow: 1;
}
.mycols:hover{
}
.mybtn{
width: 18px;
height: 18px;
}
.icon_completed {
position: relative;
transform: translateY(0%);
}
.mydescr{
}
.icon_completed {
color: rgb(178, 235, 225);
}
.status_completed {
color: $colcompleted !important;
}
.menuTitlePriority {
background-color: blue;
color:white;
padding: 2px;
margin: 2px;
font-weight: bold;
}
.test{
color: fuchsia;
&.mio1{
background-color: red;
}
}
.after_textarea {
display: none;
visibility: hidden;
}
.after_textarea:hover {
visibility: visible;
}
/*
.container {
background-color: #ccc;
padding: 10px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.item {
background-color: red;
padding: 10px;
color: white;
}
.i3{
order: 1;
flex: 1;
}
*/

View File

@@ -0,0 +1,498 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { Projects, UserStore } from '@modules'
import { tools } from '../../../store/Modules/tools'
import { IProject } from '../../../model/index'
import { SubMenusProj } from '../SubMenusProj'
import { CDate } from '../../CDate'
import { date } from 'quasar'
import { askConfirm } from '../../../classes/routinestd'
@Component({
components: { SubMenusProj, CDate },
name: 'SingleProject'
})
export default class SingleProject extends Vue {
public selectPriority: [] = []
public menuPopupProj: any[] = []
public classDescr: string = ''
public classDescrEdit: string = ''
public classExpiring: string = 'flex-item data-item shadow-1 hide-if-small'
public classExpiringEx: string = ''
public iconPriority: string = ''
public classRow: string = ''
public sel: boolean = false
public attivaEdit: boolean = false
public inEdit: boolean = false
public precDescr: string = ''
public percProgress: string = 'percProgress'
public colProgress: string = 'blue'
public percentageProgress: number = 0
public itemprojectPrec: IProject
public clButtPopover: string = 'pos-item-popover'
public $q: any
get tools() {
return tools
}
@Prop({ required: true }) public itemproject: IProject
@Watch('itemproject.enableExpiring') public valueChanged4() {
this.watchupdate('enableExpiring')
}
@Watch('itemproject.expiring_at') public valueChanged2() {
this.watchupdate('expiring_at')
}
@Watch('itemproject.descr') public valueChanged5() {
this.precDescr = this.itemproject.descr
}
@Watch('itemproject.longdescr') public valueChangedlongdescr() {
this.watchupdate('longdescr')
}
@Watch('itemproject.hoursplanned') public valueChangedhoursplanned() {
this.watchupdate('hoursplanned')
}
@Watch('itemproject.hoursworked') public valueChangedhoursworked() {
this.watchupdate('hoursworked')
}
@Watch('itemproject.begin_development') public valueChangedbegin_development() {
this.watchupdate('begin_development')
}
@Watch('itemproject.hoursweeky_plannedtowork') public valueChangedhoursweeky_plannedtowork() {
this.watchupdate('hoursweeky_plannedtowork')
}
@Watch('itemproject.begin_test') public valueChangedbegin_test() {
this.watchupdate('begin_test')
}
@Watch('itemproject.actualphase') public valueChangedactualphase() {
this.watchupdate('actualphase')
}
@Watch('itemproject.totalphases') public valueChangedtotalphases() {
this.watchupdate('totalphases')
}
@Watch('itemproject.progressCalc') public valueChanged6() {
console.log('itemproject.progressCalc')
this.updateClasses()
// console.log('this.percentageProgress', this.percentageProgress, 'this.itemproject.progressCalc', this.itemproject.progressCalc)
this.watchupdate('progressCalc')
}
get getlabeltext() {
return this.$t('proj.newproj')
}
/*
public dateToYYYYMMDD(date) {
// may have timezone caveats https://stackoverflow.com/a/29774197/1850609
return date && date.toISOString().split('T')[0]
}
*/
// Computed:
get isSel() {
return this.sel
}
public isProject() {
return this.isProjectByElem(this.itemproject)
}
public isProjectByElem(elem) {
return elem.descr.slice(-1) !== ':'
}
public watchupdate(field = '') {
console.log('watchupdate PROJ', field)
this.$emit('eventupdateproj', {myitem: this.itemproject, field } )
this.updateicon()
}
public updateClasses() {
// this.classCompleted = 'completed-item'
this.classDescr = 'flex-item div_descr show donotdrag'
this.classDescrEdit = 'flex-item div_descr_edit donotdrag'
if (!this.isProject()) {
this.classDescr += ' titleLista-item'
this.classDescrEdit += ' titleLista-item'
}
if (this.itemproject.progressCalc > 100)
this.itemproject.progressCalc = 100
this.classExpiring = 'flex-item data-item shadow-1 hide-if-small'
this.classExpiringEx = ''
this.percentageProgress = this.itemproject.progressCalc
this.percProgress = 'percProgress'
this.colProgress = tools.getProgressColor(this.itemproject.progressCalc)
this.percProgress += ' ' + tools.getProgressClassColor(this.itemproject.progressCalc)
this.clButtPopover = this.sel ? 'pos-item-popover comp_selected' : 'pos-item-popover'
if (this.itemproject.statusproj !== tools.Status.COMPLETED) {
this.clButtPopover += ' pos-item-popover_cursor'
}
// this.getinputdescr = 'inputdescr' + this.itemproject._id
// console.log('classDescrEdit = ', this.classDescrEdit)
// console.log('classDescr', this.classDescr)
// console.log('UserStore.state.lang', UserStore.state.lang)
if (this.isProject()) {
this.menuPopupProj = tools.menuPopupProj[UserStore.state.lang]
}
else {
this.menuPopupProj = []
this.menuPopupProj.push(tools.menuPopupProj[UserStore.state.lang][tools.INDEX_MENU_DELETE])
}
}
public created() {
this.precDescr = this.itemproject.descr
this.updateicon()
this.updateClasses()
this.selectPriority = tools.selectPriority[UserStore.state.lang]
}
public getClassRow() {
return 'row flex-container2 ' + this.classRow
}
public clickRiga(clickmenu: boolean = false) {
// console.log('CLICK RIGA ************')
if (!this.sel) {
if (!this.inEdit) {
// this.attivaEdit = true
this.$emit('deselectAllRowstodo', null, false)
this.$emit('deselectAllRowsproj', this.itemproject, true)
if (!this.sel) {
this.selectRiga()
} else {
this.deselectRiga()
}
}
}
}
public selectRiga() {
// console.log('selectRiga', this.itemproject.descr)
this.sel = true
this.classRow = 'rowselected'
this.updateClasses()
// console.log('FINE selectRiga', this.itemproject.descr)
}
public deselectRiga() {
// console.log('DeselectRiga', this.itemproject.descr)
this.sel = false
this.classRow = ''
this.inEdit = false
this.attivaEdit = false
this.updateClasses()
}
public deselectAndExitEdit() {
this.deselectRiga()
this.exitEdit()
}
public mouseUp() {
if (!this.inEdit) {
if (this.sel) {
this.selectRiga()
} else {
this.deselectRiga()
}
}
}
public clickProject() {
this.$emit('idsel', this.itemproject._id)
this.clickRiga()
}
public activeEdit(){
console.log('Attiva Edit')
this.attivaEdit = true
this.editProject()
}
get getrouteto() {
return '/projects/' + this.itemproject._id
}
public goIntoTheProject() {
this.$router.replace('/projects/' + this.itemproject._id)
}
public editProject() {
// console.log('INIZIO - editProject')
if (this.attivaEdit) {
// this.$emit('click')
this.precDescr = this.itemproject.descr
this.inEdit = true
if (!this.sel) {
this.selectRiga()
}
else {
this.updateClasses()
}
this.faiFocus('inputdescr', false, true)
}
// console.log('FINE - editProject')
}
public faiFocus(elem, isparent: boolean = false, select: boolean = false) {
setTimeout(() => {
let theField = null
if (isparent) {
theField = this.$parent.$parent.$parent.$parent.$refs[elem] as HTMLInputElement
}
else {
theField = this.$refs[elem] as HTMLInputElement
}
if (!!theField) {
theField.focus()
}
// console.log('focus()')
}, 100)
}
public getFocus(e) {
e.target.select()
}
public exitEdit(singola: boolean = false) {
if (this.inEdit) {
if (this.precDescr !== this.itemproject.descr) {
this.updateTodo()
}
// console.log('exitEdit')
this.inEdit = false
this.attivaEdit = false
this.updateClasses()
this.$emit('deselectAllRowstodo', null, false, false)
this.$emit('deselectAllRowsproj', this.itemproject, false, singola)
}
}
public keyDownRow(e) {
console.log('keyDownRow', e.keyCode)
// Delete Key or Backspage
if (((e.keyCode === 46)) && (this.precDescr === '') && !e.shiftKey) {
e.preventDefault()
this.deselectRiga()
this.clickMenu(tools.MenuAction.DELETE)
.then(() => {
this.faiFocus('insertProjectBottom', true)
return
})
}
}
public keyDownArea(e) {
console.log('keyDownArea')
/*
if ((e.key === 'ArrowUp') && !e.shiftKey) {
e.key = 'Tab'
e.shiftKey = true
}
if ((e.key === 'ArrowDown') && !e.shiftKey) {
let nextInput = inputs.get(inputs.index(this) + 1)
if (nextInput) {
nextInput.focus()
}
}
*/
// Delete Key or Backspage
if (((e.keyCode === 46)) && (this.precDescr === '') && !e.shiftKey) {
e.preventDefault()
this.deselectRiga()
this.clickMenu(tools.MenuAction.DELETE)
.then(() => {
this.faiFocus('insertProjectBottom', true)
return
})
}
if (((e.key === 'Enter') || (e.key === 'Tab')) && !e.shiftKey) {
this.updateTodo()
if ((e.key === 'Tab') && !e.shiftKey) {
} else {
e.preventDefault()
this.deselectRiga()
this.faiFocus('insertProjectBottom', false)
}
}
// console.log('keyDownArea', e)
if (e.key === 'Escape') {
this.deselectRiga()
// this.faiFocus('insertProject', true)
console.log('LOAD this.precDescr', this.precDescr)
this.precDescr = this.itemproject.descr
}
}
public updateTodo() {
if (this.itemproject.descr === this.precDescr) {
return
}
this.itemproject.descr = this.precDescr
console.log('updateTodo', this.precDescr, this.itemproject.descr)
console.log('itemproject', this.itemproject)
console.log('Prec:', this.itemprojectPrec)
this.watchupdate('descr')
this.inEdit = false
this.attivaEdit = false
// this.precDescr = this.itemproject.descr
this.updateClasses()
}
public aggiornaProgress(value, initialval){
if (value !== initialval) {
this.itemproject.progressCalc = value
this.updatedata('progressCalc')
this.deselectAndExitEdit()
}
}
public setCompleted() {
// console.log('setCompleted')
if (this.itemproject.statusproj === tools.Status.COMPLETED) {
this.itemproject.statusproj = tools.Status.OPENED
} else {
this.itemproject.statusproj = tools.Status.COMPLETED
}
this.updateicon()
this.deselectAndExitEdit()
}
public updatedata(field: string) {
// const myitem = tools.jsonCopy(this.itemproject)
console.log('calling this.$emit(eventupdateproj)', this.itemproject)
this.$emit('eventupdateproj', { myitem: this.itemproject, field } )
}
public updateicon() {
// console.log('updateicon')
if (this.itemproject.priority === tools.Priority.PRIORITY_HIGH) {
this.iconPriority = 'expand_less'
} // expand_less
else if (this.itemproject.priority === tools.Priority.PRIORITY_NORMAL) {
this.iconPriority = 'remove'
}
else if (this.itemproject.priority === tools.Priority.PRIORITY_LOW) {
this.iconPriority = 'expand_more'
} // expand_more
this.updateClasses()
}
public removeitem(id) {
this.$emit('deleteItemproj', id)
}
public enableExpiring() {
this.itemproject.enableExpiring = !this.itemproject.enableExpiring
}
public async clickMenu(action) {
console.log('click menu: ', action)
if (action === tools.MenuAction.DELETE) {
return await this.askConfirmDelete()
} else if (action === tools.MenuAction.TOGGLE_EXPIRING) {
return await this.enableExpiring()
} else if (action === tools.MenuAction.EDIT) {
this.activeEdit()
} else if (action === 0) {
this.deselectAndExitEdit()
}
}
public setPriority(newpriority) {
if (this.itemproject.priority !== newpriority) {
this.itemproject.priority = newpriority
this.updatedata('priority')
this.updateicon()
}
}
public async askConfirmDelete() {
const deletestr = this.$t('dialog.delete')
const cancelstr = this.$t('dialog.cancel')
const msg = this.$t('dialog.msg.deleteTask', {mytodo : this.itemproject.descr })
this.$q.dialog({
cancel: {
label: cancelstr
},
message: msg,
ok: {
label: deletestr,
push: true
},
title: this.$t('dialog.msg.titledeleteTask')
}).onOk(() => {
console.log('OK')
this.removeitem(this.itemproject._id)
}).onCancel(() => {
console.log('CANCEL')
})
/*
// return await askConfirm(this.$q, this.$t('dialog.msg.titledeleteTask'), msg, deletestr, cancelstr)
.then((ris) => {
console.log('ris', ris)
if (ris) {
this.removeitem(this.itemproject._id)
}
}).catch((err) => {
})
*/
}
}

View File

@@ -0,0 +1,63 @@
<template>
<div :class="getClassRow()" @click="clickProject" >
<q-btn class="flex-item donotdrag " size="sm" push color="primary" round icon="arrow_forward"
:to="getrouteto"/>
<div class="flex-item donotdrag divdescrTot">
<q-input v-if="(sel && inEdit)" hide-underline type="textarea" ref="inputdescr"
v-model.trim="precDescr"
autogrow
borderless
:label="getlabeltext"
dense
@focus="getFocus($event)"
:class="classDescrEdit" :max-height="100"
@keydown="keyDownArea" v-on:keydown.esc="exitEdit" @blur="exitEdit(true)" @click="editProject()"/>
<div v-else :class="classDescr"
@keydown="keyDownRow">{{itemproject.descr}}
</div>
</div>
<div v-if="isProject()" class="flex-item progress-item shadow-1">
<q-linear-progress
stripe
rounded
:value="percentageProgress / 100"
class="progrbar-item"
:color="colProgress"
>
</q-linear-progress>
<div :class="percProgress">
{{percentageProgress}}%
</div>
</div>
<div v-if="itemproject.enableExpiring" :class="classExpiring">
<CDate :mydate="itemproject.expiring_at" @input="itemproject.expiring_at = new Date(arguments[0])"
data_class="data_string">
</CDate>
</div>
<div v-if="isProject()" class="flex-item pos-item " @mousedown="clickRiga">
<q-btn flat
:class="clButtPopover"
icon="menu">
<q-menu ref="popmenu" self="top right">
<SubMenusProj :menuPopupProj="menuPopupProj" :itemproject="itemproject" @clickMenu="clickMenu"
@setPriority="setPriority"></SubMenusProj>
</q-menu>
</q-btn>
</div>
</div>
</template>
<script lang="ts" src="./SingleProject.ts">
</script>
<style lang="scss" scoped>
@import './SingleProject.scss';
</style>

View File

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

View File

@@ -0,0 +1,18 @@
.todo-menu {
min-width: 202px;
}
.item-menu {
font-size: 1rem;
}
.item-menu:hover {
cursor: pointer;
}
.menuInputProgress > div > div > div > input {
min-width: 30px;
max-width: 30px;
width: 30px;
}

View File

@@ -0,0 +1,54 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools'
import { UserStore } from '@store'
import { IProject } from '../../../model/index'
// Doesn't exist in quasar this ? error TS2305
// import { format } from 'quasar'
// const { between } = format
// import { filter } from 'quasar'
@Component({
name: 'SubMenusProj'
})
export default class SubMenusProj extends Vue {
public selectPriority: [] = tools.selectPriority[UserStore.state.lang]
@Prop({ required: false }) public menuPopupProj: any[]
@Prop({ required: false }) public itemproject: IProject
public $q: any
public clickMenu(field) {
this.$emit('clickMenu', field)
}
public setPriority(field) {
this.$emit('setPriority', field)
}
public KeychangeProgress(e) {
// between(50, 10, 20)
if (this.itemproject.progressCalc > 100) {
this.itemproject.progressCalc = 100
}
if (this.itemproject.progressCalc < 0) {
this.itemproject.progressCalc = 0
}
if (e.key === 'Enter') {
// chiudi il meno
this.$emit('clickMenu', 0)
}
}
public create() {
this.selectPriority = tools.selectPriority[UserStore.state.lang]
console.log('CREAZIONE')
}
}

View File

@@ -0,0 +1,82 @@
<template>
<q-list separator no-border class="todo-menu">
<div v-for="field in menuPopupProj" :key="field.value">
<q-item v-close-popup clickable v-if="(field.value !== 130) && (field.value !== 120)" :icon="field.icon"
@click="clickMenu(field.value)">
<q-item-section avatar>
<q-icon :name="field.icon"/>
</q-item-section>
<q-item-section label class="item-menu">
<q-item-label>{{field.label}}</q-item-label>
</q-item-section>
<q-item-section side top v-if="field.value === 101">
<q-checkbox v-model="itemproject.enableExpiring"/>
</q-item-section>
</q-item>
<q-item clickable v-if="(field.value === 120)" :icon="field.icon"
@click="clickMenu(field.value)">
<q-item-section avatar>
<q-icon :name="field.icon"/>
</q-item-section>
<q-item-section>
<q-slider label
:class="$parent.menuProgress"
v-model="itemproject.progressCalc"
:min="0"
:max="100"
:step="5" @change="val => { lazy = val }"
/>
</q-item-section>
<q-item-section side>
<div>
<q-item-label style="color: blue">{{itemproject.progressCalc}} %</q-item-label>
</div>
</q-item-section>
</q-item>
<q-item clickable v-if="(field.value === 130)">
<q-item-section avatar>
<q-icon name="priority_high" inverted color="primary"/>
</q-item-section>
<q-item-section>{{field.label}}</q-item-section>
<q-item-section side>
<q-icon name="keyboard_arrow_right"/>
</q-item-section>
<q-menu auto-close anchor="bottom middle" self="top middle">
<q-list dense>
<q-item side clickable :icon="field.icon"
@click="clickMenu(field.value)">
<q-item-section>
<q-list dense>
<q-item clickable v-ripple v-for="fieldprior in selectPriority"
:key="fieldprior.value"
@click="setPriority(fieldprior.value)">
<q-item-section avatar>
<q-icon :name="fieldprior.icon" inverted color="primary"/>
</q-item-section>
<q-item-section>
{{fieldprior.label}}
</q-item-section>
</q-item>
</q-list>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-item>
</div>
</q-list>
</template>
<script lang="ts" src="./SubMenusProj.ts">
</script>
<style lang="scss" scoped>
@import './SubMenusProj.scss';
</style>

View File

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

View File

@@ -0,0 +1,2 @@
export * from './SingleProject'
export * from './SubMenusProj'

View File

@@ -0,0 +1,235 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { IDrag, IProject, ITodo, ITodosState } from '../../../model/index'
import { tools } from '../../../store/Modules/tools'
import * as ApiTables from '../../../store/Modules/ApiTables'
import { GlobalStore, Todos } from '@store'
import { UserStore } from '@store'
import { Getter } from 'vuex-class'
import { SingleTodo } from '../SingleTodo'
const namespace: string = 'Todos'
@Component({
components: { SingleTodo },
filters: {
capitalize(value) {
return tools.capitalize(value)
}
}
})
export default class CTodo extends Vue {
public $q: any
public todotop: string = ''
public todobottom: string = ''
public polling = null
public service: any
public scrollable = true
public dragname: string = 'first'
@Prop({ required: true }) public categoryAtt: string
@Prop({ required: true }) public title: string
@Prop({ required: false, default: 'blue' }) public forecolor: string
@Prop({ required: false, default: 'lightblue' }) public backcolor: string
@Prop({ required: false, default: true }) public viewtaskTop: boolean
public $refs: {
single: SingleTodo[]
}
get tools() {
return tools
}
get showtype() {
return Todos.state.showtype
}
set showtype(value) {
console.log('showtype', value)
GlobalStore.mutations.setShowType(value)
}
get doneTodosCount() {
return Todos.getters.doneTodosCount(this.categoryAtt)
}
get menuPopupConfigTodo() {
return tools.menuPopupConfigTodo[UserStore.state.lang]
}
get listOptionShowTask() {
return tools.listOptionShowTask[UserStore.state.lang]
}
get TodosCount() {
return Todos.getters.TodosCount(this.categoryAtt)
}
@Getter('items_dacompletare', { namespace })
public items_dacompletare: (state: ITodosState, category: string) => ITodo[]
@Getter('todos_completati', { namespace })
public todos_completati: (state: ITodosState, category: string) => ITodo[]
public showTask(field_value) {
return field_value === tools.MenuAction.SHOW_TASK
}
public async onEndtodo(itemdragend) {
await Todos.actions.swapElems(itemdragend)
}
public created() {
const $service = this.$dragula.$service
tools.dragula_option($service, this.dragname)
$service.eventBus.$on('dragend', (args) => {
const itemdragend: IDrag = {
category: this.categoryAtt,
newIndex: this.getElementIndex(args.el),
oldIndex: this.getElementOldIndex(args.el)
}
this.onEndtodo(itemdragend)
})
$service.eventBus.$on('drag', (el, source) => {
this.scrollable = false
})
$service.eventBus.$on('drop', (el, source) => {
this.scrollable = true
})
this.load()
}
public mounted() {
tools.touchmove(this.scrollable)
}
public load() {
console.log('LOAD TODO....')
// Set last category selected
localStorage.setItem(tools.localStorage.categorySel, this.categoryAtt)
this.checkUpdate_everytime()
}
// Call to check if need to refresh
public checkUpdate_everytime() {
this.polling = setInterval(() => {
this.checkUpdate()
}, tools.NUMSEC_CHECKUPDATE)
}
public beforeDestroy() {
clearInterval(this.polling)
}
public mydeleteitemtodo(idobj: string) {
// console.log('mydeleteitemtodo', idobj)
return Todos.actions.deleteItemtodo({ cat: this.categoryAtt, idobj })
}
public async dbInsert(atfirst: boolean = false) {
let descr = this.todobottom.trim()
if (atfirst) {
descr = this.todotop.trim()
}
if (descr === '') {
return
}
if (!tools.checkIfUserExist(this)) {
return
}
const myobj: ITodo = {
descr,
category: this.categoryAtt
}
// empty the field
if (atfirst) {
this.todotop = ''
}
else {
this.todobottom = ''
}
return await Todos.actions.dbInsert({ myobj, atfirst })
}
public async updateitemtodo({ myitem, field }) {
console.log('calling MODIFY updateitemtodo', myitem, field)
const itemdragend: IDrag = {
category: this.categoryAtt,
field,
idelemtochange: myitem._id,
prioritychosen: myitem.priority,
atfirst: false
}
await Todos.actions.swapElems(itemdragend)
await Todos.actions.modify({ myitem, field })
}
public deselectAllRowsproj(item: IProject, check, onlythis: boolean = false) {
this.$emit('deselectAllRowsproj', item, check, onlythis)
}
public setitemsel(item: ITodo) {
this.$emit('setitemsel', item)
}
public deselectAllRowstodo(item: ITodo, check, onlythis: boolean = false) {
console.log('CTODO deselectAllRowstodo : ', item)
for (let i = 0; i < this.$refs.single.length; i++) {
const contr = this.$refs.single[i] as SingleTodo
// @ts-ignore
const id = contr.itemtodo._id
// Don't deselect the actual clicked!
let des = false
if (onlythis) {
des = item._id === id
} else {
if (!!check) {
des = ((check && (item._id !== id)) || (!check))
} else {
des = !check
}
}
if (des) {
// @ts-ignore
contr.deselectAndExitEdit()
}
}
}
public checkUpdate() {
ApiTables.waitAndcheckPendingMsg()
}
private getElementIndex(el: any) {
return [].slice.call(el.parentElement.children).indexOf(el)
}
private getElementOldIndex(el: any) {
return parseInt(el.attributes.index.value, 10)
}
}

View File

@@ -1,11 +1,12 @@
<template> <template>
<q-page> <q-page>
<div class="panel"> <div class="panel">
<div class="divtitlecat"> <div v-if="!!title" class="divtitlecat">
<div class="flex-container"> <div class="flex-container">
<div class="flex-item categorytitle">{{categoryAtt | capitalize}}</div> <div class="flex-item categorytitle" :style="`background-color: ${backcolor} !important; color: ${forecolor} !important;`">{{title | capitalize}}</div>
<div class="flex-item"> <div class="flex-item">
<q-btn push <q-btn push
size="sm"
icon="settings"> icon="settings">
<q-menu id="popconfig" self="top right"> <q-menu id="popconfig" self="top right">
<q-list link separator no-border class="todo-menu"> <q-list link separator no-border class="todo-menu">
@@ -51,10 +52,10 @@
</div> </div>
</div> </div>
<q-input ref="insertTask" color="blue-12" v-model="todotop" :label="$t('todo.inserttop')" <q-input v-if="viewtaskTop" ref="insertTask" color="blue-12" v-model="todotop" :label="$t('todo.inserttop')"
style="margin-left: 6px;" style="margin-left: 6px;"
:after="[{icon: 'arrow_forward', content: true, handler () {}}]" :after="[{icon: 'arrow_forward', content: true, handler () {}}]"
v-on:keyup.enter="insertTodo(true)"> v-on:keyup.enter="dbInsert(true)">
<template v-slot:prepend> <template v-slot:prepend>
<q-icon name="add"/> <q-icon name="add"/>
</template> </template>
@@ -63,22 +64,22 @@
<div style="display: none">{{ prior = 0, priorcomplet = false }}</div> <div style="display: none">{{ prior = 0, priorcomplet = false }}</div>
<div> <div>
<!--<q-infinite-scroll :handler="loadMoreTodo" :offset="7">--> <!--<q-infinite-scroll :handler="loadMoreTodo" :offset="7">-->
<div class="container" v-dragula="todos_dacompletare(categoryAtt)" drake="first"> <div class="container" v-dragula="items_dacompletare(categoryAtt)" :drake="dragname">
<div :id="getmyid(mytodo._id)" :index="index" <div :id="tools.getmyid(mytodo._id)" :index="index"
v-for="(mytodo, index) in todos_dacompletare(categoryAtt)" v-for="(mytodo, index) in items_dacompletare(categoryAtt)"
:key="mytodo._id" class="myitemdrag"> :key="mytodo._id" class="myitemdrag">
<div v-if="(prior !== mytodo.priority) && !mytodo.completed" <div v-if="(prior !== mytodo.priority) && mytodo.statustodo !== tools.Status.COMPLETED"
:class="getTitlePriority(mytodo.priority)"> :class="tools.getTitlePriority(mytodo.priority)">
<label>{{getPriorityByInd(mytodo.priority)}}</label> <label>{{tools.getPriorityByInd(mytodo.priority)}}</label>
</div> </div>
<SingleTodo ref="single" @deleteItem="mydeleteItem(mytodo._id)" @eventupdate="updateitem" <SingleTodo ref="single" @deleteItemtodo="mydeleteitemtodo(mytodo._id)" @eventupdate="updateitemtodo"
@deselectAllRows="deselectAllRows" @onEnd="onEnd" @setitemsel="setitemsel" @deselectAllRowstodo="deselectAllRowstodo" @deselectAllRowsproj="deselectAllRowsproj" @onEnd="onEndtodo"
:itemtodo='mytodo'/> :itemtodo='mytodo'/>
<!--<div :name="`REF${index}`" class="divdrag non-draggato"></div>--> <!--<div :nametranslate="`REF${index}`" class="divdrag non-draggato"></div>-->
<div style="display: none">{{ prior = mytodo.priority, priorcomplet = mytodo.completed }} <div style="display: none">{{ prior = mytodo.priority, priorcomplet = (mytodo.statustodo === tools.Status.COMPLETED) }}
</div> </div>
</div> </div>
</div> </div>
@@ -90,17 +91,17 @@
<!--<q-infinite-scroll :handler="loadMoreTodo" :offset="7">--> <!--<q-infinite-scroll :handler="loadMoreTodo" :offset="7">-->
<div class="container"> <div class="container">
<div :id="getmyid(mytodo._id)" :index="index" <div :id="tools.getmyid(mytodo._id)" :index="index"
v-for="(mytodo, index) in todos_completati(categoryAtt)" v-for="(mytodo, index) in todos_completati(categoryAtt)"
:key="mytodo._id" class="myitemdrag"> :key="mytodo._id" class="myitemdrag">
<SingleTodo ref="single" @deleteItem="mydeleteItem(mytodo._id)" @eventupdate="updateitem" <SingleTodo ref="single" @deleteItemtodo="mydeleteitemtodo(mytodo._id)" @eventupdate="updateitemtodo"
@deselectAllRows="deselectAllRows" @onEnd="onEnd" @setitemsel="setitemsel" @deselectAllRowstodo="deselectAllRowstodo" @deselectAllRowsproj="deselectAllRowsproj" @onEnd="onEndtodo"
:itemtodo='mytodo'/> :itemtodo='mytodo'/>
<!--<div :name="`REF${index}`" class="divdrag non-draggato"></div>--> <!--<div :nametranslate="`REF${index}`" class="divdrag non-draggato"></div>-->
<div style="display: none">{{ prior = mytodo.priority, priorcomplet = mytodo.completed }} <div style="display: none">{{ prior = mytodo.priority, priorcomplet = (mytodo.statustodo === tools.Status.COMPLETED) }}
</div> </div>
</div> </div>
</div> </div>
@@ -108,12 +109,12 @@
</div> </div>
<q-input v-if="TodosCount > 0" ref="insertTaskBottom" v-model="todobottom" <q-input v-if="TodosCount > 0 || !viewtaskTop" ref="insertTaskBottom" v-model="todobottom"
style="margin-left: 6px;" style="margin-left: 6px;"
color="blue-12" color="blue-12"
:label="$t('todo.insertbottom')" :label="$t('todo.insertbottom')"
:after="[{icon: 'arrow_forward', content: true, handler () {}}]" :after="[{icon: 'arrow_forward', content: true, handler () {}}]"
v-on:keyup.enter="insertTodo(false)"/> v-on:keyup.enter="dbInsert(false)"/>
<br> <br>
@@ -147,8 +148,8 @@
</template> </template>
<script lang="ts" src="./todo.ts"> <script lang="ts" src="./CTodo.ts">
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './todo.scss'; @import './CTodo.scss';
</style> </style>

View File

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

View File

@@ -48,7 +48,7 @@ $heightdescr: 20px;
border-width: 1px 0px 1px 0px; border-width: 1px 0px 1px 0px;
border-style: solid; border-style: solid;
border-color: rgba(49, 68, 240, 0.6); border-color: rgba(49, 68, 240, 0.6);
background-color: rgba(83, 132, 250, 0.44) !important; background-color: rgba(160, 174, 255, 0.35) !important;
} }
@@ -115,7 +115,7 @@ $heightdescr: 20px;
@media screen and (min-width: 600px) { @media screen and (min-width: 600px) {
display: none; display: none;
} }
color: #777; color: #939393;
height: $heightitem; height: $heightitem;
line-height: $heightitem; line-height: $heightitem;
//visibility: hidden; //visibility: hidden;
@@ -196,16 +196,6 @@ $heightdescr: 20px;
.colProgress { .colProgress {
} }
.lowperc {
color: red;
}
.medperc {
color: blue;
}
.highperc {
color: green;
}
.percompleted { .percompleted {
color: $colcompleted color: $colcompleted
} }
@@ -218,7 +208,7 @@ $heightdescr: 20px;
} }
.data-item { .data-item {
max-width: 78px; max-width: 100px;
@media (max-width: 600px) { @media (max-width: 600px) {
max-width: 22px; max-width: 22px;
} }

View File

@@ -10,9 +10,10 @@ import { SubMenus } from '../SubMenus'
import { date } from 'quasar' import { date } from 'quasar'
import { askConfirm } from '../../../classes/routinestd' import { askConfirm } from '../../../classes/routinestd'
import { CDate } from '../../CDate'
@Component({ @Component({
components: { SubMenus }, components: { SubMenus, CDate },
name: 'SingleTodo' name: 'SingleTodo'
}) })
export default class SingleTodo extends Vue { export default class SingleTodo extends Vue {
@@ -22,7 +23,7 @@ export default class SingleTodo extends Vue {
public classCompleted: string = '' public classCompleted: string = ''
public classDescr: string = '' public classDescr: string = ''
public classDescrEdit: string = '' public classDescrEdit: string = ''
public classExpiring: string = 'flex-item data-item shadow-1' public classExpiring: string = 'flex-item data-item shadow-1 hide-if-small'
public classExpiringEx: string = '' public classExpiringEx: string = ''
public iconPriority: string = '' public iconPriority: string = ''
public popover: boolean = false public popover: boolean = false
@@ -42,11 +43,11 @@ export default class SingleTodo extends Vue {
public $q: any public $q: any
@Prop({ required: true }) public itemtodo: ITodo get tools() {
return tools
}
// @Watch('itemtodo.completed') valueChanged() { @Prop({ required: true }) public itemtodo: ITodo
// this.watchupdate('completed')
// }
@Watch('itemtodo.enableExpiring') public valueChanged4() { @Watch('itemtodo.enableExpiring') public valueChanged4() {
this.watchupdate('enableExpiring') this.watchupdate('enableExpiring')
@@ -62,6 +63,33 @@ export default class SingleTodo extends Vue {
@Watch('itemtodo.descr') public valueChanged5() { @Watch('itemtodo.descr') public valueChanged5() {
this.precDescr = this.itemtodo.descr this.precDescr = this.itemtodo.descr
this.watchupdate('descr')
}
@Watch('itemtodo.hoursplanned') public valueChangedhoursplanned() {
console.log('itemtodo.hoursplanned', this.itemtodo.hoursplanned)
this.watchupdate('hoursplanned')
}
@Watch('itemtodo.statustodo') public valueChangedstatus() {
console.log('itemtodo.statustodo', this.itemtodo.statustodo)
this.watchupdate('statustodo')
}
@Watch('itemtodo.completed_at') public valueChangedcompleted_at() {
console.log('itemtodo.completed_at', this.itemtodo.completed_at)
this.watchupdate('completed_at')
}
@Watch('itemtodo.hoursworked') public valueChangedhoursworked() {
console.log('itemtodo.hoursworked', this.itemtodo.hoursworked)
this.watchupdate('hoursworked')
}
@Watch('itemtodo.start_date') public valueChangedstart_date() {
this.watchupdate('start_date')
}
@Watch('itemtodo.assigned_to_userId') public valueChangedend_assigned_to_userId() {
this.watchupdate('assigned_to_userId')
}
@Watch('itemtodo.phase') public valueChangedend_phase() {
this.watchupdate('phase')
} }
@Watch('itemtodo.progress') public valueChanged6() { @Watch('itemtodo.progress') public valueChanged6() {
@@ -93,6 +121,7 @@ export default class SingleTodo extends Vue {
} }
public watchupdate(field = '') { public watchupdate(field = '') {
console.log('watchupdate', field)
this.$emit('eventupdate', {myitem: this.itemtodo, field } ) this.$emit('eventupdate', {myitem: this.itemtodo, field } )
this.updateicon() this.updateicon()
} }
@@ -110,9 +139,9 @@ export default class SingleTodo extends Vue {
if (this.itemtodo.progress > 100) if (this.itemtodo.progress > 100)
this.itemtodo.progress = 100 this.itemtodo.progress = 100
this.classExpiring = 'flex-item data-item shadow-1' this.classExpiring = 'flex-item data-item shadow-1 hide-if-small'
this.classExpiringEx = '' this.classExpiringEx = ''
if (this.itemtodo.completed) { if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
this.percentageProgress = 100 this.percentageProgress = 100
this.classCompleted += ' icon_completed' this.classCompleted += ' icon_completed'
this.classDescr += ' status_completed' this.classDescr += ' status_completed'
@@ -126,27 +155,22 @@ export default class SingleTodo extends Vue {
this.menuProgress = 'menuProgress' this.menuProgress = 'menuProgress'
this.percProgress = 'percProgress' this.percProgress = 'percProgress'
let mycolcl = '' let mycolcl = ' ' + tools.getProgressClassColor(this.itemtodo.progress)
if (this.itemtodo.progress < 33) { this.colProgress = tools.getProgressColor(this.itemtodo.progress)
mycolcl = ' lowperc'
} else if (this.itemtodo.progress < 66) {
mycolcl = ' medperc'
} else {
mycolcl = ' highperc'
}
if (this.itemtodo.completed) { if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
mycolcl = ' percompleted' mycolcl = ' percompleted'
this.colProgress = 'gray'
} }
this.colProgress = mycolcl this.colProgress = tools.getProgressColor(this.itemtodo.progress)
this.menuProgress += mycolcl this.menuProgress += mycolcl
this.percProgress += mycolcl this.percProgress += mycolcl
this.clButtPopover = this.sel ? 'pos-item-popover comp_selected' : 'pos-item-popover' this.clButtPopover = this.sel ? 'pos-item-popover comp_selected' : 'pos-item-popover'
if (!this.itemtodo.completed) { if (this.itemtodo.statustodo !== tools.Status.COMPLETED) {
this.clButtPopover += ' pos-item-popover_cursor' this.clButtPopover += ' pos-item-popover_cursor'
} }
@@ -174,10 +198,6 @@ export default class SingleTodo extends Vue {
} }
public getstrDate(mytimestamp) {
return date.formatDate(mytimestamp, 'DD-MM-YY')
}
public created() { public created() {
this.precDescr = this.itemtodo.descr this.precDescr = this.itemtodo.descr
this.updateicon() this.updateicon()
@@ -197,7 +217,8 @@ export default class SingleTodo extends Vue {
if (!this.sel) { if (!this.sel) {
if (!this.inEdit) { if (!this.inEdit) {
this.$emit('deselectAllRows', this.itemtodo, true) this.$emit('deselectAllRowsproj', null, false, false)
this.$emit('deselectAllRowstodo', this.itemtodo, true)
if (!this.sel) { if (!this.sel) {
this.selectRiga() this.selectRiga()
@@ -240,11 +261,13 @@ export default class SingleTodo extends Vue {
} }
public clickRow() { public clickRow() {
this.$emit('setitemsel', null)
this.$emit('setitemsel', this.itemtodo)
this.clickRiga() this.clickRiga()
} }
public editTodo() { public editTodo() {
if (!this.itemtodo.completed) { if (this.itemtodo.statustodo !== tools.Status.COMPLETED) {
// console.log('INIZIO - editTodo') // console.log('INIZIO - editTodo')
this.$emit('click') this.$emit('click')
this.precDescr = this.itemtodo.descr this.precDescr = this.itemtodo.descr
@@ -271,7 +294,7 @@ export default class SingleTodo extends Vue {
theField = this.$refs[elem] as HTMLInputElement theField = this.$refs[elem] as HTMLInputElement
} }
if (theField !== undefined) { if (!!theField) {
theField.focus() theField.focus()
} }
// console.log('focus()') // console.log('focus()')
@@ -285,8 +308,9 @@ export default class SingleTodo extends Vue {
} }
// console.log('exitEdit') // console.log('exitEdit')
this.inEdit = false this.inEdit = false
this.updateClasses this.updateClasses()
this.$emit('deselectAllRows', this.itemtodo, false, singola) this.$emit('deselectAllRowsproj', null, false, false)
this.$emit('deselectAllRowstodo', this.itemtodo, false, singola)
} }
} }
@@ -369,9 +393,9 @@ export default class SingleTodo extends Vue {
this.updateClasses() this.updateClasses()
} }
public aggiornaProgress(value, initialval){ public aggiornaProgress(value, initialval) {
if (value !== initialval) { if (value !== initialval) {
this.itemtodo.progress = value this.itemtodo.progress = parseInt(value, 10)
this.updatedata('progress') this.updatedata('progress')
this.deselectAndExitEdit() this.deselectAndExitEdit()
} }
@@ -379,11 +403,12 @@ export default class SingleTodo extends Vue {
public setCompleted() { public setCompleted() {
// console.log('setCompleted') // console.log('setCompleted')
this.itemtodo.completed = !this.itemtodo.completed if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
this.itemtodo.statustodo = tools.Status.OPENED
this.updateicon() } else {
this.itemtodo.statustodo = tools.Status.COMPLETED
this.updatedata('completed') }
this.watchupdate('statustodo')
this.deselectAndExitEdit() this.deselectAndExitEdit()
} }
@@ -396,20 +421,20 @@ export default class SingleTodo extends Vue {
public updateicon() { public updateicon() {
// console.log('updateicon') // console.log('updateicon')
if (this.itemtodo.completed) { if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
this.iconCompleted = 'check_circle' this.iconCompleted = 'check_circle'
} }
else { else {
this.iconCompleted = 'check_circle_outline' this.iconCompleted = 'check_circle_outline'
} }
if (this.itemtodo.priority === tools.Todos.PRIORITY_HIGH) { if (this.itemtodo.priority === tools.Priority.PRIORITY_HIGH) {
this.iconPriority = 'expand_less' this.iconPriority = 'expand_less'
} // expand_less } // expand_less
else if (this.itemtodo.priority === tools.Todos.PRIORITY_NORMAL) { else if (this.itemtodo.priority === tools.Priority.PRIORITY_NORMAL) {
this.iconPriority = 'remove' this.iconPriority = 'remove'
} }
else if (this.itemtodo.priority === tools.Todos.PRIORITY_LOW) { else if (this.itemtodo.priority === tools.Priority.PRIORITY_LOW) {
this.iconPriority = 'expand_more' this.iconPriority = 'expand_more'
} // expand_more } // expand_more
@@ -417,7 +442,7 @@ export default class SingleTodo extends Vue {
} }
public removeitem(id) { public removeitem(id) {
this.$emit('deleteItem', id) this.$emit('deleteItemtodo', id)
} }
public enableExpiring() { public enableExpiring() {
@@ -458,7 +483,26 @@ export default class SingleTodo extends Vue {
const cancelstr = this.$t('dialog.cancel') const cancelstr = this.$t('dialog.cancel')
const msg = this.$t('dialog.msg.deleteTask', {mytodo : this.itemtodo.descr }) const msg = this.$t('dialog.msg.deleteTask', {mytodo : this.itemtodo.descr })
await askConfirm(this.$q, this.$t('dialog.msg.titledeleteTask'), msg, deletestr, cancelstr)
this.$q.dialog({
cancel: {
label: cancelstr
},
message: msg,
ok: {
label: deletestr,
push: true
},
title: this.$t('dialog.msg.titledeleteTask')
}).onOk(() => {
console.log('OK')
this.removeitem(this.itemtodo._id)
}).onCancel(() => {
console.log('CANCEL')
})
/*
// return await askConfirm(this.$q, this.$t('dialog.msg.titledeleteTask'), msg, deletestr, cancelstr)
.then((ris) => { .then((ris) => {
console.log('ris', ris) console.log('ris', ris)
if (ris) { if (ris) {
@@ -467,6 +511,7 @@ export default class SingleTodo extends Vue {
}).catch((err) => { }).catch((err) => {
}) })
*/
} }
} }

View File

@@ -4,12 +4,12 @@
<q-btn push flat <q-btn push flat
:class="classCompleted" :class="classCompleted"
:icon="iconCompleted" :icon="iconCompleted"
@click.native="setCompleted"> @click="setCompleted">
</q-btn> </q-btn>
</div> </div>
<div class="flex-item donotdrag divdescrTot"> <div class="flex-item donotdrag divdescrTot">
<q-input v-if="sel && !itemtodo.completed" hide-underline type="textarea" ref="inputdescr" <q-input v-if="sel && itemtodo.statustodo !== tools.Status.COMPLETED" hide-underline type="textarea" ref="inputdescr"
v-model.trim="precDescr" v-model.trim="precDescr"
autogrow autogrow
borderless borderless
@@ -56,45 +56,21 @@
<div v-if="itemtodo.enableExpiring" :class="classExpiring"> <div v-if="itemtodo.enableExpiring" :class="classExpiring">
<span class="data_string">{{getstrDate(itemtodo.expiring_at)}}</span> <CDate :mydate="itemtodo.expiring_at" @input="itemtodo.expiring_at = new Date(arguments[0])"
<q-icon name="event" class="cursor-pointer" style="padding: 2px;"> data_class="data_string">
<q-popup-proxy> </CDate>
<q-date v-model="itemtodo.expiring_at" today-btn/>
</q-popup-proxy>
</q-icon>
<!--<q-icon name="event" class="cursor-pointer" />-->
<!--<q-popup-edit v-model="itemtodo.expiring_at"-->
<!--title="Edit"-->
<!--buttons class="">-->
<!--<q-input-->
<!--filled-->
<!--v-model="itemtodo.expiring_at"-->
<!--type="date"-->
<!--class="myexpired"-->
<!--format="DD/MM/YYYY"-->
<!--&gt;-->
<!--</q-input>-->
<!--</q-popup-edit>-->
</div> </div>
<div v-if="isTodo()" class="flex-item pos-item " @mousedown="clickRiga"> <div v-if="isTodo()" class="flex-item pos-item " @mousedown="clickRiga">
<q-btn push <q-btn flat
:class="clButtPopover" :class="clButtPopover"
icon="menu"> icon="menu">
<q-menu id="popmenu" v-if="true" self="top right"> <q-menu ref="popmenu" self="top right">
<SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu" <SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu"
@setPriority="setPriority"></SubMenus> @setPriority="setPriority"></SubMenus>
</q-menu> </q-menu>
</q-btn> </q-btn>
</div> </div>
<!--clButtPopover: {{ clButtPopover }}-->
<!--Sel: {{ sel }}-->
<!--<div class="flex-item btn-item">-->
<!--{{itemtodo.expiring_at}}-->
<!--</div>-->
<!--<div class="flex-item btn-item">-->
<!--<q-btn class="mybtn" round color="" icon="delete" @click.native="removeitem(itemtodo._id)"></q-btn>-->
<!--</div>-->
</div> </div>
</template> </template>

View File

@@ -1,14 +1,13 @@
<template> <template>
<div>
<q-list separator no-border class="todo-menu"> <q-list separator no-border class="todo-menu">
<div v-for="field in menuPopupTodo" :key="field.value"> <div v-for="field in menuPopupTodo" :key="field.value">
<q-item clickable v-if="(field.value !== 130) && (field.value !== 100)" :icon="field.icon" <q-item v-close-popup clickable v-if="(field.value !== 130) && (field.value !== 120)" :icon="field.icon"
@click.native="clickMenu(field.value)"> @click="clickMenu(field.value)">
<q-item-section avatar> <q-item-section avatar>
<q-icon :name="field.icon"/> <q-icon :name="field.icon"/>
</q-item-section> </q-item-section>
<q-item-section v-if="field.value !== 120" label class="item-menu"> <q-item-section label class="item-menu">
<q-item-label>{{field.label}}</q-item-label> <q-item-label>{{field.label}}</q-item-label>
</q-item-section> </q-item-section>
@@ -16,11 +15,16 @@
<q-checkbox v-model="itemtodo.enableExpiring"/> <q-checkbox v-model="itemtodo.enableExpiring"/>
</q-item-section> </q-item-section>
<q-item-section side v-if="field.value === 110"> <q-item-section side v-if="field.value === 110">
<q-checkbox v-model="itemtodo.completed"/> <q-checkbox v-model="itemtodo.statustodo"/>
</q-item-section>
</q-item>
<q-item clickable v-if="(field.value === 120)" :icon="field.icon"
@click="clickMenu(field.value)">
<q-item-section avatar>
<q-icon :name="field.icon"/>
</q-item-section> </q-item-section>
<q-item-section>
<q-item-section v-if="field.value === 120">
<q-slider label <q-slider label
:class="$parent.menuProgress" :class="$parent.menuProgress"
v-model="itemtodo.progress" v-model="itemtodo.progress"
@@ -30,21 +34,12 @@
/> />
</q-item-section> </q-item-section>
<q-item-section side v-if="field.value === 120"> <q-item-section side>
<div> <div>
<q-item-label style="color: blue">{{itemtodo.progress}} %</q-item-label> <q-item-label style="color: blue">{{itemtodo.progress}} %</q-item-label>
</div> </div>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-item v-if="(field.value === 100)" :icon="field.icon"
@click.native="clickMenu(field.value)">
<q-item-section avatar>
<q-icon :name="field.icon" inverted color="primary"/>
</q-item-section>
<q-item-section class="item-menu">
{{field.label}}
</q-item-section>
</q-item>
<q-item clickable v-if="(field.value === 130)"> <q-item clickable v-if="(field.value === 130)">
<q-item-section avatar> <q-item-section avatar>
<q-icon name="priority_high" inverted color="primary"/> <q-icon name="priority_high" inverted color="primary"/>
@@ -80,12 +75,11 @@
</q-item> </q-item>
</div> </div>
</q-list> </q-list>
</div>
</template> </template>
<script lang="ts" src="./SubMenus.ts"> <script lang="ts" src="./SubMenus.ts">
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
@import './SubMenus.scss'; @import './SubMenus.scss';
</style> </style>

View File

@@ -1,3 +1,3 @@
export * from './SingleTodo' export * from './SingleTodo'
export * from './SubMenus' export * from './SubMenus'
export * from './todo' export * from './CTodo'

View File

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

View File

@@ -1,461 +0,0 @@
import Vue from 'vue'
import { Component, Watch } from 'vue-property-decorator'
import { ICfgServer, IDrag, IGlobalState, ITodo, ITodosState } from '@src/model'
import { SingleTodo } from '../SingleTodo'
import { tools } from '../../../store/Modules/tools'
import { GlobalStore, Todos } from '@store'
import { UserStore } from '@store'
// _.cloneDeep( Per clonare un oggetto
import { costanti } from '@src/store/Modules/costanti'
import { Getter, Mutation, State } from 'vuex-class'
const namespace: string = 'Todos'
import globalroutines from './../../../globalroutines/index'
@Component({
components: { SingleTodo },
filters: {
capitalize(value) {
if (!value) { return '' }
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
export default class Todo extends Vue {
get showtype() {
return Todos.state.showtype
}
set showtype(value) {
console.log('showtype', value)
GlobalStore.mutations.setShowType(value)
}
get doneTodosCount() {
return Todos.getters.doneTodosCount(this.categoryAtt)
}
get menuPopupConfigTodo() {
return tools.menuPopupConfigTodo[UserStore.state.lang]
}
get listOptionShowTask() {
return tools.listOptionShowTask[UserStore.state.lang]
}
get TodosCount() {
return Todos.getters.TodosCount(this.categoryAtt)
}
get todos_vista() {
let mystr = ''
const arr = Todos.getters.todos_dacompletare(this.categoryAtt)
for (const ind in arr) {
mystr += this.getstrelem(arr[ind]) + '\n'
}
return mystr + ''
}
// get mytodos_dacompletare() {
// return todos_dacompletare(this.categoryAtt)
// }
// @Watch('$route', { immediate: true, deep: true })
// onUrlChange(newVal: any) {
// // Some action
// }
// Computed:
get reload_fromServer() {
return Todos.state.reload_fromServer
}
set reload_fromServer(value: number) {
Todos.state.reload_fromServer = value
}
public $q: any
public filter: boolean = false
public title: string = ''
public todotop: string = ''
public todobottom: string = ''
public drag: boolean = true
public startpos: number = 0
public listPriorityLabel: number[] = []
public arrPrior: number[] = []
public itemDragStart: any = null
public polling = null
public loadDone: boolean = false
public inddragging: number = -1
public service: any
public actualMaxPosition: number = 15
public scrollable = true
public tmpstrTodos: string = ''
public categoryAtt: string = ''
// public showtype: number = Todos.state.showtype
public $refs: {
single: SingleTodo[]
}
@Getter('todos_dacompletare', { namespace })
public todos_dacompletare: (state: ITodosState, category: string) => ITodo[]
@Getter('todos_completati', { namespace })
public todos_completati: (state: ITodosState, category: string) => ITodo[]
@Watch('$route.params.category') public changecat() {
this.categoryAtt = this.$route.params.category
}
// clickaggshowtype () {
// console.log('1B) clickaggshowtype Todos.state.showtype=', Todos.state.showtype)
// Todos.state.showtype = costanti.ShowTypeTask.SHOW_ALL
// console.log('2B) Dopo: showtype=', this.showtype)
// }
public loadval(e) {
console.log('1) loadval, showtype=', this.showtype)
this.showtype = Todos.state.showtype
console.log('2) Dopo: showtype=', this.showtype)
}
public getmyid(id) {
return 'row' + id
}
public showTask(field_value) {
return field_value === tools.MenuAction.SHOW_TASK
}
public onStart() {
this.startpos = 0
this.itemDragStart = null
}
public logelem(mystr, elem) {
console.log(mystr, 'elem [', elem._id, '] ', elem.descr, ' Pr(', this.getPriorityByInd(elem.priority), ') [', elem.id_prev, '] modif=', elem.modified)
}
public getstrelem(elem) {
return 'elem [' + elem._id + '] ' + elem.descr + ' Pr(' + this.getPriorityByInd(elem.priority) + ') [ID_PREV=' + elem.id_prev + '] modif=' + elem.modified + ' '
}
public getTitlePriority(priority) {
let cl = ''
if (priority === tools.Todos.PRIORITY_HIGH) {
cl = 'high_priority'
}
else if (priority === tools.Todos.PRIORITY_NORMAL) {
cl = 'medium_priority'
}
else if (priority === tools.Todos.PRIORITY_LOW) {
cl = 'low_priority'
}
return cl + ' titlePriority'
}
public logga_arr(myarr: ITodo[]) {
let mystr = '\n'
myarr.forEach((item) => {
mystr += '[' + item.pos + '] ' + item.descr + ' Pr(' + this.getPriorityByInd(item.priority) + ') [' + item.id_prev + '] modif=' + item.modified + '\n'
// mystr += '[' + item.pos + '] ' + item.descr + '\n'
})
return mystr
}
public async onEnd(itemdragend) {
console.log('************ END DRAG: ', itemdragend)
this.inddragging = -1
await Todos.actions.swapElems(itemdragend)
}
public created() {
const $service = this.$dragula.$service
$service.options('first',
{
// isContainer: function (el) {
// return el.classList.contains('dragula-container')
// },
moves(el, source, handle, sibling) {
// console.log('moves')
return !el.classList.contains('donotdrag') // elements are always draggable by default
},
accepts(el, target, source, sibling) {
// console.log('accepts dragging '+ el.id + ' from ' + source.id + ' to ' + target.id)
return true // elements can be dropped in any of the `containers` by default
},
invalid(el, handle) {
// console.log('invalid')
return el.classList.contains('donotdrag') // don't prevent any drags from initiating by default
},
direction: 'vertical'
})
$service.eventBus.$on('dragend', (args) => {
const itemdragend: IDrag = {
category: this.categoryAtt,
newIndex: this.getElementIndex(args.el),
oldIndex: this.getElementOldIndex(args.el)
}
this.onEnd(itemdragend)
})
$service.eventBus.$on('drag', (el, source) => {
// mythis.inddragging = mythis.getElementIndex(el)
console.log('+++ DRAG ind=', this.inddragging)
this.scrollable = false
})
$service.eventBus.$on('drop', (el, source) => {
console.log('+++ DROP')
this.scrollable = true
})
this.load()
}
public mounted() {
// console.log('*** MOUNTED ***')
this.categoryAtt = this.$route.params.category
if (window) {
window.addEventListener('touchmove', (e) => {
// console.log('touchmove')
if (!this.scrollable) {
e.preventDefault()
}
}, { passive: false })
}
}
public setarrPriority() {
this.arrPrior = []
const arr = tools.selectPriority[UserStore.state.lang]
if (arr) {
arr.forEach((rec) => {
this.arrPrior.push(rec.value)
})
}
// console.log('Array PRIOR:', this.arrPrior)
}
public async load() {
console.log('LOAD TODO....')
this.categoryAtt = this.$route.params.category
// Set last category selected
localStorage.setItem(tools.localStorage.categorySel, this.categoryAtt)
for (const todosKey in tools.Todos) {
this.listPriorityLabel.push(tools.Todos[todosKey])
}
// console.log('Priority:' + this.listPriorityLabel)
this.setarrPriority()
this.loadDone = true
this.checkUpdate_everytime()
}
// Call to check if need to refresh
public checkUpdate_everytime() {
this.polling = setInterval(() => {
this.checkUpdate()
}, 60000)
}
public beforeDestroy() {
clearInterval(this.polling)
}
public getPriorityByInd(index) {
// console.log('LANG in PRIOR', UserStore.state.lang)
try {
const arr = tools.selectPriority[UserStore.state.lang]
for (const rec of arr) {
if (rec.value === index) {
return rec.label
}
}
} catch (e) {
}
return ''
}
public isRegistered() {
return localStorage.getItem(tools.localStorage.userId) !== ''
}
public mydeleteItem(idobj: string) {
console.log('mydeleteItem', idobj)
return Todos.actions.deleteItem({ cat: this.categoryAtt, idobj })
}
public insertTodo(atfirst: boolean = false) {
let descr = this.todobottom.trim()
if (atfirst) {
descr = this.todotop.trim()
}
if (descr === '') {
return
}
if (UserStore.state.userId === undefined) {
tools.showNotif(this.$q, this.$t('todo.usernotdefined'))
return
}
if (!this.isRegistered()) {
// Not logged
tools.showNotif(this.$q, this.$t('user.notregistered'))
return
}
const myobj: ITodo = {
descr,
category: this.categoryAtt
}
return Todos.actions.insertTodo({ myobj, atfirst })
.then((data) => {
console.log('data', data)
// if (data !== null) {
// tools.showNotif(this.$q, data)
// }
// empty the field
if (atfirst) {
this.todotop = ''
}
else {
this.todobottom = ''
}
})
}
/*
sendMessageToSW(recdata, method) {
navigator.serviceWorker.controller.postMessage({
type: 'sync',
recdata,
method,
cmd: 'sync-new-todos',
token: UserStore.state.idToken,
lang: UserStore.state.lang
})
}
*/
public async updateitem({ myitem, field }) {
console.log('calling MODIFY updateitem', myitem, field)
// Update the others components...
const itemdragend: IDrag = {
category: this.categoryAtt,
field,
idelemtochange: myitem._id,
prioritychosen: myitem.priority,
atfirst: false
}
await Todos.actions.swapElems(itemdragend)
await Todos.actions.modify({ myitem, field })
}
public deselectAllRows(item: ITodo, check, onlythis: boolean = false) {
// console.log('deselectAllRows : ', item)
for (let i = 0; i < this.$refs.single.length; i++) {
const contr = this.$refs.single[i] as SingleTodo
// @ts-ignore
const id = contr.itemtodo._id
// Don't deselect the actual clicked!
let des = false
if (onlythis) {
des = item._id === id
} else {
des = ((check && (item._id !== id)) || (!check))
}
if (des) {
// @ts-ignore
contr.deselectAndExitEdit()
}
}
}
public checkUpdate() {
Todos.actions.waitAndcheckPendingMsg()
}
public loadMoreTodo(index, done) {
setTimeout(() => {
this.actualMaxPosition += 15
done()
}, 100)
}
public getArrTodos() {
let mystr = ''
this.tmpstrTodos = ''
return globalroutines(null, 'readall', 'todos', null)
.then((alldata) => {
const myrecs = [...alldata]
myrecs.forEach((rec) => {
mystr = mystr + rec.descr + rec.completed + '] ['
})
this.tmpstrTodos = 'TODOS: ' + mystr
})
}
private getElementIndex(el: any) {
return [].slice.call(el.parentElement.children).indexOf(el)
}
private getElementOldIndex(el: any) {
return parseInt(el.attributes.index.value, 10)
}
// setArrTodos() {
//
// let mystr = ''
// let mythis = this
//
// mythis.tmpstrTodos = ''
// return globalroutines(null, 'write', 'todos', this.todos_arr[0])
// .then(function (alldata) {
// mythis.getArrTodos()
// })
// }
//
}

View File

@@ -4,7 +4,7 @@ import Graphql from './graphql'
export default (context, error) => { export default (context, error) => {
/* /*
if (error.constructor.name === 'FirebaseError') { if (error.constructor.nametranslate === 'FirebaseError') {
Firebase(error) Firebase(error)
return return
} }

View File

@@ -1,18 +1,20 @@
import { Todos, UserStore } from '@store' import { Projects, Todos, UserStore } from '@store'
import _ from 'lodash' import _ from 'lodash'
import store, { GlobalStore } from '../store' import { GlobalStore } from '../store/Modules'
import { idbKeyval as storage } from '../js/storage.js' import { idbKeyval as storage } from '../js/storage.js'
import { costanti } from '../store/Modules/costanti' import { costanti } from '../store/Modules/costanti'
import { ICfgData } from '@src/model' import { ICfgData, IGlobalState } from '@src/model'
import { tools } from '@src/store/Modules/tools'
function saveConfigIndexDb(context) { function saveConfigIndexDb(context) {
const data: ICfgData = {} const data: ICfgData = {
data._id = costanti.CONFIG_ID_CFG _id: costanti.CONFIG_ID_CFG,
data.lang = UserStore.state.lang lang: UserStore.state.lang,
data.token = UserStore.state.x_auth_token token: UserStore.state.x_auth_token,
data.userId = UserStore.state.userId userId: UserStore.state.userId
}
writeConfigIndexDb('config', data) writeConfigIndexDb('config', data)
} }
@@ -21,52 +23,54 @@ function writeConfigIndexDb(context, data) {
// console.log('writeConfigIndexDb', data) // console.log('writeConfigIndexDb', data)
storage.setdata('config', data) storage.setdata('config', data)
.then((ris) => {
return true
})
} }
async function readfromIndexDbToStateTodos(context, table) { async function readfromIndexDbToState(context, table) {
console.log('*** readfromIndexDbToStateTodos ***') console.log('*** readfromIndexDbToState ***', table)
return await storage.getalldata(table) return await storage.getalldata(table)
.then((reccat) => { .then((reccat) => {
// console.log('&&&&&&& readfromIndexDbToStateTodos OK: Num RECORD: ', records.length) // console.log('&&&&&&& readfromIndexDbToState OK: Num RECORD: ', records.length)
if (table === 'categories') { if (table === 'categories') {
console.log('reccat', reccat) console.log('reccat', reccat)
Todos.state.categories = [] Todos.state.categories = []
for (const indcat in reccat) { for (const elem of reccat) {
Todos.state.categories.push(reccat[indcat].valore) Todos.state.categories.push(elem.valore)
} }
console.log('ARRAY Categories', Todos.state.categories) console.log('ARRAY Categories', Todos.state.categories)
table = 'todos'
return storage.getalldata('todos') return storage.getalldata(table)
.then((records) => { .then((records) => {
console.log('todos records', records) console.log(table + ' records', records)
// console.log('&&&&&&& readfromIndexDbToStateTodos OK: Num RECORD: ', records.length) // console.log('&&&&&&& readfromIndexDbToState OK: Num RECORD: ', records.length)
/* const arrinit = []
for (const myrec in records) {
const cat = myrec.category for (const mytodo of records) {
const indcat = state.categories.indexOf(cat) const cat = mytodo.category
if (Todos.state.todos[indcat] === undefined) { const indcat = Todos.state.categories.indexOf(cat)
Todos.state.todos[indcat] = {} if (arrinit.indexOf(indcat) < 0) {
Todos.state.todos[indcat] = []
arrinit.push(indcat)
} }
// add to the right array Todos.state.todos[indcat].push(mytodo)
Todos.state.todos[indcat].push(myrec)
} }
*/
console.log('************ ARRAYS SALVATI IN MEMORIA Todos.state.todos ', Todos.state.todos) console.log('************ ARRAYS SALVATI IN MEMORIA ', table, records)
}) })
} else {
const arrris = tools.setArrayMainByTable(table, reccat)
// console.log('************ ARRAYS SALVATI IN MEMORIA ', table, arrris)
} }
}).catch((error) => { }).catch((error) => {
console.log('err: ', error) console.log('err readfromIndexDbToState: ', error)
}) })
} }
@@ -93,8 +97,8 @@ export default async (context, cmd, table, datakey = null, id = '') => {
GlobalStore.state.connData.uploading_indexeddb = 1 GlobalStore.state.connData.uploading_indexeddb = 1
} }
return await storage.setdata(table, datakey) return await storage.setdata(table, datakey)
} else if (cmd === 'updatefromIndexedDbToStateTodo') { } else if (cmd === 'updatefromIndexedDbToState') {
return await readfromIndexDbToStateTodos(context, table) return await readfromIndexDbToState(context, table)
} else if (cmd === 'readall') { } else if (cmd === 'readall') {
if (GlobalStore) { if (GlobalStore) {
GlobalStore.state.connData.downloading_indexeddb = 1 GlobalStore.state.connData.downloading_indexeddb = 1

View File

@@ -1,4 +1,4 @@
import { UserStore } from '../store/Modules' import { UserStore } from '@modules'
import messages from '../statics/i18n' import messages from '../statics/i18n'
function translate(params) { function translate(params) {
@@ -8,7 +8,7 @@ function translate(params) {
const stringa = messages[lang] const stringa = messages[lang]
let ris = stringa let ris = stringa
if (ris !== undefined) { if (!!ris) {
msg.forEach((param) => { msg.forEach((param) => {
ris = ris[param] ris = ris[param]
}) })

64
src/jquery.d.ts vendored
View File

@@ -225,7 +225,7 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
contains(container: Element, contained: Element): boolean contains(container: Element, contained: Element): boolean
css(elem: Element, unknown: any): any css(elem: Element, unknown: any): any
/** /**
* Returns value at named data store for the element, as set by jQuery.data(element, name, value), or * Returns value at named data store for the element, as set by jQuery.data(element, nametranslate, value), or
* the full data store for the element. * the full data store for the element.
* *
* @param element The DOM element to query for the data. * @param element The DOM element to query for the data.
@@ -246,7 +246,7 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
*/ */
data<T>(element: Element, key: string, value: T): T data<T>(element: Element, key: string, value: T): T
/** /**
* Returns value at named data store for the element, as set by jQuery.data(element, name, value), or * Returns value at named data store for the element, as set by jQuery.data(element, nametranslate, value), or
* the full data store for the element. * the full data store for the element.
* *
* @param element The DOM element to query for the data. * @param element The DOM element to query for the data.
@@ -260,7 +260,7 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
* Execute the next function on the queue for the matched element. * Execute the next function on the queue for the matched element.
* *
* @param element A DOM element from which to remove and execute a queued function. * @param element A DOM element from which to remove and execute a queued function.
* @param queueName A string containing the name of the queue. Defaults to fx, the standard effects queue. * @param queueName A string containing the nametranslate of the queue. Defaults to fx, the standard effects queue.
* @see {@link https://api.jquery.com/jQuery.dequeue/} * @see {@link https://api.jquery.com/jQuery.dequeue/}
* @since 1.3 * @since 1.3
*/ */
@@ -695,7 +695,7 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
/** /**
* Create a serialized representation of an array, a plain object, or a jQuery object suitable for use * Create a serialized representation of an array, a plain object, or a jQuery object suitable for use
* in a URL query string or Ajax request. In case a jQuery object is passed, it should contain input * in a URL query string or Ajax request. In case a jQuery object is passed, it should contain input
* elements with name/value properties. * elements with nametranslate/value properties.
* *
* @param obj An array, a plain object, or a jQuery object to serialize. * @param obj An array, a plain object, or a jQuery object to serialize.
* @param traditional A Boolean indicating whether to perform a traditional "shallow" serialization. * @param traditional A Boolean indicating whether to perform a traditional "shallow" serialization.
@@ -2772,14 +2772,14 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
// endregion // endregion
// region (context, name) // region (context, nametranslate)
/** /**
* Takes a function and returns a new one that will always have a particular context. * Takes a function and returns a new one that will always have a particular context.
* *
* @param context The object to which the context of the function should be set. * @param context The object to which the context of the function should be set.
* @param name The name of the function whose context will be changed (should be a property of the context object). * @param name The nametranslate of the function whose context will be changed (should be a property of the context object).
* @param additionalArguments Any number of arguments to be passed to the function named in the name argument. * @param additionalArguments Any number of arguments to be passed to the function named in the nametranslate argument.
* @see {@link https://api.jquery.com/jQuery.proxy/} * @see {@link https://api.jquery.com/jQuery.proxy/}
* @since 1.4 * @since 1.4
* @since 1.6 * @since 1.6
@@ -2796,7 +2796,7 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
* Manipulate the queue of functions to be executed on the matched element. * Manipulate the queue of functions to be executed on the matched element.
* *
* @param element A DOM element where the array of queued functions is attached. * @param element A DOM element where the array of queued functions is attached.
* @param queueName A string containing the name of the queue. Defaults to fx, the standard effects queue. * @param queueName A string containing the nametranslate of the queue. Defaults to fx, the standard effects queue.
* @param newQueue The new function to add to the queue. * @param newQueue The new function to add to the queue.
* An array of functions to replace the current queue contents. * An array of functions to replace the current queue contents.
* @see {@link https://api.jquery.com/jQuery.queue/} * @see {@link https://api.jquery.com/jQuery.queue/}
@@ -3004,7 +3004,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
* *
* @param className One or more space-separated classes to be added to the class attribute of each matched element. * @param className One or more space-separated classes to be added to the class attribute of each matched element.
* A function returning one or more space-separated class names to be added to the existing class * A function returning one or more space-separated class names to be added to the existing class
* name(s). Receives the index position of the element in the set and the existing class name(s) as * nametranslate(s). Receives the index position of the element in the set and the existing class nametranslate(s) as
* arguments. Within the function, this refers to the current element in the set. * arguments. Within the function, this refers to the current element in the set.
* @see {@link https://api.jquery.com/addClass/} * @see {@link https://api.jquery.com/addClass/}
* @since 1.0 * @since 1.0
@@ -3159,7 +3159,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Set one or more attributes for the set of matched elements. * Set one or more attributes for the set of matched elements.
* *
* @param attributeName The name of the attribute to set. * @param attributeName The nametranslate of the attribute to set.
* @param value A value to set for the attribute. If null, the specified attribute will be removed (as in .removeAttr()). * @param value A value to set for the attribute. If null, the specified attribute will be removed (as in .removeAttr()).
* A function returning the value to set. this is the current element. Receives the index position of * A function returning the value to set. this is the current element. Receives the index position of
* the element in the set and the old attribute value as arguments. * the element in the set and the old attribute value as arguments.
@@ -3180,7 +3180,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Get the value of an attribute for the first element in the set of matched elements. * Get the value of an attribute for the first element in the set of matched elements.
* *
* @param attributeName The name of the attribute to get. * @param attributeName The nametranslate of the attribute to get.
* @see {@link https://api.jquery.com/attr/} * @see {@link https://api.jquery.com/attr/}
* @since 1.0 * @since 1.0
*/ */
@@ -3291,7 +3291,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Remove from the queue all items that have not yet been run. * Remove from the queue all items that have not yet been run.
* *
* @param queueName A string containing the name of the queue. Defaults to fx, the standard effects queue. * @param queueName A string containing the nametranslate of the queue. Defaults to fx, the standard effects queue.
* @see {@link https://api.jquery.com/clearQueue/} * @see {@link https://api.jquery.com/clearQueue/}
* @since 1.4 * @since 1.4
*/ */
@@ -3377,7 +3377,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Set one or more CSS properties for the set of matched elements. * Set one or more CSS properties for the set of matched elements.
* *
* @param propertyName A CSS property name. * @param propertyName A CSS property nametranslate.
* @param value A value to set for the property. * @param value A value to set for the property.
* A function returning the value to set. this is the current element. Receives the index position of * A function returning the value to set. this is the current element. Receives the index position of
* the element in the set and the old value as arguments. * the element in the set and the old value as arguments.
@@ -3414,7 +3414,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
css(propertyNames: string[]): JQuery.PlainObject<string> css(propertyNames: string[]): JQuery.PlainObject<string>
/** /**
* Return the value at the named data store for the first element in the jQuery collection, as set by * Return the value at the named data store for the first element in the jQuery collection, as set by
* data(name, value) or by an HTML5 data-* attribute. * data(nametranslate, value) or by an HTML5 data-* attribute.
* *
* @param key Name of the data stored. * @param key Name of the data stored.
* @param undefined * @param undefined
@@ -3441,7 +3441,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
data(obj: JQuery.PlainObject): this data(obj: JQuery.PlainObject): this
/** /**
* Return the value at the named data store for the first element in the jQuery collection, as set by * Return the value at the named data store for the first element in the jQuery collection, as set by
* data(name, value) or by an HTML5 data-* attribute. * data(nametranslate, value) or by an HTML5 data-* attribute.
* *
* @param key Name of the data stored. * @param key Name of the data stored.
* @see {@link https://api.jquery.com/data/} * @see {@link https://api.jquery.com/data/}
@@ -3450,7 +3450,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
data(key: string): any data(key: string): any
/** /**
* Return the value at the named data store for the first element in the jQuery collection, as set by * Return the value at the named data store for the first element in the jQuery collection, as set by
* data(name, value) or by an HTML5 data-* attribute. * data(nametranslate, value) or by an HTML5 data-* attribute.
* *
* @see {@link https://api.jquery.com/data/} * @see {@link https://api.jquery.com/data/}
* @since 1.4 * @since 1.4
@@ -3478,7 +3478,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
* Set a timer to delay execution of subsequent items in the queue. * Set a timer to delay execution of subsequent items in the queue.
* *
* @param duration An integer indicating the number of milliseconds to delay execution of the next item in the queue. * @param duration An integer indicating the number of milliseconds to delay execution of the next item in the queue.
* @param queueName A string containing the name of the queue. Defaults to fx, the standard effects queue. * @param queueName A string containing the nametranslate of the queue. Defaults to fx, the standard effects queue.
* @see {@link https://api.jquery.com/delay/} * @see {@link https://api.jquery.com/delay/}
* @since 1.4 * @since 1.4
*/ */
@@ -3530,7 +3530,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Execute the next function on the queue for the matched elements. * Execute the next function on the queue for the matched elements.
* *
* @param queueName A string containing the name of the queue. Defaults to fx, the standard effects queue. * @param queueName A string containing the nametranslate of the queue. Defaults to fx, the standard effects queue.
* @see {@link https://api.jquery.com/dequeue/} * @see {@link https://api.jquery.com/dequeue/}
* @since 1.2 * @since 1.2
*/ */
@@ -3731,7 +3731,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
* Stop the currently-running animation, remove all queued animations, and complete all animations for * Stop the currently-running animation, remove all queued animations, and complete all animations for
* the matched elements. * the matched elements.
* *
* @param queue The name of the queue in which to stop animations. * @param queue The nametranslate of the queue in which to stop animations.
* @see {@link https://api.jquery.com/finish/} * @see {@link https://api.jquery.com/finish/}
* @since 1.9 * @since 1.9
*/ */
@@ -3824,7 +3824,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Determine whether any of the matched elements are assigned the given class. * Determine whether any of the matched elements are assigned the given class.
* *
* @param className The class name to search for. * @param className The class nametranslate to search for.
* @see {@link https://api.jquery.com/hasClass/} * @see {@link https://api.jquery.com/hasClass/}
* @since 1.2 * @since 1.2
*/ */
@@ -4678,7 +4678,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Set one or more properties for the set of matched elements. * Set one or more properties for the set of matched elements.
* *
* @param propertyName The name of the property to set. * @param propertyName The nametranslate of the property to set.
* @param value A function returning the value to set. Receives the index position of the element in the set and the * @param value A function returning the value to set. Receives the index position of the element in the set and the
* old property value as arguments. Within the function, the keyword this refers to the current element. * old property value as arguments. Within the function, the keyword this refers to the current element.
* @see {@link https://api.jquery.com/prop/} * @see {@link https://api.jquery.com/prop/}
@@ -4688,7 +4688,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Set one or more properties for the set of matched elements. * Set one or more properties for the set of matched elements.
* *
* @param propertyName The name of the property to set. * @param propertyName The nametranslate of the property to set.
* @param value A value to set for the property. * @param value A value to set for the property.
* @see {@link https://api.jquery.com/prop/} * @see {@link https://api.jquery.com/prop/}
* @since 1.6 * @since 1.6
@@ -4705,7 +4705,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Get the value of a property for the first element in the set of matched elements. * Get the value of a property for the first element in the set of matched elements.
* *
* @param propertyName The name of the property to get. * @param propertyName The nametranslate of the property to get.
* @see {@link https://api.jquery.com/prop/} * @see {@link https://api.jquery.com/prop/}
* @since 1.6 * @since 1.6
*/ */
@@ -4714,7 +4714,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
* Add a collection of DOM elements onto the jQuery stack. * Add a collection of DOM elements onto the jQuery stack.
* *
* @param elements An array of elements to push onto the stack and make into a new jQuery object. * @param elements An array of elements to push onto the stack and make into a new jQuery object.
* @param name The name of a jQuery method that generated the array of elements. * @param name The nametranslate of a jQuery method that generated the array of elements.
* @param args The arguments that were passed in to the jQuery method (for serialization). * @param args The arguments that were passed in to the jQuery method (for serialization).
* @see {@link https://api.jquery.com/pushStack/} * @see {@link https://api.jquery.com/pushStack/}
* @since 1.3 * @since 1.3
@@ -4731,7 +4731,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Manipulate the queue of functions to be executed, once for each matched element. * Manipulate the queue of functions to be executed, once for each matched element.
* *
* @param queueName A string containing the name of the queue. Defaults to fx, the standard effects queue. * @param queueName A string containing the nametranslate of the queue. Defaults to fx, the standard effects queue.
* @param newQueue The new function to add to the queue, with a function to call that will dequeue the next item. * @param newQueue The new function to add to the queue, with a function to call that will dequeue the next item.
* An array of functions to replace the current queue contents. * An array of functions to replace the current queue contents.
* @see {@link https://api.jquery.com/queue/} * @see {@link https://api.jquery.com/queue/}
@@ -4750,7 +4750,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Show the queue of functions to be executed on the matched elements. * Show the queue of functions to be executed on the matched elements.
* *
* @param queueName A string containing the name of the queue. Defaults to fx, the standard effects queue. * @param queueName A string containing the nametranslate of the queue. Defaults to fx, the standard effects queue.
* @see {@link https://api.jquery.com/queue/} * @see {@link https://api.jquery.com/queue/}
* @since 1.2 * @since 1.2
*/ */
@@ -4804,7 +4804,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Remove a property for the set of matched elements. * Remove a property for the set of matched elements.
* *
* @param propertyName The name of the property to remove. * @param propertyName The nametranslate of the property to remove.
* @see {@link https://api.jquery.com/removeProp/} * @see {@link https://api.jquery.com/removeProp/}
* @since 1.6 * @since 1.6
*/ */
@@ -5079,7 +5079,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
/** /**
* Stop the currently-running animation on the matched elements. * Stop the currently-running animation on the matched elements.
* *
* @param queue The name of the queue in which to stop animations. * @param queue The nametranslate of the queue in which to stop animations.
* @param clearQueue A Boolean indicating whether to remove queued animation as well. Defaults to false. * @param clearQueue A Boolean indicating whether to remove queued animation as well. Defaults to false.
* @param jumpToEnd A Boolean indicating whether to complete the current animation immediately. Defaults to false. * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately. Defaults to false.
* @see {@link https://api.jquery.com/stop/} * @see {@link https://api.jquery.com/stop/}
@@ -5584,7 +5584,7 @@ declare namespace JQuery {
*/ */
isLocal?: boolean isLocal?: boolean
/** /**
* Override the callback function name in a JSONP request. This value will be used instead of * Override the callback function nametranslate in a JSONP request. This value will be used instead of
* 'callback' in the 'callback=?' part of the query string in the url. So {jsonp:'onJSONPLoad'} would * 'callback' in the 'callback=?' part of the query string in the url. So {jsonp:'onJSONPLoad'} would
* result in 'onJSONPLoad=?' passed to the server. As of jQuery 1.5, setting the jsonp option to false * result in 'onJSONPLoad=?' passed to the server. As of jQuery 1.5, setting the jsonp option to false
* prevents jQuery from adding the "?callback" string to the URL or attempting to use "=?" for * prevents jQuery from adding the "?callback" string to the URL or attempting to use "=?" for
@@ -5594,8 +5594,8 @@ declare namespace JQuery {
*/ */
jsonp?: string | false jsonp?: string | false
/** /**
* Specify the callback function name for a JSONP request. This value will be used instead of the * Specify the callback function nametranslate for a JSONP request. This value will be used instead of the
* random name automatically generated by jQuery. It is preferable to let jQuery generate a unique name * random nametranslate automatically generated by jQuery. It is preferable to let jQuery generate a unique nametranslate
* as it'll make it easier to manage the requests and provide callbacks and error handling. You may * as it'll make it easier to manage the requests and provide callbacks and error handling. You may
* want to specify the callback when you want to enable better browser caching of GET requests. As of * want to specify the callback when you want to enable better browser caching of GET requests. As of
* jQuery 1.5, you can also use a function for this setting, in which case the value of jsonpCallback * jQuery 1.5, you can also use a function for this setting, in which case the value of jsonpCallback
@@ -7436,7 +7436,7 @@ declare namespace JQuery {
/** /**
* A Boolean indicating whether to place the animation in the effects queue. If false, the animation * A Boolean indicating whether to place the animation in the effects queue. If false, the animation
* will begin immediately. As of jQuery 1.7, the queue option can also accept a string, in which case * will begin immediately. As of jQuery 1.7, the queue option can also accept a string, in which case
* the animation is added to the queue represented by that string. When a custom queue name is used the * the animation is added to the queue represented by that string. When a custom queue nametranslate is used the
* animation does not automatically start; you must call .dequeue("queuename") to start it. * animation does not automatically start; you must call .dequeue("queuename") to start it.
*/ */
queue?: boolean | string queue?: boolean | string

View File

@@ -47,7 +47,7 @@
name = String(name) name = String(name)
} }
if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
throw new TypeError('Invalid character in header field name') throw new TypeError('Invalid character in header field nametranslate')
} }
return name.toLowerCase() return name.toLowerCase()
} }

View File

@@ -1,6 +1,7 @@
import * as ApiTables from '@src/store/Modules/ApiTables'
export let idbKeyval = (() => { export let idbKeyval = (() => {
let db; let db;
const fieldsData = ['completed_at', 'created_at', 'expiring_at', 'modify_at']
function getDB() { function getDB() {
if (!db) { if (!db) {
@@ -14,13 +15,16 @@ export let idbKeyval = (() => {
openreq.onupgradeneeded = () => { openreq.onupgradeneeded = () => {
// First time setup: create an empty object store // First time setup: create an empty object store
openreq.result.createObjectStore('todos', { keyPath: '_id' }); for (let mytab of ApiTables.MainTables) {
openreq.result.createObjectStore('categories', { keyPath: '_id' }); openreq.result.createObjectStore(mytab, { keyPath: '_id' });
openreq.result.createObjectStore('sync_todos', { keyPath: '_id' }); for (let mymeth of ApiTables.allMethod) {
openreq.result.createObjectStore('sync_todos_patch', { keyPath: '_id' }); const tab = mymeth + mytab
openreq.result.createObjectStore('delete_todos', { keyPath: '_id' }); openreq.result.createObjectStore(tab, { keyPath: '_id' });
openreq.result.createObjectStore('config', { keyPath: '_id' }); }
openreq.result.createObjectStore('swmsg', { keyPath: '_id' }); }
for (let mytab of ApiTables.OtherTables) {
openreq.result.createObjectStore(mytab, { keyPath: '_id' });
}
}; };
openreq.onsuccess = () => { openreq.onsuccess = () => {

View File

@@ -4,7 +4,6 @@ import { UserStore } from '@modules'
import { GlobalStore } from '@modules' import { GlobalStore } from '@modules'
import Vue from 'vue' import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator' import { Component, Prop } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools'
const namespace: string = 'GlobalModule' const namespace: string = 'GlobalModule'

View File

@@ -19,6 +19,13 @@ export default class MenuOne extends Vue {
return GlobalStore.getters.getmenu return GlobalStore.getters.getmenu
} }
public getLabelByItem(item) {
if (!!item.name)
return this.$t(item.name)
else
return item.text
}
public setParentVisibilityBasedOnRoute(parent) { public setParentVisibilityBasedOnRoute(parent) {
parent.routes.forEach((item) => { parent.routes.forEach((item) => {
if (this.$route.path === item.route) { if (this.$route.path === item.route) {

View File

@@ -2,13 +2,13 @@
<div class="no-border"> <div class="no-border">
<q-list class="rounded-borders text-primary"> <q-list class="rounded-borders text-primary">
<template v-for="(parent, index) in getmenu"> <template v-for="(parent, index) in getmenu">
<div class="q-list-header">{{replaceUnderlineToSpace(index)}}</div> <!--<div class="q-list-header">{{replaceUnderlineToSpace(index)}}</div>-->
<div v-for="item in parent.routes"> <div v-for="item in parent.routes">
<div v-if="item.routes2"> <div v-if="item.routes2">
<q-expansion-item <q-expansion-item
:header-inset-level="0.5" :header-inset-level="item.level_parent"
:content-inset-level="0.5" :content-inset-level="item.level_parent"
:label="$t(item.name)" :label="getLabelByItem(item)"
:icon="item.materialIcon" :icon="item.materialIcon"
expand-icon-class="my-menu-separat" expand-icon-class="my-menu-separat"
header-class="my-menu" header-class="my-menu"
@@ -16,12 +16,12 @@
> >
<q-expansion-item v-for="(child2, index) in item.routes2" :to="child2.route" :key="index" <q-expansion-item v-for="(child2, index) in item.routes2" :to="child2.route" :key="index"
:header-inset-level="0.5" :header-inset-level="item.level_child"
:duration="300" :duration="300"
expand-icon="map" expand-icon="map"
active-class="my-menu-active" active-class="my-menu-active"
class="item item-link drawer-closer cursor-pointer my-menu" class="item item-link drawer-closer cursor-pointer my-menu"
:label="$t(child2.name)"> :label="getLabelByItem(child2)">
</q-expansion-item> </q-expansion-item>
</q-expansion-item> </q-expansion-item>

View File

@@ -5,6 +5,7 @@ import { GlobalStore } from '@store'
import { IPost } from '../../../model/index' import { IPost } from '../../../model/index'
import './messagePopover.scss' import './messagePopover.scss'
import { tools } from '@src/store/Modules/tools'
@Component({ @Component({
}) })
@@ -27,7 +28,7 @@ export default class MessagePopover extends Vue {
public randomDate(): Date { public randomDate(): Date {
let myval = Math.floor(Math.random() * 10000000000) let myval = Math.floor(Math.random() * 10000000000)
return new Date(new Date().valueOf() - myval) return new Date(tools.getTimestampsNow() - myval)
} }
public randomAvatarUrl() { public randomAvatarUrl() {

View File

@@ -1,12 +1,12 @@
import { tools } from "../store/Modules/tools"; import { tools } from '../store/Modules/tools'
import { RouteNames } from '../router/route-names' import { RouteNames } from '../router/route-names'
export default function auth({ next, router }) { export default function auth({ next, router }) {
const tok = tools.getItemLS(tools.localStorage.token) const tok = tools.getItemLS(tools.localStorage.token)
if (!tok) { if (!tok) {
return router.push({ name: RouteNames.login }); return router.push({ name: RouteNames.login })
} }
return next(); return next()
} }

View File

@@ -1,5 +1,6 @@
import { costanti } from "@src/store/Modules/costanti" import { costanti } from "@src/store/Modules/costanti"
import { UserStore } from "@store" import { UserStore } from "@store"
import { tools } from '@src/store/Modules/tools'
export interface IPost { export interface IPost {
title: string title: string
@@ -55,13 +56,24 @@ export interface IGlobalState {
connData: IConnData connData: IConnData
posts: IPost[] posts: IPost[]
menulinks: {} menulinks: {}
listatodo: ITodoList[] listatodo: IMenuList[]
arrConfig: IConfig[] arrConfig: IConfig[]
} }
export interface IMenuList {
export interface ITodoList { nametranslate: string
namecat: string
description: string description: string
idelem?: string
icon?: string
} }
export interface IListRoutes {
route: string
faIcon: string
materialIcon: string
name: string
text?: string
routes2: []
level_parent: number
level_child: number
}

41
src/model/Projects.ts Normal file
View File

@@ -0,0 +1,41 @@
import objectId from '@src/js/objectId'
import { UserStore } from '@store'
import { tools } from '@src/store/Modules/tools'
export interface IProject {
_id?: any,
userId?: string
category?: string
id_parent?: string
descr?: string
longdescr?: string
priority?: number
statusproj?: number
created_at?: Date
modify_at?: Date
completed_at?: Date
expiring_at?: Date
enableExpiring?: boolean
id_prev?: string
modified?: boolean
pos?: number
order?: number
live_url?: string
test_url?: string
hoursplanned?: number
hoursworked?: number
progressCalc?: number
begin_development?: Date
hoursweeky_plannedtowork?: number
endwork_estimate?: Date
begin_test?: Date
totalphases?: number
actualphase?: number
}
export interface IProjectsState {
showtype: number
projects: IProject[]
insidePending: boolean
visuLastCompleted: number
}

View File

@@ -4,7 +4,7 @@ export interface ITodo {
category?: string category?: string
descr?: string, descr?: string,
priority?: number, priority?: number,
completed?: boolean, statustodo?: number,
created_at?: Date, created_at?: Date,
modify_at?: Date, modify_at?: Date,
completed_at?: Date, completed_at?: Date,
@@ -15,6 +15,12 @@ export interface ITodo {
pos?: number, pos?: number,
order?: number, order?: number,
progress?: number progress?: number
progressCalc?: number
phase?: number
assigned_to_userId?: string
hoursplanned?: number
hoursworked?: number
start_date?: Date
} }
export interface IParamTodo { export interface IParamTodo {
@@ -31,7 +37,8 @@ export interface IDrag {
prioritychosen?: number prioritychosen?: number
oldIndex?: number oldIndex?: number
newIndex?: number newIndex?: number
category: string category?: string
id_proj?: string
atfirst?: boolean atfirst?: boolean
} }
@@ -41,7 +48,7 @@ export interface ITodosState {
categories: string[] categories: string[]
// todos_changed: number // todos_changed: number
reload_fromServer: number reload_fromServer: number
testpao: String testpao: string
insidePending: boolean insidePending: boolean
visuLastCompleted: number visuLastCompleted: number
} }

View File

@@ -3,7 +3,6 @@ import { IToken } from 'model/other'
export const DefaultUser = <IUserState>{ export const DefaultUser = <IUserState>{
email: '', email: '',
username: '', username: '',
idapp: process.env.APP_ID,
password: '', password: '',
lang: 'it' lang: 'it'
} }
@@ -12,7 +11,6 @@ export interface IUserState {
userId?: string userId?: string
email?: string email?: string
username?: string username?: string
idapp?: any
password?: string password?: string
lang?: string lang?: string
repeatPassword?: string repeatPassword?: string

View File

@@ -7,3 +7,4 @@ export * from './key-value'
export * from './Categories' export * from './Categories'
export * from './Todos' export * from './Todos'
export * from './Projects'

View File

@@ -28,7 +28,6 @@ export default class Home extends Vue {
public visibile: boolean = false public visibile: boolean = false
public cardvisible: string = 'hidden' public cardvisible: string = 'hidden'
public displaycard: string = 'block' public displaycard: string = 'block'
public svgclass: string = 'svgclass'
public $t: any public $t: any
// public firstClassSection: string = 'landing_background fade homep-cover-img animate-fade homep-cover-img-1' // public firstClassSection: string = 'landing_background fade homep-cover-img animate-fade homep-cover-img-1'
public firstClassSection: string = 'fade homep-cover-img animate-fade homep-cover-img-1' public firstClassSection: string = 'fade homep-cover-img animate-fade homep-cover-img-1'

View File

@@ -2,7 +2,12 @@ import Vue from 'vue'
import VueRouter, { RouterMode } from 'vue-router' import VueRouter, { RouterMode } from 'vue-router'
import { PositionResult } from 'vue-router/types/router' import { PositionResult } from 'vue-router/types/router'
import { RouteConfig } from './route-config' import { IMyRoute, IMyRouteRecord, routesList } from './route-config'
import { ProgressBar } from '@src/store/Modules/Interface'
import { isEqual } from 'lodash'
import { UserStore } from '@store'
import { RouteNames } from '@src/router/route-names'
import { tools } from '@src/store/Modules/tools'
Vue.use(VueRouter) Vue.use(VueRouter)
/* /*
@@ -11,8 +16,8 @@ Vue.use(VueRouter)
*/ */
const Router = new VueRouter({ const Router = new VueRouter({
scrollBehavior: () => ({ y: 0 } as PositionResult), scrollBehavior: () => ({ x: 0, y: 0 } as PositionResult),
routes: RouteConfig, routes: routesList,
// Leave these as is and change from quasar.conf.js instead! // Leave these as is and change from quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode // quasar.conf.js -> build -> vueRouterMode
@@ -20,4 +25,159 @@ const Router = new VueRouter({
base: process.env.VUE_ROUTER_BASE base: process.env.VUE_ROUTER_BASE
}) })
function nextFactory(context, middleware, index) {
const subsequentMiddleware = middleware[index]
// If no subsequent Middleware exists,
// the default `next()` callback is returned.
if (!subsequentMiddleware) {
return context.next
}
return (...parameters) => {
// Run the default Vue Router `next()` callback first.
context.next(...parameters)
// Then run the subsequent Middleware with a new
// `nextMiddleware()` callback.
const nextMiddleware = nextFactory(context, middleware, index + 1)
subsequentMiddleware({ ...context, next: nextMiddleware })
}
}
Router.beforeEach(async (to: IMyRoute, from: IMyRoute, next) => {
try {
// Check session
// if (!LoginStore.state.sessionChecked) {
// await LoginStore.actions.checkUserSession();
// }
// console.log(to, from)
if (from.name && from.matched[0].name === to.name && from.meta.isModal) {
next()
console.log('Route interceptor log: <1>')
return
}
else if (from.name === to.name && isEqual(from.params, to.params)) {
console.log('Route interceptor log: <2>')
next()
} else {
if (!to.meta.transparent && !to.meta.isModal) {
console.log('Route interceptor log: <4>')
ProgressBar.mutations.start()
}
else if (to.meta.transparent && !from.name) {
console.log('Route interceptor log: <5>')
ProgressBar.mutations.start()
}
else if (to.meta.transparent && !to.matched.some((m) => m.name === from.name)) {
console.log('Route interceptor log: <6>')
ProgressBar.mutations.start()
}
// If page is initialazed on child
/*
if (to.matched[0] && to.meta.isModal) {
console.log('Route interceptor log: <7>')
if (!from.nametranslate) {
getRouteData(to.matched[0])
GlobalStore.mutations.setPreviousModalRoute(to.matched[0].path)
} else {
GlobalStore.mutations.setPreviousModalRoute(from.fullPath)
}
}
*/
// Check requires auth
if (to.matched.some((m) => m.meta.requiresAuth)) {
// await LoginStore.actions.refreshUserInfos()
if (tools.isLoggedToSystem()) {
if (!!to.meta.asyncData) {
await getRouteData(to)
}
/*
if (to.matched.some((m) => !!m.meta.isAuthorized)) {
const results = await Promise.all([
...to.matched.filter((m) => !!m.meta.isAuthorized)
.map((m) => m.meta.isAuthorized(to))
])
if (!results.every((m) => m)) {
NotificationsStore.actions.addNotification({
type: 'warning',
message: `Vous n'avez pas accès à cette page`
})
ProgressBar.mutations.fail()
if (from.nametranslate) {
return
} else {
next('/')
}
}
}
*/
} else {
// LoginStore.mutations.showLoginRoute(to.fullPath)
if (from.name) {
ProgressBar.mutations.hide()
} else {
// next('/')
}
return Router.push({ name: RouteNames.login })
}
} else if (to.matched.some((m) => m.meta.noAuth) && UserStore.state.isLogged) {
next('/')
} else {
if (!!to.meta.asyncData) {
await getRouteData(to)
}
}
}
// if (to.meta.middleware) {
// const middleware = Array.isArray(to.meta.middleware)
// ? to.meta.middleware
// : [to.meta.middleware]
//
// const context = {
// from,
// next,
// Router,
// to
// }
//
// const nextMiddleware = nextFactory(context, middleware, 1)
//
// return middleware[0]({ ...context, next: nextMiddleware })
// }
//
return next()
}
catch
(err) {
console.log('Route error:', err)
ProgressBar.mutations.fail()
}
}
)
const getRouteData = async (to: IMyRoute | IMyRouteRecord) => {
if (!to.meta.transparent) {
ProgressBar.mutations.start()
}
const titleToDisplay: any = await to.meta.asyncData(to)
// if (to.meta.contentProp) {
// document.title = `${titleToDisplay.title || to.meta.title} - MovingMate`
// }
}
Router.afterEach(async (from: IMyRoute, next) => {
ProgressBar.mutations.finish()
// AlertsStore.mutations.hideAlert()
// EventBus.$emit('closePopups')
})
export default Router export default Router

View File

@@ -1,12 +1,40 @@
import { RouteConfig as VueRouteConfig } from 'vue-router' import { RouteConfig, Route, RouteRecord } from 'vue-router/types'
import { RouteNames } from './route-names' import { RouteNames } from './route-names'
import { tools } from '@src/store/Modules/tools' import { tools } from '@src/store/Modules/tools'
import auth from '../middleware/auth' import auth from '../middleware/auth'
import { Projects, Todos } from "@store"
interface IMyMeta {
title?: string,
headerShadow?: boolean,
contentProp?: boolean,
transparent?: boolean,
isModal?: boolean,
requiresAuth?: boolean,
isTab?: boolean,
noAuth?: boolean,
asyncData?: (to?: IMyRoute | IMyRouteRecord) => Promise<{title?: string} | void>,
isAuthorized?: (to?: any) => boolean
middleware?: any[]
}
export const RouteConfig: VueRouteConfig[] = [ export interface IMyRoute extends Route {
meta: IMyMeta,
matched: IMyRouteRecord[]
}
export interface IMyRouteRecord extends RouteRecord {
meta: IMyMeta,
}
export interface IMyRouteConfig extends RouteConfig {
children?: IMyRouteConfig[],
meta?: IMyMeta
}
export const routesList: IMyRouteConfig[] = [
{ {
path: '/', path: '/',
name: RouteNames.home, name: RouteNames.home,
@@ -30,55 +58,74 @@ export const RouteConfig: VueRouteConfig[] = [
{ {
path: '/todo/:category', path: '/todo/:category',
name: 'Todos', name: 'Todos',
component: () => import('@/components/todos/todo/todo.vue'), component: () => import('@/views/todo-list/todo-list.vue'),
meta: { meta: {
middleware: [auth] requiresAuth: true,
async asyncData() {
await Todos.actions.dbLoad({ checkPending: false })
}
// middleware: [auth]
} }
}, },
{ {
path: '/category', path: '/category',
name: 'category', name: 'category',
component: () => import('@/components/categories/category/category.vue') component: () => import('@/views/categories/category/category.vue')
}, },
{ {
path: '/admin/cfgserv', path: '/admin/cfgserv',
name: 'cfgserv', name: 'cfgserv',
component: () => import('@/components/admin/cfgServer/cfgServer.vue'), component: () => import('@/views/admin/cfgServer/cfgServer.vue'),
meta: { meta: {
middleware: [auth] requiresAuth: true
// middleware: [auth]
} }
}, },
{ {
path: '/admin/testp1/:category', path: '/admin/testp1/:category',
name: 'Categories', name: 'Categories',
component: () => import('@/components/admin/testp1/testp1.vue') component: () => import('@/views/admin/testp1/testp1.vue')
}, },
{ {
path: '/offline', path: '/offline',
name: 'Offline', name: 'Offline',
component: () => import('@/components/offline/offline.vue') component: () => import('@/views/offline/offline.vue')
},
{
path: '/projects/:idProj',
name: 'progetti',
component: () => import('@/views/projects/proj-list/proj-list.vue'),
meta: {
requiresAuth: true,
async asyncData() {
await Projects.actions.dbLoad({ checkPending: false, onlyiffirsttime: true })
} }
// middleware: [auth]
}
}
/* /*
{ {
path: '/requestresetpwd', path: '/requestresetpwd',
component: () => import('@/views/login/requestresetpwd.vue'), component: () => import('@/views/login/requestresetpwd.vue'),
meta: { name: 'Reset your Password' } meta: { nametranslate: 'Reset your Password' }
}, },
{ {
path: '/updatepwd', path: '/updatepwd',
component: () => import('@/views/login/updatepassword.vue'), component: () => import('@/views/login/updatepassword.vue'),
meta: { name: 'Update your Password' } meta: { nametranslate: 'Update your Password' }
} }
{ {
path: '/simpleform', path: '/simpleform',
component: () => import('@/views/form/simpleForm/simpleForm.vue'), component: () => import('@/views/form/simpleForm/simpleForm.vue'),
meta: { name: 'SimpleForm' } meta: { nametranslate: 'SimpleForm' }
}, },
{ {
path: '/embeeded', path: '/embeeded',
component: () => import('@/views/form/embeeded/embeeded.vue'), component: () => import('@/views/form/embeeded/embeeded.vue'),
meta: { name: 'Embeeded' } meta: { nametranslate: 'Embeeded' }
}*/ }*/
] ]

View File

@@ -0,0 +1,184 @@
// Couleurs
$mainStyle: #4975BA;
$mainColor: #3c4858;
$yellow1: #f8ab1c;
$yellow2: rgb(221, 144, 35);
$yellow3: #f8d71c;
$blue1: #4286f4;
$blue2: #a9dff5;
$red1: #c84242;
$orange1: #cf7219;
$rose1: #dd4587;
$green1: #5cb85c;
$green2: #CEE8DF;
$green3: #70BEB1;
$green4: #4c964c;
$brown1: #D99E7E;
:export {
mainStyle: $mainStyle;
red1: $red1;
blue2: $blue2;
yellow1: $yellow1;
yellow2: $yellow2;
yellow3: $yellow3;
mainColor: $mainColor;
green1: $green1;
green2: $green2;
green3: $green3;
}
$w255: rgb(255, 255, 255);
$w250: rgb(250, 250, 250);
$w245: rgb(245, 245, 245);
$w240: rgb(240, 240, 240);
$w235: rgb(235, 235, 235);
$w230: rgb(230, 230, 230);
$w225: rgb(225, 225, 225);
$w220: rgb(220, 220, 220);
$w210: rgb(210, 210, 210);
$w200: rgb(200, 200, 200);
$w190: rgb(190, 190, 190);
$w180: rgb(180, 180, 180);
$w170: rgb(170, 170, 170);
$w160: rgb(160, 160, 160);
$w150: rgb(150, 150, 150);
$w140: rgb(140, 140, 140);
$w130: rgb(130, 130, 130);
$w120: rgb(120, 120, 120);
$w110: rgb(110, 110, 110);
$w100: rgb(100, 100, 100);
$g90: rgb(90, 90, 90);
$g80: rgb(80, 80, 80);
$g70: rgb(70, 70, 70);
$g60: rgb(60, 60, 60);
$g50: rgb(50, 50, 50);
$g40: rgb(40, 40, 40);
$g30: rgb(30, 30, 30);
$g20: rgb(20, 20, 20);
$g10: rgb(10, 10, 10);
$g0: rgb(0, 0, 0);
$ombre: rgba(10,10,10,0.2);
$mainFont: 'Arial, sans-serif';
$mini: "(max-width: 1000px)";
$desktop: "(min-width: 1001px)";
$Loadersize: 20px;
//tailles
$headerHeight: 60px;
$headerColor: #373F46;
$boutonfont: 14px;
$boutonH: 20px;
$aside-w: 180px;
$contentSize: 170px;
// fonts
@mixin transition($args...) {
-webkit-transition: $args;
-moz-transition: $args;
-o-transition: $args;
-ms-transition: $args;
transition: $args;
}
@mixin scale($scale) {
-webkit-transform: scale($scale);
-moz-transform: scale($scale);
-o-transform: scale($scale);
-ms-transform: scale($scale);
transform: scale($scale);
}
@mixin rotate($angle) {
-webkit-transform: rotate($angle);
-moz-transform: rotate($angle);
-o-transform: rotate($angle);
-ms-transform: rotate($angle);
transform: rotate($angle);
}
@mixin translateX($value) {
-webkit-transform: translateX($value);
-moz-transform: translateX($value);
-o-transform: translateX($value);
-ms-transform: translateX($value);
transform: translateX($value);
}
@mixin translateY($value) {
-webkit-transform: translateY($value);
-moz-transform: translateY($value);
-o-transform: translateY($value);
-ms-transform: translateY($value);
transform: translateY($value);
}
@mixin translate($x, $y) {
-webkit-transform: translate($x, $y);
-moz-transform: translate($x, $y);
-o-transform: translate($x, $y);
-ms-transform: translate($x, $y);
transform: translate($x, $y);
}
@mixin userselect {
-webkit-user-select: none;
-o-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@mixin ellipsis {
overflow: hidden;
text-overflow: ellipsis;
word-wrap: break-word;
white-space: nowrap;
}
@mixin inputbase {
outline: none;
border: none;
background: none;
padding: 0;
}
@mixin bg-center {
background: {
size: cover;
position: center center;
repeat: no-repeat;
};
}
@mixin filter($property) {
-webkit-filter: $property;
-o-filter: $property;
-moz-filter: $property;
-ms-filter: $property;
filter: $property;
}

View File

@@ -85,6 +85,7 @@ const messages = {
'<li><strong>Associazioni no-profit, Ecovillaggi, Comunità</strong></li>' + '<li><strong>Associazioni no-profit, Ecovillaggi, Comunità</strong></li>' +
'<li>Gruppi che intendono promuovere <strong>Progetti Sociali Innovativi</strong> per una <strong>Decrescita Felice</strong></li>' + '<li>Gruppi che intendono promuovere <strong>Progetti Sociali Innovativi</strong> per una <strong>Decrescita Felice</strong></li>' +
'<li>Chi gestisce un <strong>Gruppo di Acquisto Solidale (G.A.S.)</strong></li>' + '<li>Chi gestisce un <strong>Gruppo di Acquisto Solidale (G.A.S.)</strong></li>' +
'<li><strong>Produttori Locali Etici</strong></li>' +
'<li>Chi gestisce una <strong>Banca del Tempo</strong></li>' + '<li>Chi gestisce una <strong>Banca del Tempo</strong></li>' +
'<li><strong>Chiunque voglia partecipare</strong>, nella forma che ritiene più opportuna.</li>' + '<li><strong>Chiunque voglia partecipare</strong>, nella forma che ritiene più opportuna.</li>' +
'</ul>', '</ul>',
@@ -95,7 +96,8 @@ const messages = {
'<li><strong>Condividendolo</strong> a tutti coloro che vogliono far parte insieme della crescita e sviluppo di una Nuova Era</li>' + '<li><strong>Condividendolo</strong> a tutti coloro che vogliono far parte insieme della crescita e sviluppo di una Nuova Era</li>' +
'<li>Rispondendo ai <strong>Sondaggi Popolari</strong> e lasciando <strong>Feedback</strong></li>' + '<li>Rispondendo ai <strong>Sondaggi Popolari</strong> e lasciando <strong>Feedback</strong></li>' +
'<li>Tramite una <strong>donazione</strong> (<strong>anche 1€</strong> ) per le spese.<br>' + '<li>Tramite una <strong>donazione</strong> (<strong>anche 1€</strong> ) per le spese.<br>' +
'</ul>', '</ul>' +
'Vedo un <strong>futuro</strong> dove non si utilizzerà più denaro. Dove le persone si <strong>aiuteranno</strong> a vicenda e non avranno bisogno di "possedere" cose, ma le <strong>condivideranno</strong> con gli altri.<br>',
}, },
multiplatform: { multiplatform: {
title: 'Multi-piattaforma', title: 'Multi-piattaforma',
@@ -105,8 +107,7 @@ const messages = {
}, },
free: { free: {
title: 'Gratuita, Open Source e Niente Pubblicità', title: 'Gratuita, Open Source e Niente Pubblicità',
descr: 'Vedo un <strong>futuro</strong> dove non si utilizzerà più denaro. Dove le persone si <strong>aiuteranno</strong> a vicenda e non avranno bisogno di "possedere" cose, ma le <strong>condivideranno</strong> con gli altri.<br>' + descr: 'Questa App <strong>non è in vendita</strong>, non ha scopi commerciali, <strong>non ha prezzo</strong> ed appartiene al <strong>Popolo del Nuovo Mondo</strong>.<br>Chiunque potrá utilizzarla e beneficiarne.<br>A me il compito di gestirla e proteggerla. ' +
'Questa App <strong>non è in vendita</strong>, non ha scopi commerciali, <strong>non ha prezzo</strong> ed appartiene al <strong>Popolo del Nuovo Mondo</strong>. A me il compito di gestirla e proteggerla. ' +
'Verranno accettate solo donazioni Libere di privati ed Associazioni no-profit, in linea con i Principi, che serviranno per coprire le spese.<br>' + 'Verranno accettate solo donazioni Libere di privati ed Associazioni no-profit, in linea con i Principi, che serviranno per coprire le spese.<br>' +
'<strong>Grazie a Tutti per il sostegno</strong>. ' '<strong>Grazie a Tutti per il sostegno</strong>. '
}, },
@@ -126,6 +127,7 @@ const messages = {
Admin: 'Admin', Admin: 'Admin',
Test1: 'Test1', Test1: 'Test1',
Test2: 'Test2', Test2: 'Test2',
Projects: 'Progetti'
}, },
components: { components: {
authentication: { authentication: {
@@ -217,7 +219,12 @@ const messages = {
insertbottom: 'Inserisci il Task in basso', insertbottom: 'Inserisci il Task in basso',
edit: 'Descrizione Task:', edit: 'Descrizione Task:',
completed: 'Ultimi Completati', completed: 'Ultimi Completati',
usernotdefined: 'Attenzione, occorre essere Loggati per poter aggiungere un Todo' usernotdefined: 'Attenzione, occorre essere Loggati per poter aggiungere un Todo',
start_date: 'Data Inizio',
status: 'Stato',
completed_at: 'Data Completamento',
expiring_at: 'Data Scadenza',
phase: 'Fase',
}, },
notification: { notification: {
status: 'Stato', status: 'Stato',
@@ -233,6 +240,20 @@ const messages = {
newVersionAvailable: 'Aggiorna' newVersionAvailable: 'Aggiorna'
}, },
connection: 'Connessione', connection: 'Connessione',
proj: {
newproj: 'Titolo Progetto',
longdescr: 'Descrizione',
hoursplanned: 'Ore Preventivate',
hoursadded: 'Ore Aggiuntive',
hoursworked: 'Ore Lavorate',
begin_development: 'Inizio Sviluppo',
begin_test: 'Inizio Test',
progresstask: 'Progressione',
actualphase: 'Fase Attuale',
hoursweeky_plannedtowork: 'Ore settimanali previste',
endwork_estimate: 'Data fine lavori stimata',
totalphases: 'Totale Fasi'
}
}, },
'es': { 'es': {
dialog: { dialog: {
@@ -320,6 +341,7 @@ const messages = {
'<li> <strong>Asociaciones sin ánimo de lucro, Ecoaldeas, Comunidades</strong> </li>' + '<li> <strong>Asociaciones sin ánimo de lucro, Ecoaldeas, Comunidades</strong> </li>' +
'<li> Grupos que desean promover <strong>Proyectos sociales innovadores</strong> para <strong>Feliz Decrecimiento</strong> </li>' + '<li> Grupos que desean promover <strong>Proyectos sociales innovadores</strong> para <strong>Feliz Decrecimiento</strong> </li>' +
'<li> Quién administra un <strong>Grupo de Compra Solidario (G.C.S.)</strong> </li>' + '<li> Quién administra un <strong>Grupo de Compra Solidario (G.C.S.)</strong> </li>' +
'<li><strong>Productores locales Éticos</strong></li>' +
'<li> Quién administra un <strong>Banco de Tiempo</strong> </li>' + '<li> Quién administra un <strong>Banco de Tiempo</strong> </li>' +
'<li> <strong>Cualquier persona que quiera participar</strong>, en la forma que considere más apropiada. </li>' + '<li> <strong>Cualquier persona que quiera participar</strong>, en la forma que considere más apropiada. </li>' +
'</ul>', '</ul>',
@@ -330,7 +352,8 @@ const messages = {
'<li> <strong>Compartiéndolo</strong> a todos aquellos que quieran unirse en el crecimiento y desarrollo de una Nueva Era </li> ' + '<li> <strong>Compartiéndolo</strong> a todos aquellos que quieran unirse en el crecimiento y desarrollo de una Nueva Era </li> ' +
'<li> Respondiendo a <strong>Encuestas populares</strong> y dejando <strong>Comentarios</strong> </li>' + '<li> Respondiendo a <strong>Encuestas populares</strong> y dejando <strong>Comentarios</strong> </li>' +
'<li> A través de una <strong>donación</strong> (<strong>incluso € 1</strong>) para los gastos. <br>' + '<li> A través de una <strong>donación</strong> (<strong>incluso € 1</strong>) para los gastos. <br>' +
'</ul>', '</ul>' +
'<br>Veo un <strong>futuro</strong> en el que ya no usarás dinero. Donde las personas <strong>se ayudarán unos a otros</strong> y no necesiten "poseer" cosas, pero <strong>compartirán</strong> con otros. <br> ',
}, },
multiplatform: { multiplatform: {
title: 'Multi-plataforma', title: 'Multi-plataforma',
@@ -340,8 +363,8 @@ const messages = {
}, },
free: { free: {
title: 'Libre, Código Abierto y Sin Publicidad', title: 'Libre, Código Abierto y Sin Publicidad',
descr: 'Veo un <strong>futuro</strong> en el que ya no usarás dinero. Donde las personas <strong>se ayudarán unos a otros</strong> y no necesiten "poseer" cosas, pero <strong>compartirán</strong> con otros. <br> ' + descr: 'Esta aplicación <strong>no está a la venta</strong>, no tiene un propósito comercial, <strong>no tiene precio</strong> y pertenece a <strong>la Gente del Nuevo Mundo</strong>.<br>' +
'Esta aplicación <strong>no está a la venta</strong>, no tiene un propósito comercial, <strong>no tiene precio</strong> y pertenece a <strong>la Gente del Nuevo Mundo</strong>. A mí la tarea de gestionarlo y protegerlo. ' + 'Cualquiera puede usarla y beneficiarse.<br> A mí la tarea de gestionarlo y protegerlo. ' +
'Solo se aceptarán donaciones de particulares y asociaciones sin änimo de lucro, en línea con los Principios, que se utilizarán para cubrir los gastos. <br>' + 'Solo se aceptarán donaciones de particulares y asociaciones sin änimo de lucro, en línea con los Principios, que se utilizarán para cubrir los gastos. <br>' +
'<strong>Gracias a todos por el apoyo</strong>. ' '<strong>Gracias a todos por el apoyo</strong>. '
}, },
@@ -361,6 +384,7 @@ const messages = {
Admin: 'Administración', Admin: 'Administración',
Test1: 'Test1', Test1: 'Test1',
Test2: 'Test2', Test2: 'Test2',
Projects: 'Projectos',
}, },
components: { components: {
authentication: { authentication: {
@@ -445,7 +469,12 @@ const messages = {
insertbottom: 'Ingrese una nueva Tarea abajo', insertbottom: 'Ingrese una nueva Tarea abajo',
edit: 'Descripción Tarea:', edit: 'Descripción Tarea:',
completed: 'Ultimos Completados', completed: 'Ultimos Completados',
usernotdefined: 'Atención, debes iniciar sesión para agregar una Tarea' usernotdefined: 'Atención, debes iniciar sesión para agregar una Tarea',
start_date: 'Fecha inicio',
status: 'Estado',
completed_at: 'Fecha de finalización',
expiring_at: 'Fecha de Caducidad',
phase: 'Fase',
}, },
notification: { notification: {
status: 'Estado', status: 'Estado',
@@ -461,6 +490,20 @@ const messages = {
newVersionAvailable: 'Actualiza' newVersionAvailable: 'Actualiza'
}, },
connection: 'Connection', connection: 'Connection',
proj: {
newproj: 'Título Projecto',
longdescr: 'Descripción',
hoursplanned: 'Horas Estimadas',
hoursadded: 'Horas Adicional',
hoursworked: 'Horas Trabajadas',
begin_development: 'Comienzo desarrollo',
begin_test: 'Comienzo Prueba',
progresstask: 'Progresion',
actualphase: 'Fase Actual',
hoursweeky_plannedtowork: 'Horarios semanales programados',
endwork_estimate: 'Fecha estimada de finalización',
totalphases: 'Fases totales'
}
}, },
'enUs': { 'enUs': {
dialog: { dialog: {
@@ -548,6 +591,7 @@ const messages = {
'<li> <strong>Non-profit associations, Ecovillages, Communities</strong> </li>' + '<li> <strong>Non-profit associations, Ecovillages, Communities</strong> </li>' +
'<li> Groups that want to promote <strong>Innovative Social Projects</strong> for <strong>Happy Degrowth</strong> </li>' + '<li> Groups that want to promote <strong>Innovative Social Projects</strong> for <strong>Happy Degrowth</strong> </li>' +
'<li> Who manages a <strong>Solidarity Purchase Group</strong> </li>' + '<li> Who manages a <strong>Solidarity Purchase Group</strong> </li>' +
'<li><strong>Local Ethical Producers</strong></li>' +
'<li> Who manages a <strong>Time Bank</strong> </li>' + '<li> Who manages a <strong>Time Bank</strong> </li>' +
'<li> <strong>Anyone who wants to participate</strong>, in the form it considers most appropriate. </li>' + '<li> <strong>Anyone who wants to participate</strong>, in the form it considers most appropriate. </li>' +
'</ul>', '</ul>',
@@ -558,18 +602,19 @@ const messages = {
'<li> <strong>Sharing it</strong> to all those who want to join together in the growth and development of a New Era </li> ' + '<li> <strong>Sharing it</strong> to all those who want to join together in the growth and development of a New Era </li> ' +
'<li> Answering to <strong>Popular Polls</strong> and leaving <strong>Feedback</strong> </li>' + '<li> Answering to <strong>Popular Polls</strong> and leaving <strong>Feedback</strong> </li>' +
'<li> Through a <strong>donation</strong> (<strong>even $ 1</strong>) for expenses. <br>' + '<li> Through a <strong>donation</strong> (<strong>even $ 1</strong>) for expenses. <br>' +
'</ul>', '</ul><br>' +
'I see a <strong>future</strong> where you will no longer use money. Where people <strong>will help each other</strong> and won\'t need to "own" things, but <strong>will share</strong> with others. <br> ',
}, },
multiplatform: { multiplatform: {
title: 'Multi-platform', title: 'Multi-platform',
descr: 'It is compatible with Google Chrome, Firefox, Safari, iOS, Android and PC. The Application is easily installed, without going through the store. ' + descr: 'It is compatible with Google Chrome, Firefox, Safari, iOS, Android and PC. The Application is easily installed, without going through the store. ' +
'just share the name of this site <strong>www.freeplanet.app</strong>.<br>' + 'just share the nametranslate of this site <strong>www.freeplanet.app</strong>.<br>' +
'After registration it will ask to be added to the application list and in the screen', 'After registration it will ask to be added to the application list and in the screen',
}, },
free: { free: {
title: 'Free, Open Source and No Advertising', title: 'Free, Open Source and No Advertising',
descr: 'I see a <strong>future</strong> where you will no longer use money. Where people <strong>will help each other</strong> and won\'t need to "own" things, but <strong>will share</strong> with others. <br> ' + descr: 'This App <strong>is not for sale</strong>, has no commercial purpose, <strong>is priceless</strong> and belongs to the <strong>New World People</strong>.' +
'This App <strong>is not for sale</strong>, has no commercial purpose, <strong>is priceless</strong> and belongs to the <strong>New World People</strong>. To me the task of managing it and protecting it. ' + '<br>Anyone can use it and benefit from it.<br>To me the task of managing it and protecting it. ' +
'Only donations from private individuals and non-profit associations will be accepted, in line with the Principles, which will be used to cover the expenses. <br>' + 'Only donations from private individuals and non-profit associations will be accepted, in line with the Principles, which will be used to cover the expenses. <br>' +
'<strong>Thanks all for the support</strong>. ' '<strong>Thanks all for the support</strong>. '
}, },
@@ -589,6 +634,7 @@ const messages = {
Admin: 'Admin', Admin: 'Admin',
Test1: 'Test1', Test1: 'Test1',
Test2: 'Test2', Test2: 'Test2',
Projects: 'Projects',
}, },
components: { components: {
authentication: { authentication: {
@@ -673,7 +719,12 @@ const messages = {
insertbottom: 'Insert Task at the bottom', insertbottom: 'Insert Task at the bottom',
edit: 'Task Description:', edit: 'Task Description:',
completed: 'Lasts Completed', completed: 'Lasts Completed',
usernotdefined: 'Attention, you need to be Signed In to add a new Task' usernotdefined: 'Attention, you need to be Signed In to add a new Task',
start_date: 'Start Date',
status: 'Status',
completed_at: 'Completition Date',
expiring_at: 'Expiring Date',
phase: 'Phase',
}, },
notification: { notification: {
status: 'Status', status: 'Status',
@@ -689,6 +740,20 @@ const messages = {
newVersionAvailable: 'Upgrade' newVersionAvailable: 'Upgrade'
}, },
connection: 'Conexión', connection: 'Conexión',
proj: {
newproj: 'Project Title',
longdescr: 'Description',
hoursplanned: 'Estimated Hours',
hoursadded: 'Additional Hours',
hoursworked: 'Worked Hours',
begin_development: 'Start Dev',
begin_test: 'Start Test',
progresstask: 'Progression',
actualphase: 'Actual Phase',
hoursweeky_plannedtowork: 'Scheduled weekly hours',
endwork_estimate: 'Estimated completion date',
totalphases: 'Total Phase'
}
}, },
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

View File

@@ -47,7 +47,7 @@
name = String(name) name = String(name)
} }
if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
throw new TypeError('Invalid character in header field name') throw new TypeError('Invalid character in header field nametranslate')
} }
return name.toLowerCase() return name.toLowerCase()
} }

View File

@@ -271,7 +271,7 @@
} }
items.push(cursor.value); items.push(cursor.value);
if (count !== undefined && items.length == count) { if (!!count && items.length == count) {
resolve(items); resolve(items);
return; return;
} }

View File

@@ -1,5 +1,14 @@
const OtherTables = ['categories', 'config', 'swmsg']
const MainTables = ['todos', 'projects']
const allMethod = ['sync_post_', 'sync_patch_', 'delete_']
// -------------------------------------
let idbKeyval = (() => { let idbKeyval = (() => {
let db; let db;
// console.log('idbKeyval...') // console.log('idbKeyval...')
function getDB() { function getDB() {
@@ -14,13 +23,16 @@ let idbKeyval = (() => {
openreq.onupgradeneeded = () => { openreq.onupgradeneeded = () => {
// First time setup: create an empty object store // First time setup: create an empty object store
openreq.result.createObjectStore('todos', { keyPath: '_id' }); for (let mytab of MainTables) {
openreq.result.createObjectStore('categories', { keyPath: '_id' }); openreq.result.createObjectStore(mytab, { keyPath: '_id' });
openreq.result.createObjectStore('sync_todos', { keyPath: '_id' }); for (let mymeth of allMethod) {
openreq.result.createObjectStore('sync_todos_patch', { keyPath: '_id' }); const tab = mymeth + mytab
openreq.result.createObjectStore('delete_todos', { keyPath: '_id' }); openreq.result.createObjectStore(tab, { keyPath: '_id' });
openreq.result.createObjectStore('config', { keyPath: '_id' }); }
openreq.result.createObjectStore('swmsg', { keyPath: '_id' }); }
for (let mytab of OtherTables) {
openreq.result.createObjectStore(mytab, { keyPath: '_id' });
}
}; };
openreq.onsuccess = () => { openreq.onsuccess = () => {
@@ -31,7 +43,7 @@ let idbKeyval = (() => {
return db; return db;
} }
async function withStore(type, table, callback, ) { async function withStore(type, table, callback,) {
const db = await getDB(); const db = await getDB();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const transaction = db.transaction(table, type); const transaction = db.transaction(table, type);
@@ -42,6 +54,14 @@ let idbKeyval = (() => {
} }
return { return {
getArrayByTable(nametable, data) {
if (nametable === 'todos') {
return data.todos
} else if (nametable === 'projects') {
return data.projects
}
},
async get(key) { async get(key) {
let req; let req;
await withStore('readonly', 'keyval', store => { await withStore('readonly', 'keyval', store => {
@@ -92,6 +112,7 @@ let idbKeyval = (() => {
// console.log('setdata', table, value) // console.log('setdata', table, value)
await withStore('readwrite', table, store => { await withStore('readwrite', table, store => {
req = store.put(value); req = store.put(value);
}); });
return req.result; return req.result;

View File

@@ -1,7 +1,7 @@
// import { NotificationsStore, LoginStore } from '@store' // import { NotificationsStore, LoginStore } from '@store'
export class AxiosSuccess { export class AxiosSuccess {
public success: boolean = true public success: any = true
public status: number public status: number
public data: any public data: any
@@ -18,7 +18,7 @@ export class AxiosError {
public code: any = 0 public code: any = 0
public msgerr: string = '' public msgerr: string = ''
constructor(status: number, data?: any, code?: any, msgerr?: string) { constructor(status: number, data?: any, code?: any, msgerr: string = '') {
this.status = status this.status = status
this.data = data this.data = data
this.code = code this.code = code
@@ -89,10 +89,6 @@ export class ApiResponse {
} }
} }
export class ApiSuccess extends ApiResponse { export class ApiSuccess extends ApiResponse {
constructor(fields: {message?: string, data?: any} = {}) { constructor(fields: {message?: string, data?: any} = {}) {
super({ super({

View File

@@ -23,6 +23,4 @@ async function sendRequest(url: string, method: string, mydata: any) {
return req return req
} }
export default sendRequest export default sendRequest

View File

@@ -27,8 +27,10 @@ axiosInstance.interceptors.response.use(
if (process.env.DEBUG === '1') if (process.env.DEBUG === '1')
console.log('Status = ', error.response.status) console.log('Status = ', error.response.status)
console.log('Request Error: ', error.response) console.log('Request Error: ', error.response)
if (error.response.status) { if (error.response.status !== 0) {
GlobalStore.mutations.setStateConnection('online') GlobalStore.mutations.setStateConnection('online')
} else {
GlobalStore.mutations.setStateConnection('offline')
} }
} else { } else {
GlobalStore.mutations.setStateConnection('offline') GlobalStore.mutations.setStateConnection('offline')
@@ -48,7 +50,7 @@ export const removeAuthHeaders = () => {
async function Request(type: string, path: string, payload: any): Promise<Types.AxiosSuccess | Types.AxiosError> { async function Request(type: string, path: string, payload: any): Promise<Types.AxiosSuccess | Types.AxiosError> {
let ricevuto = false let ricevuto = false
try { try {
console.log(`Axios Request [${type}]:`, axiosInstance.defaults, 'path:', path) console.log('Axios Request', path, type, payload)
let response: AxiosResponse let response: AxiosResponse
if (type === 'post' || type === 'put' || type === 'patch') { if (type === 'post' || type === 'put' || type === 'patch') {
response = await axiosInstance[type](path, payload, { response = await axiosInstance[type](path, payload, {
@@ -58,11 +60,13 @@ async function Request(type: string, path: string, payload: any): Promise<Types.
} }
}) })
ricevuto = true ricevuto = true
console.log('Request Response: ', response) // console.log('Request Response: ', response)
// console.log(new Types.AxiosSuccess(response.data, response.status)) // console.log(new Types.AxiosSuccess(response.data, response.status))
const setAuthToken = (path === '/updatepwd') const setAuthToken = (path === '/updatepwd')
// console.log('--------- 0 ')
if (response && (response.status === 200)) { if (response && (response.status === 200)) {
let x_auth_token = '' let x_auth_token = ''
try { try {

View File

@@ -9,12 +9,13 @@ export { addAuthHeaders, removeAuthHeaders, API_URL } from './Instance'
import Paths from '@paths' import Paths from '@paths'
import { tools } from '@src/store/Modules/tools' import { tools } from '@src/store/Modules/tools'
import { GlobalStore, UserStore } from '@modules' import { GlobalStore, Projects, UserStore } from '@modules'
import globalroutines from './../../globalroutines/index' import globalroutines from './../../globalroutines/index'
import { serv_constants } from '@src/store/Modules/serv_constants' import { serv_constants } from '@src/store/Modules/serv_constants'
import router from '@router' import router from '@router'
import * as Types from '@src/store/Api/ApiTypes' import * as Types from '@src/store/Api/ApiTypes'
import { costanti } from '@src/store/Modules/costanti' import { costanti } from '@src/store/Modules/costanti'
import * as ApiTables from '@src/store/Modules/ApiTables'
// const algoliaApi = new AlgoliaSearch() // const algoliaApi = new AlgoliaSearch()
export namespace ApiTool { export namespace ApiTool {
@@ -62,6 +63,15 @@ export namespace ApiTool {
} }
export async function SendReq(url: string, method: string, mydata: any, setAuthToken: boolean = false): Promise<Types.AxiosSuccess | Types.AxiosError> { export async function SendReq(url: string, method: string, mydata: any, setAuthToken: boolean = false): Promise<Types.AxiosSuccess | Types.AxiosError> {
mydata = {
...mydata,
keyappid: process.env.PAO_APP_ID,
idapp: process.env.APP_ID
}
// console.log('mydata', mydata)
UserStore.mutations.setServerCode(tools.EMPTY) UserStore.mutations.setServerCode(tools.EMPTY)
UserStore.mutations.setResStatus(0) UserStore.mutations.setResStatus(0)
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
@@ -80,6 +90,7 @@ export namespace ApiTool {
} }
}, 1000) }, 1000)
if (!!res.status) {
UserStore.mutations.setResStatus(res.status) UserStore.mutations.setResStatus(res.status)
if (res.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) { if (res.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
// Forbidden // Forbidden
@@ -89,6 +100,7 @@ export namespace ApiTool {
router.push('/signin') router.push('/signin')
return reject({ code: tools.ERR_AUTHENTICATION }) return reject({ code: tools.ERR_AUTHENTICATION })
} }
}
return resolve(res) return resolve(res)
@@ -110,6 +122,21 @@ export namespace ApiTool {
}) })
} }
function ReceiveResponsefromServer(tablesync, nametab, method, risdata) {
// console.log('ReceiveResponsefromServer', nametab, method, risdata)
if (!!risdata) {
// Updated somw data after Server arrived data.
if (method === 'PATCH') {
if (nametab === 'projects') {
if (!!risdata.projectris) {
const copyrec = tools.jsonCopy(risdata.projectris)
Projects.mutations.updateProject({ objproj: copyrec })
}
}
}
}
}
export async function syncAlternative(mystrparam) { export async function syncAlternative(mystrparam) {
// console.log('[ALTERNATIVE Background syncing', mystrparam) // console.log('[ALTERNATIVE Background syncing', mystrparam)
@@ -117,60 +144,47 @@ export namespace ApiTool {
if (multiparams) { if (multiparams) {
if (multiparams.length > 3) { if (multiparams.length > 3) {
const cmd = multiparams[0] const cmd = multiparams[0]
const table = multiparams[1] const tablesync = multiparams[1]
const method = multiparams[2] const nametab = multiparams[2]
const token = multiparams[3] const method = multiparams[3]
// let lang = multiparams[3] // const token = multiparams[3]
if (cmd === 'sync-todos') {
// console.log('[Alternative] Syncing', cmd, table, method)
// const headers = new Headers()
// headers.append('content-Type', 'application/json')
// headers.append('Accept', 'application/json')
// headers.append('x-auth', token)
if (cmd === ApiTables.DB.CMD_SYNC) {
let errorfromserver = false let errorfromserver = false
let lettoqualcosa = false let lettoqualcosa = false
// console.log('A1) INIZIO.............................................................') // console.log('A1) INIZIO.............................................................')
return globalroutines(null, 'readall', table, null) return globalroutines(null, 'readall', tablesync, null)
.then((alldata) => { .then((alldata) => {
const myrecs = [...alldata] const myrecs = [...alldata]
// console.log('----------------------- LEGGO QUALCOSA ')
const promises = myrecs.map((rec) => { const promises = myrecs.map((rec) => {
// console.log('syncing', table, '', rec.descr) let link = '/' + ApiTables.getLinkByTableName(nametab)
// let link = String(process.env.MONGODB_HOST) + '/todos'
let link = '/todos'
if (method !== 'POST') { if (method !== 'POST') {
link += '/' + rec._id link += '/' + rec._id
} }
// console.log(' [Alternative] ++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:') // console.log('----------------------- LEGGO QUALCOSA ', link)
// Insert/Delete/Update table to the server // Insert/Delete/Update table to the server
return SendReq(link, method, rec) return SendReq(link, method, rec)
// return fetch(link, { .then((ris) => {
// method: method, ReceiveResponsefromServer(tablesync, nametab, method, ris.data)
// headers: headers,
// cache: 'no-cache',
// mode: 'cors', // 'no-cors',
// body: JSON.stringify(rec)
// })
.then(() => {
lettoqualcosa = true lettoqualcosa = true
return globalroutines(null, 'delete', table, null, rec._id) return globalroutines(null, 'delete', tablesync, null, rec._id)
}) })
.then(() => { .then(() => {
return globalroutines(null, 'delete', 'swmsg', null, mystrparam) return globalroutines(null, 'delete', 'swmsg', null, mystrparam)
}) })
.catch((err) => { .catch((err) => {
if (err.message === 'Failed to fetch') { if (!!err.msgerr) {
if (err.msgerr.message.includes('Failed to fetch') || err.msgerr.message.includes('Network Error')) {
errorfromserver = true errorfromserver = true
} }
// console.log(' [Alternative] !!!!!!!!!!!!!!! Error while sending data', err, errorfromserver, 'lettoqualcosa', lettoqualcosa) }
console.log(' [Alternative] !!!!!!!!!!!!!!! Error while sending data', err, errorfromserver, 'lettoqualcosa', lettoqualcosa)
}) })
}) })
@@ -182,23 +196,18 @@ export namespace ApiTool {
}) })
}).catch((e) => { }).catch((e) => {
// console.log('ERROR:', e)
return (errorfromserver && !lettoqualcosa) return (errorfromserver && !lettoqualcosa)
}) })
.then((errorfromserver) => { .then((error) => {
// console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ errorfromserver:', errorfromserver) console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ errorfromserver:', errorfromserver, error)
const mystate = errorfromserver ? 'offline' : 'online' const mystate = (error || errorfromserver) ? 'offline' : 'online'
GlobalStore.mutations.setStateConnection(mystate) GlobalStore.mutations.setStateConnection(mystate)
GlobalStore.mutations.saveConfig( { _id: costanti.CONFIG_ID_STATE_CONN, value: mystate }) GlobalStore.mutations.saveConfig( { _id: costanti.CONFIG_ID_STATE_CONN, value: mystate })
}) })
// console.log(' [Alternative] A2) ?????????????????????????? ESCO DAL LOOP !!!!!!!!!')
} }
} }
} }
} }
} }
export default ApiTool export default ApiTool

View File

@@ -0,0 +1,436 @@
import Api from '@api'
import { ITodo } from '@src/model'
import { GlobalStore, Todos, Projects, UserStore } from '@store'
import globalroutines from './../../globalroutines/index'
import { serv_constants } from '@src/store/Modules/serv_constants'
import { tools } from '@src/store/Modules/tools'
export const OtherTables = ['categories', 'config', 'swmsg']
export const MainTables = ['todos', 'projects']
export const allMethod = ['sync_post_', 'sync_patch_', 'delete_']
export function getLinkByTableName(nametable) {
if (nametable === 'todos') {
return 'todos'
} else if (nametable === 'projects') {
return 'projects'
}
}
export const LIST_START = '0'
export const DB = {
CMD_SYNC: 'sync',
CMD_SYNC_NEW: 'sync-new',
CMD_DELETE: 'sync-delete',
TABLE_SYNC_POST: 'sync_post_',
TABLE_SYNC_PATCH: 'sync_patch_',
TABLE_DELETE: 'delete_'
}
export function allTables() {
const myarr = OtherTables
for (const tab of MainTables) {
for (const method of allMethod) {
myarr.push(method + tab)
}
}
return myarr
}
async function dbInsertSave(call, item, method) {
let ret = true
if (!('serviceWorker' in navigator)) {
console.log('dbInsertSave', item, method)
if (UserStore.state.userId === '') {
return false
} // Login not made
call = '/' + call
if (method !== 'POST') {
call += '/' + item._id
}
console.log('SAVE: ', item)
ret = await Api.SendReq(call, method, item)
.then((res) => {
console.log('dbInsertSave ', call, 'to the Server', res.data)
return (res.status === 200)
})
.catch((error) => {
UserStore.mutations.setErrorCatch(error)
return false
})
}
return ret
}
async function dbDeleteItem(call, item) {
if (!('serviceWorker' in navigator)) {
// console.log('dbdeleteItem', item)
if (UserStore.state.userId === '') {
return false
} // Login not made
call = '/' + call
const res = await Api.SendReq(call + item._id, 'DELETE', item)
.then((myres) => {
console.log('dbdeleteItem to the Server')
return myres
})
.catch((error) => {
UserStore.mutations.setErrorCatch(error)
return UserStore.getters.getServerCode
})
return res
}
}
async function Sync_Execute(cmd, tablesync, nametab, method, item: ITodo, id, msg: String) {
// Send to Server to Sync
console.log('Sync_Execute', cmd, tablesync, nametab, method, id, msg)
if (nametab === 'todos') {
console.log(' TODO: ', item.descr)
}
let cmdSw = cmd
if ((cmd === DB.CMD_SYNC_NEW) || (cmd === DB.CMD_DELETE)) {
cmdSw = DB.CMD_SYNC
}
if ('serviceWorker' in navigator) {
return await navigator.serviceWorker.ready
.then((sw) => {
// console.log('---------------------- navigator.serviceWorker.ready')
return globalroutines(null, 'write', tablesync, item, id)
.then((id) => {
// console.log('id', id)
const sep = '|'
const multiparams = cmdSw + sep + tablesync + sep + nametab + sep + method + sep + UserStore.state.x_auth_token + sep + UserStore.state.lang
const mymsgkey = {
_id: multiparams,
value: multiparams
}
// console.log('*** swmsg')
return globalroutines(null, 'write', 'swmsg', mymsgkey, multiparams)
.then((ris) => {
// if ('SyncManager' in window) {
// console.log(' SENDING... sw.sync.register', multiparams)
// return sw.sync.register(multiparams)
// } else {
// #Todo ++ Alternative 2 to SyncManager
return Api.syncAlternative(multiparams)
// }
})
.then(() => {
let data = null
if (msg !== '') {
data = { message: msg, position: 'bottom', timeout: 3000 }
}
return data
})
.catch((err) => {
console.error('Errore in globalroutines', tablesync, nametab, err)
})
})
})
}
}
async function Sync_ExecuteCmd(cmd, nametab: string, method, item: ITodo, id, msg: String) {
// Send to Server to Sync
let tablesync = ''
if (method === 'POST') {
tablesync = DB.TABLE_SYNC_POST + nametab
} else if (method === 'PATCH') {
tablesync = DB.TABLE_SYNC_PATCH + nametab
} else if (method === 'DELETE') {
tablesync = DB.TABLE_DELETE + nametab
}
const risdata = await Sync_Execute(cmd, tablesync, nametab, method, item, id, msg)
if (cmd === DB.CMD_SYNC_NEW) {
if ((method === 'POST') || (method === 'PATCH')) {
await dbInsertSave(nametab, item, method)
}
} else if (cmd === DB.CMD_DELETE) {
await dbDeleteItem(nametab, item)
}
return risdata
}
export async function Sync_SaveItem(nametab: string, method, item) {
return await Sync_ExecuteCmd(DB.CMD_SYNC_NEW, nametab, method, item, 0, '')
}
export function Sync_DeleteItem(nametab: string, item, id) {
Sync_ExecuteCmd(DB.CMD_DELETE, nametab, 'DELETE', item, id, '')
}
export async function aftercalling(ris, checkPending: boolean, nametabindex: string) {
if (ris.status !== 200) {
if (process.env.DEBUG === '1') {
console.log('ris.status', ris.status)
}
if (ris.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
tools.consolelogpao('UNAUTHORIZING... TOKEN EXPIRED... !! ')
} else {
tools.consolelogpao('NETWORK UNREACHABLE ! (Error in fetch)', UserStore.getters.getServerCode, ris.status)
}
if ('serviceWorker' in navigator) {
// Read all data from IndexedDB Store into Memory
await updatefromIndexedDbToState(nametabindex)
}
} else {
if (ris.status === tools.OK && checkPending) {
waitAndcheckPendingMsg()
}
}
}
async function checkPendingMsg() {
// console.log('checkPendingMsg')
const config = await globalroutines(null, 'read', 'config', null, '1')
// console.log('config', config)
try {
if (config) {
if (!!config[1].stateconn) {
console.log('config.stateconn', config[1].stateconn)
if (config[1].stateconn !== GlobalStore.state.stateConnection) {
GlobalStore.mutations.setStateConnection(config[1].stateconn)
}
}
}
} catch (e) {
}
return new Promise((resolve, reject) => {
// Check if there is something
return globalroutines(null, 'count', 'swmsg')
.then((count) => {
if (count > 0) {
// console.log('count = ', count)
return resolve(true)
} else {
return resolve(false)
}
})
.catch((e) => {
return reject()
})
})
}
// If something in the call of Service Worker went wrong (Network or Server Down), then retry !
async function sendSwMsgIfAvailable() {
let something = false
if ('serviceWorker' in navigator) {
console.log(' -------- sendSwMsgIfAvailable')
const count = await checkPendingMsg()
if (count > 0) {
return await navigator.serviceWorker.ready
.then((sw) => {
return globalroutines(null, 'readall', 'swmsg')
.then((arr_recmsg) => {
if (arr_recmsg.length > 0) {
// console.log('---------------------- 2) navigator (2) .serviceWorker.ready')
let promiseChain = Promise.resolve()
for (const rec of arr_recmsg) {
// console.log(' .... sw.sync.register ( ', rec._id)
// if ('SyncManager' in window) {
// sw.sync.register(rec._id)
// } else {
// #Alternative to SyncManager
promiseChain = promiseChain.then(() => {
return Api.syncAlternative(rec._id)
.then(() => {
something = true
})
})
// }
}
return promiseChain
}
})
})
}
}
return new Promise((resolve, reject) => {
resolve(something)
})
}
async function waitAndRefreshData() {
// #Todo++ waitAndRefreshData: Check if is OK
await Projects.actions.dbLoad({ checkPending: false, onlyiffirsttime: false })
return await Todos.actions.dbLoad({ checkPending: false })
}
export async function waitAndcheckPendingMsg() {
// await aspettansec(1000)
return await checkPendingMsg()
.then((ris) => {
if (ris) {
if (!GlobalStore.getters.isOnline) { // If is Offline, then check
}
// console.log('risPending = ', ris)
return sendSwMsgIfAvailable()
.then((something) => {
if (something) {
if (process.env.DEBUG === '1') {
console.log('something')
}
// Refresh data
return waitAndRefreshData()
}
})
}
})
}
async function updatefromIndexedDbToState(nametab) {
await globalroutines(null, 'updatefromIndexedDbToState', nametab, null)
.then(() => {
console.log('updatefromIndexedDbToState! ')
return true
})
}
export function removeitemfromarray(myarray, ind) {
// console.log('PRIMA state.todos', state.todos)
// Delete Item in to Array
if (ind >= 0) {
myarray.splice(ind, 1)
}
// console.log('DOPO state.todos', state.todos, 'ind', ind)
}
/*
export async functionfunction testfunc() {
while (true) {
tools.consolelogpao('testfunc')
// console.log('Todos.state.todos_changed:', Todos.state.todos_changed)
await tools.aspettansec(5000)
}
}
*/
/*
sendMessageToSW(recdata, method) {
navigator.serviceWorker.controller.postMessage({
type: 'sync',
recdata,
method,
cmd: 'sync-new-todos',
token: UserStore.state.idToken,
lang: UserStore.state.lang
})
}
*/
function setmodifiedIfchanged(recOut, recIn, field) {
if (String(recOut[field]) !== String(recIn[field])) {
console.log('*************** CAMPO ', field, 'MODIFICATO!', recOut[field], recIn[field])
recOut.modified = true
recOut[field] = recIn[field]
return true
}
return false
}
export async function table_ModifyRecord(nametable, myitem, listFieldsToChange, field) {
if (myitem === null) {
return new Promise((resolve, reject) => {
resolve()
})
}
console.log('--> table_ModifyRecord', nametable, myitem.descr)
if ((field === 'status') && (nametable === 'todos') && (myitem.status === tools.Status.COMPLETED)) {
myitem.completed_at = tools.getDateNow()
}
const myobjsaved = tools.jsonCopy(myitem)
// get record from IndexedDb
const miorec = await globalroutines(null, 'read', nametable, null, myobjsaved._id)
if (miorec === undefined) {
console.log('~~~~~~~~~~~~~~~~~~~~ !!!!!!!!!!!!!!!!!! Record not Found !!!!!! id=', myobjsaved._id)
return
}
listFieldsToChange.forEach((myfield) => {
setmodifiedIfchanged(miorec, myobjsaved, myfield)
})
if (miorec.modified) {
// console.log(' ' + nametable + ' MODIFICATO! ', miorec.descr, miorec.pos, 'SALVALO SULLA IndexedDB')
miorec.modify_at = tools.getDateNow()
miorec.modified = false
// 1) Permit to Update the Views
tools.notifyarraychanged(miorec)
// 2) Modify on IndexedDb
return globalroutines(null, 'write', nametable, miorec)
.then((ris) => {
// 3) Modify on the Server (call)
return Sync_SaveItem(nametable, 'PATCH', miorec)
})
// } else {
// console.log(' ', miorec.descr, 'NON MODIF!')
}
}
export function table_DeleteRecord(nametable, myobjtrov, id) {
const mymodule = tools.getModulesByTable(nametable)
// 1) Delete from the Todos Array
mymodule.mutations.deletemyitem(myobjtrov)
// 2) Delete from the IndexedDb
globalroutines(null, 'delete', nametable, null, id)
// 3) Delete from the Server (call)
Sync_DeleteItem(nametable, myobjtrov, id)
}

View File

@@ -1,4 +1,4 @@
import { ICfgServer, IConfig, IGlobalState, ITodoList, StateConnection } from 'model' import { ICfgServer, IConfig, IGlobalState, IListRoutes, IMenuList, StateConnection } from 'model'
import { storeBuilder } from './Store/Store' import { storeBuilder } from './Store/Store'
import Vue from 'vue' import Vue from 'vue'
@@ -11,13 +11,11 @@ import Api from '@api'
import * as Types from '@src/store/Api/ApiTypes' import * as Types from '@src/store/Api/ApiTypes'
import { costanti } from '@src/store/Modules/costanti' import { costanti } from '@src/store/Modules/costanti'
import { tools } from '@src/store/Modules/tools' import { tools } from '@src/store/Modules/tools'
import { GlobalStore, Todos, UserStore } from '@store' import * as ApiTables from '@src/store/Modules/ApiTables'
import { GlobalStore, Projects, Todos, UserStore } from '@store'
import messages from '../../statics/i18n' import messages from '../../statics/i18n'
import globalroutines from './../../globalroutines/index' import globalroutines from './../../globalroutines/index'
const allTables = ['todos', 'categories', 'sync_todos', 'sync_todos_patch', 'delete_todos', 'config', 'swmsg']
const allTablesAfterLogin = ['todos', 'categories', 'sync_todos', 'sync_todos_patch', 'delete_todos', 'config', 'swmsg']
let stateConnDefault = 'online' let stateConnDefault = 'online'
getstateConnSaved() getstateConnSaved()
@@ -42,9 +40,9 @@ const state: IGlobalState = {
posts: [], posts: [],
menulinks: {}, menulinks: {},
listatodo: [ listatodo: [
{ namecat: 'personal', description: 'personal' }, { nametranslate: 'personal', description: 'personal' },
{ namecat: 'work', description: 'work' }, { nametranslate: 'work', description: 'work' },
{ namecat: 'shopping', description: 'shopping' } { nametranslate: 'shopping', description: 'shopping' }
], ],
connData: { connData: {
uploading_server: 0, uploading_server: 0,
@@ -74,6 +72,10 @@ async function getstateConnSaved() {
} }
} }
function addRoute(myarr, values) {
myarr.push(values)
}
const b = storeBuilder.module<IGlobalState>('GlobalModule', state) const b = storeBuilder.module<IGlobalState>('GlobalModule', state)
// Getters // Getters
@@ -109,74 +111,71 @@ namespace Getters {
}, 'showtype') }, 'showtype')
const getmenu = b.read((state) => { const getmenu = b.read((state) => {
console.log('getmenu')
const arrlista = GlobalStore.state.listatodo const arrlista = GlobalStore.state.listatodo
let listatodo = [] const lista = []
arrlista.forEach((elem: ITodoList) => { arrlista.forEach((elem: IMenuList) => {
const item = { const item = {
faIcon: 'fa fa-list-alt', faIcon: 'fa fa-list-alt',
materialIcon: 'todo', materialIcon: 'todo',
name: 'pages.' + elem.description, name: 'pages.' + elem.description,
route: '/todo/' + elem.namecat route: '/todo/' + elem.nametranslate
} }
listatodo.push(item) lista.push(item)
}) })
const arrlistaproj = Projects.getters.listaprojects()
const listaprojects = []
for (const elem of arrlistaproj) {
const item = {
materialIcon: 'next_week',
name: elem.nametranslate,
text: elem.description,
route: '/projects/' + elem.idelem
}
listaprojects.push(item)
}
const arrroutes: IListRoutes[] = []
addRoute(arrroutes, { route: '/', faIcon: 'fa fa-home', materialIcon: 'home', name: 'pages.home' }) // HOME
if (!process.env.PROD) {
addRoute(arrroutes, { route: '/todo', faIcon: 'fa fa-list-alt', materialIcon: 'format_list_numbered', name: 'pages.Todo',
routes2: lista,
level_parent: 0.5,
level_child: 0.5
})
addRoute(arrroutes,{ route: '/projects/' + process.env.PROJECT_ID_MAIN, faIcon: 'fa fa-list-alt', materialIcon: 'next_week', name: 'pages.Projects',
routes2: listaprojects,
level_parent: 0,
level_child: 0.5
})
}
if (UserStore.state.isAdmin) { if (UserStore.state.isAdmin) {
addRoute(arrroutes, { route: '/category', faIcon: 'fa fa-list-alt', materialIcon: 'category', name: 'pages.Category' })
addRoute(arrroutes, { route: '/admin/cfgserv', faIcon: 'fa fa-database', materialIcon: 'event_seat', name: 'pages.Admin' })
addRoute(arrroutes, { route: '/admin/testp1/par1', faIcon: 'fa fa-database', materialIcon: 'restore', name: 'pages.Test1' })
addRoute(arrroutes, { route: '/admin/testp1/par2', faIcon: 'fa fa-database', materialIcon: 'restore', name: 'pages.Test2' })
}
state.menulinks = { state.menulinks = {
Dashboard: { Dashboard: {
routes: [ routes: arrroutes,
{ route: '/', faIcon: 'fa fa-home', materialIcon: 'home', name: 'pages.home' },
{
route: '/todo', faIcon: 'fa fa-list-alt', materialIcon: 'format_list_numbered', name: 'pages.Todo',
routes2: listatodo
},
{ route: '/category', faIcon: 'fa fa-list-alt', materialIcon: 'category', name: 'pages.Category' },
{ route: '/admin/cfgserv', faIcon: 'fa fa-database', materialIcon: 'event_seat', name: 'pages.Admin' },
{ route: '/admin/testp1/par1', faIcon: 'fa fa-database', materialIcon: 'restore', name: 'pages.Test1' },
{ route: '/admin/testp1/par2', faIcon: 'fa fa-database', materialIcon: 'restore', name: 'pages.Test2' }
/* {route: '/vreg?idlink=aaa', faIcon: 'fa fa-login', materialIcon: 'login', name: 'pages.vreg'},*/
],
show: true show: true
} }
} }
} else {
// PRODUCTION USER:
if (process.env.PROD) {
state.menulinks = {
Dashboard: {
routes: [
{ route: '/', faIcon: 'fa fa-home', materialIcon: 'home', name: 'pages.home' }
],
show: true
}
}
} else {
// SERVER TEST
state.menulinks = {
Dashboard: {
routes: [
{ route: '/', faIcon: 'fa fa-home', materialIcon: 'home', name: 'pages.home' },
{
route: '/todo', faIcon: 'fa fa-list-alt', materialIcon: 'format_list_numbered', name: 'pages.Todo',
routes2: listatodo
},
{ route: '/category', faIcon: 'fa fa-list-alt', materialIcon: 'category', name: 'pages.Category' }
// { route: '/signup', faIcon: 'fa fa-registered', materialIcon: 'home', name: 'pages.SignUp' },
// { route: '/signin', faIcon: 'fa fa-anchor', materialIcon: 'home', name: 'pages.SignIn' },
/* {route: '/vreg?idlink=aaa', faIcon: 'fa fa-login', materialIcon: 'login', name: 'pages.vreg'},*/
],
show: true
}
}
}
}
return state.menulinks return state.menulinks
console.log('state.menulinks', state.menulinks)
}, 'getmenu') }, 'getmenu')
export const getters = { export const getters = {
@@ -215,7 +214,7 @@ namespace Getters {
}, },
get isOnline() { get isOnline() {
console.log('*********************** isOnline') // console.log('*********************** isOnline')
return state.stateConnection === 'online' return state.stateConnection === 'online'
}, },
@@ -284,7 +283,7 @@ namespace Mutations {
console.log('config', config) console.log('config', config)
if (config) { if (config) {
config.value = String(showtype) config.value = String(showtype)
Todos.state.showtype = parseInt(config.value) Todos.state.showtype = parseInt(config.value, 10)
} else { } else {
Todos.state.showtype = showtype Todos.state.showtype = showtype
} }
@@ -444,22 +443,22 @@ namespace Actions {
console.log('clearDataAfterLogout') console.log('clearDataAfterLogout')
// Clear all data from the IndexedDB // Clear all data from the IndexedDB
for (const table of allTables) { for (const table of ApiTables.allTables()) {
await globalroutines(null, 'clearalldata', table, null) await globalroutines(null, 'clearalldata', table, null)
} }
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
// REMOVE ALL SUBSCRIPTION // REMOVE ALL SUBSCRIPTION
console.log('REMOVE ALL SUBSCRIPTION...') console.log('REMOVE ALL SUBSCRIPTION...')
await navigator.serviceWorker.ready.then(function (reg) { await navigator.serviceWorker.ready.then((reg) => {
console.log('... Ready') console.log('... Ready')
reg.pushManager.getSubscription().then((subscription) => { reg.pushManager.getSubscription().then((subscription) => {
console.log(' Found Subscription...') console.log(' Found Subscription...')
if (subscription) { if (subscription) {
subscription.unsubscribe().then(function (successful) { subscription.unsubscribe().then((successful) => {
// You've successfully unsubscribed // You've successfully unsubscribed
console.log('You\'ve successfully unsubscribed') console.log('You\'ve successfully unsubscribed')
}).catch(function (e) { }).catch( (e) => {
// Unsubscription failed // Unsubscription failed
}) })
} }
@@ -473,14 +472,6 @@ namespace Actions {
async function clearDataAfterLoginOnlyIfActiveConnection(context) { async function clearDataAfterLoginOnlyIfActiveConnection(context) {
// if (Getters.getters.isOnline) {
// console.log('clearDataAfterLoginOnlyIfActiveConnection')
// // Clear all data from the IndexedDB
// allTablesAfterLogin.forEach(table => {
// globalroutines(null, 'clearalldata', table, null)
// })
// }
} }
async function loadAfterLogin(context) { async function loadAfterLogin(context) {

View File

@@ -0,0 +1,111 @@
import Vue from 'vue'
import { IProgressState } from '@types'
import { storeBuilder } from '../Store/Store'
const css = require('@css')
let TIMER = null
let TIMEOUT = null
let CUT = null
// State
const state: IProgressState = {
percent: 0,
show: false,
canSuccess: true,
duration: 3000,
height: '2px',
color: css.mainStyle,
failedColor: css.red1
}
const b = storeBuilder.module<IProgressState>('ProgressModule', state)
const stateGetter = b.state()
// Getters
namespace Getters {
export const getters = {}
}
// Mutations
namespace Mutations {
function start(state: IProgressState) {
if (!state.show) {
clearTimeout(TIMEOUT)
state.show = true
state.canSuccess = true
if (TIMER) {
clearInterval(TIMER)
state.percent = 0
}
CUT = 20000 / Math.floor(state.duration)
TIMER = setInterval(() => {
Mutations.mutations.increase(CUT * Math.random())
if (state.percent > 80) {
Mutations.mutations.pause()
}
}, 200)
}
}
function set(state: IProgressState, num: number) {
state.show = true
state.canSuccess = true
state.percent = Math.floor(num)
}
function increase(state: IProgressState, num: number) {
state.percent = state.percent + Math.floor(num)
}
function decrease(state: IProgressState, num: number) {
state.percent = state.percent - Math.floor(num)
}
function finish(state: IProgressState) {
state.percent = 100
Mutations.mutations.hide()
}
function pause(state: IProgressState) {
clearInterval(TIMER)
}
function hide(state: IProgressState) {
clearInterval(TIMER)
TIMER = null
TIMEOUT = setTimeout(() => {
state.show = false
state.percent = 0
Vue.nextTick(() => {
setTimeout(() => {
state.percent = 0
}, 200)
})
}, 500)
}
function fail(state: IProgressState) {
state.canSuccess = false
mutations.finish()
}
export const mutations = {
start: b.commit(start),
set: b.commit(set),
finish: b.commit(finish),
increase: b.commit(increase),
decrease: b.commit(decrease),
pause: b.commit(pause),
hide: b.commit(hide),
fail: b.commit(fail)
}
}
// Actions
namespace Actions {
export const actions = {
}
}
// Module
const ProgressModule = {
get state() { return stateGetter()},
getters: Getters.getters,
mutations: Mutations.mutations,
actions: Actions.actions
}
export default ProgressModule

View File

@@ -0,0 +1,4 @@
// export {default as NotificationsStore} from './NotificationsStore';
export {default as ProgressBar} from './ProgressBar'
// export {default as AlertsStore} from './AlertsStore';
// export {default as GoogleMaps, getMapInstance, geoLocate} from './GoogleMaps/GoogleMaps';

View File

@@ -0,0 +1,358 @@
import { IProject, IProjectsState, IDrag, IMenuList } from 'model'
import { storeBuilder } from './Store/Store'
import Api from '@api'
import { tools } from './tools'
import * as ApiTables from './ApiTables'
import { GlobalStore, UserStore } from '@store'
import globalroutines from './../../globalroutines/index'
import objectId from '@src/js/objectId'
import { costanti } from '@src/store/Modules/costanti'
const nametable = 'projects'
// import _ from 'lodash'
const stateglob: IProjectsState = {
showtype: costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED,
projects: [],
insidePending: false,
visuLastCompleted: 10
}
const listFieldsToChange: string [] = ['descr', 'longdescr', 'hoursplanned', 'hoursworked', 'id_parent', 'statusproj', 'category', 'expiring_at', 'priority', 'id_prev', 'pos', 'enableExpiring', 'progressCalc', 'live_url', 'test_url', 'begin_development', 'begin_test', 'actualphase', 'totalphases', 'hoursweeky_plannedtowork', 'endwork_estimate']
const listFieldsUpdateCalculation: string [] = ['hoursplanned', 'hoursworked', 'progressCalc', 'endwork_estimate']
const b = storeBuilder.module<IProjectsState>('Projects', stateglob)
const stateGetter = b.state()
function getarrByCategory(category: string) {
if (!stateglob.projects) {
return []
}
return stateglob.projects
}
function initcat() {
const rec = Getters.getters.getRecordEmpty()
rec.userId = UserStore.state.userId
return rec
}
function updateDataCalculated(projout, projin) {
listFieldsUpdateCalculation.forEach((field) => {
projout[field] = projin[field];
});
}
namespace Getters {
const getRecordEmpty = b.read((state: IProjectsState) => (): IProject => {
// const tomorrow = tools.getDateNow()
// tomorrow.setDate(tomorrow.getDate() + 1)
const obj: IProject = {
_id: objectId(),
descr: '',
longdescr: '',
id_parent: '',
priority: tools.Priority.PRIORITY_NORMAL,
statusproj: tools.Status.OPENED,
created_at: tools.getDateNow(),
modify_at: tools.getDateNow(),
completed_at: tools.getDateNull(),
category: '',
// expiring_at: tomorrow,
enableExpiring: false,
id_prev: '',
pos: 0,
modified: false,
live_url: '',
test_url: '',
totalphases: 1,
actualphase: 1,
hoursworked: 0,
hoursplanned: 0,
progressCalc: 0,
begin_development: tools.getDateNull(),
begin_test: tools.getDateNull(),
hoursweeky_plannedtowork: 0,
endwork_estimate: tools.getDateNull()
}
return obj
}, 'getRecordEmpty')
const items_dacompletare = b.read((state: IProjectsState) => (id_parent: string): IProject[] => {
if (state.projects) {
// console.log('state.projects', state.projects)
return tools.mapSort(state.projects.filter((proj) => proj.id_parent === id_parent))
} else {
return []
}
}, 'items_dacompletare')
const listaprojects = b.read((state: IProjectsState) => (): IMenuList[] => {
if (state.projects) {
// console.log('state.projects', state.projects)
const listaproj = tools.mapSort(state.projects.filter((proj) => proj.id_parent === process.env.PROJECT_ID_MAIN))
const myarr: IMenuList[] = []
for (const proj of listaproj) {
myarr.push({ nametranslate: '', description: proj.descr, idelem: proj._id })
}
return myarr
} else {
return []
}
}, 'listaprojects')
const getDescrById = b.read((state: IProjectsState) => (id: string): string => {
if (id === process.env.PROJECT_ID_MAIN)
return 'Projects'
if (state.projects) {
const itemtrov = state.projects.find((item) => item._id === id)
if (!!itemtrov)
return itemtrov.descr
}
return ''
}, 'getDescrById')
const getParentById = b.read((state: IProjectsState) => (id: string): string => {
if (state.projects) {
const itemfound = state.projects.find((item) => item._id === id)
if (!!itemfound) {
return itemfound.id_parent
}
}
return ''
}, 'getParentById')
const getRecordById = b.read((state: IProjectsState) => (id: string): IProject => {
if (state.projects) {
return state.projects.find((item) => item._id === id)
}
return null
}, 'getRecordById')
export const getters = {
get getRecordEmpty() {
return getRecordEmpty()
},
get items_dacompletare() {
return items_dacompletare()
},
get listaprojects() {
return listaprojects()
},
get getDescrById() {
return getDescrById()
},
get getParentById() {
return getParentById()
},
get getRecordById() {
return getRecordById()
}
}
}
namespace Mutations {
function createNewItem(state: IProjectsState, { objproj, atfirst, categorySel }) {
// console.log('createNewItem', objproj, 'cat=', categorySel, 'state.projects', state.projects)
if (state.projects === undefined) {
state.projects = []
state.projects.push(objproj)
console.log('push state.projects', state.projects)
return
}
if (atfirst) {
state.projects.unshift(objproj)
}
else {
state.projects.push(objproj)
}
}
function updateProject(state: IProjectsState, { objproj }) {
if (!!objproj) {
console.log('updateProject', objproj)
const index = tools.getIndexById(state.projects, objproj._id)
console.log('index', index)
if (index >= 0) {
updateDataCalculated(state.projects[index], objproj)
// state.projects.splice(index, 1, objproj)
// tools.notifyarraychanged(state.projects)
}
}
}
function deletemyitem(state: IProjectsState, myitem: IProject) {
// Find record
const ind = tools.getIndexById(state.projects, myitem._id)
ApiTables.removeitemfromarray(state.projects, ind)
}
export const mutations = {
deletemyitem: b.commit(deletemyitem),
createNewItem: b.commit(createNewItem),
updateProject: b.commit(updateProject)
}
}
namespace Actions {
async function dbLoad(context, { checkPending, onlyiffirsttime }) {
if (onlyiffirsttime) {
if (stateglob.projects.length > 0) {
// if already set, then exit.
return false
}
}
if (UserStore.state.userId === '') {
return false // Login not made
}
console.log('dbLoad', nametable, checkPending, 'userid=', UserStore.state.userId)
const ris = await Api.SendReq('/projects/' + UserStore.state.userId, 'GET', null)
.then((res) => {
if (res.data.projects) { // console.log('RISULTANTE CATEGORIES DAL SERVER = ', res.data.categories)
stateglob.projects = res.data.projects
} else {
stateglob.projects = []
}
stateglob.showtype = parseInt(GlobalStore.getters.getConfigStringbyId({
id: costanti.CONFIG_ID_SHOW_TYPE_TODOS,
default: costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED
}), 10)
if (process.env.DEBUG === '1') {
console.log('dbLoad', 'state.projects', stateglob.projects)
}
return res
})
.catch((error) => {
console.log('error dbLoad', error)
UserStore.mutations.setErrorCatch(error)
return error
})
ApiTables.aftercalling(ris, checkPending, nametable)
}
async function deleteItem(context, { idobj }) {
console.log('deleteItem: KEY = ', idobj)
const myarr = getarrByCategory('')
const myobjtrov = tools.getElemById(myarr, idobj)
console.log('myobjtrov', myobjtrov.descr)
if (!!myobjtrov) {
const myobjnext = tools.getElemPrevById(myarr, myobjtrov._id)
if (!!myobjnext) {
myobjnext.id_prev = myobjtrov.id_prev
myobjnext.modified = true
await modify(context, { myitem: myobjnext, field: 'id_prev' })
}
ApiTables.table_DeleteRecord(nametable, myobjtrov, idobj)
}
}
async function dbInsert(context, { myobj, atfirst }) {
const objproj = initcat()
objproj.descr = myobj.descr
objproj.category = myobj.category
objproj.id_parent = myobj.id_parent
let elemtochange: IProject = null
const myarr = getarrByCategory(objproj.category)
if (atfirst) {
console.log('INSERT AT THE TOP')
elemtochange = tools.getFirstList(myarr)
objproj.id_prev = ApiTables.LIST_START
} else {
console.log('INSERT AT THE BOTTOM')
// INSERT AT THE BOTTOM , so GET LAST ITEM
const lastelem = tools.getLastListNotCompleted(nametable, objproj.id_parent)
objproj.id_prev = (!!lastelem) ? lastelem._id : ApiTables.LIST_START
}
objproj.modified = false
Mutations.mutations.createNewItem({ objproj, atfirst, categorySel: objproj.category }) // 1) Create record in Memory
const id = await globalroutines(context, 'write', nametable, objproj) // 2) Insert into the IndexedDb
let field = ''
if (atfirst) { // update also the last elem
if (!!elemtochange) {
elemtochange.id_prev = id
console.log('elemtochange', elemtochange)
field = 'id_prev'
// Modify the other record
await modify(context, { myitem: elemtochange, field })
}
}
// 3) send to the Server
await ApiTables.Sync_SaveItem(nametable, 'POST', objproj)
return id
}
async function modify(context, { myitem, field }) {
return await ApiTables.table_ModifyRecord(nametable, myitem, listFieldsToChange, field)
}
async function swapElems(context, itemdragend: IDrag) {
console.log('PROJECT swapElems', itemdragend, stateglob.projects)
const myarr = Getters.getters.items_dacompletare(itemdragend.id_proj)
tools.swapGeneralElem(nametable, myarr, itemdragend, listFieldsToChange)
}
export const actions = {
dbLoad: b.dispatch(dbLoad),
swapElems: b.dispatch(swapElems),
deleteItem: b.dispatch(deleteItem),
dbInsert: b.dispatch(dbInsert),
modify: b.dispatch(modify)
}
}
// Module
const ProjectsModule = {
get state() {
return stateGetter()
},
getters: Getters.getters,
mutations: Mutations.mutations,
actions: Actions.actions
}
export default ProjectsModule

View File

@@ -1,8 +1,9 @@
import { ITodo, ITodosState, IParamTodo, IDrag } from 'model' import { ITodo, ITodosState, IParamTodo, IDrag, IProjectsState, IProject } from 'model'
import { storeBuilder } from './Store/Store' import { storeBuilder } from './Store/Store'
import Api from '@api' import Api from '@api'
import { tools } from './tools' import { tools } from './tools'
import * as ApiTables from './ApiTables'
import { GlobalStore, Todos, UserStore } from '@store' import { GlobalStore, Todos, UserStore } from '@store'
import globalroutines from './../../globalroutines/index' import globalroutines from './../../globalroutines/index'
import { Mutation } from 'vuex-module-decorators' import { Mutation } from 'vuex-module-decorators'
@@ -11,6 +12,8 @@ import { GetterTree } from 'vuex'
import objectId from '@src/js/objectId' import objectId from '@src/js/objectId'
import { costanti } from '@src/store/Modules/costanti' import { costanti } from '@src/store/Modules/costanti'
const nametable = 'todos'
// import _ from 'lodash' // import _ from 'lodash'
const state: ITodosState = { const state: ITodosState = {
@@ -24,7 +27,7 @@ const state: ITodosState = {
visuLastCompleted: 10 visuLastCompleted: 10
} }
const fieldtochange: String [] = ['descr', 'completed', 'category', 'expiring_at', 'priority', 'id_prev', 'pos', 'enableExpiring', 'progress'] const listFieldsToChange: string [] = ['descr', 'statustodo', 'category', 'expiring_at', 'priority', 'id_prev', 'pos', 'enableExpiring', 'progress', 'phase', 'assigned_to_userId', 'hoursplanned', 'hoursworked', 'start_date', 'completed_at']
const b = storeBuilder.module<ITodosState>('Todos', state) const b = storeBuilder.module<ITodosState>('Todos', state)
const stateGetter = b.state() const stateGetter = b.state()
@@ -33,209 +36,83 @@ function getindexbycategory(category: string) {
return state.categories.indexOf(category) return state.categories.indexOf(category)
} }
function gettodosByCategory(category: string) { function gettodosByCategory(category: string): [] {
const indcat = state.categories.indexOf(category) const indcat = state.categories.indexOf(category)
if (!state.todos[indcat]) if (!state.todos[indcat]) {
return [] return []
}
return state.todos[indcat] return state.todos[indcat]
} }
function isValidIndex(cat, index) {
const myarr = gettodosByCategory(cat)
return (index >= 0 && index < myarr.length)
}
function getElemByIndex(cat, index) {
const myarr = gettodosByCategory(cat)
if (index >= 0 && index < myarr.length)
return myarr[index]
else
return null
}
function getElemById(cat, id) {
const myarr = gettodosByCategory(cat)
for (let indrec = 0; indrec < myarr.length; indrec++) {
if (myarr[indrec]._id === id) {
return myarr[indrec]
}
}
return null
}
function getIndexById(cat, id) {
const myarr = gettodosByCategory(cat)
for (let indrec = 0; indrec < myarr.length; indrec++) {
if (myarr[indrec]._id === id) {
return indrec
}
}
return -1
}
function getElemPrevById(cat, id_prev) {
const myarr = gettodosByCategory(cat)
for (let indrec = 0; indrec < myarr.length; indrec++) {
if (myarr[indrec].id_prev === id_prev) {
return myarr[indrec]
}
}
return null
}
function getLastFirstElemPriority(cat: string, priority: number, atfirst: boolean, escludiId: string) {
const myarr = gettodosByCategory(cat)
if (myarr === null)
return -1
let trovato: boolean = false
console.log('priority', priority)
for (let indrec = 0; indrec < myarr.length; indrec++) {
if ((myarr[indrec].priority === priority) && (myarr[indrec]._id !== escludiId)) {
trovato = true
if (atfirst) {
return indrec - 1
}
} else {
if (trovato) {
return indrec
}
}
}
console.log('trovato?', trovato, 'indrec')
if (trovato) {
return myarr.length - 1
} else {
if (priority === tools.Todos.PRIORITY_LOW)
return myarr.length - 1
else if (priority === tools.Todos.PRIORITY_HIGH)
return 0
}
}
function getFirstList(cat) {
const myarr = gettodosByCategory(cat)
for (let indrec in myarr) {
if (myarr[indrec].id_prev === tools.LIST_START) {
return myarr[indrec]
}
}
return null
}
function getLastListNotCompleted(cat) {
const arr = Todos.getters.todos_dacompletare(cat)
// console.log('cat', cat, 'arr', arr)
if (arr.length > 0)
return arr[arr.length - 1]
else
return null
}
function getstrelem(elem) {
return 'ID [' + elem._id + '] ' + elem.descr + ' [ID_PREV=' + elem.id_prev + '] modif=' + elem.modified
}
function update_idprev(indcat, indelemchange, indelemId) {
if (indelemchange >= 0 && indelemchange < state.todos[indcat].length) {
const id_prev = (indelemId >= 0) ? state.todos[indcat][indelemId]._id : tools.LIST_START
if (state.todos[indcat][indelemchange].id_prev !== id_prev) {
state.todos[indcat][indelemchange].id_prev = id_prev
tools.notifyarraychanged(state.todos[indcat][indelemchange])
// state.todos[indcat][indelemchange].modified = true
console.log('Index=', indelemchange, 'indtoget', indelemId, getstrelem(state.todos[indcat][indelemchange]))
return state.todos[indcat][indelemchange]
}
}
return null
}
function initcat() { function initcat() {
let tomorrow = new Date() let rec = Getters.getters.getRecordEmpty()
rec.userId = UserStore.state.userId
return rec
}
namespace Getters {
const getRecordEmpty = b.read((state: ITodosState) => (): ITodo => {
const tomorrow = tools.getDateNow()
tomorrow.setDate(tomorrow.getDate() + 1) tomorrow.setDate(tomorrow.getDate() + 1)
const objtodo: ITodo = { const objtodo: ITodo = {
// _id: new Date().toISOString(), // Create NEW // _id: tools.getDateNow().toISOString(), // Create NEW
_id: objectId(), _id: objectId(),
userId: UserStore.state.userId, userId: UserStore.state.userId,
descr: '', descr: '',
priority: tools.Todos.PRIORITY_NORMAL, priority: tools.Priority.PRIORITY_NORMAL,
completed: false, statustodo: tools.Status.OPENED,
created_at: new Date(), created_at: tools.getDateNow(),
modify_at: new Date(), modify_at: tools.getDateNow(),
completed_at: new Date(), completed_at: tools.getDateNull(),
category: '', category: '',
expiring_at: tomorrow, expiring_at: tomorrow,
enableExpiring: false, enableExpiring: false,
id_prev: '', id_prev: '',
pos: 0, pos: 0,
modified: false, modified: false,
progress: 0 progress: 0,
progressCalc: 0,
phase: 0,
assigned_to_userId: '',
hoursplanned: 0,
hoursworked: 0,
start_date: tools.getDateNull(),
} }
// return this.copy(objtodo) // return this.copy(objtodo)
return objtodo return objtodo
}, 'getRecordEmpty')
} const items_dacompletare = b.read((state: ITodosState) => (cat: string): ITodo[] => {
function deleteItemToSyncAndDb(table: String, item: ITodo, id) {
cmdToSyncAndDbTodo(tools.DB.CMD_DELETE_TODOS, table, 'DELETE', item, id, '')
}
async function saveItemToSyncAndDb(table: String, method, item: ITodo) {
return await cmdToSyncAndDbTodo(tools.DB.CMD_SYNC_NEW_TODOS, table, method, item, 0, '')
}
async function cmdToSyncAndDbTodo(cmd, table, method, item: ITodo, id, msg: String) {
// Send to Server to Sync
console.log('cmdToSyncAndDbTodo', cmd, table, method, item.descr, id, msg)
const risdata = await tools.cmdToSyncAndDb(cmd, table, method, item, id, msg)
if (cmd === tools.DB.CMD_SYNC_NEW_TODOS) {
if (method === 'POST')
await Todos.actions.dbInsertTodo(item)
else if (method === 'PATCH')
await Todos.actions.dbSaveTodo(item)
} else if (cmd === tools.DB.CMD_DELETE_TODOS) {
await Todos.actions.dbdeleteItem(item)
}
return risdata
}
namespace Getters {
// const fullName = b.read(function fullName(state): string {
// return state.userInfos.firstname?capitalize(state.userInfos.firstname) + " " + capitalize(state.userInfos.lastname):null;
// })
const todos_dacompletare = b.read((state: ITodosState) => (cat: string): ITodo[] => {
const indcat = getindexbycategory(cat) const indcat = getindexbycategory(cat)
if (state.todos[indcat]) { if (state.todos[indcat]) {
return state.todos[indcat].filter(todo => !todo.completed) return state.todos[indcat].filter((todo) => todo.statustodo !== tools.Status.COMPLETED)
} else return [] } else {
}, 'todos_dacompletare') return []
}
}, 'items_dacompletare')
const todos_completati = b.read((state: ITodosState) => (cat: string): ITodo[] => { const todos_completati = b.read((state: ITodosState) => (cat: string): ITodo[] => {
const indcat = getindexbycategory(cat) const indcat = getindexbycategory(cat)
if (state.todos[indcat]) { if (state.todos[indcat]) {
if (state.showtype === costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED) if (state.showtype === costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED) { // Show only the first N completed
return state.todos[indcat].filter(todo => todo.completed).slice(0, state.visuLastCompleted) // Show only the first N completed return state.todos[indcat].filter((todo) => todo.statustodo === tools.Status.COMPLETED).slice(0, state.visuLastCompleted)
else if (state.showtype === costanti.ShowTypeTask.SHOW_ALL) }
return state.todos[indcat].filter(todo => todo.completed) else if (state.showtype === costanti.ShowTypeTask.SHOW_ONLY_TOCOMPLETE) {
else
return [] return []
} else return [] }
else if (state.showtype === costanti.ShowTypeTask.SHOW_ALL) {
return state.todos[indcat].filter((todo) => todo.statustodo === tools.Status.COMPLETED)
}
else {
return []
}
} else {
return []
}
}, 'todos_completati') }, 'todos_completati')
const doneTodosCount = b.read((state: ITodosState) => (cat: string): number => { const doneTodosCount = b.read((state: ITodosState) => (cat: string): number => {
@@ -250,11 +127,20 @@ namespace Getters {
} }
}, 'TodosCount') }, 'TodosCount')
const getRecordById = b.read((state: ITodosState) => (id: string, cat: string): ITodo => {
const indcat = getindexbycategory(cat)
if (state.todos) {
return state.todos[indcat].find((item) => item._id === id)
}
return null
}, 'getRecordById')
export const getters = { export const getters = {
// get fullName() { return fullName();}, get getRecordEmpty() {
get todos_dacompletare() { return getRecordEmpty()
return todos_dacompletare() },
get items_dacompletare() {
return items_dacompletare()
}, },
get todos_completati() { get todos_completati() {
return todos_completati() return todos_completati()
@@ -264,32 +150,23 @@ namespace Getters {
}, },
get TodosCount() { get TodosCount() {
return TodosCount() return TodosCount()
},
get getRecordById() {
return getRecordById()
} }
} }
} }
namespace Mutations { namespace Mutations {
function setTestpao(state: ITodosState, testpao: String) { function findIndTodoById(state: ITodosState, data: IParamTodo) {
state.testpao = testpao
}
function findTodoById(state: ITodosState, data: IParamTodo) {
const indcat = state.categories.indexOf(data.categorySel) const indcat = state.categories.indexOf(data.categorySel)
if (indcat >= 0) { if (indcat >= 0) {
if (state.todos[indcat]) { return tools.getIndexById(state.todos[indcat], data.id)
for (let i = 0; i < state.todos[indcat].length; i++) {
if (state.todos[indcat][i]._id === data.id)
return i
}
}
} }
return -1 return -1
} }
function createNewItem(state: ITodosState, { objtodo, atfirst, categorySel }) { function createNewItem(state: ITodosState, { objtodo, atfirst, categorySel }) {
let indcat = state.categories.indexOf(categorySel) let indcat = state.categories.indexOf(categorySel)
if (indcat == -1) { if (indcat == -1) {
@@ -303,10 +180,12 @@ namespace Mutations {
console.log('push state.todos[indcat]', state.todos) console.log('push state.todos[indcat]', state.todos)
return return
} }
if (atfirst) if (atfirst) {
state.todos[indcat].unshift(objtodo) state.todos[indcat].unshift(objtodo)
else }
else {
state.todos[indcat].push(objtodo) state.todos[indcat].push(objtodo)
}
console.log('state.todos[indcat]', state.todos[indcat]) console.log('state.todos[indcat]', state.todos[indcat])
@@ -315,338 +194,82 @@ namespace Mutations {
function deletemyitem(state: ITodosState, myitem: ITodo) { function deletemyitem(state: ITodosState, myitem: ITodo) {
// Find record // Find record
const indcat = state.categories.indexOf(myitem.category) const indcat = state.categories.indexOf(myitem.category)
const ind = findTodoById(state, { id: myitem._id, categorySel: myitem.category }) const ind = findIndTodoById(state, { id: myitem._id, categorySel: myitem.category })
console.log('PRIMA state.todos', state.todos) ApiTables.removeitemfromarray(state.todos[indcat], ind)
// Delete Item in to Array
if (ind >= 0)
state.todos[indcat].splice(ind, 1)
console.log('DOPO state.todos', state.todos, 'ind', ind)
// tools.notifyarraychanged(state.todos[indcat])
} }
export const mutations = { export const mutations = {
setTestpao: b.commit(setTestpao),
deletemyitem: b.commit(deletemyitem), deletemyitem: b.commit(deletemyitem),
createNewItem: b.commit(createNewItem) createNewItem: b.commit(createNewItem)
} }
} }
function consolelogpao(strlog, strlog2 = '', strlog3 = '') {
globalroutines(null, 'log', strlog + ' ' + strlog2 + ' ' + strlog3, null)
}
namespace Actions { namespace Actions {
// If something in the call of Service Worker went wrong (Network or Server Down), then retry ! async function dbLoad(context, { checkPending }) {
async function sendSwMsgIfAvailable() { console.log('dbLoad', nametable, checkPending, 'userid=', UserStore.state.userId)
let something = false
if ('serviceWorker' in navigator) { if (UserStore.state.userId === '') {
console.log(' -------- sendSwMsgIfAvailable')
let count = await checkPendingMsg(null)
if (count > 0) {
return await navigator.serviceWorker.ready
.then(function (sw) {
return globalroutines(null, 'readall', 'swmsg')
.then(function (arr_recmsg) {
// let recclone = [...arr_recmsg]
if (arr_recmsg.length > 0) {
// console.log('---------------------- 2) navigator (2) .serviceWorker.ready')
let promiseChain = Promise.resolve()
for (let indrec in arr_recmsg) {
// console.log(' .... sw.sync.register ( ', rec._id)
// if ('SyncManager' in window) {
// sw.sync.register(rec._id)
// } else {
// #Alternative to SyncManager
promiseChain = promiseChain.then(() => {
return Api.syncAlternative(arr_recmsg[indrec]._id)
.then(() => {
something = true
})
})
// }
}
return promiseChain
}
})
})
}
}
return new Promise(function (resolve, reject) {
resolve(something)
})
}
async function waitAndcheckPendingMsg(context) {
// await aspettansec(1000)
return await checkPendingMsg(context)
.then(ris => {
if (ris) {
// console.log('risPending = ', ris)
return sendSwMsgIfAvailable()
.then(something => {
if (something) {
if (process.env.DEBUG === '1')
console.log('something')
// Refresh data
return waitAndRefreshData(context)
}
})
}
})
}
async function waitAndRefreshData(context) {
// await aspettansec(3000)
return await dbLoadTodo(context, { checkPending: false })
}
async function readConfig(id) {
return await globalroutines(null, 'read', 'config', null, String(id))
}
async function checkPendingMsg(context) {
// console.log('checkPendingMsg')
const config = await globalroutines(null, 'read', 'config', null, '1')
// console.log('config', config)
try {
if (config) {
if (config[1].stateconn !== undefined) {
// console.log('config.stateconn', config[1].stateconn)
if (config[1].stateconn !== GlobalStore.state.stateConnection) {
GlobalStore.mutations.setStateConnection(config[1].stateconn)
}
}
}
} catch (e) {
}
return new Promise(function (resolve, reject) {
// Check if there is something
return globalroutines(null, 'count', 'swmsg')
.then(function (count) {
if (count > 0) {
// console.log('count = ', count)
return resolve(true)
} else {
return resolve(false)
}
})
.catch(e => {
return reject()
})
})
}
async function dbLoadTodo(context, { checkPending }) {
console.log('dbLoadTodo', checkPending, 'userid=', UserStore.state.userId)
if (UserStore.state.userId === '')
return false // Login not made return false // Login not made
}
let ris = await Api.SendReq('/todos/' + UserStore.state.userId, 'GET', null) const ris = await Api.SendReq('/todos/' + UserStore.state.userId, 'GET', null)
.then(res => { .then((res) => {
if (res.data.todos) { if (res.data.todos) { // console.log('RISULTANTE CATEGORIES DAL SERVER = ', res.data.categories)
// console.log('RISULTANTE CATEGORIES DAL SERVER = ', res.data.categories)
// console.log('RISULTANTE TODOS DAL SERVER = ', res.data.todos)
state.todos = res.data.todos state.todos = res.data.todos
state.categories = res.data.categories state.categories = res.data.categories
} else { } else {
state.todos = [[]] state.todos = [[]]
} }
// console.log('PRIMA showtype = ', state.showtype) state.showtype = parseInt(GlobalStore.getters.getConfigStringbyId({
id: costanti.CONFIG_ID_SHOW_TYPE_TODOS,
state.showtype = parseInt(GlobalStore.getters.getConfigStringbyId({id: costanti.CONFIG_ID_SHOW_TYPE_TODOS, default: costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED })) default: costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED
}), 10)
// console.log('showtype = ', state.showtype)
// console.log('ARRAY TODOS = ', state.todos) // console.log('ARRAY TODOS = ', state.todos)
if (process.env.DEBUG === '1') if (process.env.DEBUG === '1') {
console.log('dbLoadTodo', 'state.todos', state.todos, 'state.categories', state.categories) console.log('dbLoad', 'state.todos', state.todos, 'state.categories', state.categories)
}
return res return res
}) })
.catch(error => { .catch((error) => {
console.log('error dbLoadTodo', error) console.log('error dbLoad', error)
UserStore.mutations.setErrorCatch(error) UserStore.mutations.setErrorCatch(error)
return error return error
}) })
if (ris.status !== 200) { ApiTables.aftercalling(ris, checkPending, 'categories')
if (process.env.DEBUG === '1')
console.log('ris.status', ris.status)
if (ris.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
consolelogpao('UNAUTHORIZING... TOKEN EXPIRED... !! ')
} else {
consolelogpao('NETWORK UNREACHABLE ! (Error in fetch)', UserStore.getters.getServerCode, ris.status)
}
if ('serviceWorker' in navigator) {
// Read all data from IndexedDB Store into Memory
await updatefromIndexedDbToStateTodo(context)
}
} else {
if (ris.status === tools.OK && checkPending) {
waitAndcheckPendingMsg(context)
}
}
} }
async function updatefromIndexedDbToStateTodo(context) { async function deleteItemtodo(context, { cat, idobj }) {
// console.log('Update the array in memory, from todos table from IndexedDb') console.log('deleteItemtodo: KEY = ', idobj)
await globalroutines(null, 'updatefromIndexedDbToStateTodo', 'categories', null)
.then(() => {
console.log('updatefromIndexedDbToStateTodo! ')
return true
})
}
function aspettansec(numsec) { const myarr = gettodosByCategory(cat)
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('anything')
}, numsec)
})
}
async function testfunc() { const myobjtrov = tools.getElemById(myarr, idobj)
while (true) { if (!!myobjtrov) {
consolelogpao('testfunc')
// console.log('Todos.state.todos_changed:', Todos.state.todos_changed)
await aspettansec(5000)
}
}
async function dbSaveTodo(context, itemtodo: ITodo) { console.log('myobjtrov', myobjtrov.descr)
return await dbInsertSaveTodo(context, itemtodo, 'PATCH')
}
async function dbInsertTodo(context, itemtodo: ITodo) { if (!!myobjtrov) {
return await dbInsertSaveTodo(context, itemtodo, 'POST') const myobjnext = tools.getElemPrevById(myarr, myobjtrov._id)
}
async function dbInsertSaveTodo(context, itemtodo: ITodo, method) { if (!!myobjnext) {
if (!('serviceWorker' in navigator)) {
console.log('dbInsertSaveTodo', itemtodo, method)
let call = '/todos'
if (UserStore.state.userId === '')
return false // Login not made
if (method !== 'POST')
call += '/' + itemtodo._id
console.log('TODO TO SAVE: ', itemtodo)
let res = await Api.SendReq(call, method, itemtodo)
.then(res => {
console.log('dbInsertSaveTodo to the Server', res.data)
return (res.status === 200)
})
.catch((error) => {
UserStore.mutations.setErrorCatch(error)
// return UserStore.getters.getServerCode
return false
})
}
return true
}
async function dbdeleteItem(context, item: ITodo) {
if (!('serviceWorker' in navigator)) {
// console.log('dbdeleteItem', item)
if (UserStore.state.userId === '')
return false // Login not made
let res = await Api.SendReq('/todos/' + item._id, 'DELETE', item)
.then(res => {
console.log('dbdeleteItem to the Server')
})
.catch((error) => {
UserStore.mutations.setErrorCatch(error)
return UserStore.getters.getServerCode
})
return res
}
}
function setmodifiedIfchanged(recOut, recIn, field) {
if (String(recOut[field]) !== String(recIn[field])) {
// console.log('*************** CAMPO ', field, 'MODIFICATO!', recOut[field], recIn[field])
recOut.modified = true
recOut[field] = recIn[field]
return true
}
return false
}
async function deleteItem(context, { cat, idobj }) {
console.log('deleteItem: KEY = ', idobj)
let myobjtrov = getElemById(cat, idobj)
if (myobjtrov !== null) {
let myobjnext = getElemPrevById(cat, myobjtrov._id)
if (myobjnext !== null) {
myobjnext.id_prev = myobjtrov.id_prev myobjnext.id_prev = myobjtrov.id_prev
myobjnext.modified = true myobjnext.modified = true
console.log('calling MODIFY 1')
await modify(context, { myitem: myobjnext, field: 'id_prev' }) await modify(context, { myitem: myobjnext, field: 'id_prev' })
} }
// 1) Delete from the Todos Array ApiTables.table_DeleteRecord(nametable, myobjtrov, idobj)
Todos.mutations.deletemyitem(myobjtrov) }
}
// 2) Delete from the IndexedDb
globalroutines(context, 'delete', 'todos', null, idobj)
.then((ris) => {
}).catch((error) => {
console.log('err: ', error)
})
// 3) Delete from the Server (call)
deleteItemToSyncAndDb(tools.DB.TABLE_DELETE_TODOS, myobjtrov, idobj)
} }
// console.log('FINE deleteItem') async function dbInsert(context, { myobj, atfirst }) {
}
async function insertTodo(context, { myobj, atfirst }) {
const objtodo = initcat() const objtodo = initcat()
@@ -655,36 +278,28 @@ namespace Actions {
let elemtochange: ITodo = null let elemtochange: ITodo = null
const myarr = gettodosByCategory(objtodo.category)
if (atfirst) { if (atfirst) {
console.log('INSERT AT THE TOP') console.log('INSERT AT THE TOP')
elemtochange = getFirstList(objtodo.category) elemtochange = tools.getFirstList(myarr)
objtodo.id_prev = tools.LIST_START objtodo.id_prev = ApiTables.LIST_START
// objtodo.pos = (elemtochange !== null) ? elemtochange.pos - 1 : 1
} else { } else {
console.log('INSERT AT THE BOTTOM') console.log('INSERT AT THE BOTTOM')
// INSERT AT THE BOTTOM , so GET LAST ITEM // INSERT AT THE BOTTOM , so GET LAST ITEM
const lastelem = getLastListNotCompleted(objtodo.category) const lastelem = tools.getLastListNotCompleted(nametable, objtodo.category)
console.log('lastelem', lastelem) objtodo.id_prev = (!!lastelem) ? lastelem._id : ApiTables.LIST_START
objtodo.id_prev = (lastelem !== null) ? lastelem._id : tools.LIST_START
// objtodo.pos = (elemtochange !== null) ? elemtochange.pos + 1 : 1
} }
console.log('elemtochange TORNATO:', elemtochange)
objtodo.modified = false objtodo.modified = false
console.log('objtodo', objtodo, 'ID_PREV=', objtodo.id_prev) Todos.mutations.createNewItem({ objtodo, atfirst, categorySel: objtodo.category }) // 1) Create record in Memory
// 1) Create record in Memory const id = await globalroutines(context, 'write', nametable, objtodo) // 2) Insert into the IndexedDb
Todos.mutations.createNewItem({ objtodo, atfirst, categorySel: objtodo.category })
// 2) Insert into the IndexedDb
const id = await globalroutines(context, 'write', 'todos', objtodo)
let field = '' let field = ''
// update also the last elem if (atfirst) { // update also the last elem
if (atfirst) { if (!!elemtochange) {
if (elemtochange !== null) {
elemtochange.id_prev = id elemtochange.id_prev = id
console.log('elemtochange', elemtochange) console.log('elemtochange', elemtochange)
field = 'id_prev' field = 'id_prev'
@@ -695,16 +310,17 @@ namespace Actions {
} }
// 3) send to the Server // 3) send to the Server
return await saveItemToSyncAndDb(tools.DB.TABLE_SYNC_TODOS, 'POST', objtodo) return await ApiTables.Sync_SaveItem(nametable, 'POST', objtodo)
.then((ris) => { .then((ris) => {
// Check if need to be moved... // *** Check if need to be moved because of the --- Priority Ordering --- ...
const indelem = getIndexById(objtodo.category, objtodo._id)
let itemdragend = undefined const indelem = tools.getIndexById(myarr, objtodo._id)
let itemdragend
if (atfirst) { if (atfirst) {
// Check the second item, if it's different priority, then move to the first position of the priority // Check the second item, if it's different priority, then move to the first position of the priority
const secondindelem = indelem + 1 const secondindelem = indelem + 1
if (isValidIndex(objtodo.category, secondindelem)) { if (tools.isOkIndex(myarr, secondindelem)) {
const secondelem = getElemByIndex(objtodo.category, secondindelem) const secondelem = tools.getElemByIndex(myarr, secondindelem)
if (secondelem.priority !== objtodo.priority) { if (secondelem.priority !== objtodo.priority) {
itemdragend = { itemdragend = {
field: 'priority', field: 'priority',
@@ -719,8 +335,8 @@ namespace Actions {
} else { } else {
// get previous of the last // get previous of the last
const prevlastindelem = indelem - 1 const prevlastindelem = indelem - 1
if (isValidIndex(objtodo.category, prevlastindelem)) { if (tools.isOkIndex(myarr, prevlastindelem)) {
const prevlastelem = getElemByIndex(objtodo.category, prevlastindelem) const prevlastelem = tools.getElemByIndex(myarr, prevlastindelem)
if (prevlastelem.priority !== objtodo.priority) { if (prevlastelem.priority !== objtodo.priority) {
itemdragend = { itemdragend = {
field: 'priority', field: 'priority',
@@ -733,161 +349,39 @@ namespace Actions {
} }
} }
if (itemdragend) if (itemdragend) {
swapElems(context, itemdragend) swapElems(context, itemdragend)
}
return ris return ris
}) })
} }
async function modify(context, { myitem, field }) { async function modify(context, { myitem, field }) {
if (myitem === null) return await ApiTables.table_ModifyRecord(nametable, myitem, listFieldsToChange, field)
return new Promise(function (resolve, reject) {
resolve()
})
const myobjsaved = tools.jsonCopy(myitem)
// get record from IndexedDb
const miorec = await globalroutines(context, 'read', 'todos', null, myobjsaved._id)
if (miorec === undefined) {
console.log('~~~~~~~~~~~~~~~~~~~~ !!!!!!!!!!!!!!!!!! Record not Found !!!!!! id=', myobjsaved._id)
return
} }
if (setmodifiedIfchanged(miorec, myobjsaved, 'completed'))
miorec.completed_at = new Date().getDate()
fieldtochange.forEach(field => {
setmodifiedIfchanged(miorec, myobjsaved, field)
})
if (miorec.modified) {
// console.log('Todo MODIFICATO! ', miorec.descr, miorec.pos, 'SALVALO SULLA IndexedDB todos')
miorec.modify_at = new Date().getDate()
miorec.modified = false
// 1) Permit to Update the Views
tools.notifyarraychanged(miorec)
// Todos.mutations.modifymyItem(miorec)
// this.logelem('modify', miorec)
// 2) Modify on IndexedDb
return globalroutines(context, 'write', 'todos', miorec)
.then(ris => {
// 3) Modify on the Server (call)
saveItemToSyncAndDb(tools.DB.TABLE_SYNC_TODOS_PATCH, 'PATCH', miorec)
})
}
}
// async function updateModifyRecords(context, cat: string) {
//
// const indcat = getindexbycategory(cat)
// for (const elem of state.todos[indcat]) {
// if (elem.modified) {
// console.log('calling MODIFY 3')
// await modify(context, { myitem: elem, field })
// .then(() => {
// elem.modified = false
// })
// }
// }
// }
//
async function swapElems(context, itemdragend: IDrag) { async function swapElems(context, itemdragend: IDrag) {
console.log('swapElems', itemdragend) console.log('TODOS swapElems', itemdragend, state.todos, state.categories)
console.log('state.todos', state.todos)
console.log('state.categories', state.categories)
const cat = itemdragend.category const cat = itemdragend.category
const indcat = state.categories.indexOf(cat) const indcat = state.categories.indexOf(cat)
const myarr = state.todos[indcat]
if (itemdragend.field === 'priority') { tools.swapGeneralElem(nametable, myarr, itemdragend, listFieldsToChange)
// get last elem priority
console.log('get last elem priority')
itemdragend.newIndex = getLastFirstElemPriority(itemdragend.category, itemdragend.prioritychosen, itemdragend.atfirst, itemdragend.idelemtochange)
itemdragend.oldIndex = getIndexById(itemdragend.category, itemdragend.idelemtochange)
console.log('swapElems PRIORITY', itemdragend)
}
console.log('indcat', indcat)
if (isValidIndex(cat, indcat) && isValidIndex(cat, itemdragend.newIndex) && isValidIndex(cat, itemdragend.oldIndex)) {
console.log('isValidIndex')
state.todos[indcat].splice(itemdragend.newIndex, 0, state.todos[indcat].splice(itemdragend.oldIndex, 1)[0])
tools.notifyarraychanged(state.todos[indcat][itemdragend.newIndex])
tools.notifyarraychanged(state.todos[indcat][itemdragend.oldIndex])
if (itemdragend.field !== 'priority') {
let precind = itemdragend.newIndex - 1
let nextind = itemdragend.newIndex + 1
if (isValidIndex(cat, precind) && isValidIndex(cat, nextind)) {
if ((state.todos[indcat][precind].priority === state.todos[indcat][nextind].priority) && (state.todos[indcat][precind].priority !== state.todos[indcat][itemdragend.newIndex].priority)) {
console.log(' 1)')
state.todos[indcat][itemdragend.newIndex].priority = state.todos[indcat][precind].priority
tools.notifyarraychanged(state.todos[indcat][itemdragend.newIndex])
}
} else {
if (!isValidIndex(cat, precind)) {
if ((state.todos[indcat][nextind].priority !== state.todos[indcat][itemdragend.newIndex].priority)) {
console.log(' 2)')
state.todos[indcat][itemdragend.newIndex].priority = state.todos[indcat][nextind].priority
tools.notifyarraychanged(state.todos[indcat][itemdragend.newIndex])
}
} else {
if ((state.todos[indcat][precind].priority !== state.todos[indcat][itemdragend.newIndex].priority)) {
console.log(' 3)')
state.todos[indcat][itemdragend.newIndex].priority = state.todos[indcat][precind].priority
tools.notifyarraychanged(state.todos[indcat][itemdragend.newIndex])
}
}
}
}
// Update the id_prev property
const elem1 = update_idprev(indcat, itemdragend.newIndex, itemdragend.newIndex - 1)
const elem2 = update_idprev(indcat, itemdragend.newIndex + 1, itemdragend.newIndex)
const elem3 = update_idprev(indcat, itemdragend.oldIndex, itemdragend.oldIndex - 1)
const elem4 = update_idprev(indcat, itemdragend.oldIndex + 1, itemdragend.oldIndex)
// Update the records:
await modify(context, { myitem: elem1, field: 'id_prev' })
await modify(context, { myitem: elem2, field: 'id_prev' })
await modify(context, { myitem: elem3, field: 'id_prev' })
await modify(context, { myitem: elem4, field: 'id_prev' })
}
} }
export const actions = { export const actions = {
dbInsertTodo: b.dispatch(dbInsertTodo), dbLoad: b.dispatch(dbLoad),
dbSaveTodo: b.dispatch(dbSaveTodo),
dbLoadTodo: b.dispatch(dbLoadTodo),
dbdeleteItem: b.dispatch(dbdeleteItem),
updatefromIndexedDbToStateTodo: b.dispatch(updatefromIndexedDbToStateTodo),
checkPendingMsg: b.dispatch(checkPendingMsg),
waitAndcheckPendingMsg: b.dispatch(waitAndcheckPendingMsg),
swapElems: b.dispatch(swapElems), swapElems: b.dispatch(swapElems),
// updateModifyRecords: b.dispatch(updateModifyRecords), deleteItemtodo: b.dispatch(deleteItemtodo),
deleteItem: b.dispatch(deleteItem), dbInsert: b.dispatch(dbInsert),
insertTodo: b.dispatch(insertTodo),
modify: b.dispatch(modify) modify: b.dispatch(modify)
} }
} }
// Module // Module
const TodosModule = { const TodosModule = {
get state() { get state() {

View File

@@ -6,7 +6,7 @@ import router from '@router'
import { serv_constants } from '../Modules/serv_constants' import { serv_constants } from '../Modules/serv_constants'
import { tools } from '../Modules/tools' import { tools } from '../Modules/tools'
import { GlobalStore, UserStore, Todos } from '@store' import { GlobalStore, UserStore, Todos, Projects } from '@store'
import globalroutines from './../../globalroutines/index' import globalroutines from './../../globalroutines/index'
import translate from './../../globalroutines/util' import translate from './../../globalroutines/util'
@@ -19,7 +19,6 @@ const state: IUserState = {
userId: '', userId: '',
email: '', email: '',
username: '', username: '',
idapp: process.env.APP_ID,
password: '', password: '',
lang: '', lang: '',
repeatPassword: '', repeatPassword: '',
@@ -28,6 +27,7 @@ const state: IUserState = {
categorySel: 'personal', categorySel: 'personal',
servercode: 0, servercode: 0,
x_auth_token: '', x_auth_token: '',
isLogged: false,
isAdmin: false isAdmin: false
} }
@@ -79,14 +79,14 @@ namespace Getters {
}, },
get getServerCode() { get getServerCode() {
return getServerCode() return getServerCode()
} },
// get fullName() { return fullName();}, // get fullName() { return fullName();},
} }
} }
namespace Mutations { namespace Mutations {
function authUser(state: IUserState, data: IUserState ) { function authUser(state: IUserState, data: IUserState) {
state.userId = data.userId state.userId = data.userId
state.username = data.username state.username = data.username
if (data.verified_email) { if (data.verified_email) {
@@ -98,7 +98,7 @@ namespace Mutations {
} // ?? } // ??
resetArrToken(state.tokens) resetArrToken(state.tokens)
state.tokens.push({ access: 'auth', token: state.x_auth_token, data_login: new Date() }) state.tokens.push({ access: 'auth', token: state.x_auth_token, data_login: tools.getDateNow() })
// ++Todo: Settings Users Admin // ++Todo: Settings Users Admin
if (state.username === 'paoloar77') { if (state.username === 'paoloar77') {
@@ -127,7 +127,7 @@ namespace Mutations {
if (!state.tokens) { if (!state.tokens) {
state.tokens = [] state.tokens = []
} }
state.tokens.push({ access: 'auth', token: x_auth_token, data_login: new Date() }) state.tokens.push({ access: 'auth', token: x_auth_token, data_login: tools.getDateNow() })
} }
function setServerCode(state: IUserState, num: number) { function setServerCode(state: IUserState, num: number) {
@@ -221,8 +221,6 @@ namespace Actions {
async function resetpwd(context, paramquery: IUserState) { async function resetpwd(context, paramquery: IUserState) {
const usertosend = { const usertosend = {
keyappid: process.env.PAO_APP_ID,
idapp: process.env.APP_ID,
email: paramquery.email, email: paramquery.email,
password: paramquery.password, password: paramquery.password,
tokenforgot: paramquery.tokenforgot tokenforgot: paramquery.tokenforgot
@@ -245,8 +243,6 @@ namespace Actions {
async function requestpwd(context, paramquery: IUserState) { async function requestpwd(context, paramquery: IUserState) {
const usertosend = { const usertosend = {
keyappid: process.env.PAO_APP_ID,
idapp: process.env.APP_ID,
email: paramquery.email email: paramquery.email
} }
console.log(usertosend) console.log(usertosend)
@@ -265,8 +261,6 @@ namespace Actions {
async function vreg(context, paramquery: ILinkReg) { async function vreg(context, paramquery: ILinkReg) {
const usertosend = { const usertosend = {
keyappid: process.env.PAO_APP_ID,
idapp: process.env.APP_ID,
idlink: paramquery.idlink idlink: paramquery.idlink
} }
console.log(usertosend) console.log(usertosend)
@@ -301,12 +295,10 @@ namespace Actions {
return bcrypt.hash(authData.password, bcrypt.genSaltSync(12)) return bcrypt.hash(authData.password, bcrypt.genSaltSync(12))
.then((hashedPassword: string) => { .then((hashedPassword: string) => {
const usertosend = { const usertosend = {
keyappid: process.env.PAO_APP_ID,
lang: mylang, lang: mylang,
email: authData.email, email: authData.email,
password: String(hashedPassword), password: String(hashedPassword),
username: authData.username, username: authData.username,
idapp: process.env.APP_ID
} }
console.log(usertosend) console.log(usertosend)
@@ -336,7 +328,7 @@ namespace Actions {
verified_email: false verified_email: false
}) })
const now = new Date() const now = tools.getDateNow()
// const expirationDate = new Date(now.getTime() + myres.data.expiresIn * 1000); // const expirationDate = new Date(now.getTime() + myres.data.expiresIn * 1000);
const expirationDate = new Date(now.getTime() * 1000) const expirationDate = new Date(now.getTime() * 1000)
localStorage.setItem(tools.localStorage.lang, state.lang) localStorage.setItem(tools.localStorage.lang, state.lang)
@@ -371,7 +363,7 @@ namespace Actions {
try { try {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
sub = await navigator.serviceWorker.ready sub = await navigator.serviceWorker.ready
.then(function(swreg) { .then(function (swreg) {
console.log('swreg') console.log('swreg')
const sub = swreg.pushManager.getSubscription() const sub = swreg.pushManager.getSubscription()
return sub return sub
@@ -393,8 +385,6 @@ namespace Actions {
const usertosend = { const usertosend = {
username: authData.username, username: authData.username,
password: authData.password, password: authData.password,
idapp: process.env.APP_ID,
keyappid: process.env.PAO_APP_ID,
lang: state.lang, lang: state.lang,
subs: sub, subs: sub,
options options
@@ -437,7 +427,7 @@ namespace Actions {
verified_email verified_email
}) })
const now = new Date() const now = tools.getDateNow()
// const expirationDate = new Date(now.getTime() + myres.data.expiresIn * 1000); // const expirationDate = new Date(now.getTime() + myres.data.expiresIn * 1000);
const expirationDate = new Date(now.getTime() * 1000) const expirationDate = new Date(now.getTime() * 1000)
localStorage.setItem(tools.localStorage.lang, state.lang) localStorage.setItem(tools.localStorage.lang, state.lang)
@@ -487,13 +477,7 @@ namespace Actions {
await GlobalStore.actions.clearDataAfterLogout() await GlobalStore.actions.clearDataAfterLogout()
const usertosend = { const riscall = await Api.SendReq('/users/me/token', 'DELETE', null)
keyappid: process.env.PAO_APP_ID,
idapp: process.env.APP_ID
}
console.log(usertosend)
const riscall = await Api.SendReq('/users/me/token', 'DELETE', usertosend)
.then((res) => { .then((res) => {
console.log(res) console.log(res)
}).then(() => { }).then(() => {
@@ -510,6 +494,7 @@ namespace Actions {
async function setGlobal(loggedWithNetwork: boolean) { async function setGlobal(loggedWithNetwork: boolean) {
state.isLogged = true state.isLogged = true
console.log('state.isLogged')
GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(tools.localStorage.leftDrawerOpen) === 'true') GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(tools.localStorage.leftDrawerOpen) === 'true')
GlobalStore.mutations.setCategorySel(localStorage.getItem(tools.localStorage.categorySel)) GlobalStore.mutations.setCategorySel(localStorage.getItem(tools.localStorage.categorySel))
@@ -517,13 +502,14 @@ namespace Actions {
await GlobalStore.actions.loadAfterLogin() await GlobalStore.actions.loadAfterLogin()
.then(() => { .then(() => {
Todos.actions.dbLoadTodo({ checkPending: true }) Todos.actions.dbLoad({ checkPending: true })
Projects.actions.dbLoad({ checkPending: true, onlyiffirsttime: true })
}) })
} }
async function autologin_FromLocalStorage(context) { async function autologin_FromLocalStorage(context) {
try { try {
// console.log('*** autologin_FromLocalStorage ***') console.log('*** autologin_FromLocalStorage ***')
// INIT // INIT
UserStore.state.lang = tools.getItemLS(tools.localStorage.lang) UserStore.state.lang = tools.getItemLS(tools.localStorage.lang)
@@ -534,7 +520,7 @@ namespace Actions {
} }
const expirationDateStr = localStorage.getItem(tools.localStorage.expirationDate) const expirationDateStr = localStorage.getItem(tools.localStorage.expirationDate)
const expirationDate = new Date(String(expirationDateStr)) const expirationDate = new Date(String(expirationDateStr))
const now = new Date() const now = tools.getDateNow()
if (now >= expirationDate) { if (now >= expirationDate) {
console.log('!!! Login Expired') console.log('!!! Login Expired')
return false return false
@@ -566,6 +552,22 @@ namespace Actions {
} }
} }
/*
async function refreshUserInfos(){
let {token, refresh_token} = JWT.fetch();
if (!!token) {
try {
let { data } = await Api.checkSession({token, refresh_token});
JWT.set(data);
let userData = await jwtDecode(data.token);
LoginModule.mutations.updateUserInfos({userData, token: data.token});
} catch(e) {
Mutations.mutations.disconnectUser();
}
}
}
*/
export const actions = { export const actions = {
autologin_FromLocalStorage: b.dispatch(autologin_FromLocalStorage), autologin_FromLocalStorage: b.dispatch(autologin_FromLocalStorage),
logout: b.dispatch(logout), logout: b.dispatch(logout),

View File

@@ -6,5 +6,7 @@ export const costanti = {
}, },
CONFIG_ID_CFG: '1', CONFIG_ID_CFG: '1',
CONFIG_ID_STATE_CONN: '2', CONFIG_ID_STATE_CONN: '2',
CONFIG_ID_SHOW_TYPE_TODOS: '3' CONFIG_ID_SHOW_TYPE_TODOS: '3',
MAX_PHASES: 5
} }

View File

@@ -2,3 +2,4 @@ export {storeBuilder} from './Store/Store'
export {default as GlobalStore} from './GlobalStore' export {default as GlobalStore} from './GlobalStore'
export {default as UserStore} from './UserStore' export {default as UserStore} from './UserStore'
export {default as Todos} from './Todos' export {default as Todos} from './Todos'
export {default as Projects} from './Projects'

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
export const translation = {
it: {
fase: 'Fase',
end: ''
},
es: {
fase: 'Fase',
end: ''
},
enUs: {
fase: 'Phase',
end: ''
}
}

View File

@@ -5,6 +5,7 @@ import { IGlobalState } from 'model'
import { Route } from 'vue-router' import { Route } from 'vue-router'
import { getStoreBuilder } from 'vuex-typex' import { getStoreBuilder } from 'vuex-typex'
import { IProgressState } from '@types'
export interface RootState { export interface RootState {
GlobalModule: IGlobalState GlobalModule: IGlobalState

9
src/typings/ProgressBar.d.ts vendored Normal file
View File

@@ -0,0 +1,9 @@
export interface IProgressState {
percent: number,
show: boolean,
canSuccess: boolean,
duration: number,
height: string,
color: string,
failedColor: string,
}

View File

@@ -2,7 +2,7 @@
// export * from './GlobalState.d' // export * from './GlobalState.d'
export * from './ProgressBar.d'
export interface IResponse<T> { export interface IResponse<T> {
success?: boolean, success?: boolean,

View File

@@ -85,7 +85,7 @@ declare module 'vuelidate' {
*/ */
required?: boolean required?: boolean
/** /**
* Checks for equality with a given property. Locator might be either a sibling property name or a function, that will get your component as this and nested model which sibling properties under second parameter. * Checks for equality with a given property. Locator might be either a sibling property nametranslate or a function, that will get your component as this and nested model which sibling properties under second parameter.
*/ */
sameAs?: boolean sameAs?: boolean
/** /**
@@ -231,7 +231,7 @@ declare module 'vuelidate/lib/validators' {
*/ */
function required(value: any): boolean function required(value: any): boolean
/** /**
* Checks for equality with a given property. Locator might be either a sibling property name or a function, that will get your component as this and nested model which sibling properties under second parameter. * Checks for equality with a given property. Locator might be either a sibling property nametranslate or a function, that will get your component as this and nested model which sibling properties under second parameter.
*/ */
function sameAs(locator: any): (value: any, vm?: any) => boolean function sameAs(locator: any): (value: any, vm?: any) => boolean
/** /**

10
src/utils/methods.ts Normal file
View File

@@ -0,0 +1,10 @@
export function timeout(duration: number): Promise<{}> {
return new Promise((resolve, reject) => {
setTimeout(() => {resolve()}, duration);
})
}
export function randomNumber(min: number, max: number) : number {
return Math.floor((Math.random() * max) + min);
}

View File

@@ -33,8 +33,7 @@ export default class TableOnlyView extends Vue {
this.loading = true this.loading = true
setTimeout(() => { setTimeout(() => {
this.serverPagination = props.pagination this.serverPagination = props.pagination
let let table = this.$refs.table,
table = this.$refs.table,
rows = GlobalStore.state.cfgServer.slice(), rows = GlobalStore.state.cfgServer.slice(),
{ page, rowsPerPage, sortBy, descending } = props.pagination { page, rowsPerPage, sortBy, descending } = props.pagination

View File

@@ -21,9 +21,9 @@
</q-table> </q-table>
</q-page> </q-page>
</template> </template>
<script lang="ts" src="./tableOnlyView.ts"> <script lang="ts" src="tableOnlyView.ts">
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './tableOnlyView.scss'; @import 'tableOnlyView';
</style> </style>

View File

@@ -3,7 +3,6 @@ import { Component } from 'vue-property-decorator'
import { GlobalStore } from '@store' import { GlobalStore } from '@store'
@Component({}) @Component({})
export default class CfgServer extends Vue { export default class CfgServer extends Vue {
public loading: boolean = false public loading: boolean = false
@@ -39,21 +38,20 @@ export default class CfgServer extends Vue {
public keysel: string = '' public keysel: string = ''
public userIdsel: string = '' public userIdsel: string = ''
get tableClass() {
get tableClass () {
if (this.dark) { if (this.dark) {
return 'bg-black' return 'bg-black'
} }
} }
selItem(item) { public selItem(item) {
console.log('item', item) console.log('item', item)
this.keysel = item.chiave this.keysel = item.chiave
this.userIdsel = item.userid this.userIdsel = item.userid
console.log('this.keysel', this.keysel) console.log('this.keysel', this.keysel)
} }
SaveValue(newVal, valinitial) { public SaveValue(newVal, valinitial) {
console.log('SaveValue', newVal, 'selected', this.selected) console.log('SaveValue', newVal, 'selected', this.selected)
const mydata = { const mydata = {
@@ -65,9 +63,8 @@ export default class CfgServer extends Vue {
GlobalStore.actions.saveCfgServerKey(mydata) GlobalStore.actions.saveCfgServerKey(mydata)
} }
created() { public created() {
this.serverData = GlobalStore.state.cfgServer.slice() // [{ chiave: 'chiave1', valore: 'valore 1' }] this.serverData = GlobalStore.state.cfgServer.slice() // [{ chiave: 'chiave1', valore: 'valore 1' }]
// this.serverData = GlobalStore.state.cfgServer.slice() // this.serverData = GlobalStore.state.cfgServer.slice()
} }
} }

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