Compare commits
19 Commits
feature/re
...
main
Author | SHA1 | Date |
---|---|---|
Tim Gröger | 6737bd5b45 | |
Tim Gröger | aa3c172160 | |
Tim Gröger | 923f5ec27c | |
Tim Gröger | 084ad8f945 | |
Tim Gröger | 7b1e37b3a7 | |
Tim Gröger | 9a648e8443 | |
Tim Gröger | 38480a1eec | |
Tim Gröger | f0e07138b1 | |
Tim Gröger | ba7013ac67 | |
Tim Gröger | 252072df57 | |
Tim Gröger | c5012c8431 | |
Tim Gröger | 40148ba10f | |
Tim Gröger | 3fbbacabca | |
Tim Gröger | 6f6fca84ed | |
Tim Gröger | b5d43bb1de | |
Tim Gröger | 7ea5a8fac3 | |
Tim Gröger | 67d844d6e6 | |
Tim Gröger | 93f88792d0 | |
Tim Gröger | 6ad340fe7c |
|
@ -197,9 +197,9 @@ def get_events(
|
||||||
if not with_backup:
|
if not with_backup:
|
||||||
for event in events:
|
for event in events:
|
||||||
clear_backup(event)
|
clear_backup(event)
|
||||||
logger.debug(end)
|
# logger.debug(end)
|
||||||
for event in events:
|
# for event in events:
|
||||||
logger.debug(f"{event.start} < {end} = {event.start < end}")
|
# logger.debug(f"{event.start} < {end} = {event.start < end}")
|
||||||
return count, events
|
return count, events
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
license = MIT
|
license = MIT
|
||||||
version = 0.0.1-dev.1
|
version = 1.0.0
|
||||||
name = flaschengeist-events
|
name = flaschengeist-events
|
||||||
description = Events plugin for Flaschengeist
|
description = Events plugin for Flaschengeist
|
||||||
url = https://flaschengeist.dev/Flaschengeist/flaschengeist-schedule
|
url = https://flaschengeist.dev/Flaschengeist/flaschengeist-schedule
|
||||||
|
@ -24,7 +24,10 @@ python_requires = >=3.8
|
||||||
packages =
|
packages =
|
||||||
flaschengeist_events
|
flaschengeist_events
|
||||||
install_requires =
|
install_requires =
|
||||||
flaschengeist == 2.0.*
|
flaschengeist >= 2.0.0
|
||||||
|
|
||||||
|
[options.package_data]
|
||||||
|
* = *.toml, script.py.mako, *.ini, migrations/*.py
|
||||||
|
|
||||||
[options.entry_points]
|
[options.entry_points]
|
||||||
flaschengeist.plugins =
|
flaschengeist.plugins =
|
||||||
|
|
24
package.json
24
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "1.0.0-alpha.6",
|
"version": "1.1.0",
|
||||||
"name": "@flaschengeist/schedule",
|
"name": "@flaschengeist/schedule",
|
||||||
"author": "Ferdinand Thiessen <rpm@fthiessen.de>",
|
"author": "Ferdinand Thiessen <rpm@fthiessen.de>",
|
||||||
"homepage": "https://flaschengeist.dev/Flaschengeist",
|
"homepage": "https://flaschengeist.dev/Flaschengeist",
|
||||||
|
@ -22,24 +22,24 @@
|
||||||
"@quasar/quasar-ui-qcalendar": "^4.0.0-beta.11"
|
"@quasar/quasar-ui-qcalendar": "^4.0.0-beta.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@flaschengeist/api": "^1.0.0-alpha.7",
|
"@flaschengeist/api": "^1.0.0",
|
||||||
"@flaschengeist/types": "^1.0.0-alpha.10",
|
"@flaschengeist/types": "^1.0.0",
|
||||||
"@quasar/app": "^3.2.5",
|
"@quasar/app-webpack": "^3.7.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.6.0",
|
"@typescript-eslint/eslint-plugin": "^5.8.0",
|
||||||
"@typescript-eslint/parser": "^5.6.0",
|
"@typescript-eslint/parser": "^5.8.0",
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
"eslint": "^8.4.1",
|
"eslint": "^8.5.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"eslint-plugin-vue": "^8.2.0",
|
"eslint-plugin-vue": "^8.2.0",
|
||||||
"pinia": "^2.0.6",
|
"pinia": "^2.0.8",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"quasar": "^2.3.4",
|
"quasar": "^2.11.10",
|
||||||
"typescript": "^4.5.2"
|
"typescript": "^4.5.4"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@flaschengeist/api": "^1.0.0-alpha.7",
|
"@flaschengeist/api": "^1.0.0",
|
||||||
"@flaschengeist/users": "^1.0.0-alpha.3"
|
"@flaschengeist/users": "^1.0.0"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||||
label="Veranstaltungsende"
|
label="Veranstaltungsende"
|
||||||
:rules="[afterStart]"
|
:rules="[afterStart]"
|
||||||
|
:key="update_time"
|
||||||
/>
|
/>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="event.description"
|
v-model="event.description"
|
||||||
|
@ -61,7 +62,7 @@
|
||||||
filled
|
filled
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section v-if="event.is_template !== true && modelValue === undefined">
|
<q-card-section v-if="modelValue === undefined">
|
||||||
<q-btn-toggle
|
<q-btn-toggle
|
||||||
v-model="recurrent"
|
v-model="recurrent"
|
||||||
spread
|
spread
|
||||||
|
@ -81,8 +82,7 @@
|
||||||
<q-btn color="primary" label="Schicht hinzufügen" @click="addJob()" />
|
<q-btn color="primary" label="Schicht hinzufügen" @click="addJob()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-for="(job, index) in event.jobs" :key="index">
|
<template v-for="(job, index) in event.jobs" :key="index + update_time">
|
||||||
<!--:ref="active === index ? 'activeJob' : undefined"-->
|
|
||||||
<edit-job-slot
|
<edit-job-slot
|
||||||
ref="activeJob"
|
ref="activeJob"
|
||||||
v-model="event.jobs[index]"
|
v-model="event.jobs[index]"
|
||||||
|
@ -138,6 +138,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
emits: {
|
emits: {
|
||||||
done: (val: boolean) => typeof val === 'boolean',
|
done: (val: boolean) => typeof val === 'boolean',
|
||||||
|
'update:modelValue': (val?: FG.Event) => typeof val === 'object',
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const store = useEventStore();
|
const store = useEventStore();
|
||||||
|
@ -182,7 +183,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromTemplate(tpl: FG.Event) {
|
function fromTemplate(tpl: FG.Event) {
|
||||||
const today = new Date();
|
const today = props.modelValue?.start || new Date();
|
||||||
template.value = tpl;
|
template.value = tpl;
|
||||||
|
|
||||||
event.value = Object.assign({}, tpl, { id: undefined });
|
event.value = Object.assign({}, tpl, { id: undefined });
|
||||||
|
@ -196,16 +197,27 @@ export default defineComponent({
|
||||||
const diff = event.value.start.getTime() - tpl.start.getTime();
|
const diff = event.value.start.getTime() - tpl.start.getTime();
|
||||||
// Adjust end of event and all jobs
|
// Adjust end of event and all jobs
|
||||||
if (event.value.end) event.value.end.setTime(event.value.end.getTime() + diff);
|
if (event.value.end) event.value.end.setTime(event.value.end.getTime() + diff);
|
||||||
event.value.jobs.forEach((job) => {
|
event.value.jobs = [];
|
||||||
job.start.setTime(job.start.getTime() + diff);
|
tpl.jobs.forEach((job) => {
|
||||||
if (job.end) job.end.setTime(job.end.getTime() + diff);
|
const copied_job: FG.Job = Object.assign({}, job, {
|
||||||
|
id: NaN,
|
||||||
|
start: new Date(),
|
||||||
|
end: undefined,
|
||||||
|
});
|
||||||
|
copied_job.start.setTime(job.start.getTime() + diff);
|
||||||
|
if (job.end) {
|
||||||
|
copied_job.end = new Date();
|
||||||
|
copied_job.end.setTime(job.end.getTime() + diff);
|
||||||
|
}
|
||||||
|
event.value.jobs.push(<Job>copied_job);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function save(template = false) {
|
async function save(is_template = false) {
|
||||||
event.value.is_template = template;
|
event.value.is_template = is_template;
|
||||||
try {
|
try {
|
||||||
await store.addEvent(event.value);
|
const _event = await store.addEvent(event.value);
|
||||||
|
emit('update:modelValue', _event);
|
||||||
|
|
||||||
if (props.modelValue === undefined && recurrent.value && !event.value.is_template) {
|
if (props.modelValue === undefined && recurrent.value && !event.value.is_template) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
@ -267,7 +279,55 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const computed_start = computed({
|
||||||
|
get: () => event.value?.start,
|
||||||
|
set: (value) => {
|
||||||
|
event.value.start = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const computed_end = computed({
|
||||||
|
get: () => event.value?.end,
|
||||||
|
set: (value) => {
|
||||||
|
event.value.end = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const update_time = ref(false);
|
||||||
|
|
||||||
|
watch(computed_start, (newValue, oldValue) => {
|
||||||
|
update_time.value = true;
|
||||||
|
const diff = newValue.getTime() - oldValue.getTime();
|
||||||
|
event.value?.jobs.forEach((job) => {
|
||||||
|
job.start.setTime(job.start.getTime() + diff);
|
||||||
|
job.end?.setTime(job.end.getTime() + diff);
|
||||||
|
});
|
||||||
|
computed_end.value?.setTime(computed_end.value?.getTime() + diff);
|
||||||
|
setTimeout(() => {
|
||||||
|
update_time.value = false;
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(computed_end, (newValue, oldValue) => {
|
||||||
|
if (newValue && oldValue) {
|
||||||
|
update_time.value = true;
|
||||||
|
if (!newValue || !oldValue) return;
|
||||||
|
const diff = newValue.getTime() - oldValue.getTime();
|
||||||
|
event.value?.jobs.forEach((job) => {
|
||||||
|
if (job.end) job.end.setTime(job.end.getTime() + diff);
|
||||||
|
else job.end = new Date(newValue.getTime());
|
||||||
|
});
|
||||||
|
} else if (newValue && !oldValue) {
|
||||||
|
event.value?.jobs.forEach((job) => {
|
||||||
|
if (!job.end) job.end = new Date(newValue.getTime());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
update_time.value = false;
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
update_time,
|
||||||
activate,
|
activate,
|
||||||
active,
|
active,
|
||||||
addJob,
|
addJob,
|
||||||
|
|
|
@ -40,12 +40,12 @@
|
||||||
:rules="[notEmpty]"
|
:rules="[notEmpty]"
|
||||||
/>
|
/>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="job.required_services"
|
v-model.number="job.required_services"
|
||||||
filled
|
filled
|
||||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||||
label="Dienstanzahl"
|
label="Dienstanzahl"
|
||||||
type="number"
|
type="number"
|
||||||
:rules="[notEmpty]"
|
:rules="[minOneService, notEmpty]"
|
||||||
/>
|
/>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="job.comment"
|
v-model="job.comment"
|
||||||
|
@ -134,6 +134,10 @@ export default defineComponent({
|
||||||
validate: () => form.value?.validate() || Promise.resolve(true),
|
validate: () => form.value?.validate() || Promise.resolve(true),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function minOneService(val: number) {
|
||||||
|
return parseInt(val) > 0 || 'Mindestens ein Dienst nötig';
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
formatStartEnd,
|
formatStartEnd,
|
||||||
|
@ -141,6 +145,7 @@ export default defineComponent({
|
||||||
job,
|
job,
|
||||||
jobtypes,
|
jobtypes,
|
||||||
notEmpty,
|
notEmpty,
|
||||||
|
minOneService,
|
||||||
typeName,
|
typeName,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,10 +30,17 @@
|
||||||
|
|
||||||
<q-table :title="title" :rows="rows" row-key="id" :columns="columns">
|
<q-table :title="title" :rows="rows" row-key="id" :columns="columns">
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<q-input ref="input" v-model="actualType.name" :rules="rules" dense placeholder="Neuer Typ">
|
<q-input
|
||||||
<slot name="after"
|
ref="input"
|
||||||
><q-btn color="primary" icon="mdi-plus" title="Hinzufügen" @click="addType"
|
v-model="actualType.name"
|
||||||
/></slot>
|
:rules="rules"
|
||||||
|
dense
|
||||||
|
filled
|
||||||
|
placeholder="Neuer Typ"
|
||||||
|
>
|
||||||
|
<template #after
|
||||||
|
><q-btn color="primary" icon="mdi-plus" title="Hinzufügen" round @click="addType"
|
||||||
|
/></template>
|
||||||
</q-input>
|
</q-input>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-actions="props">
|
<template #body-cell-actions="props">
|
||||||
|
|
|
@ -88,9 +88,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ComponentPublicInstance, computed, defineComponent, onBeforeMount, ref } from 'vue';
|
import { ComponentPublicInstance, computed, defineComponent, onBeforeMount, ref, watch } from 'vue';
|
||||||
import { QCalendarAgenda } from '@quasar/quasar-ui-qcalendar';
|
import { QCalendarAgenda } from '@quasar/quasar-ui-qcalendar';
|
||||||
import { date, QDate, QPopupProxy, useQuasar } from 'quasar';
|
import { date, QDate, QPopupProxy, useQuasar } from 'quasar';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { EditableEvent, emptyEvent } from '../../store/models';
|
import { EditableEvent, emptyEvent } from '../../store/models';
|
||||||
import { startOfWeek } from '@flaschengeist/api';
|
import { startOfWeek } from '@flaschengeist/api';
|
||||||
import { useEventStore } from '../../store';
|
import { useEventStore } from '../../store';
|
||||||
|
@ -105,6 +106,8 @@ export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
const store = useEventStore();
|
const store = useEventStore();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const datepicker = ref<QDate>();
|
const datepicker = ref<QDate>();
|
||||||
const proxy = ref<QPopupProxy>();
|
const proxy = ref<QPopupProxy>();
|
||||||
|
@ -141,6 +144,19 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
|
await router.replace({ query: { ...route.query, q_tab: 'agendaView' } });
|
||||||
|
if (!Object.keys(route.query).includes('q_date')) {
|
||||||
|
const q_date = date.formatDate(selectedDate.value, 'YYYY-MM-DD');
|
||||||
|
await router.replace({ query: { ...route.query, q_date } });
|
||||||
|
} else {
|
||||||
|
selectedDate.value = date.extractDate(route.query.q_date as string, 'YYYY-MM-DD');
|
||||||
|
}
|
||||||
|
if (!Object.keys(route.query).includes('q_view')) {
|
||||||
|
const q_view = calendarView.value;
|
||||||
|
await router.replace({ query: { ...route.query, q_view } });
|
||||||
|
} else {
|
||||||
|
calendarView.value = route.query.q_view as string;
|
||||||
|
}
|
||||||
await loadAgendas();
|
await loadAgendas();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -171,7 +187,11 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
async function loadAgendas() {
|
async function loadAgendas() {
|
||||||
|
if (loading.value) return;
|
||||||
|
loading.value = true;
|
||||||
const from =
|
const from =
|
||||||
calendarView.value === 'day' ? selectedDate.value : startOfWeek(selectedDate.value);
|
calendarView.value === 'day' ? selectedDate.value : startOfWeek(selectedDate.value);
|
||||||
const to = date.addToDate(from, { days: calendarView.value === 'day' ? 1 : 7 });
|
const to = date.addToDate(from, { days: calendarView.value === 'day' ? 1 : 7 });
|
||||||
|
@ -184,8 +204,11 @@ export default defineComponent({
|
||||||
if (!events.value[day]) {
|
if (!events.value[day]) {
|
||||||
events.value[day] = [];
|
events.value[day] = [];
|
||||||
}
|
}
|
||||||
events.value[day].push(event);
|
const idx = events.value[day].findIndex((e) => e.id === event.id);
|
||||||
|
if (idx === -1) events.value[day].push(event);
|
||||||
|
else events.value[day][idx] = event;
|
||||||
});
|
});
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDays(reverse: boolean) {
|
function addDays(reverse: boolean) {
|
||||||
|
@ -212,12 +235,24 @@ export default defineComponent({
|
||||||
'November',
|
'November',
|
||||||
'Dezember',
|
'Dezember',
|
||||||
'-',
|
'-',
|
||||||
][value?.getMonth() || 12];
|
][value?.getMonth() === 0 ? 0 : value?.getMonth() || 12];
|
||||||
}
|
}
|
||||||
function asYear(value?: Date) {
|
function asYear(value?: Date) {
|
||||||
return value?.getFullYear() || '-';
|
return value?.getFullYear() || '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(selectedDate, async (newValue) => {
|
||||||
|
const q_date = date.formatDate(newValue, 'YYYY-MM-DD');
|
||||||
|
await router.replace({ query: { ...route.query, q_date } });
|
||||||
|
await loadAgendas();
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(calendarView, async (newValue) => {
|
||||||
|
const q_view = newValue;
|
||||||
|
await router.replace({ query: { ...route.query, q_view } });
|
||||||
|
await loadAgendas();
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
asYear,
|
asYear,
|
||||||
asMonth,
|
asMonth,
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<q-separator />
|
<q-separator />
|
||||||
<q-item-label header>{{ asDate(index) }}</q-item-label>
|
<q-item-label header>{{ asDate(index) }}</q-item-label>
|
||||||
<q-item v-for="(event, idx) in events" :key="idx">
|
<q-item v-for="(event, idx) in events" :key="idx">
|
||||||
<event-slot :model-value="event" />
|
<event-slot v-model="events[idx]" @edit-event="edit" @remove-event="remove" />
|
||||||
</q-item>
|
</q-item>
|
||||||
</template>
|
</template>
|
||||||
</q-list>
|
</q-list>
|
||||||
|
@ -88,6 +88,10 @@ export default defineComponent({
|
||||||
|
|
||||||
function editDone(changed: boolean) {
|
function editDone(changed: boolean) {
|
||||||
//if (changed) void loadAgendas();
|
//if (changed) void loadAgendas();
|
||||||
|
const idx = events.value.findIndex((event) => event.id === editor.value?.id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
events.value[idx] = editor.value as FG.Event;
|
||||||
|
}
|
||||||
editor.value = undefined;
|
editor.value = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +99,12 @@ export default defineComponent({
|
||||||
const start = new Date();
|
const start = new Date();
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
const { result } = await store.getEvents({ to: start, limit: 5, descending: true });
|
const { result } = await store.getEvents({ to: start, limit: 5, descending: true });
|
||||||
events.value.unshift(...result);
|
//events.value.unshift(...result);
|
||||||
|
for (const event of result) {
|
||||||
|
const idx = events.value.findIndex((e) => e.id === event.id);
|
||||||
|
if (idx === -1) events.value.unshift(event);
|
||||||
|
else events.value[idx] = event;
|
||||||
|
}
|
||||||
if (done) done(false);
|
if (done) done(false);
|
||||||
} else {
|
} else {
|
||||||
const len = events.value.length;
|
const len = events.value.length;
|
||||||
|
@ -104,7 +113,12 @@ export default defineComponent({
|
||||||
offset: (index - 1) * 10,
|
offset: (index - 1) * 10,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
});
|
});
|
||||||
if (len == events.value.push(...result)) {
|
for (const event of result) {
|
||||||
|
const idx = events.value.findIndex((e) => e.id === event.id);
|
||||||
|
if (idx === -1) events.value.unshift(event);
|
||||||
|
else events.value[idx] = event;
|
||||||
|
}
|
||||||
|
if (len == events.value.length) {
|
||||||
if (done) return done(true);
|
if (done) return done(true);
|
||||||
} else if (done) done(false);
|
} else if (done) done(false);
|
||||||
}
|
}
|
||||||
|
@ -117,16 +131,10 @@ export default defineComponent({
|
||||||
|
|
||||||
async function remove(id: number) {
|
async function remove(id: number) {
|
||||||
if (await store.removeEvent(id)) {
|
if (await store.removeEvent(id)) {
|
||||||
// Successfull removed
|
const idx = events.value.findIndex((event) => event.id === id);
|
||||||
for (const idx in agendas.value) {
|
if (idx !== -1) {
|
||||||
const i = agendas.value[idx].findIndex((event) => event.id === id);
|
events.value.splice(idx, 1);
|
||||||
if (i !== -1) {
|
|
||||||
agendas.value[idx].splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Not found, this means our eventa are outdated
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
</q-select>
|
</q-select>
|
||||||
<div class="row col-12 justify-end">
|
<div class="row col-12 justify-end">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!modelValue.locked && !isEnrolled && !isFull"
|
v-if="!modelValue.locked && !isEnrolled && !isFull && canAssign"
|
||||||
flat
|
flat
|
||||||
color="primary"
|
color="primary"
|
||||||
label="Eintragen"
|
label="Eintragen"
|
||||||
|
@ -101,6 +101,7 @@ import { PERMISSIONS } from '../../../permissions';
|
||||||
import TransferInviteDialog from './TransferInviteDialog.vue';
|
import TransferInviteDialog from './TransferInviteDialog.vue';
|
||||||
import ServiceUserChip from './ServiceUserChip.vue';
|
import ServiceUserChip from './ServiceUserChip.vue';
|
||||||
import { UserAvatar } from '@flaschengeist/api/components';
|
import { UserAvatar } from '@flaschengeist/api/components';
|
||||||
|
import { DisplayNameMode } from '@flaschengeist/users';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'JobSlot',
|
name: 'JobSlot',
|
||||||
|
@ -123,11 +124,34 @@ export default defineComponent({
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
|
||||||
// Make sure users are loaded if we can assign them
|
// Make sure users are loaded if we can assign them
|
||||||
onBeforeMount(() => void userStore.getUsers());
|
onBeforeMount(() => {
|
||||||
|
void userStore.getUsers();
|
||||||
|
void userStore.getDisplayNameModeSetting(true);
|
||||||
|
});
|
||||||
|
|
||||||
/* Stuff used for general display */
|
/* Stuff used for general display */
|
||||||
// Get displayname of user
|
// Get displayname of user
|
||||||
function userDisplay(id: string) {
|
function userDisplay(id: string) {
|
||||||
|
switch (userStore.userSettings.display_name) {
|
||||||
|
case DisplayNameMode.FIRSTNAME:
|
||||||
|
return userStore.findUser(id)?.firstname || id;
|
||||||
|
case DisplayNameMode.LASTNAME:
|
||||||
|
return userStore.findUser(id)?.lastname || id;
|
||||||
|
case DisplayNameMode.DISPLAYNAME:
|
||||||
|
return userStore.findUser(id)?.display_name || id;
|
||||||
|
case DisplayNameMode.FIRSTNAME_LASTNAME:
|
||||||
|
return (
|
||||||
|
`${<string>userStore.findUser(id)?.firstname} ${<string>(
|
||||||
|
userStore.findUser(id)?.lastname
|
||||||
|
)}` || id
|
||||||
|
);
|
||||||
|
case DisplayNameMode.LASTNAME_FIRSTNAME:
|
||||||
|
return (
|
||||||
|
`${<string>userStore.findUser(id)?.lastname}, ${<string>(
|
||||||
|
userStore.findUser(id)?.firstname
|
||||||
|
)}` || id
|
||||||
|
);
|
||||||
|
}
|
||||||
return userStore.findUser(id)?.display_name || id;
|
return userStore.findUser(id)?.display_name || id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +229,8 @@ export default defineComponent({
|
||||||
// Current user can assign other users
|
// Current user can assign other users
|
||||||
const canAssignOther = computed(() => hasPermission(PERMISSIONS.ASSIGN_OTHER));
|
const canAssignOther = computed(() => hasPermission(PERMISSIONS.ASSIGN_OTHER));
|
||||||
|
|
||||||
|
const canAssign = computed(() => hasPermission(PERMISSIONS.ASSIGN));
|
||||||
|
|
||||||
// options shown in the select
|
// options shown in the select
|
||||||
const options = ref([] as FG.Service[]);
|
const options = ref([] as FG.Service[]);
|
||||||
|
|
||||||
|
@ -257,6 +283,7 @@ export default defineComponent({
|
||||||
unassign: (s?: FG.Service) => assign(Object.assign({}, s || service.value, { value: -1 })),
|
unassign: (s?: FG.Service) => assign(Object.assign({}, s || service.value, { value: -1 })),
|
||||||
backup: (is_backup: boolean) => assign(Object.assign({}, service.value, { is_backup })),
|
backup: (is_backup: boolean) => assign(Object.assign({}, service.value, { is_backup })),
|
||||||
canAssignOther,
|
canAssignOther,
|
||||||
|
canAssign,
|
||||||
canInvite,
|
canInvite,
|
||||||
filterUsers,
|
filterUsers,
|
||||||
isBackup,
|
isBackup,
|
||||||
|
|
|
@ -44,7 +44,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, ref } from 'vue';
|
import { computed, defineComponent, ref, onBeforeMount, watch } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import ManageTypes from '../components/management/ManageTypes.vue';
|
import ManageTypes from '../components/management/ManageTypes.vue';
|
||||||
import EditEvent from '../components/management/EditEvent.vue';
|
import EditEvent from '../components/management/EditEvent.vue';
|
||||||
import { hasPermission } from '@flaschengeist/api';
|
import { hasPermission } from '@flaschengeist/api';
|
||||||
|
@ -70,6 +71,21 @@ export default defineComponent({
|
||||||
: []),
|
: []),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
if (
|
||||||
|
(route.query.q_tab && route.query.q_tab === 'create') ||
|
||||||
|
route.query.q_tab === 'jobtypes' ||
|
||||||
|
route.query.q_tab === 'eventtypes'
|
||||||
|
) {
|
||||||
|
tab.value = route.query.q_tab;
|
||||||
|
} else {
|
||||||
|
await router.replace({ query: { q_tab: tab.value } });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const drawer = ref<boolean>(false);
|
const drawer = ref<boolean>(false);
|
||||||
const tab = ref<string>('create');
|
const tab = ref<string>('create');
|
||||||
|
|
||||||
|
@ -82,6 +98,10 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(tab, async (val) => {
|
||||||
|
await router.replace({ query: { q_tab: val } });
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
showDrawer,
|
showDrawer,
|
||||||
tab,
|
tab,
|
||||||
|
|
|
@ -43,7 +43,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, ref, onBeforeMount } from 'vue';
|
import { computed, defineComponent, ref, onBeforeMount, watch } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import AgendaView from '../components/overview/AgendaView.vue';
|
import AgendaView from '../components/overview/AgendaView.vue';
|
||||||
import ListView from '../components/overview/ListView.vue';
|
import ListView from '../components/overview/ListView.vue';
|
||||||
|
@ -55,8 +56,19 @@ export default defineComponent({
|
||||||
components: { AgendaView, ListView },
|
components: { AgendaView, ListView },
|
||||||
setup() {
|
setup() {
|
||||||
const store = useEventStore();
|
const store = useEventStore();
|
||||||
onBeforeMount(() => {
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const tab = ref<string>('agendaView');
|
||||||
|
onBeforeMount(async () => {
|
||||||
void store.getJobTypes();
|
void store.getJobTypes();
|
||||||
|
if (
|
||||||
|
Object.keys(route.query).includes('q_tab') &&
|
||||||
|
(route.query.q_tab === 'listView' || route.query.q_tab === 'agendaView')
|
||||||
|
) {
|
||||||
|
tab.value = route.query.q_tab as string;
|
||||||
|
} else {
|
||||||
|
await router.replace({ query: { ...route.query, q_tab: tab.value } });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
|
||||||
|
@ -74,7 +86,10 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const tab = ref<string>('agendaView');
|
watch(tab, async (val) => {
|
||||||
|
console.log(val);
|
||||||
|
await router.replace({ query: { ...route.query, q_tab: val } });
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
showDrawer,
|
showDrawer,
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { formatStartEnd, useMainStore, useUserStore } from '@flaschengeist/api';
|
import { formatStartEnd, useMainStore, useUserStore } from '@flaschengeist/api';
|
||||||
import { computed, defineComponent, ref, onBeforeMount, watch } from 'vue';
|
import { computed, defineComponent, ref, onBeforeMount, watch } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { QTableProps } from 'quasar';
|
import { QTableProps } from 'quasar';
|
||||||
import { Job } from '../store/models';
|
import { Job } from '../store/models';
|
||||||
import { useEventStore } from '../store';
|
import { useEventStore } from '../store';
|
||||||
|
@ -67,6 +68,8 @@ export default defineComponent({
|
||||||
const store = useEventStore();
|
const store = useEventStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const mainStore = useMainStore();
|
const mainStore = useMainStore();
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
interface RowData extends FG.Invitation {
|
interface RowData extends FG.Invitation {
|
||||||
inviter: FG.User;
|
inviter: FG.User;
|
||||||
|
@ -155,7 +158,11 @@ export default defineComponent({
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(async () => {
|
||||||
|
if (route.query.sent === 'true') {
|
||||||
|
showSent.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
void Promise.allSettled([
|
void Promise.allSettled([
|
||||||
userStore.getUsers(),
|
userStore.getUsers(),
|
||||||
store.getInvitations(),
|
store.getInvitations(),
|
||||||
|
@ -165,8 +172,9 @@ export default defineComponent({
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(showSent, () => {
|
watch(showSent, async () => {
|
||||||
onRequest({ pagination: pagination.value, filter: () => [], getCellValue: () => [] });
|
onRequest({ pagination: pagination.value, filter: () => [], getCellValue: () => [] });
|
||||||
|
await router.replace({ query: { sent: showSent.value ? 'true' : 'false' } });
|
||||||
});
|
});
|
||||||
|
|
||||||
function getType(row: RowData) {
|
function getType(row: RowData) {
|
||||||
|
|
|
@ -150,15 +150,13 @@ export const useEventStore = defineStore({
|
||||||
if (event?.id === undefined) {
|
if (event?.id === undefined) {
|
||||||
const { data } = await api.post<FG.Event>('/events', event);
|
const { data } = await api.post<FG.Event>('/events', event);
|
||||||
if (data.is_template) this.templates.push(data);
|
if (data.is_template) this.templates.push(data);
|
||||||
|
fixEvent(data);
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
if (typeof event.type === 'object') event.type = event.type.id;
|
if (typeof event.type === 'object') event.type = event.type.id;
|
||||||
const { data } = await api.put<FG.Event>(
|
const { data } = await api.put<FG.Event>(`/events/${event.id}`, event);
|
||||||
`/events/${event.id}`,
|
|
||||||
// Object.assign(event, { jobs: undefined })
|
|
||||||
event
|
|
||||||
);
|
|
||||||
if (data.is_template) this.templates.push(data);
|
if (data.is_template) this.templates.push(data);
|
||||||
|
fixEvent(data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue