From aee3a58988c8d1acca2a5c56bf4e0e54a3058a06 Mon Sep 17 00:00:00 2001 From: Lera24 Date: Wed, 18 Sep 2024 16:22:50 +0300 Subject: [PATCH 1/2] feature: add special time tab in calendars page[WTEL-4099] --- src/app/locale/en/en.js | 1 + src/app/locale/ru/ru.js | 1 + src/app/locale/ua/ua.js | 1 + .../modules/calendars/api/calendars.js | 17 +++ .../opened-calendar-special-time.vue | 106 ++++++++++++++++++ .../components/opened-calendar-work-week.vue | 75 +++---------- .../calendars/components/opened-calendar.vue | 10 +- .../calendars/composables/useWeekDaysData.js | 88 +++++++++++++++ .../_internals/CalendarRouteNames.enum.js | 1 + .../modules/calendars/router/calendars.js | 5 + .../modules/calendars/store/calendars.js | 47 +++++--- 11 files changed, 274 insertions(+), 78 deletions(-) create mode 100644 src/modules/lookups/modules/calendars/components/opened-calendar-special-time.vue create mode 100644 src/modules/lookups/modules/calendars/composables/useWeekDaysData.js diff --git a/src/app/locale/en/en.js b/src/app/locale/en/en.js index adc52695e..17fa6b52f 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 fae81a5c2..f15b7e36c 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 4e8a11543..ba6555afd 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/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..470003e0e --- /dev/null +++ b/src/modules/lookups/modules/calendars/components/opened-calendar-special-time.vue @@ -0,0 +1,106 @@ + + + + + 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..8c6158c09 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 @@ > @@ -61,68 +61,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; }, }; From b7a95831bb0d27bc6197e9e7432c3024b9b38bfe Mon Sep 17 00:00:00 2001 From: Lera24 Date: Fri, 20 Sep 2024 11:49:22 +0300 Subject: [PATCH 2/2] fix/display label in timepicker[WTEL-5081] --- package-lock.json | 8 ++++---- package.json | 2 +- .../calendars/components/opened-calendar-special-time.vue | 5 ++--- .../calendars/components/opened-calendar-work-week.vue | 2 ++ 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77400f7d5..49a860799 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@vuelidate/validators": "^2.0.4", "@vueuse/core": "^11.0.3", "@webitel/flow-ui-sdk": "^0.1.14", - "@webitel/ui-sdk": "^24.10.11", + "@webitel/ui-sdk": "^24.10.15", "axios": "^1.7.7", "clipboard-copy": "^4.0.1", "cron-validator": "^1.3.1", @@ -2131,9 +2131,9 @@ } }, "node_modules/@webitel/ui-sdk": { - "version": "24.10.11", - "resolved": "https://registry.npmjs.org/@webitel/ui-sdk/-/ui-sdk-24.10.11.tgz", - "integrity": "sha512-tM9Q6UD+4Ykzw7S27L7DEeMLwUgowPpSEMoI4V0bFXvUKRS8YCzS+I50n5jiCA3puvVjZSnnUR3U8r98YNgdDw==", + "version": "24.10.15", + "resolved": "https://registry.npmjs.org/@webitel/ui-sdk/-/ui-sdk-24.10.15.tgz", + "integrity": "sha512-rq34Y6xL5Nez599wopFU3Y/8+ufeX7QomGg/KK0bRmyOzbzYLL3PBb5cFu71vV9s/Ercq1hUVgVmmErI3ENvZg==", "dependencies": { "@floating-ui/vue": "^1.0.1", "@morev/vue-transitions": "^3.0.2", diff --git a/package.json b/package.json index a4bc33085..9fb15ba19 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@vuelidate/validators": "^2.0.4", "@vueuse/core": "^11.0.3", "@webitel/flow-ui-sdk": "^0.1.14", - "@webitel/ui-sdk": "^24.10.11", + "@webitel/ui-sdk": "^24.10.15", "axios": "^1.7.7", "clipboard-copy": "^4.0.1", "cron-validator": "^1.3.1", 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 index 470003e0e..bbf2c074a 100644 --- a/src/modules/lookups/modules/calendars/components/opened-calendar-special-time.vue +++ b/src/modules/lookups/modules/calendars/components/opened-calendar-special-time.vue @@ -24,6 +24,7 @@ :disabled="disableUserInput" :value="minToSec(item.start)" format="hh:mm" + noLabel @input="setItemProp({prop: 'start', index, value: secToMin($event)})" /> @@ -32,6 +33,7 @@ :disabled="disableUserInput" :value="minToSec(item.end)" format="hh:mm" + noLabel @input="setItemProp({prop: 'end', index, value: secToMin($event)})" /> @@ -100,7 +102,4 @@ export default { 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 8c6158c09..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 @@ -24,6 +24,7 @@ :disabled="disableUserInput" :value="minToSec(item.start)" format="hh:mm" + noLabel @input="setItemProp({ prop: 'start', index, value: secToMin($event)})" /> @@ -32,6 +33,7 @@ :disabled="disableUserInput" :value="minToSec(item.end)" format="hh:mm" + noLabel @input="setItemProp({prop: 'end', index, value: secToMin($event)})" />