Merge pull request #17 from paoloar77/PushNofit2

Push nofit2
This commit is contained in:
Paolo Arena
2019-02-14 19:02:19 +01:00
committed by GitHub
43 changed files with 1331 additions and 574 deletions

View File

@@ -1,4 +1,4 @@
APP_VERSION="DEV 0.0.10" APP_VERSION="DEV 0.0.27"
SERVICE_WORKER_FILE='service-worker.js' SERVICE_WORKER_FILE='service-worker.js'
APP_ID='1' APP_ID='1'
APP_URL='https://freeplanet.app' APP_URL='https://freeplanet.app'

7
.gitignore vendored
View File

@@ -3,6 +3,9 @@
.thumbs.db .thumbs.db
.env .env
.env.production .env.production
.env.production.bak
.env.prod.bak
.env.test
node_modules node_modules
/dist /dist
/src-cordova/node_modules /src-cordova/node_modules
@@ -28,4 +31,6 @@ coverage
/_PROVE /_PROVE
/_LOCALE /_LOCALE
deploy.sh deploy.sh
deploy_production.sh deploy_on_production.sh
deploy_on_test_server.sh
send_to_production.sh

View File

@@ -21,6 +21,7 @@
"serve": "quasar serve ./dist/pwa-mat", "serve": "quasar serve ./dist/pwa-mat",
"serve:coverage": "quasar serve test/coverage/lcov-report/ --cache 0 --port 8788", "serve:coverage": "quasar serve test/coverage/lcov-report/ --cache 0 --port 8788",
"deploy": "deploy.sh", "deploy": "deploy.sh",
"deploy_server_test": "NODE_ENV=test quasar build -m pwa",
"generate-sw": "workbox generateSW workbox-config.js" "generate-sw": "workbox generateSW workbox-config.js"
}, },
"dependencies": { "dependencies": {

View File

@@ -195,6 +195,7 @@ module.exports = function (ctx) {
}, },
manifest: { manifest: {
name: 'Free Planet', name: 'Free Planet',
version: '0.0.14',
short_name: 'freeplanet', short_name: 'freeplanet',
description: 'Social project in order to connecting people each others (working in progress...)', description: 'Social project in order to connecting people each others (working in progress...)',
display: 'standalone', display: 'standalone',

View File

@@ -1,4 +1,3 @@
/* /*
* This file (which will be your service worker) * This file (which will be your service worker)
* is picked up by the build system ONLY if * is picked up by the build system ONLY if
@@ -7,49 +6,49 @@
// Questo è il swSrc // Questo è il swSrc
console.log('SW-06 ___________________________ PAO: this is my custom service worker'); console.log(' [ VER-0.0.27 ] _---------________------ PAO: this is my custom service worker');
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js'); //++Todo: Replace with local workbox.js
importScripts('../statics/js/idb.js'); importScripts('../statics/js/idb.js');
importScripts('../statics/js/storage.js'); importScripts('../statics/js/storage.js');
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js'); //++Todo: Replace with local workbox.js
console.log('SW-06 1'); let port = 3000;
if (self.location.hostname === 'test.freeplanet.app') {
port = 3001;
}
// console.log('SW-06 1');
const cfgenv = { const cfgenv = {
serverweb: self.location.protocol + "//" + self.location.hostname + ':3000', serverweb: self.location.protocol + "//" + self.location.hostname + ':' + port,
dbname: 'mydb3', dbname: 'mydb3',
dbversion: 11, dbversion: 11,
} }
console.log('SW-06 2');
console.log('SERVERWEB=', cfgenv.serverweb)
// console.log('serverweb', cfgenv.serverweb) // console.log('serverweb', cfgenv.serverweb)
async function writeData(table, data) { async function writeData(table, data) {
console.log('writeData', table, data); // console.log('writeData', table, data);
await idbKeyval.setdata(table, data); await idbKeyval.setdata(table, data);
} }
async function readAllData(table) { async function readAllData(table) {
console.log('readAllData', table); // console.log('readAllData', table);
return await idbKeyval.getalldata(table); return await idbKeyval.getalldata(table);
} }
async function clearAllData(table) { async function clearAllData(table) {
console.log('clearAllData', table); // console.log('clearAllData', table);
await idbKeyval.clearalldata(table) await idbKeyval.clearalldata(table)
} }
async function deleteItemFromData(table, id) { async function deleteItemFromData(table, id) {
console.log('deleteItemFromData', table, 'ID:', id); // console.log('deleteItemFromData', table, 'ID:', id);
await idbKeyval.deletedata(table, id) await idbKeyval.deletedata(table, id)
} }
// self.addEventListener('activate', function(event) { // self.addEventListener('activate', function(event) {
// event.waitUntil( // event.waitUntil(
// // createDB() // // createDB()
@@ -58,10 +57,10 @@ async function deleteItemFromData(table, id) {
if (!workbox) { if (!workbox) {
let workbox = new self.WorkboxSW(); let workbox = new self.WorkboxSW();
console.log('SW-06 3');
} }
if (workbox) { if (workbox) {
// console.log('WORKBOX PRESENT')
// const url = new URL(location.href); // const url = new URL(location.href);
// const debug = url.searchParams.has('debug'); // const debug = url.searchParams.has('debug');
const debug = false; const debug = false;
@@ -105,36 +104,80 @@ if (workbox) {
}) })
); );
// console.log(' routing.registerRoute function declaration:')
workbox.routing.registerRoute( workbox.routing.registerRoute(
new RegExp(cfgenv.serverweb + '/todos/'), new RegExp(cfgenv.serverweb + '/todos/'),
function (args) { function (args) {
console.log('registerRoute!') console.log('registerRoute! ', cfgenv.serverweb + '/todos/')
// 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) return fetch(args.event.request, args.event.headers)
.then(function (res) { .then(function (res) {
console.log('1° ******* [[[ SERVICE-WORKER ]]] registerRoute fetch: ', args.event) myres = res
// console.log('1° ******* [[[ SERVICE-WORKER ]]] registerRoute fetch: -> ', args.event.request, res)
// LOAD FROM SERVER , AND SAVE INTO INDEXEDDB // LOAD FROM SERVER , AND SAVE INTO INDEXEDDB
console.log('res.status', res.status) // console.log('res.status', res.status)
if (res.status === 200) { if (res.status === 200) {
var clonedRes = res.clone(); const clonedRes = res.clone();
clearAllData('todos')
.then(function () {
return clonedRes.json();
})
.then(function (data) {
if (data.todos) {
console.log('Records TODOS Received from Server [', data.todos.length, 'record]', data.todos)
for (let key in data.todos) {
writeData('todos', data.todos[key])
}
}
});
return res
}
})
}
);
return clearAllData('todos')
.then(() => {
return clonedRes
})
}
})
.then((clonedRes) => {
if (clonedRes !== undefined)
return clonedRes.json();
return null
})
.then(async data => {
if (data) {
if (data.todos) {
console.log('***********************+++++++++++++++++++++++++++++++++++++++++++++++++++********** Records TODOS Received from Server [', data.todos.length, 'record]', data.todos)
for (const key in data.todos) {
await writeData('todos', data.todos[key])
}
}
}
})
.then(() => {
return myres
})
.catch(err => {
console.log('ERROR registerRoute FETCH:', err)
return myres
})
})
workbox.routing.registerRoute(function (routeData) {
return (routeData.event.request.headers.get('accept').includes('text/html'));
}, function (args) {
return caches.match(args.event.request)
.then(function (response) {
if (response) {
return response;
} else {
return fetch(args.event.request)
.then(function (res) {
return caches.open('dynamic')
.then(function (cache) {
cache.put(args.event.request.url, res.clone());
return res;
})
})
.catch(function (err) {
return caches.match('/offline')
.then(function (res) {
return res;
});
});
}
})
});
workbox.routing.registerRoute( workbox.routing.registerRoute(
new RegExp(/.*\/(?:statics\/icons).*$/), new RegExp(/.*\/(?:statics\/icons).*$/),
@@ -225,16 +268,17 @@ if (workbox) {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
console.log('***************** Entering in custom-service-worker.js:') // console.log('***************** Entering in custom-service-worker.js:')
} }
self.addEventListener('fetch', (event) => {
if (event.request.url === '/') { // self.addEventListener('fetch', (event) => {
const staleWhileRevalidate = new workbox.strategies.StaleWhileRevalidate(); // if (event.request.url === '/') {
event.respondWith(staleWhileRevalidate.handle({event})); // const staleWhileRevalidate = new workbox.strategies.StaleWhileRevalidate();
} // event.respondWith(staleWhileRevalidate.handle({ event }));
}); // }
// });
// self.addEventListener('fetch', function (event) { // self.addEventListener('fetch', function (event) {
// console.log('[Service Worker] Fetching something ....', event); // console.log('[Service Worker] Fetching something ....', event);
@@ -245,7 +289,7 @@ self.addEventListener('fetch', (event) => {
// } // }
// event.respondWith(caches.match(event.request)); // event.respondWith(caches.match(event.request));
// }); // });
//
// const syncStore = {} // const syncStore = {}
// self.addEventListener('message', event => { // self.addEventListener('message', event => {
@@ -259,77 +303,124 @@ self.addEventListener('fetch', (event) => {
// console.log(event.data) // console.log(event.data)
// }) // })
self.addEventListener('sync', function (event) { // addEventListener('fetch', event => {
console.log('[Service Worker V5] Background syncing', event.tag); // // Prevent the default, and handle the request ourselves.
// event.respondWith(async function() {
// // Try to get the response from a cache.
// const cachedResponse = await caches.match(event.request);
// // Return it if we found one.
// if (cachedResponse && (event.request.cache !== 'no-cache'))
// return cachedResponse;
//
// // If we didn't find a match in the cache, use the network.
// return fetch(event.request);
// }());
// });
let mystrparam = event.tag // self.addEventListener('fetch', function (event) {
let multiparams = mystrparam.split('|') // event.respondWith(
if (multiparams) { // caches.match(event.request).then(function (response) {
if (multiparams.length > 3) { // return response ||
let cmd = multiparams[0] // fetch(event.request, event.headers)
let table = multiparams[1] // .catch(err => {
let method = multiparams[2] // console.log('_______________________ ERRORE FETCH SW: ', event.request, err)
let token = multiparams[3] // writeData('config', { _id: 2, stateconn: 'offline' })
// let lang = multiparams[3] // return caches.match(event.request);
// })
// })
// );
// });
if (cmd === 'sync-todos') {
console.log('[Service Worker] Syncing', cmd, table, method);
const headers = new Headers() // self.addEventListener('fetch', function (event) {
headers.append('content-Type', 'application/json') // event.respondWith(
headers.append('Accept', 'application/json') // fetch(event.request, event.headers)
headers.append('x-auth', token) // .catch(err => {
// console.log('_______________________ ERRORE FETCH SW: ', event.request, err)
// writeData('config', {_id: 2, stateconn: 'offline'})
// return caches.match(event.request);
// })
// );
// });
console.log('A1) INIZIO.............................................................');
event.waitUntil( // self.addEventListener('sync', function (event) {
readAllData(table) // console.log('[Service Worker V5] Background syncing', event.tag);
.then(function (alldata) { //
const myrecs = [...alldata] // let mystrparam = event.tag
console.log('----------------------- LEGGO QUALCOSA DAL WAITUNTIL ') // let multiparams = mystrparam.split('|')
if (myrecs) { // if (multiparams) {
for (let rec of myrecs) { // if (multiparams.length > 3) {
//console.log('syncing', table, '', rec.descr) // let cmd = multiparams[0]
let link = cfgenv.serverweb + '/todos' // let table = multiparams[1]
// let method = multiparams[2]
if (method !== 'POST') // let token = multiparams[3]
link += '/' + rec._id // // let lang = multiparams[3]
//
console.log('++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:') // if (cmd === 'sync-todos') {
// console.log('[Service Worker] Syncing', cmd, table, method);
// Insert/Delete/Update table to the server //
fetch(link, { // const headers = new Headers()
method: method, // headers.append('content-Type', 'application/json')
headers: headers, // headers.append('Accept', 'application/json')
mode: 'cors', // 'no-cors', // headers.append('x-auth', token)
body: JSON.stringify(rec) //
}) //
.then(function (resData) { // // console.log('A1) INIZIO.............................................................');
// console.log('Result CALL ', method, ' OK? =', resData.ok); //
// event.waitUntil(
// Anyway Delete this, otherwise in some cases will return error, but it's not a problem. // readAllData(table)
// for example if I change a record and then I deleted ... // .then(function (alldata) {
// if (resData.ok) { // const myrecs = [...alldata]
deleteItemFromData(table, rec._id); // console.log('----------------------- LEGGO QUALCOSA DAL WAITUNTIL ')
// let errorfromserver = false
// if (myrecs) {
// for (let rec of myrecs) {
// //console.log('syncing', table, '', rec.descr)
// let link = cfgenv.serverweb + '/todos'
//
// if (method !== 'POST')
// link += '/' + rec._id
//
// console.log('++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:')
//
// // console.log('DATATOSAVE:', JSON.stringify(rec))
//
// // Insert/Delete/Update table to the server
// fetch(link, {
// method: method,
// headers: headers,
// cache: 'no-cache',
// mode: 'cors', // 'no-cors',
// body: JSON.stringify(rec)
// })
// .then(() => {
// deleteItemFromData(table, rec._id)
// })
// .then(() => {
// deleteItemFromData('swmsg', mystrparam)
// })
// .catch(function (err) {
// console.log('!!!!!!!!!!!!!!! Error while sending data', err, err.message);
// if (err.message === 'Failed to fetch') {
// errorfromserver = true
// } // }
// })
console.log('DELETE: ', mystrparam) // }
deleteItemFromData('swmsg', mystrparam) // return errorfromserver
// }
}) // })
.catch(function (err) { // .then((errorfromserver) => {
console.log('!!!!!!!!!!!!!!! Error while sending data', err); // const mystate = !errorfromserver ? 'online' : 'offline'
}); // writeData('config', { _id: 2, stateconn: mystate })
} // })
} // );
}) // // console.log('A2) ?????????????????????????? ESCO DAL LOOP !!!!!!!!! err=')
); // }
console.log('A2) ?????????????????????????? ESCO DAL LOOP !!!!!!!!! err=') // }
} // }
} // })
} // ;
})
;
/* /*
@@ -397,10 +488,16 @@ self.addEventListener('notificationclose', function(event) {
self.addEventListener('push', function (event) { self.addEventListener('push', function (event) {
console.log('Push Notification received', event); console.log('Push Notification received', event);
var data = {title: 'New!', content: 'Something new happened!', openUrl: '/'}; var data = { title: 'New!', content: 'Something new happened!', url: '/' };
try {
if (event.data) { if (event.data) {
try {
data = JSON.parse(event.data.text()); data = JSON.parse(event.data.text());
} catch (e) {
data = event.data.text();
}
} }
var options = { var options = {
@@ -408,12 +505,15 @@ self.addEventListener('push', function(event) {
icon: '/statics/icons/android-chrome-192x192.png', icon: '/statics/icons/android-chrome-192x192.png',
badge: '/statics/icons/android-chrome-192x192.png', badge: '/statics/icons/android-chrome-192x192.png',
data: { data: {
url: data.openUrl url: data.url
} }
}; };
event.waitUntil( event.waitUntil(
self.registration.showNotification(data.title, options) self.registration.showNotification(data.title, options)
); );
} catch (e) {
console.log('Error on event push:', e)
}
}); });

View File

@@ -12,7 +12,6 @@ import globalroutines from './globalroutines/index'
import { GlobalStore } from './store/Modules' import { GlobalStore } from './store/Modules'
@Component({ @Component({
components: { components: {
appHeader: Header appHeader: Header
@@ -23,9 +22,9 @@ import { GlobalStore } from './store/Modules'
export default class App extends Vue { export default class App extends Vue {
public backgroundColor = 'whitesmoke' public backgroundColor = 'whitesmoke'
public isSubscribed = false
public $q public $q
public listaRoutingNoLogin = ['/vreg?', '/offline']
created() { created() {
if (process.env.DEV) { if (process.env.DEV) {
@@ -37,9 +36,22 @@ export default class App extends Vue {
// console.info(process.env) // console.info(process.env)
} }
UserStore.actions.autologin() // Make autologin only if some routing
.then((loginEseguito) => {
if (loginEseguito) { // console.log('window.location.href', window.location.href)
let chiamaautologin = true
this.listaRoutingNoLogin.forEach(mystr => {
if (window.location.href.includes(mystr)) {
chiamaautologin = false
}
})
if (chiamaautologin) {
console.log('CHIAMA autologin_FromLocalStorage')
UserStore.actions.autologin_FromLocalStorage()
.then((loadstorage) => {
if (loadstorage) {
globalroutines(this, 'loadapp', '') globalroutines(this, 'loadapp', '')
// this.$router.replace('/') // this.$router.replace('/')
@@ -47,9 +59,12 @@ export default class App extends Vue {
GlobalStore.actions.createPushSubscription() GlobalStore.actions.createPushSubscription()
} }
}) })
}
// Calling the Server for updates ?
// Check the verified_email
} }
} }

View File

@@ -5,6 +5,7 @@ import {
AxiosResponse AxiosResponse
} from 'axios' } from 'axios'
import { default as VueRouter } from 'vue-router' import { default as VueRouter } from 'vue-router'
import { serv_constants } from "@src/store/Modules/serv_constants"
// import { TokenHelper } from "./token-helper"; // import { TokenHelper } from "./token-helper";
let initialized: boolean = false let initialized: boolean = false
@@ -54,7 +55,7 @@ export function UseAxios(router: VueRouter) {
} }
} }
if (response.status === 403 && handle(response.status, exclude)) { if (response.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN && handle(response.status, exclude)) {
window.setTimeout(() => router.replace('/forbidden'), 200) window.setTimeout(() => router.replace('/forbidden'), 200)
} }

View File

@@ -32,6 +32,17 @@
<div slot="subtitle">{{$t('msg.myDescriz')}} {{ getAppVersion() }}</div> <div slot="subtitle">{{$t('msg.myDescriz')}} {{ getAppVersion() }}</div>
</q-toolbar-title> </q-toolbar-title>
<q-btn
flat
dense
round
@click=""
aria-label="Connection"
>
<q-icon :name="iconConn" :class="clIconConn"></q-icon>
<q-icon v-if="isUserNotAuth" name="device_unknown"></q-icon>
</q-btn>
<q-select class="sel_lang" v-model="lang" stack-label="" :options="selectOpLang"/> <q-select class="sel_lang" v-model="lang" stack-label="" :options="selectOpLang"/>
<!-- <!--
@@ -68,17 +79,72 @@
import { GlobalStore } from '@modules' import { GlobalStore } from '@modules'
import { rescodes } from '../store/Modules/rescodes' import { rescodes } from '../store/Modules/rescodes'
import QIcon from "quasar-framework/src/components/icon/QIcon";
import { StateConnection } from "../model";
import { Watch } from "vue-property-decorator";
import QField from "quasar-framework/src/components/field/QField";
@Component({ @Component({
components: { components: {
QField,
QIcon,
drawer, drawer,
messagePopover, messagePopover,
} }
}) })
export default class Header extends Vue { export default class Header extends Vue {
public $t
public $v public $v
public $q public $q
public isUserNotAuth: boolean = false
public iconConn: string = 'wifi'
public clIconConn: string = 'clIconOnline'
public strConn: string = ''
get conn_changed() {
return GlobalStore.state.stateConnection
}
@Watch('GlobalStore.state.stateConnection', { immediate: true, deep: true })
changeconn(value: string, oldValue: string) {
this.strConn = value
// this.$q.notify({
// color : 'primary',
// icon: 'wifi',
// message: "CAMBIATOO! " + value
// })
}
@Watch('conn_changed', { immediate: true, deep: true })
changeconn_changed(value: string, oldValue: string) {
if (value != oldValue) {
// console.log('SSSSSSSS: ', value, oldValue)
const color = (value === 'online') ? 'positive' : 'warning'
if (oldValue !== undefined) {
this.$q.notify({
color,
icon: 'wifi',
message: this.$t('connection') + ` ${value}`
})
}
// console.log('Todos.state.todos_changed CHANGED!', value, oldValue)
this.changeIconConn()
}
}
changeIconConn() {
this.iconConn = GlobalStore.state.stateConnection === 'online' ? "wifi" : "wifi_off"
this.clIconConn = GlobalStore.state.stateConnection === 'online' ? 'clIconOnline' : 'clIconOffline'
}
public selectOpLang = [ public selectOpLang = [
{ label: 'English (UK)', icon: 'fa-flag-us', value: 'en-uk' }, { label: 'English (UK)', icon: 'fa-flag-us', value: 'en-uk' },
@@ -115,6 +181,38 @@
}) })
} }
mounted () {
// Test this by running the code snippet below and then
// use the "Offline" checkbox in DevTools Network panel
let mythis = this
// console.log('Event LOAD')
if (window) {
window.addEventListener('load', function () {
// console.log('2) ENTERING Event LOAD')
function updateOnlineStatus(event) {
if (navigator.onLine) {
// console.log('EVENT ONLINE!')
// handle online status
GlobalStore.mutations.setStateConnection('online')
mythis.changeIconConn()
} else {
// console.log('EVENT OFFLINE!')
// handle offline status
GlobalStore.mutations.setStateConnection('offline')
mythis.changeIconConn()
}
}
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
});
}
}
public snakeToCamel(str) { public snakeToCamel(str) {
return str.replace(/(-\w)/g, m => { return str.replace(/(-\w)/g, m => {
return m[1].toUpperCase() return m[1].toUpperCase()
@@ -359,5 +457,13 @@
content: url('../statics/icons/flag_it.svg'); content: url('../statics/icons/flag_it.svg');
} }
.clIconOnline {
color: white;
}
.clIconOffline {
color: red;
}
</style> </style>

View File

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

View File

@@ -0,0 +1,29 @@
.svgclass{
color: white;
transform: translateY(0px);
}
.svgclass_animate {
transform: translateY(-70px);
color: red;
}
#sun {
animation: gravity 5s infinite;
}
@keyframes gravity{
0%{
transform: rotateY(0deg);
}
100%{
transform: rotateY(360deg);
}
}
#smile{
opacity: 0.1 !important;
fill: red;
}

View File

@@ -0,0 +1,53 @@
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,11 @@
<template>
<div id="offline">
Offline Page !
</div>
</template>
<script lang="ts" src="./offline.ts">
</script>
<style lang="scss" scoped>
@import './offline.scss';
</style>

View File

@@ -78,7 +78,10 @@ $heightitem: 19px;
padding: 0px; padding: 0px;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
display: block;
@media screen and (min-width: 600px) {
display: none; display: none;
}
color: #777; color: #777;
height: 100%; height: 100%;
//visibility: hidden; //visibility: hidden;
@@ -291,6 +294,7 @@ $heightitem: 19px;
} }
/* /*
.container { .container {
background-color: #ccc; background-color: #ccc;

View File

@@ -39,6 +39,7 @@ export default class SingleTodo extends Vue {
public colProgress: string = 'blue' public colProgress: string = 'blue'
public togglemenu: boolean = false public togglemenu: boolean = false
public percentageProgress: number = 0 public percentageProgress: number = 0
public itemtodoPrec: ITodo
$q: any $q: any
@Prop({ required: true }) itemtodo: ITodo @Prop({ required: true }) itemtodo: ITodo
@@ -69,6 +70,11 @@ export default class SingleTodo extends Vue {
this.updateClasses() this.updateClasses()
} }
dateToYYYYMMDD(date) {
// may have timezone caveats https://stackoverflow.com/a/29774197/1850609
return date && date.toISOString().split('T')[0]
}
isTodo() { isTodo() {
return this.isTodoByElem(this.itemtodo) return this.isTodoByElem(this.itemtodo)
} }
@@ -258,6 +264,15 @@ export default class SingleTodo extends Vue {
} }
} }
*/ */
if (((e.keyCode === 8) || (e.keyCode === 46)) && (this.precDescr === '') && !e.shiftKey) {
e.preventDefault()
this.deselectRiga()
this.clickMenu(rescodes.MenuAction.DELETE)
.then(() => {
this.faiFocus('insertTask', true)
return
})
}
if (((e.key === 'Enter') || (e.key === 'Tab')) && !e.shiftKey) { if (((e.key === 'Enter') || (e.key === 'Tab')) && !e.shiftKey) {
this.updateTodo() this.updateTodo()
@@ -287,6 +302,9 @@ export default class SingleTodo extends Vue {
this.itemtodo.descr = this.precDescr this.itemtodo.descr = this.precDescr
console.log('updateTodo', this.precDescr, this.itemtodo.descr) console.log('updateTodo', this.precDescr, this.itemtodo.descr)
console.log('itemtodo', this.itemtodo)
console.log('Prec:', this.itemtodoPrec)
this.watchupdate() this.watchupdate()
this.inEdit = false this.inEdit = false
// this.precDescr = this.itemtodo.descr // this.precDescr = this.itemtodo.descr
@@ -335,16 +353,16 @@ export default class SingleTodo extends Vue {
} }
clickMenu(action) { async clickMenu(action) {
console.log('click menu: ', action) console.log('click menu: ', action)
if (action === rescodes.MenuAction.DELETE) { if (action === rescodes.MenuAction.DELETE) {
this.askConfirmDelete() return await this.askConfirmDelete()
} else if (action === rescodes.MenuAction.TOGGLE_EXPIRING) { } else if (action === rescodes.MenuAction.TOGGLE_EXPIRING) {
this.enableExpiring() return await this.enableExpiring()
} else if (action === rescodes.MenuAction.COMPLETED) { } else if (action === rescodes.MenuAction.COMPLETED) {
this.setCompleted() return await this.setCompleted()
} else if (action === rescodes.MenuAction.PROGRESS_BAR) { } else if (action === rescodes.MenuAction.PROGRESS_BAR) {
this.updatedata() return await this.updatedata()
} }
} }
@@ -360,11 +378,11 @@ export default class SingleTodo extends Vue {
// this.$q.notify('setPriority: ' + elem) // this.$q.notify('setPriority: ' + elem)
} }
askConfirmDelete() { async askConfirmDelete() {
const deletestr = this.$t('dialog.delete') const deletestr = this.$t('dialog.delete')
const cancelstr = this.$t('dialog.cancel') const cancelstr = this.$t('dialog.cancel')
askConfirm(this.$q, this.$t('dialog.msg.titledeleteTask'), this.$t('dialog.msg.deleteTask').toString(), deletestr, cancelstr) await askConfirm(this.$q, this.$t('dialog.msg.titledeleteTask'), this.$t('dialog.msg.deleteTask').toString(), deletestr, cancelstr)
.then(ris => { .then(ris => {
console.log('ris', ris) console.log('ris', ris)
if (ris) if (ris)

View File

@@ -4,16 +4,6 @@
<SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu" @setPriority="setPriority"></SubMenus> <SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu" @setPriority="setPriority"></SubMenus>
</q-context-menu> </q-context-menu>
<div v-if="isTodo()" class="flex-item pos-item" @mouseup.left="mouseUp" @mousedown="clickRiga">
<q-btn flat
class="pos-item-popover"
icon="menu" >
<q-popover self="top right">
<SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu" @setPriority="setPriority"></SubMenus>
</q-popover>
</q-btn>
</div>
<div v-if="isTodo()" class="flex-item completed-item"> <div v-if="isTodo()" class="flex-item completed-item">
<q-btn push flat <q-btn push flat
@@ -23,7 +13,7 @@
</q-btn> </q-btn>
</div> </div>
<q-input type="textarea" ref="inputdescr" v-model="precDescr" <q-input type="textarea" ref="inputdescr" v-model.trim="precDescr"
:class="classDescr" :max-height="50" :class="classDescr" :max-height="50"
@keydown="keyDownArea" v-on:keydown.esc="exitEdit" @blur="exitEdit(true)" @click="editTodo()"/> @keydown="keyDownArea" v-on:keydown.esc="exitEdit" @blur="exitEdit(true)" @click="editTodo()"/>
@@ -33,7 +23,7 @@
<!--<q-field>{{ itemtodo.descr }}</q-field>--> <!--<q-field>{{ itemtodo.descr }}</q-field>-->
<!--</div>--> <!--</div>-->
<div v-if="isTodo()" class="flex-item progress-item"> <div v-if="isTodo() && (percentageProgress > 0) " class="flex-item progress-item">
<q-progress <q-progress
:percentage="percentageProgress" :percentage="percentageProgress"
class="progress-item" class="progress-item"
@@ -49,14 +39,28 @@
<div v-if="itemtodo.enableExpiring"> <div v-if="itemtodo.enableExpiring">
<div :class="classExpiring"> <div :class="classExpiring">
<q-datetime <q-datetime
type="date"
:class="classExpiringEx" :class="classExpiringEx"
v-model="itemtodo.expiring_at" v-model="itemtodo.expiring_at"
class="myexpired"> class="myexpired"
format="DD/MM/YY"
@change="val => { model = val }" >
</q-datetime> </q-datetime>
</div> </div>
</div> </div>
<div v-if="isTodo()" class="flex-item pos-item" @mouseup.left="mouseUp" @mousedown="clickRiga">
<q-btn flat
class="pos-item-popover"
icon="menu" >
<q-popover self="top right">
<SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu" @setPriority="setPriority"></SubMenus>
</q-popover>
</q-btn>
</div>
<!--<div class="flex-item btn-item">--> <!--<div class="flex-item btn-item">-->
<!--{{classPosItemPopup}}--> <!--{{itemtodo.expiring_at}}-->
<!--</div>--> <!--</div>-->
<!--<div class="flex-item btn-item">--> <!--<div class="flex-item btn-item">-->
<!--<q-btn class="mybtn" round color="" icon="delete" @click.native="removeitem(itemtodo._id)"></q-btn>--> <!--<q-btn class="mybtn" round color="" icon="delete" @click.native="removeitem(itemtodo._id)"></q-btn>-->

View File

@@ -11,6 +11,7 @@
cursor: pointer; cursor: pointer;
} }
.menuProgress { .menuInputProgress > div:nth-child(2) > div > input {
min-width: 30px;
width: 30px;
} }

View File

@@ -2,8 +2,8 @@ import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator' import { Component, Prop } from 'vue-property-decorator'
import { ITodo } from '../../../model/index' import { ITodo } from '../../../model/index'
import { rescodes } from "@src/store/Modules/rescodes" import { rescodes } from '@src/store/Modules/rescodes'
import { UserStore } from "@store" import { UserStore } from '@store'
@Component({ @Component({
@@ -14,7 +14,7 @@ export default class SubMenus extends Vue {
public selectPriority: [] = rescodes.selectPriority[UserStore.state.lang] public selectPriority: [] = rescodes.selectPriority[UserStore.state.lang]
@Prop({ required: false }) menuPopupTodo: any[] @Prop({ required: false }) menuPopupTodo: any[]
@Prop({ required: false }) itemtodo: ITodo[] @Prop({ required: false }) itemtodo: ITodo
$q: any $q: any
clickMenu (field) { clickMenu (field) {
@@ -25,6 +25,15 @@ export default class SubMenus extends Vue {
this.$emit('setPriority', field) this.$emit('setPriority', field)
} }
KeychangeProgress (e) {
if (this.itemtodo.progress > 100) {
this.itemtodo.progress = 100
}
if (this.itemtodo.progress < 0) {
this.itemtodo.progress = 0
}
}
create () { create () {
this.selectPriority = rescodes.selectPriority[UserStore.state.lang] this.selectPriority = rescodes.selectPriority[UserStore.state.lang]

View File

@@ -18,14 +18,28 @@
</q-item-side> </q-item-side>
<q-item-main v-if="field.value === 120"> <q-item-main v-if="field.value === 120">
<q-slider :class="$parent.menuProgress" v-model="itemtodo.progress" :min="0" :max="100"/> <q-slider :class="$parent.menuProgress" v-model="itemtodo.progress" :min="0" :max="100"
:step="5"/>
</q-item-main> </q-item-main>
<q-item-side v-if="field.value === 120" > <q-item-side v-if="field.value === 120" >
<div :class="$parent.percProgress"> <div>
{{$parent.percentageProgress}}% <q-input v-model="itemtodo.progress"
class="menuInputProgress"
type="number"
suffix="%"
@change="val => { model = val }"
@keydown="KeychangeProgress"
/>
</div> </div>
</q-item-side> </q-item-side>
<!--<q-item-side right v-if="field.value === 120">-->
<!--<div :class="$parent.percProgress">-->
<!--{{$parent.percentageProgress}}%-->
<!--</div>-->
<!--</q-item-side>-->
</q-item> </q-item>
<q-item v-if="(field.value === 100)" :icon="field.icon" v-close-overlay <q-item v-if="(field.value === 100)" :icon="field.icon" v-close-overlay
@click.native="clickMenu(field.value)"> @click.native="clickMenu(field.value)">
@@ -61,6 +75,6 @@
<script lang="ts" src="./SubMenus.ts"> <script lang="ts" src="./SubMenus.ts">
</script> </script>
<style lang="scss" scoped> <style lang="scss">
@import './SubMenus.scss'; @import './SubMenus.scss';
</style> </style>

View File

@@ -20,7 +20,7 @@ import VueIdb from 'vue-idb'
import globalroutines from '../../../globalroutines/index' import globalroutines from '../../../globalroutines/index'
import $ from 'jquery' import $ from 'jquery'
import Api from "@api" import Api from '@api'
@Component({ @Component({
@@ -43,6 +43,9 @@ export default class Todo extends Vue {
itemDragEnd: any = null itemDragEnd: any = null
selrowid: number = 0 selrowid: number = 0
polling = null polling = null
mytypetransgroup: string = 'flip-list'
tmpstrTodos: string = ''
loadDone: boolean = false
fieldtochange: String [] = ['descr', 'completed', 'category', 'expiring_at', 'priority', 'id_prev', 'id_next', 'pos', 'enableExpiring', 'progress'] fieldtochange: String [] = ['descr', 'completed', 'category', 'expiring_at', 'priority', 'id_prev', 'id_next', 'pos', 'enableExpiring', 'progress']
@@ -65,7 +68,10 @@ export default class Todo extends Vue {
@Watch('$route.params.category') changecat() { @Watch('$route.params.category') changecat() {
// console.log('changecat') // console.log('changecat')
this.load() this.mytypetransgroup = 'nessuno'
this.updatetable(false, '$route.params.category').then(() => {
this.mytypetransgroup = 'crossfade'
})
} }
get todos_changed() { get todos_changed() {
@@ -76,23 +82,31 @@ export default class Todo extends Vue {
return Todos.state.reload_fromServer return Todos.state.reload_fromServer
} }
set reload_fromServer(value: number) {
Todos.state.reload_fromServer = value
}
@Watch('todos_changed', { immediate: true, deep: true }) @Watch('todos_changed', { immediate: true, deep: true })
changetodos_changed(value: string, oldValue: string) { changetodos_changed(value: number, oldValue: number) {
this.$q.notify('Changed...') // this.$q.notify('Changed...')
if ((value > 1) && (this.loadDone)) {
// console.log('Todos.state.todos_changed CHANGED!', value, oldValue) // console.log('Todos.state.todos_changed CHANGED!', value, oldValue)
this.updatetable(true) this.updatetable(true, 'todos_changed')
}
} }
@Watch('reload_fromServer', { immediate: true }) @Watch('reload_fromServer', { immediate: true })
reload_fromServer_changed(value: string, oldValue: string) { reload_fromServer_changed(value: number, oldValue: number) {
console.log('reload_fromServer_changed!', value, oldValue) if (value > 0) {
// console.log('reload_fromServer_changed!', value, oldValue)
// if (value) { // if (value) {
Todos.actions.dbLoadTodo(false) Todos.actions.dbLoadTodo(false)
Todos.actions.updateArrayInMemory() Todos.actions.updateArrayInMemory()
}
// } // }
} }
@@ -104,7 +118,37 @@ export default class Todo extends Vue {
@Watch('testPao', { immediate: true, deep: true }) @Watch('testPao', { immediate: true, deep: true })
changedTestpao(value: string, oldValue: string) { changedTestpao(value: string, oldValue: string) {
// console.log('testpao CHANGED', value, oldValue) // console.log('testpao CHANGED', value, oldValue)
this.updatetable(true) // this.updatetable(true, 'testPao')
}
getArrTodos() {
let mystr = ''
let mythis = this
mythis.tmpstrTodos = ''
globalroutines(null, 'readall', 'todos', null)
.then(function (alldata) {
const myrecs = [...alldata]
myrecs.forEach(rec => {
mystr = mystr + rec.descr + '] ['
})
mythis.tmpstrTodos = 'TODOS: ' + mystr
})
}
setArrTodos() {
let mystr = ''
let mythis = this
mythis.tmpstrTodos = ''
globalroutines(null, 'write', 'todos', this.todos_arr[0])
.then(function (alldata) {
mythis.getArrTodos()
})
} }
getCategory() { getCategory() {
@@ -279,7 +323,7 @@ export default class Todo extends Vue {
// Updated only elements modified // Updated only elements modified
await this.updateModifyRecords(true) await this.updateModifyRecords(true)
this.updatetable() this.updatetable(false, 'onEnd')
} }
@@ -295,7 +339,7 @@ export default class Todo extends Vue {
}) })
if (update) if (update)
await this.updatetable(refresh) await this.updatetable(refresh, 'updateModifyRecords')
} }
@@ -318,7 +362,8 @@ export default class Todo extends Vue {
async load() { async load() {
this.todos_arr = [...Todos.state.todos]
// this.todos_arr = [...Todos.state.todos]
// Set last category selected // Set last category selected
localStorage.setItem(rescodes.localStorage.categorySel, this.getCategory()) localStorage.setItem(rescodes.localStorage.categorySel, this.getCategory())
@@ -330,17 +375,13 @@ export default class Todo extends Vue {
this.setarrPriority() this.setarrPriority()
this.clearArr() this.clearArr()
await this.updatetable() await this.updatetable(false, 'load')
this.checkUpdate_everytime() this.checkUpdate_everytime()
/*
this.todos_arr.forEach((elem, index) => {
this.logelem('LOAD ' + index, elem)
})
*/
this.loadDone = true
} }
// Call to check if need to refresh // Call to check if need to refresh
@@ -350,24 +391,11 @@ export default class Todo extends Vue {
}, 10000) }, 10000)
} }
copy(o) {
let output, v, key
output = Array.isArray(o) ? [] : {}
for (key in o) {
v = o[key]
output[key] = (typeof v === 'object') ? this.copy(v) : v
}
return output
}
initcat() { initcat() {
let tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1)
let mydatenow = new Date().getDate()
let mydateexp = new Date().getDate() + 10
console.log('User:' + UserStore.state.userId)
const objtodo: ITodo = { const objtodo: ITodo = {
// _id: new Date().toISOString(), // Create NEW // _id: new Date().toISOString(), // Create NEW
@@ -376,11 +404,11 @@ export default class Todo extends Vue {
descr: '', descr: '',
priority: rescodes.Todos.PRIORITY_NORMAL, priority: rescodes.Todos.PRIORITY_NORMAL,
completed: false, completed: false,
created_at: mydatenow, created_at: new Date(),
modify_at: mydatenow, modify_at: new Date(),
completed_at: 0, completed_at: new Date(),
category: '', category: '',
expiring_at: mydateexp, expiring_at: tomorrow,
enableExpiring: false, enableExpiring: false,
id_prev: '', id_prev: '',
id_next: '', id_next: '',
@@ -388,7 +416,8 @@ export default class Todo extends Vue {
modified: false, modified: false,
progress: 0 progress: 0
} }
return this.copy(objtodo) // return this.copy(objtodo)
return objtodo
} }
@@ -417,8 +446,6 @@ export default class Todo extends Vue {
const objtodo = this.initcat() const objtodo = this.initcat()
console.log('insertTodo ', UserStore.state.userId)
objtodo.descr = this.todo objtodo.descr = this.todo
objtodo.category = this.getCategory() objtodo.category = this.getCategory()
const lastelem: ITodo = this.getLastList() const lastelem: ITodo = this.getLastList()
@@ -432,30 +459,18 @@ export default class Todo extends Vue {
return return
} }
await globalroutines(this, 'write', 'todos', objtodo) const id = await globalroutines(this, 'write', 'todos', objtodo)
.then((id) => {
console.log('*** IDNEW (3) = ', id)
// update also the last elem // update also the last elem
if (lastelem !== null) { if (lastelem !== null) {
lastelem.id_next = id lastelem.id_next = id
// lastelem.modified = true // lastelem.modified = true
console.log('calling MODIFY 4', lastelem) // console.log('calling MODIFY 4', lastelem)
} }
this.modify(lastelem, false) const rismod = await this.modify(lastelem, false)
.then(ris => {
console.log('END calling MODIFY 4')
this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS, 'POST', objtodo, true) this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS, 'POST', objtodo, true)
this.updatetable(false) this.updatetable(false, 'insertTodo')
})
}).catch(err => {
console.log('Errore: ' + err.message)
})
// console.log('ESCO.........') // console.log('ESCO.........')
@@ -474,17 +489,17 @@ export default class Todo extends Vue {
cmdSw = rescodes.DB.CMD_SYNC_TODOS cmdSw = rescodes.DB.CMD_SYNC_TODOS
} }
if (process.env.DEV) { // if (process.env.DEV) {
console.log('serviceWorker ', ('serviceWorker' in navigator) ? 'PRESENT!' : 'DOESN\'T EXIST!') // console.log('serviceWorker ', ('serviceWorker' in navigator) ? 'PRESENT!' : 'DOESN\'T EXIST!')
console.log('SyncManager ', ('SyncManager' in window) ? 'PRESENT!' : 'DOESN\'T EXIST!') // console.log('SyncManager ', ('SyncManager' in window) ? 'PRESENT!' : 'DOESN\'T EXIST!')
} // }
const mythis = this const mythis = this
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
await navigator.serviceWorker.ready await navigator.serviceWorker.ready
.then(function (sw) { .then(function (sw) {
// _id: new Date().toISOString(), // _id: new Date().toISOString(),
console.log('---------------------- navigator.serviceWorker.ready') // console.log('---------------------- navigator.serviceWorker.ready')
// mythis.sendMessageToSW(item, method) // mythis.sendMessageToSW(item, method)
@@ -495,20 +510,20 @@ export default class Todo extends Vue {
}) })
const sep = '|' const sep = '|'
let multiparams = cmdSw + sep + table + sep + method + sep + UserStore.state.idToken + sep + UserStore.state.lang let multiparams = cmdSw + sep + table + sep + method + sep + UserStore.state.x_auth_token + sep + UserStore.state.lang
let mymsgkey = { let mymsgkey = {
_id: multiparams, _id: multiparams,
value: multiparams value: multiparams
} }
globalroutines(mythis, 'write', 'swmsg', mymsgkey, multiparams) globalroutines(mythis, 'write', 'swmsg', mymsgkey, multiparams)
.then(ris => { .then(ris => {
if ('SyncManager' in window) { // if ('SyncManager' in window) {
console.log(' SENDING... sw.sync.register', multiparams) // console.log(' SENDING... sw.sync.register', multiparams)
return sw.sync.register(multiparams) // return sw.sync.register(multiparams)
} else { // } else {
// #Todo ++ Alternative 2 to SyncManager // #Todo ++ Alternative 2 to SyncManager
Api.syncAlternative(multiparams) Api.syncAlternative(multiparams)
} // }
}) })
.then(function () { .then(function () {
@@ -541,12 +556,12 @@ export default class Todo extends Vue {
} }
async saveItemToSyncAndDb(table: String, method, item: ITodo, update: boolean) { async saveItemToSyncAndDb(table: String, method, item: ITodo, update: boolean) {
return await this.cmdToSyncAndDb(rescodes.DB.CMD_SYNC_NEW_TODOS, table, method, item, 0, 'Your Post was saved for syncing!', update) return await this.cmdToSyncAndDb(rescodes.DB.CMD_SYNC_NEW_TODOS, table, method, item, 0, '', update)
} }
deleteItemToSyncAndDb(table: String, item: ITodo, id, update: boolean) { deleteItemToSyncAndDb(table: String, item: ITodo, id, update: boolean) {
return this.cmdToSyncAndDb(rescodes.DB.CMD_DELETE_TODOS, table, 'DELETE', item, id, 'Your Post was canceled for syncing!', update) return this.cmdToSyncAndDb(rescodes.DB.CMD_DELETE_TODOS, table, 'DELETE', item, id, '', update)
} }
/* /*
@@ -604,13 +619,13 @@ export default class Todo extends Vue {
// Delete item // Delete item
await globalroutines(this, 'delete', 'todos', null, id) await globalroutines(this, 'delete', 'todos', null, id)
.then((ris) => { .then((ris) => {
mythis.updatetable() mythis.updatetable(false, 'deleteitem')
}).catch((error) => { }).catch((error) => {
console.log('err: ', error) console.log('err: ', error)
}) })
} }
console.log('FINE deleteitem') // console.log('FINE deleteitem')
} }
getElem(myarray: ITodo[], id) { getElem(myarray: ITodo[], id) {
@@ -625,13 +640,17 @@ export default class Todo extends Vue {
return itemnew.pos !== itemold.pos return itemnew.pos !== itemold.pos
} }
async updatetable(refresh: boolean = false) { async updatetable(refresh: boolean = false, strpos = '') {
// console.log('updatetable') console.log('updatetable', strpos)
this.prevRecords = [...this.todos_arr] this.prevRecords = [...this.todos_arr]
return await Todos.actions.getTodosByCategory(this.getCategory()) return await Todos.actions.getTodosByCategory(this.getCategory())
.then(arrtemp => { .then(arrris => {
this.todos_arr = []
let arrtemp = [...arrris]
arrtemp = _.orderBy(arrtemp, ['completed', 'priority', 'pos'], ['asc', 'desc', 'asc']) arrtemp = _.orderBy(arrtemp, ['completed', 'priority', 'pos'], ['asc', 'desc', 'asc'])
@@ -646,6 +665,8 @@ export default class Todo extends Vue {
this.todos_arr = [...arrtemp] // make copy this.todos_arr = [...arrtemp] // make copy
console.log('AGGIORNA todos_arr')
}) })
} }
@@ -729,7 +750,7 @@ export default class Todo extends Vue {
} }
updateitem(myobj) { updateitem(myobj) {
console.log('updateitem') console.log('calling MODIFY 4 updateitem')
this.modify(myobj, true) this.modify(myobj, true)
} }
@@ -777,8 +798,10 @@ export default class Todo extends Vue {
// } // }
modifyField(recOut, recIn, field) { modifyField(recOut, recIn, field) {
if (recOut[field] !== recIn[field]) { if (String(recOut[field]) !== String(recIn[field])) {
console.log('*************** CAMPO ', field, 'MODIFICATO!', recOut[field], recIn[field]) console.log('*************** CAMPO ', field, 'MODIFICATO!')
console.log(recOut[field])
console.log(recIn[field])
recOut.modified = true recOut.modified = true
recOut[field] = recIn[field] recOut[field] = recIn[field]
return true return true
@@ -822,7 +845,7 @@ export default class Todo extends Vue {
// console.log('SET MODIFIED FALSE') // console.log('SET MODIFIED FALSE')
if (update) if (update)
this.updatetable(false) this.updatetable(false, 'modify')
}) })
}) })
@@ -843,7 +866,7 @@ export default class Todo extends Vue {
} }
clicktest2() { clicktest2() {
this.updatetable(false) this.updatetable(false, 'clicktest')
console.log('Todos.state.todos', Todos.state.todos) console.log('Todos.state.todos', Todos.state.todos)
} }

View File

@@ -12,7 +12,7 @@
<div class="drag"> <div class="drag">
<draggable v-model="todos_arr" :options="{draggable:'.myitemdrag'}" <draggable v-model="todos_arr" :options="{draggable:'.myitemdrag'}"
@start="onStart" @end="onEnd" class="dragArea"> @start="onStart" @end="onEnd" class="dragArea">
<transition-group> <transition-group :name="mytypetransgroup">
<div :id="getmyid(mytodo._id)" :key="mytodo._id" v-for="mytodo in todos_arr" class="myitemdrag"> <div :id="getmyid(mytodo._id)" :key="mytodo._id" v-for="mytodo in todos_arr" class="myitemdrag">
<div v-if="(prior !== mytodo.priority) && !mytodo.completed" :class="getTitlePriority(mytodo.priority)"> <div v-if="(prior !== mytodo.priority) && !mytodo.completed" :class="getTitlePriority(mytodo.priority)">
@@ -35,15 +35,24 @@
:after="[{icon: 'arrow_forward', content: true, handler () {}}]" :after="[{icon: 'arrow_forward', content: true, handler () {}}]"
v-on:keyup.enter="insertTodo"/> v-on:keyup.enter="insertTodo"/>
<q-input v-model="testPao" float-label="testPao"/> <!--{{ tmpstrTodos }}-->
<q-input v-model="todos_changed" float-label="todos_changed"/>
<q-input v-model="reload_fromServer" float-label="reload_fromServer"/>
<div class="flex-item btn-item"> <!--<div class="flex-item btn-item">-->
<!--<q-btn class="mybtn" round color="" icon="lock" @click="clicktest()"></q-btn>--> <!--<q-btn class="mybtn" round color="" icon="lock" @click="getArrTodos">Get Todo</q-btn>-->
<!--<q-btn class="mybtn" round color="" icon="person" @click="clicktest2()"></q-btn>--> <!--<q-btn class="mybtn" round color="" icon="person" @click="setArrTodos">Set Todo</q-btn>-->
<q-btn class="mybtn" round color="" icon="list" @click="checkUpdate()"></q-btn> <!--<q-btn class="mybtn" round color="" icon="list" @click="reload_fromServer++">Reload</q-btn>-->
</div> <!--</div>-->
<!--<q-input v-model="testPao" float-label="testPao"/>-->
<!--<q-input v-model="todos_changed" float-label="todos_changed"/>-->
<!--<q-input v-model="reload_fromServer" float-label="reload_fromServer"/>-->
<!--<div class="flex-item btn-item">-->
<!--&lt;!&ndash;<q-btn class="mybtn" round color="" icon="lock" @click="clicktest()"></q-btn>&ndash;&gt;-->
<!--&lt;!&ndash;<q-btn class="mybtn" round color="" icon="person" @click="clicktest2()"></q-btn>&ndash;&gt;-->
<!--<q-btn class="mybtn" round color="" icon="list" @click="checkUpdate()"></q-btn>-->
<!--</div>-->
</div> </div>
</q-page> </q-page>

View File

@@ -23,3 +23,4 @@ $positive = #21BA45
$negative = #DB2828 $negative = #DB2828
$info = #31CCEC $info = #31CCEC
$warning = #F2C037 $warning = #F2C037

View File

@@ -1,4 +1,4 @@
import store from '../store' import store, { GlobalStore } from '../store'
import _ from 'lodash' import _ from 'lodash'
import { UserStore, Todos } from '@store' import { UserStore, Todos } from '@store'
import { i18n } from '../plugins/i18n' import { i18n } from '../plugins/i18n'
@@ -10,7 +10,7 @@ function saveConfigIndexDb(context) {
let data = [] let data = []
data['_id'] = 1 data['_id'] = 1
data['lang'] = UserStore.state.lang data['lang'] = UserStore.state.lang
data['token'] = UserStore.state.idToken data['token'] = UserStore.state.x_auth_token
data['userId'] = UserStore.state.userId data['userId'] = UserStore.state.userId
writeConfigIndexDb('config', data) writeConfigIndexDb('config', data)
@@ -73,6 +73,8 @@ export default async (context, cmd, table, datakey = null, id = '') => {
return await storage.getdata(table, id) return await storage.getdata(table, id)
} else if (cmd === 'delete') { } else if (cmd === 'delete') {
return await storage.deletedata(table, id) return await storage.deletedata(table, id)
} else if (cmd === 'clearalldata') {
return await storage.clearalldata(table)
} else if (cmd === 'log') { } else if (cmd === 'log') {
consolelogpao(table) consolelogpao(table)
} }

View File

@@ -1,5 +1,6 @@
export let idbKeyval = (() => { export let idbKeyval = (() => {
let db; let db;
const fieldsData = ['completed_at', 'created_at', 'expiring_at', 'modify_at']
function getDB() { function getDB() {
if (!db) { if (!db) {
@@ -47,14 +48,18 @@ export let idbKeyval = (() => {
}); });
return req.result; return req.result;
}, },
jsonCopy(src) {
return JSON.parse(JSON.stringify(src));
},
async getdata(table, key) { async getdata(table, key) {
let req; let req;
await withStore('readonly', table, store => { await withStore('readonly', table, store => {
console.log('store', store, 'key', key) console.log('getdata', table, key)
req = store.get(key); req = store.get(key);
}); });
// console.log('RISFINALE!', req.result)
return req.result; return req.result;
}, },
async getalldata(table) { async getalldata(table) {
@@ -80,8 +85,8 @@ export let idbKeyval = (() => {
}, },
async setdata(table, value) { async setdata(table, value) {
let req; let req;
console.log('setdata', table, value)
// console.log('setdata', table, value)
await withStore('readwrite', table, store => { await withStore('readwrite', table, store => {
req = store.put(value); req = store.put(value);
}); });
@@ -98,6 +103,7 @@ export let idbKeyval = (() => {
}); });
}, },
async clearalldata(table) { async clearalldata(table) {
// console.log('clearalldata', table)
return await withStore('readwrite', table, store => { return await withStore('readwrite', table, store => {
store.clear(); store.clear();
}); });

View File

@@ -102,7 +102,7 @@
} }
get Verificato() { get Verificato() {
return UserStore.state.verifiedEmail return UserStore.state.verified_email
} }
get Email() { get Email() {
@@ -111,6 +111,7 @@
logoutHandler() { logoutHandler() {
UserStore.actions.logout() UserStore.actions.logout()
this.$router.push('/signin')
this.$q.notify(this.$t('logout.uscito')) this.$q.notify(this.$t('logout.uscito'))
} }
} }

View File

@@ -2,15 +2,19 @@ export interface IPost {
title: string title: string
} }
export type StateConnection = 'online' | 'offline'
export interface IGlobalState { export interface IGlobalState {
conta: number conta: number
isSubscribed: boolean wasAlreadySubOnDb: boolean
wasAlreadySubscribed: boolean
isLoginPage: boolean isLoginPage: boolean
layoutNeeded: boolean layoutNeeded: boolean
mobileMode: boolean mobileMode: boolean
menuCollapse: boolean menuCollapse: boolean
leftDrawerOpen: boolean leftDrawerOpen: boolean
category: string category: string
stateConnection: string
posts: IPost[] posts: IPost[]
listatodo: ITodoList[] listatodo: ITodoList[]
} }

View File

@@ -5,10 +5,10 @@ export interface ITodo {
descr?: string, descr?: string,
priority: number, priority: number,
completed: boolean, completed: boolean,
created_at: any, created_at: Date,
modify_at: any, modify_at: Date,
completed_at: any, completed_at: Date,
expiring_at: any, expiring_at: Date,
enableExpiring?: boolean, enableExpiring?: boolean,
id_prev?: string, id_prev?: string,
id_next?: string, id_next?: string,
@@ -22,7 +22,7 @@ export interface ITodosState {
networkDataReceived: boolean networkDataReceived: boolean
todos: ITodo[] todos: ITodo[]
todos_changed: number todos_changed: number
reload_fromServer: boolean reload_fromServer: number
testpao: String testpao: String
insidePending: boolean insidePending: boolean
} }

View File

@@ -17,8 +17,6 @@ export interface IUserState {
lang?: string lang?: string
repeatPassword?: string repeatPassword?: string
idToken?: string
tokens?: IToken[] tokens?: IToken[]
verified_email?: boolean verified_email?: boolean
@@ -27,6 +25,7 @@ export interface IUserState {
tokenforgot?: string tokenforgot?: string
servercode?: number servercode?: number
resStatus?: number
x_auth_token?: string x_auth_token?: string
isLogged?: boolean isLogged?: boolean
} }

View File

@@ -1,6 +1,8 @@
export interface IToken { export interface IToken {
access: string access: string
// browser: string
token: string token: string
data_login: Date
} }
@@ -9,7 +11,7 @@ export interface ILinkReg {
} }
export interface IIdToken { export interface IIdToken {
idToken: string x_auth_token: string
} }
export interface IResult { export interface IResult {

View File

@@ -57,9 +57,10 @@ export default class Home extends Vue {
initprompt() { initprompt() {
window.addEventListener('beforeinstallprompt', function (event) { window.addEventListener('beforeinstallprompt', function (event) {
console.log('******************************** beforeinstallprompt fired') // console.log('******************************** beforeinstallprompt fired')
event.preventDefault() event.preventDefault()
console.log('§§§§§§§§§§§§§§§§§§§§ IMPOSTA DEFERRED PROMPT !!!!!!!!!!!!!!!!! ') // console.log('§§§§§§§§§§§§§§§§§§§§ IMPOSTA DEFERRED PROMPT !!!!!!!!!!!!!!!!! ')
// #Todo++ IMPOSTA DEFERRED PROMPT
return false return false
}) })
@@ -69,6 +70,10 @@ export default class Home extends Vue {
return Notification.permission return Notification.permission
} }
NotServiceWorker () {
return (!('serviceWorker' in navigator))
}
displayConfirmNotification() { displayConfirmNotification() {
let options = null let options = null
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
@@ -88,12 +93,14 @@ export default class Home extends Vue {
] ]
} }
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready navigator.serviceWorker.ready
.then(function (swreg) { .then(function (swreg) {
swreg.showNotification('Successfully subscribed!', options) swreg.showNotification('Successfully subscribed!', options)
}) })
} }
} }
}
urlBase64ToUint8Array(base64String) { urlBase64ToUint8Array(base64String) {
let padding = '='.repeat((4 - base64String.length % 4) % 4) let padding = '='.repeat((4 - base64String.length % 4) % 4)
@@ -168,7 +175,6 @@ export default class Home extends Vue {
} }
test_fetch() { test_fetch() {
fetch('https:/httpbin.org/post', { fetch('https:/httpbin.org/post', {
method: 'POST', method: 'POST',

View File

@@ -5,6 +5,8 @@
<q-btn v-if="getPermission() !== 'granted'" class="enable-notifications" color="primary" rounded size="lg" icon="notifications" @click="askfornotification" :label="$t('notification.ask')"/> <q-btn v-if="getPermission() !== 'granted'" class="enable-notifications" color="primary" rounded size="lg" icon="notifications" @click="askfornotification" :label="$t('notification.ask')"/>
<q-btn v-if="getPermission() === 'granted'" class="enable-notifications" color="primary" rounded size="lg" icon="notifications" @click="showNotificationExample" label="Send Notification"/> <q-btn v-if="getPermission() === 'granted'" class="enable-notifications" color="primary" rounded size="lg" icon="notifications" @click="showNotificationExample" label="Send Notification"/>
<!--<q-btn v-if="getPermission() === 'granted'" class="enable-notifications" color="secondary" rounded size="lg" icon="notifications" @click="createPushSubscription" label="Create Push Subscription !"/>--> <!--<q-btn v-if="getPermission() === 'granted'" class="enable-notifications" color="secondary" rounded size="lg" icon="notifications" @click="createPushSubscription" label="Create Push Subscription !"/>-->
<br> <br>
<div> <div>
<q-chip square color="secondary"> <q-chip square color="secondary">
@@ -16,6 +18,12 @@
:label="$t('notification.titlegranted')" :label="$t('notification.titlegranted')"
helper="Stato Notifiche"> helper="Stato Notifiche">
</q-field> </q-field>
<q-field
v-if="NotServiceWorker()"
icon="notifications"
label="Service Worker not present"
>
</q-field>
</div> </div>
</q-page> </q-page>

View File

@@ -34,6 +34,11 @@ export const RouteConfig: VueRouteConfig[] = [
path: '/category', path: '/category',
component: () => import('@/components/categories/category/category.vue'), component: () => import('@/components/categories/category/category.vue'),
meta: { name: 'Categories' } meta: { name: 'Categories' }
},
{
path: '/offline',
component: () => import('@/components/offline/offline.vue'),
meta: { name: 'Offline' }
} }
/* /*
{ {

View File

@@ -17,7 +17,7 @@ const messages = {
msg: { msg: {
hello: 'Buongiorno', hello: 'Buongiorno',
myAppName: 'FreePlanet', myAppName: 'FreePlanet',
myDescriz: 'La prima App Libera' myDescriz: ''
}, },
pages: { pages: {
home: 'Principale', home: 'Principale',
@@ -51,6 +51,7 @@ const messages = {
fetch: { fetch: {
errore_generico: 'Errore Generico', errore_generico: 'Errore Generico',
errore_server: 'Impossibile accedere al Server. Riprovare Grazie', errore_server: 'Impossibile accedere al Server. Riprovare Grazie',
error_doppiologin: 'Rieseguire il Login. Accesso aperto da un altro dispositivo.',
}, },
user: { user: {
notregistered: 'Devi registrarti al servizio prima di porter memorizzare i dati' notregistered: 'Devi registrarti al servizio prima di porter memorizzare i dati'
@@ -121,7 +122,8 @@ const messages = {
titledenied: 'Permesso Notifiche Disabilitato!', titledenied: 'Permesso Notifiche Disabilitato!',
title_subscribed: 'Sottoscrizione a FreePlanet.app!', title_subscribed: 'Sottoscrizione a FreePlanet.app!',
subscribed: 'Ora potrai ricevere i messaggi e le notifiche.' subscribed: 'Ora potrai ricevere i messaggi e le notifiche.'
} },
connection: 'Connessione',
}, },
es: { es: {
dialog: { dialog: {
@@ -141,7 +143,7 @@ const messages = {
msg: { msg: {
hello: 'Buenos Días', hello: 'Buenos Días',
myAppName: 'FreePlanet', myAppName: 'FreePlanet',
myDescriz: 'La primera App Libera' myDescriz: ''
}, },
pages: { pages: {
home: 'Principal', home: 'Principal',
@@ -175,6 +177,7 @@ const messages = {
fetch: { fetch: {
errore_generico: 'Error genérico', errore_generico: 'Error genérico',
errore_server: 'No se puede acceder al Servidor. Inténtalo de nuevo, Gracias', errore_server: 'No se puede acceder al Servidor. Inténtalo de nuevo, Gracias',
error_doppiologin: 'Vuelva a iniciar sesión. Acceso abierto por otro dispositivo.',
}, },
user: { user: {
notregistered: 'Debe registrarse en el servicio antes de poder almacenar los datos' notregistered: 'Debe registrarse en el servicio antes de poder almacenar los datos'
@@ -245,7 +248,8 @@ const messages = {
titledenied: 'Notificaciones permitidas deshabilitadas!', titledenied: 'Notificaciones permitidas deshabilitadas!',
title_subscribed: 'Suscripción a FreePlanet.app!', title_subscribed: 'Suscripción a FreePlanet.app!',
subscribed: 'Ahora puedes recibir mensajes y notificaciones.' subscribed: 'Ahora puedes recibir mensajes y notificaciones.'
} },
connection: 'Connection',
}, },
enUk: { enUk: {
dialog: { dialog: {
@@ -265,7 +269,7 @@ const messages = {
msg: { msg: {
hello: 'Hello!', hello: 'Hello!',
myAppName: 'FreePlanet', myAppName: 'FreePlanet',
myDescriz: 'The first Free app' myDescriz: ''
}, },
pages: { pages: {
home: 'Dashboard One', home: 'Dashboard One',
@@ -299,6 +303,7 @@ const messages = {
fetch: { fetch: {
errore_generico: 'Generic Error', errore_generico: 'Generic Error',
errore_server: 'Unable to access to the Server. Retry. Thank you.', errore_server: 'Unable to access to the Server. Retry. Thank you.',
error_doppiologin: 'Signup again. Another access was made with another device.',
}, },
user: { user: {
notregistered: 'You need first to SignUp before storing data' notregistered: 'You need first to SignUp before storing data'
@@ -369,7 +374,8 @@ const messages = {
titledenied: 'Notification Permission Denied!', titledenied: 'Notification Permission Denied!',
title_subscribed: 'Subscribed to FreePlanet.app!', title_subscribed: 'Subscribed to FreePlanet.app!',
subscribed: 'You can now receive Notification and Messages.' subscribed: 'You can now receive Notification and Messages.'
} },
connection: 'Conexión',
}, },
}; };

View File

@@ -1,5 +1,6 @@
let idbKeyval = (() => { let idbKeyval = (() => {
let db; let db;
// console.log('idbKeyval...')
function getDB() { function getDB() {
if (!db) { if (!db) {
@@ -47,14 +48,28 @@ let idbKeyval = (() => {
}); });
return req.result; return req.result;
}, },
// jsonCopy(src) {
// return JSON.parse(JSON.stringify(src));
// },
// contains(a, b) {
// // array matches
// if (Array.isArray(b)) {
// return b.some(x => a.indexOf(x) > -1);
// }
// // string match
// return a.indexOf(b) > -1;
// },
async getdata(table, key) { async getdata(table, key) {
let req; let req;
await withStore('readonly', table, store => { await withStore('readonly', table, store => {
console.log('store', store, 'key', key) // console.log('store', store, 'key', key)
req = store.get(key); req = store.get(key);
}); });
// console.log('RISFINALE!', req.result)
return req.result; return req.result;
}, },
async getalldata(table) { async getalldata(table) {
@@ -73,7 +88,7 @@ let idbKeyval = (() => {
}, },
async setdata(table, value) { async setdata(table, value) {
let req; let req;
console.log('setdata', table, value) // console.log('setdata', table, value)
await withStore('readwrite', table, store => { await withStore('readwrite', table, store => {
req = store.put(value); req = store.put(value);
@@ -91,6 +106,7 @@ let idbKeyval = (() => {
}); });
}, },
async clearalldata(table) { async clearalldata(table) {
// console.log('clearalldata', table)
return await withStore('readwrite', table, store => { return await withStore('readwrite', table, store => {
store.clear(); store.clear();
}); });

View File

@@ -7,7 +7,10 @@ async function sendRequest(url: string, lang: string, mytok: string, method: str
const authHeader = new Headers() const authHeader = new Headers()
authHeader.append('content-Type', 'application/json') authHeader.append('content-Type', 'application/json')
authHeader.append('Accept', 'application/json') authHeader.append('Accept', 'application/json')
if (url !== process.env.MONGODB_HOST + '/users/login') {
authHeader.append('x-auth', mytok) authHeader.append('x-auth', mytok)
// console.log('TOK PASSATO ALLA FETCH:', mytok)
}
// authHeader.append('accept-language', lang) // authHeader.append('accept-language', lang)
let configInit: RequestInit let configInit: RequestInit
@@ -16,21 +19,27 @@ async function sendRequest(url: string, lang: string, mytok: string, method: str
configInit = { configInit = {
method: method, method: method,
cache: 'no-cache', cache: 'no-cache',
mode: 'cors',
headers: authHeader headers: authHeader
} }
} else if (method === 'DELETE') { } else if (method === 'DELETE') {
configInit = { configInit = {
method: method, method: method,
cache: 'no-cache', cache: 'no-cache',
mode: 'cors',
headers: authHeader headers: authHeader
} }
} else { } else {
configInit = { configInit = {
method: method, method: method,
cache: 'no-cache', cache: 'no-cache',
body: JSON.stringify(mydata), mode: 'cors',
headers: authHeader headers: authHeader
} }
if (mydata !== null)
configInit.body = JSON.stringify(mydata)
} }
const request: Promise<Response> = fetch(url, configInit) const request: Promise<Response> = fetch(url, configInit)

View File

@@ -9,8 +9,10 @@ export { addAuthHeaders, removeAuthHeaders, API_URL } from './Instance'
import Paths from '@paths' import Paths from '@paths'
import { rescodes } from '@src/store/Modules/rescodes' import { rescodes } from '@src/store/Modules/rescodes'
import { UserStore } from '@modules' import { GlobalStore, UserStore } from '@modules'
import globalroutines from './../../globalroutines/index' import globalroutines from './../../globalroutines/index'
import { serv_constants } from '@src/store/Modules/serv_constants'
import router from '@router'
// const algoliaApi = new AlgoliaSearch() // const algoliaApi = new AlgoliaSearch()
@@ -45,53 +47,70 @@ export namespace ApiTool {
}) })
} }
export async function SendReq(url: string, lang: string, mytok: string, method: string, mydata: any, noAuth: boolean = false) { export async function SendReq(url: string, method: string, mydata: any, setAuthToken: boolean = false) {
UserStore.mutations.setServerCode(rescodes.EMPTY) UserStore.mutations.setServerCode(rescodes.EMPTY)
UserStore.mutations.setAuth('') UserStore.mutations.setResStatus(0)
return await new Promise(function (resolve, reject) { return await new Promise(function (resolve, reject) {
let ricevuto = false let ricevuto = false
sendRequest(url, lang, mytok, method, mydata)
return sendRequest(url, UserStore.state.lang, UserStore.state.x_auth_token, method, mydata)
.then(resreceived => { .then(resreceived => {
console.log('resreceived', resreceived)
ricevuto = true ricevuto = true
let res = resreceived.clone() let res = resreceived.clone()
if (process.env.DEV) { if (process.env.DEV) {
console.log('SendReq RES [', res.status, ']', res) // console.log('SendReq RES [', res.status, ']', res)
} }
let x_auth_token = '' UserStore.mutations.setResStatus(res.status)
if (res.status === 200) { if (res.status === 200) {
let x_auth_token = ''
try { try {
if (!noAuth) { if (setAuthToken) {
x_auth_token = String(res.headers.get('x-auth')) x_auth_token = String(res.headers.get('x-auth'))
if (url === process.env.MONGODB_HOST + '/updatepwd') {
UserStore.mutations.UpdatePwd({ idToken: x_auth_token })
localStorage.setItem(rescodes.localStorage.token, x_auth_token)
}
if (x_auth_token === '') { if (x_auth_token === '') {
UserStore.mutations.setServerCode(rescodes.ERR_AUTHENTICATION) UserStore.mutations.setServerCode(rescodes.ERR_AUTHENTICATION)
} }
UserStore.mutations.setAuth(x_auth_token)
if (url === process.env.MONGODB_HOST + '/updatepwd') {
UserStore.mutations.UpdatePwd({ x_auth_token })
localStorage.setItem(rescodes.localStorage.token, x_auth_token)
}
} }
UserStore.mutations.setServerCode(rescodes.OK) UserStore.mutations.setServerCode(rescodes.OK)
UserStore.mutations.setAuth(x_auth_token)
} catch (e) { } catch (e) {
if (!noAuth) { if (setAuthToken) {
UserStore.mutations.setServerCode(rescodes.ERR_AUTHENTICATION) UserStore.mutations.setServerCode(rescodes.ERR_AUTHENTICATION)
UserStore.mutations.setAuth(x_auth_token) UserStore.mutations.setAuth('')
} }
return reject(e) GlobalStore.mutations.setStateConnection(ricevuto ? 'online' : 'offline')
return reject({ code: rescodes.ERR_AUTHENTICATION })
} }
} else if (res.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
// Forbidden
// You probably is connectiong with other page...
UserStore.mutations.setServerCode(rescodes.ERR_AUTHENTICATION)
UserStore.mutations.setAuth('')
GlobalStore.mutations.setStateConnection(ricevuto ? 'online' : 'offline')
router.push('/signin')
return reject({ code: rescodes.ERR_AUTHENTICATION })
} }
GlobalStore.mutations.setStateConnection(ricevuto ? 'online' : 'offline')
return res.json() return res.json()
.then((body) => { .then((body) => {
return resolve({ res, body }) // console.log('BODY RES = ', body)
return resolve({ res, body, status: res.status })
}) })
.catch(e => { .catch(e => {
UserStore.mutations.setServerCode(rescodes.ERR_GENERICO) return resolve({ res, body: {}, status: res.status })
return reject(e) // Array not found...
// UserStore.mutations.setServerCode(rescodes.ERR_GENERICO)
// return reject({ code: rescodes.ERR_GENERICO, status: res.status })
}) })
}) })
@@ -104,7 +123,10 @@ export namespace ApiTool {
} else { } else {
UserStore.mutations.setServerCode(rescodes.ERR_GENERICO) UserStore.mutations.setServerCode(rescodes.ERR_GENERICO)
} }
return reject(error)
GlobalStore.mutations.setStateConnection(ricevuto ? 'online' : 'offline')
return reject({ code: error })
}) })
}) })
} }
@@ -122,57 +144,74 @@ export namespace ApiTool {
// let lang = multiparams[3] // let lang = multiparams[3]
if (cmd === 'sync-todos') { if (cmd === 'sync-todos') {
console.log('[Alternative] Syncing', cmd, table, method) // console.log('[Alternative] Syncing', cmd, table, method)
const headers = new Headers() const headers = new Headers()
headers.append('content-Type', 'application/json') headers.append('content-Type', 'application/json')
headers.append('Accept', 'application/json') headers.append('Accept', 'application/json')
headers.append('x-auth', token) headers.append('x-auth', token)
console.log('A1) INIZIO.............................................................') let errorfromserver = false
let lettoqualcosa = false
await globalroutines(null, 'readall', table, null) // console.log('A1) INIZIO.............................................................')
return globalroutines(null, 'readall', table, null)
.then(function (alldata) { .then(function (alldata) {
const myrecs = [...alldata] const myrecs = [...alldata]
console.log('----------------------- LEGGO QUALCOSA ') // console.log('----------------------- LEGGO QUALCOSA ')
if (myrecs) {
for (let rec of myrecs) { const promises = myrecs.map(rec => {
// console.log('syncing', table, '', rec.descr) // console.log('syncing', table, '', rec.descr)
let link = process.env.MONGODB_HOST + '/todos' let link = process.env.MONGODB_HOST + '/todos'
if (method !== 'POST') if (method !== 'POST')
link += '/' + rec._id link += '/' + rec._id
console.log(' [Alternative] ++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:') // console.log(' [Alternative] ++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:')
// Insert/Delete/Update table to the server // Insert/Delete/Update table to the server
fetch(link, { return fetch(link, {
method: method, method: method,
headers: headers, headers: headers,
cache: 'no-cache',
mode: 'cors', // 'no-cors', mode: 'cors', // 'no-cors',
body: JSON.stringify(rec) body: JSON.stringify(rec)
}) })
.then(function (resData) { .then(() => {
// console.log('Result CALL ', method, ' OK? =', resData.ok); lettoqualcosa = true
return globalroutines(null, 'delete', table, null, rec._id)
// Anyway Delete this, otherwise in some cases will return error, but it's not a problem. })
// for example if I change a record and then I deleted ... .then(() => {
// if (resData.ok) { return globalroutines(null, 'delete', 'swmsg', null, mystrparam)
// deleteItemFromData(table, rec._id);
globalroutines(null, 'delete', table, null, rec._id)
console.log('DELETE: ', mystrparam)
// deleteItemFromData('swmsg', mystrparam)
globalroutines(null, 'delete', 'swmsg', null, mystrparam)
}) })
.catch(function (err) { .catch(function (err) {
console.log(' [Alternative] !!!!!!!!!!!!!!! Error while sending data', err) if (err.message === 'Failed to fetch') {
}) errorfromserver = true
}
} }
// console.log(' [Alternative] !!!!!!!!!!!!!!! Error while sending data', err, errorfromserver, 'lettoqualcosa', lettoqualcosa)
}) })
console.log(' [Alternative] A2) ?????????????????????????? ESCO DAL LOOP !!!!!!!!! err=') })
// CALL ALL THE PROMISES
return Promise.all(promises).then(() => {
return (errorfromserver && !lettoqualcosa)
}).catch(err => {
return (errorfromserver && !lettoqualcosa)
})
}).catch(e => {
// console.log('ERROR:', e)
return (errorfromserver && !lettoqualcosa)
})
.then((errorfromserver) => {
// console.log('¨¨¨¨¨¨¨¨¨¨¨¨¨¨ errorfromserver:', errorfromserver)
const mystate = errorfromserver ? 'offline' : 'online'
GlobalStore.mutations.setStateConnection(mystate)
return globalroutines(null, 'write', 'config', { _id: 2, stateconn: mystate })
})
// console.log(' [Alternative] A2) ?????????????????????????? ESCO DAL LOOP !!!!!!!!!')
} }
} }
} }

View File

@@ -1,4 +1,4 @@
import { IGlobalState } from 'model' import { IGlobalState, StateConnection } from 'model'
import { storeBuilder } from './Store/Store' import { storeBuilder } from './Store/Store'
import Vue from 'vue' import Vue from 'vue'
@@ -8,16 +8,40 @@ import translate from './../../globalroutines/util'
import urlBase64ToUint8Array from '../../js/utility' import urlBase64ToUint8Array from '../../js/utility'
import messages from '../../statics/i18n' import messages from '../../statics/i18n'
import { UserStore } from "@store" import { GlobalStore, UserStore } from '@store'
import globalroutines from './../../globalroutines/index'
import Api from "@api"
import { rescodes } from "@src/store/Modules/rescodes"
const allTables = ['todos', 'sync_todos', 'sync_todos_patch', 'delete_todos', 'config', 'swmsg']
const allTablesAfterLogin = ['todos', 'sync_todos', 'sync_todos_patch', 'delete_todos', 'config', 'swmsg']
async function getstateConnSaved() {
const config = await globalroutines(null, 'readall', 'config', null)
if (config.length > 1) {
return config[1].stateconn
} else {
return 'online'
}
}
let stateConnDefault = 'online'
getstateConnSaved()
.then(conn => {
stateConnDefault = conn
})
const state: IGlobalState = { const state: IGlobalState = {
conta: 0, conta: 0,
isSubscribed: false, wasAlreadySubscribed: false,
wasAlreadySubOnDb: false,
isLoginPage: false, isLoginPage: false,
layoutNeeded: true, layoutNeeded: true,
mobileMode: false, mobileMode: false,
menuCollapse: true, menuCollapse: true,
leftDrawerOpen: true, leftDrawerOpen: true,
stateConnection: stateConnDefault,
category: 'personal', category: 'personal',
posts: [], posts: [],
listatodo: [ listatodo: [
@@ -27,6 +51,7 @@ const state: IGlobalState = {
] ]
} }
const b = storeBuilder.module<IGlobalState>('GlobalModule', state) const b = storeBuilder.module<IGlobalState>('GlobalModule', state)
// Getters // Getters
@@ -47,6 +72,10 @@ namespace Getters {
get category() { get category() {
return category() return category()
},
get isOnline() {
return state.stateConnection === 'online'
} }
} }
} }
@@ -65,11 +94,23 @@ namespace Mutations {
state.category = cat state.category = cat
} }
function setStateConnection(state: IGlobalState, stateconn: StateConnection) {
if (state.stateConnection !== stateconn) {
console.log('INTERNET ', stateconn)
state.stateConnection = stateconn
}
}
function SetwasAlreadySubOnDb(state: IGlobalState, subscrib: boolean) {
state.wasAlreadySubOnDb = subscrib
}
export const mutations = { export const mutations = {
setConta: b.commit(setConta), setConta: b.commit(setConta),
setleftDrawerOpen: b.commit(setleftDrawerOpen), setleftDrawerOpen: b.commit(setleftDrawerOpen),
setCategorySel: b.commit(setCategorySel) setCategorySel: b.commit(setCategorySel),
setStateConnection: b.commit(setStateConnection),
SetwasAlreadySubOnDb: b.commit(SetwasAlreadySubOnDb)
} }
} }
@@ -80,27 +121,41 @@ namespace Actions {
} }
function createPushSubscription(context) { function createPushSubscription(context) {
// If Already subscribed, don't send to the Server DB
// if (state.wasAlreadySubOnDb) {
// // console.log('wasAlreadySubOnDb!')
// return
// }
if (!('serviceWorker' in navigator)) { if (!('serviceWorker' in navigator)) {
return return
} }
if (!('PushManager' in window)) {
return
}
console.log('createPushSubscription') console.log('createPushSubscription')
let reg let reg
const mykey = process.env.PUBLICKEY_PUSH const mykey = process.env.PUBLICKEY_PUSH
const mystate = state const mystate = state
navigator.serviceWorker.ready return navigator.serviceWorker.ready
.then(function (swreg) { .then(function (swreg) {
reg = swreg reg = swreg
return swreg.pushManager.getSubscription() return swreg.pushManager.getSubscription()
}) })
.then(function (subscription) { .then(function (subscription) {
mystate.isSubscribed = !(subscription === null) mystate.wasAlreadySubscribed = !(subscription === null)
if (mystate.isSubscribed) { if (mystate.wasAlreadySubscribed) {
console.log('User is already Subscribed!') console.log('User is already SAVED Subscribe on DB!')
// return null
return subscription
} else { } else {
// Create a new subscription // Create a new subscription
console.log('Create a new subscription')
let convertedVapidPublicKey = urlBase64ToUint8Array(mykey) let convertedVapidPublicKey = urlBase64ToUint8Array(mykey)
return reg.pushManager.subscribe({ return reg.pushManager.subscribe({
userVisibleOnly: true, userVisibleOnly: true,
@@ -109,44 +164,66 @@ namespace Actions {
} }
}) })
.then(function (newSub) { .then(function (newSub) {
if (newSub) {
saveNewSubscriptionToServer(context, newSub) saveNewSubscriptionToServer(context, newSub)
mystate.isSubscribed = true;
}
return null
}) })
.catch(function (err) { .catch(function (err) {
console.log(err) console.log('ERR createPushSubscription:', err)
}) })
} }
// Calling the Server to Save in the MongoDB the Subscriber // Calling the Server to Save in the MongoDB the Subscriber
function saveNewSubscriptionToServer(context, newSub) { function saveNewSubscriptionToServer(context, newSub) {
console.log('saveSubscriptionToServer: ', newSub) // If already subscribed, exit
console.log('context', context) if (!newSub)
return
const options = { console.log('saveSubscriptionToServer: ', newSub)
// console.log('context', context)
let options = null
// If is not already stored in DB, then show the message to the user.
if (!state.wasAlreadySubscribed) {
options = {
title: translate('notification.title_subscribed'), title: translate('notification.title_subscribed'),
content: translate('notification.subscribed'), content: translate('notification.subscribed'),
openUrl: '/' openUrl: '/'
} }
}
let myres = { let myres = {
options: { ...options }, options,
subs: newSub, subs: newSub,
others: { others: {
userId: UserStore.state.userId userId: UserStore.state.userId,
} access: UserStore.state.tokens[0].access
},
} }
return fetch(process.env.MONGODB_HOST + '/subscribe', { let call = process.env.MONGODB_HOST + '/subscribe'
method: 'POST',
return Api.SendReq(call, 'POST', myres)
.then(({ res, body }) => {
state.wasAlreadySubscribed = true
state.wasAlreadySubOnDb = true
localStorage.setItem(rescodes.localStorage.wasAlreadySubOnDb, String(state.wasAlreadySubOnDb))
})
.catch(e => {
console.log('Error during Subscription!', e)
})
}
async function deleteSubscriptionToServer(context) {
console.log('DeleteSubscriptionToServer: ')
return await fetch(process.env.MONGODB_HOST + '/subscribe/del', {
method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json' 'Accept': 'application/json',
}, 'x-auth': UserStore.state.x_auth_token
body: JSON.stringify(myres) }
}) })
} }
@@ -174,8 +251,50 @@ namespace Actions {
} }
function loadAfterLogin (context) { async function clearDataAfterLogout(context) {
console.log('clearDataAfterLogout')
// Clear all data from the IndexedDB
await allTables.forEach(table => {
globalroutines(null, 'clearalldata', table, null)
})
if ('serviceWorker' in navigator) {
// REMOVE ALL SUBSCRIPTION
console.log('REMOVE ALL SUBSCRIPTION...')
await navigator.serviceWorker.ready.then(function (reg) {
console.log('... Ready')
reg.pushManager.getSubscription().then(function (subscription) {
console.log(' Found Subscription...')
subscription.unsubscribe().then(function (successful) {
// You've successfully unsubscribed
console.log('You\'ve successfully unsubscribed')
}).catch(function (e) {
// Unsubscription failed
})
})
})
}
await deleteSubscriptionToServer(context)
}
async function clearDataAfterLoginOnlyIfActiveConnection(context) {
// if (Getters.getters.isOnline) {
// console.log('clearDataAfterLoginOnlyIfActiveConnection')
// // Clear all data from the IndexedDB
// allTablesAfterLogin.forEach(table => {
// globalroutines(null, 'clearalldata', table, null)
// })
// }
}
async function loadAfterLogin(context) {
actions.clearDataAfterLoginOnlyIfActiveConnection()
} }
@@ -183,6 +302,8 @@ namespace Actions {
setConta: b.dispatch(setConta), setConta: b.dispatch(setConta),
createPushSubscription: b.dispatch(createPushSubscription), createPushSubscription: b.dispatch(createPushSubscription),
loadAfterLogin: b.dispatch(loadAfterLogin), loadAfterLogin: b.dispatch(loadAfterLogin),
clearDataAfterLogout: b.dispatch(clearDataAfterLogout),
clearDataAfterLoginOnlyIfActiveConnection: b.dispatch(clearDataAfterLoginOnlyIfActiveConnection),
prova: b.dispatch(prova) prova: b.dispatch(prova)
} }
@@ -202,4 +323,3 @@ const GlobalModule = {
export default GlobalModule export default GlobalModule

View File

@@ -5,7 +5,8 @@ import Api from '@api'
import { rescodes } from './rescodes' import { rescodes } from './rescodes'
import { GlobalStore, Todos, UserStore } from '@store' import { GlobalStore, Todos, UserStore } from '@store'
import globalroutines from './../../globalroutines/index' import globalroutines from './../../globalroutines/index'
import { Mutation } from "vuex-module-decorators" import { Mutation } from 'vuex-module-decorators'
import { serv_constants } from '@src/store/Modules/serv_constants'
const state: ITodosState = { const state: ITodosState = {
@@ -13,7 +14,7 @@ const state: ITodosState = {
networkDataReceived: false, networkDataReceived: false,
todos: [], todos: [],
todos_changed: 1, todos_changed: 1,
reload_fromServer: false, reload_fromServer: 0,
testpao: 'Test', testpao: 'Test',
insidePending: false insidePending: false
} }
@@ -42,7 +43,7 @@ namespace Mutations {
function setTodos_changed(state: ITodosState) { function setTodos_changed(state: ITodosState) {
state.todos_changed++ state.todos_changed++
mutations.setTestpao('Cambiato : ' + String(state.todos_changed)) mutations.setTestpao('Cambiato : ' + String(state.todos_changed))
console.log('******************************* state.todos_changed', state.todos_changed) // console.log('******* state.todos_changed', state.todos_changed)
} }
export const mutations = { export const mutations = {
@@ -77,27 +78,27 @@ namespace Actions {
let count = await checkPendingMsg(null) let count = await checkPendingMsg(null)
if (count > 0) { if (count > 0) {
return navigator.serviceWorker.ready return await navigator.serviceWorker.ready
.then(function (sw) { .then(function (sw) {
globalroutines(null, 'readall', 'swmsg') return globalroutines(null, 'readall', 'swmsg')
.then(function (arr_recmsg) { .then(function (arr_recmsg) {
// let recclone = [...arr_recmsg] // let recclone = [...arr_recmsg]
if (arr_recmsg.length > 0) { if (arr_recmsg.length > 0) {
console.log(' TROVATI MSG PENDENTI ! ORA LI MANDO: ', arr_recmsg) // console.log(' TROVATI MSG PENDENTI ! ORA LI MANDO: ', arr_recmsg)
// console.log('---------------------- 2) navigator (2) .serviceWorker.ready') // console.log('---------------------- 2) navigator (2) .serviceWorker.ready')
something = true something = true
for (let rec of arr_recmsg) { for (let rec of arr_recmsg) {
console.log(' .... sw.sync.register ( ', rec._id) // console.log(' .... sw.sync.register ( ', rec._id)
if ('SyncManager' in window) { // if ('SyncManager' in window) {
sw.sync.register(rec._id) // sw.sync.register(rec._id)
} else { // } else {
// #Todo ++ Alternative to SyncManager // #Todo ++ Alternative to SyncManager
Api.syncAlternative(rec._id) Api.syncAlternative(rec._id)
} // }
} }
return something return something
} }
@@ -114,17 +115,15 @@ namespace Actions {
await aspettansec(1000) await aspettansec(1000)
// console.log('waitAndcheckPendingMsg')
return await checkPendingMsg(context) return await checkPendingMsg(context)
.then(ris => { .then(ris => {
if (ris) { if (ris) {
console.log('ris = ', ris) console.log('risPending = ', ris)
const result = sendSwMsgIfAvailable() return sendSwMsgIfAvailable()
.then(something => { .then(something => {
if (something) { if (something) {
// Refresh data // Refresh data
waitAndRefreshData(context) return waitAndRefreshData(context)
} }
}) })
} }
@@ -135,14 +134,30 @@ namespace Actions {
async function waitAndRefreshData(context) { async function waitAndRefreshData(context) {
await aspettansec(3000) await aspettansec(3000)
console.log('waitAndRefreshData')
return await dbLoadTodo(context, false) return await dbLoadTodo(context, false)
} }
async function checkPendingMsg(context) { async function checkPendingMsg(context) {
// console.log('checkPendingMsg') // console.log('checkPendingMsg')
const config = await globalroutines(null, 'readall', 'config', null)
// 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) { return new Promise(function (resolve, reject) {
/* /*
@@ -172,47 +187,56 @@ namespace Actions {
async function dbLoadTodo(context, checkPending: boolean = false) { async function dbLoadTodo(context, checkPending: boolean = false) {
console.log('dbLoadTodo', checkPending) console.log('dbLoadTodo', checkPending)
const token = UserStore.state.idToken if (UserStore.state.userId === '')
return false // Login not made
let call = process.env.MONGODB_HOST + '/todos/' + UserStore.state.userId let call = process.env.MONGODB_HOST + '/todos/' + UserStore.state.userId
state.networkDataReceived = false state.networkDataReceived = false
let ris = await Api.SendReq(call, UserStore.state.lang, token, 'GET', null) let ris = await Api.SendReq(call, 'GET', null)
.then(({ resData, body }) => { .then(({ res, body, status }) => {
state.networkDataReceived = true state.networkDataReceived = true
// console.log('******* UPDATE TODOS.STATE.TODOS !:', resData.todos) // console.log('******* UPDATE TODOS.STATE.TODOS !:', res.todos)
if (body.todos) {
state.todos = [...body.todos] state.todos = [...body.todos]
Todos.mutations.setTodos_changed() // Todos.mutations.setTodos_changed()
}
console.log('state.todos', state.todos, 'checkPending', checkPending) console.log('********** res', 'state.todos', state.todos, 'checkPending', checkPending)
// After Login will store into the indexedDb... // After Login will store into the indexedDb...
return rescodes.OK return { status }
}) })
.catch((error) => { .catch(error => {
console.log('error=', error)
UserStore.mutations.setErrorCatch(error) UserStore.mutations.setErrorCatch(error)
return UserStore.getters.getServerCode return { status }
}) })
console.log('fine della funz...') // console.log('ris : ', ris)
// console.log('ris STATUS: ', ris.status)
if (!Todos.state.networkDataReceived) { if (!Todos.state.networkDataReceived) {
console.log('NETWORK UNREACHABLE ! (Error in fetch)')
consolelogpao('NETWORK UNREACHABLE ! (Error in fetch)') 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)
}
// Read all data from IndexedDB Store into Memory // Read all data from IndexedDB Store into Memory
await updateArrayInMemory(context) await updateArrayInMemory(context)
} else { } else {
if (ris === rescodes.OK && checkPending) { if (ris.status === rescodes.OK && checkPending) {
waitAndcheckPendingMsg(context) waitAndcheckPendingMsg(context)
} }
} }
} }
async function updateArrayInMemory(context) { async function updateArrayInMemory(context) {
console.log('Update the array in memory, from todos table from IndexedDb') // console.log('Update the array in memory, from todos table from IndexedDb')
await globalroutines(null, 'updateinMemory', 'todos', null) await globalroutines(null, 'updateinMemory', 'todos', null)
.then(() => { .then(() => {
// console.log('updateArrayInMemory! ') // console.log('updateArrayInMemory! ')
@@ -246,8 +270,8 @@ namespace Actions {
} }
function UpdateNewIdFromDB(oldItem, newItem, method) { function UpdateNewIdFromDB(oldItem, newItem, method) {
console.log('PRIMA state.todos', state.todos) // console.log('PRIMA state.todos', state.todos)
console.log('ITEM', newItem) // console.log('ITEM', newItem)
if (method === 'POST') { if (method === 'POST') {
state.todos.push(newItem) state.todos.push(newItem)
Todos.mutations.setTodos_changed() Todos.mutations.setTodos_changed()
@@ -260,19 +284,22 @@ namespace Actions {
} }
console.log('DOPO state.todos', state.todos) // console.log('DOPO state.todos', state.todos)
} }
async function dbInsertSaveTodo(context, itemtodo: ITodo, method) { async function dbInsertSaveTodo(context, itemtodo: ITodo, method) {
console.log('dbInsertSaveTodo', itemtodo, method) console.log('dbInsertSaveTodo', itemtodo, method)
let call = process.env.MONGODB_HOST + '/todos' let call = process.env.MONGODB_HOST + '/todos'
if (UserStore.state.userId === '')
return false // Login not made
if (method !== 'POST') if (method !== 'POST')
call += '/' + itemtodo._id call += '/' + itemtodo._id
const token = UserStore.state.idToken console.log('TODO TO SAVE: ', itemtodo)
let res = await Api.SendReq(call, UserStore.state.lang, token, method, itemtodo) let res = await Api.SendReq(call, method, itemtodo)
.then(({ res, newItem }) => { .then(({ res, newItem }) => {
console.log('dbInsertSaveTodo RIS =', newItem) console.log('dbInsertSaveTodo RIS =', newItem)
if (newItem) { if (newItem) {
@@ -290,12 +317,13 @@ namespace Actions {
} }
async function dbDeleteTodo(context, item: ITodo) { async function dbDeleteTodo(context, item: ITodo) {
console.log('dbDeleteTodo', item) // console.log('dbDeleteTodo', item)
let call = process.env.MONGODB_HOST + '/todos/' + item._id let call = process.env.MONGODB_HOST + '/todos/' + item._id
const token = UserStore.state.idToken if (UserStore.state.userId === '')
return false // Login not made
let res = await Api.SendReq(call, UserStore.state.lang, token, 'DELETE', item) let res = await Api.SendReq(call, 'DELETE', item)
.then(function ({ res, itemris }) { .then(function ({ res, itemris }) {
if (res.status === 200) { if (res.status === 200) {

View File

@@ -1,6 +1,6 @@
import Api from '@api' import Api from '@api'
import { ISignupOptions, ISigninOptions, IUserState } from 'model' import { ISignupOptions, ISigninOptions, IUserState } from 'model'
import { ILinkReg, IResult, IIdToken } from 'model/other' import { ILinkReg, IResult, IIdToken, IToken } from 'model/other'
import { storeBuilder } from './Store/Store' import { storeBuilder } from './Store/Store'
import router from '@router' import router from '@router'
@@ -22,7 +22,6 @@ const state: IUserState = {
password: '', password: '',
lang: '', lang: '',
repeatPassword: '', repeatPassword: '',
idToken: '',
tokens: [], tokens: [],
verified_email: false, verified_email: false,
categorySel: 'personal', categorySel: 'personal',
@@ -44,17 +43,17 @@ namespace Getters {
} }
}, 'lang') }, 'lang')
const tok = b.read(state => { // const tok = b.read(state => {
if (state.tokens) { // if (state.tokens) {
if (typeof state.tokens[0] !== 'undefined') { // if (typeof state.tokens[0] !== 'undefined') {
return state.tokens[0].token // return state.tokens[0].token
} else { // } else {
return '' // return ''
} // }
} else { // } else {
return '' // return ''
} // }
}, 'tok') // }, 'tok')
const isServerError = b.read(state => { const isServerError = b.read(state => {
return (state.servercode === rescodes.ERR_SERVERFETCH) return (state.servercode === rescodes.ERR_SERVERFETCH)
@@ -68,9 +67,9 @@ namespace Getters {
get lang() { get lang() {
return lang() return lang()
}, },
get tok() { // get tok() {
return tok() // return tok()
}, // },
get isServerError() { get isServerError() {
return isServerError() return isServerError()
}, },
@@ -87,13 +86,11 @@ namespace Mutations {
function authUser(state, data: IUserState) { function authUser(state, data: IUserState) {
state.userId = data.userId state.userId = data.userId
state.username = data.username state.username = data.username
state.idToken = data.idToken
state.verified_email = data.verified_email state.verified_email = data.verified_email
state.category = data.categorySel state.category = data.categorySel
// @ts-ignore resetArrToken(state.tokens)
state.tokens = [ state.tokens.push({ access: 'auth', token: state.x_auth_token, date_login: new Date() })
{ access: 'auth', token: data.idToken } // console.log('state.tokens', state.tokens)
]
} }
function setpassword(state: IUserState, newstr: string) { function setpassword(state: IUserState, newstr: string) {
@@ -110,26 +107,43 @@ namespace Mutations {
} }
function UpdatePwd(state: IUserState, data: IIdToken) { function UpdatePwd(state: IUserState, data: IIdToken) {
state.idToken = data.idToken state.x_auth_token = data.x_auth_token
if (!state.tokens) { if (!state.tokens) {
state.tokens = [] state.tokens = []
} }
state.tokens.push({ access: 'auth', token: data.idToken }) state.tokens.push({ access: 'auth', token: data.x_auth_token, data_login: new Date() })
} }
function setServerCode(state: IUserState, num: number) { function setServerCode(state: IUserState, num: number) {
state.servercode = num state.servercode = num
} }
function setResStatus(state: IUserState, status: number) {
state.resStatus = status
}
function setAuth(state: IUserState, x_auth_token: string) { function setAuth(state: IUserState, x_auth_token: string) {
state.x_auth_token = x_auth_token state.x_auth_token = x_auth_token
} }
function resetArrToken(arrtokens) {
if (!arrtokens.tokens) {
arrtokens.tokens = []
}
// Take only the others access (from others Browser)
return arrtokens.filter((token: IToken) => {
return token.access !== 'auth'
})
}
function clearAuthData(state: IUserState) { function clearAuthData(state: IUserState) {
state.userId = '' state.userId = ''
state.username = '' state.username = ''
state.tokens = [] resetArrToken(state.tokens)
state.idToken = '' state.x_auth_token = ''
state.verified_email = false state.verified_email = false
state.categorySel = 'personal' state.categorySel = 'personal'
} }
@@ -139,6 +153,7 @@ namespace Mutations {
if (state.servercode !== rescodes.ERR_SERVERFETCH) { if (state.servercode !== rescodes.ERR_SERVERFETCH) {
state.servercode = err state.servercode = err
} }
console.log('Err catch: (servercode:', err, ')')
} }
function getMsgError(state: IUserState, err: number) { function getMsgError(state: IUserState, err: number) {
@@ -168,6 +183,7 @@ namespace Mutations {
setlang: b.commit(setlang), setlang: b.commit(setlang),
UpdatePwd: b.commit(UpdatePwd), UpdatePwd: b.commit(UpdatePwd),
setServerCode: b.commit(setServerCode), setServerCode: b.commit(setServerCode),
setResStatus: b.commit(setResStatus),
setAuth: b.commit(setAuth), setAuth: b.commit(setAuth),
clearAuthData: b.commit(clearAuthData), clearAuthData: b.commit(clearAuthData),
setErrorCatch: b.commit(setErrorCatch), setErrorCatch: b.commit(setErrorCatch),
@@ -205,13 +221,13 @@ namespace Actions {
Mutations.mutations.setServerCode(rescodes.CALLING) Mutations.mutations.setServerCode(rescodes.CALLING)
return await Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) return await Api.SendReq(call, 'POST', usertosend, true)
.then(({ res, body }) => { .then(({ res, body }) => {
return { code: body.code, msg: body.msg } return { code: body.code, msg: body.msg }
}) })
.catch((error) => { .catch((error) => {
UserStore.mutations.setErrorCatch(error) UserStore.mutations.setErrorCatch(error)
return UserStore.getters.getServerCode return { code: UserStore.getters.getServerCode, msg: error }
}) })
} }
@@ -230,7 +246,7 @@ namespace Actions {
Mutations.mutations.setServerCode(rescodes.CALLING) Mutations.mutations.setServerCode(rescodes.CALLING)
return await Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) return await Api.SendReq(call, 'POST', usertosend)
.then(({ res, body }) => { .then(({ res, body }) => {
return { code: body.code, msg: body.msg } return { code: body.code, msg: body.msg }
}).catch((error) => { }).catch((error) => {
@@ -253,13 +269,13 @@ namespace Actions {
Mutations.mutations.setServerCode(rescodes.CALLING) Mutations.mutations.setServerCode(rescodes.CALLING)
return await Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) return await Api.SendReq(call, 'POST', usertosend)
.then(({ res, body }) => { .then(({ res, body }) => {
// console.log("RITORNO 2 "); // console.log("RITORNO 2 ");
// mutations.setServerCode(myres); // mutations.setServerCode(myres);
if (body.code === serv_constants.RIS_CODE_EMAIL_VERIFIED) { if (body.code === serv_constants.RIS_CODE_EMAIL_VERIFIED) {
console.log('VERIFICATO !!') console.log('VERIFICATO !!')
localStorage.setItem(rescodes.localStorage.verifiedEmail, '1') localStorage.setItem(rescodes.localStorage.verified_email, String(true))
} else { } else {
console.log('Risultato di vreg: ', body.code) console.log('Risultato di vreg: ', body.code)
} }
@@ -296,16 +312,18 @@ namespace Actions {
Mutations.mutations.setServerCode(rescodes.CALLING) Mutations.mutations.setServerCode(rescodes.CALLING)
let x_auth_token: string = '' return Api.SendReq(call, 'POST', usertosend)
.then(({ res, body }) => {
return Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend)
.then(({ res, newuser }) => {
myres = res myres = res
const newuser = body
console.log('newuser', newuser)
Mutations.mutations.setServerCode(myres.status) Mutations.mutations.setServerCode(myres.status)
if (myres.status === 200) { if (myres.status === 200) {
let userId = newuser.userId let userId = newuser._id
let username = authData.username let username = authData.username
if (process.env.DEV) { if (process.env.DEV) {
console.log('USERNAME = ' + username) console.log('USERNAME = ' + username)
@@ -313,9 +331,8 @@ namespace Actions {
} }
Mutations.mutations.authUser({ Mutations.mutations.authUser({
userId: userId, userId,
username: username, username,
idToken: x_auth_token,
verified_email: false verified_email: false
}) })
@@ -324,9 +341,9 @@ namespace Actions {
const expirationDate = new Date(now.getTime() * 1000) const expirationDate = new Date(now.getTime() * 1000)
localStorage.setItem(rescodes.localStorage.userId, userId) localStorage.setItem(rescodes.localStorage.userId, userId)
localStorage.setItem(rescodes.localStorage.username, username) localStorage.setItem(rescodes.localStorage.username, username)
localStorage.setItem(rescodes.localStorage.token, x_auth_token) localStorage.setItem(rescodes.localStorage.token, state.x_auth_token)
localStorage.setItem(rescodes.localStorage.expirationDate, expirationDate.toString()) localStorage.setItem(rescodes.localStorage.expirationDate, expirationDate.toString())
localStorage.setItem(rescodes.localStorage.verifiedEmail, '0') localStorage.setItem(rescodes.localStorage.verified_email, String(false))
state.isLogged = true state.isLogged = true
// dispatch('storeUser', authData); // dispatch('storeUser', authData);
// dispatch('setLogoutTimer', myres.data.expiresIn); // dispatch('setLogoutTimer', myres.data.expiresIn);
@@ -349,46 +366,90 @@ namespace Actions {
console.log('MYLANG = ' + state.lang) console.log('MYLANG = ' + state.lang)
let sub = null
if ('serviceWorker' in navigator) {
sub = await navigator.serviceWorker.ready
.then(function (swreg) {
const sub = swreg.pushManager.getSubscription()
return sub
})
.catch(e => {
sub = null
})
}
const options = {
title: translate('notification.title_subscribed'),
content: translate('notification.subscribed'),
openUrl: '/'
}
const usertosend = { const usertosend = {
username: authData.username, username: authData.username,
password: authData.password, password: authData.password,
idapp: process.env.APP_ID, idapp: process.env.APP_ID,
keyappid: process.env.PAO_APP_ID, keyappid: process.env.PAO_APP_ID,
lang: state.lang lang: state.lang,
subs: sub,
options
} }
console.log(usertosend) console.log(usertosend)
let myres: IResult
Mutations.mutations.setServerCode(rescodes.CALLING) Mutations.mutations.setServerCode(rescodes.CALLING)
return await Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) let myres: IResult
return Api.SendReq(call, 'POST', usertosend, true)
.then(({ res, body }) => { .then(({ res, body }) => {
myres = res myres = res
if (res.code === serv_constants.RIS_CODE_LOGIN_ERR) {
if (body.code === serv_constants.RIS_CODE_LOGIN_ERR) {
Mutations.mutations.setServerCode(body.code) Mutations.mutations.setServerCode(body.code)
return body.code return { myres, body }
} }
Mutations.mutations.setServerCode(myres.status) Mutations.mutations.setServerCode(myres.status)
if (myres.status !== 200) {
return Promise.reject(rescodes.ERR_GENERICO)
}
return { myres, body }
}).then(({ myres, body }) => {
if (myres.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
if (process.env.DEV) {
console.log('CODE = ' + body.code)
}
return body.code
} else if (myres.status !== 200) {
if (process.env.DEV) {
console.log('CODE = ' + body.code)
}
return body.code
}
if (myres.status === 200) { if (myres.status === 200) {
GlobalStore.mutations.SetwasAlreadySubOnDb(body.subsExistonDb)
let myuser: IUserState = body.usertosend let myuser: IUserState = body.usertosend
if (myuser) {
let userId = myuser.userId let userId = myuser.userId
let username = authData.username let username = authData.username
let verifiedEmail = myuser.verified_email === true let verified_email = myuser.verified_email
if (process.env.DEV) { if (process.env.DEV) {
console.log('USERNAME = ' + username) console.log('USERNAME = ' + username, 'IDUSER= ' + userId)
console.log('IDUSER= ' + userId) // console.log('state.x_auth_token= ' + state.x_auth_token)
Mutations.mutations.authUser({
userId: userId,
username: username,
idToken: state.x_auth_token,
verified_email: verifiedEmail
})
} }
Mutations.mutations.authUser({
userId,
username,
verified_email
})
const now = new Date() const now = new Date()
// const expirationDate = new Date(now.getTime() + myres.data.expiresIn * 1000); // const expirationDate = new Date(now.getTime() + myres.data.expiresIn * 1000);
const expirationDate = new Date(now.getTime() * 1000) const expirationDate = new Date(now.getTime() * 1000)
@@ -397,23 +458,22 @@ namespace Actions {
localStorage.setItem(rescodes.localStorage.token, state.x_auth_token) localStorage.setItem(rescodes.localStorage.token, state.x_auth_token)
localStorage.setItem(rescodes.localStorage.expirationDate, expirationDate.toString()) localStorage.setItem(rescodes.localStorage.expirationDate, expirationDate.toString())
localStorage.setItem(rescodes.localStorage.isLogged, String(true)) localStorage.setItem(rescodes.localStorage.isLogged, String(true))
localStorage.setItem(rescodes.localStorage.verifiedEmail, Number(verifiedEmail).toString()) localStorage.setItem(rescodes.localStorage.verified_email, String(verified_email))
localStorage.setItem(rescodes.localStorage.wasAlreadySubOnDb, String(GlobalStore.state.wasAlreadySubOnDb))
setGlobal() }
}
// dispatch('storeUser', authData);
// dispatch('setLogoutTimer', myres.data.expiresIn);
return rescodes.OK return rescodes.OK
} else if (myres.status === 404) {
if (process.env.DEV) { }).then(code => {
console.log('CODE = ' + body.code) if (code === rescodes.OK) {
} return setGlobal(true)
return body.code .then(() => {
return code
})
} else { } else {
if (process.env.DEV) { return code
console.log('CODE = ' + body.code)
}
return body.code
} }
}) })
.catch((error) => { .catch((error) => {
@@ -423,6 +483,20 @@ namespace Actions {
} }
async function logout(context) { async function logout(context) {
console.log('logout')
localStorage.removeItem(rescodes.localStorage.expirationDate)
localStorage.removeItem(rescodes.localStorage.token)
localStorage.removeItem(rescodes.localStorage.userId)
localStorage.removeItem(rescodes.localStorage.username)
localStorage.removeItem(rescodes.localStorage.isLogged)
// localStorage.removeItem(rescodes.localStorage.leftDrawerOpen)
localStorage.removeItem(rescodes.localStorage.verified_email)
localStorage.removeItem(rescodes.localStorage.categorySel)
localStorage.removeItem(rescodes.localStorage.wasAlreadySubOnDb)
await GlobalStore.actions.clearDataAfterLogout()
let call = process.env.MONGODB_HOST + '/users/me/token' let call = process.env.MONGODB_HOST + '/users/me/token'
console.log('CALL ' + call) console.log('CALL ' + call)
@@ -433,7 +507,7 @@ namespace Actions {
} }
console.log(usertosend) console.log(usertosend)
return await Api.SendReq(call, state.lang, Getters.getters.tok, 'DELETE', usertosend) const riscall = await Api.SendReq(call, 'DELETE', usertosend)
.then(({ res, body }) => { .then(({ res, body }) => {
console.log(res) console.log(res)
}).then(() => { }).then(() => {
@@ -443,37 +517,31 @@ namespace Actions {
return UserStore.getters.getServerCode return UserStore.getters.getServerCode
}) })
localStorage.removeItem(rescodes.localStorage.expirationDate) return riscall
localStorage.removeItem(rescodes.localStorage.token)
localStorage.removeItem(rescodes.localStorage.userId)
localStorage.removeItem(rescodes.localStorage.username)
localStorage.removeItem(rescodes.localStorage.isLogged)
// localStorage.removeItem(rescodes.localStorage.leftDrawerOpen)
localStorage.removeItem(rescodes.localStorage.verifiedEmail)
localStorage.removeItem(rescodes.localStorage.categorySel)
router.push('/signin') // this.$router.push('/signin')
} }
function setGlobal() { async function setGlobal(loggedWithNetwork: boolean) {
state.isLogged = true state.isLogged = true
GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(rescodes.localStorage.leftDrawerOpen) === 'true') GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(rescodes.localStorage.leftDrawerOpen) === 'true')
GlobalStore.mutations.setCategorySel(localStorage.getItem(rescodes.localStorage.categorySel)) GlobalStore.mutations.setCategorySel(localStorage.getItem(rescodes.localStorage.categorySel))
GlobalStore.actions.loadAfterLogin()
await GlobalStore.actions.loadAfterLogin()
.then(() => {
Todos.actions.dbLoadTodo(true) Todos.actions.dbLoadTodo(true)
})
} }
async function autologin(context) { async function autologin_FromLocalStorage(context) {
try { try {
console.log('*** Autologin ***') // console.log('*** autologin_FromLocalStorage ***')
// INIT // INIT
UserStore.mutations.setlang(process.env.LANG_DEFAULT) UserStore.mutations.setlang(process.env.LANG_DEFAULT)
// ++Todo: Estrai la Lang dal Localstorage // Estrai la Lang dal Localstorage
const lang = localStorage.getItem('lang') const lang = localStorage.getItem('lang')
if (lang) { if (lang) {
UserStore.mutations.setlang(lang) UserStore.mutations.setlang(lang)
@@ -492,18 +560,21 @@ namespace Actions {
} }
const userId = String(localStorage.getItem(rescodes.localStorage.userId)) const userId = String(localStorage.getItem(rescodes.localStorage.userId))
const username = String(localStorage.getItem(rescodes.localStorage.username)) const username = String(localStorage.getItem(rescodes.localStorage.username))
const verifiedEmail = localStorage.getItem(rescodes.localStorage.verifiedEmail) === '1' const verified_email = localStorage.getItem(rescodes.localStorage.verified_email) === 'true'
console.log('autologin userId', userId) GlobalStore.state.wasAlreadySubOnDb = localStorage.getItem(rescodes.localStorage.wasAlreadySubOnDb) === 'true'
console.log('************* autologin userId', userId)
UserStore.mutations.setAuth(token)
Mutations.mutations.authUser({ Mutations.mutations.authUser({
userId: userId, userId: userId,
username: username, username: username,
idToken: token, verified_email: verified_email,
verified_email: verifiedEmail
}) })
setGlobal() await setGlobal(false)
console.log('autologin userId STATE ', state.userId) console.log('autologin userId STATE ', state.userId)
@@ -522,7 +593,7 @@ namespace Actions {
signup: b.dispatch(signup), signup: b.dispatch(signup),
signin: b.dispatch(signin), signin: b.dispatch(signin),
logout: b.dispatch(logout), logout: b.dispatch(logout),
autologin: b.dispatch(autologin) autologin_FromLocalStorage: b.dispatch(autologin_FromLocalStorage)
} }
} }

View File

@@ -12,7 +12,8 @@ export const rescodes = {
LIST_START: '0', LIST_START: '0',
localStorage: { localStorage: {
verifiedEmail: 'vf', verified_email: 'vf',
wasAlreadySubOnDb: 'sb',
categorySel: 'cs', categorySel: 'cs',
isLogged: 'ilog', isLogged: 'ilog',
expirationDate: 'expdate', expirationDate: 'expdate',

View File

@@ -6,10 +6,11 @@ export const serv_constants = {
RIS_CODE_EMAIL_VERIFIED: 1, RIS_CODE_EMAIL_VERIFIED: 1,
RIS_CODE_LOGIN_ERR_GENERIC: -20, RIS_CODE_LOGIN_ERR_GENERIC: -20,
RIS_CODE_LOGIN_ERR: -10, RIS_CODE_LOGIN_ERR: -10,
RIS_CODE_OK: 1, RIS_CODE_OK: 1,
RIS_CODE_LOGIN_OK: 1,
RIS_CODE_LOGIN_OK: 1 RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN: 403
} }

View File

@@ -104,8 +104,8 @@
if (ris.code === serv_constants.RIS_CODE_OK) if (ris.code === serv_constants.RIS_CODE_OK)
this.emailsent = true; this.emailsent = true;
this.$q.loading.hide(); this.$q.loading.hide();
}).catch(error => { }).catch(err => {
console.log("ERROR = " + error); console.log("ERROR = " + err.error);
this.$q.loading.hide(); this.$q.loading.hide();
}); });

View File

@@ -39,6 +39,11 @@ export default class Signin extends Vue {
created() { created() {
this.$v.$reset() this.$v.$reset()
if (UserStore.state.resStatus === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
this.showNotif(this.$t('fetch.error_doppiologin'))
}
// this.$myconfig.socialLogin.facebook = true // this.$myconfig.socialLogin.facebook = true
// console.log('PROVA fb:', this.$myconfig.socialLogin.facebook) // console.log('PROVA fb:', this.$myconfig.socialLogin.facebook)
} }
@@ -75,8 +80,17 @@ export default class Signin extends Vue {
this.showNotif({ type: 'positive', message: this.$t('login.completato') }) this.showNotif({ type: 'positive', message: this.$t('login.completato') })
this.$router.push('/') this.$router.push('/')
} else if (riscode === serv_constants.RIS_CODE_LOGIN_ERR) { } else if (riscode === serv_constants.RIS_CODE_LOGIN_ERR) {
// Wait N seconds to avoid calling many times...
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('anything')
}, 1000)
}).then(() => {
this.showNotif(this.$t('login.errato')) this.showNotif(this.$t('login.errato'))
this.$router.push('/signin') this.$router.push('/signin')
})
} else if (riscode === rescodes.ERR_SERVERFETCH) { } else if (riscode === rescodes.ERR_SERVERFETCH) {
this.showNotif(this.$t('fetch.errore_server')) this.showNotif(this.$t('fetch.errore_server'))
} else if (riscode === rescodes.ERR_GENERICO) { } else if (riscode === rescodes.ERR_GENERICO) {
@@ -122,16 +136,30 @@ export default class Signin extends Vue {
console.log(this.signin) console.log(this.signin)
UserStore.actions.signin(this.signin) UserStore.actions.signin(this.signin)
.then((riscode) => { .then((riscode) => {
console.log('riscode=', riscode) // console.log('riscode=', riscode)
if (riscode === rescodes.OK) { if (riscode === rescodes.OK) {
router.push('/signin') router.push('/signin')
globalroutines(this, 'loadapp', '')
GlobalStore.actions.createPushSubscription()
} }
return riscode
}).then((riscode) => {
globalroutines(this, 'loadapp', '')
return riscode
})
.then((riscode) => {
if (riscode === rescodes.OK) {
GlobalStore.actions.createPushSubscription()
.then(ris => {
})
.catch(e => {
console.log('ERROR = ' + e)
})
.then(() => {
this.checkErrors(riscode) this.checkErrors(riscode)
this.$q.loading.hide() this.$q.loading.hide()
}).catch(error => { })
}
})
.catch(error => {
console.log('ERROR = ' + error) console.log('ERROR = ' + error)
this.checkErrors(error) this.checkErrors(error)

View File

@@ -8,9 +8,7 @@ import { serv_constants } from '../../../store/Modules/serv_constants'
import './vreg.css' import './vreg.css'
import { ILinkReg } from '../../../model/other' import { ILinkReg } from '../../../model/other'
@Component({ @Component({})
})
export default class Vreg extends Vue { export default class Vreg extends Vue {
public risultato: string = '---' public risultato: string = '---'
public riscode: number = 0 public riscode: number = 0
@@ -43,7 +41,8 @@ export default class Vreg extends Vue {
let param: ILinkReg let param: ILinkReg
param = { idlink: this.$route.query.idlink.toString() } param = { idlink: this.$route.query.idlink.toString() }
console.log('idlink = ', param) console.log('idlink = ', param)
UserStore.actions.vreg(param).then((ris) => { return UserStore.actions.vreg(param)
.then((ris) => {
this.riscode = ris.code this.riscode = ris.code
this.risultato = ris.msg this.risultato = ris.msg
console.log('RIS = ') console.log('RIS = ')