diff --git a/frontend/src/components/activity/ScheduleEntry.vue b/frontend/src/components/activity/ScheduleEntry.vue index 655ba7caa2..f0093491cc 100644 --- a/frontend/src/components/activity/ScheduleEntry.vue +++ b/frontend/src/components/activity/ScheduleEntry.vue @@ -164,11 +164,15 @@ Displays a single scheduleEntry @@ -31,7 +30,7 @@ import DialogForm from '@/components/dialog/DialogForm.vue' import DialogBase from '@/components/dialog/DialogBase.vue' import DialogActivityForm from './DialogActivityForm.vue' -import { scheduleEntryRoute } from '@/router.js' +import { firstActivityScheduleEntryRoute } from '@/router.js' export default { name: 'DialogActivityEdit', @@ -39,6 +38,10 @@ export default { extends: DialogBase, props: { scheduleEntry: { type: Object, required: true }, + hideHeaderFields: { + type: Boolean, + default: false, + }, }, data() { return { @@ -47,12 +50,15 @@ export default { } }, computed: { - scheduleEntries() { - return this.activity.scheduleEntries() - }, activity() { return this.scheduleEntry.activity() }, + period() { + return this.scheduleEntry.period() + }, + scheduleEntries() { + return this.activity.scheduleEntries() + }, }, watch: { showDialog: async function (showDialog) { @@ -95,24 +101,49 @@ export default { // update existing if (entry.self) { - return this.api.patch(entry.self, { + return this.api + .patch(entry.self, { + period: entry.period()._meta.self, + start: entry.start, + end: entry.end, + }) + .then((serverEntry) => { + entry.start = serverEntry.start + entry.end = serverEntry.end + entry.period = serverEntry.period + }) + .catch(async (e) => { + // entry was deleted in the meantime + if (e.response.status === 404) { + if (entry.self === this.scheduleEntry._meta.self) { + // redirect to first entry to not break UI + this.$router.push(await firstActivityScheduleEntryRoute(this.activity)) + } + entry.deleted = true + return Promise.resolve() + } + return Promise.reject(e) + }) + } + + // else: create new entry + return this.scheduleEntries + .$post({ period: entry.period()._meta.self, start: entry.start, end: entry.end, + activity: this.activity._meta.self, + }) + .then((data) => { + entry.self = data._meta.self }) - } - - // else: create new entry - return this.scheduleEntries.$post({ - period: entry.period()._meta.self, - start: entry.start, - end: entry.end, - activity: this.activity._meta.self, - }) }) // patch activity entity const activityPayload = { ...this.entityData } + if (this.hideHeaderFields) { + delete activityPayload.location + } delete activityPayload.scheduleEntries promises.push(this.api.patch(this.entityUri, activityPayload)) @@ -126,9 +157,10 @@ export default { }, updatedSuccessful(data) { this.close() + this.api.reload(this.activity) + this.api.reload(this.scheduleEntry.period().scheduleEntries()) this.$emit('activity-updated', data) }, - scheduleEntryRoute, }, } diff --git a/frontend/src/components/program/DialogActivityForm.vue b/frontend/src/components/activity/dialog/DialogActivityForm.vue similarity index 87% rename from frontend/src/components/program/DialogActivityForm.vue rename to frontend/src/components/activity/dialog/DialogActivityForm.vue index f1d9c7b5eb..b28db8a9d7 100644 --- a/frontend/src/components/program/DialogActivityForm.vue +++ b/frontend/src/components/activity/dialog/DialogActivityForm.vue @@ -36,11 +36,12 @@ - + @@ -69,10 +70,18 @@ export default { type: Object, required: true, }, + currentScheduleEntry: { + type: Object, + default: null, + }, autoselectTitle: { type: Boolean, default: false, }, + hideLocation: { + type: Boolean, + default: false, + }, }, data() { return { diff --git a/frontend/src/components/program/FormScheduleEntryItem.vue b/frontend/src/components/activity/dialog/FormScheduleEntryItem.vue similarity index 97% rename from frontend/src/components/program/FormScheduleEntryItem.vue rename to frontend/src/components/activity/dialog/FormScheduleEntryItem.vue index 2726ce06a6..fe35687130 100644 --- a/frontend/src/components/program/FormScheduleEntryItem.vue +++ b/frontend/src/components/activity/dialog/FormScheduleEntryItem.vue @@ -50,7 +50,7 @@ - + @@ -82,9 +82,9 @@ export default { }, // true if current item is the last scheduleEntry - isLastItem: { + deletable: { type: Boolean, - required: true, + required: false, }, }, data() { diff --git a/frontend/src/components/program/FormScheduleEntryList.vue b/frontend/src/components/activity/dialog/FormScheduleEntryList.vue similarity index 90% rename from frontend/src/components/program/FormScheduleEntryList.vue rename to frontend/src/components/activity/dialog/FormScheduleEntryList.vue index c0d7c1e716..ac79f70d12 100644 --- a/frontend/src/components/program/FormScheduleEntryList.vue +++ b/frontend/src/components/activity/dialog/FormScheduleEntryList.vue @@ -4,7 +4,7 @@ - {{ $tc('components.program.formScheduleEntryList.name') }} + {{ $tc('components.activity.dialog.formScheduleEntryList.name') }} @@ -47,6 +51,11 @@ export default { required: true, }, + currentScheduleEntry: { + type: Object, + default: null, + }, + // all available periods periods: { type: Array, diff --git a/frontend/src/components/campAdmin/DialogCategoryCreate.vue b/frontend/src/components/campAdmin/DialogCategoryCreate.vue index d12377e6ed..889073acb2 100644 --- a/frontend/src/components/campAdmin/DialogCategoryCreate.vue +++ b/frontend/src/components/campAdmin/DialogCategoryCreate.vue @@ -264,10 +264,7 @@ export default { const match = router.matcher.match(url) if (match.name === 'camp/activity') { - const scheduleEntry = await this.api - .get() - .scheduleEntries({ id: match.params['scheduleEntryId'] }) - return await scheduleEntry.activity() + return await this.api.get().activities({ id: match.params['activityId'] }) } else if (match.name === 'camp/admin/activity/category') { return await this.api.get().categories({ id: match.params['categoryId'] }) } diff --git a/frontend/src/components/campAdmin/ErrorExistingActivitiesList.vue b/frontend/src/components/campAdmin/ErrorExistingActivitiesList.vue index b594587211..6a75a13db1 100644 --- a/frontend/src/components/campAdmin/ErrorExistingActivitiesList.vue +++ b/frontend/src/components/campAdmin/ErrorExistingActivitiesList.vue @@ -16,6 +16,7 @@ name: 'camp/activity', params: { campId: camp.id, + activityId: activity.id, scheduleEntryId: scheduleEntry.id, }, }" diff --git a/frontend/src/components/dashboard/ActivityRow.vue b/frontend/src/components/dashboard/ActivityRow.vue index f1123a24af..a91cd55078 100644 --- a/frontend/src/components/dashboard/ActivityRow.vue +++ b/frontend/src/components/dashboard/ActivityRow.vue @@ -92,6 +92,7 @@ import AvatarRow from '@/components/generic/AvatarRow.vue' import CategoryChip from '@/components/generic/CategoryChip.vue' import { dateHelperUTCFormatted } from '@/mixins/dateHelperUTCFormatted.js' import TextAlignBaseline from '@/components/layout/TextAlignBaseline.vue' +import { scheduleEntryRoute } from '@/router.js' export default { name: 'ActivityRow', @@ -135,13 +136,7 @@ export default { return this.timeDurationShort(this.scheduleEntry.start, this.scheduleEntry.end) }, routerLink() { - return { - name: 'camp/activity', - params: { - campId: this.scheduleEntry.period().camp().id, - scheduleEntryId: this.scheduleEntry.id, - }, - } + return scheduleEntryRoute(this.scheduleEntry) }, }, } diff --git a/frontend/src/components/program/DialogActivityCreate.vue b/frontend/src/components/program/DialogActivityCreate.vue index 959206f040..6bb1bbc9ff 100644 --- a/frontend/src/components/program/DialogActivityCreate.vue +++ b/frontend/src/components/program/DialogActivityCreate.vue @@ -106,7 +106,7 @@ diff --git a/frontend/src/views/camp/activity/SideBarProgram.vue b/frontend/src/views/camp/activity/SideBarProgram.vue index e8ca4dbc26..de03c6ac20 100644 --- a/frontend/src/views/camp/activity/SideBarProgram.vue +++ b/frontend/src/views/camp/activity/SideBarProgram.vue @@ -3,7 +3,7 @@ :title="$tc('views.camp.activity.sideBarProgram.title')" icon="mdi-format-list-numbered" > - +