From 484439efe0ce45649e300b321ac242b51ff8a67d Mon Sep 17 00:00:00 2001 From: Paolo Arena Date: Fri, 1 Feb 2019 04:10:31 +0100 Subject: [PATCH] - Service Worker: Save on IndexDb and Sync to send after to the DB. - Insert record on MongoDb, POST, GET. --- src-pwa/custom-service-worker.js | 130 +++++++++++++- .../categories/category/category.vue | 2 +- src/components/todos/SingleTodo/SingleTodo.ts | 4 +- .../todos/SingleTodo/SingleTodo.vue | 2 +- src/components/todos/todo/todo.ts | 162 +++++++++++------- src/components/todos/todo/todo.vue | 2 +- src/js/utility.js | 91 ++++++++++ src/model/Todos.ts | 5 +- src/plugins/vue-idb.js | 11 +- src/root/home/home.ts | 1 + src/store/Api/Inst-Pao.ts | 23 ++- src/store/Modules/Todos.ts | 138 ++++++++++++++- src/store/Modules/UserStore.ts | 22 ++- src/store/Modules/index.ts | 1 + 14 files changed, 494 insertions(+), 100 deletions(-) create mode 100644 src/js/utility.js diff --git a/src-pwa/custom-service-worker.js b/src-pwa/custom-service-worker.js index be847ef..c3a2d27 100644 --- a/src-pwa/custom-service-worker.js +++ b/src-pwa/custom-service-worker.js @@ -6,15 +6,24 @@ // Questo è il swSrc -console.log('___________________________ PAO: this is my custom service worker'); +console.log('05 ___________________________ 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('js/idb.js'); +importScripts('js/utility.js'); -importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js'); if (!workbox) { - workbox = new self.WorkboxSW(); + let workbox = new self.WorkboxSW(); + } if (workbox) { + // const url = new URL(location.href); + // const debug = url.searchParams.has('debug'); + const debug = false; + workbox.setConfig({ debug: debug }); + workbox.core.setCacheNameDetails({ prefix: "freeplanet" }); /** @@ -28,18 +37,49 @@ if (workbox) { // workbox.routing.registerRoute(/^http/, workbox.strategies.networkFirst(), 'GET'); + workbox.routing.registerRoute( + /\.(?:png|gif|jpg|jpeg|svg)$/, + workbox.strategies.staleWhileRevalidate({ + cacheName: 'images', + plugins: [ + new workbox.expiration.Plugin({ + maxEntries: 60, + maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days + }), + ], + }), + ); + workbox.routing.registerRoute( new RegExp(/.*(?:googleapis|gstatic)\.com.*$/), workbox.strategies.staleWhileRevalidate({ cacheName: 'google-fonts', plugins: [ new workbox.expiration.Plugin({ - maxAgeSeconds: 30 * 24 * 60 * 60, + maxEntries: 30, }), ] }) ); + workbox.routing.registerRoute('http://localhost:3000/todos', function (args) { + return fetch(args.event.request) + .then(function (res) { + var clonedRes = res.clone(); + clearAllData('todos') + .then(function () { + return clonedRes.json(); + }) + .then(function (data) { + for (let key in data) { + writeData('todos', data[key]) + } + }); + return res; + }); + }); + + workbox.routing.registerRoute( new RegExp(/.*\/(?:statics\/icons).*$/), workbox.strategies.cacheFirst({ @@ -118,12 +158,37 @@ if (workbox) { }) ); + // workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug); + + workbox.routing.registerRoute( + new RegExp('http://localhost:8080/todos'), + function (args) { + return fetch(args.event.request) + .then(function (res) { + console.log('******* fetch: ', args.event) + var clonedRes = res.clone(); + clearAllData('todos') + .then(function () { + return clonedRes.json(); + }) + .then(function (data) { + for (let key in data) { + writeData('todos', data[key]) + } + }); + return res + }) + } + ); + } if ('serviceWorker' in navigator) { console.log('***************** Entering in custom-service-worker.js:') +} + // self.addEventListener('fetch', function (event) { // console.log('[Service Worker] Fetching something ....', event); // console.log('event.request.cache=', event.request.cache) @@ -131,8 +196,61 @@ if ('serviceWorker' in navigator) { // console.log('SAME ORIGIN!', event); // return; // } - // event.respondWith(fetch(event.request)); + // event.respondWith(caches.match(event.request)); // }); -} + + self.addEventListener('sync', function (event) { + console.log('[Service Worker] Background syncing', event); + + if (event.tag === 'sync-new-todos') { + console.log('[Service Worker] Syncing new Todos'); + + let authHeader = [] + authHeader['content-type'] = 'application/json'; + authHeader['accept-language'] = 'en'; + // authHeader.append('x-auth', mytok) + + event.waitUntil( + readAllData('sync_todos') + .then(function (data) { + for (var dt of data) { + // var postData = new FormData(); + // postData.append('_id', dt._id); + // postData.append('title', dt.title); + // postData.append('location', dt.location); + // postData.append('rawLocationLat', dt.rawLocation.lat); + // postData.append('rawLocationLng', dt.rawLocation.lng); + // postData.append('file', dt.picture, dt._id + '.png'); + + console.log('Data to Send 6: ', JSON.stringify(dt)) + + // Update myTodo to the server + fetch('http://localhost:3000/todos', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + // mode: 'no-cors', + mode: 'cors', + body: JSON.stringify(dt) + }) + .then(function (resData) { + console.log('Sent data Todo:', resData); + if (resData.ok) { + deleteItemFromData('sync_todos', dt.id); + } + }) + .catch(function (err) { + console.log('Error while sending data', err); + }); + } + + }) + ); + } + }); + +// } diff --git a/src/components/categories/category/category.vue b/src/components/categories/category/category.vue index 1d9eff6..6a9c70c 100644 --- a/src/components/categories/category/category.vue +++ b/src/components/categories/category/category.vue @@ -53,7 +53,7 @@ - + diff --git a/src/components/todos/SingleTodo/SingleTodo.ts b/src/components/todos/SingleTodo/SingleTodo.ts index 895197e..37c2c0f 100644 --- a/src/components/todos/SingleTodo/SingleTodo.ts +++ b/src/components/todos/SingleTodo/SingleTodo.ts @@ -130,7 +130,7 @@ export default class SingleTodo extends Vue { // this.classDescr += ' show' // } - // this.getinputdescr = 'inputdescr' + this.itemtodo.id + // this.getinputdescr = 'inputdescr' + this.itemtodo._id // console.log('classDescrEdit = ', this.classDescrEdit) // console.log('classDescr', this.classDescr) @@ -344,7 +344,7 @@ export default class SingleTodo extends Vue { .then(ris => { console.log('ris', ris) if (ris) - this.removeitem(this.itemtodo.id) + this.removeitem(this.itemtodo._id) }).catch(err => { }) diff --git a/src/components/todos/SingleTodo/SingleTodo.vue b/src/components/todos/SingleTodo/SingleTodo.vue index bbc070f..1c33fb7 100644 --- a/src/components/todos/SingleTodo/SingleTodo.vue +++ b/src/components/todos/SingleTodo/SingleTodo.vue @@ -59,7 +59,7 @@ - + diff --git a/src/components/todos/todo/todo.ts b/src/components/todos/todo/todo.ts index ffcc80d..0de8502 100644 --- a/src/components/todos/todo/todo.ts +++ b/src/components/todos/todo/todo.ts @@ -1,11 +1,12 @@ import Vue from 'vue' -import { Component, Prop, Watch } from 'vue-property-decorator' +import { Component, Watch } from 'vue-property-decorator' import { SingleTodo } from '../SingleTodo' import { ITodo } from '@src/model' import { rescodes } from '../../../store/Modules/rescodes' +import { Todos } from '@store' import { UserStore } from '@store' import _ from 'lodash' @@ -104,13 +105,13 @@ export default class Todo extends Vue { idprev = rescodes.LIST_START } else { const elemprev = this.getelem(index - 1, arr) - idprev = elemprev.id + idprev = elemprev._id } if (index === arr.length - 1) { idnext = rescodes.LIST_END } else { const elemnext = this.getelem(index + 1, arr) - idnext = elemnext.id + idnext = elemnext._id } elem.modified = ((elem.id_prev !== idprev) || (elem.id_next !== idnext) || (elem.pos !== pos)) ? true : elem.modified @@ -129,7 +130,7 @@ export default class Todo extends Vue { } logelem(mystr, elem) { - console.log(mystr, 'elem [', elem.id, '] ', elem.descr, ' Pr(', this.getPriorityByInd(elem.priority), ') [', elem.id_prev, '-', elem.id_next, '] modif=', elem.modified) + console.log(mystr, 'elem [', elem._id, '] ', elem.descr, ' Pr(', this.getPriorityByInd(elem.priority), ') [', elem.id_prev, '-', elem.id_next, '] modif=', elem.modified) } getPriorityToSet(ind1, ind2) { @@ -164,7 +165,7 @@ export default class Todo extends Vue { } - getTitlePriority (priority) { + getTitlePriority(priority) { let cl = '' if (priority === rescodes.Todos.PRIORITY_HIGH) @@ -245,6 +246,8 @@ export default class Todo extends Vue { async load() { + + // Set last category selected localStorage.setItem(rescodes.localStorage.categorySel, this.getCategory()) @@ -257,11 +260,11 @@ export default class Todo extends Vue { await this.updatetable() -/* - this.todos_arr.forEach((elem, index) => { - this.logelem('LOAD ' + index, elem) - }) -*/ + /* + this.todos_arr.forEach((elem, index) => { + this.logelem('LOAD ' + index, elem) + }) + */ } @@ -269,6 +272,8 @@ export default class Todo extends Vue { const mydateexp = new Date().setDate((new Date()).getDate() + 1) + console.log('User:' + UserStore.state.userId) + const objtodo: ITodo = { userId: UserStore.state.userId, descr: '', @@ -276,6 +281,7 @@ export default class Todo extends Vue { completed: false, created_at: new Date(), modify_at: new Date(), + completed_at: null, category: '', expiring_at: mydateexp, enableExpiring: false, @@ -298,16 +304,18 @@ export default class Todo extends Vue { return '' } - async insertTodo() { + insertTodo() { if (this.todo.trim() === '') return const objtodo = this.initcat() + console.log('autologin userId STATE ', UserStore.state.userId) + objtodo.descr = this.todo objtodo.category = this.getCategory() const lastelem = this.getLastList() - objtodo.id_prev = (lastelem !== null) ? lastelem.id : rescodes.LIST_START + objtodo.id_prev = (lastelem !== null) ? lastelem._id : rescodes.LIST_START objtodo.id_next = rescodes.LIST_END objtodo.pos = (lastelem !== null) ? lastelem.pos + 1 : 1 objtodo.modified = true @@ -317,29 +325,69 @@ export default class Todo extends Vue { return } + this.$db.todos.add(objtodo) // Add to Indexdb + .then((id) => { + console.log('*** IDNEW = ', id) - // Add to Indexdb - await this.$db.todos.add(objtodo - ).then((id) => { - console.log('*** IDNEW = ', id) - if (lastelem !== null) { - lastelem.id_next = id - lastelem.modified = true - this.modify(lastelem, false) - } - this.modify(objtodo, true) - }).catch(err => { - console.log('Errore: ' + err.message) - }) + // update also the last elem + if (lastelem !== null) { + lastelem.id_next = id + lastelem.modified = true + this.modify(lastelem, false) + } + + this.saveItemToSyncAndDb(objtodo) + + // this.modify(objtodo, true) + this.updatetable(false) + }).catch(err => { + console.log('Errore: ' + err.message) + }) + + console.log('ESCO.........') // empty the field this.todo = '' } + saveItemToSyncAndDb(item: ITodo) { + // Send to Server to Sync + const mythis = this + console.log('saveItemToSyncAndDb') + if ('serviceWorker' in navigator && 'SyncManager' in window) { + navigator.serviceWorker.ready + .then(function (sw) { + // _id: new Date().toISOString(), + console.log('---------------------- navigator.serviceWorker.ready') + + // check if exist _id, delete it + mythis.$db.sync_todos + .where('id').equals(item._id) + .delete() + + mythis.$db.sync_todos.add(item) + .then(function () { + return sw.sync.register('sync-new-todos') + }) + .then(function () { + let snackbarContainer = document.querySelector('#confirmation-toast') + let data = { message: 'Your Post was saved for syncing!' } + // snackbarContainer.MaterialSnackbar.showSnackbar(data) + }) + .catch(function (err) { + console.log(err) + }) + }) + } else { + Todos.actions.dbSaveTodo(item) + } + + } + getElemById(id, lista = this.todos_arr) { let myobj: ITodo for (myobj of lista) { - if (myobj.id === id) { + if (myobj._id === id) { return myobj } } @@ -436,7 +484,7 @@ export default class Todo extends Vue { current = this.getElemById(current.id_next, arrris) if (current === null) break - if (current.id === currentprec.id) + if (current._id === currentprec._id) break myarr.push(current) currentprec = current @@ -452,45 +500,21 @@ export default class Todo extends Vue { async filtertodos(refresh: boolean = false) { // console.log('filtertodos') - let arrtemp = [] + return await Todos.actions.getTodosByCategory(this.getCategory()) + .then(arrtemp => { - if (this.filter) { - // #Todo If need to filter the output database ... - await this.$db.todos - .where('userId').equals(UserStore.state.userId) - .and(todo => todo.category === this.getCategory()) - .toArray() - .then((response) => { - Promise.all(response.map(key => key)) - .then((ristodos) => { - arrtemp = ristodos - }) - }) - } else { - await this.$db.todos - .where('userId').equals(UserStore.state.userId) - .and(todo => todo.category === this.getCategory()) - .toArray().then(ristodos => { - arrtemp = ristodos - }) + arrtemp = _.orderBy(arrtemp, ['completed', 'priority', 'pos'], ['asc', 'desc', 'asc']) - arrtemp = _.orderBy(arrtemp, ['completed', 'priority', 'pos'], ['asc', 'desc', 'asc']) - } + this.updateLinkedList(true, arrtemp) - this.updateLinkedList(true, arrtemp) + this.todos_arr = [...arrtemp] // make copy + }) - // set array - // arrtemp = this.setArrayFinale(arrtemp) - - this.todos_arr = [...arrtemp] // make copy - - - return [] } sortarr(arr, field) { - return arr.slice().sort(function(a, b) { + return arr.slice().sort(function (a, b) { return a[field] - b[field] }) @@ -522,7 +546,7 @@ export default class Todo extends Vue { // } // - deselectAllRows(item, check, onlythis: boolean = false) { + deselectAllRows(item: ITodo, check, onlythis: boolean = false) { // console.log('deselectAllRows : ', item) for (let i = 0; i < this.$refs.single.length; i++) { @@ -530,13 +554,13 @@ export default class Todo extends Vue { let contr = this.$refs.single[i] // @ts-ignore - let id = contr.itemtodo.id + let id = contr.itemtodo._id // Don't deselect the actual clicked! let des = false if (onlythis) { - des = item.id === id - }else { - des = ((check && (item.id !== id)) || (!check)) + des = item._id === id + } else { + des = ((check && (item._id !== id)) || (!check)) } if (des) { // @ts-ignore @@ -549,7 +573,7 @@ export default class Todo extends Vue { // let index = -1 // // get index // this.$refs.single.forEach( (singletodo: SingleTodo) => { - // if (singletodo.itemtodo.id === rec.id) + // if (singletodo.itemtodo._id === rec._id) // index = -1 // }) // @@ -559,16 +583,20 @@ export default class Todo extends Vue { if (recOut[field] !== recIn[field]) { recOut.modified = true recOut[field] = recIn[field] + return true } + return false } async modify(myobj: ITodo, update: boolean) { await this.$db.transaction('rw', [this.$db.todos], async () => { - const miorec = await this.$db.todos.get(myobj.id) + const miorec = await this.$db.todos.get(myobj._id) this.modifyField(miorec, myobj, 'descr') - this.modifyField(miorec, myobj, 'completed') + if (this.modifyField(miorec, myobj, 'completed')) + miorec.completed_at = new Date() + this.modifyField(miorec, myobj, 'category') this.modifyField(miorec, myobj, 'expiring_at') this.modifyField(miorec, myobj, 'priority') @@ -586,6 +614,8 @@ export default class Todo extends Vue { await this.$db.todos.put(miorec) + this.saveItemToSyncAndDb(miorec) + if (update) await this.updatetable(false) } diff --git a/src/components/todos/todo/todo.vue b/src/components/todos/todo/todo.vue index a01f401..49d9656 100644 --- a/src/components/todos/todo/todo.vue +++ b/src/components/todos/todo/todo.vue @@ -13,7 +13,7 @@ -
+
diff --git a/src/js/utility.js b/src/js/utility.js new file mode 100644 index 0000000..ab782ba --- /dev/null +++ b/src/js/utility.js @@ -0,0 +1,91 @@ +console.log('utility.js') + +var dbPromise = idb.open('mydb', 10, function (db) { + console.log('OPEN MYDB') + if (!db.objectStoreNames.contains('sync_todos')) { + db.createObjectStore('sync_todos', { keyPath: 'id' }); + } + if (!db.objectStoreNames.contains('todos')) { + db.createObjectStore('todos', { keyPath: 'id' }); + } +}); + +function writeData(st, data) { + console.log('writeData', st, data); + return dbPromise + .then(function (db) { + var tx = db.transaction(st, 'readwrite'); + var store = tx.objectStore(st); + store.put(data); + return tx.complete; + }); +} + +function readAllData(st) { + console.log('readAllData', st); + return dbPromise + .then(function (db) { + var tx = db.transaction(st, 'readonly'); + var store = tx.objectStore(st); + return store.getAll(); + }); +} + +function clearAllData(st) { + console.log('clearAllData', st); + return dbPromise + .then(function (db) { + var tx = db.transaction(st, 'readwrite'); + var store = tx.objectStore(st); + store.clear(); + return tx.complete; + }); +} + +function deleteItemFromData(st, id) { + console.log('deleteItemFromData', st, 'ID:', id); + dbPromise + .then(function (db) { + + var tx = db.transaction(st, 'readwrite'); + var store = tx.objectStore(st); + + try { + store.delete(id); + return tx.complete; + } catch (e) { + return false; + } + }) + .then(function (res) { + if (res) + console.log('Item deleted!'); + }); +} + +function urlBase64ToUint8Array(base64String) { + var padding = '='.repeat((4 - base64String.length % 4) % 4); + var base64 = (base64String + padding) + .replace(/\-/g, '+') + .replace(/_/g, '/'); + + var rawData = window.atob(base64); + var outputArray = new Uint8Array(rawData.length); + + for (var i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +} + +function dataURItoBlob(dataURI) { + var byteString = atob(dataURI.split(',')[1]); + var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] + var ab = new ArrayBuffer(byteString.length); + var ia = new Uint8Array(ab); + for (var i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + var blob = new Blob([ab], { type: mimeString }); + return blob; +} diff --git a/src/model/Todos.ts b/src/model/Todos.ts index 825e74d..e89ebc6 100644 --- a/src/model/Todos.ts +++ b/src/model/Todos.ts @@ -1,5 +1,5 @@ export interface ITodo { - id?: number, + _id?: number, userId: string category?: string descr?: string, @@ -7,6 +7,7 @@ export interface ITodo { completed: boolean, created_at: any, modify_at: any, + completed_at: any, expiring_at: any, enableExpiring?: boolean, id_prev?: number, @@ -18,4 +19,6 @@ export interface ITodo { export interface ITodosState { visuOnlyUncompleted: boolean + networkDataReceived: boolean + todos: ITodo[] } diff --git a/src/plugins/vue-idb.js b/src/plugins/vue-idb.js index af71717..192e9df 100644 --- a/src/plugins/vue-idb.js +++ b/src/plugins/vue-idb.js @@ -6,13 +6,16 @@ export default ({ Vue }) => { // Insert here the database for IndexDB new VueIdb({ - database: 'test', + database: 'mydb', + version: 1, schemas: [ - { categories: '++id, sub_categ_id, descr_it, campo2bool, campo3bool' }, - { todos: '++id, userId, category, pos, descr, priority, completed, created_at, modify_at, expiring_at, progress, enableExpiring' } + { categories: '++_id, sub_categ_id, descr_it, campo2bool, campo3bool' }, + { todos: '++_id, userId, category, pos, descr, priority, completed, created_at, modify_at, completed_at, expiring_at, progress, enableExpiring' }, + { sync_todos: '++_id, userId, category, pos, descr, priority, completed, created_at, modify_at, completed_at, expiring_at, progress, enableExpiring' } ], options: { todos: { type: 'list', primary: 'pos', label: 'label', updated_at: 'updated_at' }, + sync_todos: { type: 'list', primary: 'pos', label: 'label', updated_at: 'updated_at' }, } }) } @@ -25,7 +28,7 @@ export default new VueIdb({ version: 1, database: 'test', schemas: [ - { categories: '++id, sub_categ_id, descr_it' } + { categories: '++_id, sub_categ_id, descr_it' } ] }) */ diff --git a/src/root/home/home.ts b/src/root/home/home.ts index df3acf2..9666a70 100644 --- a/src/root/home/home.ts +++ b/src/root/home/home.ts @@ -54,6 +54,7 @@ export default class Home extends Vue { console.log('§§§§§§§§§§§§§§§§§§§§ IMPOSTA DEFERRED PROMPT !!!!!!!!!!!!!!!!! ') return false }) + } test_fetch() { diff --git a/src/store/Api/Inst-Pao.ts b/src/store/Api/Inst-Pao.ts index c155d03..5b7983d 100644 --- a/src/store/Api/Inst-Pao.ts +++ b/src/store/Api/Inst-Pao.ts @@ -5,14 +5,27 @@ async function sendRequest (url: string, lang: string, mytok: string, method: st // let mytok: string = this.getTok() const authHeader = new Headers() + console.log('sendRequest:', url) + authHeader.append('content-type', 'application/json') authHeader.append('x-auth', mytok) authHeader.append('accept-language', lang) - const configInit: RequestInit = { - method: method, - cache: 'no-cache', - body: JSON.stringify(mydata), - headers: authHeader + + let configInit: RequestInit + + if (method === 'GET') { + configInit = { + method: method, + cache: 'no-cache', + headers: authHeader + } + } else { + configInit = { + method: method, + cache: 'no-cache', + body: JSON.stringify(mydata), + headers: authHeader + } } const request: Promise = fetch(url, configInit) diff --git a/src/store/Modules/Todos.ts b/src/store/Modules/Todos.ts index cc4b656..a041576 100644 --- a/src/store/Modules/Todos.ts +++ b/src/store/Modules/Todos.ts @@ -1,12 +1,22 @@ -import { ITodosState } from 'model' +import VueIdb from 'vue-idb' +import { ISigninOptions, ITodo, ITodosState } from 'model' import { storeBuilder } from './Store/Store' +import Api from '@api' +import { serv_constants } from '../Modules/serv_constants' +import { rescodes } from './rescodes' +import { UserStore } from '@store' +import { IResult } from 'model/other' + const state: ITodosState = { - visuOnlyUncompleted: false + visuOnlyUncompleted: false, + networkDataReceived: false, + todos: [] } const b = storeBuilder.module('TodosModule', state) +const stateGetter = b.state() // Getters namespace Getters { @@ -27,8 +37,42 @@ namespace Mutations { // Cancella Item } + async function clearAllData(state: ITodosState) { + // Delete item + + VueIdb.$db.todos + .where('userId').equals(UserStore.state.userId) + .delete() + .then(() => { + console.log('Todo clearAllData !') + + // state + + }).catch((error) => { + console.log('err: ', error) + }) + } + + async function readdbTodoData(state: ITodosState) { + // Delete item + + VueIdb.$db.todos + .where('userId').equals(UserStore.state.userId) + // .and(todo => todo.category === this.getCategory()) + .toArray() + .then(ristodos => { + console.log('readdbTodoData OK !') + state.todos = ristodos + }).catch((error) => { + console.log('err: ', error) + }) + + } + export const mutations = { deleteItem: b.commit(deleteItem), + clearAllData: b.commit(clearAllData), + readdbTodoData: b.commit(readdbTodoData) } } @@ -38,13 +82,95 @@ namespace Actions { Mutations.mutations.deleteItem(num) } + function json2array(json){ + var result = [] + var keys = Object.keys(json); + keys.forEach(function(key){ + result.push(json[key]) + }); + return result; + } + + async function dbLoadTodo(context) { + + console.log('dbLoadTodo') + + const token = localStorage.getItem(rescodes.localStorage.token) + + let call = process.env.MONGODB_HOST + '/todos/' + UserStore.state.userId + + return await Api.SendReq(call, UserStore.state.lang, token, 'GET', null) + .then((res) => { + return res.json() + }).then((resData) => { + // console.log('res.todos:', res.todos) + + state.todos = [] + for(var i in resData.todos) + state.todos.push(resData.todos [i]) + + // state.todos = Object.keys(resData.todos).map((key) => { + // return resData.todos[key] + // }) + + console.log('state.todos', state.todos) + return rescodes.OK + }) + .catch((error) => { + if (process.env.DEV) { + console.log('ERROREEEEEEEEE') + console.log(error) + } + return rescodes.ERR_GENERICO + }) + } + + async function dbSaveTodo(context, itemtodo: ITodo) { + let call = process.env.MONGODB_HOST + '/todos/' + itemtodo._id + + const token = localStorage.getItem(rescodes.localStorage.token) + + let res = await Api.SendReq(call, UserStore.state.lang, token, 'PATCH', itemtodo) + .then(function (res) { + state.networkDataReceived = true + return rescodes.OK + }) + .catch((error) => { + if (process.env.DEV) { + console.log('ERROREEEEEEEEE') + console.log(error) + } + return rescodes.ERR_GENERICO + }) + + + if ('indexedDB' in window) { + await Mutations.mutations.readdbTodoData() + if (!state.networkDataReceived) { + console.log('From cache', state.todos) + } + } + + return res + } + + async function getTodosByCategory(context, category: string) { + let myarr = state.todos.filter((p) => { + return p.category === category + }) + + return myarr + } + export const actions = { - setConta: b.dispatch(deleteItem) + setConta: b.dispatch(deleteItem), + dbSaveTodo: b.dispatch(dbSaveTodo), + dbLoadTodo: b.dispatch(dbLoadTodo), + getTodosByCategory: b.dispatch(getTodosByCategory) } } -const stateGetter = b.state() // Module const TodosModule = { @@ -56,6 +182,4 @@ const TodosModule = { actions: Actions.actions } - -export default ITodosState - +export default TodosModule diff --git a/src/store/Modules/UserStore.ts b/src/store/Modules/UserStore.ts index d728707..78933c6 100644 --- a/src/store/Modules/UserStore.ts +++ b/src/store/Modules/UserStore.ts @@ -6,7 +6,7 @@ import router from '@router' import { serv_constants } from '../Modules/serv_constants' import { rescodes } from '../Modules/rescodes' -import { GlobalStore, UserStore } from '@store' +import { GlobalStore, UserStore, Todos } from '@store' const bcrypt = require('bcryptjs') @@ -156,7 +156,7 @@ namespace Actions { let x_auth_token: string = '' - return Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) + return await Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) .then((res) => { console.log(res) myres = res @@ -197,7 +197,7 @@ namespace Actions { let myres - return Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) + return await Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) .then((res) => { console.log(res) myres = res @@ -381,7 +381,7 @@ namespace Actions { let x_auth_token: string = '' - return Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) + return await Api.SendReq(call, state.lang, Getters.getters.tok, 'POST', usertosend) .then((res) => { myres = res x_auth_token = String(res.headers.get('x-auth')) @@ -433,6 +433,8 @@ namespace Actions { localStorage.setItem(rescodes.localStorage.isLogged, String(true)) localStorage.setItem(rescodes.localStorage.verifiedEmail, Number(verifiedEmail).toString()) + setGlobal() + // dispatch('storeUser', authData); // dispatch('setLogoutTimer', myres.data.expiresIn); return rescodes.OK @@ -469,7 +471,7 @@ namespace Actions { } console.log(usertosend) - Api.SendReq(call, state.lang, Getters.getters.tok, 'DELETE', usertosend) + return await Api.SendReq(call, state.lang, Getters.getters.tok, 'DELETE', usertosend) .then( (res) => { console.log(res) @@ -495,10 +497,13 @@ namespace Actions { function setGlobal() { GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(rescodes.localStorage.leftDrawerOpen) === 'true') GlobalStore.mutations.setCategorySel(localStorage.getItem(rescodes.localStorage.categorySel)) + + Todos.actions.dbLoadTodo() } async function autologin (context) { try { + console.log('*** Autologin ***') // INIT UserStore.mutations.setlang(process.env.LANG_DEFAULT) // ++Todo: Estrai la Lang dal Localstorage @@ -521,7 +526,7 @@ namespace Actions { const username = String(localStorage.getItem(rescodes.localStorage.username)) const verifiedEmail = localStorage.getItem(rescodes.localStorage.verifiedEmail) === '1' - setGlobal() + console.log('autologin userId', userId) Mutations.mutations.authUser({ userId: userId, @@ -529,6 +534,11 @@ namespace Actions { idToken: token, verifiedEmail: verifiedEmail }) + + setGlobal() + + console.log('autologin userId STATE ', state.userId) + return true } catch (e) { console.error('ERR autologin ', e.message) diff --git a/src/store/Modules/index.ts b/src/store/Modules/index.ts index 38b5fa1..f84bfb8 100644 --- a/src/store/Modules/index.ts +++ b/src/store/Modules/index.ts @@ -1,3 +1,4 @@ export {storeBuilder} from './Store/Store' export {default as GlobalStore} from './GlobalStore' export {default as UserStore} from './UserStore' +export {default as Todos} from './Todos'