[manage] Merge types management into one component
This commit is contained in:
parent
9331006db3
commit
3dc108656a
|
@ -1,125 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<q-dialog v-model="edittype">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<div class="text-h6">Editere Diensttyp {{ actualJob.name }}</div>
|
|
||||||
</q-card-section>
|
|
||||||
<q-card-section>
|
|
||||||
<q-input v-model="newJobName" dense label="name" filled />
|
|
||||||
</q-card-section>
|
|
||||||
<q-card-actions>
|
|
||||||
<q-btn flat color="danger" label="Abbrechen" @click="discardChanges()" />
|
|
||||||
<q-btn flat color="primary" label="Speichern" @click="saveChanges()" />
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card>
|
|
||||||
</q-dialog>
|
|
||||||
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<q-table title="Diensttypen" :rows="rows" row-key="jobid" :columns="columns">
|
|
||||||
<template #top-right>
|
|
||||||
<q-input v-model="newJob" dense placeholder="Neuer Typ" />
|
|
||||||
|
|
||||||
<div></div>
|
|
||||||
<q-btn color="primary" icon="mdi-plus" label="Hinzufügen" @click="addType" />
|
|
||||||
</template>
|
|
||||||
<template #body-cell-actions="props">
|
|
||||||
<!-- <q-btn :label="item"> -->
|
|
||||||
<!-- {{ item.row.name }} -->
|
|
||||||
<q-td :props="props" align="right" :auto-width="true">
|
|
||||||
<q-btn
|
|
||||||
round
|
|
||||||
icon="mdi-pencil"
|
|
||||||
@click="editType({ id: props.row.id, name: props.row.name })"
|
|
||||||
/>
|
|
||||||
<q-btn round icon="mdi-delete" @click="deleteType(props.row.id)" />
|
|
||||||
</q-td>
|
|
||||||
</template>
|
|
||||||
</q-table>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, ref, computed, onBeforeMount } from 'vue';
|
|
||||||
import { useScheduleStore } from '../../store';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'JobTypes',
|
|
||||||
components: {},
|
|
||||||
setup() {
|
|
||||||
const store = useScheduleStore();
|
|
||||||
const newJob = ref('');
|
|
||||||
const edittype = ref(false);
|
|
||||||
const emptyJob: FG.JobType = { id: -1, name: '' };
|
|
||||||
const actualJob = ref(emptyJob);
|
|
||||||
const newJobName = ref('');
|
|
||||||
|
|
||||||
onBeforeMount(() => store.getJobTypes());
|
|
||||||
|
|
||||||
const rows = computed(() => store.jobTypes);
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
name: 'jobname',
|
|
||||||
label: 'Name',
|
|
||||||
field: 'name',
|
|
||||||
align: 'left',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'actions',
|
|
||||||
label: 'Aktionen',
|
|
||||||
field: 'actions',
|
|
||||||
align: 'right',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
async function addType() {
|
|
||||||
await store.addJobType(newJob.value);
|
|
||||||
newJob.value = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function editType(job: FG.JobType) {
|
|
||||||
edittype.value = true;
|
|
||||||
actualJob.value = job;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveChanges() {
|
|
||||||
try {
|
|
||||||
await store.renameJobType(actualJob.value.id, newJobName.value);
|
|
||||||
} finally {
|
|
||||||
discardChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function discardChanges() {
|
|
||||||
actualJob.value = emptyJob;
|
|
||||||
newJobName.value = '';
|
|
||||||
edittype.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteType(id: number) {
|
|
||||||
void store.removeJobType(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
columns,
|
|
||||||
rows,
|
|
||||||
addType,
|
|
||||||
newJob,
|
|
||||||
deleteType,
|
|
||||||
edittype,
|
|
||||||
editType,
|
|
||||||
actualJob,
|
|
||||||
newJobName,
|
|
||||||
discardChanges,
|
|
||||||
saveChanges,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
|
@ -3,10 +3,10 @@
|
||||||
<q-dialog v-model="dialogOpen">
|
<q-dialog v-model="dialogOpen">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div class="text-h6">Editere Diensttyp {{ actualEvent.name }}</div>
|
<div class="text-h6">Editere {{title}} {{ actualType.name }}</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input v-model="newEventName" :rules="rules" ref="dialogInput" dense label="name" filled />
|
<q-input v-model="actualType.name" :rules="rules" ref="dialogInput" dense label="name" filled />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions>
|
<q-card-actions>
|
||||||
<q-btn flat color="danger" label="Abbrechen" @click="discardChanges()" />
|
<q-btn flat color="danger" label="Abbrechen" @click="discardChanges()" />
|
||||||
|
@ -17,10 +17,10 @@
|
||||||
|
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-table title="Veranstaltungstypen" :rows="rows" row-key="jobid" :columns="columns">
|
<q-table :title="title" :rows="rows" row-key="id" :columns="columns">
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="newEventType"
|
v-model="actualType.name"
|
||||||
ref="input"
|
ref="input"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
dense
|
dense
|
||||||
|
@ -32,13 +32,11 @@
|
||||||
</q-input>
|
</q-input>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell-actions="props">
|
<template #body-cell-actions="props">
|
||||||
<!-- <q-btn :label="item"> -->
|
|
||||||
<!-- {{ item.row.name }} -->
|
|
||||||
<q-td :props="props" align="right" :auto-width="true">
|
<q-td :props="props" align="right" :auto-width="true">
|
||||||
<q-btn
|
<q-btn
|
||||||
round
|
round
|
||||||
icon="mdi-pencil"
|
icon="mdi-pencil"
|
||||||
@click="editType({ id: props.row.id, name: props.row.name })"
|
@click="editType(props.row.id)"
|
||||||
/>
|
/>
|
||||||
<q-btn round icon="mdi-delete" @click="deleteType(props.row.id)" />
|
<q-btn round icon="mdi-delete" @click="deleteType(props.row.id)" />
|
||||||
</q-td>
|
</q-td>
|
||||||
|
@ -51,38 +49,42 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { isAxiosError } from '@flaschengeist/api';
|
import { isAxiosError } from '@flaschengeist/api';
|
||||||
import { defineComponent, ref, computed, onBeforeMount } from 'vue';
|
import { defineComponent, ref, computed, PropType, onBeforeMount } from 'vue';
|
||||||
import { useScheduleStore } from '../../store';
|
import { useScheduleStore } from '../../store';
|
||||||
import { Notify, QInput } from 'quasar';
|
import { Notify, QInput } from 'quasar';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'EventTypes',
|
name: 'ManageTypes',
|
||||||
components: {},
|
components: {},
|
||||||
setup() {
|
props:{
|
||||||
|
type: {type: String as PropType<'EventType' | 'JobType'>, required: true},
|
||||||
|
title: {type: String, required: true}
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
const store = useScheduleStore();
|
const store = useScheduleStore();
|
||||||
const newEventType = ref('');
|
const newType = ref('');
|
||||||
const dialogOpen = ref(false);
|
const dialogOpen = ref(false);
|
||||||
const emptyEvent: FG.EventType = { id: -1, name: '' };
|
const emptyType = { id: -1, name: '' };
|
||||||
const actualEvent = ref(emptyEvent);
|
const actualType = ref(emptyType);
|
||||||
const newEventName = ref('');
|
|
||||||
const input = ref<QInput>(null);
|
const input = ref<QInput>(null);
|
||||||
const dialogInput = ref<QInput>(null);
|
const dialogInput = ref<QInput>(null);
|
||||||
|
const storeName = computed(() => props.type.charAt(0).toLowerCase() + props.type.slice(1) + 's')
|
||||||
|
|
||||||
onBeforeMount(async () => await store.getEventTypes());
|
onBeforeMount(async () => await store[`get${props.type}s`]());
|
||||||
|
|
||||||
const rows = computed(() => store.eventTypes);
|
const rows = computed(() => store[storeName.value]);
|
||||||
|
|
||||||
const rules = [
|
const rules = [
|
||||||
(s: any) => !!s || 'Darf nicht leer sein!',
|
(s: any) => !!s || 'Darf nicht leer sein!',
|
||||||
(s: string) =>
|
(s: string) =>
|
||||||
store.eventTypes.find((e) => e.name === s) === undefined ||
|
store[storeName.value].find((e) => e.name === s) === undefined ||
|
||||||
'Der Name wird bereits verwendet',
|
'Der Name wird bereits verwendet',
|
||||||
];
|
];
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Veranstaltungstyp',
|
label: props.title,
|
||||||
field: 'name',
|
field: 'name',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -98,9 +100,9 @@ export default defineComponent({
|
||||||
function addType() {
|
function addType() {
|
||||||
if (input.value === null || input.value.validate())
|
if (input.value === null || input.value.validate())
|
||||||
store
|
store
|
||||||
.addEventType(newEventType.value)
|
[`add${props.type}`](actualType.value.name)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
newEventType.value = '';
|
actualType.value.name = '';
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
if (isAxiosError(e, 409))
|
if (isAxiosError(e, 409))
|
||||||
|
@ -116,28 +118,27 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function editType(event: FG.EventType) {
|
function editType(id: number) {
|
||||||
dialogOpen.value = true;
|
dialogOpen.value = true;
|
||||||
actualEvent.value = event;
|
actualType.value = Object.assign({}, rows.value.find((v) => v.id === id));
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveChanges() {
|
function saveChanges() {
|
||||||
if (dialogInput.value === null || dialogInput.value.validate())
|
if (dialogInput.value === null || dialogInput.value.validate())
|
||||||
store.renameEventType(actualEvent.value.id, newEventName.value).then(() => discardChanges());
|
store[`rename${props.type}`](actualType.value.id, actualType.value.name).then(() => discardChanges());
|
||||||
}
|
}
|
||||||
|
|
||||||
function discardChanges() {
|
function discardChanges() {
|
||||||
actualEvent.value = emptyEvent;
|
actualType.value = emptyType;
|
||||||
newEventName.value = '';
|
|
||||||
dialogOpen.value = false;
|
dialogOpen.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteType(id: number) {
|
async function deleteType(id: number) {
|
||||||
await store.removeEventType(id);
|
await store[`remove${props.type}`](id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
actualEvent,
|
actualType,
|
||||||
addType,
|
addType,
|
||||||
columns,
|
columns,
|
||||||
deleteType,
|
deleteType,
|
||||||
|
@ -148,8 +149,6 @@ export default defineComponent({
|
||||||
input,
|
input,
|
||||||
rows,
|
rows,
|
||||||
rules,
|
rules,
|
||||||
newEventType,
|
|
||||||
newEventName,
|
|
||||||
saveChanges,
|
saveChanges,
|
||||||
};
|
};
|
||||||
},
|
},
|
|
@ -35,10 +35,10 @@
|
||||||
<EditEvent />
|
<EditEvent />
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="eventtypes">
|
<q-tab-panel name="eventtypes">
|
||||||
<EventTypes />
|
<ManageTypes title="Veranstaltungstyp" type="EventType" />
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="jobtypes">
|
<q-tab-panel name="jobtypes">
|
||||||
<JobTypes />
|
<ManageTypes title="Dienstart" type="JobType" />
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
</q-tab-panels>
|
</q-tab-panels>
|
||||||
</q-page>
|
</q-page>
|
||||||
|
@ -47,8 +47,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, ref } from 'vue';
|
import { computed, defineComponent, ref } from 'vue';
|
||||||
import EventTypes from '../components/management/EventTypes.vue';
|
import ManageTypes from '../components/management/ManageTypes.vue';
|
||||||
import JobTypes from '../components/management/JobTypes.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';
|
||||||
import { PERMISSIONS } from '../permissions';
|
import { PERMISSIONS } from '../permissions';
|
||||||
|
@ -56,7 +55,7 @@ import { Screen } from 'quasar';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'EventManagement',
|
name: 'EventManagement',
|
||||||
components: { EditEvent, EventTypes, JobTypes },
|
components: { EditEvent, ManageTypes },
|
||||||
setup() {
|
setup() {
|
||||||
const tabs = computed(() => [
|
const tabs = computed(() => [
|
||||||
{ name: 'create', label: 'Veranstaltungen' },
|
{ name: 'create', label: 'Veranstaltungen' },
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
<AgendaView />
|
<AgendaView />
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="eventtypes">
|
<q-tab-panel name="eventtypes">
|
||||||
<EventTypes />
|
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
</q-tab-panels>
|
</q-tab-panels>
|
||||||
</q-page>
|
</q-page>
|
||||||
|
@ -44,14 +43,12 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, ref } from 'vue';
|
import { computed, defineComponent, ref } from 'vue';
|
||||||
import EventTypes from '../components/management/EventTypes.vue';
|
|
||||||
//import CreateEvent from '../components/management/CreateEvent.vue';
|
|
||||||
import AgendaView from '../components/overview/AgendaView.vue';
|
import AgendaView from '../components/overview/AgendaView.vue';
|
||||||
import { Screen } from 'quasar';
|
import { Screen } from 'quasar';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'EventOverview',
|
name: 'EventOverview',
|
||||||
components: { AgendaView, EventTypes },
|
components: { AgendaView },
|
||||||
setup() {
|
setup() {
|
||||||
interface Tab {
|
interface Tab {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
77
src/store.ts
77
src/store.ts
|
@ -1,4 +1,4 @@
|
||||||
import { api } from '@flaschengeist/api';
|
import { api, isAxiosError } from '@flaschengeist/api';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ function fixEvent(event: FG.Event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useScheduleStore = defineStore({
|
export const useScheduleStore = defineStore({
|
||||||
id: 'schedule',
|
id: 'events',
|
||||||
|
|
||||||
state: () => ({
|
state: () => ({
|
||||||
jobTypes: [] as FG.JobType[],
|
jobTypes: [] as FG.JobType[],
|
||||||
|
@ -41,24 +41,25 @@ export const useScheduleStore = defineStore({
|
||||||
return this.jobTypes;
|
return this.jobTypes;
|
||||||
},
|
},
|
||||||
|
|
||||||
async addJobType(name: string) {
|
addJobType(name: string) {
|
||||||
try {
|
return api
|
||||||
const { data } = await api.post<FG.JobType>('/events/job-types', { name: name });
|
.post<FG.JobType>('/events/job-types', { name: name })
|
||||||
this.jobTypes.push(data);
|
.then(({ data }) => this.jobTypes.push(data));
|
||||||
} catch (error) {
|
|
||||||
// TODO: HANDLE ERROR
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async removeJobType(id: number) {
|
removeJobType(id: number) {
|
||||||
await api.delete(`/events/job-types/${id}`);
|
return api
|
||||||
//Todo Handle delete JT
|
.delete(`/events/job-types/${id}`)
|
||||||
|
.then(() => this.jobTypes = this.jobTypes.filter(v => v.id !== id));
|
||||||
},
|
},
|
||||||
|
|
||||||
async renameJobType(id: number, newName: string) {
|
renameJobType(id: number, newName: string) {
|
||||||
await api.put(`/events/job-types/${id}`, { name: newName });
|
return api
|
||||||
// TODO handle rename
|
.put(`/events/job-types/${id}`, { name: newName })
|
||||||
|
.then(() => {
|
||||||
|
const idx = this.jobTypes.findIndex(v=>v.id===id);
|
||||||
|
if (idx >= 0) this.jobTypes[idx].name = newName;
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
async getEventTypes(force = false) {
|
async getEventTypes(force = false) {
|
||||||
|
@ -75,21 +76,13 @@ export const useScheduleStore = defineStore({
|
||||||
/** Add new EventType
|
/** Add new EventType
|
||||||
*
|
*
|
||||||
* @param name Name of new EventType
|
* @param name Name of new EventType
|
||||||
* @returns EventType object or null if name already exists
|
|
||||||
* @throws Exception if requests fails because of an other reason
|
|
||||||
*/
|
*/
|
||||||
async addEventType(name: string) {
|
addEventType(name: string) {
|
||||||
try {
|
return api
|
||||||
const { data } = await api.post<FG.EventType>('/events/event-types', { name: name });
|
.post<FG.EventType>('/events/event-types', { name: name })
|
||||||
return data;
|
.then(({data}) => this.eventTypes.push(data))
|
||||||
} catch (error) {
|
|
||||||
if ('response' in error) {
|
|
||||||
const ae = <AxiosError>error;
|
|
||||||
if (ae.response && ae.response.status == 409 /* CONFLICT */) return null;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async removeEvent(id: number) {
|
async removeEvent(id: number) {
|
||||||
try {
|
try {
|
||||||
await api.delete(`/events/${id}`);
|
await api.delete(`/events/${id}`);
|
||||||
|
@ -103,23 +96,19 @@ export const useScheduleStore = defineStore({
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
async removeEventType(id: number) {
|
removeEventType(id: number) {
|
||||||
await api.delete(`/events/event-types/${id}`);
|
return api
|
||||||
// TODO handle delete
|
.delete(`/events/event-types/${id}`)
|
||||||
|
.then(() => this.eventTypes = this.eventTypes.filter(v => v.id !== id));
|
||||||
},
|
},
|
||||||
|
|
||||||
async renameEventType(id: number, newName: string) {
|
renameEventType(id: number, newName: string) {
|
||||||
try {
|
return api
|
||||||
await api.put(`/events/event-types/${id}`, { name: newName });
|
.put(`/events/event-types/${id}`, { name: newName })
|
||||||
// TODO handle rename
|
.then(() => {
|
||||||
return true;
|
const idx = this.eventTypes.findIndex(v=>v.id===id);
|
||||||
} catch (error) {
|
if (idx >= 0) this.eventTypes[idx].name = newName;
|
||||||
if ('response' in error) {
|
})
|
||||||
const ae = <AxiosError>error;
|
|
||||||
if (ae.response && ae.response.status == 409 /* CONFLICT */) return false;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async getTemplates(force = false) {
|
async getTemplates(force = false) {
|
||||||
|
|
Loading…
Reference in New Issue