diff --git a/src-pwa/custom-service-worker.js b/src-pwa/custom-service-worker.js index 05a14e0..dbac57d 100644 --- a/src-pwa/custom-service-worker.js +++ b/src-pwa/custom-service-worker.js @@ -105,14 +105,15 @@ if (workbox) { function (args) { return fetch(args.event.request, args.event.headers) .then(function (res) { - console.log('******* registerRoute fetch: (1) ', args.event) + // console.log('1° ******* registerRoute fetch: ', args.event) + // LOAD FROM SERVER , AND SAVE INTO INDEXEDDB var clonedRes = res.clone(); clearAllData('todos') .then(function () { return clonedRes.json(); }) .then(function (data) { - console.log('2) data Received ', 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]) } @@ -234,53 +235,65 @@ if ('serviceWorker' in navigator) { // }) self.addEventListener('sync', function (event) { - console.log('[Service Worker V5] Background syncing', event); + console.log('[Service Worker V5] Background syncing', event.tag); - let multiparams = event.tag.split('|') - if (multiparams && multiparams.length > 3) { - let cmd = multiparams[0] - let table = multiparams[1] - let method = multiparams[2] - let token = multiparams[3] - // let lang = multiparams[3] + let mystrparam = event.tag + let multiparams = mystrparam.split('|') + if (multiparams) { + if (multiparams.length > 3) { + let cmd = multiparams[0] + let table = multiparams[1] + let method = multiparams[2] + let token = multiparams[3] + // let lang = multiparams[3] - if ((cmd === 'sync-new-todos') || (cmd === 'sync-delete-todos')) { - console.log('[Service Worker] Syncing', cmd, table, method); + if (cmd === 'sync-todos') { + console.log('[Service Worker] Syncing', cmd, table, method); - const headers = new Headers() - headers.append('content-Type', 'application/json') - headers.append('Accept', 'application/json') - headers.append('x-auth', token) + const headers = new Headers() + headers.append('content-Type', 'application/json') + headers.append('Accept', 'application/json') + headers.append('x-auth', token) - event.waitUntil( - readAllData(table) - .then(function (alldata) { - if (alldata) { - for (var rec of alldata) { - //console.log('syncing', table, '', rec.descr) - let link = cfgenv.serverweb + '/todos/' + rec._id - console.log('syncing', table, 'FETCH: ', method, link, 'data:', rec.descr) + console.log('A1) INIZIO.............................................................'); - // Insert/Delete/Update table to the server - fetch(link, { - method: method, - headers: headers, - mode: 'cors', // 'no-cors', - body: JSON.stringify(rec) - }) - .then(function (resData) { - console.log('Result CALL ', method, ' OK? =', resData.ok); - if (resData.ok) { - deleteItemFromData(table, rec._id); - } + event.waitUntil( + readAllData(table) + .then(function (alldata) { + const myrecs = [...alldata] + console.log('----------------------- LEGGO QUALCOSA DAL WAITUNTIL ') + if (myrecs) { + for (let rec of myrecs) { + //console.log('syncing', table, '', rec.descr) + let link = cfgenv.serverweb + '/todos/' + rec._id + console.log('++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:') + + // Insert/Delete/Update table to the server + fetch(link, { + method: method, + headers: headers, + mode: 'cors', // 'no-cors', + body: JSON.stringify(rec) }) - .catch(function (err) { - console.log('!!!!!!!!!!!!!!! Error while sending data', err); - }); + .then(function (resData) { + console.log('Result CALL ', method, ' OK? =', resData.ok); + if (resData.ok) { + deleteItemFromData(table, rec._id); + } + + console.log('DELETE: ', mystrparam) + deleteItemFromData('swmsg', mystrparam) + + }) + .catch(function (err) { + console.log('!!!!!!!!!!!!!!! Error while sending data', err); + }); + } } - } - }) - ); + }) + ); + console.log('A2) ?????????????????????????? ESCO DAL LOOP !!!!!!!!! err=') + } } } }) diff --git a/src-pwa/register-service-worker.js b/src-pwa/register-service-worker.js index b331a7e..3fa63be 100644 --- a/src-pwa/register-service-worker.js +++ b/src-pwa/register-service-worker.js @@ -3,13 +3,13 @@ * when building for PRODUCTION */ -import {register} from 'register-service-worker' +import { register } from 'register-service-worker' register(process.env.SERVICE_WORKER_FILE, { ready() { console.log('READY::: App is being served from cache by a service worker.') - }, + registered(registration) { // registration -> a ServiceWorkerRegistration instance console.log('REGISTERED::: !!!', process.env.SERVICE_WORKER_FILE) @@ -35,6 +35,4 @@ register(process.env.SERVICE_WORKER_FILE, { // ServiceWorkerRegistration: https://developer.mozilla.org/en-uk/docs/Web/API/ServiceWorkerRegistration - - // "build": "quasar build -m pwa && workbox generateSW workbox-config.js", diff --git a/src/components/todos/todo/todo.ts b/src/components/todos/todo/todo.ts index 7fed4b3..93ef05c 100644 --- a/src/components/todos/todo/todo.ts +++ b/src/components/todos/todo/todo.ts @@ -70,19 +70,35 @@ export default class Todo extends Vue { return Todos.state.todos_changed } + get reload_fromServer() { + return Todos.state.reload_fromServer + } + + @Watch('todos_changed', { immediate: true }) changetodos_changed(value: string, oldValue: string) { - console.log('Todos.state.todos_changed CHANGED!', value, oldValue) + // console.log('Todos.state.todos_changed CHANGED!', value, oldValue) this.updatetable(true) } + @Watch('reload_fromServer', { immediate: true }) + reload_fromServer_changed(value: string, oldValue: string) { + console.log('reload_fromServer_changed!', value, oldValue) + if (value) { + Todos.actions.dbLoadTodo(false) + + Todos.actions.updateArrayInMemory() + } + } + + get testPao() { return Todos.state.testpao } @Watch('testPao', { immediate: true, deep: true }) changedTestpao(value: string, oldValue: string) { - console.log('testpao CHANGED', value, oldValue) + // console.log('testpao CHANGED', value, oldValue) this.updatetable(true) } @@ -372,7 +388,7 @@ export default class Todo extends Vue { const objtodo = this.initcat() - console.log('autologin userId STATE ', UserStore.state.userId) + console.log('insertTodo ', UserStore.state.userId) objtodo.descr = this.todo objtodo.category = this.getCategory() @@ -424,6 +440,11 @@ export default class Todo extends Vue { console.log('cmdToSyncAndDb', cmd, table, method, item.descr, id, msg) + let cmdSw = cmd + if ((cmd === rescodes.DB.CMD_SYNC_NEW_TODOS) || (cmd === rescodes.DB.CMD_DELETE_TODOS)) { + cmdSw = rescodes.DB.CMD_SYNC_TODOS + } + const mythis = this if (('serviceWorker' in navigator && 'SyncManager' in window)) { await navigator.serviceWorker.ready @@ -438,11 +459,18 @@ export default class Todo extends Vue { // console.log('id', id) const sep = '|' - let multiparams = cmd + sep + table + sep + method + sep + UserStore.state.idToken + sep + UserStore.state.lang - return sw.sync.register(multiparams) + let multiparams = cmdSw + sep + table + sep + method + sep + UserStore.state.idToken + sep + UserStore.state.lang + console.log(' SENDING... sw.sync.register', multiparams) + let mymsgkey = { + _id: multiparams, + value: multiparams + } + globalroutines(mythis, 'write', 'swmsg', mymsgkey, multiparams) + .then(ris => { + return sw.sync.register(multiparams) + }) }) .then(function () { - console.log('USCITO dalla sw.sync.register(multiparams) ') let snackbarContainer = document.querySelector('#confirmation-toast') let data = { message: msg } @@ -462,7 +490,7 @@ export default class Todo extends Vue { } } else { - if (cmd === rescodes.DB.CMD_SYNC_TODOS) { + if (cmd === rescodes.DB.CMD_SYNC_NEW_TODOS) { if (method === 'POST') Todos.actions.dbInsertTodo(item) else if (method === 'PATCH') @@ -473,7 +501,7 @@ export default class Todo extends Vue { } async saveItemToSyncAndDb(table: String, method, item: ITodo, update: boolean) { - return await this.cmdToSyncAndDb(rescodes.DB.CMD_SYNC_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, 'Your Post was saved for syncing!', update) } @@ -558,7 +586,7 @@ export default class Todo extends Vue { } async updatetable(refresh: boolean = false) { - console.log('updatetable') + // console.log('updatetable') this.prevRecords = [...this.todos_arr] @@ -749,7 +777,7 @@ export default class Todo extends Vue { globalroutines(this, 'write', 'todos', miorec) .then(ris => { - this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS, 'PATCH', miorec, update) + this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS_PATCH, 'PATCH', miorec, update) .then(() => { // console.log('SET MODIFIED FALSE') @@ -778,4 +806,8 @@ export default class Todo extends Vue { console.log('Todos.state.todos', Todos.state.todos) } + checkUpdate () { + Todos.actions.waitAndcheckPendingMsg() + } + } diff --git a/src/components/todos/todo/todo.vue b/src/components/todos/todo/todo.vue index 2320df1..86b3e5c 100644 --- a/src/components/todos/todo/todo.vue +++ b/src/components/todos/todo/todo.vue @@ -37,13 +37,12 @@ +
- -
- -
+ +
diff --git a/src/globalroutines/indexdb.js b/src/globalroutines/indexdb.js index 4a08125..d4b77a4 100644 --- a/src/globalroutines/indexdb.js +++ b/src/globalroutines/indexdb.js @@ -17,7 +17,7 @@ function saveConfigIndexDb(context) { } function writeConfigIndexDb(context, data) { - console.log('writeConfigIndexDb', data) + // console.log('writeConfigIndexDb', data) storage.setdata('config', data) .then(ris => { @@ -27,15 +27,15 @@ function writeConfigIndexDb(context, data) { } async function readfromIndexDbToStateTodos(context, table) { - console.log('*** read from IndexDb to state.todos') + // console.log('*** read from IndexDb to state.todos') return await storage.getalldata(table) .then(records => { - console.log('&&&&&&& readfromIndexDbToStateTodos OK: Num RECORD: ', records.length) + // console.log('&&&&&&& readfromIndexDbToStateTodos OK: Num RECORD: ', records.length) if (table === 'todos') { Todos.state.todos = [...records] Todos.state.todos_changed++ - console.log('Todos.state.todos_changed:', Todos.state.todos_changed) + // console.log('Todos.state.todos_changed:', Todos.state.todos_changed) // setTimeout(testfunc2, 3000) } }).catch((error) => { @@ -67,6 +67,8 @@ export default async (context, cmd, table, datakey = null, id = '') => { return await readfromIndexDbToStateTodos(context, table) } else if (cmd === 'readall') { return await storage.getalldata(table) + } else if (cmd === 'count') { + return await storage.count(table) } else if (cmd === 'read') { return await storage.getdata(table, id) } else if (cmd === 'delete') { diff --git a/src/js/storage.js b/src/js/storage.js index bd5511e..acdeed1 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -1,10 +1,9 @@ - export let idbKeyval = (() => { let db; function getDB() { if (!db) { - console.log('CREO DB STORAGE JS !') + // console.log('CREO DB STORAGE JS !') db = new Promise((resolve, reject) => { const openreq = indexedDB.open('mydb3', 11); @@ -16,8 +15,10 @@ export let idbKeyval = (() => { // First time setup: create an empty object store openreq.result.createObjectStore('todos', { keyPath: '_id' }); openreq.result.createObjectStore('sync_todos', { keyPath: '_id' }); + openreq.result.createObjectStore('sync_todos_patch', { keyPath: '_id' }); openreq.result.createObjectStore('delete_todos', { keyPath: '_id' }); openreq.result.createObjectStore('config', { keyPath: '_id' }); + openreq.result.createObjectStore('swmsg', { keyPath: '_id' }); }; openreq.onsuccess = () => { @@ -50,7 +51,7 @@ export let idbKeyval = (() => { let req; await withStore('readonly', table, store => { - // console.log('store', store, 'key', key) + console.log('store', store, 'key', key) req = store.get(key); }); // console.log('RISFINALE!', req.result) @@ -63,6 +64,13 @@ export let idbKeyval = (() => { }); return req.result; }, + async count(table) { + let req; + await withStore('readonly', table, store => { + req = store.count(); + }); + return req.result; + }, async set(key, value) { let req; await withStore('readwrite', 'keyval', store => { @@ -72,7 +80,7 @@ export let idbKeyval = (() => { }, async setdata(table, value) { let req; - // console.log('setdata', table, value) + console.log('setdata', table, value) await withStore('readwrite', table, store => { req = store.put(value); diff --git a/src/model/Todos.ts b/src/model/Todos.ts index 414fce5..0243a45 100644 --- a/src/model/Todos.ts +++ b/src/model/Todos.ts @@ -22,5 +22,7 @@ export interface ITodosState { networkDataReceived: boolean todos: ITodo[] todos_changed: number + reload_fromServer: boolean testpao: String + insidePending: boolean } diff --git a/src/statics/js/storage.js b/src/statics/js/storage.js index 4763a9e..c8b2316 100644 --- a/src/statics/js/storage.js +++ b/src/statics/js/storage.js @@ -3,7 +3,7 @@ let idbKeyval = (() => { function getDB() { if (!db) { - console.log('CREO DB STORAGE JS !') + // console.log('CREO DB STORAGE JS !') db = new Promise((resolve, reject) => { const openreq = indexedDB.open('mydb3', 11); @@ -15,8 +15,10 @@ let idbKeyval = (() => { // First time setup: create an empty object store openreq.result.createObjectStore('todos', { keyPath: '_id' }); openreq.result.createObjectStore('sync_todos', { keyPath: '_id' }); + openreq.result.createObjectStore('sync_todos_patch', { keyPath: '_id' }); openreq.result.createObjectStore('delete_todos', { keyPath: '_id' }); openreq.result.createObjectStore('config', { keyPath: '_id' }); + openreq.result.createObjectStore('swmsg', { keyPath: '_id' }); }; openreq.onsuccess = () => { @@ -71,7 +73,7 @@ let idbKeyval = (() => { }, async setdata(table, value) { let req; - console.log('setdata', table, value.descr) + console.log('setdata', table, value) await withStore('readwrite', table, store => { req = store.put(value); diff --git a/src/store/Modules/Todos.ts b/src/store/Modules/Todos.ts index cb9ba43..b103211 100644 --- a/src/store/Modules/Todos.ts +++ b/src/store/Modules/Todos.ts @@ -12,7 +12,9 @@ const state: ITodosState = { networkDataReceived: false, todos: [], todos_changed: 1, - testpao: 'Test' + reload_fromServer: false, + testpao: 'Test', + insidePending: false } const b = storeBuilder.module('TodosModule', state) @@ -63,8 +65,103 @@ namespace Actions { return result } - async function dbLoadTodo(context) { - console.log('dbLoadTodo') + // If something in the call of Service Worker went wrong (Network or Server Down), then retry ! + async function sendSwMsgIfAvailable() { + + console.log(' -------- sendSwMsgIfAvailable') + + let something = false + + let count = await checkPendingMsg(null) + if (count > 0) { + if (('serviceWorker' in navigator && 'SyncManager' in window)) { + return navigator.serviceWorker.ready + .then(function (sw) { + + globalroutines(null, 'readall', 'swmsg') + .then(function (arr_recmsg) { + let recclone = [...arr_recmsg] + if (arr_recmsg.length > 0) { + + console.log(' TROVATI MSG PENDENTI ! ORA LI MANDO: ', arr_recmsg) + + console.log('---------------------- 2) navigator (2) .serviceWorker.ready') + + something = true + for (let rec of arr_recmsg) { + console.log(' .... sw.sync.register ( ', rec._id) + sw.sync.register(rec._id) + } + } + return something + }) + }) + } + } + return something + } + + async function waitAndcheckPendingMsg(context) { + + await aspettansec(1000) + + console.log('waitAndcheckPendingMsg') + + return await checkPendingMsg(context) + .then(ris => { + console.log('ris = ', ris) + if (ris) { + const result = sendSwMsgIfAvailable() + .then(something => { + if (something) { + // Refresh data + waitAndRefreshData(context) + } + }) + } + }) + + } + + async function waitAndRefreshData(context) { + await aspettansec(3000) + + console.log('waitAndRefreshData') + + return await dbLoadTodo(context, false) + } + + async function checkPendingMsg(context) { + console.log('checkPendingMsg') + + return new Promise(function (resolve, reject) { + + /* + globalroutines(null, 'readall', 'swmsg') + .then(function (arr_recmsg) { + if (arr_recmsg.length > 0) { + */ + + // Check if there is something + globalroutines(null, 'count', 'swmsg') + .then(function (count) { + console.log('count = ', count) + if (count > 0) { + return resolve(true) + } else { + return resolve(false) + } + }) + .catch(e => { + return reject() + }) + }) + + + } + + async function dbLoadTodo(context, checkPending: boolean = false) { + console.log('dbLoadTodo', checkPending) const token = UserStore.state.idToken @@ -78,29 +175,36 @@ namespace Actions { }).then((resData) => { state.networkDataReceived = true - console.log('******* UPDATE TODOS.STATE.TODOS !:', resData.todos) + // console.log('******* UPDATE TODOS.STATE.TODOS !:', resData.todos) state.todos = [...resData.todos] + Todos.state.todos_changed++ + + console.log('state.todos', state.todos, 'checkPending', checkPending) // After Login will store into the indexedDb... - console.log('state.todos', state.todos) return rescodes.OK }) .catch((error) => { if (process.env.DEV) { - console.log('dbLoadTodo ERRORE', error) - console.log(error) + // console.log('dbLoadTodo ERRORE', error) } // If error network connection, take the data from IndexedDb return rescodes.ERR_GENERICO }) + console.log('fine della funz...') + if (!Todos.state.networkDataReceived) { console.log('NETWORK UNREACHABLE ! (Error in fetch)') consolelogpao('NETWORK UNREACHABLE ! (Error in fetch)') // Read all data from IndexedDB Store into Memory await updateArrayInMemory(context) + } else { + if (ris === rescodes.OK && checkPending) { + waitAndcheckPendingMsg(context) + } } } @@ -108,7 +212,7 @@ namespace Actions { console.log('Update the array in memory, from todos table from IndexedDb') await globalroutines(null, 'updateinMemory', 'todos', null) .then(() => { - console.log('updateArrayInMemory! ') + // console.log('updateArrayInMemory! ') return true }) } @@ -229,7 +333,9 @@ namespace Actions { dbLoadTodo: b.dispatch(dbLoadTodo), dbDeleteTodo: b.dispatch(dbDeleteTodo), updateArrayInMemory: b.dispatch(updateArrayInMemory), - getTodosByCategory: b.dispatch(getTodosByCategory) + getTodosByCategory: b.dispatch(getTodosByCategory), + checkPendingMsg: b.dispatch(checkPendingMsg), + waitAndcheckPendingMsg: b.dispatch(waitAndcheckPendingMsg) } } diff --git a/src/store/Modules/UserStore.ts b/src/store/Modules/UserStore.ts index 633dec3..b058041 100644 --- a/src/store/Modules/UserStore.ts +++ b/src/store/Modules/UserStore.ts @@ -496,7 +496,7 @@ namespace Actions { GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(rescodes.localStorage.leftDrawerOpen) === 'true') GlobalStore.mutations.setCategorySel(localStorage.getItem(rescodes.localStorage.categorySel)) - Todos.actions.dbLoadTodo() + Todos.actions.dbLoadTodo(true) } diff --git a/src/store/Modules/rescodes.ts b/src/store/Modules/rescodes.ts index 1549108..eacdbd4 100644 --- a/src/store/Modules/rescodes.ts +++ b/src/store/Modules/rescodes.ts @@ -26,9 +26,11 @@ export const rescodes = { }, DB: { - CMD_SYNC_TODOS: 'sync-new-todos', + CMD_SYNC_TODOS: 'sync-todos', + CMD_SYNC_NEW_TODOS: 'sync-new-todos', CMD_DELETE_TODOS: 'sync-delete-todos', TABLE_SYNC_TODOS : 'sync_todos', + TABLE_SYNC_TODOS_PATCH : 'sync_todos_patch', TABLE_DELETE_TODOS : 'delete_todos' },