Reportistica Ore 3

This commit is contained in:
Paolo Arena
2021-02-25 03:00:29 +01:00
parent 1fdafbb0e4
commit 47b01c9002
14 changed files with 304 additions and 52 deletions

View File

@@ -57,7 +57,7 @@ export default class CEventsCalendar extends MixinEvents {
public $q public $q
public $t: any public $t: any
public calendarView = 'month' public calendarView = 'month'
public selectedDate = '2019-04-01' public selectedDate = ''
public tabeditor: string = 'details' public tabeditor: string = 'details'
public formDefault: IEvents = { public formDefault: IEvents = {
title: '', title: '',
@@ -381,16 +381,21 @@ export default class CEventsCalendar extends MixinEvents {
} }
public mounted() { public mounted() {
this.selectedDate = this.formatDate(tools.getDateNow())
this.$root.$on('calendar:next', this.calendarNext) this.$root.$on('calendar:next', this.calendarNext)
this.$root.$on('calendar:prev', this.calendarPrev) this.$root.$on('calendar:prev', this.calendarPrev)
this.$root.$on('calendar:today', this.calendarToday) this.$root.$on('calendar:today', this.calendarToday)
this.SetToday()
// CalendarStore.state.eventlist = events // CalendarStore.state.eventlist = events
this.updateFormatters() this.updateFormatters()
} }
public beforeMount() { public beforeMount() {
console.log('mounted')
this.selectedDate = this.formatDate(tools.getDateNow())
console.log('this.selectedDate', this.selectedDate)
CalendarStore.state.locale = toolsext.getLocale() CalendarStore.state.locale = toolsext.getLocale()
this.updateFormatters() this.updateFormatters()
} }
@@ -976,6 +981,7 @@ export default class CEventsCalendar extends MixinEvents {
public getEvents(dt) { public getEvents(dt) {
const eventsloc = [] const eventsloc = []
console.log('dt', dt)
for (let i = 0; i < CalendarStore.state.eventlist.length; ++i) { for (let i = 0; i < CalendarStore.state.eventlist.length; ++i) {
let added = false let added = false
@@ -984,11 +990,11 @@ export default class CEventsCalendar extends MixinEvents {
// check for overlapping times // check for overlapping times
const startTime = CalendarStore.state.eventlist[i].dateTimeStart const startTime = CalendarStore.state.eventlist[i].dateTimeStart
const endTime = CalendarStore.state.eventlist[i].dateTimeEnd const endTime = CalendarStore.state.eventlist[i].dateTimeEnd
for (let j = 0; j < eventsloc.length; ++j) { for (const item of eventsloc) {
const startTime2 = eventsloc[j].dateTimeStart const startTime2 = item.dateTimeStart
const endTime2 = eventsloc[j].dateTimeEnd const endTime2 = item.dateTimeEnd
if (date.isBetweenDates(startTime, startTime2, endTime2) || date.isBetweenDates(endTime, startTime2, endTime2)) { if (date.isBetweenDates(startTime, startTime2, endTime2) || date.isBetweenDates(endTime, startTime2, endTime2)) {
eventsloc[j].side = 'left' item.side = 'left'
eventsloc.push(CalendarStore.state.eventlist[i]) eventsloc.push(CalendarStore.state.eventlist[i])
added = true added = true
break break
@@ -1008,6 +1014,8 @@ export default class CEventsCalendar extends MixinEvents {
} }
} }
} }
if (eventsloc.length > 0)
console.log('eventsloc', eventsloc)
return eventsloc return eventsloc
} }

View File

@@ -516,8 +516,8 @@
dayPadding="35px 2px" dayPadding="35px 2px"
> >
<template #day="{ date }"> <template #day="{ timestamp }">
<template v-for="(event, index) in getEvents(date)"> <template v-for="(event, index) in getEvents(timestamp.date)">
<q-badge <q-badge
:key="index" :key="index"
style="width: 100%; cursor: pointer;" style="width: 100%; cursor: pointer;"
@@ -539,9 +539,9 @@
</template> </template>
</template> </template>
<template #day-header="{ date }"> <template #day-header="{ timestamp }">
<div class="row justify-center"> <div class="row justify-center">
<template v-for="(event, index) in eventsMap[date]"> <template v-for="(event, index) in eventsMap[timestamp.date]">
<q-badge <q-badge
:key="index" :key="index"
class="q-ma-xs" class="q-ma-xs"
@@ -552,8 +552,8 @@
</template> </template>
</div> </div>
</template> </template>
<template #day-body="{ date, timeStartPos, timeDurationHeight }"> <template #day-body="{ timestamp, timeStartPos, timeDurationHeight }">
<template v-for="(event, index) in getEvents(date)"> <template v-for="(event, index) in getEvents(timestamp.date)">
<div <div
:key="index" :key="index"
:label="tools.getstrTime(event.dateTimeStart)" :label="tools.getstrTime(event.dateTimeStart)"

View File

@@ -29,10 +29,10 @@ export default class CGridTableRec extends Vue {
@Prop({ required: false, default: 'Aggiungi' }) public labelBtnAddRow: string @Prop({ required: false, default: 'Aggiungi' }) public labelBtnAddRow: string
@Prop({ required: false, default: '' }) public noresultLabel: string @Prop({ required: false, default: '' }) public noresultLabel: string
@Prop({ @Prop({
required: false, default: function mydef() { required: false, default: function mydef(): object {
return true return {}
} }
}) public defaultnewrec: any }) public defaultnewrec: object
@Prop({ required: false, default: null }) public tablesList: ITableRec[] @Prop({ required: false, default: null }) public tablesList: ITableRec[]
@Prop({ required: false, default: null }) public arrfilters: IFilter[] @Prop({ required: false, default: null }) public arrfilters: IFilter[]
@Prop({ required: false, default: [] }) public filterdef: number[] @Prop({ required: false, default: [] }) public filterdef: number[]
@@ -415,6 +415,7 @@ export default class CGridTableRec extends Vue {
// mydata.data[mykey] = '' // mydata.data[mykey] = ''
console.log('mydata', mydata)
const data = await GlobalStore.actions.saveTable(mydata) const data = await GlobalStore.actions.saveTable(mydata)
this.newRecord = data this.newRecord = data
@@ -436,6 +437,7 @@ export default class CGridTableRec extends Vue {
// mydata.data[mykey] = '' // mydata.data[mykey] = ''
console.log('mydata', mydata)
const data = await GlobalStore.actions.saveTable(mydata) const data = await GlobalStore.actions.saveTable(mydata)
this.serverData.push(data) this.serverData.push(data)

View File

@@ -84,7 +84,7 @@
map-options map-options
:options="mycolumns" :options="mycolumns"
option-value="name" option-value="name"
style="min-width: 150px" º
@input="changeCol"> @input="changeCol">
</q-select> </q-select>

View File

@@ -37,6 +37,7 @@ export default class CHours extends MixinBase {
lk_LF: 'userId', lk_LF: 'userId',
lk_FF: '_id', lk_FF: '_id',
lk_as: 'user', lk_as: 'user',
af_objId_tab: 'myId',
lk_proj: { lk_proj: {
todoId: 1, userId: 1, descr: 1, date: 1, time_start: 1, time_end: 1, hours: 1, todoId: 1, userId: 1, descr: 1, date: 1, time_start: 1, time_end: 1, hours: 1,
username: 1, name: 1, surname: 1 username: 1, name: 1, surname: 1

View File

@@ -52,10 +52,13 @@ export default class CMyPopupEdit extends Vue {
this.$emit('update:row', newval) this.$emit('update:row', newval)
} }
public changevalRec(newval) { public getrealval(newval) {
if (this.col.fieldtype === tools.FieldType.hours) { if (this.col.fieldtype === tools.FieldType.hours) {
newval = newval.value newval = newval.value
} }
}
public changevalRec(newval) {
console.log('this.row', this.row, 'this.col', this.col, 'newval', newval) console.log('this.row', this.row, 'this.col', this.col, 'newval', newval)
console.log('this.row[this.col.name]', this.row[this.col.name]) console.log('this.row[this.col.name]', this.row[this.col.name])
this.row[this.col.name] = newval this.row[this.col.name] = newval
@@ -63,6 +66,15 @@ export default class CMyPopupEdit extends Vue {
this.$emit('update:row', this.row) this.$emit('update:row', this.row)
} }
public changevalRecHours(newval) {
if (this.col.fieldtype === tools.FieldType.hours) {
newval = newval.value
}
this.changevalRec(newval)
this.myvalue = newval
}
public updatedata() { public updatedata() {
this.mounted() this.mounted()
} }

View File

@@ -50,14 +50,25 @@
</q-input> </q-input>
</div> </div>
<div v-else-if="col.fieldtype === tools.FieldType.hours"> <div v-else-if="col.fieldtype === tools.FieldType.hours">
<div class="row">
<q-input v-model="myvalue" type="number"
autofocus
@input="changevalRec"
style="max-width: 100px;"
:label="col.label"
>
</q-input>
<CMySelect label="Ore" :value.sync="myvalue" <CMySelect label="Ore" :value.sync="myvalue"
optval="value" optlab="label" optval="value" optlab="label"
:useinput="true" :dense="false"
@changeval="changevalRec" :use-input="false"
:newvaluefunc="createHours" @changeval="changevalRecHours"
style="max-width: 100px;"
:options="tools.SelectHours"> :options="tools.SelectHours">
</CMySelect> </CMySelect>
</div>
<!--<q-input v-model="myvalue" type="number" <!--<q-input v-model="myvalue" type="number"
autofocus autofocus

View File

@@ -15,6 +15,7 @@ export default class CMySelect extends Vue {
@Prop({ required: true, default: '' }) public optlab @Prop({ required: true, default: '' }) public optlab
@Prop({ required: true, default: '' }) public optval @Prop({ required: true, default: '' }) public optval
@Prop({ required: false, default: true }) public useinput: boolean @Prop({ required: false, default: true }) public useinput: boolean
@Prop({ required: false, default: true }) public dense: boolean
@Prop({ required: false, default: null }) public newvaluefunc @Prop({ required: false, default: null }) public newvaluefunc
@Prop({ required: false, default: null }) public funcgetvaluebyid @Prop({ required: false, default: null }) public funcgetvaluebyid
@Prop({ required: true }) public options @Prop({ required: true }) public options

View File

@@ -15,7 +15,7 @@
:option-label="optlab" :option-label="optlab"
@input="changeval" @input="changeval"
:label="label" :label="label"
dense :dense="dense"
> >
</q-select> </q-select>
</div> </div>
@@ -23,7 +23,7 @@
<q-select <q-select
rounded rounded
outlined outlined
dense :dense="dense"
:input-class="myclass" :input-class="myclass"
v-model="myvalue" v-model="myvalue"
:options="options" :options="options"

View File

@@ -379,6 +379,7 @@ export interface IParamsQuery {
userId: string userId: string
codeId?: string codeId?: string
lk_tab?: string, lk_tab?: string,
af_objId_tab?: string,
lk_LF?: string, lk_LF?: string,
lk_FF?: string, lk_FF?: string,
lk_as?: string, lk_as?: string,

View File

@@ -258,7 +258,22 @@ export const tools = {
id: 50, id: 50,
label: '5', label: '5',
value: 5 value: 5
} },
{
id: 60,
label: '6',
value: 6
},
{
id: 70,
label: '7',
value: 7
},
{
id: 80,
label: '8',
value: 8
},
], ],
SelectListNumPeople: [ SelectListNumPeople: [
@@ -4220,6 +4235,62 @@ export const tools = {
return UserStore.state.isLogged return UserStore.state.isLogged
else else
return false return false
},
formatDate(mydate: any) {
let d = void 0
if (mydate !== void 0) {
d = new Date(mydate)
} else {
d = new Date()
}
const month = '' + (d.getMonth() + 1)
const day = '' + d.getDate()
const year = d.getFullYear()
return [year, tools.padTime(month), tools.padTime(day)].join('-')
},
firstDayOfDate(mydate: any) {
let d = void 0
if (mydate !== void 0) {
d = new Date(mydate)
} else {
d = new Date()
}
const month = d.getMonth()
const day = 1
const year = d.getFullYear()
return new Date(year, month, day)
},
LastDayOfDate(mydate: any) {
let d = void 0
if (mydate !== void 0) {
d = new Date(mydate)
} else {
d = new Date()
}
let month = d.getMonth()
if (month === 11)
month = 0
else
month++
const year = d.getFullYear()
return new Date(year, month, 0)
},
formatTime(mydate) {
const d = mydate !== void 0 ? new Date(mydate) : new Date(),
hours = '' + d.getHours(),
minutes = '' + d.getMinutes()
return [tools.padTime(hours), tools.padTime(minutes)].join(':')
} }
// getLocale() { // getLocale() {

View File

@@ -923,6 +923,7 @@ export default class ProjList extends Vue {
lk_LF: 'userId', lk_LF: 'userId',
lk_FF: '_id', lk_FF: '_id',
lk_as: 'user', lk_as: 'user',
af_objId_tab: 'userId',
lk_proj: { lk_proj: {
todoId: 1, userId: 1, descr: 1, date: 1, time_start: 1, time_end: 1, hours: 1, todoId: 1, userId: 1, descr: 1, date: 1, time_start: 1, time_end: 1, hours: 1,
username: 1, name: 1, surname: 1 username: 1, name: 1, surname: 1

View File

@@ -15,6 +15,7 @@ import { shared_consts } from '@src/common/shared_vuejs'
export default class Report extends MixinBase { export default class Report extends MixinBase {
public dateFormatter: any = '' public dateFormatter: any = ''
public titleFormatter: any = null
public selectedDate = '' public selectedDate = ''
public arrhour: {} = {} public arrhour: {} = {}
public listaResidenti: any[] = [] public listaResidenti: any[] = []
@@ -22,20 +23,61 @@ export default class Report extends MixinBase {
calendar: any calendar: any
} }
public resourceHeight = 100 public myView: string = 'month'
public myresource = { username: '' }
public title: string = ''
public optView = [{ _id: 1, label: 'Settimanale', value: 'week-scheduler' },
{ _id: 2, label: 'Mensile', value: 'month' }]
public resourceHeight = 60
public valfilter: number = 0 public valfilter: number = 0
public arrfilters = [ public arrfilters = [
// { label: 'Responsabili', value: 1, ris: false }, // { label: 'Responsabili', value: 1, ris: false },
{ label: 'Attività', value: 2, ris: false } { label: 'Visualizza Progetti', value: 2, ris: false }
] ]
public calendarNext() {
this.$refs.calendar.next()
}
public calendarPrev() {
this.$refs.calendar.prev()
}
public calendarToday(today) {
this.selectedDate = today
}
public SetToday() {
this.$root.$emit('calendar:today', tools.formatDate(tools.getDateNow()))
}
public mounted() { public mounted() {
this.$root.$on('calendar:next', this.calendarNext)
this.$root.$on('calendar:prev', this.calendarPrev)
this.$root.$on('calendar:today', this.calendarToday)
this.SetToday()
// CalendarStore.state.eventlist = events
this.updateFormatters()
this.load() this.load()
} }
get locale() {
return CalendarStore.state.locale
}
public created() {
this.refreshFilter(false)
}
public load() { public load() {
this.myresource.username = UserStore.state.my.username
const date_start = tools.addDays(new Date(tools.getTimestampsNow()), -90) const date_start = tools.addDays(new Date(tools.getTimestampsNow()), -90)
const date_end = tools.addDays(new Date(tools.getTimestampsNow()), 30) const date_end = tools.addDays(new Date(tools.getTimestampsNow()), 30)
UserStore.actions.reportload({ date_start, date_end, filter: this.valfilter }) UserStore.actions.reportload({ date_start, date_end, filter: this.valfilter })
@@ -46,16 +88,7 @@ export default class Report extends MixinBase {
this.listaResidenti = myris.listaResidenti this.listaResidenti = myris.listaResidenti
} }
}) })
}
public calendarNext() {
this.$refs.calendar.next()
console.log('SelectedDate', this.selectedDate)
}
public calendarPrev() {
this.$refs.calendar.prev()
console.log('SelectedDate', this.selectedDate)
} }
public getEventDate(eventparam) { public getEventDate(eventparam) {
@@ -106,7 +139,7 @@ export default class Report extends MixinBase {
if (!!this.arrhour[objres.username]) { if (!!this.arrhour[objres.username]) {
if (this.arrhour[objres.username].length > 0) { if (this.arrhour[objres.username].length > 0) {
this.arrhour[objres.username].forEach((item) => { this.arrhour[objres.username].forEach((item) => {
if (item) { if (!!item && dt) {
if (tools.getstrYYMMDDDate(item.date) === dt.date) { if (tools.getstrYYMMDDDate(item.date) === dt.date) {
// console.log('dt', dt, 'objres', objres, 'this.arrhour[objres.username]', this.arrhour[objres.username]) // console.log('dt', dt, 'objres', objres, 'this.arrhour[objres.username]', this.arrhour[objres.username])
// console.log('Eccolo!', item) // console.log('Eccolo!', item)
@@ -134,7 +167,7 @@ export default class Report extends MixinBase {
return arr return arr
} }
public refreshFilter() { public refreshFilter(refresh) {
this.valfilter = 0 this.valfilter = 0
for (const filter of this.arrfilters) { for (const filter of this.arrfilters) {
@@ -144,11 +177,69 @@ export default class Report extends MixinBase {
if (filter.value === shared_consts.REPORT_FILT_ATTIVITA && filter.ris) { if (filter.value === shared_consts.REPORT_FILT_ATTIVITA && filter.ris) {
this.resourceHeight = 120 this.resourceHeight = 120
} else { } else {
this.resourceHeight = 60 this.resourceHeight = 80
} }
} }
if (refresh)
this.load() this.load()
} }
@Watch('locale')
public checkloc() {
this.updateFormatters()
}
public updateFormatters() {
try {
// console.log('tools.getLocale() =', tools.getLocale())
// console.log('Calendar', CalendarStore.state.locale)
this.dateFormatter = new Intl.DateTimeFormat(tools.getLocale() || void 0, {
weekday: CalendarStore.state.shortWeekdayLabel ? 'short' : 'long',
month: CalendarStore.state.shortMonthLabel ? 'short' : 'long',
day: 'numeric',
year: 'numeric',
timeZone: 'UTC'
})
this.titleFormatter = new Intl.DateTimeFormat(this.locale || void 0, {
month: 'long',
year: 'numeric',
timeZone: 'UTC'
})
} catch (e) {
console.error('Intl.DateTimeFormat not supported')
this.dateFormatter = void 0
}
}
get title_cal() {
if (this.titleFormatter && this.locale) {
const mydate = new Date(this.selectedDate)
return this.titleFormatter.format(mydate)
}
return ''
}
get getOreMensili() {
const startday = tools.firstDayOfDate(this.selectedDate)
const endday = tools.LastDayOfDate(this.selectedDate)
console.log('ore mensili', startday, endday)
let count = 0
if (!!this.arrhour[this.myresource.username]) {
if (this.arrhour[this.myresource.username].length > 0) {
this.arrhour[this.myresource.username].forEach((item) => {
if (!!item) {
if (date.isBetweenDates(item.date, startday, endday)) {
if (item.totalhours > 0)
count += item.totalhours
}
}
})
}
}
return count
}
} }

View File

@@ -2,19 +2,36 @@
<q-page> <q-page>
<div> <div>
<CTitleBanner title="Report"></CTitleBanner> <CTitleBanner title="Report"></CTitleBanner>
<div class="flex-container">
<div v-for="filter in arrfilters"> <div v-for="filter in arrfilters">
<q-toggle dark color="green" v-model="filter.ris" :label="filter.label" <q-toggle dark color="green" v-model="filter.ris" :label="filter.label"
@input="refreshFilter"></q-toggle> @input="refreshFilter(true)"></q-toggle>
</div>
<q-select v-model="myView" :options="optView" emit-value map-options style="max-width: 150px"></q-select>
</div> </div>
</div> </div>
<div class="row justify-center items-center">
<div class="items-lg-start row">
<q-btn flat dense icon="fas fa-chevron-left" @click="calendarPrev"/>
<q-separator vertical/>
<q-btn flat dense icon="fas fa-chevron-right" @click="calendarNext"/>
</div>
<div class="text-center"><span
class="q-mr-xl q-toolbar__title nowrap text-blue">{{ title_cal }}</span>
</div>
</div>
<q-calendar <q-calendar
v-model="selectedDate" v-model="selectedDate"
ref="calendar" ref="calendar"
view="week-scheduler" :view="myView"
:weekdays="[1,2,3,4,5,6,0]" :weekdays="[1,2,3,4,5,6,0]"
animated animated
:day-height="resourceHeight"
:resource-height="resourceHeight" :resource-height="resourceHeight"
:resource-width="60" :resource-width="60"
transition-prev="slide-right" transition-prev="slide-right"
@@ -23,16 +40,16 @@
:locale="toolsext.getLocale()" :locale="toolsext.getLocale()"
> >
<!-- eslint-disable vue/no-unused-vars --> <!-- eslint-disable vue/no-unused-vars -->
<template #scheduler-resources-header> <!--<template #scheduler-resources-header>
<div class="row justify-center items-center"> <div class="row justify-center items-center">
<q-btn flat icon="fas fa-chevron-left" @click="calendarPrev"/> <q-btn flat icon="fas fa-chevron-left" @click="calendarPrev"/>
<q-btn flat icon="fas fa-chevron-right" @click="calendarNext"/> <q-btn flat icon="fas fa-chevron-right" @click="calendarNext"/>
</div> </div>
<!--<div class="full-height row justify-center items-center"> <div class="full-height row justify-center items-center">
<q-btn label="here"/> <q-btn label="here"/>
</div>--> </div>
</template> </template>-->
<template #scheduler-resource-day="{ timestamp, /* index, */ resource }"> <template #scheduler-resource-day="{ timestamp, /* index, */ resource }">
<template v-for="(event, index) in getEvents(timestamp, resource)"> <template v-for="(event, index) in getEvents(timestamp, resource)">
@@ -41,7 +58,7 @@
:key="index" :key="index"
class="flex justify-center text-h7" class="flex justify-center text-h7"
> >
{{ event.totalhours }} <q-chip dense color="primary" text-color="white" >{{ event.totalhours }}</q-chip>
</p> </p>
</div> </div>
<div v-if="event.totalacchours > 0" class="row justify-center items-center"> <div v-if="event.totalacchours > 0" class="row justify-center items-center">
@@ -49,7 +66,7 @@
:key="index" :key="index"
class="flex justify-center text-h7 boldhigh text-blue" class="flex justify-center text-h7 boldhigh text-blue"
> >
Tot: {{ event.totalacchours }} <q-chip dense :color="event.totalacchours > 24 ? 'positive' : 'negative'" text-color="white">[{{ event.totalacchours }}]</q-chip>
</p> </p>
</div> </div>
<div v-if="!!event.title"> <div v-if="!!event.title">
@@ -66,8 +83,44 @@
</template> </template>
</template> </template>
</q-calendar>
<template #day="{ timestamp }">
<template v-for="(event, index) in getEvents(timestamp, myresource)">
<div v-if="event.totalhours > 0" class="centermydiv">
<p
:key="index"
class="flex justify-center text-h7"
>
<q-chip dense color="primary" text-color="white" >{{ event.totalhours }}</q-chip>
</p>
</div> </div>
<div v-if="event.totalacchours > 0" class="row justify-center items-center">
<p
:key="index"
class="flex justify-center text-h7 boldhigh text-blue"
>
<q-chip dense :color="event.totalacchours > 24 ? 'positive' : 'negative'" text-color="white">[{{ event.totalacchours }}]</q-chip>
</p>
</div>
<div v-if="!!event.title">
<q-badge
:key="index"
class="my-event justify-center ellipsis"
:class="badgeClasses(event, 'body')"
:style="badgeStyles(event)"
>
<span class="ellipsis">{{ event.title }}</span>
</q-badge>
</div>
</template>
</template>
</q-calendar>
<div v-if="myView === 'month'">
<CTitleBanner :title="'Ore Mensili: ' + getOreMensili"></CTitleBanner>
</div>
</q-page> </q-page>
</template> </template>