diff --git a/frontend/src/components/activity/DaySwitcher.vue b/frontend/src/components/activity/DaySwitcher.vue index 1034f02590..2235af6b0a 100644 --- a/frontend/src/components/activity/DaySwitcher.vue +++ b/frontend/src/components/activity/DaySwitcher.vue @@ -82,7 +82,7 @@ export default { name: 'DaySwitcher', components: { AvatarRow }, props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, daySelection: { type: Object, required: true }, loading: { type: Boolean }, }, @@ -104,7 +104,7 @@ export default { ) }, periods() { - return sortBy(this.camp().periods().items, 'start') + return sortBy(this.camp.periods().items, 'start') }, }, methods: { diff --git a/frontend/src/components/activity/ScheduleEntry.vue b/frontend/src/components/activity/ScheduleEntry.vue index 650e80b8ae..75b9afa3ee 100644 --- a/frontend/src/components/activity/ScheduleEntry.vue +++ b/frontend/src/components/activity/ScheduleEntry.vue @@ -7,13 +7,13 @@ Displays a single scheduleEntry class="ec-schedule-entry" toolbar back - :loaded="!scheduleEntry()._meta.loading && !activity.camp()._meta.loading" + :loaded="!scheduleEntry._meta.loading && !activity.camp()._meta.loading" :max-width="isPaperDisplaySize ? '944px' : ''" > - {{ scheduleEntry().number }} + {{ scheduleEntry.number }} mdi-autorenew + >mdi-autorenew + mdi-alert + >mdi-alert + mdi-chevron-down @@ -286,13 +286,13 @@ export default { return { preferredContentTypes: () => this.preferredContentTypes, allContentNodes: () => this.contentNodes, - camp: () => this.camp, + camp: this.camp, isPaperDisplaySize: () => this.isPaperDisplaySize, } }, props: { scheduleEntry: { - type: Function, + type: Object, required: true, }, }, @@ -306,7 +306,7 @@ export default { }, computed: { activity() { - return this.scheduleEntry().activity() + return this.scheduleEntry.activity() }, camp() { return this.activity.camp() @@ -319,7 +319,7 @@ export default { }, activityName() { return ( - (this.scheduleEntry().number ? this.scheduleEntry().number + ' ' : '') + + (this.scheduleEntry.number ? this.scheduleEntry.number + ' ' : '') + (this.category.short ? this.category.short + ': ' : '') + this.activity.title ) @@ -347,7 +347,7 @@ export default { type: 'Activity', options: { activity: this.activity._meta.self, - scheduleEntry: this.scheduleEntry()._meta.self, + scheduleEntry: this.scheduleEntry._meta.self, }, }, ], @@ -369,11 +369,11 @@ export default { // reload data every time user navigates to Activity view async mounted() { this.loading = true - await this.scheduleEntry().activity()._meta.load // wait if activity is being loaded as part of a collection + await this.scheduleEntry.activity()._meta.load // wait if activity is being loaded as part of a collection this.loading = false // to avoid stale data, trigger reload (which includes embedded contentNode data). However, don't await in order to render early with cached data. - this.scheduleEntry().activity().$reload() + this.scheduleEntry.activity().$reload() }, methods: { @@ -410,7 +410,7 @@ export default { console.warn('clipboard permission not requestable') } - const scheduleEntry = scheduleEntryRoute(this.scheduleEntry()) + const scheduleEntry = scheduleEntryRoute(this.scheduleEntry) const url = window.location.origin + router.resolve(scheduleEntry).href await navigator.clipboard.writeText(url) @@ -423,7 +423,7 @@ export default { }, onDelete() { // redirect to Picasso - this.$router.push(periodRoute(this.scheduleEntry().period())) + this.$router.push(periodRoute(this.scheduleEntry.period())) }, }, } diff --git a/frontend/src/components/activity/content/Material.vue b/frontend/src/components/activity/content/Material.vue index 62eb316bf5..db78fe5c85 100644 --- a/frontend/src/components/activity/content/Material.vue +++ b/frontend/src/components/activity/content/Material.vue @@ -1,7 +1,7 @@ {{ $tc('components.campAdmin.campActivityProgressLabels.title') }} - + @@ -69,7 +69,7 @@ {{ @@ -120,7 +120,7 @@ export default { DialogActivityProgressLabelEdit, }, props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, disabled: { type: Boolean, default: false }, }, data: () => ({ @@ -128,7 +128,7 @@ export default { }), computed: { progressLabels() { - return sortBy(this.camp().progressLabels().allItems, (label) => label.position) + return sortBy(this.camp.progressLabels().allItems, (label) => label.position) }, }, } diff --git a/frontend/src/components/campAdmin/CampAddress.vue b/frontend/src/components/campAdmin/CampAddress.vue index e237aae2c3..bb57fb76e0 100644 --- a/frontend/src/components/campAdmin/CampAddress.vue +++ b/frontend/src/components/campAdmin/CampAddress.vue @@ -4,9 +4,9 @@ Displays address and allows to edit - + - + @@ -29,7 +29,7 @@ export default { components: { ContentGroup, ApiTextField, ApiForm }, props: { camp: { - type: Function, + type: Object, required: true, }, disabled: { diff --git a/frontend/src/components/campAdmin/CampCategories.vue b/frontend/src/components/campAdmin/CampCategories.vue index 17ad1880df..2ddb4015a3 100644 --- a/frontend/src/components/campAdmin/CampCategories.vue +++ b/frontend/src/components/campAdmin/CampCategories.vue @@ -3,7 +3,7 @@ {{ $tc('components.campAdmin.campCategories.title') }} - + @@ -28,7 +28,7 @@ v-for="category in categories.items" :key="category._meta.self" class="px-2 rounded" - :to="categoryRoute(camp(), category)" + :to="categoryRoute(camp, category)" > @@ -68,7 +68,7 @@ export default { }, mixins: [dateHelperUTCFormatted], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, disabled: { type: Boolean, default: false }, }, data() { @@ -76,7 +76,7 @@ export default { }, computed: { categories() { - return this.camp().categories() + return this.camp.categories() }, }, methods: { diff --git a/frontend/src/components/campAdmin/CampConditionalFields.vue b/frontend/src/components/campAdmin/CampConditionalFields.vue index 9158db5805..39de7a9f10 100644 --- a/frontend/src/components/campAdmin/CampConditionalFields.vue +++ b/frontend/src/components/campAdmin/CampConditionalFields.vue @@ -15,9 +15,9 @@ Displays fields which don't apply to all camps, but are required for some - + - + @@ -31,9 +31,9 @@ Displays fields which don't apply to all camps, but are required for some - + - + @@ -61,7 +61,7 @@ export default { components: { ContentGroup, ApiTextField, ApiCheckbox, ApiForm }, props: { camp: { - type: Function, + type: Object, required: true, }, disabled: { diff --git a/frontend/src/components/campAdmin/CampDangerZone.vue b/frontend/src/components/campAdmin/CampDangerZone.vue index 8b112120db..27fee7e7dd 100644 --- a/frontend/src/components/campAdmin/CampDangerZone.vue +++ b/frontend/src/components/campAdmin/CampDangerZone.vue @@ -10,7 +10,7 @@ Critical operations on camp - + @@ -24,8 +24,8 @@ Critical operations on camp @@ -44,14 +44,14 @@ Critical operations on camp {{ $tc('components.campAdmin.campDangerZone.deleteCamp.explanation', 0, { - campName: camp().name, + campName: camp.name, }) }} {{ $tc('components.campAdmin.campDangerZone.deleteCamp.label', 0, { - campName: camp().name, + campName: camp.name, }) }} @@ -79,7 +79,7 @@ export default { }, props: { camp: { - type: Function, + type: Object, required: true, }, }, diff --git a/frontend/src/components/campAdmin/CampMaterialLists.vue b/frontend/src/components/campAdmin/CampMaterialLists.vue index d98b17e069..21dd484b48 100644 --- a/frontend/src/components/campAdmin/CampMaterialLists.vue +++ b/frontend/src/components/campAdmin/CampMaterialLists.vue @@ -3,7 +3,7 @@ {{ $tc('components.campAdmin.campMaterialLists.title') }} - + - + + - + - + - + @@ -27,7 +27,7 @@ export default { components: { ContentGroup, ApiTextField, ApiForm }, props: { camp: { - type: Function, + type: Object, required: true, }, disabled: { diff --git a/frontend/src/components/material/DialogMaterialItemCreate.vue b/frontend/src/components/material/DialogMaterialItemCreate.vue index 1d1c90aee0..ded58f7e9e 100644 --- a/frontend/src/components/material/DialogMaterialItemCreate.vue +++ b/frontend/src/components/material/DialogMaterialItemCreate.vue @@ -14,7 +14,7 @@ diff --git a/frontend/src/components/material/DialogMaterialItemEdit.vue b/frontend/src/components/material/DialogMaterialItemEdit.vue index 8adc552634..9cca2132f5 100644 --- a/frontend/src/components/material/DialogMaterialItemEdit.vue +++ b/frontend/src/components/material/DialogMaterialItemEdit.vue @@ -26,7 +26,7 @@ diff --git a/frontend/src/components/material/DialogMaterialItemForm.vue b/frontend/src/components/material/DialogMaterialItemForm.vue index 3b112ad492..e916515fed 100644 --- a/frontend/src/components/material/DialogMaterialItemForm.vue +++ b/frontend/src/components/material/DialogMaterialItemForm.vue @@ -27,7 +27,7 @@ export default { name: 'DialogMaterialItemForm', props: { - materialLists: { type: Function, required: true }, + materialLists: { type: Object, required: true }, materialItem: { type: Object, required: true }, }, computed: { @@ -35,7 +35,7 @@ export default { return this.materialItem }, materialListArray() { - return this.materialLists().items.map((l) => ({ + return this.materialLists.items.map((l) => ({ value: l._meta.self, text: l.name, })) diff --git a/frontend/src/components/material/MaterialLists.vue b/frontend/src/components/material/MaterialLists.vue index e9fb7b64d8..18adc631a8 100644 --- a/frontend/src/components/material/MaterialLists.vue +++ b/frontend/src/components/material/MaterialLists.vue @@ -1,6 +1,6 @@ - + {{ $tc('components.material.materialLists.overview') }} @@ -12,7 +12,7 @@ @@ -42,11 +42,11 @@ import { materialListRoute } from '@/router.js' export default { name: 'MaterialLists', props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, computed: { materialLists() { - return this.camp().materialLists() + return this.camp.materialLists() }, }, mounted() { diff --git a/frontend/src/components/material/useMaterialViewHelper.js b/frontend/src/components/material/useMaterialViewHelper.js index 554b0a0c40..d1862e18cc 100644 --- a/frontend/src/components/material/useMaterialViewHelper.js +++ b/frontend/src/components/material/useMaterialViewHelper.js @@ -106,9 +106,7 @@ function loadPeriods(camp) { * @param {boolean} [list] */ export function useMaterialViewHelper(camp, list) { - const computedList = computed(() => - list ? materialListFromRoute(useRoute()).call({ api: apiStore }) : null - ) + const computedList = computed(() => (list ? materialListFromRoute(useRoute()) : null)) const collection = computed(() => { const materialList = computedList.value?._meta.self diff --git a/frontend/src/components/print/PrintConfigurator.vue b/frontend/src/components/print/PrintConfigurator.vue index 02748d10a2..60863f5764 100644 --- a/frontend/src/components/print/PrintConfigurator.vue +++ b/frontend/src/components/print/PrintConfigurator.vue @@ -1,5 +1,5 @@ - + @@ -132,7 +132,7 @@ export default { }, props: { camp: { - type: Function, + type: Object, required: true, }, }, @@ -155,10 +155,10 @@ export default { }, cnf() { return this.repairConfig( - this.$store.getters.getLastPrintConfig(this.camp()._meta.self, { + this.$store.getters.getLastPrintConfig(this.camp._meta.self, { language: this.lang, - documentName: this.camp().name, - camp: this.camp()._meta.self, + documentName: this.camp.name, + camp: this.camp._meta.self, contents: this.defaultContents(), }) ) @@ -176,17 +176,15 @@ export default { }, }, mounted() { - this.camp() - .periods() - .items.forEach((period) => { - period.days().$reload() - period.contentNodes().$reload() - }) + this.camp.periods().items.forEach((period) => { + period.days().$reload() + period.contentNodes().$reload() + }) }, methods: { resetConfig() { this.$store.commit('setLastPrintConfig', { - campUri: this.camp()._meta.self, + campUri: this.camp._meta.self, printConfig: undefined, }) }, @@ -199,30 +197,26 @@ export default { { type: 'Picasso', options: { - periods: this.camp() - .periods() - .items.map((period) => period._meta.self), + periods: this.camp.periods().items.map((period) => period._meta.self), orientation: 'L', }, }, ] - this.camp() - .periods() - .items.forEach((period) => { - contents.push({ - type: 'Story', - options: { - periods: [period._meta.self], - }, - }) - contents.push({ - type: 'Program', - options: { - periods: [period._meta.self], - }, - }) + this.camp.periods().items.forEach((period) => { + contents.push({ + type: 'Story', + options: { + periods: [period._meta.self], + }, }) + contents.push({ + type: 'Program', + options: { + periods: [period._meta.self], + }, + }) + }) contents.push({ type: 'Toc', @@ -242,7 +236,7 @@ export default { onChange() { this.$nextTick(() => { this.$store.commit('setLastPrintConfig', { - campUri: this.camp()._meta.self, + campUri: this.camp._meta.self, printConfig: cloneDeep(this.cnf), }) }) @@ -257,7 +251,7 @@ export default { return repairConfig( config, - this.camp(), + this.camp, VueI18n.availableLocales, this.lang, repairers, diff --git a/frontend/src/components/program/DialogActivityCreate.vue b/frontend/src/components/program/DialogActivityCreate.vue index f9f67373e5..1f4d56f053 100644 --- a/frontend/src/components/program/DialogActivityCreate.vue +++ b/frontend/src/components/program/DialogActivityCreate.vue @@ -127,7 +127,7 @@ export default { scheduleEntry: { type: Object, required: true }, // currently visible period - period: { type: Function, required: true }, + period: { type: Object, required: true }, }, data() { return { @@ -143,7 +143,7 @@ export default { }, computed: { camp() { - return this.period().camp() + return this.period.camp() }, clipboardAccessDenied() { return ( diff --git a/frontend/src/components/program/DialogActivityEdit.vue b/frontend/src/components/program/DialogActivityEdit.vue index 0869d9a1f9..d9d7db9b30 100644 --- a/frontend/src/components/program/DialogActivityEdit.vue +++ b/frontend/src/components/program/DialogActivityEdit.vue @@ -23,7 +23,7 @@ {{ $tc('global.button.open') }} - + diff --git a/frontend/src/components/program/DialogActivityForm.vue b/frontend/src/components/program/DialogActivityForm.vue index 3ca5da3c54..f1d9c7b5eb 100644 --- a/frontend/src/components/program/DialogActivityForm.vue +++ b/frontend/src/components/program/DialogActivityForm.vue @@ -66,7 +66,7 @@ export default { }, // currently visible period period: { - type: Function, + type: Object, required: true, }, autoselectTitle: { @@ -84,7 +84,7 @@ export default { return this.camp.categories() }, camp() { - return this.period().camp() + return this.period.camp() }, }, } diff --git a/frontend/src/components/program/FormScheduleEntryList.vue b/frontend/src/components/program/FormScheduleEntryList.vue index 68d15e309c..d8144ac3f5 100644 --- a/frontend/src/components/program/FormScheduleEntryList.vue +++ b/frontend/src/components/program/FormScheduleEntryList.vue @@ -55,7 +55,7 @@ export default { // currently visible period period: { - type: Function, + type: Object, required: true, }, }, @@ -72,9 +72,9 @@ export default { methods: { addScheduleEntry() { this.localScheduleEntries.push({ - period: () => this.period(), - start: dayjs.utc(this.period().start).add(7, 'hour').format(), - end: dayjs.utc(this.period().start).add(8, 'hour').format(), + period: () => this.period, + start: dayjs.utc(this.period.start).add(7, 'hour').format(), + end: dayjs.utc(this.period.start).add(8, 'hour').format(), key: uniqueId(), deleted: false, }) diff --git a/frontend/src/components/program/PeriodSwitcher.vue b/frontend/src/components/program/PeriodSwitcher.vue index bc6090468c..4df1bc50a4 100644 --- a/frontend/src/components/program/PeriodSwitcher.vue +++ b/frontend/src/components/program/PeriodSwitcher.vue @@ -1,5 +1,5 @@ - + - {{ period().description }} + {{ period.description }} mdi-menu-up mdi-menu-down @@ -21,7 +21,7 @@ {{ $tc('components.program.periodSwitcher.title') }} - {{ period().description }} + {{ period.description }} @@ -51,7 +51,7 @@ export default { mixins: [dateHelperUTCFormatted], props: { period: { - type: Function, + type: Object, required: true, }, routeName: { type: String, default: 'camp/period/program' }, diff --git a/frontend/src/components/program/ScheduleEntries.vue b/frontend/src/components/program/ScheduleEntries.vue index 456ed0a04a..fecbd6c77c 100644 --- a/frontend/src/components/program/ScheduleEntries.vue +++ b/frontend/src/components/program/ScheduleEntries.vue @@ -40,7 +40,7 @@ export default { DialogActivityCreate, }, props: { - period: { type: Function, required: true }, + period: { type: Object, required: true }, showButton: { type: Boolean, required: true }, matchFn: { type: Function, required: false, default: () => true }, }, @@ -50,7 +50,7 @@ export default { newEntry: this.newEntryFromPicasso, }, newScheduleEntry: { - period: () => this.period(), + period: () => this.period, start: null, end: null, }, @@ -59,7 +59,7 @@ export default { computed: { scheduleEntries() { // TODO for SideBar, add filtering for the current day, now that the API supports it - return this.period().scheduleEntries() + return this.period.scheduleEntries() }, filteredScheduleEntries() { return this.scheduleEntries.items.map((item) => ({ @@ -70,8 +70,8 @@ export default { loading() { return ( this.scheduleEntries._meta.loading || - this.period().camp().activities()._meta.loading || - this.period().camp().categories()._meta.loading + this.period.camp().activities()._meta.loading || + this.period.camp().categories()._meta.loading ) }, }, @@ -79,11 +79,11 @@ export default { methods: { createNewActivity() { this.newScheduleEntry.start = this.$date - .utc(this.period().start) + .utc(this.period.start) .add(8, 'hour') .format() this.newScheduleEntry.end = this.$date - .utc(this.period().start) + .utc(this.period.start) .add(9, 'hour') .format() this.showActivityCreateDialog() @@ -92,7 +92,7 @@ export default { this.$refs.dialogActivityCreate.showDialog = true }, afterCreateActivity() { - this.api.reload(this.period().scheduleEntries()) + this.api.reload(this.period.scheduleEntries()) }, // Event Handler on.newEntry: update position & open create dialog diff --git a/frontend/src/components/program/ScheduleEntryFilters.vue b/frontend/src/components/program/ScheduleEntryFilters.vue index 57f42a16dd..b6f367f4c2 100644 --- a/frontend/src/components/program/ScheduleEntryFilters.vue +++ b/frontend/src/components/program/ScheduleEntryFilters.vue @@ -142,7 +142,7 @@ export default { }), }, camp: { - type: Function, + type: Object, required: true, }, periods: { @@ -176,14 +176,14 @@ export default { label: this.$tc('components.program.scheduleEntryFilters.responsibleNone'), _meta: { self: 'none' }, }, - ...keyBy(this.camp().campCollaborations().items, '_meta.self'), + ...keyBy(this.camp.campCollaborations().items, '_meta.self'), } }, categories() { - return keyBy(this.camp().categories().items, '_meta.self') + return keyBy(this.camp.categories().items, '_meta.self') }, progressLabels() { - const labels = sortBy(this.camp().progressLabels().items, (l) => l.position) + const labels = sortBy(this.camp.progressLabels().items, (l) => l.position) return { none: { title: this.$tc('components.program.scheduleEntryFilters.progressLabelNone'), @@ -229,17 +229,15 @@ export default { return campCollaborationDisplayName(campCollaboration, this.$tc.bind(this)) }, loadEndpointData(endpoint, filterKey, hasNone = false) { - this.camp() - [endpoint]() - ._meta.load.then(({ allItems }) => { - const collection = allItems.map((entry) => entry._meta.self) - if (hasNone) { - collection.push('none') - } - this.value[filterKey] = - this.value[filterKey].filter((value) => collection.includes(value)) ?? null - this.loadingEndpoints[endpoint] = false - }) + this.camp[endpoint]()._meta.load.then(({ allItems }) => { + const collection = allItems.map((entry) => entry._meta.self) + if (hasNone) { + collection.push('none') + } + this.value[filterKey] = + this.value[filterKey].filter((value) => collection.includes(value)) ?? null + this.loadingEndpoints[endpoint] = false + }) }, resetFilter() { this.value.period = null diff --git a/frontend/src/router.js b/frontend/src/router.js index 4628c3b09a..00e1573615 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -453,107 +453,136 @@ function requireAuth(to, from, next) { } async function requireCamp(to, from, next) { - await campFromRoute(to) - .call({ api: { get: apiStore.get } }) - ._meta.load.then(() => { - next() + const camp = await campFromRoute(to) + if (camp === undefined) { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, }) - .catch(() => { - next({ - name: 'PageNotFound', - params: [to.fullPath, ''], - replace: true, + } else { + await camp._meta.load + .then(() => { + next() }) - }) + .catch(() => { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, + }) + }) + } } async function requireScheduleEntry(to, from, next) { - await scheduleEntryFromRoute(to) - .call({ api: { get: apiStore.get } }) - ._meta.load.then(() => { - next() + const scheduleEntry = await scheduleEntryFromRoute(to) + if (scheduleEntry === undefined) { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, }) - .catch(() => { - next({ - name: 'PageNotFound', - params: [to.fullPath, ''], - replace: true, + } else { + await scheduleEntry._meta.load + .then(() => { + next() }) - }) + .catch(() => { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, + }) + }) + } } async function requirePeriod(to, from, next) { - await periodFromRoute(to) - .call({ api: { get: apiStore.get } }) - ._meta.load.then(() => { - next() - }) - .catch(() => { - next(campRoute(campFromRoute(to).call({ api: { get: apiStore.get } }))) + const period = await periodFromRoute(to) + if (period === undefined) { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, }) + } else { + await period._meta.load + .then(() => { + next() + }) + .catch(() => { + next(campRoute(campFromRoute(to))) + }) + } } async function requireCategory(to, from, next) { - await categoryFromRoute(to) - .call({ api: { get: apiStore.get } }) - ._meta.load.then(() => { - next() + const category = await categoryFromRoute(to) + if (category === undefined) { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, }) - .catch(() => { - next({ - name: 'PageNotFound', - params: [to.fullPath, ''], - replace: true, + } else { + await category._meta.load + .then(() => { + next() }) - }) + .catch(() => { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, + }) + }) + } } async function requireMaterialList(to, from, next) { - await materialListFromRoute(to) - .call({ api: { get: apiStore.get } }) - ._meta.load.then(() => { - next() - }) - .catch(() => { - next(campRoute(campFromRoute(to).call({ api: { get: apiStore.get } }))) + const materialList = await materialListFromRoute(to) + if (materialList === undefined) { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, }) + } else { + await materialList._meta.load + .then(() => { + next() + }) + .catch(() => { + next(campRoute(campFromRoute(to))) + }) + } } export function campFromRoute(route) { - return function () { - return this.api.get().camps({ id: route.params.campId }) - } + return apiStore.get().camps({ id: route.params.campId }) } export function invitationFromInviteKey(inviteKey) { - return function () { - return this.api.get().invitations({ action: 'find', id: inviteKey }) - } + return apiStore.get().invitations({ action: 'find', id: inviteKey }) } export function periodFromRoute(route) { - return function () { - return this.api.get().periods({ id: route.params.periodId }) - } + return apiStore.get().periods({ id: route.params.periodId }) } function scheduleEntryFromRoute(route) { - return function () { - return this.api.get().scheduleEntries({ id: route.params.scheduleEntryId }) - } + return apiStore.get().scheduleEntries({ id: route.params.scheduleEntryId }) } function categoryFromRoute(route) { - return function () { - const camp = this.api.get().camps({ id: route.params.campId }) - return camp.categories().allItems.find((c) => c.id === route.params.categoryId) - } + return campFromRoute(route) + .categories() + .allItems.find((c) => c.id === route.params.categoryId) } export function materialListFromRoute(route) { - return function () { - return this.api.get().materialLists({ id: route.params.materialId }) - } + return apiStore.get().materialLists({ id: route.params.materialId }) } function getContentLayout(route) { @@ -575,9 +604,7 @@ function getContentLayout(route) { } function dayFromScheduleEntryInRoute(route) { - return function () { - return this.api.get().scheduleEntries({ id: route.params.scheduleEntryId }).day() - } + return apiStore.get().scheduleEntries({ id: route.params.scheduleEntryId }).day() } /** diff --git a/frontend/src/views/activity/Activity.vue b/frontend/src/views/activity/Activity.vue index 958ce76170..e297a5b085 100644 --- a/frontend/src/views/activity/Activity.vue +++ b/frontend/src/views/activity/Activity.vue @@ -4,7 +4,7 @@ Displays a single activity - + @@ -19,7 +19,7 @@ export default { props: { scheduleEntry: { - type: Function, + type: Object, required: true, }, }, diff --git a/frontend/src/views/activity/SideBarProgram.vue b/frontend/src/views/activity/SideBarProgram.vue index c38e8f427f..62d1520dd4 100644 --- a/frontend/src/views/activity/SideBarProgram.vue +++ b/frontend/src/views/activity/SideBarProgram.vue @@ -17,7 +17,7 @@ v-else class="ec-sidebar-program__picasso" :schedule-entries="slotProps.scheduleEntries" - :period="period()" + :period="period" :start="currentDayAsString" :interval-height="36" :end="currentDayAsString" @@ -42,8 +42,8 @@ export default { name: 'SideBarProgram', components: { DaySwitcher, SideBar, Picasso, ScheduleEntries }, props: { - day: { type: Function, required: true }, - camp: { type: Function, required: true }, + day: { type: Object, required: true }, + camp: { type: Object, required: true }, }, data() { return { @@ -52,10 +52,10 @@ export default { }, computed: { period() { - return this.daySelection.period + return this.daySelection.period() }, daySelection() { - return this.selectedDay ?? this.day() + return this.selectedDay ?? this.day }, currentDayAsString() { return this.$date.utc(this.daySelection.start).format(HTML5_FMT.DATE) diff --git a/frontend/src/views/admin/Activity.vue b/frontend/src/views/admin/Activity.vue index 43f671b0de..e8ce8d34b9 100644 --- a/frontend/src/views/admin/Activity.vue +++ b/frontend/src/views/admin/Activity.vue @@ -28,7 +28,7 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, } diff --git a/frontend/src/views/admin/AdminMaterialLists.vue b/frontend/src/views/admin/AdminMaterialLists.vue index 2d8544726c..34607c286d 100644 --- a/frontend/src/views/admin/AdminMaterialLists.vue +++ b/frontend/src/views/admin/AdminMaterialLists.vue @@ -5,7 +5,7 @@ Show all material lists for a camp on mobile - + {{ $tc('global.button.create') }} @@ -38,11 +38,11 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, computed: { materialLists() { - return this.camp().materialLists() + return this.camp.materialLists() }, }, mounted() { diff --git a/frontend/src/views/admin/Collaborators.vue b/frontend/src/views/admin/Collaborators.vue index 713131845a..2e0ff95c41 100644 --- a/frontend/src/views/admin/Collaborators.vue +++ b/frontend/src/views/admin/Collaborators.vue @@ -6,7 +6,7 @@ Displays collaborators of a single camp. - + @@ -44,11 +44,11 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, computed: { collaborators() { - return this.camp().campCollaborations().items + return this.camp.campCollaborations().items }, established() { return this.collaborators.filter((c) => c.status === 'established') @@ -61,7 +61,7 @@ export default { }, }, created() { - return this.camp().campCollaborations() + return this.camp.campCollaborations() }, } diff --git a/frontend/src/views/admin/Info.vue b/frontend/src/views/admin/Info.vue index 9d59b5bb7d..46bd035339 100644 --- a/frontend/src/views/admin/Info.vue +++ b/frontend/src/views/admin/Info.vue @@ -43,13 +43,13 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, data: () => ({ openPanels: [], }), mounted() { - this.camp()._meta.load.then((camp) => { + this.camp._meta.load.then((camp) => { if ( camp?.organizer || camp?.kind || diff --git a/frontend/src/views/admin/Print.vue b/frontend/src/views/admin/Print.vue index 86166261b6..178260053f 100644 --- a/frontend/src/views/admin/Print.vue +++ b/frontend/src/views/admin/Print.vue @@ -25,7 +25,7 @@ export default { PrintConfigurator, }, props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, data() { return {} diff --git a/frontend/src/views/admin/SideBarAdmin.vue b/frontend/src/views/admin/SideBarAdmin.vue index 4fdf5cbd37..2d1abd7e4a 100644 --- a/frontend/src/views/admin/SideBarAdmin.vue +++ b/frontend/src/views/admin/SideBarAdmin.vue @@ -2,28 +2,28 @@ @@ -43,7 +43,7 @@ export default { mixins: [campRoleMixin], props: { camp: { - type: Function, + type: Object, required: true, }, }, diff --git a/frontend/src/views/admin/__tests__/Admin.spec.js b/frontend/src/views/admin/__tests__/Admin.spec.js index c27a40de78..6aded65fc2 100644 --- a/frontend/src/views/admin/__tests__/Admin.spec.js +++ b/frontend/src/views/admin/__tests__/Admin.spec.js @@ -9,7 +9,7 @@ describe('Admin view', () => { const camp = createCampWithRole('manager') const { getByText } = render(Admin, { props: { - camp: () => camp, + camp, }, routes: [], store: createStoreObject(), @@ -33,7 +33,7 @@ describe('Admin view', () => { const camp = createCampWithRole('member') const { queryByText } = render(Admin, { props: { - camp: () => camp, + camp, }, routes: [], store: createStoreObject(), @@ -53,7 +53,7 @@ describe('Admin view', () => { const camp = createCampWithRole('guest') const { queryByText } = render(Admin, { props: { - camp: () => camp, + camp, }, routes: [], store: createStoreObject(), diff --git a/frontend/src/views/camp/Admin.vue b/frontend/src/views/camp/Admin.vue index 1b55d9cb3d..d94ef0c96b 100644 --- a/frontend/src/views/camp/Admin.vue +++ b/frontend/src/views/camp/Admin.vue @@ -60,15 +60,15 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, data() { return {} }, mounted() { - this.api.reload(this.camp()) - this.api.reload(this.camp().materialLists()) - this.api.reload(this.camp().progressLabels()) + this.api.reload(this.camp) + this.api.reload(this.camp.materialLists()) + this.api.reload(this.camp.progressLabels()) }, } diff --git a/frontend/src/views/camp/CampProgram.vue b/frontend/src/views/camp/CampProgram.vue index 223c3c78ee..9dcab22140 100644 --- a/frontend/src/views/camp/CampProgram.vue +++ b/frontend/src/views/camp/CampProgram.vue @@ -104,9 +104,9 @@ Show all activity schedule entries of a single period. period.scheduleEntries()._meta.load), - this.camp().activities()._meta.load, + this.camp._meta.load, + this.api.get().days({ 'period.camp': this.camp._meta.self }), + ...this.camp.periods().items.map((period) => period.scheduleEntries()._meta.load), + this.camp.activities()._meta.load, ]) this.loading = false @@ -258,14 +256,12 @@ export default { this.filter[key] = value }) - this.camp() - .periods() - ._meta.load.then(({ allItems }) => { - const collection = allItems.map((entry) => entry._meta.self) - this.filter.periods = - this.filter.periods?.filter((value) => collection.includes(value)) ?? null - this.loadingEndpoints.periods = false - }) + this.camp.periods()._meta.load.then(({ allItems }) => { + const collection = allItems.map((entry) => entry._meta.self) + this.filter.periods = + this.filter.periods?.filter((value) => collection.includes(value)) ?? null + this.loadingEndpoints.periods = false + }) }, methods: { persistRouterState() { diff --git a/frontend/src/views/camp/Invitation.vue b/frontend/src/views/camp/Invitation.vue index e471f222da..b68b8a4c42 100644 --- a/frontend/src/views/camp/Invitation.vue +++ b/frontend/src/views/camp/Invitation.vue @@ -111,7 +111,7 @@ export default { name: 'Invitation', components: { ButtonBack, UserMeta }, props: { - invitation: { type: Function, required: false, default: null }, + invitation: { type: Object, required: false, default: null }, variant: { type: String, default: 'default' }, }, data: () => ({ @@ -119,7 +119,7 @@ export default { }), computed: { invite() { - return this.invitationFound === true ? this.invitation?.() : null + return this.invitationFound === true ? this.invitation : null }, campLink() { return { @@ -142,16 +142,14 @@ export default { if (this.variant === 'default') { // Content of api response depends on authenticated user --> reload every time this component is mounted - this.invitation?.() - .$reload() - .then( - () => { - this.invitationFound = true - }, - () => { - this.invitationFound = false - } - ) + this.invitation?.$reload().then( + () => { + this.invitationFound = true + }, + () => { + this.invitationFound = false + } + ) } }, methods: { diff --git a/frontend/src/views/camp/Story.vue b/frontend/src/views/camp/Story.vue index 05e03b6007..b732514e4e 100644 --- a/frontend/src/views/camp/Story.vue +++ b/frontend/src/views/camp/Story.vue @@ -26,7 +26,7 @@ - + @@ -51,20 +51,20 @@ export default { }, mixins: [campRoleMixin], props: { - period: { type: Function, required: true }, - camp: { type: Function, required: true }, + period: { type: Object, required: true }, + camp: { type: Object, required: true }, }, computed: { printConfig() { return { - camp: this.camp()._meta.self, + camp: this.camp._meta.self, language: this.$store.state.lang.language, - documentName: this.camp().title + '-StorySummary.pdf', + documentName: this.camp.title + '-StorySummary.pdf', contents: [ { type: 'Story', options: { - periods: [this.period()._meta.self], + periods: [this.period._meta.self], }, }, ], @@ -72,11 +72,11 @@ export default { }, editMode: { get() { - return this.$store.getters.getStoryContextEditMode(this.camp()._meta.self) + return this.$store.getters.getStoryContextEditMode(this.camp._meta.self) }, set(value) { this.$store.commit('setStoryContextEditMode', { - campUri: this.camp()._meta.self, + campUri: this.camp._meta.self, editMode: value, }) }, diff --git a/frontend/src/views/camp/navigation/NavigationCamp.vue b/frontend/src/views/camp/navigation/NavigationCamp.vue index 16112f7a16..12bd8e5265 100644 --- a/frontend/src/views/camp/navigation/NavigationCamp.vue +++ b/frontend/src/views/camp/navigation/NavigationCamp.vue @@ -19,7 +19,7 @@ export default { NavSidebar, }, props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, data() { return { diff --git a/frontend/src/views/camp/navigation/desktop/NavTopbar.vue b/frontend/src/views/camp/navigation/desktop/NavTopbar.vue index bf3e9dfe56..2464dafd8e 100644 --- a/frontend/src/views/camp/navigation/desktop/NavTopbar.vue +++ b/frontend/src/views/camp/navigation/desktop/NavTopbar.vue @@ -3,32 +3,32 @@ - + mdi-tent {{ - camp().title + camp.title | loading($tc('views.camp.navigation.desktop.navTopbar.campIsLoading')) }} - + mdi-view-dashboard {{ $tc('views.camp.navigation.desktop.navTopbar.program') }} - + mdi-book-open-variant {{ $tc('views.camp.navigation.desktop.navTopbar.story') }} - + mdi-package-variant {{ $tc('views.camp.navigation.desktop.navTopbar.material') }} - + mdi-cogs {{ $tc('global.navigation.admin.title') @@ -62,7 +62,7 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, data() { return { diff --git a/frontend/src/views/camp/navigation/mobile/NavBottombar.vue b/frontend/src/views/camp/navigation/mobile/NavBottombar.vue index 1f95ff3161..e458f90590 100644 --- a/frontend/src/views/camp/navigation/mobile/NavBottombar.vue +++ b/frontend/src/views/camp/navigation/mobile/NavBottombar.vue @@ -1,18 +1,18 @@ - + {{ $tc('views.camp.navigation.mobile.navBottombar.program') }} mdi-view-dashboard - + {{ $tc('views.camp.navigation.mobile.navBottombar.story') }} mdi-book-open-variant - - {{ camp().name }} + + {{ camp.name }} mdi-tent - + {{ $tc('views.camp.navigation.mobile.navBottombar.material') }} mdi-package-variant @@ -30,7 +30,7 @@ import { mapGetters } from 'vuex' export default { name: 'NavBottombar', props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, data() { return { diff --git a/frontend/src/views/camp/navigation/mobile/NavSidebar.vue b/frontend/src/views/camp/navigation/mobile/NavSidebar.vue index e9b93d8b16..0f20487ff8 100644 --- a/frontend/src/views/camp/navigation/mobile/NavSidebar.vue +++ b/frontend/src/views/camp/navigation/mobile/NavSidebar.vue @@ -37,23 +37,23 @@ - + @@ -74,7 +74,7 @@ @@ -129,7 +129,7 @@ export default { }, props: { value: { type: Boolean, required: true }, - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, computed: { newsLink() { diff --git a/frontend/src/views/category/Category.vue b/frontend/src/views/category/Category.vue index ae88dce0ff..1fa30f3cc4 100644 --- a/frontend/src/views/category/Category.vue +++ b/frontend/src/views/category/Category.vue @@ -1,7 +1,7 @@ - - {{ category().name }} + + {{ category.name }} @@ -34,8 +34,8 @@ @@ -49,10 +49,10 @@ - + @@ -67,7 +67,7 @@ - + @@ -79,7 +79,7 @@ this.preferredContentTypes, allContentNodes: () => this.contentNodes, - camp: () => this.camp(), + camp: this.camp, isPaperDisplaySize: () => this.isPaperDisplaySize, } }, props: { camp: { - type: Function, - required: true, + type: Object, + default: null, + required: false, }, category: { - type: Function, - required: true, + type: Object, + default: null, + required: false, }, }, data() { @@ -143,18 +145,18 @@ export default { }, computed: { contentNodes() { - return this.category().contentNodes() + return this.category.contentNodes() }, preferredContentTypes() { - return this.category().preferredContentTypes() + return this.category.preferredContentTypes() }, isPaperDisplaySize: { get() { - return this.$store.getters.getPaperDisplaySize(this.camp()._meta.self) + return this.$store.getters.getPaperDisplaySize(this.camp._meta.self) }, set(value) { this.$store.commit('setPaperDisplaySize', { - campUri: this.camp()._meta.self, + campUri: this.camp._meta.self, paperDisplaySize: value, }) }, @@ -171,20 +173,20 @@ export default { this.openPanels = [1] } this.loading = true - await this.category()._meta.load // wait if category is being loaded as part of a collection - await this.category().$reload() // reload as single entity to ensure all embedded entities are included in a single network request + await this.category._meta.load // wait if category is being loaded as part of a collection + await this.category.$reload() // reload as single entity to ensure all embedded entities are included in a single network request this.loading = false }, methods: { findActivities(category) { - return this.camp() + return this.camp .activities() .items.filter( (activity) => activity.category()._meta.self === category._meta.self ) }, goToActivityAdmin() { - this.$router.push({ name: 'admin/activity', params: { campId: this.camp().id } }) + this.$router.replace({ name: 'admin/activity', params: { campId: this.camp.id } }) }, async copyUrlToClipboard() { try { @@ -196,12 +198,12 @@ export default { console.warn('clipboard permission not requestable') } - const category = categoryRoute(this.camp(), this.category()) + const category = categoryRoute(this.camp, this.category) const url = window.location.origin + router.resolve(category).href await navigator.clipboard.writeText(url) this.$toast.info( - this.$tc('global.toast.copied', null, { source: this.category().name }), + this.$tc('global.toast.copied', null, { source: this.category.name }), { timeout: 2000, } diff --git a/frontend/src/views/category/SideBarCategory.vue b/frontend/src/views/category/SideBarCategory.vue index 14d18fa348..aec7ccb99a 100644 --- a/frontend/src/views/category/SideBarCategory.vue +++ b/frontend/src/views/category/SideBarCategory.vue @@ -5,9 +5,9 @@ > @@ -31,7 +31,7 @@ export default { name: 'SideBarCategory', components: { CategoryChip, SideBar }, props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, methods: { categoryRoute }, } diff --git a/frontend/src/views/material/MaterialDetail.vue b/frontend/src/views/material/MaterialDetail.vue index ec6c27fe05..060167a470 100644 --- a/frontend/src/views/material/MaterialDetail.vue +++ b/frontend/src/views/material/MaterialDetail.vue @@ -1,6 +1,6 @@ - + @@ -9,7 +9,7 @@ - + @@ -44,7 +44,7 @@ :key="period._meta.self" :period="period" :material-item-collection="materialItems" - :material-list="materialList()" + :material-list="materialList" :disabled="!isContributor" /> @@ -52,10 +52,10 @@ @@ -70,7 +70,6 @@ import MaterialTable from '@/components/material/MaterialTable.vue' import DialogMaterialListEdit from '@/components/campAdmin/DialogMaterialListEdit.vue' import { campRoleMixin } from '@/mixins/campRoleMixin.js' import { useMaterialViewHelper } from '@/components/material/useMaterialViewHelper.js' -import { apiStore } from '@/plugins/store/index.js' export default { name: 'MaterialDetail', @@ -82,11 +81,11 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, - materialList: { type: Function, required: true }, + camp: { type: Object, required: true }, + materialList: { type: Object, required: true }, }, setup(props) { - return useMaterialViewHelper(props.camp.call({ api: { get: apiStore.get } }), true) + return useMaterialViewHelper(props.camp, true) }, } diff --git a/frontend/src/views/material/MaterialLists.vue b/frontend/src/views/material/MaterialLists.vue index 457a88a90a..b41468ac0a 100644 --- a/frontend/src/views/material/MaterialLists.vue +++ b/frontend/src/views/material/MaterialLists.vue @@ -5,7 +5,7 @@ Show all material lists for a camp on mobile - + {{ $tc('global.button.create') }} @@ -34,11 +34,11 @@ export default { }, mixins: [campRoleMixin], props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, computed: { materialLists() { - return this.camp().materialLists() + return this.camp.materialLists() }, }, mounted() { diff --git a/frontend/src/views/material/MaterialOverview.vue b/frontend/src/views/material/MaterialOverview.vue index e8b4402768..5307ad2459 100644 --- a/frontend/src/views/material/MaterialOverview.vue +++ b/frontend/src/views/material/MaterialOverview.vue @@ -9,7 +9,7 @@ - + @@ -50,7 +50,7 @@ diff --git a/frontend/src/views/material/SideBarMaterialLists.vue b/frontend/src/views/material/SideBarMaterialLists.vue index 3478e8e189..aa8ec58cc7 100644 --- a/frontend/src/views/material/SideBarMaterialLists.vue +++ b/frontend/src/views/material/SideBarMaterialLists.vue @@ -14,7 +14,7 @@ export default { name: 'SideBarMaterialLists', components: { MaterialLists, SideBar }, props: { - camp: { type: Function, required: true }, + camp: { type: Object, required: true }, }, }
{{ $tc('components.campAdmin.campDangerZone.deleteCamp.explanation', 0, { - campName: camp().name, + campName: camp.name, }) }}