Show Button, when Upgrade Version is available ! (check from the server, the version number

- for debug: added led button to see when is calling the server and the IndexedDb.
This commit is contained in:
Paolo Arena
2019-02-22 10:23:00 +01:00
parent 1623a5c35d
commit 0e98ac1eaa
41 changed files with 1411 additions and 992 deletions

View File

@@ -22,15 +22,6 @@
"loose": false,
"useBuiltIns": "usage"
}
],
[
"@babel/preset-stage-2",
{
"modules": false,
"loose": false,
"useBuiltIns": true,
"decoratorsLegacy": true
}
]
],
"plugins": [

View File

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

View File

@@ -97,7 +97,7 @@
"json-loader": "^0.5.4",
"node-sass": "^4.11.0",
"postcss-loader": "^3.0.0",
"quasar-cli": "^0.17.20",
"quasar-cli": "^0.17.23",
"sass-loader": "^7.1.0",
"strip-ansi": "=3.0.1",
"ts-jest": "^23.0.0",

View File

@@ -150,6 +150,11 @@ module.exports = function (ctx) {
'QDatetime',
'QSlideTransition',
'QTable',
'QTableColumns',
'QTh',
'QTr',
'QSearch',
'QTd',
'QContextMenu',
'QProgress',
'QSlider',
@@ -161,9 +166,9 @@ module.exports = function (ctx) {
],
// Quasar plugins
plugins: [
'Meta',
'Dialog',
'Notify',
'Meta',
'Cookies',
'ActionSheet', 'Loading'
],

View File

@@ -20,6 +20,7 @@ register(process.env.SERVICE_WORKER_FILE, {
},
updatefound(registration) {
console.log('UPDATEFOUND::: New content is downloading.')
// $('#newvers').addClass('btnNewVersShow').removeClass("btnNewVersHide")
},
updated(registration) {
console.log('New content is available; please refresh.')

View File

@@ -26,6 +26,17 @@ export default class App extends Vue {
public listaRoutingNoLogin = ['/vreg?', '/offline']
meta () {
return {
keywords: { name: 'keywords', content: 'WebSite' },
// meta tags
meta: {
mykey: { name: 'mykey', content: 'Key 1' },
keywords: { name: 'keywords', content: 'MyKeywords' }
}
}
}
created() {
if (process.env.DEV) {
console.info('SESSIONE IN SVILUPPO ! (DEV)')

View File

@@ -27,11 +27,38 @@
</q-btn>
<div v-if="$q.platform.is.desktop">
<!--I'm only rendered on desktop!-->
</div>
<div v-if="$q.platform.is.mobile">
<!--I'm only rendered on mobile!-->
</div>
<div v-if="$q.platform.is.electron">
<!--I'm only rendered on Electron!-->
</div>
<q-btn id="newvers" v-if="isNewVersionAvailable" color="secondary" rounded icon="refresh"
class="btnNewVersShow" @click="RefreshApp" :label="$t('notification.newVersionAvailable')"/>
<q-toolbar-title>
{{$t('msg.myAppName')}}
<div slot="subtitle">{{$t('msg.myDescriz')}} {{ getAppVersion() }}</div>
</q-toolbar-title>
<div v-if="isAdmin">
<q-btn flat dense round aria-label="">
<q-icon :class="clCloudUpload" name="cloud_upload"></q-icon>
</q-btn>
<q-btn flat dense round aria-label="">
<q-icon :class="clCloudUp_Indexeddb" name="arrow_upward"></q-icon>
</q-btn>
</div>
<q-btn
flat
dense
@@ -43,6 +70,7 @@
<q-icon v-if="isUserNotAuth" name="device_unknown"></q-icon>
</q-btn>
<q-btn-dropdown
:label="langshort"
>
@@ -117,11 +145,23 @@
public clIconConn: string = 'clIconOnline'
public strConn: string = ''
public langshort: string = ''
public clCloudUpload: string = ''
public clCloudDownload: string = ''
public clCloudUp_Indexeddb: string = ''
public clCloudDown_Indexeddb: string = 'clIndexeddbsend'
get conn_changed() {
return GlobalStore.state.stateConnection
}
get isAdmin() {
return UserStore.state.isAdmin
}
get conndata_changed() {
return GlobalStore.state.connData
}
@Watch('GlobalStore.state.stateConnection', { immediate: true, deep: true })
changeconn(value: string, oldValue: string) {
@@ -135,6 +175,27 @@
}
@Watch('conndata_changed', { immediate: true, deep: true })
changeconnData(value: any, oldValue: any) {
// console.log('CHANGED GlobalStore.state.connData', value)
this.clCloudUpload = (value.uploading_server === 1) ? "clCloudUpload send" : "clCloudUpload"
this.clCloudUpload = (value.downloading_server === 1) ? "clCloudUpload receive" : "clCloudUpload"
this.clCloudUp_Indexeddb = (value.uploading_indexeddb === 1) ? "clIndexeddb send" : "clIndexeddb"
this.clCloudUp_Indexeddb = (value.downloading_indexeddb === 1) ? "clIndexeddb receive" : "clIndexeddb"
this.clCloudUpload = (value.uploading_server === -1) ? "clCloudUpload error" : this.clCloudUpload
this.clCloudUpload = (value.downloading_server === -1) ? "clCloudUpload error" : this.clCloudDownload
this.clCloudUp_Indexeddb = (value.uploading_indexeddb === -1) ? "clIndexeddb error" : this.clCloudUp_Indexeddb
this.clCloudUp_Indexeddb = (value.downloading_indexeddb === -1) ? "clIndexeddb error" : this.clCloudDown_Indexeddb
// console.log('clCloudUpload', this.clCloudUpload)
// console.log('clCloudDownload', this.clCloudDownload)
// console.log('clCloudUp_Indexeddb', this.clCloudUp_Indexeddb)
// console.log('value.downloading_indexeddb', value.downloading_indexeddb)
// console.log('value.uploading_server', value.uploading_server)
}
@Watch('conn_changed', { immediate: true, deep: true })
changeconn_changed(value: string, oldValue: string) {
@@ -157,6 +218,20 @@
}
}
get isNewVersionAvailable() {
console.log('______________ isNewVersionAvailable')
return GlobalStore.getters.isNewVersionAvailable
}
RefreshApp() {
// Unregister Service Worker
navigator.serviceWorker.getRegistrations().then(function(registrations) {
for(let registration of registrations) {
registration.unregister()
} })
window.location.reload(true)
}
changeIconConn() {
this.iconConn = GlobalStore.state.stateConnection === 'online' ? "wifi" : "wifi_off"
this.clIconConn = GlobalStore.state.stateConnection === 'online' ? 'clIconOnline' : 'clIconOffline'
@@ -169,6 +244,35 @@
{ label: 'Spanish', icon: 'fa-flag-es', value: 'esEs', image: '../statics/images/es.png', short: 'ES' }
]
// -------------------------------------------------------------------------
// QUASAR Example using event to open drawer from another component or page
// -------------------------------------------------------------------------
// (1) This code is inside layout file that have a drawer
// if this.leftDrawerOpen is true, drawer is displayed
// (2) Listen for an event in created
/* created(){
this.$root.$on("openLeftDrawer", this.openLeftDrawercb);
},
methods: {
openURL,
// (3) Define the callback in methods
openLeftDrawercb() {
this.leftDrawerOpen = !this.leftDrawerOpen;
}
}
// (4) In another component or page, emit the event!
// Call the method when clicking button etc.
methods: {
openLeftDrawer() {
this.$root.$emit("openLeftDrawer");
}
}
// -------------------------------------------------------------------------
*/
get leftDrawerOpen() {
return GlobalStore.state.leftDrawerOpen
}
@@ -180,7 +284,13 @@
getAppVersion() {
// return "AA"
return "[" + process.env.APP_VERSION + "]"
let strv = ''
if (process.env.DEV) {
strv = 'DEV '
} else if (process.env.TEST) {
strv = 'TEST '
}
return "[" + strv + process.env.APP_VERSION + "]"
}
get lang() {
@@ -188,7 +298,7 @@
}
setshortlang (lang) {
setshortlang(lang) {
for (let indrec in this.selectOpLang) {
if (this.selectOpLang[indrec].value === lang) {
// console.log('this.selectOpLang[indrec].short', this.selectOpLang[indrec].short, this.selectOpLang[indrec].value)
@@ -241,8 +351,7 @@
// this.$q.notify('prima: ' + String(my))
let mylang = rescodes.getItemLS(rescodes.localStorage.lang)
if (mylang === '')
{
if (mylang === '') {
if (navigator) {
mylang = navigator.language
console.log(`LANG2 NAVIGATOR ${mylang}`)
@@ -275,7 +384,7 @@
// Test this by running the code snippet below and then
// use the "Offline" checkbox in DevTools Network panel
// use the "TableOnlyView" checkbox in DevTools Network panel
let mythis = this
// console.log('Event LOAD')
@@ -560,5 +669,47 @@
height: 24px;
}
.clCloudUpload {
transition: all 1s ease-out;
color: initial;
&.send {
transition: all 1s ease-in;
background-color: lightgreen;
}
&.receive {
transition: all 1s ease-in;
background-color: yellow;
}
&.error {
transition: all 1s ease-in;
background-color: red;
}
}
.clIndexeddb {
transition: all 1s ease-out;
color: initial;
&.receive {
transition: all 1s ease-in;
background-color: yellow;
}
&.send {
transition: all 1s ease-in;
background-color: lightgreen;
}
&.error {
transition: all 1s ease-in;
background-color: red;
}
}
.btnNewVersHide {
display: none;
}
.btnNewVersShow {
display: inline-block;
}
</style>

View File

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

View File

@@ -0,0 +1,63 @@
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
import { GlobalStore, UserStore } from '@store'
@Component({})
export default class TableOnlyView extends Vue {
public loading: boolean = false
public serverPagination: {
page: number ,
rowsNumber: number // specifying this determines pagination is server-side
} = {page: 1, rowsNumber: 10}
public serverData: any [] = []
public columns: any[] = [
{
name: 'chiave',
required: true,
label: 'Chiave',
align: 'left',
field: 'chiave',
sortable: true
},
{ name: 'valore', label: 'Valore', field: 'valore', sortable: false }
]
public filter: string = ''
public selected: any[] = []
request(props) {
this.loading = true
setTimeout(() => {
this.serverPagination = props.pagination
let
table = this.$refs.table,
rows = GlobalStore.state.cfgServer.slice(),
{ page, rowsPerPage, sortBy, descending } = props.pagination
// if (props.filter) {
// rows = table.filterMethod(rows, props.filter)
// }
// if (sortBy) {
// rows = table.sortMethod(rows, sortBy, descending)
// }
this.serverPagination.rowsNumber = rows.length
if (rowsPerPage) {
rows = rows.slice((page - 1) * rowsPerPage, page * rowsPerPage)
}
this.serverData = rows
this.loading = false
}, 1500)
}
mounted() {
this.request({
pagination: this.serverPagination,
filter: this.filter
})
}
}

View File

@@ -0,0 +1,29 @@
<template>
<q-page padding class="docs-table">
<p class="caption">TableOnlyView</p>
<q-table
ref="table"
color="primary"
title="Parametri di Configurazione Server"
:data="serverData"
:columns="columns"
:filter="filter"
selection="multiple"
:selected.sync="selected"
row-key="chiave"
:pagination.sync="serverPagination"
@request="request"
:loading="loading"
>
<template slot="top-right" slot-scope="props">
<q-search hide-underline v-model="filter" />
</template>
</q-table>
</q-page>
</template>
<script lang="ts" src="./tableOnlyView.ts">
</script>
<style lang="scss" scoped>
@import './tableOnlyView.scss';
</style>

View File

@@ -0,0 +1,68 @@
import Vue from 'vue'
import { Component, Watch } from 'vue-property-decorator'
import { GlobalStore, UserStore } from '@store'
@Component({})
export default class CfgServer extends Vue {
public loading: boolean = false
public paginationControl: {
page: number,
rowsPerPage: number // specifying this determines pagination is server-side
} = { page: 1, rowsPerPage: 20 }
public pagination: {
page: number
} = {page: 1 }
public serverData: any [] = GlobalStore.state.cfgServer.slice() // [{ chiave: 'chiave1', valore: 'valore 1' }]
public columns: any[] = [
{
name: 'chiave',
required: true,
label: 'Chiave',
align: 'left',
field: 'chiave',
sortable: true
},
{ name: 'valore', label: 'Valore', field: 'valore', sortable: false }
]
public visibleColumns: ['chiave', 'valore']
public separator: 'horizontal'
public filter: string = ''
public selected: any[] = []
public dark: boolean = true
public keysel: string = ''
get tableClass () {
if (this.dark) {
return 'bg-black'
}
}
selItem(item) {
console.log('item', item)
this.keysel = item.chiave
console.log('this.keysel', this.keysel)
}
SaveValue(newVal, valinitial) {
console.log('SaveValue', newVal, 'selected', this.selected)
const mydata = {
chiave: this.keysel,
valore: newVal
}
// Save on Server
GlobalStore.actions.saveCfgServerKey(mydata)
}
created() {
this.serverData = GlobalStore.state.cfgServer.slice() // [{ chiave: 'chiave1', valore: 'valore 1' }]
// this.serverData = GlobalStore.state.cfgServer.slice()
}
}

View File

@@ -0,0 +1,32 @@
<template>
<q-table
:data="serverData"
:columns="columns"
:filter="filter"
title="Configurazione Server"
row-key="chiave"
>
<q-tr slot="body" slot-scope="props" :props="props">
<q-td key="chiave" :props="props">
{{ props.row.chiave }}
<q-popup-edit v-model="props.row.chiave" disable>
<q-field count>
<q-input v-model="props.row.chiave" />
</q-field>
</q-popup-edit>
</q-td>
<q-td key="valore" :props="props">
{{ props.row.valore }}
<q-popup-edit v-model="props.row.valore" title="Aggiorna Valore" buttons @save="SaveValue" @show="selItem(props.row)">
<q-input v-model="props.row.valore"/>
</q-popup-edit>
</q-td>
</q-tr>
</q-table>
</template>
<script lang="ts" src="./cfgServer.ts">
</script>
<style lang="scss" scoped>
@import './cfgServer.scss';
</style>

View File

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

View File

@@ -1,6 +1,6 @@
<template>
<div id="offline">
Offline Page !
TableOnlyView Page !
</div>
</template>
<script lang="ts" src="./offline.ts">

View File

@@ -218,7 +218,7 @@ $heightdescr: 20px;
}
.data-item {
max-width: 85px;
max-width: 84px;
//min-width: 100px;
//display: flex;
//visibility: initial;

View File

@@ -78,6 +78,11 @@ export default class SingleTodo extends Vue {
return date && date.toISOString().split('T')[0]
}
// Computed:
get isSel() {
return this.sel
}
isTodo() {
return this.isTodoByElem(this.itemtodo)
}
@@ -176,8 +181,9 @@ export default class SingleTodo extends Vue {
return 'row flex-container2 ' + this.classRow
}
clickRiga() {
clickRiga(clickmenu: boolean = false) {
// console.log('CLICK RIGA ************')
if (!this.sel) {
if (!this.inEdit) {
this.$emit('deselectAllRows', this.itemtodo, true)
@@ -361,8 +367,9 @@ export default class SingleTodo extends Vue {
}
updatedata() {
console.log('calling this.$emit(eventupdate)')
this.$emit('eventupdate', this.itemtodo)
const myitem = rescodes.jsonCopy(this.itemtodo)
console.log('calling this.$emit(eventupdate)', myitem)
this.$emit('eventupdate', myitem)
}
updateicon() {

View File

@@ -1,13 +1,13 @@
<template>
<div :class="getClassRow()" @click="clickRow">
<div v-if="isTodo()" class="flex-item counter-item dragula-container">{{itemtodo.pos}}</div>
<!--<div v-if="isTodo()" class="flex-item counter-item dragula-container">{{itemtodo.pos}}</div>-->
<!--<div v-if="isFirst">-->
<!--<q-context-menu ref="contextMenu">-->
<!--<SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu" @setPriority="setPriority"></SubMenus>-->
<!--</q-context-menu>-->
<!--</div>-->
<div v-if="isTodo()" class="flex-item completed-item">
<div v-if="isTodo()" class="flex-item completed-item donotdrag">
<q-btn push flat
:class="classCompleted"
:icon="iconCompleted"
@@ -64,11 +64,11 @@
</q-datetime>
</div>
<div v-if="isTodo()" class="flex-item pos-item " @mouseup.left="mouseUp" @mousedown="clickRiga">
<div v-if="isTodo()" class="flex-item pos-item " @mousedown="clickRiga">
<q-btn push
:class="clButtPopover"
icon="menu">
<q-popover v-if="sel" self="top right">
<q-popover id="popmenu" v-if="true" self="top right">
<SubMenus :menuPopupTodo="menuPopupTodo" :itemtodo="itemtodo" @clickMenu="clickMenu"
@setPriority="setPriority"></SubMenus>
</q-popover>

View File

@@ -5,6 +5,11 @@ import { ITodo } from '../../../model/index'
import { rescodes } from '@src/store/Modules/rescodes'
import { UserStore } from '@store'
// Doesn't exist in quasar this ? error TS2305
// import { format } from 'quasar'
// const { between } = format
// import { filter } from 'quasar'
@Component({
name: 'SubMenus'
@@ -26,6 +31,8 @@ export default class SubMenus extends Vue {
}
KeychangeProgress (e) {
// between(50, 10, 20)
if (this.itemtodo.progress > 100) {
this.itemtodo.progress = 100
}

View File

@@ -22,6 +22,8 @@ import globalroutines from '../../../globalroutines/index'
import $ from 'jquery'
import Api from '@api'
import { Getter, State } from 'vuex-class'
import { GetterTree } from 'vuex'
@Component({
@@ -53,6 +55,12 @@ export default class Todo extends Vue {
public service: any
public actualMaxPosition: number = 15
public scrollable = true
public compKey1: number = 0
public compKey2: number = 0
public compKey3: number = 0
// public priorcomplet: number[] = []
public arrFiltered: any [] = []
fieldtochange: String [] = ['descr', 'completed', 'category', 'expiring_at', 'priority', 'id_prev', 'id_next', 'pos', 'enableExpiring', 'progress']
@@ -67,6 +75,8 @@ export default class Todo extends Vue {
console.log('drag = ' + this.drag)
}
// @Getter
@Watch('$route', { immediate: true, deep: true })
onUrlChange(newVal: any) {
@@ -103,7 +113,8 @@ export default class Todo extends Vue {
// Computed:
get showingDataTodo() {
return this.todos_arr.slice(0, this.actualMaxPosition)
// return this.todos_arr.slice(0, this.actualMaxPosition)
return this.arrFiltered
}
@@ -157,7 +168,7 @@ export default class Todo extends Vue {
const myrecs = [...alldata]
myrecs.forEach(rec => {
mystr = mystr + rec.descr + '] ['
mystr = mystr + rec.descr + rec.completed + '] ['
})
mythis.tmpstrTodos = 'TODOS: ' + mystr
@@ -465,7 +476,7 @@ export default class Todo extends Vue {
let mythis = this
if (window) {
window.addEventListener('touchmove', function (e) {
console.log('touchmove')
// console.log('touchmove')
if (!mythis.scrollable) {
e.preventDefault()
}
@@ -515,7 +526,7 @@ export default class Todo extends Vue {
checkUpdate_everytime() {
this.polling = setInterval(() => {
this.checkUpdate()
}, 10000)
}, 60000)
}
initcat() {
@@ -840,6 +851,8 @@ export default class Todo extends Vue {
this.todos_arr = [...arrtemp] // make copy
this.arrFiltered = this.todos_arr.filter((item, index) => index < this.actualMaxPosition)
console.log('AGGIORNA todos_arr [', this.todos_arr.length, ']')
})
@@ -925,10 +938,17 @@ export default class Todo extends Vue {
}
updateitem(myobj) {
console.log('calling MODIFY 4 updateitem')
this.modify(myobj, true)
console.log('calling MODIFY 4 updateitem', myobj)
// Update the others components...
this.compKey1++
this.compKey2++
this.compKey3++
console.log('this.compKey3', this.compKey3)
return this.modify(myobj, true)
}
// inactiveAllButtons() {
// let divs = this.$children.filter(function (child) {
// return child.$attrs['component-type'] === 'my-custom-button'
@@ -988,18 +1008,19 @@ export default class Todo extends Vue {
return new Promise(function (resolve, reject) {
resolve()
})
return await globalroutines(this, 'read', 'todos', null, myobj._id)
const myobjsaved = rescodes.jsonCopy(myobj)
return await globalroutines(this, 'read', 'todos', null, myobjsaved._id)
.then(miorec => {
if (miorec === undefined) {
console.log('~~~~~~~~~~~~~~~~~~~~ !!!!!!!!!!!!!!!!!! Record not Found !!!!!! id=', myobj._id)
console.log('~~~~~~~~~~~~~~~~~~~~ !!!!!!!!!!!!!!!!!! Record not Found !!!!!! id=', myobjsaved._id)
return
}
if (this.modifyField(miorec, myobj, 'completed'))
if (this.modifyField(miorec, myobjsaved, 'completed'))
miorec.completed_at = new Date().getDate()
this.fieldtochange.forEach(field => {
this.modifyField(miorec, myobj, field)
this.modifyField(miorec, myobjsaved, field)
})
@@ -1022,7 +1043,7 @@ export default class Todo extends Vue {
.then(ris => {
// 3) Modify on the Server (call)
return this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS_PATCH, 'PATCH', miorec, update)
this.saveItemToSyncAndDb(rescodes.DB.TABLE_SYNC_TODOS_PATCH, 'PATCH', miorec, update)
})
}

View File

@@ -20,16 +20,16 @@
<!--draggable="true" @dragstart="dragStart(index, $event)" @dragover.prevent @dragenter="dragEnter(index)"-->
<!--@dragleave="dragLeave(index)" @dragend="dragEnd" @drop="dragFinish(index, $event)" >-->
<q-infinite-scroll :handler="loadMoreTodo" :offset="7">
<div class="container" v-dragula="todos_arr" drake="first">
<div class="container" v-dragula="todos_arr" drake="first" :key="compKey3">
<div :id="getmyid(mytodo._id)" :index="index" v-for="(mytodo, index) in showingDataTodo"
:key="mytodo._id" class="myitemdrag">
<div v-if="(prior !== mytodo.priority) && !mytodo.completed"
:class="getTitlePriority(mytodo.priority)">
:class="getTitlePriority(mytodo.priority)" :key="compKey1">
<label>{{getPriorityByInd(mytodo.priority)}}</label>
</div>
<div v-if="(!priorcomplet && mytodo.completed)" class="titleCompleted">
<div v-if="(!priorcomplet && mytodo.completed)" class="titleCompleted" :key="compKey2">
<label>{{$t('todo.completed')}}</label>
<div style="display: none">{{ priorcomplet = true }}</div>
</div>
@@ -54,12 +54,13 @@
v-on:keyup.enter="insertTodo(false)"/>
<!--{{ tmpstrTodos }}-->
<!--<br>-->
<!--<div class="flex-item btn-item">-->
<!--&lt;!&ndash;<div class="flex-item btn-item">&ndash;&gt;-->
<!--<q-btn class="mybtn" round color="" icon="lock" @click="getArrTodos">Get Todo</q-btn>-->
<!--<q-btn class="mybtn" round color="" icon="person" @click="setArrTodos">Set Todo</q-btn>-->
<!--<q-btn class="mybtn" round color="" icon="list" @click="reload_fromServer++">Reload</q-btn>-->
<!--</div>-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<q-input v-model="testPao" float-label="testPao"/>&ndash;&gt;-->
<!--<q-input v-model="todos_changed" float-label="todos_changed"/>-->
@@ -67,8 +68,8 @@
<!--<q-input v-model="reload_fromServer" float-label="reload_fromServer"/>-->
<!--<div class="flex-item btn-item">-->
<!--&lt;!&ndash;<q-btn class="mybtn" round color="" icon="lock" @click="clicktest()"></q-btn>&ndash;&gt;-->
<!--&lt;!&ndash;<q-btn class="mybtn" round color="" icon="person" @click="clicktest2()"></q-btn>&ndash;&gt;-->
<!--<q-btn class="mybtn" round color="" icon="lock" @click="clicktest()"></q-btn>-->
<!--<q-btn class="mybtn" round color="" icon="person" @click="clicktest2()"></q-btn>-->
<!--<q-btn class="mybtn" round color="" icon="list" @click="checkUpdate()"></q-btn>-->
<!--</div>-->

View File

@@ -1,7 +1,24 @@
import indexdb from './indexdb'
import { GlobalStore } from "../store/Modules";
export default async (context, cmd, table, data = null, id = '') => {
const descr = data !== null ? data.descr : ''
// console.log('globalroutines', cmd, table, descr, id)
return await indexdb(context, cmd, table, data, id)
.then(ris => {
setTimeout(function () {
GlobalStore.state.connData.uploading_indexeddb = 0
GlobalStore.state.connData.downloading_indexeddb = 0
}, 1000)
return ris
}
).catch(err => {
setTimeout(function () {
GlobalStore.state.connData.uploading_indexeddb = (GlobalStore.state.connData.uploading_indexeddb === 1) ? -1 : GlobalStore.state.connData.uploading_indexeddb
GlobalStore.state.connData.downloading_indexeddb = (GlobalStore.state.connData.downloading_indexeddb === 1) ? -1 : GlobalStore.state.connData.downloading_indexeddb
}, 1000)
console.log('ERROR INDEXEDDB: ', err)
})
}

View File

@@ -57,23 +57,35 @@ function testfunc2 () {
}
export default async (context, cmd, table, datakey = null, id = '') => {
// console.log('TABLE', table, 'cmd', cmd)
if (cmd === 'loadapp') {
// ****** LOAD APP AL CARICAMENTO ! *******
return saveConfigIndexDb(context, datakey)
} else if (cmd === 'write') {
if (GlobalStore)
GlobalStore.state.connData.uploading_indexeddb = 1
return await storage.setdata(table, datakey)
} else if (cmd === 'updatefromIndexedDbToStateTodo') {
return await readfromIndexDbToStateTodos(context, table)
} else if (cmd === 'readall') {
if (GlobalStore)
GlobalStore.state.connData.downloading_indexeddb = 1
return await storage.getalldata(table)
} else if (cmd === 'count') {
return await storage.count(table)
} else if (cmd === 'read') {
if (GlobalStore)
GlobalStore.state.connData.downloading_indexeddb = 1
return await storage.getdata(table, id)
} else if (cmd === 'delete') {
if (GlobalStore)
GlobalStore.state.connData.uploading_indexeddb = 1
return await storage.deletedata(table, id)
} else if (cmd === 'clearalldata') {
if (GlobalStore)
GlobalStore.state.connData.uploading_indexeddb = 1
return await storage.clearalldata(table)
} else if (cmd === 'log') {
consolelogpao(table)

View File

@@ -19,16 +19,6 @@
<script src="/statics/js/fetch.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 href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

View File

@@ -17,6 +17,7 @@
</div>
</div>
<menu-one :links="links"></menu-one>
<!--<footer>
@@ -55,8 +56,6 @@
links
created() {
// console.log('Drawer created...')
let listatodo = []
this.arrlista.forEach((elem: ITodoList) => {
@@ -65,30 +64,43 @@
})
this.links = {
Dashboard: {
routes: [
{ route: '/', faIcon: 'fa fa-home', materialIcon: 'home', name: 'pages.home' },
{
route: '/todo', faIcon: 'fa fa-list-alt', materialIcon: 'todo', name: 'pages.Todo',
routes2: listatodo
},
{ route: '/category', faIcon: 'fa fa-list-alt', materialIcon: 'category', name: 'pages.Category' },
{ route: '/signup', faIcon: 'fa fa-registered', materialIcon: 'home', name: 'pages.SignUp' },
{ route: '/signin', faIcon: 'fa fa-anchor', materialIcon: 'home', name: 'pages.SignIn' },
/* {route: '/vreg?idlink=aaa', faIcon: 'fa fa-login', materialIcon: 'login', name: 'pages.vreg'},*/
],
show: true,
if (UserStore.state.isAdmin) {
this.links = {
Dashboard: {
routes: [
{ route: '/', faIcon: 'fa fa-home', materialIcon: 'home', name: 'pages.home' },
{
route: '/todo', faIcon: 'fa fa-list-alt', materialIcon: 'todo', name: 'pages.Todo',
routes2: listatodo
},
{ route: '/category', faIcon: 'fa fa-list-alt', materialIcon: 'category', name: 'pages.Category' },
{ route: '/signup', faIcon: 'fa fa-registered', materialIcon: 'home', name: 'pages.SignUp' },
{ route: '/admin/cfgserv', faIcon: 'fa fa-database', materialIcon: 'admin', name: 'pages.Admin' },
{ route: '/signin', faIcon: 'fa fa-anchor', materialIcon: 'home', name: 'pages.SignIn' },
/* {route: '/vreg?idlink=aaa', faIcon: 'fa fa-login', materialIcon: 'login', name: 'pages.vreg'},*/
],
show: true,
}
}
} else {
// Normal USER:
this.links = {
Dashboard: {
routes: [
{ route: '/', faIcon: 'fa fa-home', materialIcon: 'home', name: 'pages.home' },
{
route: '/todo', faIcon: 'fa fa-list-alt', materialIcon: 'todo', name: 'pages.Todo',
routes2: listatodo
},
{ route: '/signup', faIcon: 'fa fa-registered', materialIcon: 'home', name: 'pages.SignUp' },
{ route: '/signin', faIcon: 'fa fa-anchor', materialIcon: 'home', name: 'pages.SignIn' },
],
show: true,
}
}
// ,
// Forms: {
// routes: [
// { route: '/prec', faIcon: 'fa fa-search', materialIcon: 'search', name: 'pages.Test' },
// ],
// show: false
// },
}
}

View File

@@ -2,6 +2,18 @@ export interface IPost {
title: string
}
export interface IConnData {
downloading_server: number
downloading_indexeddb: number
uploading_server: number
uploading_indexeddb: number
}
export interface ICfgServer {
chiave: string
valore: string
}
export type StateConnection = 'online' | 'offline'
export interface IGlobalState {
@@ -15,6 +27,9 @@ export interface IGlobalState {
leftDrawerOpen: boolean
category: string
stateConnection: string
networkDataReceived: boolean
cfgServer: ICfgServer[]
connData: IConnData
posts: IPost[]
listatodo: ITodoList[]
}

View File

@@ -20,7 +20,6 @@ export interface ITodo {
export interface ITodosState {
visuOnlyUncompleted: boolean
networkDataReceived: boolean
todos: ITodo[]
todos_changed: number
reload_fromServer: number

View File

@@ -28,4 +28,5 @@ export interface IUserState {
resStatus?: number
x_auth_token?: string
isLogged?: boolean
isAdmin?: boolean
}

View File

@@ -26,9 +26,24 @@ export default class Home extends Vue {
created() {
// console.log('Home created...')
GlobalStore.actions.prova()
}
meta() {
return {
keywords: { name: 'keywords', content: 'Quasar website' },
// meta tags
meta: {
mykey: { name: 'mykey', content: 'Key 1' },
description: { name: 'description', content: 'Page 1' },
keywords: { name: 'keywords', content: 'Quasar website' },
equiv: { 'http-equiv': 'Content-Type', content: 'text/html; charset=UTF-8' }
}
}
}
mystilecard() {
return {
visibility: this.cardvisible,
@@ -70,7 +85,7 @@ export default class Home extends Vue {
return Notification.permission
}
NotServiceWorker () {
NotServiceWorker() {
return (!('serviceWorker' in navigator))
}
@@ -157,6 +172,8 @@ export default class Home extends Vue {
}
}
askfornotification() {
this.showNotif(this.$t('notification.waitingconfirm'), 'positive', 'notifications')

View File

@@ -7,6 +7,8 @@
<!--<q-btn v-if="getPermission() === 'granted'" class="enable-notifications" color="secondary" rounded size="lg" icon="notifications" @click="createPushSubscription" label="Create Push Subscription !"/>-->
<br>
<div>
<q-chip square color="secondary">

View File

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

View File

@@ -30,6 +30,7 @@ const messages = {
personal: 'Personale',
work: 'Lavoro',
shopping: 'Spesa',
Admin: 'Admin',
},
components: {
authentication:{
@@ -122,7 +123,8 @@ const messages = {
titlegranted: 'Permesso Notifiche Abilitato!',
titledenied: 'Permesso Notifiche Disabilitato!',
title_subscribed: 'Sottoscrizione a FreePlanet.app!',
subscribed: 'Ora potrai ricevere i messaggi e le notifiche.'
subscribed: 'Ora potrai ricevere i messaggi e le notifiche.',
newVersionAvailable: 'Nuova Versione!'
},
connection: 'Connessione',
},
@@ -157,6 +159,7 @@ const messages = {
personal: 'Personal',
work: 'Trabajo',
shopping: 'Compras',
Admin: 'Administración',
},
components: {
authentication:{
@@ -249,7 +252,8 @@ const messages = {
titlegranted: 'Notificaciones permitidas habilitadas!',
titledenied: 'Notificaciones permitidas deshabilitadas!',
title_subscribed: 'Suscripción a FreePlanet.app!',
subscribed: 'Ahora puedes recibir mensajes y notificaciones.'
subscribed: 'Ahora puedes recibir mensajes y notificaciones.',
newVersionAvailable: 'Nueva Versión!'
},
connection: 'Connection',
},
@@ -284,6 +288,7 @@ const messages = {
personal: 'Personal',
work: 'Work',
shopping: 'Shopping',
Admin: 'Admin',
},
components: {
authentication:{
@@ -376,7 +381,8 @@ const messages = {
titlegranted: 'Notification Permission Granted!',
titledenied: 'Notification Permission Denied!',
title_subscribed: 'Subscribed to FreePlanet.app!',
subscribed: 'You can now receive Notification and Messages.'
subscribed: 'You can now receive Notification and Messages.',
newVersionAvailable: 'New Version!'
},
connection: 'Conexión',
},

View File

@@ -15,6 +15,8 @@ async function sendRequest(url: string, method: string, mydata: any) {
request = Api.Delete(url, mydata)
else if (method === 'PUT')
request = Api.put(url, mydata)
else if (method === 'PATCH')
request = Api.patch(url, mydata)
const req: Promise<Types.AxiosSuccess | Types.AxiosError> = request
return req

View File

@@ -42,7 +42,7 @@ async function Request(type: string, path: string, payload: any, setAuthToken?:
try {
console.log(`Axios Request [${type}]:`, axiosInstance.defaults)
let response: AxiosResponse
if (type === 'post' || type === 'put') {
if (type === 'post' || type === 'put' || type === 'patch') {
response = await axiosInstance[type](path, payload, {
headers: {
'Content-Type': 'application/json',
@@ -107,6 +107,11 @@ async function Request(type: string, path: string, payload: any, setAuthToken?:
}
}
catch (error) {
setTimeout(function () {
GlobalStore.state.connData.uploading_server = (GlobalStore.state.connData.uploading_server === 1) ? -1 : GlobalStore.state.connData.uploading_server
GlobalStore.state.connData.downloading_server = (GlobalStore.state.connData.downloading_server === 1) ? -1 : GlobalStore.state.connData.downloading_server
}, 1000)
if (process.env.DEV) {
console.log('ERROR using', path)
// console.log('Error received: ', error)

View File

@@ -19,22 +19,35 @@ import * as Types from "@src/store/Api/ApiTypes"
// const algoliaApi = new AlgoliaSearch()
export namespace ApiTool {
export async function post(path: string, payload?: any) {
GlobalStore.state.connData.downloading_server = 1
GlobalStore.state.connData.uploading_server = 1
return await Request('post', path, payload)
}
export async function postFormData(path: string, payload?: any) {
GlobalStore.state.connData.uploading_server = 1
GlobalStore.state.connData.downloading_server = 1
return await Request('postFormData', path, payload)
}
export async function get(path: string, payload?: any) {
GlobalStore.state.connData.downloading_server = 1
GlobalStore.state.connData.uploading_server = 0
return await Request('get', path, payload)
}
export async function put(path: string, payload?: any) {
GlobalStore.state.connData.uploading_server = 1
return await Request('put', path, payload)
}
export async function patch(path: string, payload?: any) {
GlobalStore.state.connData.uploading_server = 1
return await Request('patch', path, payload)
}
export async function Delete(path: string, payload: any) {
GlobalStore.state.connData.uploading_server = 1
return await Request('delete', path, payload)
}
@@ -53,10 +66,21 @@ export namespace ApiTool {
UserStore.mutations.setResStatus(0)
return await new Promise(function (resolve, reject) {
return sendRequest(url, method, mydata)
.then(res => {
// console.log('res', res)
setTimeout(function () {
if (method === 'get')
GlobalStore.state.connData.downloading_server = 0
else {
GlobalStore.state.connData.uploading_server = 0
GlobalStore.state.connData.downloading_server = 0
}
}, 1000)
UserStore.mutations.setResStatus(res.status)
if (res.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
// Forbidden
@@ -71,6 +95,15 @@ export namespace ApiTool {
})
.catch(error => {
setTimeout(function () {
if (method === 'get')
GlobalStore.state.connData.downloading_server = -1
else {
GlobalStore.state.connData.uploading_server = -1
GlobalStore.state.connData.downloading_server = -1
}
}, 1000)
console.log('error', error)
return reject(error)
})
@@ -92,10 +125,10 @@ export namespace ApiTool {
if (cmd === 'sync-todos') {
// console.log('[Alternative] Syncing', cmd, table, method)
const headers = new Headers()
headers.append('content-Type', 'application/json')
headers.append('Accept', 'application/json')
headers.append('x-auth', token)
// const headers = new Headers()
// headers.append('content-Type', 'application/json')
// headers.append('Accept', 'application/json')
// headers.append('x-auth', token)
let errorfromserver = false
let lettoqualcosa = false
@@ -108,21 +141,23 @@ export namespace ApiTool {
const promises = myrecs.map(rec => {
// console.log('syncing', table, '', rec.descr)
let link = String(process.env.MONGODB_HOST) + '/todos'
// let link = String(process.env.MONGODB_HOST) + '/todos'
let link = '/todos'
if (method !== 'POST')
link += '/' + rec._id
// console.log(' [Alternative] ++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:')
console.log(' [Alternative] ++++++++++++++++++ SYNCING !!!! ', rec.descr, table, 'FETCH: ', method, link, 'data:')
// Insert/Delete/Update table to the server
return fetch(link, {
method: method,
headers: headers,
cache: 'no-cache',
mode: 'cors', // 'no-cors',
body: JSON.stringify(rec)
})
return SendReq(link, method, rec)
// return fetch(link, {
// method: method,
// headers: headers,
// cache: 'no-cache',
// mode: 'cors', // 'no-cors',
// body: JSON.stringify(rec)
// })
.then(() => {
lettoqualcosa = true
return globalroutines(null, 'delete', table, null, rec._id)

View File

@@ -1,4 +1,4 @@
import { IGlobalState, StateConnection } from 'model'
import { ICfgServer, IGlobalState, StateConnection } from 'model'
import { storeBuilder } from './Store/Store'
import Vue from 'vue'
@@ -8,10 +8,10 @@ import translate from './../../globalroutines/util'
import urlBase64ToUint8Array from '../../js/utility'
import messages from '../../statics/i18n'
import { GlobalStore, UserStore } from '@store'
import { GlobalStore, Todos, UserStore } from '@store'
import globalroutines from './../../globalroutines/index'
import Api from "@api"
import { rescodes } from "@src/store/Modules/rescodes"
import Api from '@api'
import { rescodes } from '@src/store/Modules/rescodes'
const allTables = ['todos', 'sync_todos', 'sync_todos_patch', 'delete_todos', 'config', 'swmsg']
const allTablesAfterLogin = ['todos', 'sync_todos', 'sync_todos_patch', 'delete_todos', 'config', 'swmsg']
@@ -42,13 +42,21 @@ const state: IGlobalState = {
menuCollapse: true,
leftDrawerOpen: true,
stateConnection: stateConnDefault,
networkDataReceived: false,
cfgServer: [],
category: 'personal',
posts: [],
listatodo: [
{ namecat: 'personal', description: 'personal' },
{ namecat: 'work', description: 'work' },
{ namecat: 'shopping', description: 'shopping' }
]
],
connData: {
uploading_server: 0,
uploading_indexeddb: 0,
downloading_server: 0,
downloading_indexeddb: 0
}
}
@@ -75,7 +83,19 @@ namespace Getters {
},
get isOnline() {
console.log('*********************** isOnline')
return state.stateConnection === 'online'
},
get isNewVersionAvailable() {
console.log('state.cfgServer', state.cfgServer)
const serversrec = state.cfgServer.find(x => x.chiave === rescodes.SERVKEY_VERS)
console.log('Record ', serversrec)
if (serversrec) {
console.log('Vers Server ', serversrec.valore, 'Vers locale:', process.env.APP_VERSION)
return serversrec.valore !== process.env.APP_VERSION
} else
return false
}
}
}
@@ -197,7 +217,7 @@ namespace Actions {
others: {
userId: UserStore.state.userId,
access: UserStore.state.tokens[0].access
},
}
}
return Api.SendReq('/subscribe', 'POST', myres)
@@ -253,7 +273,7 @@ namespace Actions {
console.log('clearDataAfterLogout')
// Clear all data from the IndexedDB
for (const table of allTables){
for (const table of allTables) {
await globalroutines(null, 'clearalldata', table, null)
}
@@ -295,6 +315,47 @@ namespace Actions {
actions.clearDataAfterLoginOnlyIfActiveConnection()
}
async function saveCfgServerKey(context, dataval: ICfgServer) {
console.log('saveCfgServerKey dataval', dataval)
let ris = await Api.SendReq('/admin/updateval', 'POST', {pairval: dataval})
.then(res => {
})
}
async function checkUpdates(context) {
console.log('checkUpdates')
// if (UserStore.state.userId === '')
// return false // Login not made
state.networkDataReceived = false
let ris = await Api.SendReq('/checkupdates', 'GET', null)
.then(res => {
state.networkDataReceived = true
console.log('******* checkUpdates RES :', res.data.cfgServer)
if (res.data.cfgServer) {
state.cfgServer = [...res.data.cfgServer]
console.log('res.data.cfgServer', res.data.cfgServer)
// Todos.mutations.setTodos_changed()
}
// console.log('********** res', 'state.todos', state.todos, 'checkPending', checkPending)
// After Login will store into the indexedDb...
return res
})
.catch(error => {
console.log('error checkUpdates', error)
UserStore.mutations.setErrorCatch(error)
return error
})
}
export const actions = {
setConta: b.dispatch(setConta),
@@ -302,7 +363,9 @@ namespace Actions {
loadAfterLogin: b.dispatch(loadAfterLogin),
clearDataAfterLogout: b.dispatch(clearDataAfterLogout),
clearDataAfterLoginOnlyIfActiveConnection: b.dispatch(clearDataAfterLoginOnlyIfActiveConnection),
prova: b.dispatch(prova)
prova: b.dispatch(prova),
saveCfgServerKey: b.dispatch(saveCfgServerKey),
checkUpdates: b.dispatch(checkUpdates)
}
}

View File

@@ -11,7 +11,6 @@ import { serv_constants } from '@src/store/Modules/serv_constants'
const state: ITodosState = {
visuOnlyUncompleted: false,
networkDataReceived: false,
todos: [],
todos_changed: 1,
reload_fromServer: 0,
@@ -162,14 +161,15 @@ namespace Actions {
})
}
async function waitAndcheckPendingMsg(context) {
await aspettansec(1000)
// await aspettansec(1000)
return await checkPendingMsg(context)
.then(ris => {
if (ris) {
console.log('risPending = ', ris)
// console.log('risPending = ', ris)
return sendSwMsgIfAvailable()
.then(something => {
if (something) {
@@ -184,7 +184,7 @@ namespace Actions {
}
async function waitAndRefreshData(context) {
await aspettansec(3000)
// await aspettansec(3000)
return await dbLoadTodo(context, false)
}
@@ -214,7 +214,7 @@ namespace Actions {
return globalroutines(null, 'count', 'swmsg')
.then(function (count) {
if (count > 0) {
console.log('count = ', count)
// console.log('count = ', count)
return resolve(true)
} else {
return resolve(false)
@@ -234,11 +234,11 @@ namespace Actions {
if (UserStore.state.userId === '')
return false // Login not made
state.networkDataReceived = false
GlobalStore.state.networkDataReceived = false
let ris = await Api.SendReq('/todos/' + UserStore.state.userId, 'GET', null)
.then(res => {
state.networkDataReceived = true
GlobalStore.state.networkDataReceived = true
// console.log('******* UPDATE TODOS.STATE.TODOS !:', res.todos)
if (res.data.todos) {
@@ -260,7 +260,7 @@ namespace Actions {
// console.log('ris : ', ris)
// console.log('ris STATUS: ', ris.status)
if (!Todos.state.networkDataReceived) {
if (!GlobalStore.state.networkDataReceived) {
if (ris.status === serv_constants.RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN) {
consolelogpao('UNAUTHORIZING... TOKEN EXPIRED... !! ')
@@ -379,7 +379,7 @@ namespace Actions {
updatefromIndexedDbToStateTodo: b.dispatch(updatefromIndexedDbToStateTodo),
getTodosByCategory: b.dispatch(getTodosByCategory),
checkPendingMsg: b.dispatch(checkPendingMsg),
waitAndcheckPendingMsg: b.dispatch(waitAndcheckPendingMsg)
waitAndcheckPendingMsg: b.dispatch(waitAndcheckPendingMsg),
}
}

View File

@@ -10,7 +10,7 @@ import { GlobalStore, UserStore, Todos } from '@store'
import globalroutines from './../../globalroutines/index'
import translate from './../../globalroutines/util'
import * as Types from "@src/store/Api/ApiTypes"
import * as Types from '@src/store/Api/ApiTypes'
const bcrypt = require('bcryptjs')
@@ -27,7 +27,8 @@ const state: IUserState = {
verified_email: false,
categorySel: 'personal',
servercode: 0,
x_auth_token: ''
x_auth_token: '',
isAdmin: false
}
@@ -84,13 +85,23 @@ namespace Getters {
namespace Mutations {
function authUser(state, data: IUserState) {
function authUser(state: IUserState, data: IUserState ) {
state.userId = data.userId
state.username = data.username
state.verified_email = data.verified_email
state.category = data.categorySel
if (data.verified_email)
state.verified_email = data.verified_email
if (data.categorySel)
state.categorySel = data.categorySel // ??
resetArrToken(state.tokens)
state.tokens.push({ access: 'auth', token: state.x_auth_token, date_login: new Date() })
state.tokens.push({ access: 'auth', token: state.x_auth_token, data_login: new Date() })
// ++Todo: Settings Users Admin
if (state.username === 'paoloar77')
state.isAdmin = true
// console.log('state.tokens', state.tokens)
}
@@ -501,6 +512,7 @@ namespace Actions {
GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(rescodes.localStorage.leftDrawerOpen) === 'true')
GlobalStore.mutations.setCategorySel(localStorage.getItem(rescodes.localStorage.categorySel))
GlobalStore.actions.checkUpdates()
await GlobalStore.actions.loadAfterLogin()
.then(() => {

View File

@@ -11,6 +11,8 @@ export const rescodes = {
LIST_END: '10000000',
LIST_START: '0',
SERVKEY_VERS: 'vers',
localStorage: {
verified_email: 'vf',
wasAlreadySubOnDb: 'sb',

1581
yarn.lock

File diff suppressed because it is too large Load Diff