- Service Worker

- Indexdb
This commit is contained in:
Paolo Arena
2019-02-02 20:13:06 +01:00
parent 484439efe0
commit 3c6b2c7bef
41 changed files with 762 additions and 755 deletions

View File

@@ -1,4 +1,4 @@
SERVICE_WORKER_FILE='service-worker.js' SERVICE_WORKER_FILE='service-worker.js${Math.random()}'
APP_ID='1' APP_ID='1'
VUE_APP_URL='prova SVILUPPO!' VUE_APP_URL='prova SVILUPPO!'
PROVA_PAOLO='PROVA SVILUPPO' PROVA_PAOLO='PROVA SVILUPPO'

14
package-lock.json generated
View File

@@ -11193,6 +11193,11 @@
} }
} }
}, },
"idb-keyval": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-3.1.0.tgz",
"integrity": "sha512-iFwFN5n00KNNnVxlOOK280SJJfXWY7pbMUOQXdIXehvvc/mGCV/6T2Ae+Pk2KwAkkATDTwfMavOiDH5lrJKWXQ=="
},
"ieee754": { "ieee754": {
"version": "1.1.12", "version": "1.1.12",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
@@ -11216,6 +11221,15 @@
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
}, },
"immortal-db": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/immortal-db/-/immortal-db-1.0.2.tgz",
"integrity": "sha512-7EaVr6vUaaqsl9Jnp+CY4FzA1jIQD+o1tFEY2+O4ibYgmVB+FEWDoyUNN/naq9ZfiYKw4+uly1fpxk0xyE358w==",
"requires": {
"idb-keyval": "3.1.0",
"js-cookie": "2.2.0"
}
},
"import-cwd": { "import-cwd": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",

View File

@@ -36,6 +36,7 @@
"graphql": "^0.13.2", "graphql": "^0.13.2",
"graphql-tag": "^2.8.0", "graphql-tag": "^2.8.0",
"gsap": "^2.0.2", "gsap": "^2.0.2",
"immortal-db": "^1.0.2",
"jquery": "^3.3.1", "jquery": "^3.3.1",
"js-cookie": "^2.2.0", "js-cookie": "^2.2.0",
"localforage": "^1.7.3", "localforage": "^1.7.3",

View File

@@ -59,7 +59,7 @@ module.exports = function (ctx) {
store: 'src/store/index.ts' store: 'src/store/index.ts'
}, },
// app plugins (/src/plugins) // app plugins (/src/plugins)
plugins: ['i18n', 'axios', 'vee-validate', 'myconfig', 'local-storage', 'error-handler', 'indexdb', 'vue-idb'], plugins: ['i18n', 'axios', 'vee-validate', 'myconfig', 'local-storage', 'error-handler', 'globalroutines', 'vue-idb'],
css: [ css: [
'app.styl' 'app.styl'
], ],

View File

@@ -9,13 +9,50 @@
console.log('05 ___________________________ 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('https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js'); //++Todo: Replace with local workbox.js
importScripts('js/idb.js'); importScripts('../statics/js/idb.js');
importScripts('js/utility.js'); importScripts('js/globalenv.js');
// importScripts('js/utility.js');
importScripts('../statics/js/storage.js');
const cfgenv = {
website: 'http://localhost:8080',
serverweb: 'http://localhost:3000',
dbname: 'mydb3',
dbversion: 11,
}
async function writeData(table, data) {
console.log('writeData', table, data);
await idbKeyval.setdata(table, data);
}
async function readAllData(table) {
console.log('readAllData', table);
return await idbKeyval.getalldata(table);
}
async function clearAllData(table) {
console.log('clearAllData', table);
await idbKeyval.clearalldata(table)
}
async function deleteItemFromData(table, id) {
console.log('deleteItemFromData', table, 'ID:', id);
await idbKeyval.deletedata(table, id)
}
// self.addEventListener('activate', function(event) {
// event.waitUntil(
// // createDB()
// );
// });
if (!workbox) { if (!workbox) {
let workbox = new self.WorkboxSW(); let workbox = new self.WorkboxSW();
} }
if (workbox) { if (workbox) {
@@ -38,7 +75,7 @@ if (workbox) {
// workbox.routing.registerRoute(/^http/, workbox.strategies.networkFirst(), 'GET'); // workbox.routing.registerRoute(/^http/, workbox.strategies.networkFirst(), 'GET');
workbox.routing.registerRoute( workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg)$/, new RegExp(/\.(?:png|gif|jpg|jpeg|svg)$/),
workbox.strategies.staleWhileRevalidate({ workbox.strategies.staleWhileRevalidate({
cacheName: 'images', cacheName: 'images',
plugins: [ plugins: [
@@ -62,22 +99,28 @@ if (workbox) {
}) })
); );
workbox.routing.registerRoute('http://localhost:3000/todos', function (args) {
return fetch(args.event.request) workbox.routing.registerRoute(
new RegExp(cfgenv.serverweb + '/todos/'),
function (args) {
return fetch(args.event.request, args.event.headers)
.then(function (res) { .then(function (res) {
console.log('******* registerRoute fetch: (1) ', args.event)
var clonedRes = res.clone(); var clonedRes = res.clone();
clearAllData('todos') clearAllData('todos')
.then(function () { .then(function () {
return clonedRes.json(); return clonedRes.json();
}) })
.then(function (data) { .then(function (data) {
for (let key in data) { console.log('2) data Received ', data.todos)
writeData('todos', data[key]) for (let key in data.todos) {
writeData('todos', data.todos[key])
} }
}); });
return res; return res
}); })
}); }
);
workbox.routing.registerRoute( workbox.routing.registerRoute(
@@ -158,28 +201,6 @@ 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
})
}
);
} }
@@ -189,68 +210,107 @@ if ('serviceWorker' in navigator) {
} }
// self.addEventListener('fetch', function (event) { // self.addEventListener('fetch', function (event) {
// console.log('[Service Worker] Fetching something ....', event); // console.log('[Service Worker] Fetching something ....', event);
// console.log('event.request.cache=', event.request.cache) // console.log('event.request.cache=', event.request.cache)
// if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') { // if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
// console.log('SAME ORIGIN!', event); // console.log('SAME ORIGIN!', event);
// return; // return;
// } // }
// event.respondWith(caches.match(event.request)); // event.respondWith(caches.match(event.request));
// }); // });
self.addEventListener('sync', function (event) { // const syncStore = {}
console.log('[Service Worker] Background syncing', event); // self.addEventListener('message', event => {
// if (event.data.type === 'sync') {
// // get a unique id to save the data
// const id = uuid()
// syncStore[id] = event.data
// // register a sync and pass the id as tag for it to get the data
// self.registration.sync.register(id)
// }
// console.log(event.data)
// })
if (event.tag === 'sync-new-todos') { self.addEventListener('sync', function (event) {
console.log('[Service Worker] Syncing new Todos'); console.log('[Service Worker V5] Background syncing', event);
let authHeader = [] let multiparams = event.tag.split('|')
authHeader['content-type'] = 'application/json'; if (multiparams && multiparams.length > 3) {
authHeader['accept-language'] = 'en'; let cmd = multiparams[0]
// authHeader.append('x-auth', mytok) 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);
const headers = new Headers()
headers.append('content-Type', 'application/json')
headers.append('Accept', 'application/json')
headers.append('x-auth', token)
event.waitUntil( event.waitUntil(
readAllData('sync_todos') readAllData(table)
.then(function (data) { .then(function (alldata) {
for (var dt of data) { console.log('data: ', alldata)
// var postData = new FormData(); if (alldata) {
// postData.append('_id', dt._id); for (var rec of alldata) {
// postData.append('title', dt.title); let link = cfgenv.serverweb + '/todos/' + rec._id
// postData.append('location', dt.location); console.log('FETCH: ', method, link, 'data:', JSON.stringify(rec))
// 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)) // Insert/Delete/Update table to the server
fetch(link, {
// Update myTodo to the server method: method,
fetch('http://localhost:3000/todos', { headers: headers,
method: 'POST', mode: 'cors', // 'no-cors',
headers: { body: JSON.stringify(rec)
'Content-Type': 'application/json',
'Accept': 'application/json'
},
// mode: 'no-cors',
mode: 'cors',
body: JSON.stringify(dt)
}) })
.then(function (resData) { .then(function (resData) {
console.log('Sent data Todo:', resData); console.log('Result data Todo:', resData);
if (resData.ok) { if (resData.ok) {
deleteItemFromData('sync_todos', dt.id); deleteItemFromData(table, rec._id);
} }
}) })
.catch(function (err) { .catch(function (err) {
console.log('Error while sending data', err); console.log('Error while sending data', err);
}); });
} }
}
}) })
); );
} }
}); }
})
;
// }
/*
// send message to serviceWorker
function sync (url, options) {
navigator.serviceWorker.controller.postMessage({type: 'sync', url, options})
}
const syncStore = {}
self.addEventListener('message', event => {
if(event.data.type === 'sync') {
// get a unique id to save the data
const id = uuid()
syncStore[id] = event.data
// register a sync and pass the id as tag for it to get the data
self.registration.sync.register(id)
}
console.log(event.data)
})
self.addEventListener('sync', event => {
// get the data by tag
const {url, options} = syncStore[event.tag]
event.waitUntil(fetch(url, options))
})
*/

View File

@@ -14,13 +14,13 @@ register(process.env.SERVICE_WORKER_FILE, {
console.log('REGISTERED::: !!!', process.env.SERVICE_WORKER_FILE) console.log('REGISTERED::: !!!', process.env.SERVICE_WORKER_FILE)
}, },
cached(registration) { // registration -> a ServiceWorkerRegistration instance cached(registration) {
console.log('CACHED::: Content has been cached for offline use.') console.log('CACHED::: Content has been cached for offline use.')
}, },
updatefound(registration) { // registration -> a ServiceWorkerRegistration instance updatefound(registration) {
console.log('UPDATEFOUND::: New content is downloading.') console.log('UPDATEFOUND::: New content is downloading.')
}, },
updated(registration) { // registration -> a ServiceWorkerRegistration instance updated(registration) {
console.log('New content is available; please refresh.') console.log('New content is available; please refresh.')
}, },
offline() { offline() {

View File

@@ -26,6 +26,8 @@
import Header from './components/Header.vue' import Header from './components/Header.vue'
import globalroutines from './globalroutines/index'
@Component({ @Component({
components: { components: {
appHeader: Header, appHeader: Header,
@@ -49,6 +51,7 @@
UserStore.actions.autologin() UserStore.actions.autologin()
.then((loginEseguito) => { .then((loginEseguito) => {
if (loginEseguito) { if (loginEseguito) {
globalroutines(this, 'loadapp', '')
// this.$router.replace('/') // this.$router.replace('/')
} }
}) })

View File

@@ -80,7 +80,7 @@ export default class Category extends Vue {
} }
async loadCat() { async loadCat() {
await this.$db.categories.toArray().then(ris => this.categories_loc = ris) // await this.$db.categories.toArray().then(ris => this.categories_loc = ris)
this.updatetable() this.updatetable()
} }

View File

@@ -100,7 +100,7 @@ export default class Tabledata extends Vue {
objcat.descr_it = this.category objcat.descr_it = this.category
// Add to Indexdb // Add to Indexdb
await this.$db.categories.add(objcat await this.$db.categories.put(objcat
).then(ris => { ).then(ris => {
myid = ris myid = ris
}) })

View File

@@ -57,15 +57,7 @@ $heightitem: 19px;
font-size: 0.75rem; font-size: 0.75rem;
} }
.todo-menu {
min-width: 202px;
}
.item-menu{
font-size: 1rem;
}
.titleLista-item { .titleLista-item {
max-width: 92px; max-width: 92px;
@@ -144,9 +136,6 @@ $heightitem: 19px;
color: #888; color: #888;
} }
.menuProgress {
}
.colProgress { .colProgress {
} }

View File

@@ -0,0 +1,16 @@
.todo-menu {
min-width: 202px;
}
.item-menu{
font-size: 1rem;
}
.item-menu:hover {
cursor: pointer;
}
.menuProgress {
}

View File

@@ -30,7 +30,7 @@
<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)">
<q-item-side :icon="field.icon"/> <q-item-side :icon="field.icon"/>
<q-item-tile label class="item-menu">{{field.label}}</q-item-tile> <q-item-main label class="item-menu">{{field.label}}</q-item-main>
</q-item> </q-item>
<q-item v-if="(field.value === 130)" :icon="field.icon" <q-item v-if="(field.value === 130)" :icon="field.icon"
@click.native="clickMenu(field.value)"> @click.native="clickMenu(field.value)">
@@ -60,3 +60,7 @@
<script lang="ts" src="./SubMenus.ts"> <script lang="ts" src="./SubMenus.ts">
</script> </script>
<style lang="scss" scoped>
@import './SubMenus.scss';
</style>

View File

@@ -13,6 +13,10 @@ import _ from 'lodash'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import VueIdb from 'vue-idb'
import globalroutines from '../../../globalroutines/index'
import $ from 'jquery' import $ from 'jquery'
@Component({ @Component({
@@ -93,8 +97,8 @@ export default class Todo extends Vue {
// console.log('updateLinkedList', this.todos_arr) // console.log('updateLinkedList', this.todos_arr)
let idprev = -1 let idprev = ''
let idnext = -1 let idnext = ''
let pos = 1 let pos = 1
if (arr.length > 0) { if (arr.length > 0) {
idprev = arr[0].id_prev idprev = arr[0].id_prev
@@ -221,6 +225,7 @@ export default class Todo extends Vue {
let update = false let update = false
await this.todos_arr.forEach((elem: ITodo) => { await this.todos_arr.forEach((elem: ITodo) => {
if (elem.modified) { if (elem.modified) {
console.log('calling MODIFY 3')
this.modify(elem, false) this.modify(elem, false)
update = true update = true
} }
@@ -275,6 +280,7 @@ export default class Todo extends Vue {
console.log('User:' + UserStore.state.userId) console.log('User:' + UserStore.state.userId)
const objtodo: ITodo = { const objtodo: ITodo = {
_id: new Date().toISOString(), // Create NEW
userId: UserStore.state.userId, userId: UserStore.state.userId,
descr: '', descr: '',
priority: rescodes.Todos.PRIORITY_NORMAL, priority: rescodes.Todos.PRIORITY_NORMAL,
@@ -285,8 +291,8 @@ export default class Todo extends Vue {
category: '', category: '',
expiring_at: mydateexp, expiring_at: mydateexp,
enableExpiring: false, enableExpiring: false,
id_prev: 0, id_prev: '',
id_next: 0, id_next: '',
pos: 0, pos: 0,
modified: true, modified: true,
progress: 0 progress: 0
@@ -304,7 +310,7 @@ export default class Todo extends Vue {
return '' return ''
} }
insertTodo() { async insertTodo() {
if (this.todo.trim() === '') if (this.todo.trim() === '')
return return
@@ -314,7 +320,7 @@ export default class Todo extends Vue {
objtodo.descr = this.todo objtodo.descr = this.todo
objtodo.category = this.getCategory() objtodo.category = this.getCategory()
const lastelem = this.getLastList() const lastelem: ITodo = 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.id_next = rescodes.LIST_END
objtodo.pos = (lastelem !== null) ? lastelem.pos + 1 : 1 objtodo.pos = (lastelem !== null) ? lastelem.pos + 1 : 1
@@ -325,21 +331,28 @@ export default class Todo extends Vue {
return return
} }
this.$db.todos.add(objtodo) // Add to Indexdb await globalroutines(this, 'write', 'todos', objtodo)
.then((id) => { .then((id) => {
console.log('*** IDNEW = ', id) console.log('*** IDNEW (2) = ', 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)
this.modify(lastelem, false) this.modify(lastelem, false)
.then(ris => {
console.log('END calling MODIFY 4')
this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS, 'POST', objtodo)
this.updatetable(false)
})
} else {
this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS, 'POST', objtodo)
this.updatetable(false)
} }
this.saveItemToSyncAndDb(objtodo)
// this.modify(objtodo, true)
this.updatetable(false)
}).catch(err => { }).catch(err => {
console.log('Errore: ' + err.message) console.log('Errore: ' + err.message)
}) })
@@ -350,40 +363,69 @@ export default class Todo extends Vue {
this.todo = '' this.todo = ''
} }
saveItemToSyncAndDb(item: ITodo) { cmdToSyncAndDb(cmd, table, method, itemOrId, msg: String) {
// Send to Server to Sync // Send to Server to Sync
console.log('cmdToSyncAndDb', cmd, table, method, itemOrId, msg)
const mythis = this const mythis = this
console.log('saveItemToSyncAndDb')
if ('serviceWorker' in navigator && 'SyncManager' in window) { if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready 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')
// check if exist _id, delete it // mythis.sendMessageToSW(item, method)
mythis.$db.sync_todos
.where('id').equals(item._id)
.delete()
mythis.$db.sync_todos.add(item) globalroutines(mythis, 'write', table, itemOrId)
.then(function () { .then(function (id) {
return sw.sync.register('sync-new-todos') 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)
}) })
.then(function () { .then(function () {
let snackbarContainer = document.querySelector('#confirmation-toast') let snackbarContainer = document.querySelector('#confirmation-toast')
let data = { message: 'Your Post was saved for syncing!' } let data = { message: msg }
// snackbarContainer.MaterialSnackbar.showSnackbar(data) // snackbarContainer.MaterialSnackbar.showSnackbar(data)
}) })
.catch(function (err) { .catch(function (err) {
console.log(err) console.error('Errore in globalroutines', table, err)
}) })
}) })
} else { } else {
Todos.actions.dbSaveTodo(item) if (cmd === rescodes.DB.CMD_SYNC_TODOS)
Todos.actions.dbSaveTodo(itemOrId)
else if (cmd === rescodes.DB.CMD_DELETE_TODOS)
Todos.actions.dbDeleteTodo(itemOrId)
}
} }
saveItemToSyncAndDb(table: String, method, item: ITodo) {
return this.cmdToSyncAndDb(rescodes.DB.CMD_SYNC_TODOS, table, method, item, 'Your Post was saved for syncing!')
} }
deleteItemToSyncAndDb(table: String, id: String) {
return this.cmdToSyncAndDb(rescodes.DB.CMD_DELETE_TODOS, table, 'DELETE', id, 'Your Post was canceled for syncing!')
}
/*
sendMessageToSW(recdata, method) {
navigator.serviceWorker.controller.postMessage({
type: 'sync',
recdata,
method,
cmd: 'sync-new-todos',
token: UserStore.state.idToken,
lang: UserStore.state.lang
})
}
*/
getElemById(id, lista = this.todos_arr) { getElemById(id, lista = this.todos_arr) {
let myobj: ITodo let myobj: ITodo
for (myobj of lista) { for (myobj of lista) {
@@ -407,23 +449,24 @@ export default class Todo extends Vue {
if (myobjprev !== null) { if (myobjprev !== null) {
myobjprev.id_next = myobjtrov.id_next myobjprev.id_next = myobjtrov.id_next
myobjprev.modified = true myobjprev.modified = true
console.log('calling MODIFY 2')
this.modify(myobjprev, false) this.modify(myobjprev, false)
} }
if (myobjnext !== null) { if (myobjnext !== null) {
myobjnext.id_prev = myobjtrov.id_prev myobjnext.id_prev = myobjtrov.id_prev
myobjnext.modified = true myobjnext.modified = true
console.log('calling MODIFY 1')
this.modify(myobjnext, false) this.modify(myobjnext, false)
} }
console.log('ENTRATO') this.deleteItemToSyncAndDb(rescodes.DB.TABLE_DELETE_TODOS, id)
const mythis = this const mythis = this
// Delete item // Delete item
await this.$db.todos await globalroutines(this, 'delete', 'todos', id)
.where('id').equals(id) .then((ris) => {
.delete() console.log('UpdateTable', ris)
.then(() => {
console.log('UpdateTable')
mythis.updatetable() mythis.updatetable()
}).catch((error) => { }).catch((error) => {
console.log('err: ', error) console.log('err: ', error)
@@ -498,7 +541,7 @@ export default class Todo extends Vue {
} }
async filtertodos(refresh: boolean = false) { async filtertodos(refresh: boolean = false) {
// console.log('filtertodos') console.log('filtertodos')
return await Todos.actions.getTodosByCategory(this.getCategory()) return await Todos.actions.getTodosByCategory(this.getCategory())
.then(arrtemp => { .then(arrtemp => {
@@ -583,15 +626,21 @@ export default class Todo extends Vue {
if (recOut[field] !== recIn[field]) { if (recOut[field] !== recIn[field]) {
recOut.modified = true recOut.modified = true
recOut[field] = recIn[field] recOut[field] = recIn[field]
return true return recOut[field]
} }
return false return false
} }
async modify(myobj: ITodo, update: boolean) { async modify(myobj: ITodo, update: boolean) {
await this.$db.transaction('rw', [this.$db.todos], async () => { await globalroutines(this, 'read', 'todos', myobj._id)
const miorec = await this.$db.todos.get(myobj._id) .then(miorec => {
console.log('ArrTodos: ', myobj.descr, '[', myobj._id, ']')
if (miorec === undefined) {
console.log('Record not Found !!!!!! id=', myobj._id)
return
}
this.modifyField(miorec, myobj, 'descr') this.modifyField(miorec, myobj, 'descr')
if (this.modifyField(miorec, myobj, 'completed')) if (this.modifyField(miorec, myobj, 'completed'))
@@ -612,16 +661,16 @@ export default class Todo extends Vue {
// this.logelem('modify', miorec) // this.logelem('modify', miorec)
await this.$db.todos.put(miorec) globalroutines(this, 'write', 'todos', miorec)
.then(ris => {
this.saveItemToSyncAndDb(miorec) this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS, 'PATCH', miorec)
if (update) if (update)
await this.updatetable(false) this.updatetable(false)
})
} }
}) })
} }
} }

View File

@@ -0,0 +1,6 @@
import indexdb from './indexdb'
export default async (context, cmd, table, data = null) => {
console.log('globalroutines', cmd, table, data)
return await indexdb(context, cmd, table, data)
}

View File

@@ -0,0 +1,63 @@
import store from '../store'
import _ from 'lodash'
import { UserStore } from '@modules'
import { i18n } from '../plugins/i18n'
import {idbKeyval as storage} from '../js/storage.js';
function saveConfigIndexDb(context) {
let data = []
data['_id'] = 1
data['lang'] = UserStore.state.lang
data['token'] = UserStore.state.idToken
data['userId'] = UserStore.state.userId
writeConfigIndexDb('config', data)
}
function writeConfigIndexDb(context, data) {
console.log('writeConfigIndexDb', data)
storage.setdata('config', data)
.then(ris => {
return true
})
}
async function readfromIndexDbToStateTodos(context) {
console.log('*** read from IndexDb to state.todos')
return await storage.getalldata('todos')
.then(ristodos => {
console.log('&&&&&&& readfromIndexDbToStateTodos OK: Num RECORD: ', ristodos.length)
UserStore.state.todos = ristodos
}).catch((error) => {
console.log('err: ', error)
})
}
export default async (context, cmd, table, datakey) => {
if (cmd === 'loadapp') {
// ****** LOAD APP AL CARICAMENTO ! *******
return saveConfigIndexDb(context, datakey)
if ('indexedDB' in window) {
if (!UserStore.state.networkDataReceived) {
return await readfromIndexDbToStateTodos(context)
}
}
} else if (cmd === 'write') {
return await storage.setdata(table, datakey)
} else if (cmd === 'readall') {
return await storage.getalldata(table)
} else if (cmd === 'read') {
return await storage.getdata(table, datakey)
} else if (cmd === 'delete') {
return await storage.deletedata(table, datakey)
}
}

View File

@@ -17,6 +17,16 @@
<script src="/statics/js/promise.js"></script> <script src="/statics/js/promise.js"></script>
<script src="/statics/js/fetch.js"></script> <script src="/statics/js/fetch.js"></script>
<script src="/statics/js/idb.js"></script> <script src="/statics/js/idb.js"></script>
<script src="/statics/js/storage.js"></script>
<!--
<script src="/statics/js/immortal-db.min.js"></script>
<script>
;(async () => {
const db = ImmortalDB.ImmortalDB
await db.set('hi', 'lolsup')
})()
</script>
-->
<!--<link type="text/css" rel="stylesheet" href="statics/firebaseui.css" />--> <!--<link type="text/css" rel="stylesheet" href="statics/firebaseui.css" />-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

View File

@@ -295,7 +295,7 @@
} }
// HTTP methods whose capitalization should be normalized // HTTP methods whose capitalization should be normalized
var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH']
function normalizeMethod(method) { function normalizeMethod(method) {
var upcased = method.toUpperCase() var upcased = method.toUpperCase()

24
src/js/globalenv.js Normal file
View File

@@ -0,0 +1,24 @@
// importScripts('/statics/js/immortal-db.min.js');
// const cfgenv = {
// website: 'http://localhost:8080',
// serverweb: 'http://localhost:3000',
// dbname: 'mydb3',
// dbversion: 10,
// }
/*
async function clearAllDataImmortal(table) {
console.log('clearAllDataImmortal', table)
const db = ImmortalDB.ImmortalDB
await db.remove(table)
}
async function writeDataImmortal(table, datavalue) {
console.log('writeDataImmortal', table, datavalue)
const db = ImmortalDB.ImmortalDB
await db.set(table, datavalue)
}
*/

View File

@@ -1,311 +0,0 @@
'use strict';
(function() {
function toArray(arr) {
return Array.prototype.slice.call(arr);
}
function promisifyRequest(request) {
return new Promise(function(resolve, reject) {
request.onsuccess = function() {
resolve(request.result);
};
request.onerror = function() {
reject(request.error);
};
});
}
function promisifyRequestCall(obj, method, args) {
var request;
var p = new Promise(function(resolve, reject) {
request = obj[method].apply(obj, args);
promisifyRequest(request).then(resolve, reject);
});
p.request = request;
return p;
}
function promisifyCursorRequestCall(obj, method, args) {
var p = promisifyRequestCall(obj, method, args);
return p.then(function(value) {
if (!value) return;
return new Cursor(value, p.request);
});
}
function proxyProperties(ProxyClass, targetProp, properties) {
properties.forEach(function(prop) {
Object.defineProperty(ProxyClass.prototype, prop, {
get: function() {
return this[targetProp][prop];
},
set: function(val) {
this[targetProp][prop] = val;
}
});
});
}
function proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) {
properties.forEach(function(prop) {
if (!(prop in Constructor.prototype)) return;
ProxyClass.prototype[prop] = function() {
return promisifyRequestCall(this[targetProp], prop, arguments);
};
});
}
function proxyMethods(ProxyClass, targetProp, Constructor, properties) {
properties.forEach(function(prop) {
if (!(prop in Constructor.prototype)) return;
ProxyClass.prototype[prop] = function() {
return this[targetProp][prop].apply(this[targetProp], arguments);
};
});
}
function proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) {
properties.forEach(function(prop) {
if (!(prop in Constructor.prototype)) return;
ProxyClass.prototype[prop] = function() {
return promisifyCursorRequestCall(this[targetProp], prop, arguments);
};
});
}
function Index(index) {
this._index = index;
}
proxyProperties(Index, '_index', [
'name',
'keyPath',
'multiEntry',
'unique'
]);
proxyRequestMethods(Index, '_index', IDBIndex, [
'get',
'getKey',
'getAll',
'getAllKeys',
'count'
]);
proxyCursorRequestMethods(Index, '_index', IDBIndex, [
'openCursor',
'openKeyCursor'
]);
function Cursor(cursor, request) {
this._cursor = cursor;
this._request = request;
}
proxyProperties(Cursor, '_cursor', [
'direction',
'key',
'primaryKey',
'value'
]);
proxyRequestMethods(Cursor, '_cursor', IDBCursor, [
'update',
'delete'
]);
// proxy 'next' methods
['advance', 'continue', 'continuePrimaryKey'].forEach(function(methodName) {
if (!(methodName in IDBCursor.prototype)) return;
Cursor.prototype[methodName] = function() {
var cursor = this;
var args = arguments;
return Promise.resolve().then(function() {
cursor._cursor[methodName].apply(cursor._cursor, args);
return promisifyRequest(cursor._request).then(function(value) {
if (!value) return;
return new Cursor(value, cursor._request);
});
});
};
});
function ObjectStore(store) {
this._store = store;
}
ObjectStore.prototype.createIndex = function() {
return new Index(this._store.createIndex.apply(this._store, arguments));
};
ObjectStore.prototype.index = function() {
return new Index(this._store.index.apply(this._store, arguments));
};
proxyProperties(ObjectStore, '_store', [
'name',
'keyPath',
'indexNames',
'autoIncrement'
]);
proxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [
'put',
'add',
'delete',
'clear',
'get',
'getAll',
'getKey',
'getAllKeys',
'count'
]);
proxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [
'openCursor',
'openKeyCursor'
]);
proxyMethods(ObjectStore, '_store', IDBObjectStore, [
'deleteIndex'
]);
function Transaction(idbTransaction) {
this._tx = idbTransaction;
this.complete = new Promise(function(resolve, reject) {
idbTransaction.oncomplete = function() {
resolve();
};
idbTransaction.onerror = function() {
reject(idbTransaction.error);
};
idbTransaction.onabort = function() {
reject(idbTransaction.error);
};
});
}
Transaction.prototype.objectStore = function() {
return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments));
};
proxyProperties(Transaction, '_tx', [
'objectStoreNames',
'mode'
]);
proxyMethods(Transaction, '_tx', IDBTransaction, [
'abort'
]);
function UpgradeDB(db, oldVersion, transaction) {
this._db = db;
this.oldVersion = oldVersion;
this.transaction = new Transaction(transaction);
}
UpgradeDB.prototype.createObjectStore = function() {
return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments));
};
proxyProperties(UpgradeDB, '_db', [
'name',
'version',
'objectStoreNames'
]);
proxyMethods(UpgradeDB, '_db', IDBDatabase, [
'deleteObjectStore',
'close'
]);
function DB(db) {
this._db = db;
}
DB.prototype.transaction = function() {
return new Transaction(this._db.transaction.apply(this._db, arguments));
};
proxyProperties(DB, '_db', [
'name',
'version',
'objectStoreNames'
]);
proxyMethods(DB, '_db', IDBDatabase, [
'close'
]);
// Add cursor iterators
// TODO: remove this once browsers do the right thing with promises
['openCursor', 'openKeyCursor'].forEach(function(funcName) {
[ObjectStore, Index].forEach(function(Constructor) {
Constructor.prototype[funcName.replace('open', 'iterate')] = function() {
var args = toArray(arguments);
var callback = args[args.length - 1];
var nativeObject = this._store || this._index;
var request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1));
request.onsuccess = function() {
callback(request.result);
};
};
});
});
// polyfill getAll
[Index, ObjectStore].forEach(function(Constructor) {
if (Constructor.prototype.getAll) return;
Constructor.prototype.getAll = function(query, count) {
var instance = this;
var items = [];
return new Promise(function(resolve) {
instance.iterateCursor(query, function(cursor) {
if (!cursor) {
resolve(items);
return;
}
items.push(cursor.value);
if (count !== undefined && items.length == count) {
resolve(items);
return;
}
cursor.continue();
});
});
};
});
var exp = {
open: function(name, version, upgradeCallback) {
var p = promisifyRequestCall(indexedDB, 'open', [name, version]);
var request = p.request;
request.onupgradeneeded = function(event) {
if (upgradeCallback) {
upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction));
}
};
return p.then(function(db) {
return new DB(db);
});
},
delete: function(name) {
return promisifyRequestCall(indexedDB, 'deleteDatabase', [name]);
}
};
if (typeof module !== 'undefined') {
module.exports = exp;
module.exports.default = module.exports;
}
else {
self.idb = exp;
}
}());

8
src/js/immortal-db.min.js vendored Normal file

File diff suppressed because one or more lines are too long

112
src/js/storage.js Normal file
View File

@@ -0,0 +1,112 @@
import { rescodes } from "../store/Modules/rescodes";
export let idbKeyval = (() => {
let db;
function getDB() {
if (!db) {
console.log('CREO DB STORAGE JS !')
db = new Promise((resolve, reject) => {
const openreq = indexedDB.open('mydb3', 11);
openreq.onerror = () => {
reject(openreq.error);
};
openreq.onupgradeneeded = () => {
// First time setup: create an empty object store
openreq.result.createObjectStore('todos', { keyPath: '_id' });
openreq.result.createObjectStore('sync_todos', { keyPath: '_id' });
openreq.result.createObjectStore('delete_todos', { keyPath: '_id' });
openreq.result.createObjectStore('config', { keyPath: '_id' });
};
openreq.onsuccess = () => {
resolve(openreq.result);
};
});
}
return db;
}
async function withStore(type, table, callback, ) {
const db = await getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction(table, type);
transaction.oncomplete = () => resolve();
transaction.onerror = () => reject(transaction.error);
callback(transaction.objectStore(table));
});
}
return {
async get(key) {
let req;
await withStore('readonly', 'keyval', store => {
req = store.get(key);
});
return req.result;
},
async getdata(table, key) {
let req;
await withStore('readonly', table, store => {
console.log('store', store, 'key', key)
req = store.get(key);
});
console.log('RISFINALE!', req.result)
return req.result;
},
async getalldata(table) {
let req;
await withStore('readonly', table, store => {
req = store.getAll();
});
return req.result;
},
async set(key, value) {
return await withStore('readwrite', 'keyval', store => {
store.put(value, key);
});
},
async setdata(table, valuekey) {
let value = []
if (table === rescodes.DB.CMD_DELETE_TODOS) {
value['_id'] = valuekey
}else {
value = valuekey
}
console.log('setdata', table, value)
return await withStore('readwrite', table, store => {
store.put(value);
});
},
async delete(key) {
return await withStore('readwrite', 'keyval', store => {
store.delete(key);
});
},
async deletedata(table, key) {
return await withStore('readwrite', table, store => {
store.delete(key);
});
},
async clearalldata(table) {
return await withStore('readwrite', table, store => {
store.clear();
});
}
};
})();
// iOS add-to-homescreen is missing IDB, or at least it used to.
// I haven't tested this in a while.
if (!self.indexedDB) {
idbKeyval = {
get: key => Promise.resolve(localStorage.getItem(key)),
set: (key, val) => Promise.resolve(localStorage.setItem(key, val)),
delete: key => Promise.resolve(localStorage.removeItem(key))
};
}

View File

@@ -1,67 +1,57 @@
console.log('utility.js') console.log('utility.js')
var dbPromise = idb.open('mydb', 10, function (db) { // var dbPromise = idb.open('mydb1', 1, function (db) {
console.log('OPEN MYDB') // console.log('OPEN MYDB')
if (!db.objectStoreNames.contains('sync_todos')) { // if (!db.objectStoreNames.contains('todos')) {
db.createObjectStore('sync_todos', { keyPath: 'id' }); // db.createObjectStore('todos', { keyPath: '_id' });
} // }
if (!db.objectStoreNames.contains('todos')) { // if (!db.objectStoreNames.contains('config')) {
db.createObjectStore('todos', { keyPath: 'id' }); // db.createObjectStore('config', { 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) { // function readAllData(st) {
console.log('readAllData', st); // console.log('readAllData', st);
return dbPromise // return dbPromise
.then(function (db) { // .then(function (db) {
var tx = db.transaction(st, 'readonly'); // var tx = db.transaction(st, 'readonly');
var store = tx.objectStore(st); // var store = tx.objectStore(st);
return store.getAll(); // return store.getAll();
}); // });
} // }
function clearAllData(st) { // function clearAllData(st) {
console.log('clearAllData', st); // console.log('clearAllData', st);
return dbPromise // return dbPromise
.then(function (db) { // .then(function (db) {
var tx = db.transaction(st, 'readwrite'); // var tx = db.transaction(st, 'readwrite');
var store = tx.objectStore(st); // var store = tx.objectStore(st);
store.clear(); // store.clear();
return tx.complete; // return tx.complete;
}); // });
} // }
function deleteItemFromData(st, id) { // function deleteItemFromData(st, id) {
console.log('deleteItemFromData', st, 'ID:', id); // console.log('deleteItemFromData', st, 'ID:', id);
dbPromise // dbPromise
.then(function (db) { // .then(function (db) {
//
var tx = db.transaction(st, 'readwrite'); // var tx = db.transaction(st, 'readwrite');
var store = tx.objectStore(st); // var store = tx.objectStore(st);
//
try { // try {
store.delete(id); // store.delete(id);
return tx.complete; // return tx.complete;
} catch (e) { // } catch (e) {
return false; // return false;
} // }
}) // })
.then(function (res) { // .then(function (res) {
if (res) // if (res)
console.log('Item deleted!'); // console.log('Item deleted!');
}); // });
} // }
function urlBase64ToUint8Array(base64String) { function urlBase64ToUint8Array(base64String) {
var padding = '='.repeat((4 - base64String.length % 4) % 4); var padding = '='.repeat((4 - base64String.length % 4) % 4);

View File

@@ -1,5 +1,5 @@
export interface ITodo { export interface ITodo {
_id?: number, _id?: string,
userId: string userId: string
category?: string category?: string
descr?: string, descr?: string,
@@ -10,8 +10,8 @@ export interface ITodo {
completed_at: any, completed_at: any,
expiring_at: any, expiring_at: any,
enableExpiring?: boolean, enableExpiring?: boolean,
id_prev?: number, id_prev?: string,
id_next?: number, id_next?: string,
modified?: boolean, modified?: boolean,
pos?: number, pos?: number,
progress?: number progress?: number

View File

@@ -3,7 +3,7 @@ export * from './GlobalStore'
export * from './signin-option' export * from './signin-option'
export * from './signup-option' export * from './signup-option'
export * from './key-value' export * from './key-value'
export * from './payload' // export * from './payload'
export * from './Categories' export * from './Categories'
export * from './Todos' export * from './Todos'

View File

@@ -1,4 +0,0 @@
export { IPayload } from './payload'
export { IPayloadMessage } from './payload-message'
export * from './payload-mapper'

View File

@@ -1,80 +0,0 @@
import { AxiosError, AxiosResponse } from 'axios'
import { PayloadMessageTypes } from 'common'
import { IPayload } from './payload'
export { PayloadMessageTypes } from '../../common/message'
export class PayloadMapper {
private fromError<T>(o: Error): IPayload<T> {
return {
data: null,
message: {
messageTypeId: PayloadMessageTypes.error,
text: o.message,
title: o.name
}
}
}
private fromAxiosError<T>(o: AxiosError): IPayload<T> {
let data: T = null
if (o.response && isAxiosResponse(o.response))
data = this.fromAxiosResponse<T>(o.response).data
return {
data: data,
message: {
messageTypeId: PayloadMessageTypes.error,
text: o.message,
title: 'Code:' + o.code + '. ' + o.name
}
}
}
private fromAxiosResponse<T>(o: AxiosResponse): IPayload<T> {
let value: IPayload<T> = null
if (isPayload<T>(o.data))
value = o.data
else
value = {
data: <any>o.data,
message: {
messageTypeId: PayloadMessageTypes.success,
text: null
}
}
return value
}
public fromObject<T>(o: any): IPayload<T> {
if (isAxiosError(o))
return this.fromAxiosError<T>(o)
if (o instanceof Error)
return this.fromError<T>(o)
if (isAxiosResponse(o))
return this.fromAxiosResponse<T>(o)
return null
}
}
function isAxiosResponse(o: any): o is AxiosResponse {
return o instanceof Object && 'data' in o && 'config' in o && 'status' in o && 'statusText' in o && 'headers' in o
}
function isAxiosError(o: any): o is AxiosError {
return o instanceof Object && o instanceof Error && 'config' in o
}
function isPayload<T>(o: any): o is IPayload<T> {
return o instanceof Object && 'data' in o && 'message' in o
}

View File

@@ -1,6 +0,0 @@
export interface IPayloadMessage {
text: string
title?: string
messageTypeId: string
}

View File

@@ -1,8 +0,0 @@
import { IPayloadMessage } from './payload-message'
export interface IPayload<T> {
data: T
message: IPayloadMessage
}

View File

@@ -0,0 +1,8 @@
import globalroutines from '../globalroutines'
export default ({ app, router, store, Vue }) => {
// something to do
Vue.prototype.$globalroutines = globalroutines
}

View File

@@ -1,5 +0,0 @@
import VueIdb from 'vue-idb'
export default ({ Vue }) => {
Vue.use(VueIdb)
}

View File

@@ -4,20 +4,6 @@ import VueIdb from 'vue-idb'
export default ({ Vue }) => { export default ({ Vue }) => {
Vue.use(VueIdb) Vue.use(VueIdb)
// Insert here the database for IndexDB
new VueIdb({
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, 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' },
}
})
} }

View File

@@ -6,8 +6,8 @@ const messages = {
delete: 'Elimina', delete: 'Elimina',
cancel: 'Annulla', cancel: 'Annulla',
msg: { msg: {
titledeleteTask: 'Cancella Task', titledeleteTask: 'Elimina Task',
deleteTask: 'Vuoi cancellare questo Task?' deleteTask: 'Vuoi Eliminare questo Task?'
} }
}, },
comp:{ comp:{

8
src/statics/js/immortal-db.min.js vendored Normal file

File diff suppressed because one or more lines are too long

91
src/statics/js/storage.js Normal file
View File

@@ -0,0 +1,91 @@
let idbKeyval = (() => {
let db;
function getDB() {
if (!db) {
console.log('CREO DB STATICS!')
db = new Promise((resolve, reject) => {
const openreq = indexedDB.open('mydb3', 11);
openreq.onerror = () => {
reject(openreq.error);
};
openreq.onupgradeneeded = () => {
// First time setup: create an empty object store
openreq.result.createObjectStore('todos', { keyPath: '_id' });
openreq.result.createObjectStore('sync_todos', { keyPath: '_id' });
openreq.result.createObjectStore('delete_todos', { keyPath: '_id' });
openreq.result.createObjectStore('config', { keyPath: '_id' });
};
openreq.onsuccess = () => {
resolve(openreq.result);
};
});
}
return db;
}
async function withStore(type, table, callback, ) {
const db = await getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction(table, type);
transaction.oncomplete = () => resolve();
transaction.onerror = () => reject(transaction.error);
callback(transaction.objectStore(table));
});
}
return {
async get(key) {
let req;
await withStore('readonly', store => {
req = store.get(key);
});
return req.result;
},
async getalldata(table) {
let req;
await withStore('readonly', table, store => {
req = store.getAll();
});
return req.result;
},
set(key, value) {
return withStore('readwrite', 'keyval', store => {
store.put(value, key);
});
},
setdata(table, value) {
return withStore('readwrite', table, store => {
store.put(value);
});
},
delete(key) {
return withStore('readwrite', 'keyval', store => {
store.delete(key);
});
},
async deletedata(table, key) {
return await withStore('readwrite', table, store => {
store.delete(key);
});
},
async clearalldata(table) {
return await withStore('readwrite', table, store => {
store.clear();
});
}
};
})();
// iOS add-to-homescreen is missing IDB, or at least it used to.
// I haven't tested this in a while.
if (!self.indexedDB) {
idbKeyval = {
get: key => Promise.resolve(localStorage.getItem(key)),
set: (key, val) => Promise.resolve(localStorage.setItem(key, val)),
delete: key => Promise.resolve(localStorage.removeItem(key))
};
}

View File

@@ -1,15 +1,14 @@
import axios, { AxiosInstance, AxiosPromise, AxiosResponse, AxiosInterceptorManager } from 'axios' import axios, { AxiosInstance, AxiosPromise, AxiosResponse, AxiosInterceptorManager } from 'axios'
async function sendRequest (url: string, lang: string, mytok: string, method: string, mydata: any) { async function sendRequest (url: string, lang: string, mytok: string, method: string, mydata: any) {
console.log('LANG ' + lang)
// let mytok: string = this.getTok() console.log('sendRequest', method, url, '[', lang, ']')
const authHeader = new Headers() const authHeader = new Headers()
authHeader.append('content-Type', 'application/json')
console.log('sendRequest:', url) authHeader.append('Accept', 'application/json')
authHeader.append('content-type', 'application/json')
authHeader.append('x-auth', mytok) authHeader.append('x-auth', mytok)
authHeader.append('accept-language', lang) // authHeader.append('accept-language', lang)
let configInit: RequestInit let configInit: RequestInit

View File

@@ -1,12 +1,9 @@
import VueIdb from 'vue-idb' import { ITodo, ITodosState } from 'model'
import { ISigninOptions, ITodo, ITodosState } from 'model'
import { storeBuilder } from './Store/Store' import { storeBuilder } from './Store/Store'
import Api from '@api' import Api from '@api'
import { serv_constants } from '../Modules/serv_constants'
import { rescodes } from './rescodes' import { rescodes } from './rescodes'
import { UserStore } from '@store' import { UserStore } from '@store'
import { IResult } from 'model/other'
const state: ITodosState = { const state: ITodosState = {
@@ -32,86 +29,37 @@ namespace Getters {
namespace Mutations { namespace Mutations {
function deleteItem(state: ITodosState, num: number) {
// state.conta = num
// 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)
}
} }
namespace Actions { namespace Actions {
async function deleteItem(context, num: number) {
Mutations.mutations.deleteItem(num)
}
function json2array(json){ function json2array(json) {
var result = [] let result = []
var keys = Object.keys(json); let keys = Object.keys(json)
keys.forEach(function(key){ keys.forEach(function (key) {
result.push(json[key]) result.push(json[key])
}); })
return result; return result
} }
async function dbLoadTodo(context) { async function dbLoadTodo(context) {
console.log('dbLoadTodo') console.log('dbLoadTodo')
const token = localStorage.getItem(rescodes.localStorage.token) const token = UserStore.state.idToken
let call = process.env.MONGODB_HOST + '/todos/' + UserStore.state.userId let call = process.env.MONGODB_HOST + '/todos/' + UserStore.state.userId
return await Api.SendReq(call, UserStore.state.lang, token, 'GET', null) state.networkDataReceived = false
let ris = await Api.SendReq(call, UserStore.state.lang, token, 'GET', null)
.then((res) => { .then((res) => {
return res.json() return res.json()
}).then((resData) => { }).then((resData) => {
// console.log('res.todos:', res.todos) state.networkDataReceived = true
state.todos = [] state.todos = resData.todos
for(var i in resData.todos)
state.todos.push(resData.todos [i])
// state.todos = Object.keys(resData.todos).map((key) => { // After Login will store into the indexedDb...
// return resData.todos[key]
// })
console.log('state.todos', state.todos) console.log('state.todos', state.todos)
return rescodes.OK return rescodes.OK
@@ -123,16 +71,19 @@ namespace Actions {
} }
return rescodes.ERR_GENERICO return rescodes.ERR_GENERICO
}) })
} }
async function dbSaveTodo(context, itemtodo: ITodo) { async function dbSaveTodo(context, itemtodo: ITodo) {
console.log('dbSaveTodo', itemtodo)
let call = process.env.MONGODB_HOST + '/todos/' + itemtodo._id let call = process.env.MONGODB_HOST + '/todos/' + itemtodo._id
const token = localStorage.getItem(rescodes.localStorage.token) const token = UserStore.state.idToken
let res = await Api.SendReq(call, UserStore.state.lang, token, 'PATCH', itemtodo) let res = await Api.SendReq(call, UserStore.state.lang, token, 'PATCH', itemtodo)
.then(function (res) { .then(function (res) {
state.networkDataReceived = true
return rescodes.OK return rescodes.OK
}) })
.catch((error) => { .catch((error) => {
@@ -144,12 +95,25 @@ namespace Actions {
}) })
if ('indexedDB' in window) { return res
await Mutations.mutations.readdbTodoData()
if (!state.networkDataReceived) {
console.log('From cache', state.todos)
} }
async function dbDeleteTodo(context, id: String) {
console.log('dbDeleteTodo', id)
let call = process.env.MONGODB_HOST + '/todos/' + id
const token = UserStore.state.idToken
let res = await Api.SendReq(call, UserStore.state.lang, token, 'DELETE', id)
.then(function (res) {
return rescodes.OK
})
.catch((error) => {
if (process.env.DEV) {
console.log('ERROREEEEEEEEE', error)
} }
return rescodes.ERR_GENERICO
})
return res return res
} }
@@ -163,9 +127,9 @@ namespace Actions {
} }
export const actions = { export const actions = {
setConta: b.dispatch(deleteItem),
dbSaveTodo: b.dispatch(dbSaveTodo), dbSaveTodo: b.dispatch(dbSaveTodo),
dbLoadTodo: b.dispatch(dbLoadTodo), dbLoadTodo: b.dispatch(dbLoadTodo),
dbDeleteTodo: b.dispatch(dbDeleteTodo),
getTodosByCategory: b.dispatch(getTodosByCategory) getTodosByCategory: b.dispatch(getTodosByCategory)
} }
@@ -178,7 +142,7 @@ const TodosModule = {
return stateGetter() return stateGetter()
}, },
getters: Getters.getters, getters: Getters.getters,
mutations: Mutations.mutations, // mutations: Mutations.mutations,
actions: Actions.actions actions: Actions.actions
} }

View File

@@ -10,7 +10,6 @@ import { GlobalStore, UserStore, Todos } from '@store'
const bcrypt = require('bcryptjs') const bcrypt = require('bcryptjs')
// State // State
const state: IUserState = { const state: IUserState = {
userId: '', userId: '',
@@ -136,7 +135,6 @@ namespace Actions {
} }
} }
async function resetpwd (context, paramquery: IUserState) { async function resetpwd (context, paramquery: IUserState) {
let call = process.env.MONGODB_HOST + '/updatepwd' let call = process.env.MONGODB_HOST + '/updatepwd'
console.log('CALL ' + call) console.log('CALL ' + call)

View File

@@ -5,8 +5,8 @@ export const rescodes = {
DUPLICATE_EMAIL_ID: 11000, DUPLICATE_EMAIL_ID: 11000,
DUPLICATE_USERNAME_ID: 11100, DUPLICATE_USERNAME_ID: 11100,
LIST_END: 10000000, LIST_END: '10000000',
LIST_START: 0, LIST_START: '0',
localStorage: { localStorage: {
verifiedEmail: 'vf', verifiedEmail: 'vf',
@@ -25,6 +25,13 @@ export const rescodes = {
PRIORITY_LOW: 0 PRIORITY_LOW: 0
}, },
DB: {
CMD_SYNC_TODOS: 'sync-new-todos',
CMD_DELETE_TODOS: 'sync-delete-todos',
TABLE_SYNC_TODOS : 'sync_todos,',
TABLE_DELETE_TODOS : 'delete_todos,'
},
MenuAction: { MenuAction: {
DELETE: 100, DELETE: 100,
TOGGLE_EXPIRING: 101, TOGGLE_EXPIRING: 101,
@@ -110,7 +117,7 @@ export const rescodes = {
}, },
{ {
id: 50, id: 50,
label: 'Cancella', label: 'Elimina',
value: 100, // DELETE value: 100, // DELETE
icon: 'delete', icon: 'delete',
checked: false checked: false

8
src/typings/libs/globalroutines.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
import { globalroutines } from '../../globalroutines'
declare module 'vue/types/vue' {
interface Vue {
$globalroutines: globalroutines
}
}

View File

@@ -1,5 +1,5 @@
import { default as Axios, AxiosResponse } from 'axios' import { default as Axios, AxiosResponse } from 'axios'
import { IPayload } from 'model' // import { IPayload } from 'model'
import { GlobalConfig, PayloadMessageTypes } from '../common' import { GlobalConfig, PayloadMessageTypes } from '../common'
// const SITE_URL = GlobalConfig.uri.site // const SITE_URL = GlobalConfig.uri.site

View File

@@ -14,6 +14,8 @@ import { Logo } from '../../../components/logo'
import router from '@router' import router from '@router'
import globalroutines from '../../../globalroutines/index'
// import {Loading, QSpinnerFacebook, QSpinnerGears} from 'quasar' // import {Loading, QSpinnerFacebook, QSpinnerGears} from 'quasar'
@@ -117,6 +119,7 @@ export default class Signin extends Vue {
.then((riscode) => { .then((riscode) => {
if (riscode === rescodes.OK) { if (riscode === rescodes.OK) {
router.push('/signin') router.push('/signin')
globalroutines(this, 'loadapp', null)
} }
this.checkErrors(riscode) this.checkErrors(riscode)
this.$q.loading.hide() this.$q.loading.hide()