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",
"version": "0.0.4",
"version": "0.0.5",
"private": true,
"keywords": [
"freeplanet",
@@ -12,6 +12,7 @@
"lint": "tslint --project tsconfig.json",
"lint:fix": "tslint --project tsconfig.json --fix",
"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",
"pwa": "NODE_ENV=development NODE_OPTIONS=--max_old_space_size=4096 DEBUG=v8:* quasar dev -m pwa",
"test:unit": "jest",
@@ -25,15 +26,20 @@
"generate-sw": "workbox generateSW workbox-config.js"
},
"dependencies": {
"@babel/plugin-transform-runtime": "^7.4.0",
"@babel/runtime": "^7.0.0",
"@quasar/extras": "^1.1.0",
"@types/vuelidate": "^0.7.0",
"@vue/eslint-config-standard": "^4.0.0",
"acorn": "^6.0.0",
"autoprefixer": "^9.5.0",
"axios": "^0.18.0",
"babel-runtime": "^6.26.0",
"babel-eslint": "^10.0.1",
"bcrypt-nodejs": "0.0.3",
"bcryptjs": "^2.4.3",
"dotenv": "^6.1.0",
"element-ui": "^2.3.6",
"eslint-plugin-vue": "^5.2.2",
"google-translate-api": "^2.3.0",
"graphql": "^0.13.2",
"graphql-tag": "^2.8.0",
@@ -42,13 +48,13 @@
"js-cookie": "^2.2.0",
"localforage": "^1.7.3",
"normalize.css": "^8.0.0",
"npm": "^6.4.1",
"npm": "^6.9.0",
"nprogress": "^0.2.0",
"quasar": "^1.0.0-beta.10",
"quasar": "^1.0.0-beta.11",
"quasar-extras": "^2.0.8",
"register-service-worker": "^1.0.0",
"vee-validate": "^2.1.2",
"vue": "^2.5.17",
"vue": "^2.6.10",
"vue-class-component": "^6.3.2",
"vue-i18n": "^8.1.0",
"vue-idb": "^0.2.0",
@@ -62,26 +68,29 @@
"vuex-class": "^0.3.1",
"vuex-module-decorators": "^0.4.3",
"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": {
"@babel/code-frame": "7.0.0-beta.54",
"@babel/core": "7.0.0-beta.50",
"@babel/generator": "7.0.0-beta.54",
"@babel/helpers": "7.0.0-beta.54",
"@babel/parser": "7.0.0-beta.54",
"@babel/preset-env": "7.0.0-beta.54",
"@babel/preset-react": "7.0.0",
"@babel/runtime": "7.0.0-beta.54",
"@babel/template": "7.0.0-beta.54",
"@babel/traverse": "7.0.0-beta.54",
"@babel/types": "7.0.0-beta.54",
"@babel/cli": "^7.2.3",
"@babel/core": "^7.4.0",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-decorators": "^7.0.0",
"@babel/plugin-proposal-export-namespace-from": "^7.0.0",
"@babel/plugin-proposal-function-sent": "^7.0.0",
"@babel/plugin-proposal-json-strings": "^7.0.0",
"@babel/plugin-proposal-numeric-separator": "^7.0.0",
"@babel/plugin-proposal-throw-expressions": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.4.2",
"@quasar/app": "^1.0.0-beta.11",
"@quasar/quasar-app-extension-typescript": "^1.0.0-alpha.11",
"@types/dotenv": "^4.0.3",
"@types/jest": "^23.1.4",
"@types/js-cookie": "^2.1.0",
"@types/node": "11.9.5",
"@types/node": "^11.9.5",
"@types/nprogress": "^0.0.29",
"@types/webpack-env": "^1.13.6",
"@vue/babel-preset-app": "3.1.1",
@@ -89,15 +98,18 @@
"@vue/cli-plugin-e2e-cypress": "^3.0.1",
"@vue/cli-plugin-pwa": "^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/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",
"eslint": "^5.5.0",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^2.8.1",
"http-proxy-middleware": "^0.17.0",
"jest": "^23.6.0",
"http-proxy-middleware": "^0.19.1",
"jest": "^24.5.0",
"json-loader": "^0.5.4",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
@@ -105,13 +117,13 @@
"sass-loader": "^7.1.0",
"strip-ansi": "=3.0.1",
"ts-jest": "^23.0.0",
"ts-loader": "^5.3.0",
"ts-loader": "^5.3.3",
"tslint": "^5.11.0",
"tslint-config-standard": "^8.0.1",
"tslint-loader": "^3.4.3",
"typescript": "^3.1.6",
"typescript": "^3.3.3333",
"vue-cli-plugin-element-ui": "^1.1.2",
"vue-template-compiler": "^2.5.17",
"vue-template-compiler": "^2.6.10",
"vueify": "^9.4.1",
"webpack": "^4.29.6",
"webpack-dev-middleware": "^3.2.0",
@@ -128,5 +140,8 @@
"> 1%",
"last 2 versions",
"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
.set('@components', helpers.root('src/components/index.ts'))
// .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('@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('@images', helpers.root('src/statics/images/*'))
.set('@classes', helpers.root('src/classes/index.ts'))
@@ -25,6 +25,7 @@ const extendTypescriptToWebpack = (config) => {
.set('@utils', helpers.root('src/utils/*'))
.set('@router', helpers.root('src/router/index.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('@paths', helpers.root('src/store/Api/ApiRoutes.ts'))
.set('@types', helpers.root('src/typings/index.ts'))
@@ -169,10 +170,13 @@ module.exports = function (ctx) {
'QPageScroller',
'QAvatar',
'QImg',
'QSplitter',
'QSeparator',
'QCarouselSlide'
],
directives: [
'Ripple',
'ClosePopup'
],
// Quasar 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)
async function writeData(table, data) {
// console.log('writeData', table, data);
await idbKeyval.setdata(table, data);
}
async function readAllData(table) {
// console.log('readAllData', table);
return await idbKeyval.getalldata(table);
@@ -123,59 +123,73 @@ if (workbox) {
// console.log(' routing.registerRoute function declaration:')
workbox.routing.registerRoute(
new RegExp(cfgenv.serverweb + '/todos/'),
function (args) {
console.log('registerRoute! ', cfgenv.serverweb + '/todos/')
function Execute_Fetch(table, args) {
console.log('Execute_Fetch registerRoute! ', cfgenv.serverweb + '/' + table + '/')
// console.log('DATABODY:', args.event.request.body)
let myres = null
// return fetch(args.event.request, args.event.headers)
return fetch(args.event.request, args.event.headers)
.then(function (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) {
const clonedRes = res.clone();
// console.log('1) clearAllData(categories)')
return clearAllData('categories')
let secondatab = ''
if (table === 'todos') {
secondatab = 'categories'
}
console.log('1) clearAllData: ', table)
return clearAllData(table)
.then(() => {
if (secondatab !== '') {
// console.log('2) clearAllData(todos)')
return clearAllData('todos')
return clearAllData(secondatab)
.then(() => {
// console.log('3) ....return clonedRes')
return clonedRes
})
} else {
return clonedRes
}
})
}
})
.then((clonedRes) => {
// console.log(' 3) ')
if (clonedRes !== undefined)
if (!!clonedRes)
return clonedRes.json();
return null
})
.then(data => {
// console.log(' 4) data = ', data)
if (data) {
if (data.todos) {
myarr = idbKeyval.getArrayByTable(table, data)
if (myarr) {
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(() => {
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 (let indrec in data.todos[indrecCat]) {
for (const arrsing of myarr) {
for (const rec of arrsing) {
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)
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) {
return (routeData.event.request.headers.get('accept').includes('text/html'));
@@ -236,12 +258,12 @@ if (workbox) {
workbox.routing.registerRoute(
new RegExp(/\.(?:js|css|font)$/),
new workbox.strategies.StaleWhileRevalidate( {
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'js-css-fonts',
}),
);
/*
/*
workbox.routing.registerRoute(
new RegExp('https://cdnjs.coudflare.com/ajax/libs/material-design-lite/1.3.0/material.indigo-pink.min.css'),
workbox.strategies.staleWhileRevalidate({
@@ -253,7 +275,7 @@ if (workbox) {
]
})
);
*/
*/
// Storage
workbox.routing.registerRoute(
@@ -283,7 +305,7 @@ if (workbox) {
})
);
/*
/*
workbox.routing.registerRoute(
new RegExp(/^http/),
workbox.strategies.networkFirst({
@@ -296,7 +318,7 @@ if (workbox) {
]
})
);
*/
*/
workbox.routing.registerRoute(
@@ -514,7 +536,7 @@ self.addEventListener('notificationclick', function (event) {
return c.visibilityState === 'visible';
});
if (client !== undefined) {
if (!!client) {
client.navigate(notification.data.url);
client.focus();
} else {

View File

@@ -50,3 +50,26 @@
font-size: 1.1rem;
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 { 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 }) => {
// ******************************************
// *** 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
// runs the default `next()` callback but also triggers
// 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) => {
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
if (timeoutId !== undefined) {
if (!!timeoutId) {
clearTimeout(timeoutId)
}

View File

@@ -10,9 +10,11 @@ export async function askConfirm($q: any, mytitle, mytext, ok, cancel) {
push: true
},
title: mytitle
}).then((ris) => {
return ris
}).catch(() => {
}).onOk(() => {
console.log('OK')
return true
}).onCancel(() => {
console.log('CANCEL')
return false
})
} 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'
if (oldValue !== undefined) {
if (!!oldValue) {
tools.showNotif(this.$q, this.$t('connection') + ` ${value}`, {
color,
icon: 'wifi'
@@ -262,12 +262,12 @@ export default class Header extends Vue {
function updateOnlineStatus(event) {
if (navigator.onLine) {
// console.log('EVENT ONLINE!')
console.log('EVENT ONLINE!')
// handle online status
GlobalStore.mutations.setStateConnection('online')
mythis.changeIconConn()
} else {
// console.log('EVENT OFFLINE!')
console.log('EVENT OFFLINE!')
// handle offline status
GlobalStore.mutations.setStateConnection('offline')
mythis.changeIconConn()

View File

@@ -47,11 +47,11 @@
<!--
<div v-if="isAdmin">
<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 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>
</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 './logo'
export * from './CProgress'
export * from './CDate'

View File

@@ -1,52 +1,11 @@
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
import { TimelineLite, Back } from 'gsap'
import $ from 'jquery'
import Timeout = NodeJS.Timeout
import { tools } from "@src/store/Modules/tools"
import { tools } from '@src/store/Modules/tools'
@Component({
})
export default class Logo extends Vue {
public logoimg: string = ''
public created() {
this.logoimg = '../../' + tools.getimglogo()
this.animate()
get logoimg() {
return '../../' + tools.getimglogo()
}
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>
<q-page>
<div class="panel">
<div class="divtitlecat">
<div v-if="!!title" class="divtitlecat">
<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">
<q-btn push
size="sm"
icon="settings">
<q-menu id="popconfig" self="top right">
<q-list link separator no-border class="todo-menu">
@@ -51,10 +52,10 @@
</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;"
:after="[{icon: 'arrow_forward', content: true, handler () {}}]"
v-on:keyup.enter="insertTodo(true)">
v-on:keyup.enter="dbInsert(true)">
<template v-slot:prepend>
<q-icon name="add"/>
</template>
@@ -63,22 +64,22 @@
<div style="display: none">{{ prior = 0, priorcomplet = false }}</div>
<div>
<!--<q-infinite-scroll :handler="loadMoreTodo" :offset="7">-->
<div class="container" v-dragula="todos_dacompletare(categoryAtt)" drake="first">
<div :id="getmyid(mytodo._id)" :index="index"
v-for="(mytodo, index) in todos_dacompletare(categoryAtt)"
<div class="container" v-dragula="items_dacompletare(categoryAtt)" :drake="dragname">
<div :id="tools.getmyid(mytodo._id)" :index="index"
v-for="(mytodo, index) in items_dacompletare(categoryAtt)"
:key="mytodo._id" class="myitemdrag">
<div v-if="(prior !== mytodo.priority) && !mytodo.completed"
:class="getTitlePriority(mytodo.priority)">
<label>{{getPriorityByInd(mytodo.priority)}}</label>
<div v-if="(prior !== mytodo.priority) && mytodo.statustodo !== tools.Status.COMPLETED"
:class="tools.getTitlePriority(mytodo.priority)">
<label>{{tools.getPriorityByInd(mytodo.priority)}}</label>
</div>
<SingleTodo ref="single" @deleteItem="mydeleteItem(mytodo._id)" @eventupdate="updateitem"
@deselectAllRows="deselectAllRows" @onEnd="onEnd"
<SingleTodo ref="single" @deleteItemtodo="mydeleteitemtodo(mytodo._id)" @eventupdate="updateitemtodo"
@setitemsel="setitemsel" @deselectAllRowstodo="deselectAllRowstodo" @deselectAllRowsproj="deselectAllRowsproj" @onEnd="onEndtodo"
: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>
@@ -90,17 +91,17 @@
<!--<q-infinite-scroll :handler="loadMoreTodo" :offset="7">-->
<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)"
:key="mytodo._id" class="myitemdrag">
<SingleTodo ref="single" @deleteItem="mydeleteItem(mytodo._id)" @eventupdate="updateitem"
@deselectAllRows="deselectAllRows" @onEnd="onEnd"
<SingleTodo ref="single" @deleteItemtodo="mydeleteitemtodo(mytodo._id)" @eventupdate="updateitemtodo"
@setitemsel="setitemsel" @deselectAllRowstodo="deselectAllRowstodo" @deselectAllRowsproj="deselectAllRowsproj" @onEnd="onEndtodo"
: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>
@@ -108,12 +109,12 @@
</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;"
color="blue-12"
:label="$t('todo.insertbottom')"
:after="[{icon: 'arrow_forward', content: true, handler () {}}]"
v-on:keyup.enter="insertTodo(false)"/>
v-on:keyup.enter="dbInsert(false)"/>
<br>
@@ -147,8 +148,8 @@
</template>
<script lang="ts" src="./todo.ts">
<script lang="ts" src="./CTodo.ts">
</script>
<style lang="scss" scoped>
@import './todo.scss';
@import './CTodo.scss';
</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-style: solid;
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) {
display: none;
}
color: #777;
color: #939393;
height: $heightitem;
line-height: $heightitem;
//visibility: hidden;
@@ -196,16 +196,6 @@ $heightdescr: 20px;
.colProgress {
}
.lowperc {
color: red;
}
.medperc {
color: blue;
}
.highperc {
color: green;
}
.percompleted {
color: $colcompleted
}
@@ -218,7 +208,7 @@ $heightdescr: 20px;
}
.data-item {
max-width: 78px;
max-width: 100px;
@media (max-width: 600px) {
max-width: 22px;
}

View File

@@ -10,9 +10,10 @@ import { SubMenus } from '../SubMenus'
import { date } from 'quasar'
import { askConfirm } from '../../../classes/routinestd'
import { CDate } from '../../CDate'
@Component({
components: { SubMenus },
components: { SubMenus, CDate },
name: 'SingleTodo'
})
export default class SingleTodo extends Vue {
@@ -22,7 +23,7 @@ export default class SingleTodo extends Vue {
public classCompleted: string = ''
public classDescr: 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 iconPriority: string = ''
public popover: boolean = false
@@ -42,11 +43,11 @@ export default class SingleTodo extends Vue {
public $q: any
@Prop({ required: true }) public itemtodo: ITodo
get tools() {
return tools
}
// @Watch('itemtodo.completed') valueChanged() {
// this.watchupdate('completed')
// }
@Prop({ required: true }) public itemtodo: ITodo
@Watch('itemtodo.enableExpiring') public valueChanged4() {
this.watchupdate('enableExpiring')
@@ -62,6 +63,33 @@ export default class SingleTodo extends Vue {
@Watch('itemtodo.descr') public valueChanged5() {
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() {
@@ -93,6 +121,7 @@ export default class SingleTodo extends Vue {
}
public watchupdate(field = '') {
console.log('watchupdate', field)
this.$emit('eventupdate', {myitem: this.itemtodo, field } )
this.updateicon()
}
@@ -110,9 +139,9 @@ export default class SingleTodo extends Vue {
if (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 = ''
if (this.itemtodo.completed) {
if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
this.percentageProgress = 100
this.classCompleted += ' icon_completed'
this.classDescr += ' status_completed'
@@ -126,27 +155,22 @@ export default class SingleTodo extends Vue {
this.menuProgress = 'menuProgress'
this.percProgress = 'percProgress'
let mycolcl = ''
if (this.itemtodo.progress < 33) {
mycolcl = ' lowperc'
} else if (this.itemtodo.progress < 66) {
mycolcl = ' medperc'
} else {
mycolcl = ' highperc'
}
let mycolcl = ' ' + tools.getProgressClassColor(this.itemtodo.progress)
this.colProgress = tools.getProgressColor(this.itemtodo.progress)
if (this.itemtodo.completed) {
if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
mycolcl = ' percompleted'
this.colProgress = 'gray'
}
this.colProgress = mycolcl
this.colProgress = tools.getProgressColor(this.itemtodo.progress)
this.menuProgress += mycolcl
this.percProgress += mycolcl
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'
}
@@ -174,10 +198,6 @@ export default class SingleTodo extends Vue {
}
public getstrDate(mytimestamp) {
return date.formatDate(mytimestamp, 'DD-MM-YY')
}
public created() {
this.precDescr = this.itemtodo.descr
this.updateicon()
@@ -197,7 +217,8 @@ export default class SingleTodo extends Vue {
if (!this.sel) {
if (!this.inEdit) {
this.$emit('deselectAllRows', this.itemtodo, true)
this.$emit('deselectAllRowsproj', null, false, false)
this.$emit('deselectAllRowstodo', this.itemtodo, true)
if (!this.sel) {
this.selectRiga()
@@ -240,11 +261,13 @@ export default class SingleTodo extends Vue {
}
public clickRow() {
this.$emit('setitemsel', null)
this.$emit('setitemsel', this.itemtodo)
this.clickRiga()
}
public editTodo() {
if (!this.itemtodo.completed) {
if (this.itemtodo.statustodo !== tools.Status.COMPLETED) {
// console.log('INIZIO - editTodo')
this.$emit('click')
this.precDescr = this.itemtodo.descr
@@ -271,7 +294,7 @@ export default class SingleTodo extends Vue {
theField = this.$refs[elem] as HTMLInputElement
}
if (theField !== undefined) {
if (!!theField) {
theField.focus()
}
// console.log('focus()')
@@ -285,8 +308,9 @@ export default class SingleTodo extends Vue {
}
// console.log('exitEdit')
this.inEdit = false
this.updateClasses
this.$emit('deselectAllRows', this.itemtodo, false, singola)
this.updateClasses()
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()
}
public aggiornaProgress(value, initialval){
public aggiornaProgress(value, initialval) {
if (value !== initialval) {
this.itemtodo.progress = value
this.itemtodo.progress = parseInt(value, 10)
this.updatedata('progress')
this.deselectAndExitEdit()
}
@@ -379,11 +403,12 @@ export default class SingleTodo extends Vue {
public setCompleted() {
// console.log('setCompleted')
this.itemtodo.completed = !this.itemtodo.completed
this.updateicon()
this.updatedata('completed')
if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
this.itemtodo.statustodo = tools.Status.OPENED
} else {
this.itemtodo.statustodo = tools.Status.COMPLETED
}
this.watchupdate('statustodo')
this.deselectAndExitEdit()
}
@@ -396,20 +421,20 @@ export default class SingleTodo extends Vue {
public updateicon() {
// console.log('updateicon')
if (this.itemtodo.completed) {
if (this.itemtodo.statustodo === tools.Status.COMPLETED) {
this.iconCompleted = 'check_circle'
}
else {
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'
} // expand_less
else if (this.itemtodo.priority === tools.Todos.PRIORITY_NORMAL) {
else if (this.itemtodo.priority === tools.Priority.PRIORITY_NORMAL) {
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'
} // expand_more
@@ -417,7 +442,7 @@ export default class SingleTodo extends Vue {
}
public removeitem(id) {
this.$emit('deleteItem', id)
this.$emit('deleteItemtodo', id)
}
public enableExpiring() {
@@ -458,7 +483,26 @@ export default class SingleTodo extends Vue {
const cancelstr = this.$t('dialog.cancel')
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) => {
console.log('ris', ris)
if (ris) {
@@ -467,6 +511,7 @@ export default class SingleTodo extends Vue {
}).catch((err) => {
})
*/
}
}

View File

@@ -4,12 +4,12 @@
<q-btn push flat
:class="classCompleted"
:icon="iconCompleted"
@click.native="setCompleted">
@click="setCompleted">
</q-btn>
</div>
<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"
autogrow
borderless
@@ -56,45 +56,21 @@
<div v-if="itemtodo.enableExpiring" :class="classExpiring">
<span class="data_string">{{getstrDate(itemtodo.expiring_at)}}</span>
<q-icon name="event" class="cursor-pointer" style="padding: 2px;">
<q-popup-proxy>
<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>-->
<CDate :mydate="itemtodo.expiring_at" @input="itemtodo.expiring_at = new Date(arguments[0])"
data_class="data_string">
</CDate>
</div>
<div v-if="isTodo()" class="flex-item pos-item " @mousedown="clickRiga">
<q-btn push
<q-btn flat
:class="clButtPopover"
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"
@setPriority="setPriority"></SubMenus>
</q-menu>
</q-btn>
</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>
</template>

View File

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

View File

@@ -1,3 +1,3 @@
export * from './SingleTodo'
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) => {
/*
if (error.constructor.name === 'FirebaseError') {
if (error.constructor.nametranslate === 'FirebaseError') {
Firebase(error)
return
}

View File

@@ -1,18 +1,20 @@
import { Todos, UserStore } from '@store'
import { Projects, Todos, UserStore } from '@store'
import _ from 'lodash'
import store, { GlobalStore } from '../store'
import { GlobalStore } from '../store/Modules'
import { idbKeyval as storage } from '../js/storage.js'
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) {
const data: ICfgData = {}
data._id = costanti.CONFIG_ID_CFG
data.lang = UserStore.state.lang
data.token = UserStore.state.x_auth_token
data.userId = UserStore.state.userId
const data: ICfgData = {
_id: costanti.CONFIG_ID_CFG,
lang: UserStore.state.lang,
token: UserStore.state.x_auth_token,
userId: UserStore.state.userId
}
writeConfigIndexDb('config', data)
}
@@ -21,52 +23,54 @@ function writeConfigIndexDb(context, data) {
// console.log('writeConfigIndexDb', data)
storage.setdata('config', data)
.then((ris) => {
return true
})
}
async function readfromIndexDbToStateTodos(context, table) {
console.log('*** readfromIndexDbToStateTodos ***')
async function readfromIndexDbToState(context, table) {
console.log('*** readfromIndexDbToState ***', table)
return await storage.getalldata(table)
.then((reccat) => {
// console.log('&&&&&&& readfromIndexDbToStateTodos OK: Num RECORD: ', records.length)
// console.log('&&&&&&& readfromIndexDbToState OK: Num RECORD: ', records.length)
if (table === 'categories') {
console.log('reccat', reccat)
Todos.state.categories = []
for (const indcat in reccat) {
Todos.state.categories.push(reccat[indcat].valore)
for (const elem of reccat) {
Todos.state.categories.push(elem.valore)
}
console.log('ARRAY Categories', Todos.state.categories)
table = 'todos'
return storage.getalldata('todos')
return storage.getalldata(table)
.then((records) => {
console.log('todos records', records)
// console.log('&&&&&&& readfromIndexDbToStateTodos OK: Num RECORD: ', records.length)
console.log(table + ' records', records)
// console.log('&&&&&&& readfromIndexDbToState OK: Num RECORD: ', records.length)
/*
for (const myrec in records) {
const cat = myrec.category
const indcat = state.categories.indexOf(cat)
if (Todos.state.todos[indcat] === undefined) {
Todos.state.todos[indcat] = {}
const arrinit = []
for (const mytodo of records) {
const cat = mytodo.category
const indcat = Todos.state.categories.indexOf(cat)
if (arrinit.indexOf(indcat) < 0) {
Todos.state.todos[indcat] = []
arrinit.push(indcat)
}
// add to the right array
Todos.state.todos[indcat].push(myrec)
Todos.state.todos[indcat].push(mytodo)
}
*/
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) => {
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
}
return await storage.setdata(table, datakey)
} else if (cmd === 'updatefromIndexedDbToStateTodo') {
return await readfromIndexDbToStateTodos(context, table)
} else if (cmd === 'updatefromIndexedDbToState') {
return await readfromIndexDbToState(context, table)
} else if (cmd === 'readall') {
if (GlobalStore) {
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'
function translate(params) {
@@ -8,7 +8,7 @@ function translate(params) {
const stringa = messages[lang]
let ris = stringa
if (ris !== undefined) {
if (!!ris) {
msg.forEach((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
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.
*
* @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
/**
* 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.
*
* @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.
*
* @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/}
* @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
* 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 traditional A Boolean indicating whether to perform a traditional "shallow" serialization.
@@ -2772,14 +2772,14 @@ interface JQueryStatic<TElement extends Node = HTMLElement> {
// endregion
// region (context, name)
// region (context, nametranslate)
/**
* 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 name The name 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 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 nametranslate argument.
* @see {@link https://api.jquery.com/jQuery.proxy/}
* @since 1.4
* @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.
*
* @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.
* An array of functions to replace the current queue contents.
* @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.
* 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.
* @see {@link https://api.jquery.com/addClass/}
* @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.
*
* @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()).
* 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.
@@ -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.
*
* @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/}
* @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.
*
* @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/}
* @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.
*
* @param propertyName A CSS property name.
* @param propertyName A CSS property nametranslate.
* @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
* 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>
/**
* 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 undefined
@@ -3441,7 +3441,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
data(obj: JQuery.PlainObject): this
/**
* 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.
* @see {@link https://api.jquery.com/data/}
@@ -3450,7 +3450,7 @@ interface JQuery<TElement extends Node = HTMLElement> extends Iterable<TElement>
data(key: string): any
/**
* 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/}
* @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.
*
* @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/}
* @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.
*
* @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/}
* @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
* 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/}
* @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.
*
* @param className The class name to search for.
* @param className The class nametranslate to search for.
* @see {@link https://api.jquery.com/hasClass/}
* @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.
*
* @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
* old property value as arguments. Within the function, the keyword this refers to the current element.
* @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.
*
* @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.
* @see {@link https://api.jquery.com/prop/}
* @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.
*
* @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/}
* @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.
*
* @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).
* @see {@link https://api.jquery.com/pushStack/}
* @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.
*
* @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.
* An array of functions to replace the current queue contents.
* @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.
*
* @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/}
* @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.
*
* @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/}
* @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.
*
* @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 jumpToEnd A Boolean indicating whether to complete the current animation immediately. Defaults to false.
* @see {@link https://api.jquery.com/stop/}
@@ -5584,7 +5584,7 @@ declare namespace JQuery {
*/
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
* 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
@@ -5594,8 +5594,8 @@ declare namespace JQuery {
*/
jsonp?: string | false
/**
* Specify the callback function name 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
* Specify the callback function nametranslate for a JSONP request. This value will be used instead of the
* 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
* 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
@@ -7436,7 +7436,7 @@ declare namespace JQuery {
/**
* 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
* 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.
*/
queue?: boolean | string

View File

@@ -47,7 +47,7 @@
name = String(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()
}

View File

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

View File

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

View File

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

View File

@@ -2,13 +2,13 @@
<div class="no-border">
<q-list class="rounded-borders text-primary">
<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-if="item.routes2">
<q-expansion-item
:header-inset-level="0.5"
:content-inset-level="0.5"
:label="$t(item.name)"
:header-inset-level="item.level_parent"
:content-inset-level="item.level_parent"
:label="getLabelByItem(item)"
:icon="item.materialIcon"
expand-icon-class="my-menu-separat"
header-class="my-menu"
@@ -16,12 +16,12 @@
>
<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"
expand-icon="map"
active-class="my-menu-active"
class="item item-link drawer-closer cursor-pointer my-menu"
:label="$t(child2.name)">
:label="getLabelByItem(child2)">
</q-expansion-item>
</q-expansion-item>

View File

@@ -5,6 +5,7 @@ import { GlobalStore } from '@store'
import { IPost } from '../../../model/index'
import './messagePopover.scss'
import { tools } from '@src/store/Modules/tools'
@Component({
})
@@ -27,7 +28,7 @@ export default class MessagePopover extends Vue {
public randomDate(): Date {
let myval = Math.floor(Math.random() * 10000000000)
return new Date(new Date().valueOf() - myval)
return new Date(tools.getTimestampsNow() - myval)
}
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'
export default function auth({ next, router }) {
const tok = tools.getItemLS(tools.localStorage.token)
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 { UserStore } from "@store"
import { tools } from '@src/store/Modules/tools'
export interface IPost {
title: string
@@ -55,13 +56,24 @@ export interface IGlobalState {
connData: IConnData
posts: IPost[]
menulinks: {}
listatodo: ITodoList[]
listatodo: IMenuList[]
arrConfig: IConfig[]
}
export interface ITodoList {
namecat: string
export interface IMenuList {
nametranslate: 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
descr?: string,
priority?: number,
completed?: boolean,
statustodo?: number,
created_at?: Date,
modify_at?: Date,
completed_at?: Date,
@@ -15,6 +15,12 @@ export interface ITodo {
pos?: number,
order?: number,
progress?: number
progressCalc?: number
phase?: number
assigned_to_userId?: string
hoursplanned?: number
hoursworked?: number
start_date?: Date
}
export interface IParamTodo {
@@ -31,7 +37,8 @@ export interface IDrag {
prioritychosen?: number
oldIndex?: number
newIndex?: number
category: string
category?: string
id_proj?: string
atfirst?: boolean
}
@@ -41,7 +48,7 @@ export interface ITodosState {
categories: string[]
// todos_changed: number
reload_fromServer: number
testpao: String
testpao: string
insidePending: boolean
visuLastCompleted: number
}

View File

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

View File

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

View File

@@ -28,7 +28,6 @@ export default class Home extends Vue {
public visibile: boolean = false
public cardvisible: string = 'hidden'
public displaycard: string = 'block'
public svgclass: string = 'svgclass'
public $t: any
// 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'

View File

@@ -2,7 +2,12 @@ import Vue from 'vue'
import VueRouter, { RouterMode } from 'vue-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)
/*
@@ -11,8 +16,8 @@ Vue.use(VueRouter)
*/
const Router = new VueRouter({
scrollBehavior: () => ({ y: 0 } as PositionResult),
routes: RouteConfig,
scrollBehavior: () => ({ x: 0, y: 0 } as PositionResult),
routes: routesList,
// Leave these as is and change from quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode
@@ -20,4 +25,159 @@ const Router = new VueRouter({
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

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 { tools } from '@src/store/Modules/tools'
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: '/',
name: RouteNames.home,
@@ -30,55 +58,74 @@ export const RouteConfig: VueRouteConfig[] = [
{
path: '/todo/:category',
name: 'Todos',
component: () => import('@/components/todos/todo/todo.vue'),
component: () => import('@/views/todo-list/todo-list.vue'),
meta: {
middleware: [auth]
requiresAuth: true,
async asyncData() {
await Todos.actions.dbLoad({ checkPending: false })
}
// middleware: [auth]
}
},
{
path: '/category',
name: 'category',
component: () => import('@/components/categories/category/category.vue')
component: () => import('@/views/categories/category/category.vue')
},
{
path: '/admin/cfgserv',
name: 'cfgserv',
component: () => import('@/components/admin/cfgServer/cfgServer.vue'),
component: () => import('@/views/admin/cfgServer/cfgServer.vue'),
meta: {
middleware: [auth]
requiresAuth: true
// middleware: [auth]
}
},
{
path: '/admin/testp1/:category',
name: 'Categories',
component: () => import('@/components/admin/testp1/testp1.vue')
component: () => import('@/views/admin/testp1/testp1.vue')
},
{
path: '/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',
component: () => import('@/views/login/requestresetpwd.vue'),
meta: { name: 'Reset your Password' }
meta: { nametranslate: 'Reset your Password' }
},
{
path: '/updatepwd',
component: () => import('@/views/login/updatepassword.vue'),
meta: { name: 'Update your Password' }
meta: { nametranslate: 'Update your Password' }
}
{
path: '/simpleform',
component: () => import('@/views/form/simpleForm/simpleForm.vue'),
meta: { name: 'SimpleForm' }
meta: { nametranslate: 'SimpleForm' }
},
{
path: '/embeeded',
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>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><strong>Produttori Locali Etici</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>' +
'</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>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>' +
'</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: {
title: 'Multi-piattaforma',
@@ -105,8 +107,7 @@ const messages = {
},
free: {
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>' +
'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. ' +
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. ' +
'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>. '
},
@@ -126,6 +127,7 @@ const messages = {
Admin: 'Admin',
Test1: 'Test1',
Test2: 'Test2',
Projects: 'Progetti'
},
components: {
authentication: {
@@ -217,7 +219,12 @@ const messages = {
insertbottom: 'Inserisci il Task in basso',
edit: 'Descrizione Task:',
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: {
status: 'Stato',
@@ -233,6 +240,20 @@ const messages = {
newVersionAvailable: 'Aggiorna'
},
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': {
dialog: {
@@ -320,6 +341,7 @@ const messages = {
'<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> 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> <strong>Cualquier persona que quiera participar</strong>, en la forma que considere más apropiada. </li>' +
'</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> 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>' +
'</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: {
title: 'Multi-plataforma',
@@ -340,8 +363,8 @@ const messages = {
},
free: {
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> ' +
'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. ' +
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>' +
'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>' +
'<strong>Gracias a todos por el apoyo</strong>. '
},
@@ -361,6 +384,7 @@ const messages = {
Admin: 'Administración',
Test1: 'Test1',
Test2: 'Test2',
Projects: 'Projectos',
},
components: {
authentication: {
@@ -445,7 +469,12 @@ const messages = {
insertbottom: 'Ingrese una nueva Tarea abajo',
edit: 'Descripción Tarea:',
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: {
status: 'Estado',
@@ -461,6 +490,20 @@ const messages = {
newVersionAvailable: 'Actualiza'
},
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': {
dialog: {
@@ -548,6 +591,7 @@ const messages = {
'<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> 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> <strong>Anyone who wants to participate</strong>, in the form it considers most appropriate. </li>' +
'</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> 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>' +
'</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: {
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. ' +
'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',
},
free: {
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> ' +
'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. ' +
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>.' +
'<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>' +
'<strong>Thanks all for the support</strong>. '
},
@@ -589,6 +634,7 @@ const messages = {
Admin: 'Admin',
Test1: 'Test1',
Test2: 'Test2',
Projects: 'Projects',
},
components: {
authentication: {
@@ -673,7 +719,12 @@ const messages = {
insertbottom: 'Insert Task at the bottom',
edit: 'Task Description:',
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: {
status: 'Status',
@@ -689,6 +740,20 @@ const messages = {
newVersionAvailable: 'Upgrade'
},
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)
}
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()
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,12 +9,13 @@ export { addAuthHeaders, removeAuthHeaders, API_URL } from './Instance'
import Paths from '@paths'
import { tools } from '@src/store/Modules/tools'
import { GlobalStore, UserStore } from '@modules'
import { GlobalStore, Projects, UserStore } from '@modules'
import globalroutines from './../../globalroutines/index'
import { serv_constants } from '@src/store/Modules/serv_constants'
import router from '@router'
import * as Types from '@src/store/Api/ApiTypes'
import { costanti } from '@src/store/Modules/costanti'
import * as ApiTables from '@src/store/Modules/ApiTables'
// const algoliaApi = new AlgoliaSearch()
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> {
mydata = {
...mydata,
keyappid: process.env.PAO_APP_ID,
idapp: process.env.APP_ID
}
// console.log('mydata', mydata)
UserStore.mutations.setServerCode(tools.EMPTY)
UserStore.mutations.setResStatus(0)
return await new Promise((resolve, reject) => {
@@ -80,6 +90,7 @@ export namespace ApiTool {
}
}, 1000)
if (!!res.status) {
UserStore.mutations.setResStatus(res.status)
if (res.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
// Forbidden
@@ -89,6 +100,7 @@ export namespace ApiTool {
router.push('/signin')
return reject({ code: tools.ERR_AUTHENTICATION })
}
}
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) {
// console.log('[ALTERNATIVE Background syncing', mystrparam)
@@ -117,60 +144,47 @@ export namespace ApiTool {
if (multiparams) {
if (multiparams.length > 3) {
const cmd = multiparams[0]
const table = multiparams[1]
const method = multiparams[2]
const token = multiparams[3]
// let lang = 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)
const tablesync = multiparams[1]
const nametab = multiparams[2]
const method = multiparams[3]
// const token = multiparams[3]
if (cmd === ApiTables.DB.CMD_SYNC) {
let errorfromserver = false
let lettoqualcosa = false
// console.log('A1) INIZIO.............................................................')
return globalroutines(null, 'readall', table, null)
return globalroutines(null, 'readall', tablesync, null)
.then((alldata) => {
const myrecs = [...alldata]
// console.log('----------------------- LEGGO QUALCOSA ')
const promises = myrecs.map((rec) => {
// console.log('syncing', table, '', rec.descr)
// let link = String(process.env.MONGODB_HOST) + '/todos'
let link = '/todos'
let link = '/' + ApiTables.getLinkByTableName(nametab)
if (method !== 'POST') {
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
return SendReq(link, method, rec)
// return fetch(link, {
// method: method,
// headers: headers,
// cache: 'no-cache',
// mode: 'cors', // 'no-cors',
// body: JSON.stringify(rec)
// })
.then(() => {
.then((ris) => {
ReceiveResponsefromServer(tablesync, nametab, method, ris.data)
lettoqualcosa = true
return globalroutines(null, 'delete', table, null, rec._id)
return globalroutines(null, 'delete', tablesync, null, rec._id)
})
.then(() => {
return globalroutines(null, 'delete', 'swmsg', null, mystrparam)
})
.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
}
// 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) => {
// console.log('ERROR:', e)
return (errorfromserver && !lettoqualcosa)
})
.then((errorfromserver) => {
// console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ errorfromserver:', errorfromserver)
const mystate = errorfromserver ? 'offline' : 'online'
.then((error) => {
console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ errorfromserver:', errorfromserver, error)
const mystate = (error || errorfromserver) ? 'offline' : 'online'
GlobalStore.mutations.setStateConnection(mystate)
GlobalStore.mutations.saveConfig( { _id: costanti.CONFIG_ID_STATE_CONN, value: mystate })
})
// console.log(' [Alternative] A2) ?????????????????????????? ESCO DAL LOOP !!!!!!!!!')
}
}
}
}
}
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 Vue from 'vue'
@@ -11,13 +11,11 @@ import Api from '@api'
import * as Types from '@src/store/Api/ApiTypes'
import { costanti } from '@src/store/Modules/costanti'
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 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'
getstateConnSaved()
@@ -42,9 +40,9 @@ const state: IGlobalState = {
posts: [],
menulinks: {},
listatodo: [
{ namecat: 'personal', description: 'personal' },
{ namecat: 'work', description: 'work' },
{ namecat: 'shopping', description: 'shopping' }
{ nametranslate: 'personal', description: 'personal' },
{ nametranslate: 'work', description: 'work' },
{ nametranslate: 'shopping', description: 'shopping' }
],
connData: {
uploading_server: 0,
@@ -74,6 +72,10 @@ async function getstateConnSaved() {
}
}
function addRoute(myarr, values) {
myarr.push(values)
}
const b = storeBuilder.module<IGlobalState>('GlobalModule', state)
// Getters
@@ -109,74 +111,71 @@ namespace Getters {
}, 'showtype')
const getmenu = b.read((state) => {
console.log('getmenu')
const arrlista = GlobalStore.state.listatodo
let listatodo = []
const lista = []
arrlista.forEach((elem: ITodoList) => {
arrlista.forEach((elem: IMenuList) => {
const item = {
faIcon: 'fa fa-list-alt',
materialIcon: 'todo',
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) {
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 = {
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: '/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'},*/
],
routes: arrroutes,
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
console.log('state.menulinks', state.menulinks)
}, 'getmenu')
export const getters = {
@@ -215,7 +214,7 @@ namespace Getters {
},
get isOnline() {
console.log('*********************** isOnline')
// console.log('*********************** isOnline')
return state.stateConnection === 'online'
},
@@ -284,7 +283,7 @@ namespace Mutations {
console.log('config', config)
if (config) {
config.value = String(showtype)
Todos.state.showtype = parseInt(config.value)
Todos.state.showtype = parseInt(config.value, 10)
} else {
Todos.state.showtype = showtype
}
@@ -444,22 +443,22 @@ namespace Actions {
console.log('clearDataAfterLogout')
// Clear all data from the IndexedDB
for (const table of allTables) {
for (const table of ApiTables.allTables()) {
await globalroutines(null, 'clearalldata', table, null)
}
if ('serviceWorker' in navigator) {
// REMOVE ALL SUBSCRIPTION
console.log('REMOVE ALL SUBSCRIPTION...')
await navigator.serviceWorker.ready.then(function (reg) {
await navigator.serviceWorker.ready.then((reg) => {
console.log('... Ready')
reg.pushManager.getSubscription().then((subscription) => {
console.log(' Found Subscription...')
if (subscription) {
subscription.unsubscribe().then(function (successful) {
subscription.unsubscribe().then((successful) => {
// You've successfully unsubscribed
console.log('You\'ve successfully unsubscribed')
}).catch(function (e) {
}).catch( (e) => {
// Unsubscription failed
})
}
@@ -473,14 +472,6 @@ namespace Actions {
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) {

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 Api from '@api'
import { tools } from './tools'
import * as ApiTables from './ApiTables'
import { GlobalStore, Todos, UserStore } from '@store'
import globalroutines from './../../globalroutines/index'
import { Mutation } from 'vuex-module-decorators'
@@ -11,6 +12,8 @@ import { GetterTree } from 'vuex'
import objectId from '@src/js/objectId'
import { costanti } from '@src/store/Modules/costanti'
const nametable = 'todos'
// import _ from 'lodash'
const state: ITodosState = {
@@ -24,7 +27,7 @@ const state: ITodosState = {
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 stateGetter = b.state()
@@ -33,209 +36,83 @@ function getindexbycategory(category: string) {
return state.categories.indexOf(category)
}
function gettodosByCategory(category: string) {
function gettodosByCategory(category: string): [] {
const indcat = state.categories.indexOf(category)
if (!state.todos[indcat])
if (!state.todos[indcat]) {
return []
}
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() {
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)
const objtodo: ITodo = {
// _id: new Date().toISOString(), // Create NEW
// _id: tools.getDateNow().toISOString(), // Create NEW
_id: objectId(),
userId: UserStore.state.userId,
descr: '',
priority: tools.Todos.PRIORITY_NORMAL,
completed: false,
created_at: new Date(),
modify_at: new Date(),
completed_at: new Date(),
priority: tools.Priority.PRIORITY_NORMAL,
statustodo: 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,
progress: 0
progress: 0,
progressCalc: 0,
phase: 0,
assigned_to_userId: '',
hoursplanned: 0,
hoursworked: 0,
start_date: tools.getDateNull(),
}
// return this.copy(objtodo)
return objtodo
}
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[] => {
}, 'getRecordEmpty')
const items_dacompletare = b.read((state: ITodosState) => (cat: string): ITodo[] => {
const indcat = getindexbycategory(cat)
if (state.todos[indcat]) {
return state.todos[indcat].filter(todo => !todo.completed)
} else return []
}, 'todos_dacompletare')
return state.todos[indcat].filter((todo) => todo.statustodo !== tools.Status.COMPLETED)
} else {
return []
}
}, 'items_dacompletare')
const todos_completati = b.read((state: ITodosState) => (cat: string): ITodo[] => {
const indcat = getindexbycategory(cat)
if (state.todos[indcat]) {
if (state.showtype === costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED)
return state.todos[indcat].filter(todo => todo.completed).slice(0, state.visuLastCompleted) // Show only the first N completed
else if (state.showtype === costanti.ShowTypeTask.SHOW_ALL)
return state.todos[indcat].filter(todo => todo.completed)
else
if (state.showtype === costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED) { // 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_ONLY_TOCOMPLETE) {
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')
const doneTodosCount = b.read((state: ITodosState) => (cat: string): number => {
@@ -250,11 +127,20 @@ namespace Getters {
}
}, '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 = {
// get fullName() { return fullName();},
get todos_dacompletare() {
return todos_dacompletare()
get getRecordEmpty() {
return getRecordEmpty()
},
get items_dacompletare() {
return items_dacompletare()
},
get todos_completati() {
return todos_completati()
@@ -264,32 +150,23 @@ namespace Getters {
},
get TodosCount() {
return TodosCount()
},
get getRecordById() {
return getRecordById()
}
}
}
namespace Mutations {
function setTestpao(state: ITodosState, testpao: String) {
state.testpao = testpao
}
function findTodoById(state: ITodosState, data: IParamTodo) {
function findIndTodoById(state: ITodosState, data: IParamTodo) {
const indcat = state.categories.indexOf(data.categorySel)
if (indcat >= 0) {
if (state.todos[indcat]) {
for (let i = 0; i < state.todos[indcat].length; i++) {
if (state.todos[indcat][i]._id === data.id)
return i
}
}
return tools.getIndexById(state.todos[indcat], data.id)
}
return -1
}
function createNewItem(state: ITodosState, { objtodo, atfirst, categorySel }) {
let indcat = state.categories.indexOf(categorySel)
if (indcat == -1) {
@@ -303,10 +180,12 @@ namespace Mutations {
console.log('push state.todos[indcat]', state.todos)
return
}
if (atfirst)
if (atfirst) {
state.todos[indcat].unshift(objtodo)
else
}
else {
state.todos[indcat].push(objtodo)
}
console.log('state.todos[indcat]', state.todos[indcat])
@@ -315,338 +194,82 @@ namespace Mutations {
function deletemyitem(state: ITodosState, myitem: ITodo) {
// Find record
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)
// 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])
ApiTables.removeitemfromarray(state.todos[indcat], ind)
}
export const mutations = {
setTestpao: b.commit(setTestpao),
deletemyitem: b.commit(deletemyitem),
createNewItem: b.commit(createNewItem)
}
}
function consolelogpao(strlog, strlog2 = '', strlog3 = '') {
globalroutines(null, 'log', strlog + ' ' + strlog2 + ' ' + strlog3, null)
}
namespace Actions {
// If something in the call of Service Worker went wrong (Network or Server Down), then retry !
async function sendSwMsgIfAvailable() {
let something = false
async function dbLoad(context, { checkPending }) {
console.log('dbLoad', nametable, checkPending, 'userid=', UserStore.state.userId)
if ('serviceWorker' in navigator) {
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 === '')
if (UserStore.state.userId === '') {
return false // Login not made
}
let ris = await Api.SendReq('/todos/' + UserStore.state.userId, 'GET', null)
.then(res => {
if (res.data.todos) {
// console.log('RISULTANTE CATEGORIES DAL SERVER = ', res.data.categories)
// console.log('RISULTANTE TODOS DAL SERVER = ', res.data.todos)
const ris = await Api.SendReq('/todos/' + UserStore.state.userId, 'GET', null)
.then((res) => {
if (res.data.todos) { // console.log('RISULTANTE CATEGORIES DAL SERVER = ', res.data.categories)
state.todos = res.data.todos
state.categories = res.data.categories
} else {
state.todos = [[]]
}
// console.log('PRIMA showtype = ', state.showtype)
state.showtype = parseInt(GlobalStore.getters.getConfigStringbyId({id: costanti.CONFIG_ID_SHOW_TYPE_TODOS, default: costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED }))
// console.log('showtype = ', state.showtype)
state.showtype = parseInt(GlobalStore.getters.getConfigStringbyId({
id: costanti.CONFIG_ID_SHOW_TYPE_TODOS,
default: costanti.ShowTypeTask.SHOW_LAST_N_COMPLETED
}), 10)
// console.log('ARRAY TODOS = ', state.todos)
if (process.env.DEBUG === '1')
console.log('dbLoadTodo', 'state.todos', state.todos, 'state.categories', state.categories)
if (process.env.DEBUG === '1') {
console.log('dbLoad', 'state.todos', state.todos, 'state.categories', state.categories)
}
return res
})
.catch(error => {
console.log('error dbLoadTodo', error)
.catch((error) => {
console.log('error dbLoad', error)
UserStore.mutations.setErrorCatch(error)
return error
})
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) {
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)
}
}
ApiTables.aftercalling(ris, checkPending, 'categories')
}
async function updatefromIndexedDbToStateTodo(context) {
// console.log('Update the array in memory, from todos table from IndexedDb')
await globalroutines(null, 'updatefromIndexedDbToStateTodo', 'categories', null)
.then(() => {
console.log('updatefromIndexedDbToStateTodo! ')
return true
})
}
async function deleteItemtodo(context, { cat, idobj }) {
console.log('deleteItemtodo: KEY = ', idobj)
function aspettansec(numsec) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('anything')
}, numsec)
})
}
const myarr = gettodosByCategory(cat)
async function testfunc() {
while (true) {
consolelogpao('testfunc')
// console.log('Todos.state.todos_changed:', Todos.state.todos_changed)
await aspettansec(5000)
}
}
const myobjtrov = tools.getElemById(myarr, idobj)
if (!!myobjtrov) {
async function dbSaveTodo(context, itemtodo: ITodo) {
return await dbInsertSaveTodo(context, itemtodo, 'PATCH')
}
console.log('myobjtrov', myobjtrov.descr)
async function dbInsertTodo(context, itemtodo: ITodo) {
return await dbInsertSaveTodo(context, itemtodo, 'POST')
}
if (!!myobjtrov) {
const myobjnext = tools.getElemPrevById(myarr, myobjtrov._id)
async function dbInsertSaveTodo(context, itemtodo: ITodo, method) {
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) {
if (!!myobjnext) {
myobjnext.id_prev = myobjtrov.id_prev
myobjnext.modified = true
console.log('calling MODIFY 1')
await modify(context, { myitem: myobjnext, field: 'id_prev' })
}
// 1) Delete from the Todos Array
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)
ApiTables.table_DeleteRecord(nametable, myobjtrov, idobj)
}
}
}
// console.log('FINE deleteItem')
}
async function insertTodo(context, { myobj, atfirst }) {
async function dbInsert(context, { myobj, atfirst }) {
const objtodo = initcat()
@@ -655,36 +278,28 @@ namespace Actions {
let elemtochange: ITodo = null
const myarr = gettodosByCategory(objtodo.category)
if (atfirst) {
console.log('INSERT AT THE TOP')
elemtochange = getFirstList(objtodo.category)
objtodo.id_prev = tools.LIST_START
// objtodo.pos = (elemtochange !== null) ? elemtochange.pos - 1 : 1
elemtochange = tools.getFirstList(myarr)
objtodo.id_prev = ApiTables.LIST_START
} else {
console.log('INSERT AT THE BOTTOM')
// 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 !== null) ? lastelem._id : tools.LIST_START
// objtodo.pos = (elemtochange !== null) ? elemtochange.pos + 1 : 1
objtodo.id_prev = (!!lastelem) ? lastelem._id : ApiTables.LIST_START
}
console.log('elemtochange TORNATO:', elemtochange)
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
Todos.mutations.createNewItem({ objtodo, atfirst, categorySel: objtodo.category })
// 2) Insert into the IndexedDb
const id = await globalroutines(context, 'write', 'todos', objtodo)
const id = await globalroutines(context, 'write', nametable, objtodo) // 2) Insert into the IndexedDb
let field = ''
// update also the last elem
if (atfirst) {
if (elemtochange !== null) {
if (atfirst) { // update also the last elem
if (!!elemtochange) {
elemtochange.id_prev = id
console.log('elemtochange', elemtochange)
field = 'id_prev'
@@ -695,16 +310,17 @@ namespace Actions {
}
// 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) => {
// Check if need to be moved...
const indelem = getIndexById(objtodo.category, objtodo._id)
let itemdragend = undefined
// *** Check if need to be moved because of the --- Priority Ordering --- ...
const indelem = tools.getIndexById(myarr, objtodo._id)
let itemdragend
if (atfirst) {
// Check the second item, if it's different priority, then move to the first position of the priority
const secondindelem = indelem + 1
if (isValidIndex(objtodo.category, secondindelem)) {
const secondelem = getElemByIndex(objtodo.category, secondindelem)
if (tools.isOkIndex(myarr, secondindelem)) {
const secondelem = tools.getElemByIndex(myarr, secondindelem)
if (secondelem.priority !== objtodo.priority) {
itemdragend = {
field: 'priority',
@@ -719,8 +335,8 @@ namespace Actions {
} else {
// get previous of the last
const prevlastindelem = indelem - 1
if (isValidIndex(objtodo.category, prevlastindelem)) {
const prevlastelem = getElemByIndex(objtodo.category, prevlastindelem)
if (tools.isOkIndex(myarr, prevlastindelem)) {
const prevlastelem = tools.getElemByIndex(myarr, prevlastindelem)
if (prevlastelem.priority !== objtodo.priority) {
itemdragend = {
field: 'priority',
@@ -733,161 +349,39 @@ namespace Actions {
}
}
if (itemdragend)
if (itemdragend) {
swapElems(context, itemdragend)
}
return ris
})
}
async function modify(context, { myitem, field }) {
if (myitem === null)
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
return await ApiTables.table_ModifyRecord(nametable, myitem, listFieldsToChange, field)
}
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) {
console.log('swapElems', itemdragend)
console.log('state.todos', state.todos)
console.log('state.categories', state.categories)
console.log('TODOS swapElems', itemdragend, state.todos, state.categories)
const cat = itemdragend.category
const indcat = state.categories.indexOf(cat)
const myarr = state.todos[indcat]
if (itemdragend.field === 'priority') {
// 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' })
}
tools.swapGeneralElem(nametable, myarr, itemdragend, listFieldsToChange)
}
export const actions = {
dbInsertTodo: b.dispatch(dbInsertTodo),
dbSaveTodo: b.dispatch(dbSaveTodo),
dbLoadTodo: b.dispatch(dbLoadTodo),
dbdeleteItem: b.dispatch(dbdeleteItem),
updatefromIndexedDbToStateTodo: b.dispatch(updatefromIndexedDbToStateTodo),
checkPendingMsg: b.dispatch(checkPendingMsg),
waitAndcheckPendingMsg: b.dispatch(waitAndcheckPendingMsg),
dbLoad: b.dispatch(dbLoad),
swapElems: b.dispatch(swapElems),
// updateModifyRecords: b.dispatch(updateModifyRecords),
deleteItem: b.dispatch(deleteItem),
insertTodo: b.dispatch(insertTodo),
deleteItemtodo: b.dispatch(deleteItemtodo),
dbInsert: b.dispatch(dbInsert),
modify: b.dispatch(modify)
}
}
// Module
const TodosModule = {
get state() {

View File

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

View File

@@ -6,5 +6,7 @@ export const costanti = {
},
CONFIG_ID_CFG: '1',
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 UserStore} from './UserStore'
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 { getStoreBuilder } from 'vuex-typex'
import { IProgressState } from '@types'
export interface RootState {
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 './ProgressBar.d'
export interface IResponse<T> {
success?: boolean,

View File

@@ -85,7 +85,7 @@ declare module 'vuelidate' {
*/
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
/**
@@ -231,7 +231,7 @@ declare module 'vuelidate/lib/validators' {
*/
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
/**

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
setTimeout(() => {
this.serverPagination = props.pagination
let
table = this.$refs.table,
let table = this.$refs.table,
rows = GlobalStore.state.cfgServer.slice(),
{ page, rowsPerPage, sortBy, descending } = props.pagination

View File

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

View File

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

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