stash events admin frontend

This commit is contained in:
j3d1 2024-11-01 22:26:15 +01:00
parent c6ddbfe7b8
commit 546e49e50e
6 changed files with 131 additions and 10 deletions

View file

@ -3,6 +3,7 @@
<AddItemModal v-if="addItemModalOpen && isLoggedIn" @close="closeAddItemModal()" isModal="true"/> <AddItemModal v-if="addItemModalOpen && isLoggedIn" @close="closeAddItemModal()" isModal="true"/>
<AddTicketModal v-if="addTicketModalOpen && isLoggedIn" @close="closeAddTicketModal()" isModal="true"/> <AddTicketModal v-if="addTicketModalOpen && isLoggedIn" @close="closeAddTicketModal()" isModal="true"/>
<AddBoxModal v-if="showAddBoxModal && isLoggedIn" @close="closeAddBoxModal()" isModal="true"/> <AddBoxModal v-if="showAddBoxModal && isLoggedIn" @close="closeAddBoxModal()" isModal="true"/>
<AddEventModal v-if="showAddEventModal && isLoggedIn" @close="closeAddEventModal()" isModal="true"/>
<Navbar v-if="isLoggedIn" @addItemClicked="openAddItemModal()" @addTicketClicked="openAddTicketModal()"/> <Navbar v-if="isLoggedIn" @addItemClicked="openAddItemModal()" @addTicketClicked="openAddTicketModal()"/>
<router-view style="flex: 1 1;"/> <router-view style="flex: 1 1;"/>
</div> </div>
@ -14,12 +15,13 @@ import AddItemModal from '@/components/AddItemModal';
import {mapState, mapMutations, mapActions, mapGetters} from 'vuex'; import {mapState, mapMutations, mapActions, mapGetters} from 'vuex';
import AddTicketModal from "@/components/AddTicketModal.vue"; import AddTicketModal from "@/components/AddTicketModal.vue";
import AddBoxModal from "@/components/AddBoxModal.vue"; import AddBoxModal from "@/components/AddBoxModal.vue";
import AddEventModal from "@/components/AddEventModal.vue";
export default { export default {
name: 'app', name: 'app',
components: {AddBoxModal, Navbar, AddItemModal, AddTicketModal}, components: {AddBoxModal, AddEventModal, Navbar, AddItemModal, AddTicketModal},
computed: { computed: {
...mapState(['loadedItems', 'layout', 'toasts', 'showAddBoxModal']), ...mapState(['loadedItems', 'layout', 'toasts', 'showAddBoxModal', 'showAddEventModal']),
...mapGetters(['isLoggedIn']), ...mapGetters(['isLoggedIn']),
}, },
data: () => ({ data: () => ({
@ -27,7 +29,7 @@ export default {
addTicketModalOpen: false addTicketModalOpen: false
}), }),
methods: { methods: {
...mapMutations(['removeToast', 'createToast', 'closeAddBoxModal', 'openAddBoxModal']), ...mapMutations(['removeToast', 'createToast', 'closeAddBoxModal', 'openAddBoxModal', 'closeAddEventModal']),
...mapActions(['loadEvents', 'scheduleAfterInit']), ...mapActions(['loadEvents', 'scheduleAfterInit']),
openAddItemModal() { openAddItemModal() {
this.addItemModalOpen = true; this.addItemModalOpen = true;

View file

@ -0,0 +1,86 @@
<template>
<div>
<Modal v-if="isModal" title="Add Event" @close="$emit('close')">
<template #body>
<div>
<div class="row mb-3">
<div class="col">
<input type="text" class="form-control" placeholder="Event Title"
v-model="data.name">
</div>
<div class="col">
<input type="text" class="form-control" placeholder="Event Slug" v-model="data.slug">
</div>
</div>
<div class="row">
<div class="col">
<input type="date" class="form-control" title="Buildup Start" v-model="data.pre_start"
:max="data.start" @focus="prepare_date_field">
</div>
<div class="col">
<input type="date" class="form-control" title="Official Event Start" v-model="data.start"
:min="data.pre_start" :max="data.end" @focus="prepare_date_field">
</div>
<div class="col">
<input type="date" class="form-control" title="Official Event End" v-model="data.end"
:min="data.start" :max="data.post_end" @focus="prepare_date_field">
</div>
<div class="col">
<input type="date" class="form-control" title="Teardown End" v-model="data.post_end"
:min="data.end" @focus="prepare_date_field">
</div>
</div>
<small>The buildup and teardown dates only relate to the timeframe in which the c3lf team is
present.</small>
</div>
</template>
<template #buttons>
<button type="button" class="btn btn-secondary" @click="$emit('close')">Cancel</button>
<button type="button" class="btn btn-success" @click="createEvent(data).then(()=>$emit('close'))">
Create
</button>
</template>
</Modal>
</div>
</template>
<script>
import Modal from '@/components/Modal';
import {mapActions} from "vuex";
export default {
name: 'AddEventModal',
components: {Modal},
props: ['isModal'],
data: () => ({
data: {
name: '',
slug: '',
start: null,
end: null,
pre_start: null,
post_end: null,
},
errors: {},
}),
methods: {
...mapActions(['createEvent']),
validate_data() {
return this.pre_start <= this.start && this.start <= this.end && this.end <= this.post_end && !!this.event_slug && !!this.event_name;
},
prepare_date_field(e) {
if (!e.target.value) {
if (e.target.min) {
e.target.value = e.target.min
} else if (e.target.max) {
e.target.value = e.target.max
}
}
}
},
};
</script>
<style scoped>
</style>

View file

@ -57,7 +57,7 @@ export default {
color: #17a2b8; color: #17a2b8;
} }
.async-wrapper.loaded > .loader-wrapper > .loader-ellipsis { .async-wrapper.loaded > .loader-wrapper {
display: none; display: none;
} }

View file

@ -54,6 +54,7 @@ const store = createStore({
afterInitHandlers: [], afterInitHandlers: [],
showAddBoxModal: false, showAddBoxModal: false,
showAddEventModal: false,
test: ['foo', 'bar', 'baz'], test: ['foo', 'bar', 'baz'],
shippingVoucherTypes: { shippingVoucherTypes: {
@ -179,6 +180,12 @@ const store = createStore({
closeAddBoxModal(state) { closeAddBoxModal(state) {
state.showAddBoxModal = false; state.showAddBoxModal = false;
}, },
openAddEventModal(state) {
state.showAddEventModal = true;
},
closeAddEventModal(state) {
state.showAddEventModal = false;
},
createToast(state, {title, message, color}) { createToast(state, {title, message, color}) {
var toast = {title, message, color, key: state.keyIncrement} var toast = {title, message, color, key: state.keyIncrement}
state.toasts.push(toast); state.toasts.push(toast);
@ -321,6 +328,18 @@ const store = createStore({
if (data && success) if (data && success)
commit('replaceEvents', data); commit('replaceEvents', data);
}, },
async createEvent({commit, dispatch, state}, event) {
const {data, success} = await http.post('/2/events/', event, state.user.token);
if (data && success)
commit('replaceEvents', [...state.events, data]);
},
async deleteEvent({commit, dispatch, state}, event_id) {
const {data, success} = await http.delete(`/2/events/${event_id}/`, state.user.token);
if (success) {
await dispatch('loadEvents')
commit('replaceEvents', [...state.events.filter(e => e.eid !== event_id)])
}
},
async fetchTicketStates({commit, state}) { async fetchTicketStates({commit, state}) {
if (!state.user.token) return; if (!state.user.token) return;
if (state.fetchedData.states > Date.now() - 1000 * 60 * 60 * 24) return; if (state.fetchedData.states > Date.now() - 1000 * 60 * 60 * 24) return;

View file

@ -95,8 +95,8 @@ const http = {
"Authorization": `Token ${token}`, "Authorization": `Token ${token}`,
}, },
}); });
const success = response.status === 200 || response.status === 201; const success = response.status === 204;
return {data: await response.json() || {}, success}; return {data: await response.text() || {}, success};
} }
} }

View file

@ -4,13 +4,19 @@
:items="events" :items="events"
:keyName="'slug'" :keyName="'slug'"
> >
<template #actions="{ item }"> <template v-slot:header_actions>
<button class="btn btn-success" @click.prevent="openAddEventModal">
<font-awesome-icon icon="plus"/>
Create Event
</button>
</template>
<template v-slot:actions="{ item }">
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-secondary" @click.stop="changeEvent(item)"> <button class="btn btn-secondary" @click.stop="changeEvent(item)">
<font-awesome-icon icon="archive"/> <font-awesome-icon icon="archive"/>
use use
</button> </button>
<button class="btn btn-danger" @click.stop=""> <button class="btn btn-danger" @click.stop="safeDeleteEvent(item.eid)">
<font-awesome-icon icon="trash"/> <font-awesome-icon icon="trash"/>
delete delete
</button> </button>
@ -20,14 +26,22 @@
</template> </template>
<script> <script>
import {mapActions, mapState} from 'vuex'; import {mapActions, mapMutations, mapState} from 'vuex';
import Table from '@/components/Table'; import Table from '@/components/Table';
export default { export default {
name: 'Events', name: 'Events',
components: {Table}, components: {Table},
computed: mapState(['events']), computed: mapState(['events']),
methods: mapActions(['changeEvent']), methods: {
...mapActions(['changeEvent', 'deleteEvent']),
...mapMutations(['openAddEventModal']),
safeDeleteEvent(id) {
if (confirm('do you want to completely delete this event and related data?')) {
this.deleteEvent(id)
}
},
},
}; };
</script> </script>