From ed38edd880410076a2cd76f716fc425e2044ae54 Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Mon, 7 Aug 2023 12:24:52 +0200 Subject: [PATCH] ticket gen working + various changes --- .gitignore | 9 +- assets/basicTicketTemplate/README.md | 3 + .../basicTicketTemplate.pdf | Bin 0 -> 15520 bytes .../basicTicketTemplate.tex | 25 ++++ src/server/admin/adminRoutes.js | 10 +- src/server/admin/api/getHandler.js | 8 +- src/server/admin/pwdmanager.js | 2 +- src/server/app.js | 2 +- src/server/backend/api/getHandler.js | 2 +- src/server/backend/api/postHandler.js | 2 + src/server/backend/db/data/tickets.json | 2 +- src/server/backend/db/db.js | 10 ++ src/server/backend/db/mysqldb.js | 8 +- .../plugins/payments/stripe/stripeRoutes.js | 20 ++- src/server/backend/tickets/ticketGenerator.js | 23 ++-- src/server/backend/userRoutes.js | 5 +- src/server/config/settings.config.json | 2 +- src/webapp/main/notes.md | 10 +- .../src/components/seatplan/editor/window.vue | 2 +- .../seatplan/userApp/userWindow.vue | 29 ++--- .../main/src/components/sideCartView.vue | 7 +- .../main/src/views/admin/SettingsView.vue | 6 +- .../views/admin/events/TicketEditorView.vue | 116 +++++++++++------- src/webapp/main/src/views/user/SignupView.vue | 6 + 24 files changed, 211 insertions(+), 98 deletions(-) create mode 100644 assets/basicTicketTemplate/README.md create mode 100644 assets/basicTicketTemplate/basicTicketTemplate.pdf create mode 100644 assets/basicTicketTemplate/basicTicketTemplate.tex diff --git a/.gitignore b/.gitignore index e371d95..b06f450 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,11 @@ node_modules # ignore dist folder (this repo only contains source code!) /dist -*.secret.json \ No newline at end of file +*.secret.json + +# ignore all latex files except .tex +*.aux +*.fls +*.synctex.gz +*.fdb_latexmk +._wordcount_selection.tex \ No newline at end of file diff --git a/assets/basicTicketTemplate/README.md b/assets/basicTicketTemplate/README.md new file mode 100644 index 0000000..21a4e9c --- /dev/null +++ b/assets/basicTicketTemplate/README.md @@ -0,0 +1,3 @@ +# Ticket Template + +This template can be used by libreevent if you do not edit the template. It is entirely copyleft and you can change it to your liking. The LaTex document is included with libreevent. \ No newline at end of file diff --git a/assets/basicTicketTemplate/basicTicketTemplate.pdf b/assets/basicTicketTemplate/basicTicketTemplate.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f8f353271a35a3a5adf7f822384cc91ea441014d GIT binary patch literal 15520 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 { if ( request.body.mail && request.body.password ) { pwdmanager.checkpassword( request.body.mail, request.body.password ).then( data => { request.session.username = request.body.mail; - if ( data ) { + if ( data.status ) { request.session.username = request.body.mail; - // TODO: Check if user has 2fa enabled - if ( settings.twoFA === 'standard' ) { + if ( data.twoFA === 'simple' ) { ( async () => { let tok = twoFA.registerStandardAuthentication()[ 'token' ]; let ipRetrieved = request.headers[ 'x-forwarded-for' ]; @@ -40,7 +39,7 @@ module.exports = ( app, settings ) => { request.session.token = tok; response.send( { 'status': '2fa' } ); } )(); - } else if ( settings.twoFA === 'enhanced' ) { + } else if ( data.twoFA === 'enhanced' ) { ( async () => { let res = twoFA.registerEnhancedAuthentication(); let ipRetrieved = request.headers[ 'x-forwarded-for' ]; @@ -50,7 +49,7 @@ module.exports = ( app, settings ) => { response.send( { 'status': '2fa+', 'code': res.code } ); } )(); } else { - request.session.loggedInUser = true; + request.session.loggedInAdmin = true; response.send( { 'status': 'ok' } ); } } else { @@ -63,7 +62,6 @@ module.exports = ( app, settings ) => { } ); app.get( '/admin/2fa', ( request, response ) => { - // TODO: Add multi language let tokType = twoFA.verifySimple( request.query.token ); if ( tokType === 'standard' ) { request.session.loggedInAdmin = true; diff --git a/src/server/admin/api/getHandler.js b/src/server/admin/api/getHandler.js index 9e8c648..8a2be51 100644 --- a/src/server/admin/api/getHandler.js +++ b/src/server/admin/api/getHandler.js @@ -42,7 +42,13 @@ class GETHandler { } ); } else if ( call === 'getLocations' ) { db.getJSONData( 'locations' ).then( data => { - resolve( data ); + resolve( data ?? {} ); + } ).catch( error => { + reject( { 'code': 500, 'error': error } ); + } ); + } else if ( call === 'getTicketTemplate' ) { + db.getJSONDataSimple( 'tickets', query.ticket ).then( data => { + resolve( data ?? {} ); } ).catch( error => { reject( { 'code': 500, 'error': error } ); } ); diff --git a/src/server/admin/pwdmanager.js b/src/server/admin/pwdmanager.js index cf6b816..10cbf61 100644 --- a/src/server/admin/pwdmanager.js +++ b/src/server/admin/pwdmanager.js @@ -24,7 +24,7 @@ module.exports.checkpassword = ( username, password ) => { if ( data ) { if ( data[ 0 ] ) { bcrypt.compare( password, data[ 0 ].pass ).then( res => { - resolve( res ); + resolve( { 'status': res, 'twoFA': data[ 0 ].two_fa } ); } ); } else { resolve( false ); diff --git a/src/server/app.js b/src/server/app.js index 78cca10..95155f7 100644 --- a/src/server/app.js +++ b/src/server/app.js @@ -101,6 +101,6 @@ app.use( ( request, response ) => { console.log( '\n\n[ Server ] loading complete!\n\n' ); -const PORT = process.env.PORT || 8081; +const PORT = process.env.PORT || 8080; console.log( '[ Server ] listening on port ' + PORT ); http.createServer( app ).listen( PORT ); \ No newline at end of file diff --git a/src/server/backend/api/getHandler.js b/src/server/backend/api/getHandler.js index bd7954c..55bf42b 100644 --- a/src/server/backend/api/getHandler.js +++ b/src/server/backend/api/getHandler.js @@ -30,7 +30,7 @@ class GETHandler { if ( query.event ) { db.getJSONDataSimple( 'booked', query.event ).then( data => { db.getDataSimple( 'temp', 'user_id', session.id ).then( dat => { - resolve( { 'booked': data ? data.booked : {}, 'user': dat[ 0 ] ? JSON.parse( dat[ 0 ].data )[ query.event ] ?? {} : {} } ); + resolve( { 'booked': data ?? {}, 'user': dat[ 0 ] ? JSON.parse( dat[ 0 ].data )[ query.event ] ?? {} : {} } ); } ); } ).catch( error => { reject( { 'code': 500, 'message': error } ); diff --git a/src/server/backend/api/postHandler.js b/src/server/backend/api/postHandler.js index f9551b1..ca17cab 100644 --- a/src/server/backend/api/postHandler.js +++ b/src/server/backend/api/postHandler.js @@ -39,7 +39,9 @@ class POSTHandler { return; } transmit[ data.eventID ][ data.id ] = data; + // TODO: Prevent seat selection if already taken (also if in booked!) // TODO: Respect max ticket count per user + // TODO: maybe move to per event setting let totalUserTickets = 0; for ( let event in transmit ) { for ( let ticket in transmit[ event ] ) { diff --git a/src/server/backend/db/data/tickets.json b/src/server/backend/db/data/tickets.json index 9e26dfe..eb27a54 100644 --- a/src/server/backend/db/data/tickets.json +++ b/src/server/backend/db/data/tickets.json @@ -1 +1 @@ -{} \ No newline at end of file +{"test2":{"basePdf":"data:application/pdf;base64,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LTEuNDAuMjUgKFRlWCBMaXZlIDIwMjMvQXJjaCBMaW51eCkga3BhdGhzZWEgdmVyc2lvbiA2LjMuNSkKPj4KZW5kb2JqCjggMCBvYmoKPDwKL1R5cGUgL09ialN0bQovTiAxMAovRmlyc3QgNjIKL0xlbmd0aCA2MzEgICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42o1UTW/bMAy9+1fwuGGoKVm2bANBsCZd2q3rUCTZ1iHIQXU0x1hqB7ZStP9+pGw0aXfZwYL0+Pj4YUoJCIgh1yAhEvRBpCQoWgkREKUxyAh0qiCFXOaQE6olSIKlUMFoFODyeW8Bb01pA5w2tbO160CT7DzAue2aQ1vYjmJ44MZuKjNpnmAlCEjyJIxSDVkswyxfB6TSkjtFYfJ4zPpAorumXexNYSkxMnAw52xbU7b++OnJXS6ccZaKYCDAGeUBoxHgTHHmDJIa3rZNsbAOViRxMQNc2icH6z4Q4L78/bEwMhTeszDA2/HYW3uK5+zb8h5WLznghX2sCju/nKw5xkopFVL/0jTMIBHiv7/e43RN/RqnURgNa4+kiYBUZBQljTyqVZiDzkSoQScRM7I4TD1PaRlKSCQzem8dJfQn9WAfMO87qCvNHknCSK/PPPqkiF7C06clSx8Lfbs7aYEXi+M4jF/tleD9kdF7DGh01Mh8S3vOkd0zVC6pFJV7vSyjMk+s65MB5ZG4sF3RVnvXtP2IfDMPZPlydTe9vP4wvZlLQfjOlDSuPWHiR/UsFnAW+Q6InGunST3vCp5UnRNzavZXtiq3dMxUgByFbWeSjZ+d2VXFeV3uLJD8wtmHH+QW4N3gEytJElvT8mS+wyX+QoP3WKDFErfP+62tscI/uMMHrLHBprbYYocOD/j4vs9zVpG6lCfX5qRqCnq4d/7IIEWbmM76K/K29lc94pvvL+2sajvHGUKcBPjVDAcpswB/Vhu37fit8NRl872uimZD2ah/s+FHouNX4kCxKY/ratPBKmHi+jVzaqhtTRn0LscH4S82riOxCmVuZHN0cmVhbQplbmRvYmoKMTYgMCBvYmoKPDwKL1R5cGUgL1hSZWYKL0luZGV4IFswIDE3XQovU2l6ZSAxNwovVyBbMSAyIDFdCi9Sb290IDE0IDAgUgovSW5mbyAxNSAwIFIKL0lEIFs8QThGQURBNEJENDA3NjdFMzY5MDY3MDI0NjNBQTI5N0E+IDxBOEZBREE0QkQ0MDc2N0UzNjkwNjcwMjQ2M0FBMjk3QT5dCi9MZW5ndGggNjAgICAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNpjYGD4z8TAwQTEzEDMAsSMQMzAyMDPAKTZGS3aQDQHELMyMmmC2GyMJs4gmpPRvIyB0TqLAQCCZgRYCmVuZHN0cmVhbQplbmRvYmoKc3RhcnR4cmVmCjE1MjEwCiUlRU9GCg==","schemas":[{"locationAndTime":{"type":"text","position":{"x":90,"y":70},"width":85,"height":10,"fontName":"Roboto"},"eventName":{"type":"text","position":{"x":89.7,"y":30},"width":85,"height":15,"alignment":"left","fontSize":18,"characterSpacing":0,"lineHeight":1,"fontName":"Roboto"},"ticketName":{"type":"text","position":{"x":90,"y":55},"width":85,"height":10,"fontName":"Roboto","alignment":"left"},"ticketQRCode":{"type":"qrcode","position":{"x":25,"y":30.05},"width":50,"height":50}}],"columns":["locationAndTime","eventName","ticketName","ticketQRCode"],"sampledata":[{"locationAndTime":"Time and date of event","eventName":"Your Event name goes here","ticketName":"Ticket details go here (Ticket name)","ticketQRCode":"QR-Code for entry control will appear here"}]}} \ No newline at end of file diff --git a/src/server/backend/db/db.js b/src/server/backend/db/db.js index 233926d..11307ac 100644 --- a/src/server/backend/db/db.js +++ b/src/server/backend/db/db.js @@ -58,6 +58,16 @@ module.exports.writeDataSimple = ( db, column, searchQuery, data ) => { } ); }; +module.exports.deleteDataSimple = ( db, column, searchQuery ) => { + return new Promise( ( resolve, reject ) => { + dbh.query( { 'command': 'deleteData', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( dat => { + resolve( dat ); + } ).catch( error => { + reject( error ); + } ); + } ); +}; + module.exports.checkDataAvailability = ( db, column, searchQuery ) => { return new Promise( ( resolve, reject ) => { dbh.query( { 'command': 'checkDataAvailability', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( res => { diff --git a/src/server/backend/db/mysqldb.js b/src/server/backend/db/mysqldb.js index 4fad8a4..6ddce97 100644 --- a/src/server/backend/db/mysqldb.js +++ b/src/server/backend/db/mysqldb.js @@ -55,7 +55,7 @@ class SQLDB { if ( error ) throw error; if ( results[ 0 ][ '@@default_storage_engine' ] !== 'InnoDB' ) return 'DB HAS TO USE InnoDB!'; } ); - this.sqlConnection.query( 'CREATE TABLE libreevent_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, pass TEXT, name TEXT, first_name TEXT, two_fa TINYTEXT, user_data VARCHAR( 60000 ), mail_confirmed TINYTEXT, marketing_ok TINYTEXT, PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', ( error ) => { + this.sqlConnection.query( 'CREATE TABLE libreevent_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, pass TEXT, name TEXT, first_name TEXT, two_fa TINYTEXT, user_data VARCHAR( 60000 ), mail_confirmed TINYTEXT, marketing TINYTEXT, PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', ( error ) => { if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error; this.sqlConnection.query( 'CREATE TABLE libreevent_orders ( order_id INT ( 10 ) NOT NULL AUTO_INCREMENT, order_name TINYTEXT, account_id INT ( 10 ) NOT NULL, tickets VARCHAR( 60000 ), processed TINYTEXT, PRIMARY KEY ( order_id ), FOREIGN KEY ( account_id ) REFERENCES libreevent_users( account_id ) ) ENGINE=INNODB;', ( error ) => { if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error; @@ -103,7 +103,11 @@ class SQLDB { - addData: - operation.data (key-value pair with all data as values and column to insert into as key) - + + - deleteData: + - operation.property (the column to search for the value) + - operation.searchQuery (the value to search for [will be sanitised by method]) + - updateData: - operation.newValues (a object with keys being the column and value being the value to be inserted into that column, values are being sanitised by the function) diff --git a/src/server/backend/plugins/payments/stripe/stripeRoutes.js b/src/server/backend/plugins/payments/stripe/stripeRoutes.js index 53ccb01..4d441a1 100644 --- a/src/server/backend/plugins/payments/stripe/stripeRoutes.js +++ b/src/server/backend/plugins/payments/stripe/stripeRoutes.js @@ -40,6 +40,7 @@ module.exports = ( app, settings ) => { if ( dat[ 0 ] ) { db.getJSONData( 'events' ).then( events => { let data = JSON.parse( dat[ 0 ].data ); + console.log( data ); ( async () => { for ( let event in data ) { for ( let item in data[ event ] ) { @@ -116,7 +117,7 @@ module.exports = ( app, settings ) => { } } ); - app.post( '/payments/webhook', bodyParser.raw( { type: 'application/json' } ), ( req, res ) => { + app.post( '/payments/webhook', bodyParser.raw( { type: 'application/json' } ), async ( req, res ) => { const payload = req.body; const sig = req.headers[ 'stripe-signature' ]; @@ -139,9 +140,26 @@ module.exports = ( app, settings ) => { db.getDataSimple( 'users', 'email', sessionReference[ event.data.object.id ][ 'email' ] ).then( user => { if ( user[ 0 ] ) { console.log( sessionReference[ event.data.object.id ][ 'tok' ] ); + const tickets = JSON.parse( dat[ 0 ].data ); db.writeDataSimple( 'orders', 'account_id', user[ 0 ].account_id, { 'account_id': user[ 0 ].account_id, 'tickets': dat[ 0 ].data, 'order_name': sessionReference[ event.data.object.id ][ 'tok' ] } ).then( () => { TicketGenerator.generateTickets( sessionReference[ event.data.object.id ] ); } ); + db.getJSONData( 'booked' ).then( ret => { + let booked = ret ?? {}; + for ( let event in tickets ) { + if ( !booked[ String( event ) ] ) { + booked[ String( event ) ] = {}; + } + for ( let tik in tickets[ event ] ) { + booked[ event ][ tik ] = tickets[ event ][ tik ]; + } + } + db.writeJSONData( 'booked', booked ); + } ); + + db.deleteDataSimple( 'temp', 'user_id', sessionReference[ event.data.object.id ][ 'tok' ] ).catch( error => { + console.error( '[ STRIPE ] ERROR whilst deleting data from DB: ' + error ); + } ); } else { console.log( sessionReference[ event.data.object.id ][ 'email' ] ); console.error( 'user not found' ); diff --git a/src/server/backend/tickets/ticketGenerator.js b/src/server/backend/tickets/ticketGenerator.js index 2948f2f..1f578a1 100644 --- a/src/server/backend/tickets/ticketGenerator.js +++ b/src/server/backend/tickets/ticketGenerator.js @@ -35,7 +35,7 @@ class TicketGenerator { this.runningTickets = {}; } - // TODO: Save to disk in case of crash of server / reboot / whatever + // TODO: Save to disk / DB in case of crash of server / reboot / whatever // and continue processing once back online generateTickets ( order ) { this.ticketQueue[ this.jobId ] = { 'order': order }; @@ -114,15 +114,18 @@ class TicketGenerator { for ( let event in order ) { const template = this.tickets[ event ]; for ( let ticket in order[ event ] ) { - const data = [ { - 'locationAndTime': this.events[ event ][ 'date' ], - 'ticketName': order[ event ][ ticket ][ 'name' ], - 'ticketQRCode': ord[ 0 ].order_name + '_' + order[ event ][ ticket ][ 'id' ], - } ]; - const page = await pdfLib.PDFDocument.load( await pdfme.generate( { 'template': template, 'inputs': data } ) ); - const p = await doc.copyPages( page, page.getPageIndices() ); - pages.push( p ); - p.forEach( ( page ) => doc.addPage( page ) ); + for ( let tik = 0; tik < ( order[ event ][ ticket ].count ?? 1 ); tik++ ) { + const data = [ { + 'eventName': this.events[ event ][ 'name' ], + 'locationAndTime': new Date( this.events[ event ][ 'date' ] ).toLocaleString(), + 'ticketName': order[ event ][ ticket ][ 'name' ], + 'ticketQRCode': ord[ 0 ].order_name + '_' + order[ event ][ ticket ][ 'id' ], + } ]; + const page = await pdfLib.PDFDocument.load( await pdfme.generate( { 'template': template, 'inputs': data } ) ); + const p = await doc.copyPages( page, page.getPageIndices() ); + pages.push( p ); + p.forEach( ( page ) => doc.addPage( page ) ); + } } } const f = path.join( __dirname + '/store/' + ord[ 0 ].order_name + '.pdf' ); diff --git a/src/server/backend/userRoutes.js b/src/server/backend/userRoutes.js index 1c3ae8e..0d12c3b 100644 --- a/src/server/backend/userRoutes.js +++ b/src/server/backend/userRoutes.js @@ -49,8 +49,8 @@ module.exports = ( app, settings ) => { app.post( '/user/login', bodyParser.json(), ( request, response ) => { if ( request.body.mail && request.body.password ) { pwdmanager.checkpassword( request.body.mail, request.body.password ).then( data => { - request.session.username = request.body.mail; if ( data.status ) { + request.session.username = request.body.mail; if ( data.twoFA === 'simple' ) { ( async () => { let tok = twoFA.registerStandardAuthentication()[ 'token' ]; @@ -83,7 +83,6 @@ module.exports = ( app, settings ) => { } ); app.get( '/user/2fa', ( request, response ) => { - // TODO: Add multi language let tokType = twoFA.verifySimple( request.query.token ); if ( tokType === 'standard' ) { request.session.loggedInUser = true; @@ -154,7 +153,7 @@ module.exports = ( app, settings ) => { mailManager.sendMail( request.body.mail, await twoFA.generateSignupEmail( tok, settings.yourDomain, settings.name ), 'Confirm your email', settings.mailSender ); } )(); pwdmanager.hashPassword( request.body.password ).then( hash => { - db.writeDataSimple( 'users', 'email', request.body.mail, { 'email': request.body.mail, 'pass': hash, 'first_name': request.body.firstName, 'name': request.body.name, 'two_fa': 'disabled', 'user_data': JSON.stringify( { 'country': request.body.country } ) } ).then( () => { + db.writeDataSimple( 'users', 'email', request.body.mail, { 'email': request.body.mail, 'pass': hash, 'first_name': request.body.firstName, 'name': request.body.name, 'two_fa': 'disabled', 'user_data': JSON.stringify( { 'country': request.body.country } ), 'marketing': request.body.newsletter ? generator.generateToken( 60 ) : null } ).then( () => { request.session.loggedInUser = true; request.session.username = request.body.mail; response.send( 'ok' ); diff --git a/src/server/config/settings.config.json b/src/server/config/settings.config.json index 7322949..667c4c0 100644 --- a/src/server/config/settings.config.json +++ b/src/server/config/settings.config.json @@ -5,6 +5,6 @@ "db": "mysql", "payments": "stripe", "name": "libreevent", - "yourDomain": "http://localhost:8081", + "yourDomain": "http://localhost:8080", "mailSender": "libreevent " } \ No newline at end of file diff --git a/src/webapp/main/notes.md b/src/webapp/main/notes.md index fa294ac..b4eab6f 100644 --- a/src/webapp/main/notes.md +++ b/src/webapp/main/notes.md @@ -3,11 +3,13 @@ - make pricing groups changeable in UI (event categories) -- create function that parses DB every 15 minutes and clears out junk +- create function that parses DB every 15 minutes and clears out junk --> Also update data in db when user goes to purchase to prevent clearing during purchase - Require user to confirm email before purchasing -- Guest purchase in the future (remove from matura shit) + + +- Guest purchase in the future (maybe remove from matura) - Create password changing endpoint (to reset forgotten pwd) - Add Admin profile (page to change account settings per person like changing pwd) @@ -19,7 +21,9 @@ - Implement Permission system -- Seat numbering +- Seat numbering!! + +- Add localization for date - add webpack (or any other minifying tool) to project website to decrease file size (OPTIONAL) \ No newline at end of file diff --git a/src/webapp/main/src/components/seatplan/editor/window.vue b/src/webapp/main/src/components/seatplan/editor/window.vue index 1664d6e..8d6a09c 100644 --- a/src/webapp/main/src/components/seatplan/editor/window.vue +++ b/src/webapp/main/src/components/seatplan/editor/window.vue @@ -169,7 +169,7 @@ } ); if ( !sessionStorage.getItem( 'seatplan-history' ) ) { - sessionStorage.setItem( 'seatplaTODO:n-history', JSON.stringify( { '1': this.scaleDown( this.draggables ) } ) ); + sessionStorage.setItem( 'seatplan-history', JSON.stringify( { '1': this.scaleDown( this.draggables ) } ) ); } let history = sessionStorage.getItem( 'seatplan-history' ) ? JSON.parse( sessionStorage.getItem( 'seatplan-history' ) ) : {}; diff --git a/src/webapp/main/src/components/seatplan/userApp/userWindow.vue b/src/webapp/main/src/components/seatplan/userApp/userWindow.vue index 3f54322..f733261 100644 --- a/src/webapp/main/src/components/seatplan/userApp/userWindow.vue +++ b/src/webapp/main/src/components/seatplan/userApp/userWindow.vue @@ -9,7 +9,6 @@