mirror of
https://github.com/janishutz/libreevent.git
synced 2025-11-25 21:34:24 +00:00
popups, fixes, location editing
This commit is contained in:
@@ -2,3 +2,5 @@
|
|||||||
- Load: email, settings, change pw, change mail, see all tickets
|
- Load: email, settings, change pw, change mail, see all tickets
|
||||||
|
|
||||||
- set page title based on settings
|
- set page title based on settings
|
||||||
|
|
||||||
|
- make pricing groups changeable in UI (event categories)
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
--accent-color: #42b983;
|
--accent-color: #42b983;
|
||||||
--hover-color: rgb(165, 165, 165);
|
--hover-color: rgb(165, 165, 165);
|
||||||
--accent-background-hover: #4380a8;
|
--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);
|
--inactive-color: rgb(100, 100, 100);
|
||||||
--highlight-backdrop: rgb(143, 134, 192);
|
--highlight-backdrop: rgb(143, 134, 192);
|
||||||
--PI: 3.14159265358979;
|
--PI: 3.14159265358979;
|
||||||
|
|||||||
@@ -1,131 +1,100 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="notifications" @click="handleNotifications();">
|
<div id="popup-backdrop" :class="status">
|
||||||
<div class="message-box" :class="messageType">
|
<div class="popup-container">
|
||||||
|
<div class="popup" :class="size">
|
||||||
|
<span class="material-symbols-outlined" @click="closePopup();">close</span>
|
||||||
<div class="message-container">
|
<div class="message-container">
|
||||||
<span class="material-symbols-outlined types" v-if="messageType == 'ok'" style="background-color: green;">done</span>
|
{{ message }}
|
||||||
<span class="material-symbols-outlined types" v-else-if="messageType == 'error'" style="background-color: red;">close</span>
|
</div>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Options to be passed in: HTML, Settings (for settings component), strings, numbers, confirm, radio, dropdowns, selection -->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'notifications',
|
name: 'popups',
|
||||||
|
prop: {
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
'default': 'normal',
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: Object,
|
||||||
|
'default': '{}',
|
||||||
|
},
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
notifications: {},
|
status: 'hidden',
|
||||||
queue: [],
|
|
||||||
message: '',
|
|
||||||
messageType: 'hide',
|
|
||||||
notificationDisplayTime: 1,
|
|
||||||
notificationPriority: 'normal',
|
|
||||||
currentlyDisplayedNotificationID: 0,
|
|
||||||
currentID: { 'critical': 0, 'medium': 1000, 'low': 100000 },
|
|
||||||
displayTimeCurrentNotification: 0,
|
|
||||||
notificationScheduler: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
createNotification( message, showDuration, messageType, priority ) {
|
closePopup() {
|
||||||
/*
|
this.shown = 'hidden'
|
||||||
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
|
openPopup () {
|
||||||
one at a time and prioritize messages with higher priority. Use vue refs to access these methods.
|
|
||||||
*/
|
|
||||||
let id = 0;
|
|
||||||
|
|
||||||
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>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.message-box {
|
#popup-backdrop {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0.5%;
|
top: 0;
|
||||||
z-index: 5;
|
left: 0;
|
||||||
top: 3%;
|
z-index: 10;
|
||||||
color: white;
|
width: 100vw;
|
||||||
height: 10vh;
|
height: 100vh;
|
||||||
width: 15vw;
|
background-color: var( --overlay-color );
|
||||||
opacity: 1;
|
display: none;
|
||||||
transition: all 0.5s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-container {
|
.shown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
flex-direction: column;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.types {
|
.popup {
|
||||||
color: white;
|
border: none;
|
||||||
border-radius: 100%;
|
border-radius: 20px;
|
||||||
margin-right: auto;
|
background-color: var( --popup-color );
|
||||||
margin-left: 5%;
|
|
||||||
font-size: 200%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.small {
|
||||||
margin-right: 5%;
|
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>
|
</style>
|
||||||
@@ -80,5 +80,14 @@ export default {
|
|||||||
adminAuthRequired: true,
|
adminAuthRequired: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'locations/view',
|
||||||
|
name: 'locationDetails',
|
||||||
|
component: () => import( '../views/admin/locations/LocationEditView.vue' ),
|
||||||
|
meta: {
|
||||||
|
title: 'Admin - libreevent',
|
||||||
|
adminAuthRequired: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,22 @@
|
|||||||
<div>
|
<div>
|
||||||
<h2>Locations</h2>
|
<h2>Locations</h2>
|
||||||
<p>Here you can change everything regarding event locations. All locations can have a seating plan.</p>
|
<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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -19,13 +34,57 @@
|
|||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
formData: {}
|
locations: { 'test':{ 'name':'TestLocation', 'locationID':'test', 'seatplan-enabled': true, 'seatplan': {} } },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setup () {
|
selectLocation ( locationID ) {
|
||||||
|
sessionStorage.setItem( 'locationID', locationID );
|
||||||
|
},
|
||||||
|
addLocation () {
|
||||||
|
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</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>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h2>Seatplan Editor</h2>
|
<h2>Seat Plan Editor</h2>
|
||||||
<window />
|
<window />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
84
src/webapp/src/views/admin/locations/LocationEditView.vue
Normal file
84
src/webapp/src/views/admin/locations/LocationEditView.vue
Normal 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>
|
||||||
|
|
||||||
Reference in New Issue
Block a user