popups, fixes, location editing

This commit is contained in:
2023-06-25 15:26:46 +02:00
parent aed1ca4712
commit c05bd545b4
7 changed files with 230 additions and 107 deletions

View File

@@ -2,3 +2,5 @@
- Load: email, settings, change pw, change mail, see all tickets
- set page title based on settings
- make pricing groups changeable in UI (event categories)

View File

@@ -32,7 +32,7 @@
--accent-color: #42b983;
--hover-color: rgb(165, 165, 165);
--accent-background-hover: #4380a8;
--overlay-color: rgba(37, 37, 37, 0.575);
--overlay-color: rgba(0, 0, 0, 0.7);
--inactive-color: rgb(100, 100, 100);
--highlight-backdrop: rgb(143, 134, 192);
--PI: 3.14159265358979;

View File

@@ -1,131 +1,100 @@
<template>
<div id="notifications" @click="handleNotifications();">
<div class="message-box" :class="messageType">
<div id="popup-backdrop" :class="status">
<div class="popup-container">
<div class="popup" :class="size">
<span class="material-symbols-outlined" @click="closePopup();">close</span>
<div class="message-container">
<span class="material-symbols-outlined types" v-if="messageType == 'ok'" style="background-color: green;">done</span>
<span class="material-symbols-outlined types" v-else-if="messageType == 'error'" style="background-color: red;">close</span>
<span class="material-symbols-outlined types progress-spinner" v-else-if="messageType == 'progress'" style="background-color: blue;">progress_activity</span>
<span class="material-symbols-outlined types" v-else-if="messageType == 'info'" style="background-color: lightblue;">info</span>
<p class="message">{{ message }}</p>
{{ message }}
</div>
</div>
</div>
</div>
</template>
<!-- Options to be passed in: HTML, Settings (for settings component), strings, numbers, confirm, radio, dropdowns, selection -->
<script>
export default {
name: 'notifications',
name: 'popups',
prop: {
size: {
type: String,
'default': 'normal',
},
message: {
type: Object,
'default': '{}',
},
},
data () {
return {
notifications: {},
queue: [],
message: '',
messageType: 'hide',
notificationDisplayTime: 1,
notificationPriority: 'normal',
currentlyDisplayedNotificationID: 0,
currentID: { 'critical': 0, 'medium': 1000, 'low': 100000 },
displayTimeCurrentNotification: 0,
notificationScheduler: null,
status: 'hidden',
}
},
methods: {
createNotification( message, showDuration, messageType, priority ) {
/*
Takes a notification options array that contains: message, showDuration (in seconds), messageType (ok, error, progress, info) and priority (low, medium, critical).
Returns a notification ID which can be used to cancel the notification. The component will throttle notifications and display
one at a time and prioritize messages with higher priority. Use vue refs to access these methods.
*/
let id = 0;
closePopup() {
this.shown = 'hidden'
},
openPopup () {
if ( priority === 'critical' ) {
this.currentID[ 'critical' ] += 1;
id = this.currentID[ 'critical' ];
} else if ( priority === 'normal' ) {
this.currentID[ 'medium' ] += 1;
id = this.currentID[ 'medium' ];
} else if ( priority === 'low' ) {
this.currentID[ 'low' ] += 1;
id = this.currentID[ 'low' ];
}
this.notifications[ id ] = { 'message': message, 'showDuration': showDuration, 'messageType': messageType, 'priority': priority };
this.queue.push( id );
console.log( 'scheduled notification: ' + id + ' (' + message + ')' );
return id;
},
cancelNotification ( id ) {
/*
This method deletes a notification and, in case the notification is being displayed, hides it.
*/
delete notifications[ id ];
delete this.queue[ this.queue.findIndex( id ) ];
if ( this.currentlyDisplayedNotificationID == id ) {
this.handleNotifications();
}
},
handleNotifications () {
/*
This methods should NOT be called in any other component than this one!
*/
this.displayTimeCurrentNotification = 0;
this.queue.sort();
if ( this.queue.length > 0 ) {
this.message = this.notifications[ this.queue[ 0 ] ][ 'message' ];
this.messageType = this.notifications[ this.queue[ 0 ] ][ 'messageType' ];
this.priority = this.notifications[ this.queue[ 0 ] ][ 'priority' ];
this.notificationDisplayTime = this.notifications[ this.queue[ 0 ] ][ 'showDuration' ];
this.queue.reverse();
this.queue.pop();
} else {
this.messageType = 'hide';
}
}
},
created () {
this.notificationScheduler = setInterval( () => {
if ( this.displayTimeCurrentNotification >= this.notificationDisplayTime ) {
this.handleNotifications();
} else {
this.displayTimeCurrentNotification += 0.5;
}
}, 500 );
},
unmounted ( ) {
clearInterval( this.notificationScheduler );
}
}
</script>
<style scoped>
.message-box {
#popup-backdrop {
position: fixed;
left: 0.5%;
z-index: 5;
top: 3%;
color: white;
height: 10vh;
width: 15vw;
opacity: 1;
transition: all 0.5s;
top: 0;
left: 0;
z-index: 10;
width: 100vw;
height: 100vh;
background-color: var( --overlay-color );
display: none;
}
.message-container {
.shown {
display: block;
}
.popup-container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
flex-direction: column;
}
.types {
color: white;
border-radius: 100%;
margin-right: auto;
margin-left: 5%;
font-size: 200%;
.popup {
border: none;
border-radius: 20px;
background-color: var( --popup-color );
}
.message {
margin-right: 5%;
.small {
width: 40%;
height: 40%;
}
.normal {
width: 50%;
height: 50%;
}
.big {
width: 60%;
height: 60%;
}
.bigger {
width: 70%;
height: 70%;
}
.huge {
width: 80%;
height: 80%;
}
</style>

View File

@@ -80,5 +80,14 @@ export default {
adminAuthRequired: true,
}
},
{
path: 'locations/view',
name: 'locationDetails',
component: () => import( '../views/admin/locations/LocationEditView.vue' ),
meta: {
title: 'Admin - libreevent',
adminAuthRequired: true,
}
},
]
}

View File

@@ -11,7 +11,22 @@
<div>
<h2>Locations</h2>
<p>Here you can change everything regarding event locations. All locations can have a seating plan.</p>
<div class="bigButtons"></div>
<div class="location-app" v-if="Object.keys( locations ).length">
<ul>
<li v-for="location in locations">
<router-link to="/admin/locations/view" class="location" @click="selectLocation( location.locationID );">
<div class="location-name">
<h3>{{ location.name }}</h3>
<p v-if="location['seatplan-enabled']">This location has a seatplan.</p>
<p v-else>This location has NO seatplan.</p>
</div>
</router-link>
</li>
</ul>
</div>
<div v-else class="no-location-hint">
No locations configured, please <b @click="addLocation();" style="cursor: pointer;">add</b> one
</div>
</div>
</template>
@@ -19,13 +34,57 @@
export default {
data () {
return {
formData: {}
locations: { 'test':{ 'name':'TestLocation', 'locationID':'test', 'seatplan-enabled': true, 'seatplan': {} } },
}
},
methods: {
setup () {
selectLocation ( locationID ) {
sessionStorage.setItem( 'locationID', locationID );
},
addLocation () {
}
},
}
};
</script>
<style scoped>
.location-app {
text-align: justify;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
ul {
list-style: none;
width: 80%;
}
.location {
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
color: var( --primary-color );
border-color: var( --primary-color );
border-width: 1px;
height: fit-content;
border-style: solid;
padding: 10px;
transition: 0.4s;
}
.location:hover {
background-color: var( --hover-color );
transition: 0.4s;
}
.location-name {
margin-right: auto;
max-width: 35%;
}
</style>

View File

@@ -9,7 +9,7 @@
<template>
<div>
<h2>Seatplan Editor</h2>
<h2>Seat Plan Editor</h2>
<window />
</div>
</template>

View File

@@ -0,0 +1,84 @@
<!--
* libreevent - TicketsDetailsView.vue
*
* Created by Janis Hutz 05/14/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
-->
<template>
<div class="details">
<h2>{{ event.name }}</h2>
<div class="category-wrapper">
<table class="category">
<tr>
<td>Location name</td>
<td>
<input type="text" v-model="event.name">
</td>
</tr>
<tr>
<td>Seat plan editor</td>
<router-link to="/admin/seatplan">Edit seat plan</router-link>
</tr>
</table>
</div>
<popups ref="popup"></popups>
<notifications ref="notification" location="topright"></notifications>
</div>
</template>
<style scoped>
.details {
flex-grow: 1;
}
.ticket-settings {
width: 100%;
}
.category-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
flex-direction: column;
}
.category {
width: 50%;
text-align: justify;
}
.category-details {
margin-left: 7%;;
}
</style>
<script>
import settings from '@/components/settings/settings.vue';
import notifications from '@/components/notifications/notifications.vue';
import popups from '@/components/notifications/popups.vue';
export default {
name: 'TicketsDetailsView',
components: {
settings,
notifications,
popups,
},
created () {
if ( !sessionStorage.getItem( 'selectedTicket' ) ) {
this.$router.push( '/admin/events' );
}
this.eventID = sessionStorage.getItem( 'selectedTicket' );
},
data() {
return {
event: { 'name': 'TestEvent', 'description': 'This is a description for the TestEvent to test multiline support and proper positioning of the Fields', 'freeSeats': 2, 'maxSeats': 2, 'date':'TestDate', 'startingPrice':15, 'location': 'TestLocation', 'eventID': 'test', 'currency': 'CHF', 'logo': 'logo.png', 'categories': { '1': { 'price': { '1': { 'price':25, 'name':'Child (0-15.99 years)'}, '2': { 'price':35, 'name':'Adult'} }, 'bg': 'black', 'fg': 'white', 'name': 'Category 1' }, '2': { 'price': { '1': { 'price':25, 'name':'Child (0-15.99 years)' }, '2': { 'price':35, 'name':'Adult'} }, 'bg': 'green', 'fg': 'white', 'name': 'Category 2' } } },
}
}
};
</script>