diff --git a/package-lock.json b/package-lock.json index 7e2d63d93..299291a9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@fullcalendar/multimonth": "6.1.19", "@fullcalendar/vue3": "6.1.19", "@google/model-viewer": "4.1.0", - "@sentry/vue": "10.31.0", + "@sentry/vue": "10.32.0", "@unhead/vue": "2.0.19", "@vuepic/vue-datepicker": "11.0.3", "async": "3.2.6", @@ -30,7 +30,7 @@ "exceljs": "4.4.0", "fabric": "cgwire/fabric.js", "file-saver": "2.0.5", - "lucide-vue-next": "0.561.0", + "lucide-vue-next": "0.562.0", "marked": "17.0.1", "marked-emoji": "2.0.2", "moment": "2.30.1", @@ -2257,97 +2257,101 @@ ] }, "node_modules/@sentry-internal/browser-utils": { - "version": "10.31.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.31.0.tgz", - "integrity": "sha512-2Pvk0aRA0M/wiUj2K00mhw8dhD/zRhGKK9xQVAPtSz9cbKO/0WIS5dMAX0bfNvYVVMQPrQM46BmEwxeMMuY6HQ==", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.32.0.tgz", + "integrity": "sha512-LI83ZKv5ItRajfY7xmQpNs00nWNOXO+A6MCj8LNDpPouYA8m7VvqkCKG9Yh50a/5eIO9lbSWTrARO8rWR3c9jA==", "license": "MIT", "dependencies": { - "@sentry/core": "10.31.0" + "@sentry/core": "10.32.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/feedback": { - "version": "10.31.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.31.0.tgz", - "integrity": "sha512-uLmh6n0Ax/yjVO4FROpeVqzEJVMgIxDsnmKlAoQ4/HYmc2wQQbJmdIgjzZN2ruelaYEaQV7iouSYLZv4wdujOQ==", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.32.0.tgz", + "integrity": "sha512-YjDdVR8Ep7lOGilRfSrioBKQlFzWP+j1ibL+9rfwYPWWeQSfK2mbg8+PmbWOcTIXZ/MpuZRMF6ZdkVi7VYBSJw==", "license": "MIT", "dependencies": { - "@sentry/core": "10.31.0" + "@sentry/core": "10.32.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay": { - "version": "10.31.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.31.0.tgz", - "integrity": "sha512-1rChhtgSSq83vef/ZID5vNRGgCVOdi3c239J3T0GWUSrmZAWHFWohqosT1jBYLIcBQia1jjJjl7j0QX0UNpSsg==", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.32.0.tgz", + "integrity": "sha512-P6paw7bLDP72ZNJkcyKSXCXfd+/NKwRfnJpwgkRI9kjy9o0KZrIW2P/xTGftp5q1XxQ7tCt94j2gc1HelOpngw==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "10.31.0", - "@sentry/core": "10.31.0" + "@sentry-internal/browser-utils": "10.32.0", + "@sentry/core": "10.32.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "10.31.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.31.0.tgz", - "integrity": "sha512-mR6t6YNMLKndn1FvaDoOTWA15LfatcC/RMXkKYggULJWxMOs1/TCowjVidPXb/2JtfeHQvbJg5dH/hM+wW5c1Q==", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.32.0.tgz", + "integrity": "sha512-GdhyRKywIP9IQc7RoTrBFjx2EFBjiRSndxeiW43qybO1xD2S5Cq/S7ZwkaJOXN8Ie1awm3/E6+mVct5jc6KKAg==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "10.31.0", - "@sentry/core": "10.31.0" + "@sentry-internal/replay": "10.32.0", + "@sentry/core": "10.32.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/browser": { - "version": "10.31.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.31.0.tgz", - "integrity": "sha512-r+unS+yzVn4lh+jRGtR1rhfcPFsSJXDzW9ngn8+VmgzuvBMLVNSVEwCO+HsghnFfWorrXYZ6GVhemsGHK8gsfg==", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.32.0.tgz", + "integrity": "sha512-NtQlXQybrWMbUOPENS4bvxzhMX1Oi+IUH9NXA/mZ06KbQntPLES7yfIKhLNpRipuCzeS16hCJp6HMao2bZB2Hg==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "10.31.0", - "@sentry-internal/feedback": "10.31.0", - "@sentry-internal/replay": "10.31.0", - "@sentry-internal/replay-canvas": "10.31.0", - "@sentry/core": "10.31.0" + "@sentry-internal/browser-utils": "10.32.0", + "@sentry-internal/feedback": "10.32.0", + "@sentry-internal/replay": "10.32.0", + "@sentry-internal/replay-canvas": "10.32.0", + "@sentry/core": "10.32.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/core": { - "version": "10.31.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.31.0.tgz", - "integrity": "sha512-VTSXdyhnu3CNaSwhp/CchZRCKh1fa7byP+KClApthsppQ57w7OjXN8dDUf38K1ZCsfdTEvdEU4qCL/WnAEbd+g==", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.32.0.tgz", + "integrity": "sha512-E+ihb8+5PBfYMamnXHalgsmxkcG2YQqhRdgYf3yWJ5dJvi4njh1VWK3kNVj1GvsU6ktaielAx4Rg5dwEFMnbZg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/vue": { - "version": "10.31.0", - "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-10.31.0.tgz", - "integrity": "sha512-3CbF1yd5dq46K2eX+mN7cAXJOchFL5x1tYtUDWQPGAkMxsMV7mqun/eXabZWBSlRzDbevl0s364dNjPNs+1btg==", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-10.32.0.tgz", + "integrity": "sha512-n4foL3xWqrxxM8rhsToFLx+JLQwW8h2XTMbbMQjNFymgAsAgCEU/Cpib1EudJM5m1KCfnEMqsaqPDitQmP+e8Q==", "license": "MIT", "dependencies": { - "@sentry/browser": "10.31.0", - "@sentry/core": "10.31.0" + "@sentry/browser": "10.32.0", + "@sentry/core": "10.32.0" }, "engines": { "node": ">=18" }, "peerDependencies": { + "@tanstack/vue-router": "^1.64.0", "pinia": "2.x || 3.x", "vue": "2.x || 3.x" }, "peerDependenciesMeta": { + "@tanstack/vue-router": { + "optional": true + }, "pinia": { "optional": true } @@ -6721,9 +6725,9 @@ } }, "node_modules/lucide-vue-next": { - "version": "0.561.0", - "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.561.0.tgz", - "integrity": "sha512-c5HUckO0qHklVSOf/0vaSR3pEb8fYImRDCRDLde56uqS9js0D/e3RAvq0/YFWjkmyOBKCb0/IdskdoHZQEkT5g==", + "version": "0.562.0", + "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.562.0.tgz", + "integrity": "sha512-LN0BLGKMFulv0lnfK29r14DcngRUhIqdcaL0zXTt2o0oS9odlrjCGaU3/X9hIihOjjN8l8e+Y9G/famcNYaI7Q==", "license": "ISC", "peerDependencies": { "vue": ">=3.0.1" diff --git a/package.json b/package.json index b388a8c4d..fb0c9ab44 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@fullcalendar/multimonth": "6.1.19", "@fullcalendar/vue3": "6.1.19", "@google/model-viewer": "4.1.0", - "@sentry/vue": "10.31.0", + "@sentry/vue": "10.32.0", "@unhead/vue": "2.0.19", "@vuepic/vue-datepicker": "11.0.3", "async": "3.2.6", @@ -40,7 +40,7 @@ "exceljs": "4.4.0", "fabric": "cgwire/fabric.js", "file-saver": "2.0.5", - "lucide-vue-next": "0.561.0", + "lucide-vue-next": "0.562.0", "marked": "17.0.1", "marked-emoji": "2.0.2", "moment": "2.30.1", diff --git a/src/components/lists/TimesheetList.vue b/src/components/lists/TimesheetList.vue index 24019ae75..8b3f7c8d7 100644 --- a/src/components/lists/TimesheetList.vue +++ b/src/components/lists/TimesheetList.vue @@ -6,6 +6,7 @@ :can-delete="false" :min-date="disabledDates.to" :max-date="disabledDates.from" + utc :with-margin="false" v-model="selectedDate" /> @@ -201,7 +202,7 @@ " :is-error="isDayOffError" :error-text="dayOffTextError" - @confirm="$emit('unset-day-off')" + @confirm="$emit('unset-day-off', personDayOff)" @cancel="closeUnsetDayOffModal" /> @@ -259,6 +260,10 @@ export default { default: false, type: Boolean }, + daysOff: { + default: () => [], + type: Array + }, dayOffError: { default: false, type: [String, Boolean] @@ -316,13 +321,24 @@ export default { ...mapGetters([ 'isCurrentUserArtist', 'organisation', - 'personDayOff', - 'personIsDayOff', 'productionMap', 'taskTypeMap', 'user' ]), + personDayOff() { + const selectedDate = moment(this.selectedDate).format('YYYY-MM-DD') + return this.daysOff.find( + dayOff => + selectedDate >= dayOff.date && + selectedDate <= (dayOff.end_date || dayOff.date) + ) + }, + + personIsDayOff() { + return Boolean(this.personDayOff) + }, + displayedTasks() { return this.tasks.slice(0, this.page * (PAGE_SIZE / 2)) }, diff --git a/src/components/pages/Person.vue b/src/components/pages/Person.vue index 42d417e29..a70b7c263 100644 --- a/src/components/pages/Person.vue +++ b/src/components/pages/Person.vue @@ -109,6 +109,7 @@ :done-tasks="loggableDoneTasks" :is-loading="isTasksLoading" :is-error="isTasksLoadingError" + :days-off="daysOff" :day-off-error="dayOffError" :time-spent-map="personTimeSpentMap" :time-spent-total="personTimeSpentTotal" @@ -688,6 +689,11 @@ export default { this.isTasksLoadingError = true } + this.loadDaysOff() + }, + + async loadDaysOff() { + const personId = this.person.id try { this.daysOff = await this.loadAggregatedPersonDaysOff({ personId }) } catch (error) { @@ -784,16 +790,18 @@ export default { } catch (error) { this.dayOffError = error.body?.message || true } + await this.loadDaysOff() }, - async onUnsetDayOff() { + async onUnsetDayOff(dayOff) { this.dayOffError = false try { - await this.unsetDayOff() + await this.unsetDayOff(dayOff) this.$refs['timesheet-list']?.closeUnsetDayOffModal() } catch (error) { this.dayOffError = error.body?.message || true } + await this.loadDaysOff() }, saveTaskScheduleItem(item) { diff --git a/src/components/pages/Todos.vue b/src/components/pages/Todos.vue index e67febaea..554856377 100644 --- a/src/components/pages/Todos.vue +++ b/src/components/pages/Todos.vue @@ -109,6 +109,7 @@ :done-tasks="loggableDoneTasks" :is-loading="loading.timesheets || isTodosLoading" :is-error="isTodosLoadingError" + :days-off="daysOff" :day-off-error="dayOffError" :time-spent-map="timeSpentMap" :time-spent-total="timeSpentTotal" @@ -514,7 +515,7 @@ export default { await this.loadData(true) }, - async onUnsetDayOff(dayOff = null) { + async onUnsetDayOff(dayOff) { this.dayOffError = false try { await this.unsetDayOff(dayOff) diff --git a/src/store/modules/people.js b/src/store/modules/people.js index 8b885f70f..77a39ae68 100644 --- a/src/store/modules/people.js +++ b/src/store/modules/people.js @@ -34,7 +34,6 @@ import { CLEAR_SELECTED_TASKS, SET_TIME_SPENT, PEOPLE_TIMESHEET_LOADED, - PERSON_SET_DAY_OFF, PERSON_LOAD_TIME_SPENTS_END, SET_ORGANISATION, SET_PERSON_TASKS_SCROLL_POSITION, @@ -209,8 +208,6 @@ const getters = { timesheet: state => state.timesheet, personTimeSpentMap: state => state.personTimeSpentMap, personTimeSpentTotal: state => state.personTimeSpentTotal, - personDayOff: state => state.personDayOff, - personIsDayOff: state => Boolean(state.personDayOff?.id), dayOffMap: state => state.dayOffMap, daysOff: state => state.daysOff } @@ -359,13 +356,11 @@ const actions = { }) commit(LOAD_PERSON_DONE_TASKS_END, []) - const [tasks, timeSpents, dayOff] = await Promise.all([ + const [tasks, timeSpents] = await Promise.all([ peopleApi.getPersonTasks(personId).catch(() => []), - peopleApi.getTimeSpents(personId, date), - peopleApi.getDayOff(personId, date) + peopleApi.getTimeSpents(personId, date) ]) commit(PERSON_LOAD_TIME_SPENTS_END, timeSpents || []) - commit(PERSON_SET_DAY_OFF, dayOff || {}) commit(LOAD_PERSON_TASKS_END, { personId, tasks, @@ -471,30 +466,14 @@ const actions = { commit(SET_TIME_SPENT, timeSpent) }, - async setDayOff({ commit }, { id, personId, date, end_date, description }) { - let dayOff - if (id) { - dayOff = await peopleApi.updateDayOff( - id, - personId, - date, - end_date, - description - ) - } else { - dayOff = await peopleApi.createDayOff( - personId, - date, - end_date, - description - ) - } - commit(PERSON_SET_DAY_OFF, dayOff) + setDayOff(_, { id, personId, date, end_date, description }) { + return id + ? peopleApi.updateDayOff(id, personId, date, end_date, description) + : peopleApi.createDayOff(personId, date, end_date, description) }, - async unsetDayOff({ commit }, dayOff = null) { - await peopleApi.deleteDayOff(dayOff || state.personDayOff) - commit(PERSON_SET_DAY_OFF, {}) + async unsetDayOff(_, dayOff) { + await peopleApi.deleteDayOff(dayOff) }, setPersonTasksScrollPosition({ commit }, scrollPosition) { @@ -852,10 +831,6 @@ const mutations = { ) / 60 }, - [PERSON_SET_DAY_OFF](state, dayOff) { - state.personDayOff = dayOff - }, - [PEOPLE_SET_DAYS_OFF](state, daysOff) { state.daysOff = daysOff }, diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 60866cad6..10e390ec7 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -37,7 +37,6 @@ import { USER_LOAD_DONE_TASKS_END, USER_LOAD_TIME_SPENTS_END, REGISTER_USER_TASKS, - PERSON_SET_DAY_OFF, SET_TODOS_SEARCH, LOAD_USER_FILTERS_END, LOAD_USER_FILTERS_ERROR, @@ -281,11 +280,9 @@ const actions = { try { const tasks = await peopleApi.loadTodos() const timeSpents = await peopleApi.loadTimeSpents(date) - const dayOff = await peopleApi.getDayOff(state.user.id, date) commit(USER_LOAD_TODOS_END, { tasks, userFilters, taskTypeMap }) commit(REGISTER_USER_TASKS, { tasks }) commit(USER_LOAD_TIME_SPENTS_END, timeSpents) - commit(PERSON_SET_DAY_OFF, dayOff) return tasks } catch (err) { console.error(err) diff --git a/src/store/mutation-types.js b/src/store/mutation-types.js index f1d15229c..ec80e1434 100644 --- a/src/store/mutation-types.js +++ b/src/store/mutation-types.js @@ -41,7 +41,6 @@ export const PEOPLE_TIMESHEET_LOADED = 'PEOPLE_TIMESHEET_LOADED' export const PEOPLE_SET_DAY_OFFS = 'PEOPLE_SET_DAY_OFFS' export const PEOPLE_SET_DAYS_OFF = 'PEOPLE_SET_DAYS_OFF' export const PERSON_LOAD_TIME_SPENTS_END = 'PERSON_LOAD_TIME_SPENTS_END' -export const PERSON_SET_DAY_OFF = 'PERSON_SET_DAY_OFF' export const SET_PERSON_TASKS_SCROLL_POSITION = 'SET_PERSON_TASKS_SCROLL_POSITION'