Notifiche - Tutti - non letti

This commit is contained in:
Paolo Arena
2022-07-21 00:20:48 +02:00
parent 7006d62cae
commit 6ae82f14cc
41 changed files with 640 additions and 135 deletions

View File

@@ -854,26 +854,68 @@ export const shared_consts = {
NEW_ADV_CITY: 2,
NEW_ADV_MY_GROUPS: 4,
NEW_ADV_MY_RIS_CIRCUIT: 8,
},
typeNotifs: [
{
value: 1, //
labeltrans: 'typenotifs.new_rec_bacheca',
descr: 'typenotifs.new_rec_bacheca_descr',
},
{
value: 2, //
labeltrans: 'typenotifs.events',
descr: 'typenotifs.events_descr',
},
{
value: 3, //
labeltrans: 'typenotifs.friends',
descr: 'typenotifs.friends_descr',
},
{
value: 4, //
labeltrans: 'typenotifs.circuits',
descr: 'typenotifs.circuits_descr',
},
{
value: 5, //
labeltrans: 'typenotifs.booking',
descr: '',
},
],
UsersNotif_Adv_List: [
{
value: 1, // NEW_ADV_PROVINCE
label: 'notifs.warn_province',
labeltrans: 'notifs.warn_province',
directory: 1,
},
{
value: 2, // NEW_ADV_CITY
label: 'notifs.warn_city',
labeltrans: 'notifs.warn_city',
directory: 1,
},
{
value: 4, // NEW_ADV_MY_GROUPS
label: 'notifs.warn_my_groups',
labeltrans: 'notifs.warn_my_groups',
directory: 1,
},
{
value: 8, // NEW_ADV_MY_RIS_CIRCUIT
label: 'notifs.warn_my_ris_circuit',
labeltrans: 'notifs.warn_my_ris_circuit',
directory: 1,
},
{
value: 1, //
labeltrans: 'notifs.new_event',
directory: 2,
},
{
value: 1, //
labeltrans: 'notifs.new_friends',
directory: 3,
},
],

View File

@@ -16,12 +16,12 @@ export default defineComponent({
required: true,
},
myvalue: {
type: String,
type: [String, Number ],
required: false,
default: '',
},
mydate: {
type: Date,
type: [Date, String],
required: false,
default: null,
},

View File

@@ -17,6 +17,7 @@
<span v-if="mydate">
<CDateTime
v-model:value="mydate"
label=""
:canEdit="false">
</CDateTime>
</span>

View File

@@ -164,6 +164,7 @@ export default defineComponent({
} else {
if (tools.isBitActive(myval.value, rec[props.optval])) {
// console.log('rec', rec, 'props.optlab', props.optlab)
const mydata = {
label: t(tools.getValueByFunzOrVal(rec, props.optlab)),
value: rec[props.optval],

View File

@@ -6,7 +6,7 @@ import { fieldsTable } from '@store/Modules/fieldsTable'
import { tools } from '@store/Modules/tools'
import { costanti } from '@costanti'
import { CMyPopupEdit } from '@/components/CMyPopupEdit'
import { IColGridTable } from 'model'
import { IColGridTable, IOperators, ISpecialField } from 'model'
import MixinBase from '@/mixins/mixin-base'
@@ -26,6 +26,16 @@ export default defineComponent({
required: false,
default: '',
},
specialField: {
type: Object as PropType<ISpecialField>,
required: false,
default: null,
},
filter: {
type: [String, Function],
required: false,
default: null,
},
indrec: {
type: Number,
required: false,
@@ -128,7 +138,7 @@ export default defineComponent({
console.log('showandsel CMyFieldDb', row, col, newval)
if (newval !== valinitial)
setValDb($q, props.mykey, newval, props.type, props.serv, props.table, props.mysubkey, props.id, props.indrec, props.mysubsubkey)
setValDb($q, props.mykey, newval, props.type, props.serv, props.table, props.mysubkey, props.id, props.indrec, props.mysubsubkey, props.specialField)
}
function withBorder() {

View File

@@ -29,7 +29,9 @@
:table="table"
:title="title"
:field="mykey"
:filter="filter"
:subfield="mysubkey"
:specialField="specialField"
:mysubsubkey="mysubsubkey"
:indrec="indrec"
:type="type"

View File

@@ -6,7 +6,7 @@ import { fieldsTable } from '@store/Modules/fieldsTable'
import { tools } from '@store/Modules/tools'
import { costanti } from '@costanti'
import { CMyPopupEdit } from '@/components/CMyPopupEdit'
import { IColGridTable } from 'model'
import { IColGridTable, ISpecialField } from 'model'
import MixinBase from '@/mixins/mixin-base'
@@ -36,6 +36,11 @@ export default defineComponent({
required: false,
default: '',
},
specialField: {
type: Object as PropType<ISpecialField>,
required: false,
default: null,
},
myimg: {
type: String,
required: false,
@@ -146,7 +151,7 @@ export default defineComponent({
console.log('showandsel CMyFieldDb', row, col, newval)
if (newval !== valinitial)
setValDb($q, mykey.value, newval, props.fieldtype || col.fieldtype, false, props.table, mysubkey.value, props.id, props.indrec, mysubsubkey.value)
setValDb($q, mykey.value, newval, props.fieldtype || col.fieldtype, false, props.table, mysubkey.value, props.id, props.indrec, mysubsubkey.value, props.specialField)
}
function withBorder() {

View File

@@ -3,7 +3,7 @@ import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { IColGridTable, IImgGallery } from 'model'
import { IColGridTable, IImgGallery, ISpecialField } from 'model'
import { CMyChipList } from '../CMyChipList'
import { CDate } from '../CDate'
import { CDateTime } from '../CDateTime'
@@ -89,6 +89,11 @@ export default defineComponent({
required: false,
default: '',
},
specialField: {
type: Object as PropType<ISpecialField>,
required: false,
default: null,
},
serv: {
type: Boolean,
required: false,
@@ -134,6 +139,11 @@ export default defineComponent({
required: false,
default: '',
},
filter: {
type: [String, Function],
required: false,
default: null,
},
field_extra: {
type: String,
required: false,
@@ -231,9 +241,11 @@ export default defineComponent({
// console.table(props)
myvalue.value = getValDb(props.field, props.serv, '', props.table, props.subfield, props.id, props.idmain)
myvalue.value = getValDb(props.field, props.serv, '', props.table, props.subfield, props.id, props.idmain, props.indrec, props.mysubsubkey, props.specialField)
// console.log('myvalue.value', myvalue.value)
col.value.jointable = props.jointable
if (props.filter)
col.value.filter = props.filter
col.value.fieldtype = props.type
col.value.label = props.title
@@ -459,7 +471,7 @@ export default defineComponent({
function savefield(value: any, initialval: any, myq: any) {
if (!props.insertMode) {
myvalue.value = value
setValDb(myq, props.field, myvalue.value, props.type, props.serv, props.table, props.subfield, props.id, props.indrec, props.mysubsubkey)
setValDb(myq, props.field, myvalue.value, props.type, props.serv, props.table, props.subfield, props.id, props.indrec, props.mysubsubkey, props.specialField)
}
}
@@ -474,7 +486,7 @@ export default defineComponent({
else
myvalue.value = value
setValDb($q, props.field, myvalue, props.type, props.serv, props.table, props.subfield, props.id, props.indrec, props.mysubsubkey)
setValDb($q, props.field, myvalue, props.type, props.serv, props.table, props.subfield, props.id, props.indrec, props.mysubsubkey, props.specialField)
}

View File

@@ -0,0 +1,40 @@
import { defineComponent, onMounted, PropType, ref, watch } from 'vue'
import { useQuasar } from 'quasar'
import { useI18n } from '@/boot/i18n'
import { useGlobalStore } from '@store/globalStore'
import { fieldsTable } from '@store/Modules/fieldsTable'
import { tools } from '@store/Modules/tools'
import { costanti } from '@costanti'
import { shared_consts } from '@/common/shared_vuejs'
import { CMyFieldDb } from '@/components/CMyFieldDb'
import { CDateTime } from '@/components/CDateTime'
export default defineComponent({
name: 'CNotifSettings',
props: {
},
components: { CMyFieldDb },
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const globalStore = useGlobalStore()
function mounted() {
//
}
onMounted(mounted)
return {
t,
tools,
costanti,
shared_consts,
fieldsTable,
globalStore,
}
},
})

View File

@@ -0,0 +1,46 @@
<template>
<div class="text-center">
<div class="row items-center justify-center q-gutter-md q-ma-xs">
<q-list bordered class="rounded-borders">
<q-expansion-item v-for="(rec, index) in shared_consts.typeNotifs"
:key="index"
expand-separator
icon="perm_identity"
:label="t(rec.labeltrans)"
>
<q-card>
<q-card-section>
<div>{{ t(rec.descr) }}</div>
<CMyFieldDb
title=""
table="users"
mykey="profile"
mysubkey="notifs"
:specialField="{
findsubkey: (myrec) => myrec.dir === rec.value,
paramtosetsubkey: 'value',
paramdef: rec.value,
defaultnewrec: { dir: rec.value},
}"
jointable="usernotifs"
tablesel="usernotifs"
:filter="(myrec) => myrec.directory === rec.value"
:type="costanti.FieldType.binary">
</CMyFieldDb>
</q-card-section>
</q-card>
</q-expansion-item>
</q-list>
</div>
</div>
</template>
<script lang="ts" src="./CNotifSettings.ts">
</script>
<style lang="scss" scoped>
@import './CNotifSettings.scss';
</style>

View File

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

View File

@@ -55,4 +55,5 @@ export * from './COpenStreetMap'
export * from './COperators'
export * from './CFundRaising'
export * from './CKeyAndValue'
export * from './CNotifSettings'
// export * from './CPreloadImages'

View File

@@ -30,6 +30,7 @@ const msg_website_it = {
myhosps2: 'myhosps2',
mygood2: 'mygood2',
fundraising: 'Sostieni il Progetto',
notifs: 'Configura le Notifiche',
test: 'Test',
projects: 'Progetti',
report: 'Report Ore',

View File

@@ -653,6 +653,17 @@ const baseroutes: IListRoutes[] = [
inmenu: true,
infooter: true,
},
{
active: true,
order: 200,
path: '/notifs',
materialIcon: 'fas fa-user',
name: 'pages.notifs',
component: () => import('@/views/user/usernotifs/usernotifs.vue'),
meta: { requiresAuth: true },
inmenu: false,
infooter: false,
},
{
active: true,
order: 400,

View File

@@ -18,7 +18,7 @@ export default defineComponent({
setup(props) {
const $router = useRouter()
const { getNumMsgUnread, getNumMsg, getUsernameChatByMsg, getImgByMsg, getNumNotifUnread } = MixinUsers()
const { getNumMsgUnread, getNumMsg, getUsernameChatByMsg, getImgByMsg } = MixinUsers()
// function lasts_messages (state: IUserState) => IMessage[] {
//
@@ -73,7 +73,6 @@ export default defineComponent({
getNumMsg,
getUsernameChatByMsg,
getImgByMsg,
getNumNotifUnread,
tools,
}
},

View File

@@ -40,7 +40,7 @@
</q-menu>
</q-btn>
<q-btn v-if="false" flat round dense icon="fas fa-comment">
<q-badge v-if="getNumNotifUnread() > 0" floating color="red">{{getNumNotifUnread()}}</q-badge>
<q-badge v-if="getNumMsgUnread() > 0" floating color="red">{{getNumMsgUnread()}}</q-badge>
</q-btn>
</div>
</template>

View File

@@ -15,3 +15,17 @@
width: 57px;
font-size: 13px;
}
.unread {
font-weight: bold;
}
.read {
color: grey;
}
.my-custom-toggle {
border: 1px solid #027be3;
}

View File

@@ -5,7 +5,6 @@ import {
IMessage, IMsgUsers, INotif,
} from '@model'
import './notifPopover.scss'
import { tools } from '@src/store/Modules/tools'
import { useRouter } from 'vue-router'
@@ -39,7 +38,11 @@ export default defineComponent({
const myuser = ref({})
const lasts_notifs = computed(() => notifStore.getlasts_notifs)
const show_all = ref(true)
const username = computed(() => userStore.my.username)
const lasts_notifs = computed(() => notifStore.getlasts_notifs().filter((rec) => show_all.value ? true : !rec.read))
const num_notifs_unread = computed(() => notifStore.getnumNotifUnread())
const usernotifs = computed(() => userStore.my.profile.notifs)
const userId = ref('')
@@ -50,13 +53,12 @@ export default defineComponent({
datenotif: new Date()
})
const { getNumNotifUnread, getNumNotif, getUsernameChatByNotif, getImgByNotif, getNotifText } = MixinUsers()
const { getNumNotifUnread, getNumNotif, getUsernameChatByNotif, getImgByNotif, getNotifText, getTypeNotif } = MixinUsers()
// function lasts_notifs (state: IUserState) => IMessage[] {
//
// }
watch(() => usernotifs.value, async (to: any, from: any) => {
if (usernotifs.value) {
@@ -70,8 +72,20 @@ export default defineComponent({
}
})
function clickChat(msg: IMessage) {
// $router.replace(`/notifs/${ msg.dest.username}`)
watch(() => userStore.my.username, async (to: any, from: any) => {
if (userStore.my.username) {
await refreshdata(userStore.my.username)
}
})
function clickNotif(notif: INotif) {
if (notif.link) {
let mylink = tools.updateQueryStringParameter(notif.link, 'idnotif', notif._id)
console.log('mylink', mylink, notif._id)
if (mylink) {
$router.replace(mylink)
}
}
}
function getlastnotif(username: string): any {
@@ -98,16 +112,19 @@ export default defineComponent({
}
function refreshdata(username: string) {
async function refreshdata(username: string) {
loading.value = true
userId.value = userStore.my._id
notifsel.value.dest = ''
if (!!username) {
return notifStore.updateNotifDataFromServer({
username,
lastdataread: getlastdataread(username)
}).then((ris) => {
notifsel.value.dest = username
loading.value = false
@@ -120,22 +137,25 @@ export default defineComponent({
loading.value = false
})
}
}
function mounted() {
async function mounted() {
myuser.value = userStore.my
refreshdata(userStore.my.username)
await refreshdata(userStore.my.username)
}
onMounted(mounted)
return {
lasts_notifs,
clickChat,
num_notifs_unread,
clickNotif,
getNumNotifUnread,
getNumNotif,
getUsernameChatByNotif,
getImgByNotif,
getNotifText,
getTypeNotif,
tools,
usernotifs,
shared_consts,
@@ -143,6 +163,10 @@ export default defineComponent({
myuser,
costanti,
open,
notifStore,
show_all,
t,
username,
}
},
})

View File

@@ -1,50 +1,63 @@
<template>
<div>
<q-btn flat round dense icon="fas fa-bell" class="q-mx-xs" @click="open = !open">
<q-badge v-if="getNumNotifUnread() > 0" floating color="red">{{ getNumNotifUnread() }}</q-badge>
<q-badge v-if="num_notifs_unread > 0" floating color="red">{{ num_notifs_unread }}</q-badge>
</q-btn>
<q-btn v-if="false" flat round dense icon="fas fa-bell">
<q-badge v-if="getNumNotifUnread() > 0" floating color="red">{{ getNumNotifUnread() }}</q-badge>
<q-badge v-if="num_notifs_unread > 0" floating color="red">{{ num_notifs_unread }}</q-badge>
</q-btn>
<q-drawer v-model="open" side="right" elevated class="text-black">
<q-bar class="bg-primary text-white">
{{ $t('notifs.notifs') }}
<q-space/>
<q-btn round dense icon="fas fa-pencil-alt" class="q-mx-xs">
<q-menu style="min-width: 200px">
<q-list style="">
<q-item clickable v-close-popup to="/notifs">
<q-item-section side>
<q-icon name="fas fa-cog"/>
</q-item-section>
<q-item-section>{{ $t('notifs.settings') }}</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="notifStore.setAllRead(username)">
<q-item-section side>
<q-icon name="fas fa-check"/>
</q-item-section>
<q-item-section>{{ $t('notifs.setallread') }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
<q-btn flat round color="white" icon="close" @click="open = false"></q-btn>
</q-bar>
<div class="">
<CTitleBanner
class="q-pa-xs"
title="Imposta notifiche"
bgcolor="bg-green" clcolor="text-white"
mystyle="" myclass="myshad" :canopen="true">
<div>
<div>Avvisami se nuovo annuncio:</div>
<CMyFieldDb
title=""
table="users"
mykey="profile"
mysubkey="notifs"
jointable="usernotifs"
tablesel="usernotifs"
:type="costanti.FieldType.binary">
</CMyFieldDb>
<div class="row justify-center margin_buttons q-gutter-lg">
<q-btn-toggle
v-model="show_all"
class="my-custom-toggle"
no-caps
rounded
dense
unelevated
toggle-color="primary"
color="white"
text-color="primary"
:options="[
{label: t('notifs.all'), value: true},
{label: t('notifs.notread'), value: false}
]"
/>
</div>
</CTitleBanner>
</div>
<div class="clBorderSperator"></div>
<div class="q-ma-xs">
<q-list bordered class="rounded-borders">
<div v-if="getNumNotif() === 0">
<div v-if="num_notifs_unread === 0">
<q-item>
<q-item-label lines="1">{{ $t('notifs.nonotif') }}</q-item-label>
@@ -52,30 +65,50 @@
</div>
<q-item clickable v-ripple v-for="(notif, index) in lasts_notifs()" :key="index" @click="clickChat(notif)">
<q-item-section avatar>
<q-avatar>
<q-item-label lines="1">{{ getTypeNotif(notif) }}</q-item-label>
</q-avatar>
</q-item-section>
<q-item clickable v-for="(notif, index) in lasts_notifs" :key="index" @click="clickNotif(notif)">
<!--<q-item-section avatar>
<q-avatar>
<img :src="getImgByNotif(notif)" :alt="getUsernameChatByNotif(notif)">
<q-item-label lines="1">{{ getTypeNotif(notif) }}</q-item-label>
</q-avatar>
</q-item-section>-->
<q-item-section>
<q-item-label lines="1">{{ getUsernameChatByNotif(notif) }}</q-item-label>
<q-item-section avatar>
<q-avatar>
<img :src="getImgByNotif(notif)" :alt="getUsernameChatByNotif(notif)">
</q-avatar>
</q-item-section>
<q-item-section v-ripple >
<q-item-label lines="1" :class="(!notif.read) ? 'unread' : 'read'">{{ getNotifText(notif, false) }}</q-item-label>
<q-item-label caption lines="2">
{{ getNotifText(notif, false) }}
{{ tools.getstrDateTimeShort(notif.datenotif) }}
<!--{{ // getUsernameChatByNotif(notif) }}-->
</q-item-label>
</q-item-section>
<q-item-section side>
<q-item-label>
<q-btn rounded icon="fas fa-pencil-alt">
<q-menu>
<q-list style="min-width: 150px">
<q-item clickable v-close-popup @click="notifStore.deleteRec(notif._id)">
<q-item-section side>
<q-icon name="fas fa-trash-alt"/>
</q-item-section>
<q-item-section>{{ $t('notifs.delete_notif') }}</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="notifStore.deactivateRec(notif._id)">
<q-item-section side>
<q-icon name="fas fa-trash-alt"/>
</q-item-section>
<q-item-section>{{ $t('notifs.deactivate_notif') }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-item-label>
</q-item-section>
<q-item-section side top>
{{ tools.getstrDateTimeShort(notif.datenotif) }}
</q-item-section>
</q-item>
<q-separator/>
</q-list>
@@ -86,3 +119,6 @@
<script lang="ts" src="./notifPopover.ts">
</script>
<style lang="scss" scoped>
@import './notifPopover.scss';
</style>

View File

@@ -8,7 +8,7 @@ import MixinMetaTags from '@src/mixins/mixin-metatags'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { IDataPass } from '@model'
import { IDataPass, ISpecialField } from '@model'
import { tools } from '../store/Modules/tools'
import { costanti } from '@costanti'
import { fieldsTable } from '@store/Modules/fieldsTable'
@@ -28,9 +28,9 @@ export default function () {
return fieldsTable
}
function getValDb(keystr: string, serv: boolean, def?: any, table?: string, subkey?: any, id?: any, idmain?: any, indrec?: number, subsubkey?: string) {
function getValDb(keystr: string, serv: boolean, def?: any, table?: string, subkey?: any, id?: any, idmain?: any, indrec?: number, subsubkey?: string, specialField?: ISpecialField) {
// console.log('getValDb')
return toolsext.getValDb(keystr, serv, def, table, subkey, id, idmain, indrec, subsubkey)
return toolsext.getValDb(keystr, serv, def, table, subkey, id, idmain, indrec, subsubkey, specialField)
}
@@ -40,12 +40,12 @@ export default function () {
return ris
}
async function setValDb($q: any, key: string, value: any, type: any, serv: boolean, table?: string, subkey?: string, id?: any, indrec?: number, subsubkey?: string) {
async function setValDb($q: any, key: string, value: any, type: any, serv: boolean, table?: string, subkey?: string, id?: any, indrec?: number, subsubkey?: string, specialField?: ISpecialField) {
const userStore = useUserStore()
const globalStore = useGlobalStore()
const { t } = useI18n()
console.log('setValDb', key, value, serv, table, subkey, indrec, subsubkey, indrec, subsubkey)
// console.log('setValDb', key, value, serv, table, subkey, indrec, subsubkey, specialField)
let mydatatosave: IDataPass | null = null
if (table === 'users') {
@@ -55,24 +55,51 @@ export default function () {
if (key === 'profile') {
if (subsubkey && indrec) {
if (subsubkey && !!indrec && indrec >= 0) {
// @ts-ignore
userStore.my.profile[subkey][indrec][subsubkey] = value
}else {
} else {
if (!!specialField && subkey) {
// @ts-ignore
const myrec = userStore.my.profile[subkey].filter(specialField.findsubkey)
if (myrec && tools.isArray(myrec) && myrec.length > 0 && !!specialField.paramtosetsubkey) {
myrec[0][specialField.paramtosetsubkey] = value
// console.log('myrec[specialField.paramtosetsubkey]', myrec[0][specialField.paramtosetsubkey], myrec)
// @ts-ignore
} else {
//let mynewrec = tools.getDefaultRecByTableAndSpecialField(table, specialField)
// @ts-ignore
let mynewrec = specialField.defaultnewrec
// @ts-ignore
mynewrec[specialField.paramtosetsubkey] = value
// console.log('mynewrec', mynewrec)
// @ts-ignore
userStore.my.profile[subkey].push(mynewrec)
}
// @ts-ignore
// console.log('saved', userStore.my.profile[subkey])
} else {
// @ts-ignore
userStore.my.profile[subkey] = value
}
}
// Save to the DB:
// @ts-ignore
myfield[`${key}.${subkey}`] = userStore.my.profile[subkey]
} else {
// Save to the DB:
myfield[key] = value
// @ts-ignore
userStore.my[key] = value
}
// Save to the DB:
if (subkey) {
myfield[`${key}.${subkey}`] = value
} else {
myfield[key] = value
}
// console.log('myfield', myfield)
@@ -102,7 +129,7 @@ export default function () {
globalStore.setValueSettingsByKey({ key, value, serv })
let myrec = globalStore.getrecSettingsByKey(key, serv)
console.log('settings... myrec ', myrec, 'key=', key, 'serv', serv)
// console.log('settings... myrec ', myrec, 'key=', key, 'serv', serv)
if (myrec === undefined) {
myrec = {
idapp: process.env.APP_ID,
@@ -128,7 +155,7 @@ export default function () {
},
)
}
console.log('myrec', myrec)
// console.log('myrec', myrec)
mydatatosave = {
// @ts-ignore

View File

@@ -1,5 +1,6 @@
import { IMessage, INotif } from '@src/model'
import { useUserStore } from '@store/UserStore'
import { useNotifStore } from '@store/NotifStore'
import { useGlobalStore } from '@store/globalStore'
import { useProducts } from '@store/Products'
import { serv_constants } from '@store/Modules/serv_constants'
@@ -161,19 +162,18 @@ export default function () {
}
function getNumNotif() {
// ++Todo: conv
/*
return NotifStore.getlasts_messages().length
*/
const notifStore = useNotifStore()
const mynotifs = notifStore.getlasts_notifs
if (!!mynotifs)
return mynotifs.length
return 0
}
function getNumNotifUnread() {
// return userStore.getlasts_messages().length
// ++Todo: conv
// return NotifStore.getnumMsgUnread()
return 0
const notifStore = useNotifStore()
return notifStore.getnumNotifUnread
}
function getUsernameChatByNotif(msg: INotif) {
@@ -198,13 +198,11 @@ export default function () {
return ''
}
function getImgByNotif(msg: INotif) {
function getImgByNotif(notif: INotif) {
const userStore = useUserStore()
const notifStore = useNotifStore()
//++Todo: Notif
return ''
// @ts-ignore
// return `${userStore.getImgByUsername(this.getUsernameChatByMsg(msg))}`
return `${userStore.getImgByUsername(notif.sender)}`
}

View File

@@ -540,6 +540,13 @@ export interface IParamsQuery {
extrapar?: string
}
export interface ISpecialField {
findsubkey?: any
paramtosetsubkey?: any
paramdef?: any
defaultnewrec?: object
}
export interface IColGridTable {
name: string
subfield?: string

View File

@@ -86,6 +86,7 @@ export interface INotif {
descr: string
datenotif?: Date
status?: StatusMessage
link?: string
read?: boolean
deleted?: boolean
}
@@ -108,4 +109,5 @@ export interface IMessageState {
export interface INotifState {
last_notifs: INotif[]
show_all: boolean
}

View File

@@ -35,6 +35,13 @@ export interface ICalcStat {
numByTab: {}
}
export interface IUserNotifType {
_id: number
dir: number
value: number
}
export interface IUserProfile {
img?: string
nationality?: string
@@ -78,7 +85,7 @@ export interface IUserProfile {
req_friends: IFriends[]
mygroups: IMyGroup[]
manage_mygroups: IMyGroup[]
notifs: number
notifs: IUserNotifType[]
// in memory
asked_friends: any[]

View File

@@ -9,9 +9,13 @@ import { static_data } from '@/db/static_data'
import { fieldsTable } from '@src/store/Modules/fieldsTable'
import { shared_consts } from '@/common/shared_vuejs'
import { useUserStore } from '@store/UserStore'
import { DefaultProfile, useUserStore } from '@store/UserStore'
import { costanti } from '@costanti'
import { useQuasar } from 'quasar'
import { useNotifStore } from '@store/NotifStore'
import { INotif } from 'model'
import { IUserFields } from '@model/UserStore'
import { useI18n } from '@/boot/i18n'
export default defineComponent({
name: 'userPanel',
@@ -24,15 +28,28 @@ export default defineComponent({
const search = ref('')
const colVisib = ref('')
const mycolumns = ref([])
const myuser = ref({})
const myuser = ref(<IUserFields>{_id: '', username: '', name: '', surname: '', profile: DefaultProfile})
const risultato = ref('')
const mynotif = ref('')
const mylink = ref('')
const notiftype = ref(1)
const listnotif = ref(<any>[])
const { t } = useI18n();
const userStore = useUserStore()
const notifStore = useNotifStore()
async function mounted() {
//
search.value = tools.getCookie(tools.COOK_SEARCH + 'searchpanel')
await refresh()
listnotif.value = shared_consts.UsersNotif_Adv_List
for (const rec of listnotif.value) {
rec.label = t(rec.labeltrans)
}
}
function changeCol(newval: any) {
@@ -43,7 +60,7 @@ export default defineComponent({
if (!!search.value)
myuser.value = await userStore.loadUserPanel(search.value)
else
myuser.value = {}
myuser.value = {_id: '', username: '', name: '', surname: '', profile: DefaultProfile}
}
@@ -62,6 +79,21 @@ export default defineComponent({
tools.copyStringToClipboard($q, risultato.value, false)
}
async function sendNotifToUser() {
if (!!myuser.value) {
const notif: INotif = {
type: notiftype.value,
sender: userStore.my.username,
dest: myuser.value.username,
descr: mynotif.value,
link: mylink.value,
}
await notifStore.SendNotifEvent(notif)
}
}
onMounted(mounted)
return {
@@ -69,6 +101,7 @@ export default defineComponent({
fieldsTable,
search,
tools,
shared_consts,
doSearch,
changeCol,
myuser,
@@ -76,7 +109,12 @@ export default defineComponent({
mycolumns,
colVisib,
exportListaEmail,
sendNotifToUser,
risultato,
mynotif,
mylink,
notiftype,
listnotif,
}
}
})

View File

@@ -2,7 +2,19 @@
<CMyPage img="" :title="$t('otherpages.admin.userpanel')" keywords="" :description="$t('otherpages.admin.userpanel')">
<q-btn color="green" label="Esporta Lista Email" @click="exportListaEmail"></q-btn>
<q-btn color="green" label="Invia Notifica a " @click="sendNotifToUser"></q-btn>
<div class="q-ma-sm row">
<q-select rounded outlined v-model="notiftype" :options="listnotif" label="Tipo di Notifica" emit-value map-options>
</q-select>
<q-input
v-model="mynotif" type="textarea" autofocus label="Notifica da Inviare"
input-class="myinput-area"
style="height: 100px; width: 500px;"></q-input>
<q-input
v-model="mylink" label="Link"></q-input>
<q-btn color="green" :label="`Invia Notifica a ` + myuser.username" @click="sendNotifToUser"></q-btn>
</div>
<!--<CCopyBtn title="Copia Dati" :texttocopy="risultato"></CCopyBtn>-->

View File

@@ -746,14 +746,33 @@ const msg_it = {
nomessage: 'Nessun Messaggio',
},
notifs: {
all: 'Tutte',
notread: 'Non lette',
settings: 'Configura Notifiche',
setallread: 'Segna tutte come già lette',
telegrammsg: 'Telegram',
notif: 'Notifica',
notifs: 'Notifiche',
nonotif: 'Nessuna Notifica',
nonotif: 'Nessuna Nuova Notifica',
warn_province: 'in Provincia',
warn_city: 'in Città',
warn_my_groups: 'miei Gruppi',
warn_my_ris_circuit: 'miei Circuiti',
new_event: 'Nuovo Evento',
new_friends: 'Nuove Richieste di Amicizia',
delete_notif: 'Elimina questa notifica',
deactivate_notif: 'Smetti di ricevere notifiche come questa',
},
typenotifs: {
new_rec_bacheca: 'Annunci',
new_rec_bacheca_descr: 'Avvisami se vengono aggiunti nuovi Annunci',
friends: 'Richieste di Amicizia',
friends_descr: 'Avvisami se:',
events: 'Eventi',
events_descr: 'Avvisami se vengono aggiunti nuovi Eventi',
circuits: 'Circuiti',
circuits_descr: 'Avvisami:',
booking: 'Prenotazioni',
},
event: {
_id: 'id',

View File

@@ -265,6 +265,7 @@ export const costanti = {
username_chip: 12000,
link: 12500,
listobj: 13000,
},
FieldTypeArr: [
@@ -276,6 +277,11 @@ export const costanti = {
{ label: 'Select', value: 32 },
{ label: 'Number', value: 64 },
{ label: 'crypted', value: 9000 },
{ label: 'object', value: 10000 },
{ label: 'separator', value: 11000 },
{ label: 'username_chip', value: 12000 },
{ label: 'link', value: 12500 },
{ label: 'listobj', value: 13000 },
],
TipoVisu: {

View File

@@ -1598,6 +1598,11 @@ const colTableGeneric = [
AddCol({ name: 'label', label_trans: 'proj.longdescr' }),
]
const colTableGenTrans = [
AddCol({ name: 'value', label_trans: 'others.value' }),
AddCol({ name: 'labeltrans', label_trans: 'proj.longdescr' }),
]
export const colTableOperator = [
AddCol({ name: 'username', label_trans: 'reg.username_short' }),
AddCol({ name: 'name', label_trans: 'reg.name' }),
@@ -2710,9 +2715,18 @@ export const fieldsTable = {
{
value: 'usernotifs',
label: 'Notifiche',
columns: colTableGeneric,
columns: colTableGenTrans,
colkey: 'value',
collabel: 'label',
collabel: 'labeltrans',
colicon: 'icon',
noshow: true,
},
{
value: 'typenotifs',
label: 'Tipi di Notifiche',
columns: colTableGenTrans,
colkey: 'value',
collabel: 'labeltrans',
colicon: 'icon',
noshow: true,
},

View File

@@ -12,7 +12,7 @@ import {
ITodo,
IUserFields,
Privacy,
TipoVisu, IGroup, IMySkill, IMyBacheca, IImgGallery, IMsgGlobParam, IUserExport,
TipoVisu, IGroup, IMySkill, IMyBacheca, IImgGallery, IMsgGlobParam, IUserExport, ISpecialField,
} from '@model'
import { addToDate } from '@quasar/quasar-ui-qcalendar'
@@ -3527,7 +3527,7 @@ export const tools = {
},
getValDb(keystr: string, serv: boolean, def?: any, table?: string, subkey?: any, id?: any, idmain?: any): any {
getValDb(keystr: string, serv: boolean, def?: any, table?: string, subkey?: any, id?: any, idmain?: any, specialField?: ISpecialField): any {
const globalStore = useGlobalStore()
const todos = useTodoStore()
const userStore = useUserStore()
@@ -5544,7 +5544,17 @@ export const tools = {
return myval
}
},
updateQueryStringParameter(uri: string, key: string, value: string) {
const re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i')
const separator = uri.indexOf('?') !== -1 ? '&' : '?'
if (uri.match(re)) {
return uri.replace(re, '$1' + key + '=' + value + '$2')
} else {
return uri + separator + key + '=' + value
}
},
// getLocale() {

View File

@@ -5,6 +5,7 @@ import { static_data } from '@/db/static_data'
import { useGlobalStore } from '@store/globalStore'
import { useTodoStore } from '@store/Todos'
import { Router } from 'vue-router'
import { ISpecialField } from 'model'
export const func_tools = {
getLocale(vero ?: boolean): string {
@@ -155,7 +156,7 @@ export const toolsext = {
// this.$q.lang.set(mylang)
},
getValDb(keystr: string, serv: boolean, def?: any, table?: string, subkey?: string, id?: any, idmain?: any, indrec?: number, subsubkey?: string): any | undefined {
getValDb(keystr: string, serv: boolean, def?: any, table?: string, subkey?: string, id?: any, idmain?: any, indrec?: number, subsubkey?: string, specialField?: ISpecialField): any | undefined {
const todos = useTodoStore()
const userStore = useUserStore()
@@ -168,10 +169,25 @@ export const toolsext = {
// @ts-ignore
return userStore.my.profile[subkey][indrec][subsubkey]
} else {
if (specialField && specialField.findsubkey && !!subkey) {
// @ts-ignore
const myrec = userStore.my.profile[subkey].filter(specialField.findsubkey)
// console.log('loaded', myrec)
if (myrec && myrec.length > 0 && !!specialField.paramtosetsubkey) {
// @ts-ignore
return myrec[0][specialField.paramtosetsubkey]
} else {
return ''
}
} else {
// @ts-ignore
return userStore.my.profile[subkey]
}
}
}
} else if (keystr) { // @ts-ignore
// @ts-ignore
return userStore.my[keystr]

View File

@@ -12,19 +12,21 @@ import { useUserStore } from '@store/UserStore'
export const useNotifStore = defineStore('NotifStore', {
state: (): INotifState => ({
last_notifs: [],
show_all: true
}),
getters: {
getlasts_notifs: (mystate: INotifState) => (): INotif[] => {
const ctrec = (mystate.last_notifs) ? mystate.last_notifs.slice(0, 5) : []
const ctrec = (mystate.last_notifs) ? mystate.last_notifs.slice(0, 5).filter((rec) => mystate.show_all ? true : !rec.read) : []
// const ctrec = (mystate.notifs) ? mystate.notifs.slice().reverse().slice(0, 5) : []
return (ctrec)
},
getnumNotifUnread: (mystate: INotifState) => () => {
return mystate.last_notifs.filter((notif) => !notif.read).length
const myarr = mystate.last_notifs.filter((notif) => !notif.read)
return (tools.isArray(myarr) ? myarr.length : 0)
},
},
@@ -37,12 +39,50 @@ export const useNotifStore = defineStore('NotifStore', {
}
},
setAsRead(idnotif: string) {
const rec = this.last_notifs.find((rec: any) => rec._id === idnotif)
if (rec) {
rec.read = true
}
},
setAllRead(username: string) {
return Api.SendReq(`/sendnotif/setall/${username}/${process.env.APP_ID}`, 'GET', null)
.then((res) => {
// console.log('res', res)
if (res) {
for (const rec of this.last_notifs) {
rec.read = true
}
}
})
.catch((error) => {
console.error(error)
return false
})
},
deleteRec(id: string) {
},
deactivateRec(id: string) {
},
async updateNotifDataFromServer({ username, lastdataread }: {username: string, lastdataread: Date}) {
// console.log('updateNotifDataFromServer', username, lastdataread)
return Api.SendReq(`/sendnotif/${username}/${lastdataread}/${process.env.APP_ID}`, 'GET', null)
.then((res) => {
// console.log('res', res)
if (!!res.data && !!res.data.arrnotif) {
this.last_notifs = res.data.arrnotif
} else {
this.last_notifs = []
}
return true
})
.catch((error) => {
@@ -61,6 +101,7 @@ export const useNotifStore = defineStore('NotifStore', {
data.sender = notif.sender
data.dest = notif.dest
data.descr = notif.descr
data.link = notif.link
data.datenotif = tools.getDateNow()
data.read = false

View File

@@ -3,7 +3,7 @@ import { defineStore } from 'pinia'
import {
IFriends, IMsgGlobParam,
ISigninOptions,
ISignupOptions, IUserFields, IUserProfile, IUserState,
ISignupOptions, IUserFields, IUserNotifType, IUserProfile, IUserState,
} from '@src/model'
import { tools } from '@store/Modules/tools'
import translate from '@src/globalroutines/util'
@@ -54,7 +54,7 @@ export const DefaultUser: IUserFields = {
manage_mygroups: [],
asked_friends: [],
asked_groups: [],
notifs: 15,
notifs: [],
},
cart: {
userId: '',
@@ -100,7 +100,7 @@ export const DefaultProfile: IUserProfile = {
manage_mygroups: [],
asked_friends: [],
asked_groups: [],
notifs: 15,
notifs: [],
}
export const useUserStore = defineStore('UserStore', {
@@ -975,9 +975,10 @@ export const useUserStore = defineStore('UserStore', {
}
},
async loadUserProfile(username: string) {
async loadUserProfile({username, idnotif}: {username: string, idnotif?: string}) {
const data = {
username
username,
idnotif
}
return Api.SendReq('/users/profile', 'POST', data)
@@ -993,7 +994,7 @@ export const useUserStore = defineStore('UserStore', {
},
async setUserNotifs(notifs: number) {
async setUserNotifs(notifs: IUserNotifType[]) {
const data = {
notifs
}

View File

@@ -30,7 +30,7 @@ import urlBase64ToUint8Array from '@src/js/utility'
import translate from '@src/globalroutines/util'
import { useTodoStore } from '@store/Todos'
import { useMessageStore } from './MessageStore'
import { useNotifStore } from './NotifStore'
import { useNotifStore } from '@store/NotifStore'
const stateConnDefault = 'online'
@@ -1592,6 +1592,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
else if (table === toolsext.TABLOCACCOM) myarr = shared_consts.LocationAccom
else if (table === toolsext.TABPREF) myarr = shared_consts.Preferences
else if (table === 'usernotifs') myarr = shared_consts.UsersNotif_Adv_List
else if (table === 'typenotifs') myarr = shared_consts.typeNotifs
else myarr = this.getListByTable(table)
if (costanti.TABLES_ARRAY.includes(table)) {

View File

@@ -78,6 +78,8 @@ export default defineComponent({
const myrec = msgchat(username)
// Get msg for this chat
const lastdata: any = (myrec) ? myrec.lastdataread : tools.getLastDateReadReset()
if (!lastdata)
return null
console.table(myrec)
let mydate = ''
if (!tools.isIsoDate(lastdata))

View File

@@ -80,7 +80,7 @@ export default defineComponent({
function loadProfile() {
// Carica il profilo di quest'utente
userStore.loadUserProfile(userStore.my.username).then((ris) => {
userStore.loadUserProfile({username: userStore.my.username}).then((ris) => {
myuser.value = ris
})
}

View File

@@ -21,6 +21,7 @@ import { IMyGroup, IUserFields } from 'model'
import { shared_consts } from '@/common/shared_vuejs'
import { static_data } from '@/db/static_data'
import { fieldsTable } from '@store/Modules/fieldsTable'
import { useNotifStore } from '@store/NotifStore'
import MixinUsers from '@/mixins/mixin-users'
@@ -43,6 +44,7 @@ export default defineComponent({
const animation = ref('fade')
const username = computed(() => $route.params.username ? $route.params.username.toString() : userStore.my.username)
const idnotif = computed(() => $route.query.idnotif ? $route.query.idnotif.toString() : '')
const filtroutente = ref(<any[]>[])
const showPic = ref(false)
@@ -52,6 +54,8 @@ export default defineComponent({
const actualcard = ref('mygoods')
const notifStore = useNotifStore()
const mycards = computed(() => {
return costanti.MAINCARDS.filter((rec: any) => rec.table)
})
@@ -70,10 +74,11 @@ export default defineComponent({
async function loadProfile() {
// Carica il profilo di quest'utente
if (username.value) {
await userStore.loadUserProfile(username.value).then((ris) => {
await userStore.loadUserProfile({ username: username.value, idnotif: idnotif.value }).then((ris) => {
myuser.value = ris
if (myuser.value) {
filtroutente.value = [{ userId: myuser.value._id }]
notifStore.setAsRead(idnotif.value)
try {
listgroupsfiltered.value = globalStore.mygroups.filter((grp: IMyGroup) => myuser.value!.profile.mygroups.findIndex((rec: IMyGroup) => rec.groupname === grp.groupname) >= 0)
@@ -97,6 +102,7 @@ export default defineComponent({
})
function mounted() {
console.log('idnotif', idnotif)
loadProfile()
}
@@ -168,6 +174,7 @@ export default defineComponent({
actualcard,
caricato,
listgroupsfiltered,
idnotif,
}
}
})

View File

View File

@@ -0,0 +1,30 @@
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import { useUserStore } from '@store/UserStore'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from '@/boot/i18n'
import { useQuasar } from 'quasar'
import { CMyCardPopup } from '@/components/CMyCardPopup'
import { CMyPage } from '@/components/CMyPage'
import { CNotifSettings } from '@/components/CNotifSettings'
import { toolsext } from '@store/Modules/toolsext'
import { tools } from '@store/Modules/tools'
import { shared_consts } from '@src/common/shared_vuejs'
export default defineComponent({
name: 'usernotifs',
components: { CMyCardPopup, CNotifSettings, CMyPage },
props: {},
setup() {
const userStore = useUserStore()
const $route = useRoute()
const $q = useQuasar()
const { t } = useI18n()
return {
t,
toolsext,
tools,
shared_consts,
}
}
})

View File

@@ -0,0 +1,21 @@
<template>
<CMyPage :title="$t('pages.notifs')"
imgbackground="images/calendario_eventi.jpg"
sizes="max-height: 120px" styleadd="bottom: -20px !important;">
<CNotifSettings>
</CNotifSettings>
<br>
</CMyPage>
</template>
<script lang="ts" src="./usernotifs.ts">
</script>
<style lang="scss" scoped>
@import './usernotifs.scss';
</style>