TT#99204 CSC: As a Customer, I want to manage "Office Hours" as call forwarding type

AC:
Can select "and Office Hours are" as additional menu item from the Condition Menu of a forwarding group
Can open a popup containing the "Office Hours" controls
Can toggle whether the times for each weekday are the same or not
Can enable/disable specific weekdays, if times are all the same
Can manage times for each day separately, if times are not supposed to be the same
Can add multiple periods for all selected or a specific weekday
Can add a period consisting of start- and end-time
Can remove a period
Can cancel the "Office Hours" popup
Can save the state of the "Office Hours" popup
Can see the "Office Hours" as title of the forwarding group
Can click the "Office Hours" title to open and configure the "Office Hours" again

Change-Id: Id60d2e6f9032102e260570a2f6bb347049acd251
pull/4/head
Carlo Venusino 5 years ago
parent 63347a0b7d
commit efd518f95c

@ -0,0 +1,168 @@
<template>
<q-item
class="justify-center q-pl-none q-pr-none q-pb-none csc-cf-timerange-input-container"
>
<q-input
v-model="timeFrom"
filled
mask="time"
:rules="['time']"
dark
dense
no-error-icon
:placeholder="$t('pages.newCallForward.dateRangeStartTime')"
class="q-pa-sm"
@click="$refs.timeFromPopup.show()"
>
<template
v-slot:append
>
<q-icon
name="access_time"
class="cursor-pointer"
>
<q-popup-proxy
ref="timeFromPopup"
transition-show="scale"
transition-hide="scale"
@hide="addTimeRange"
>
<q-time
v-model="timeFrom"
format24h
>
<div
class="row items-center justify-end"
>
<q-btn
v-close-popup
:label="$t('buttons.close')"
color="primary"
flat
/>
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-input
v-model="timeTo"
filled
mask="time"
:rules="['time']"
dark
dense
no-error-icon
:placeholder="$t('pages.newCallForward.dateRangeEndTime')"
class="q-pa-sm"
@click="$refs.timeToPopup.show()"
>
<template
v-slot:append
>
<q-icon
name="access_time"
class="cursor-pointer"
>
<q-popup-proxy
ref="timeToPopup"
transition-show="scale"
transition-hide="scale"
@hide="addTimeRange"
>
<q-time
v-model="timeTo"
format24h
>
<div
class="row items-center justify-end"
>
<q-btn
v-close-popup
:label="$t('buttons.close')"
color="primary"
flat
/>
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-btn
v-if="mode === 'edit'"
flat
color="red"
icon="delete"
padding="xs"
@click="removeTimeRange"
/>
</q-item>
</template>
<script>
import { showGlobalError } from 'src/helpers/ui'
export default {
name: 'CscTimeRange',
props: {
items: {
type: Array,
default: () => []
},
index: {
type: Number,
default: null
},
time: {
type: Object,
default: null
},
mode: {
type: String,
default: null
}
},
data () {
return {
timeFrom: null,
timeTo: null
}
},
mounted () {
if (this.time && this.time.hour && this.time.minute) {
this.timeFrom = this.time.hour.split('-')[0] + ':' + this.time.minute.split('-')[0]
this.timeTo = this.time.hour.split('-')[1] + ':' + this.time.minute.split('-')[1]
}
},
methods: {
addTimeRange () {
if (this.timeFrom && this.timeTo) {
if (this.isTimerangeValid()) {
this.$emit('add-time-range', { from: this.timeFrom, to: this.timeTo, index: this.index })
if (this.mode === 'add') {
this.timeFrom = this.timeTo = null
}
} else {
this.timeTo = null
showGlobalError(this.$t('pages.newCallForward.officeHoursInvalidTimerange'))
}
}
},
removeTimeRange () {
this.$emit('delete-time-range', { from: this.timeFrom, to: this.timeTo, index: this.index })
},
isTimerangeValid () {
const hourFrom = parseInt(this.timeFrom.split(':')[0])
const minuteFrom = parseInt(this.timeFrom.split(':')[1])
const hourTo = parseInt(this.timeTo.split(':')[0])
const minuteTo = parseInt(this.timeTo.split(':')[1])
return hourTo > hourFrom || (hourFrom === hourTo && minuteTo > minuteFrom)
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.csc-cf-timerange-input-container
max-width 360px
</style>

@ -16,11 +16,8 @@
{{ $t('pages.newCallForward.conditionBtnLabelPrefix') }}
<span class="csc-cf-from-link">
{{ $t('pages.newCallForward.fromLabelShort') +'"'+ groupSourceset +'"' }}
</span>
<q-menu
ref="sourcesList"
:target="$refs.target"
@show="showSources()"
ref="sourcesListEditMenu"
>
<csc-new-call-forward-edit-sources
ref="editSources"
@ -29,10 +26,10 @@
:source-set-id="sourceSet.id"
:group-name="group.name"
:group-id="group.id"
@close="()=>{this.$refs.sourcesList.hide}"
@close="()=>{this.$refs.sourcesListEditMenu.hide()}"
/>
</q-menu>
</span>
</span>
<span
v-if="groupTimeset && !isRange"
@ -89,7 +86,7 @@
>
{{ $t('pages.newCallForward.dateRangeShort') + groupTimeRange }}
<q-menu
ref="daterange"
ref="editDateRangeMenu"
@hide="resetAction()"
>
<csc-new-call-forward-date-range
@ -99,7 +96,7 @@
:group-id="group.id"
:group-time-range="groupTimeRangeObj"
@confirm-delete="showConfirmDeleteTimesetDialog()"
@close="() => {this.$refs.daterange.hide()}"
@close="() => {this.$refs.editDateRangeMenu.hide()}"
/>
<csc-confirm-dialog
ref="confirmDeleteTimesetDialog"
@ -112,7 +109,7 @@
</span>
</span>
<span
v-if="isWeekdays"
v-if="isWeekdays && !isOfficeHours"
>
{{ $t('pages.newCallForward.conditionBtnLabelPrefix') }}
<span
@ -122,22 +119,47 @@
{{ weekdaysLabelShort + groupWeekdays }}
</span>
<q-menu
ref="weekdayEditPanel"
@show="showWeekdayEditForm()"
ref="addWeekdayMenu"
>
<csc-new-call-forward-add-weekday-form
:id="timeSet.id"
ref="weekdayEditForm"
class="q-pa-md"
:days="times"
:enabled="true"
:group-name="group.name"
:group-id="group.id"
@close="() => {this.$refs.addWeekdayMenu.hide()}"
/>
</q-menu>
</span>
<span
v-if="isOfficeHours"
>
{{ $t('pages.newCallForward.conditionBtnLabelPrefix') }}
<span
ref="isOfficeHoursLink"
class="csc-cf-from-link"
>
{{ officeHoursLabelShort +' '+ readableOfficeHours }}
</span>
<q-menu
ref="addOfficeHoursMenu"
persistent
>
<csc-new-call-forward-add-office-hours-form
:id="timeSet.id"
ref="officeHoursEditForm"
class="q-pa-md"
:times="cloneTimes(times)"
:same-office-hours-for-all-days="sameOfficeHoursForAllDays"
:group-name="group.name"
:group-id="group.id"
@close="() => {this.$refs.addOfficeHoursMenu.hide()}"
/>
</q-menu>
</span>
<span
v-if="isTempGroup || (!isTempGroup && !(groupSourceset && groupTimeset || groupSourceset && isWeekdays || groupTimeset && isWeekdays ))"
v-if="isTempGroup || !(groupSourceset && groupTimeset || groupSourceset && isWeekdays || groupTimeset && isWeekdays )"
class="csc-cf-destination-add-condition"
>
{{ $t('pages.newCallForward.conditionBtnLabelPrefix') }}
@ -160,7 +182,7 @@
<q-item-section>{{ $t('pages.newCallForward.fromLabel') }}</q-item-section>
</q-item>
<q-item
v-if="isTempGroup || !groupTimeset && !isRange && !isWeekdays"
v-if="isTempGroup || !hasTimeset"
v-close-popup
clickable
@click="()=>{action = 'addDateIsCondition'}"
@ -168,7 +190,7 @@
<q-item-section>{{ $t('pages.newCallForward.dateIsLabel') }}</q-item-section>
</q-item>
<q-item
v-if="isTempGroup || !groupTimeset && !isRange && !isWeekdays"
v-if="isTempGroup || !hasTimeset"
v-close-popup
clickable
@click="()=>{action = 'addDateRangeCondition'}"
@ -176,34 +198,40 @@
<q-item-section>{{ $t('pages.newCallForward.dateRangeLabel') }}</q-item-section>
</q-item>
<q-item
v-if="isTempGroup || !groupTimeset && !isRange && !isWeekdays"
v-if="isTempGroup || !hasTimeset"
v-close-popup
clickable
@click="()=>{action = 'addWeekdayCondition'}"
>
<q-item-section>{{ $t('pages.newCallForward.weekdaysLabel') }}</q-item-section>
</q-item>
<q-item
v-if="isTempGroup || !hasTimeset"
v-close-popup
clickable
@click="()=>{action = 'addOfficeHoursCondition'}"
>
<q-item-section>{{ $t('pages.newCallForward.officeHoursLabel') }}</q-item-section>
</q-item>
</q-list>
</q-menu>
<span>
<q-menu
ref="onlineSourceset"
@show="showSourcesetForm()"
@hide="resetToggleCondition(); resetAction()"
ref="addSourcesetMenu"
@hide="resetAction()"
>
<csc-new-call-forward-add-sourceset-form
ref="addSourceSet"
class="q-pa-md"
:enabled="true"
:group-name="group.name"
:group-id="group.id"
@close="()=>{this.$refs.onlineSourceset.hide()}"
@close="()=>{this.$refs.addSourcesetMenu.hide()}"
/>
</q-menu>
</span>
<span>
<q-menu
ref="dayWidgetFromMenu"
ref="addDateFromMenu"
@hide="resetAction()"
>
<q-date
@ -235,7 +263,7 @@
</span>
<span>
<q-menu
ref="daterangeFromMenu"
ref="addDateRangeMenu"
@hide="resetAction()"
>
<csc-new-call-forward-date-range
@ -244,22 +272,35 @@
:group-name="group.name"
:group-id="group.id"
:no-clear="true"
@close="() => {this.$refs.daterangeFromMenu.hide()}"
@close="() => {this.$refs.addDateRangeMenu.hide()}"
/>
</q-menu>
</span>
<span>
<q-menu
ref="weekdayPanel"
@show="showWeekdayPanel()"
@hide="resetWeekdayCondition(); resetAction()"
ref="addWeekdayMenu"
@hide="resetAction()"
>
<csc-new-call-forward-add-weekday-form
ref="weekdayForm"
class="q-pa-md"
:enabled="true"
:group-name="group.name"
:group-id="group.id"
@close="() => {this.$refs.addWeekdayMenu.hide()}"
/>
</q-menu>
</span>
<span>
<q-menu
ref="officeHoursPanel"
persistent
>
<csc-new-call-forward-add-office-hours-form
ref="weekdayForm"
class="q-pa-md"
:group-name="group.name"
:group-id="group.id"
@close="() => {this.$refs.officeHoursPanel.hide()}"
/>
</q-menu>
</span>
@ -344,7 +385,6 @@
<q-btn
flat
color="primary"
class=""
>
<q-icon
name="add"
@ -353,13 +393,13 @@
/>
{{ $t('pages.newCallForward.addDestinationLabel') }}
<q-menu
ref="destTypeForm"
ref="destTypeMenu"
:auto-close="true"
@show="showDestTypeForm()"
@hide="showNext()"
>
<csc-new-call-forward-destination-type-form
ref="selectDestinationType"
@close="()=>{this.$refs.destTypeMenu.hide()}"
/>
</q-menu>
</q-btn>
@ -368,18 +408,17 @@
ref="numberForm"
:no-parent-event="true"
:class="{ 'csc-cf-popover-hide': toggleNumberForm }"
@show="showNewDestNumber()"
>
<csc-new-call-forward-add-destination-form
ref="addDestinationForm"
class="q-pa-md"
:enabled="true"
:group-name="group.name"
:group-id="group.id"
@close="()=>{this.$refs.numberForm.hide()}"
/>
</q-menu>
</div>
<div class="col-xs-6 col-md-6 " />
<div class="col-xs-6 col-md-6" />
</div>
</div>
</template>
@ -399,6 +438,7 @@ import CscNewCallForwardAddDestinationForm from './CscNewCallForwardAddDestinati
import CscNewCallForwardEditSources from './CscNewCallForwardEditSources'
import CscNewCallForwardAddSourcesetForm from './CscNewCallForwardAddSourcesetForm'
import CscNewCallForwardAddWeekdayForm from './CscNewCallForwardAddWeekdayForm'
import CscNewCallForwardAddOfficeHoursForm from './CscNewCallForwardAddOfficeHoursForm'
import CscNewCallForwardDestinationTypeForm from './CscNewCallForwardDestinationTypeForm'
import CscNewCallForwardDateRange from './CscNewCallForwardDateRange'
export default {
@ -410,6 +450,7 @@ export default {
CscNewCallForwardEditSources,
CscNewCallForwardAddSourcesetForm,
CscNewCallForwardAddWeekdayForm,
CscNewCallForwardAddOfficeHoursForm,
CscNewCallForwardDestinationTypeForm,
CscNewCallForwardDateRange
},
@ -426,13 +467,8 @@ export default {
data () {
return {
firstDestinationInCreation: false,
toggleGroup: true,
isEnabled: true,
toggleNumberForm: true,
toggleConditionFromForm: true,
toggleWeekdayPanel: true,
toggleIsDatePanel: true,
toggleIsRangePanel: true,
groupIsLoading: false,
sourceSet: null,
sources: [],
@ -441,7 +477,8 @@ export default {
action: null,
enabled: false,
day: null,
today: new Date().toString()
today: new Date().toString(),
sameOfficeHoursForAllDays: false
}
},
computed: {
@ -549,52 +586,53 @@ export default {
? `${this.$t('pages.newCallForward.weekdaysLabelShort')}`
: `${this.$t('pages.newCallForward.weekdayLabelShort')}`
},
officeHoursLabelShort () {
return this.$tc('pages.newCallForward.officeHoursLabelShort', this.timeSet.times.length)
},
groupWeekdays () {
let retVal = ''
let times = _.cloneDeep(_.get(this.timeSet, 'times', []))
times = times.sort((a, b) => (parseInt(a.wday) > parseInt(b.wday)) ? 1 : ((parseInt(b.wday) > parseInt(a.wday)) ? -1 : 0))
times.forEach((time, index) => {
const separator = (index === times.length - 1) ? '' : ', '
switch (time.wday) {
case '2':
retVal += `${this.$t('pages.callForward.times.monday')}`
break
case '3':
retVal += `${this.$t('pages.callForward.times.tuesday')}`
break
case '4':
retVal += `${this.$t('pages.callForward.times.wednesday')}`
break
case '5':
retVal += `${this.$t('pages.callForward.times.thursday')}`
break
case '6':
retVal += `${this.$t('pages.callForward.times.friday')}`
break
case '7':
retVal += `${this.$t('pages.callForward.times.saturday')}`
break
case '1':
retVal += `${this.$t('pages.callForward.times.sunday')}`
break
return this.parseWeekDays(times)
},
readableOfficeHours () {
// TODO improve
// The goal here is to transform the timeranges from the endpoint format
// to a human readable format like:
//
// - Tuesday 12:30 - 14:30, Wednesday 19:12 - 12:45 in case of different
// timeranges in different days
// - Monday, Tuesday, Friday 13:39 - 14:45 in case of same timeranges in
// different days
const times = _.cloneDeep(_.get(this.timeSet, 'times', []))
let days = []
for (const time of times) {
if (days[time.wday]) {
continue
}
days[time.wday] = times.filter(($time) => {
return $time.wday === time.wday
}).map(item => ' ' + item.hour.split('-')[0] + ':' + item.minute.split('-')[0] + '-' + item.hour.split('-')[1] + ':' + item.minute.split('-')[1])
}
days = Object.keys(days).map((key) => { return { wday: key, times: days[key] } })
this.checkOfficeHoursForAllDays(days.map(day => day.times))
if (this.sameOfficeHoursForAllDays) {
return this.parseWeekDays(days) + ' ' + days[0].times
} else {
return days.map(day => this.parseWeekDays([day]) + day.times).join(', ')
}
retVal += separator
})
return retVal
},
isWeekdays () {
const isWeekdays = this.timeSet &&
this.timeSet.times &&
this.timeSet.times.length > 0 &&
this.timeSet.times[0].wday &&
this.timeSet.times[0].wday > 0
return isWeekdays
return this.timeSet && this.timeSet.times && this.timeSet.times.length > 0 && this.timeSet.times[0].wday !== null
},
isOfficeHours () {
return this.isWeekdays && this.timeSet.times[0].hour !== null && this.timeSet.times[0].minute !== null
},
isTempGroup () {
return this.group.id.toString().includes('temp-')
},
isFirstDestInCreation () {
return this.group.id.toString() === this.getFirstDestinationInCreation
hasTimeset () {
return this.groupTimeset || this.isRange || this.isWeekdays
},
toggleLabel () {
return this.toggleDefaultNumber ? `${this.$t('pages.newCallForward.primarNumberEnabled')}` : `${this.$t('pages.newCallForward.primarNumberDisabled')}`
@ -651,13 +689,6 @@ export default {
}
},
methods: {
// we need to generate key because destinations have no id
genKey () {
return Math.random()
},
showNewDestNumber () {
this.$refs.addDestinationForm.add()
},
async showNext () {
switch (this.getSelectedDestinationType) {
case 'destination':
@ -680,13 +711,8 @@ export default {
} else {
firstDestinationCmp.movePopoverToTop()
}
firstDestinationCmp.$refs.destTypeForm.show()
},
setCondition (action) {
this.action = action
this.$refs.conditions.hide()
},
showConditionForm () {
if (this.isTempGroup) {
this.showFirstDestMenu()
@ -695,33 +721,22 @@ export default {
const action = this.action
switch (action) {
case 'addFromCondition':
this.toggleConditionFromForm = false
this.$refs.onlineSourceset.show()
this.$refs.addSourcesetMenu.show()
break
case 'addDateIsCondition':
this.toggleIsDatePanel = false
this.$refs.dayWidgetFromMenu.show()
this.$refs.addDateFromMenu.show()
break
case 'addDateRangeCondition':
this.toggleIsRangePanel = false
this.$refs.daterangeFromMenu.show()
this.$refs.addDateRangeMenu.show()
break
case 'addWeekdayCondition':
this.toggleWeekdayPanel = false
this.$refs.weekdayPanel.show()
this.$refs.addWeekdayMenu.show()
break
case 'addOfficeHoursCondition':
this.$refs.officeHoursPanel.show()
break
}
},
showDestTypeForm () {
this.toggleNumberForm = true
this.$refs.selectDestinationType.add()
},
showWeekdayEditForm () {
this.$refs.weekdayEditForm.add()
},
getDestName (index) {
return 'destination' + index
},
getDestination (index) {
const destination = { ...this.group.destinations[index] }
if (index === 0) {
@ -740,30 +755,9 @@ export default {
})
this.$store.dispatch('newCallForward/removeGroupLoader', this.group.id)
},
openConditionsPopover () {
this.$refs.conditions.show()
},
showConditions () {
this.$refs.addCondition.add()
},
showSourcesetForm () {
this.$refs.addSourceSet.add()
},
showWeekdayPanel () {
this.$refs.weekdayForm.add()
},
showSources () {
this.$refs.editSources.add()
},
resetToggleCondition () {
this.toggleConditionFromForm = true
},
resetAction () {
this.action = null
},
resetWeekdayCondition () {
this.toggleWeekdayPanel = true
},
async updateSourcesetNames () {
const mappings = this.getMappings
const groupMappingId = await this.$store.dispatch('newCallForward/getMappingIdByGroupName', this.group.name)
@ -860,11 +854,21 @@ export default {
console.log(e)
}
},
rangeChanged () {
this.$refs.daterange.show()
},
minDate (day) {
return day >= date.formatDate(new Date(), 'YYYY/MM/DD')
},
parseWeekDays (times) {
const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']
return times
.map(time => this.$t('pages.callForward.times.' + weekDays[Number(time.wday) - 1]))
.join(', ')
},
checkOfficeHoursForAllDays (times) {
const weekdaysObj = _.groupBy(_.cloneDeep(this.times), 'wday')
this.sameOfficeHoursForAllDays = Object.keys(weekdaysObj).length > 1 && times.every(array => array.join() === times[0].join())
},
cloneTimes (times) {
return _.cloneDeep(times)
}
}
}

@ -1,6 +1,5 @@
<template>
<div
v-if="enabled"
class="csc-form"
>
<csc-input
@ -88,7 +87,6 @@ export default {
},
data () {
return {
enabled: false,
number: '',
numberError: false,
destinationIndex: null
@ -147,16 +145,13 @@ export default {
this.$store.dispatch('newCallForward/removeGroupLoader', this.groupId)
},
cancel () {
this.enabled = false
},
add () {
this.enabled = true
this.close()
},
close () {
this.enabled = false
this.$emit('close')
},
reset () {
this.cancel()
this.close()
},
error (state) {
this.numberError = state

@ -0,0 +1,401 @@
<template>
<q-list
class="csc-form"
>
<q-list>
<q-item
class="justify-center text-bold"
>
{{ $t('pages.newCallForward.officeHoursTitle') }}
</q-item>
<q-item
class="justify-center"
>
<q-checkbox
v-model="checkOfficeHoursForAllDays"
:value="sameOfficeHoursForAllDays"
:label="$t('pages.newCallForward.sameOfficeHoursForAllDays')"
@input="toggleAllDaysSameOfficeHours"
/>
</q-item>
<q-item
v-if="!checkOfficeHoursForAllDays"
class="justify-center"
>
<q-tabs
v-model="selectedDay"
active-color="primary"
dense
>
<q-tab
v-for="(dayLetter, index) in $t('pages.newCallForward.daysOfTheWeekShort').split(',')"
:key="index"
:alert="hasOfficeHours(getDayNumber(index))"
:name="getDayNumber(index)"
class="q-pa-xs"
>
<q-btn
class="weekday-btn"
rounded
ripple
>
{{ dayLetter }}
</q-btn>
</q-tab>
</q-tabs>
</q-item>
<q-item
v-if="checkOfficeHoursForAllDays"
class="justify-center"
>
<q-btn
v-for="(dayLetter, index) in $t('pages.newCallForward.daysOfTheWeekShort').split(',')"
:key="index"
class="weekday-btn q-ma-sm"
:class="{ 'day-selected-btn': weekdays.includes(getDayNumber(index))}"
rounded
@click="toggleWeekday(getDayNumber(index))"
>
{{ dayLetter }}
</q-btn>
</q-item>
<div
v-for="(time, index) in timeRanges"
:key="time.wday + '-' + time.hour + '-' + time.minute"
dense
>
<q-item
v-if="showTimeslot(time)"
>
<csc-time-range
:ref="'officeHours-' + index"
:index="getTimeSlotIndex(time, index)"
:time="time"
mode="edit"
@delete-time-range="deleteTimeRange"
@add-time-range="editTimeRange"
/>
</q-item>
</div>
<q-item
v-show="showNewTimeRangeFields"
dense
>
<csc-time-range
mode="add"
@add-time-range="addTimeRange"
/>
</q-item>
<q-item
class="justify-center"
>
<q-btn
flat
color="primary"
:disabled="checkOfficeHoursForAllDays && weekdays.length < 1"
@click="showStaticTimeRangeFields"
>
<q-icon
name="add"
color="primary"
size="24px"
/>
{{ $t('pages.newCallForward.officeHoursAddBtnLabel') }}
</q-btn>
</q-item>
</q-list>
<q-item
class="justify-center csc-actions-cont"
>
<q-btn
:disabled="!id"
flat
color="red"
icon="delete"
@click="showRemoveDialog()"
>
{{ $t('buttons.remove') }}
</q-btn>
<csc-confirm-dialog
ref="confirmDeleteTimesetDialog"
title-icon="delete"
class="csc-cf-delete-weekdays-btn"
:title="$t('pages.newCallForward.cancelTimesetDialogTitle', {name: 'office hours'})"
:message="$t('pages.newCallForward.cancelTimesetText', {name: 'this'})"
@confirm="deleteTimeset"
/>
<q-btn
flat
color="default"
icon="clear"
@click="cancel()"
>
{{ $t('buttons.cancel') }}
</q-btn>
<q-btn
flat
color="primary"
icon="done"
:disabled="timeRanges.length < 1"
@click="save()"
>
{{ $t('buttons.save') }}
</q-btn>
</q-item>
</q-list>
</template>
<script>
import CscConfirmDialog from '../../CscConfirmationDialog'
import CscTimeRange from '../../CscTimeRange'
import _ from 'lodash'
export default {
name: 'CscNewCallForwardAddOfficeHoursForm',
components: {
CscConfirmDialog,
CscTimeRange
},
props: {
groupName: {
type: String,
default: ''
},
groupId: {
type: [String, Number],
default: null
},
id: {
type: [String, Number],
default: null
},
times: {
type: Array,
default: null
},
sameOfficeHoursForAllDays: {
type: Boolean,
default: false
}
},
data () {
return {
timesetId: null,
timesetName: null,
weekdays: [],
timeRanges: [],
checkOfficeHoursForAllDays: false,
showNewTimeRangeFields: false,
selectedDay: '2' // Monday default
}
},
mounted () {
this.timesetName = 'timeset-' + this.groupId
this.timeSetId = this.id
if (this.times) {
this.weekdays = this.times.map(time => time.wday)
this.timeRanges = this.times
this.checkOfficeHoursForAllDays = this.sameOfficeHoursForAllDays
}
},
methods: {
async save () {
const forwardGroupId = this.groupId
this.$store.dispatch('newCallForward/addGroupLoader', forwardGroupId)
try {
if (this.checkOfficeHoursForAllDays && this.weekdays.length < 1) {
this.deleteTimeset()
} else {
if (this.id) {
this.timeSetId = this.id
} else {
this.timeSetId = await this.$store.dispatch('newCallForward/createTimeSet', this.timesetName)
}
await this.$store.dispatch('newCallForward/addTimesetToGroup', {
name: this.groupName,
groupId: this.groupId,
timeSetId: this.timeSetId
})
const updatedTimeset = await this.$store.dispatch('newCallForward/addTimeToTimeset', {
id: this.timeSetId,
time: this.timeRanges
})
this.$store.dispatch('newCallForward/setTimeset', updatedTimeset)
}
} catch (err) {
console.log(err)
}
this.close()
this.$store.dispatch('newCallForward/removeGroupLoader', forwardGroupId)
},
cancel () {
this.weekdays = []
if (this.days) {
for (const day of this.days) {
this.weekdays.push(day.wday)
}
}
this.close()
},
close () {
this.$emit('close')
},
showRemoveDialog () {
this.$refs.confirmDeleteTimesetDialog.open()
},
toggleWeekday (weekday) {
if (this.weekdays.includes(weekday)) {
this.weekdays = this.weekdays.filter(item => item !== weekday)
this.removeDayFromTimerange(weekday)
} else {
this.weekdays.push(weekday)
this.addDayToTimerange(weekday)
}
this.weekdays.sort((a, b) => (parseInt(a) - parseInt(b)))
},
async deleteTimeset () {
this.$store.dispatch('newCallForward/addGroupLoader', this.groupId)
try {
await this.$store.dispatch('newCallForward/deleteTimeset', this.timeSetId)
} catch (error) {
console.log(error)
}
this.$store.dispatch('newCallForward/loadMappings')
this.$store.dispatch('newCallForward/removeGroupLoader', this.groupId)
},
toggleAllDaysSameOfficeHours () {
this.weekdays = []
this.timeRanges = []
this.showNewTimeRangeFields = false
},
showStaticTimeRangeFields () {
this.showNewTimeRangeFields = true
},
editTimeRange (data) {
if (data.from && data.to) {
const timeFrom = data.from.split(':')
const timeTo = data.to.split(':')
const editedTimes = []
const timeRangesGroupByWeekday = _.groupBy(_.cloneDeep(this.timeRanges), 'wday')
if (this.checkOfficeHoursForAllDays) {
for (const wday in timeRangesGroupByWeekday) {
const time = timeRangesGroupByWeekday[wday][data.index]
time.hour = timeFrom[0] + '-' + timeTo[0]
time.minute = timeFrom[1] + '-' + timeTo[1]
editedTimes.push(...timeRangesGroupByWeekday[wday])
}
} else {
const time = timeRangesGroupByWeekday[this.selectedDay][data.index]
time.hour = timeFrom[0] + '-' + timeTo[0]
time.minute = timeFrom[1] + '-' + timeTo[1]
for (const wday in timeRangesGroupByWeekday) {
editedTimes.push(...timeRangesGroupByWeekday[wday])
}
}
this.timeRanges = editedTimes
}
},
addTimeRange (data) {
if (data.from && data.to) {
const timeFrom = data.from.split(':')
const timeTo = data.to.split(':')
if (this.checkOfficeHoursForAllDays) {
for (const weekday of this.weekdays) {
this.timeRanges.push({
wday: weekday,
hour: timeFrom[0] + '-' + timeTo[0],
minute: timeFrom[1] + '-' + timeTo[1]
})
}
} else {
this.timeRanges.push({
wday: this.selectedDay,
hour: timeFrom[0] + '-' + timeTo[0],
minute: timeFrom[1] + '-' + timeTo[1]
})
}
this.showNewTimeRangeFields = false
}
},
addDayToTimerange (day) {
if (this.timeRanges.length > 0) {
const dayRanges = this.timeRanges.filter(time => time.wday === this.timeRanges[0].wday)
for (const range of dayRanges) {
this.timeRanges.push({
wday: day,
hour: range.hour,
minute: range.minute
})
}
}
},
removeDayFromTimerange (day) {
if (this.timeRanges.length > 1) {
this.timeRanges = this.timeRanges.filter(time => time.wday !== day)
}
},
findIndexInGroup (data, timeRange) {
return timeRange.findIndex(time => {
const [fromHours, fromMinutes] = data.from ? data.from.split(':') : []
const [toHours, toMinutes] = data.from ? data.to.split(':') : []
return time.hour === (data.hour ? data.hour : `${fromHours}-${toHours}`) &&
time.minute === (data.minute ? data.minute : `${fromMinutes}-${toMinutes}`)
})
},
deleteTimeRange (data) {
const editedTimes = []
const timeToDelete = this.timeRanges[data.index]
const timeRangesGroupByWeekday = _.groupBy(this.timeRanges, 'wday')
if (this.checkOfficeHoursForAllDays) {
const indexInGroup = this.findIndexInGroup(data, timeRangesGroupByWeekday[timeToDelete.wday])
for (const wday in timeRangesGroupByWeekday) {
delete timeRangesGroupByWeekday[wday][indexInGroup]
editedTimes.push(...timeRangesGroupByWeekday[wday].filter(el => el !== undefined))
}
} else {
delete timeRangesGroupByWeekday[this.selectedDay][data.index]
for (const wday in timeRangesGroupByWeekday) {
editedTimes.push(...timeRangesGroupByWeekday[wday].filter(el => el !== undefined))
}
}
this.timeRanges = editedTimes
},
showTimeslot (time) {
// in case of same office hours for all days, shows the time slot once;
// in case of different office hours for different days, shows the time slot
// if belongs to the selected day
switch (true) {
case this.checkOfficeHoursForAllDays:
return time.wday && time.wday === this.timeRanges[0].wday
case !this.checkOfficeHoursForAllDays:
return time.wday && time.wday === this.selectedDay
default:
return false
}
},
hasOfficeHours (wday) {
const timeRangesGroupByWeekday = _.groupBy(this.timeRanges, 'wday')
return timeRangesGroupByWeekday[wday] && timeRangesGroupByWeekday[wday].length > 0 ? 'primary' : false
},
getTimeSlotIndex (time, index) {
if (this.checkOfficeHoursForAllDays) {
return index
}
const timeRangesGroupByWeekday = _.groupBy(this.timeRanges, 'wday')
return this.findIndexInGroup(time, timeRangesGroupByWeekday[time.wday])
},
getDayNumber (index) {
return index === 7 ? '1' : String(index + 2)
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.weekday-btn
background $main-menu-item-hover-background
width 35px
.day-selected-btn
background $primary
</style>

@ -1,6 +1,5 @@
<template>
<div
v-if="enabled"
class="csc-form"
>
<csc-input
@ -79,7 +78,6 @@ export default {
data () {
return {
loading: false,
enabled: false,
number: '',
name: '',
nameError: false,
@ -132,16 +130,13 @@ export default {
cancel () {
this.number = ''
this.name = ''
this.enabled = false
this.$emit('close')
},
add () {
this.number = ''
this.name = ''
this.enabled = true
},
close () {
this.enabled = false
this.$emit('close')
},
reset () {

@ -1,8 +1,6 @@
<template>
<div
v-if="enabled"
class="csc-form"
:class="{ 'csc-cf-popover-hide': toggleFormVisibility}"
>
<div
class="csc-cf-delete-weekdays-btn"
@ -134,11 +132,11 @@ export default {
default: null
},
id: {
type: String,
type: [String, Number],
default: null
},
days: {
type: Object,
type: Array,
default: null
}
},
@ -146,9 +144,7 @@ export default {
return {
timesetId: null,
timesetName: null,
toggleFormVisibility: false,
loading: false,
enabled: false,
weekdays: []
}
},
@ -209,14 +205,8 @@ export default {
},
close () {
this.$emit('close')
this.enabled = false
},
add () {
this.toggleFormVisibility = false
this.enabled = true
},
showRemoveDialog () {
this.toggleFormVisibility = true
this.$refs.confirmDeleteTimesetDialog.open()
},
toggleWeekday (weekday) {

@ -58,6 +58,7 @@
<q-time
ref="hourFrom"
v-model="hourFrom"
format24h
:no-unset="true"
>
<div class="row items-center justify-end q-gutter-sm">
@ -79,6 +80,7 @@
<q-time
ref="hourTo"
v-model="hourTo"
format24h
:no-unset="true"
>
<div class="row items-center justify-end q-gutter-sm">

@ -60,6 +60,7 @@
</div>
<csc-new-call-forward-destination-type-form
ref="selectDestinationType"
@close="()=>{this.$refs.destTypeMenu.hide()}"
/>
</q-menu>
<q-menu
@ -68,7 +69,6 @@
:no-parent-event="true"
class="csc-cf-dest-popover-bottom"
:class="{ 'csc-cf-popover-hide': disableNumberPopover, 'csc-cf-popover-to-top': popoverToTop, 'csc-cf-popover-timeout-to-top': popoverTimeoutToTop }"
@show="showNumberForm()"
@hide="movePopoverToInitialPos(); movePopoverTimeoutToInitialPos()"
>
<csc-new-call-forward-add-destination-form
@ -79,6 +79,7 @@
:group-name="groupName"
:group-id="groupId"
:first-destination-in-creation="firstDestinationInCreation"
@close="()=>{this.$refs.numberForm.hide()}"
/>
</q-menu>
</div>
@ -239,12 +240,8 @@ export default {
this.$refs.destTypeForm.show()
}
},
showNumberForm () {
this.$refs.addDestinationForm.add()
},
showDestTypeForm () {
this.toggleNumberForm = true
this.$refs.selectDestinationType.add()
},
async saveTimeout () {
this.$store.dispatch('newCallForward/addGroupLoader', this.groupId)

@ -1,7 +1,5 @@
<template>
<div
v-if="enabled"
>
<div>
<div
class="csc-cf-dest-type"
@click="setSelectedDestinationType('destination')"
@ -23,11 +21,6 @@ import {
} from 'vuex'
export default {
name: 'CscNewCallForwardDestinationTypeForm',
data () {
return {
enabled: false
}
},
mounted () {
this.setSelectedDestinationType(null)
},
@ -36,13 +29,10 @@ export default {
'setSelectedDestinationType'
]),
cancel () {
this.enabled = false
},
add () {
this.enabled = true
this.close = false
},
close () {
this.enabled = false
this.$emit('close')
}
}
}

@ -1,7 +1,5 @@
<template>
<div
v-if="enabled"
>
<div>
<div
class="csc-cf-dest-type"
@click="addDestinationsetUnconditional()"
@ -29,11 +27,6 @@ import {
} from 'vuex'
export default {
name: 'CscNewCallForwardDestinationsetTypeSelect',
data () {
return {
enabled: true
}
},
computed: {
...mapGetters('newCallForward', [
'timeoutGroupExists',
@ -57,15 +50,11 @@ export default {
async addDestinationsetBusy () {
await this.$store.dispatch('newCallForward/setSelectedDestType', 'busy')
},
cancel () {
this.enabled = false
},
add () {
this.enabled = true
this.close()
},
close () {
this.enabled = false
this.$emit('close')
}
}
}

@ -1,6 +1,5 @@
<template>
<div
v-if="enabled"
class="csc-form q-pa-lg"
:class="{ 'csc-cf-popover-hide': toggleFormVisibility}"
>
@ -132,7 +131,6 @@ export default {
return {
mode: 'create',
loading: false,
enabled: false,
number: '',
numberError: false,
destinationIndex: null,
@ -206,15 +204,12 @@ export default {
},
cancel () {
this.number = ''
this.enabled = false
this.$emit('close')
this.close()
},
add () {
this.number = ''
this.enabled = true
},
close () {
this.enabled = false
this.$emit('close')
},
reset () {

@ -285,9 +285,16 @@
"weekdaysLabel": "If weekdays are ...",
"weekdayLabel": "If weekday is ...",
"weekdaysLabelShort": " weekdays are ",
"officeHoursLabelShort": " office hour is | office hours are",
"weekdays":"weekdays",
"weekdayLabelShort": " weekday is ",
"officeHoursLabel": "If office hours are ...",
"offlineLabel": "If not available",
"officeHoursTitle": "Office hours",
"officeHoursAddBtnLabel": "Add time range",
"officeHoursInvalidTimerange": "Please select a valid timerange",
"daysOfTheWeekShort": "M,T,W,T,F,S,S",
"sameOfficeHoursForAllDays": "Same time for all selected days",
"busyLabel": "If busy",
"sourcesetName": "List name",
"mandatoryDestinationLabel": "Please add a destination to the group before adding conditions",

Loading…
Cancel
Save