notifications, settings, editor, event view fixes

This commit is contained in:
2023-06-22 19:34:29 +02:00
parent dee06e4eef
commit 644891c5af
4 changed files with 121 additions and 30 deletions

View File

@@ -7,6 +7,7 @@
<span class="material-symbols-outlined types" v-else-if="messageType == 'error'" style="background-color: red;">close</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 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> <span class="material-symbols-outlined types" v-else-if="messageType == 'info'" style="background-color: lightblue;">info</span>
<span class="material-symbols-outlined types" v-else-if="messageType == 'warning'" style="background-color: orangered;">warning</span>
<p class="message">{{ message }}</p> <p class="message">{{ message }}</p>
</div> </div>
</div> </div>
@@ -55,7 +56,7 @@
this.currentID[ 'low' ] += 1; this.currentID[ 'low' ] += 1;
id = this.currentID[ 'low' ]; id = this.currentID[ 'low' ];
} }
this.notifications[ id ] = { 'message': message, 'showDuration': showDuration, 'messageType': messageType, 'priority': priority }; this.notifications[ id ] = { 'message': message, 'showDuration': showDuration, 'messageType': messageType, 'priority': priority, 'id': id };
this.queue.push( id ); this.queue.push( id );
console.log( 'scheduled notification: ' + id + ' (' + message + ')' ); console.log( 'scheduled notification: ' + id + ' (' + message + ')' );
if ( this.displayTimeCurrentNotification >= this.notificationDisplayTime ) { if ( this.displayTimeCurrentNotification >= this.notificationDisplayTime ) {
@@ -67,8 +68,12 @@
/* /*
This method deletes a notification and, in case the notification is being displayed, hides it. This method deletes a notification and, in case the notification is being displayed, hides it.
*/ */
delete notifications[ id ]; try {
delete this.queue[ this.queue.findIndex( id ) ]; delete notifications[ id ];
delete this.queue[ this.queue.findIndex( id ) ];
} catch ( error ) {
console.log( 'notification to be deleted is nonexistent or currently being displayed' );
}
if ( this.currentlyDisplayedNotificationID == id ) { if ( this.currentlyDisplayedNotificationID == id ) {
this.handleNotifications(); this.handleNotifications();
} }
@@ -85,6 +90,7 @@
this.message = this.notifications[ this.queue[ 0 ] ][ 'message' ]; this.message = this.notifications[ this.queue[ 0 ] ][ 'message' ];
this.messageType = this.notifications[ this.queue[ 0 ] ][ 'messageType' ]; this.messageType = this.notifications[ this.queue[ 0 ] ][ 'messageType' ];
this.priority = this.notifications[ this.queue[ 0 ] ][ 'priority' ]; this.priority = this.notifications[ this.queue[ 0 ] ][ 'priority' ];
this.currentlyDisplayedNotificationID = this.notifications[ this.queue[ 0 ] ][ 'id' ];
this.notificationDisplayTime = this.notifications[ this.queue[ 0 ] ][ 'showDuration' ]; this.notificationDisplayTime = this.notifications[ this.queue[ 0 ] ][ 'showDuration' ];
this.queue.reverse(); this.queue.reverse();
this.queue.pop(); this.queue.pop();
@@ -111,7 +117,7 @@
<style scoped> <style scoped>
.message-box { .message-box {
position: fixed; position: fixed;
z-index: 5; z-index: 10;
color: white; color: white;
height: 10vh; height: 10vh;
width: 15vw; width: 15vw;
@@ -119,23 +125,23 @@
} }
.topleft { .topleft {
top: 3%; top: 3vh;
left: 0.5%; left: 0.5vw;
} }
.topright { .topright {
top: 3%; top: 3vh;
right: 0.5%; right: 0.5vw;
} }
.bottomright { .bottomright {
bottom: 3%; bottom: 3vh;
right: 0.5%; right: 0.5vw;
} }
.bottomleft { .bottomleft {
top: 3%; top: 3vh;
right: 0.5%; right: 0.5vw;
} }
.message-container { .message-container {
@@ -154,11 +160,13 @@
border-radius: 100%; border-radius: 100%;
margin-right: auto; margin-right: auto;
margin-left: 5%; margin-left: 5%;
padding: 1.5%;
font-size: 200%; font-size: 200%;
} }
.message { .message {
margin-right: 5%; margin-right: 5%;
text-align: end;
} }
.ok { .ok {
@@ -173,6 +181,10 @@
background-color: rgb(44, 112, 151); background-color: rgb(44, 112, 151);
} }
.warning {
background-color: orange;
}
.hide { .hide {
opacity: 0; opacity: 0;
} }

View File

@@ -16,8 +16,7 @@
<div class="info-container" @mouseenter="showInfo( setting.id )" @mouseleave="hideInfo( setting.id )"> <div class="info-container" @mouseenter="showInfo( setting.id )" @mouseleave="hideInfo( setting.id )">
<span class="material-symbols-outlined info-icon">info</span> <span class="material-symbols-outlined info-icon">info</span>
<div class="info-box" :id="setting.id"> <div class="info-box" :id="setting.id">
<div class="info-box-container"> <div class="info-box-container" v-html="setting.tooltip">
{{ setting.tooltip }}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -11,17 +11,22 @@
<div class="details"> <div class="details">
<h2>{{ event.name }}</h2> <h2>{{ event.name }}</h2>
<div class="general-settings"> <div class="general-settings">
<textarea v-model="event.description" class="big-text"></textarea><br> <p>Event Description</p>
<textarea v-model="event.description" class="big-text" cols="70" rows="3" placeholder="Event description..."></textarea>
<p>Event location</p>
<select v-model="event.location" class="small-text"> <select v-model="event.location" class="small-text">
<option value="TestLocation">TestLocation</option> <option value="TestLocation">TestLocation</option>
</select><br> </select>
<p>Event date</p>
<input v-model="event.date" class="small-text" type="date"><br> <input v-model="event.date" class="small-text" type="date"><br>
<p>Ticket editor</p>
<router-link to="/admin/ticketEditor">Edit ticket layout</router-link> <router-link to="/admin/ticketEditor">Edit ticket layout</router-link>
</div> </div>
<div class="ticket-settings"> <div class="ticket-settings">
<h3>Ticket Settings</h3> <h3>Ticket Settings</h3>
<p>The foreground and background colours of the seats are used to show the customer to which category the seats belong.</p>
<table class="category" v-for="category in event.categories"> <table class="category" v-for="category in event.categories">
{{ category.name }}: {{ category.name }}
<tr v-for="price in category.price"> <tr v-for="price in category.price">
<td> <td>
{{ price.name }}: {{ price.name }}:
@@ -45,10 +50,14 @@
</table> </table>
</div> </div>
<div class="special-settings"> <div class="special-settings">
<h3>Special Settings</h3> <h3>General Settings</h3>
<p>Currency codes used must be valid ISO 4217 codes. Read more on <a href="https://libreevent.janishutz.com/docs/admin-panel/events#currency">this page</a> of the documentation <!-- https://en.wikipedia.org/wiki/ISO_4217#List_of_ISO_4217_currency_codes"--></p>
<settings v-model:settings="specialSettings"></settings> <settings v-model:settings="specialSettings"></settings>
</div> </div>
<notifications ref="notification" location="'topright'"></notifications> <div>
<p>Please read into the documentation of this section if you want to use the requirements. It requires specific syntax to work. See <a href="https://libreevent.janishutz.com/docs/admin-panel/events#special-requirements">here</a> for more information</p>
</div>
<notifications ref="notification" location="topright"></notifications>
</div> </div>
</template> </template>
@@ -86,6 +95,13 @@
return { 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' } } }, 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' } } },
specialSettings: { specialSettings: {
'currency': {
'display': 'Currency',
'id': 'currency',
'tooltip':'Specify a currency in which the prices are displayed to the customer. Defaults to USD. Please use valid currency codes.',
'value': 'USD',
'type': 'text',
},
'guest-purchase': { 'guest-purchase': {
'display': 'Enable guest purchase', 'display': 'Enable guest purchase',
'id': 'guest-purchase', 'id': 'guest-purchase',
@@ -137,15 +153,11 @@
} }
}, },
'requiredParameterValue': { 'requiredParameterValue': {
'display': 'Maximum ticket count per account', 'display': 'Special requirements values ',
'id': 'requiredParameterValue', 'id': 'requiredParameterValue',
'tooltip':'With this setting you can control how many tickets a person can buy. Defaults to 0, which means do not limit.', 'tooltip':'Put a filter here, corresponding to your selection above. Please read the documentation on our website. See link below!',
'value': 0, 'value': '',
'type': 'number', 'type': 'text',
'restrictions': {
'min': 0,
'max': 100,
}
}, },
} }
} }

View File

@@ -1,14 +1,23 @@
<template> <template>
<div id="ticketEditor"> <div id="ticketEditor">
<h1>Ticket Editor</h1> <h1>Ticket Editor</h1>
<router-link to="/admin/events/view">Back to event settings</router-link> <div class="toolbar">
<button @click="saveTemplate()">Save Template</button> <router-link to="/admin/events/view" class="toolbar-item" title="Back to event settings">Back</router-link>
<form class="toolbar-item">
<input type="file" accept="application/pdf" id="pdfTemplate" class="toolbar-item">
</form>
<button @click="loadPDF();" class="toolbar-item">Load file</button>
<button @click="saveTemplate()" class="toolbar-item" title="Save your ticket">Save Template</button>
<button @click="testNotifications();" class="toolbar-item">Test notifications</button>
</div>
<div id="editor">Loading editor...</div> <div id="editor">Loading editor...</div>
<notifications ref="notification" location="topleft"></notifications>
</div> </div>
</template> </template>
<script> <script>
import { Designer, BLANK_PDF } from '@pdfme/ui'; import { Designer, BLANK_PDF } from '@pdfme/ui';
import notifications from '@/components/notifications/notifications.vue';
export default { export default {
name: 'ticketEditor', name: 'ticketEditor',
@@ -17,14 +26,57 @@
designer: null, designer: null,
} }
}, },
components: {
notifications
},
methods: { methods: {
saveTemplate() { saveTemplate() {
// Save to server instead
this.$refs.notification.createNotification( 'Saving...', 5, 'progress', 'normal' );
this.$refs.notification.createNotification( 'Saved successfully', 5, 'ok', 'normal' );
console.log( this.designer.getTemplate() ); console.log( this.designer.getTemplate() );
},
testNotifications () {
this.$refs.notification.createNotification( 'Warning', 10, 'warning', 'normal' );
this.$refs.notification.createNotification( 'Error', 10, 'error', 'normal' );
this.$refs.notification.createNotification( 'Info', 10, 'info', 'normal' );
this.$refs.notification.createNotification( 'Ok', 10, 'ok', 'normal' );
this.$refs.notification.createNotification( 'Progress', 10, 'progress', 'normal' );
},
loadPDF () {
let files = document.getElementById( 'pdfTemplate' ).files;
if ( files.length ) {
let pdfLoading = this.$refs.notification.createNotification( 'Loading pdf...', 5, 'progress', 'normal' );
let pdf = files[ 0 ];
if ( pdf.name.substring( pdf.name.length - 4 ) === '.pdf' ) {
let fileReader = new FileReader();
let base64;
let self = this;
// Onload of file read the file content
// https://stackoverflow.com/questions/13538832/convert-pdf-to-a-base64-encoded-string-in-javascript?rq=4
fileReader.onload = function( fileLoadedEvent ) {
base64 = fileLoadedEvent.target.result;
let oldTemplate = self.designer.getTemplate();
oldTemplate[ 'basePdf' ] = base64;
self.designer.updateTemplate( oldTemplate );
self.$refs.notification.cancelNotification( pdfLoading );
self.$refs.notification.createNotification( 'Loaded pdf successfully', 5, 'ok', 'normal' );
};
fileReader.readAsDataURL( pdf );
} else {
this.$refs.notification.createNotification( 'Cannot load pdf: Not a pdf!', 5, 'error', 'normal' );
}
} else {
this.$refs.notification.createNotification( 'Cannot load pdf: No file selected', 5, 'error', 'normal' );
}
} }
}, },
created() { created() {
setTimeout( () => { setTimeout( () => {
const domContainer = document.getElementById( 'editor' ); const domContainer = document.getElementById( 'editor' );
// TODO: Load from server if available
const template = { const template = {
basePdf: BLANK_PDF, basePdf: BLANK_PDF,
schemas: [ schemas: [
@@ -61,8 +113,24 @@
nav { nav {
display: none; display: none;
} }
</style>
<style scoped>
#editor { #editor {
height: 90vh; height: 85vh;
}
.toolbar {
height: 5vh;
display: flex;
width: 100%;
justify-content: center;
align-items: center;
margin-top: 0;
}
.toolbar-item {
margin: 0;
margin-left: 0.5%;
} }
</style> </style>