diff --git a/src/app/locale/en/en.js b/src/app/locale/en/en.js index e27b53f5e..484b7569a 100644 --- a/src/app/locale/en/en.js +++ b/src/app/locale/en/en.js @@ -428,6 +428,7 @@ export default { start: 'Start', end: 'End', workWeek: 'Working week', + specialTime: 'Special time', holidays: 'Holiday | Holidays', date: 'Date', repeat: 'Repeat', diff --git a/src/app/locale/ru/ru.js b/src/app/locale/ru/ru.js index a0c1d90c4..925a07f63 100644 --- a/src/app/locale/ru/ru.js +++ b/src/app/locale/ru/ru.js @@ -434,6 +434,7 @@ export default { start: 'Начало', end: 'Конец', workWeek: 'Рабочая неделя', + specialTime: 'Особенное время', holidays: 'Выходной | Выходные', date: 'Дата', repeat: 'Повторить', diff --git a/src/app/locale/ua/ua.js b/src/app/locale/ua/ua.js index 1d358aeff..3d853ddd1 100644 --- a/src/app/locale/ua/ua.js +++ b/src/app/locale/ua/ua.js @@ -429,6 +429,7 @@ export default { start: 'Початок', end: 'Кінець', workWeek: 'Робочий тиждень', + specialTime: 'Особливий час', holidays: 'Вихідний | Вихідні', date: 'Дата', repeat: 'Повторювати', diff --git a/src/modules/contact-center/modules/queues/components/opened-queue-general.vue b/src/modules/contact-center/modules/queues/components/opened-queue-general.vue index 7ff2c5acb..ed32c5c80 100644 --- a/src/modules/contact-center/modules/queues/components/opened-queue-general.vue +++ b/src/modules/contact-center/modules/queues/components/opened-queue-general.vue @@ -15,7 +15,7 @@ @input="setItemProp({ prop: 'name', value: $event })" /> {{ item.schema.name }} diff --git a/src/modules/contact-center/modules/teams/modules/hooks/components/opened-team-hooks.vue b/src/modules/contact-center/modules/teams/modules/hooks/components/opened-team-hooks.vue index 480c62e72..a1a1103bd 100644 --- a/src/modules/contact-center/modules/teams/modules/hooks/components/opened-team-hooks.vue +++ b/src/modules/contact-center/modules/teams/modules/hooks/components/opened-team-hooks.vue @@ -64,6 +64,7 @@ {{ item.schema.name }} diff --git a/src/modules/integrations/modules/email-profiles/components/the-email-profiles.vue b/src/modules/integrations/modules/email-profiles/components/the-email-profiles.vue index 42ac26672..5db8b46a2 100644 --- a/src/modules/integrations/modules/email-profiles/components/the-email-profiles.vue +++ b/src/modules/integrations/modules/email-profiles/components/the-email-profiles.vue @@ -85,6 +85,7 @@ {{ item.schema.name }} diff --git a/src/modules/integrations/modules/triggers/components/the-triggers.vue b/src/modules/integrations/modules/triggers/components/the-triggers.vue index a4ecf6e96..24f0e6fbf 100644 --- a/src/modules/integrations/modules/triggers/components/the-triggers.vue +++ b/src/modules/integrations/modules/triggers/components/the-triggers.vue @@ -89,6 +89,7 @@ v-if="item.schema" :id="item.schema.id" :route-name="RouteNames.FLOW" + target="_blank" > {{ item.schema.name }} diff --git a/src/modules/lookups/modules/calendars/api/calendars.js b/src/modules/lookups/modules/calendars/api/calendars.js index 02e9cfa0e..b77addf4f 100644 --- a/src/modules/lookups/modules/calendars/api/calendars.js +++ b/src/modules/lookups/modules/calendars/api/calendars.js @@ -48,6 +48,7 @@ const getCalendar = async ({ itemId: id }) => { expires: !!(copy.startAt || copy.endAt), accepts: [], excepts: [], + specials: [], }; // eslint-disable-next-line no-param-reassign copy.accepts = copy.accepts.map((accept) => ({ @@ -56,6 +57,14 @@ const getCalendar = async ({ itemId: id }) => { start: accept.startTimeOfDay || 0, end: accept.endTimeOfDay || 0, })); + if(copy.specials) { + copy.specials = copy.specials.map((special) => ({ + day: special.day || 0, + disabled: special.disabled || false, + start: special.startTimeOfDay || 0, + end: special.endTimeOfDay || 0, + })); + } if (copy.excepts) { // eslint-disable-next-line no-param-reassign copy.excepts = copy.excepts.map((except) => ({ @@ -87,6 +96,7 @@ const fieldsToSend = [ 'day', 'accepts', 'excepts', + 'specials', 'startTimeOfDay', 'endTimeOfDay', 'disabled', @@ -111,6 +121,13 @@ const preRequestHandler = (item) => { startTimeOfDay: accept.start, endTimeOfDay: accept.end, })); + + copy.specials = copy.specials.map((special) => ({ + day: special.day, + disabled: special.disabled, + startTimeOfDay: special.start, + endTimeOfDay: special.end, + })); return copy; }; diff --git a/src/modules/lookups/modules/calendars/components/opened-calendar-special-time.vue b/src/modules/lookups/modules/calendars/components/opened-calendar-special-time.vue new file mode 100644 index 000000000..bbf2c074a --- /dev/null +++ b/src/modules/lookups/modules/calendars/components/opened-calendar-special-time.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/src/modules/lookups/modules/calendars/components/opened-calendar-work-week.vue b/src/modules/lookups/modules/calendars/components/opened-calendar-work-week.vue index eb3218734..db9a3238e 100644 --- a/src/modules/lookups/modules/calendars/components/opened-calendar-work-week.vue +++ b/src/modules/lookups/modules/calendars/components/opened-calendar-work-week.vue @@ -16,7 +16,7 @@ > @@ -46,12 +48,12 @@ @@ -61,68 +63,19 @@ diff --git a/src/modules/lookups/modules/calendars/components/opened-calendar.vue b/src/modules/lookups/modules/calendars/components/opened-calendar.vue index 88ffaae2a..fecf79338 100644 --- a/src/modules/lookups/modules/calendars/components/opened-calendar.vue +++ b/src/modules/lookups/modules/calendars/components/opened-calendar.vue @@ -46,10 +46,11 @@ import CalendarRouteNames from '../router/_internals/CalendarRouteNames.enum.js' import General from './opened-calendar-general.vue'; import Holidays from './opened-calendar-holidays.vue'; import WorkWeek from './opened-calendar-work-week.vue'; +import SpecialTime from './opened-calendar-special-time.vue'; export default { name: 'OpenedCalendar', - components: { General, WorkWeek, Holidays }, + components: { General, WorkWeek, Holidays, SpecialTime }, mixins: [openedObjectMixin], setup: () => ({ @@ -70,6 +71,12 @@ export default { timerangeStartLessThanEnd, }), }, + specials: { + timerangeNotIntersect, + $each: helpers.forEach({ + timerangeStartLessThanEnd, + }), + }, }, }, @@ -79,6 +86,7 @@ export default { { value: 'general', text: this.$t('objects.general'), pathName: CalendarRouteNames.GENERAL }, { value: 'work-week', text: this.$t('objects.lookups.calendars.workWeek'), pathName: CalendarRouteNames.WORKING_WEEK }, { value: 'holidays', text: this.$tc('objects.lookups.calendars.holidays', 2), pathName: CalendarRouteNames.HOLIDAYS }, + { value: 'special-time', text: this.$t('objects.lookups.calendars.specialTime'), pathName: CalendarRouteNames.SPECIAL_TIME }, ]; if (this.id) tabs.push(this.permissionsTab); diff --git a/src/modules/lookups/modules/calendars/composables/useWeekDaysData.js b/src/modules/lookups/modules/calendars/composables/useWeekDaysData.js new file mode 100644 index 000000000..88974a0a5 --- /dev/null +++ b/src/modules/lookups/modules/calendars/composables/useWeekDaysData.js @@ -0,0 +1,88 @@ +import getNamespacedState from '@webitel/ui-sdk/src/store/helpers/getNamespacedState.js'; +import { computed } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useStore } from 'vuex'; + +export function useWeekDaysData(namespace, dataName) { + const { t } = useI18n(); + const store = useStore(); + + const dataList = computed( + () => getNamespacedState(store.state, namespace).itemInstance[dataName], + ); + + const headers = computed(() => { + return [ + { + value: 'name', + text: t('objects.name'), + }, + { + value: 'start', + text: t('objects.lookups.calendars.start'), + }, + { + value: 'end', + text: t('objects.lookups.calendars.end'), + }, + { + value: 'state', + text: t('reusable.state'), + }, + ]; + }); + + const weekDaysList = computed(() => { + return [ + t('objects.lookups.calendars.mon'), + t('objects.lookups.calendars.tue'), + t('objects.lookups.calendars.wed'), + t('objects.lookups.calendars.thu'), + t('objects.lookups.calendars.fri'), + t('objects.lookups.calendars.sat'), + t('objects.lookups.calendars.sun'), + ]; + }); + + function setItemProp(payload) { + return store.dispatch(`${namespace}/SET_CALENDAR_ITEM_PROPERTY`, { name: dataName, ...payload}); + } + + function addRange(day) { + return store.dispatch(`${namespace}/ADD_RANGE`, { day, name: dataName }); + } + + function removeRange(index) { + return store.dispatch(`${namespace}/REMOVE_RANGE`, { index, name: dataName}); + } + + function isDayStart(index) { + if (index === 0) return true; + return ( + dataList.value[index].day !== // this day index is not equal to + dataList.value[index - 1].day + ); // prev day index + } + + function minToSec(min) { + return min * 60; + } + + function secToMin(sec) { + return sec / 60; + } + + return { + dataList, + headers, + weekDaysList, + + setItemProp, + addRange, + removeRange, + + isDayStart, + minToSec, + secToMin, + }; +} diff --git a/src/modules/lookups/modules/calendars/router/_internals/CalendarRouteNames.enum.js b/src/modules/lookups/modules/calendars/router/_internals/CalendarRouteNames.enum.js index 72eadb014..df3c6d9be 100644 --- a/src/modules/lookups/modules/calendars/router/_internals/CalendarRouteNames.enum.js +++ b/src/modules/lookups/modules/calendars/router/_internals/CalendarRouteNames.enum.js @@ -3,5 +3,6 @@ export default Object.freeze({ GENERAL: `${RouteNames.CALENDARS}-general`, WORKING_WEEK: `${RouteNames.CALENDARS}-working-week`, HOLIDAYS: `${RouteNames.CALENDARS}-holidays`, + SPECIAL_TIME: `${RouteNames.CALENDARS}-special-time`, PERMISSIONS: `${RouteNames.CALENDARS}-permissions`, }); diff --git a/src/modules/lookups/modules/calendars/router/calendars.js b/src/modules/lookups/modules/calendars/router/calendars.js index c163bf632..bc383eb85 100644 --- a/src/modules/lookups/modules/calendars/router/calendars.js +++ b/src/modules/lookups/modules/calendars/router/calendars.js @@ -8,6 +8,7 @@ const OpenedCalendar = () => import('../components/opened-calendar.vue'); const OpenedCalendarGeneral = () => import('../components/opened-calendar-general.vue'); const OpenedCalendarHolidays = () => import('../components/opened-calendar-holidays.vue'); const OpenedCalendarWorkingWeek = () => import('../components/opened-calendar-work-week.vue'); +const OpenedCalendarSpecialTime = () => import('../components/opened-calendar-special-time.vue'); const PermissionsTab = () => import("../../../../_shared/permissions-tab/components/permissions-tab.vue"); const CalendarsRoutes = [ @@ -36,6 +37,10 @@ const CalendarsRoutes = [ path: 'holidays/:holidayIndex?', name: CalendarRouteNames.HOLIDAYS, component: OpenedCalendarHolidays, + },{ + path: 'special-time', + name: CalendarRouteNames.SPECIAL_TIME, + component: OpenedCalendarSpecialTime, },{ path: 'permissions/:permissionId?', name: CalendarRouteNames.PERMISSIONS, diff --git a/src/modules/lookups/modules/calendars/store/calendars.js b/src/modules/lookups/modules/calendars/store/calendars.js index 57fcfeac5..c52d36460 100644 --- a/src/modules/lookups/modules/calendars/store/calendars.js +++ b/src/modules/lookups/modules/calendars/store/calendars.js @@ -16,6 +16,19 @@ const defaultAccepts = () => { return accepts; }; +const defaultSpecials = () => { + const specials = []; + for (let i = 0; i < 7; i++) { + specials.push({ + day: i, + disabled: true, + start: 9 * 60, + end: 20 * 60, + }); + } + return specials; +}; + const resettableState = { itemInstance: { name: '', @@ -25,21 +38,22 @@ const resettableState = { endAt: Date.now(), expires: false, accepts: defaultAccepts(), + specials: defaultSpecials(), excepts: [], }, }; const actions = { - SET_ACCEPT_ITEM_PROPERTY: async (context, payload) => { - context.commit('SET_ACCEPT_ITEM_PROPERTY', payload); + SET_CALENDAR_ITEM_PROPERTY: async (context, payload) => { + context.commit('SET_CALENDAR_ITEM_PROPERTY', payload); context.commit('SET_ITEM_PROPERTY', { prop: '_dirty', value: true, }); }, - ADD_ACCEPT_ITEM: (context, day) => { - const value = context.state.itemInstance.accepts; + ADD_RANGE: (context, { day, name }) => { + const value = context.state.itemInstance[name]; // iterates through array and tries to find first day next to param day const dayIndex = value.findIndex((workday) => workday.day > day); const dayItem = { @@ -50,7 +64,7 @@ const actions = { }; value.splice(dayIndex, 0, dayItem); context.commit('SET_ITEM_PROPERTY', { - prop: 'accepts', + prop: name, value, }); context.commit('SET_ITEM_PROPERTY', { @@ -59,11 +73,11 @@ const actions = { }); }, - REMOVE_ACCEPT_ITEM: (context, index) => { - const value = context.state.itemInstance.accepts; + REMOVE_RANGE: (context, { index, name} ) => { + const value = context.state.itemInstance[name]; value.splice(index, 1); context.commit('SET_ITEM_PROPERTY', { - prop: 'accepts', + prop: name, value, }); context.commit('SET_ITEM_PROPERTY', { @@ -71,6 +85,12 @@ const actions = { value: true, }); }, + INITIALIZE_SPECIALS: (context) => { + context.commit('SET_ITEM_PROPERTY', { + prop: 'specials', + value: defaultSpecials(), + }); + }, ADD_EXCEPT_ITEM: (context, item) => { const value = context.state.itemInstance.excepts.concat(item); @@ -127,7 +147,8 @@ const actions = { Promise.allSettled(deleted.map((item) => context.dispatch('DELETE_SINGLE_EXCEPT_ITEM', item))), SET_EXCEPT_ITEM_PROPERTY: (context, { index, prop, value }) => { - context.commit('SET_EXCEPT_ITEM_PROPERTY', { + context.commit('SET_CALENDAR_ITEM_PROPERTY', { + name: 'excepts', index, prop, value, @@ -140,12 +161,8 @@ const actions = { }; const mutations = { - SET_ACCEPT_ITEM_PROPERTY: (state, { prop, index, value }) => { - state.itemInstance.accepts[index][prop] = value; - }, - - SET_EXCEPT_ITEM_PROPERTY: (state, { index, prop, value }) => { - state.itemInstance.excepts[index][prop] = value; + SET_CALENDAR_ITEM_PROPERTY: (state, { name, prop, index, value }) => { + state.itemInstance[name][index][prop] = value; }, }; diff --git a/src/modules/routing/modules/chat-gateways/components/the-chat-gateways.vue b/src/modules/routing/modules/chat-gateways/components/the-chat-gateways.vue index 8da2bd427..51a5ea668 100644 --- a/src/modules/routing/modules/chat-gateways/components/the-chat-gateways.vue +++ b/src/modules/routing/modules/chat-gateways/components/the-chat-gateways.vue @@ -93,6 +93,7 @@ v-if="item.flow" :id="item.flow.id" :route-name="RouteNames.FLOW" + target="_blank" > {{ item.flow.name }} diff --git a/src/modules/routing/modules/chatplan/components/the-chatplan.vue b/src/modules/routing/modules/chatplan/components/the-chatplan.vue index 86f51eded..dc15004cd 100644 --- a/src/modules/routing/modules/chatplan/components/the-chatplan.vue +++ b/src/modules/routing/modules/chatplan/components/the-chatplan.vue @@ -87,6 +87,7 @@ v-if="item.schema" :id="item.schema.id" :route-name="RouteNames.FLOW" + target="_blank" > {{ item.schema.name }} diff --git a/src/modules/routing/modules/dialplan/components/the-dialplan.vue b/src/modules/routing/modules/dialplan/components/the-dialplan.vue index d73b8a574..fbb5fb749 100644 --- a/src/modules/routing/modules/dialplan/components/the-dialplan.vue +++ b/src/modules/routing/modules/dialplan/components/the-dialplan.vue @@ -87,6 +87,7 @@ v-if="item.schema" :id="item.schema.id" :route-name="RouteNames.FLOW" + target="_blank" > {{ item.schema.name }}