user facing seat plan

This commit is contained in:
2023-07-02 15:43:10 +02:00
parent e57c13341b
commit a5aae2c54f
8 changed files with 715 additions and 51 deletions

View File

@@ -0,0 +1,119 @@
<!--
* libreevent - properties.vue
*
* Created by Janis Hutz 05/12/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
-->
<template>
<div id="circularSeatplan">
<div v-for="row in seats">
<span class="material-symbols-outlined seats" v-for="seat in row" :style="seat.style">living</span>
</div>
</div>
</template>
<style scoped>
.seats {
position: absolute;
}
</style>
<script>
export default {
name: 'circularSeatplanComponent',
props: {
h: {
type: Number,
"default": 100,
},
w: {
type: Number,
"default": 200,
},
scaleFactor: {
type: Number,
"default": 1,
},
origin: {
type: Number,
"default": 1,
},
startingRow: {
type: Number,
"default": 1,
},
id: {
type: Number,
"default": 1
}
},
data () {
return {
seats: {},
}
},
methods: {
calculateChairs () {
// Size of seat at scale 1 is 32px
// w & h are normalised
let w = Math.round( this.w / this.scaleFactor );
let h = Math.round( this.h / this.scaleFactor );
const size = 33;
let count = Math.min( Math.floor( w / size ), Math.floor( h / size ) );
this.seats = {};
let details = { 'data': {}, 'id': this.id };
for ( let row = this.startingRow; row < count; row++ ) {
let nn = row * ( Math.PI / 2 );
details.data[ row ] = Math.floor( nn );
let r = row * size;
this.seats[ row ] = {};
for ( let n = 0; n < nn; n++ ) {
let phi = n * size / ( row * size );
if ( this.origin === 1 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; bottom: ${ r * Math.cos( phi ) * this.scaleFactor }px; left: ${ r * Math.sin( phi ) * this.scaleFactor }px; rotate: ${ phi }rad` };
} else if ( this.origin === 2 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; bottom: ${ r * Math.cos( phi ) * this.scaleFactor }px; right: ${ r * Math.sin( phi ) * this.scaleFactor }px; rotate: ${ Math.PI * 2 - phi }rad` };
} else if ( this.origin === 3 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; top: ${ r * Math.cos( phi ) * this.scaleFactor }px; right: ${ r * Math.sin( phi ) * this.scaleFactor }px; rotate: ${ phi + Math.PI }rad` };
} else if ( this.origin === 4 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; top: ${ r * Math.cos( phi ) * this.scaleFactor }px; left: ${ r * Math.sin( phi ) * this.scaleFactor }px; rotate: ${ Math.PI - phi }rad` };
}
}
}
this.$emit( 'seatingInfo', details );
},
setScaleFactor () {
for ( let row in this.seats ) {
for ( let seat in this.seats[ row ] ) {
let styles = this.seats[ row ][ seat ].style.substring( this.seats[ row ][ seat ].style.indexOf( ';' ) + 1 );
this.seats[ row ][ seat ].style = `font-size: ${this.scaleFactor * 200}%;` + styles;
}
}
}
},
watch: {
scaleFactor() {
this.setScaleFactor();
},
h() {
this.calculateChairs();
},
w() {
this.calculateChairs();
},
origin() {
this.calculateChairs();
},
startingRow() {
this.calculateChairs();
}
},
created() {
this.calculateChairs();
}
}
</script>

View File

@@ -0,0 +1,105 @@
<!--
* libreevent - properties.vue
*
* Created by Janis Hutz 05/12/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
-->
<template>
<div id="rectangularSeatplan">
<div v-for="row in seats" class="rows">
<span class="material-symbols-outlined seats" v-for="seat in row" :style="seat.style" @click="selectSeat( seat.id )">living</span>
</div>
</div>
</template>
<style scoped>
.seats {
position: absolute;
}
</style>
<script>
export default {
name: 'rectangularSeatplanComponent',
props: {
h: {
type: Number,
"default": 100,
},
w: {
type: Number,
"default": 200,
},
scaleFactor: {
type: Number,
"default": 1,
},
origin: {
type: Number,
"default": 1,
},
id: {
type: Number,
"default": 1
}
},
data () {
return {
seats: {},
}
},
methods: {
calculateChairs () {
// Size of seat at scale 1 is 32px
// w & h are normalised
let w = Math.floor( this.w / this.scaleFactor );
let h = Math.floor( this.h / this.scaleFactor );
const size = 33;
this.seats = {};
for ( let row = 0; row < Math.floor( h / size ); row++ ) {
this.seats[ row ] = {};
for ( let n = 0; n < Math.floor( w / size ); n++ ) {
if ( this.origin === 1 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; bottom: ${ row * size * this.scaleFactor }px; left: ${ n * size * this.scaleFactor }px; rotate: ${ this.origin / 4 - 0.25 }turn;` };
} else if ( this.origin === 2 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; bottom: ${ row * size * this.scaleFactor }px; right: ${ n * size * this.scaleFactor }px; rotate: ${ this.origin / 4 - 0.25 }turn;` };
} else if ( this.origin === 3 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; top: ${ row * size * this.scaleFactor }px; right: ${ n * size * this.scaleFactor }px; rotate: ${ this.origin / 4 - 0.25 }turn;` };
} else if ( this.origin === 4 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; top: ${ row * size * this.scaleFactor }px; left: ${ n * size * this.scaleFactor }px; rotate: ${ this.origin / 4 - 0.25 }turn;` };
}
}
}
},
setScaleFactor () {
for ( let row in this.seats ) {
for ( let seat in this.seats[ row ] ) {
let styles = this.seats[ row ][ seat ].style.substring( this.seats[ row ][ seat ].style.indexOf( ';' ) + 1 );
this.seats[ row ][ seat ].style = `font-size: ${this.scaleFactor * 200}%;` + styles;
}
}
}
},
watch: {
scaleFactor() {
this.setScaleFactor();
},
h() {
this.calculateChairs();
},
w() {
this.calculateChairs();
},
origin() {
this.calculateChairs();
}
},
created() {
this.calculateChairs();
}
}
</script>

View File

@@ -0,0 +1,122 @@
<!--
* libreevent - properties.vue
*
* Created by Janis Hutz 05/12/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
-->
<template>
<div id="trapezoidSeatplan">
<div v-for="row in seats">
<span class="material-symbols-outlined seats" v-for="seat in row" :style="seat.style">living</span>
</div>
</div>
</template>
<style scoped>
.seats {
position: absolute;
}
</style>
<script>
export default {
name: 'trapezoidSeatplanComponent',
props: {
h: {
type: Number,
"default": 100,
},
w: {
type: Number,
"default": 200,
},
scaleFactor: {
type: Number,
"default": 1,
},
origin: {
type: Number,
"default": 1,
},
startingRow: {
type: Number,
"default": 1,
},
id: {
type: Number,
"default": 1
}
},
data () {
return {
seats: {},
}
},
methods: {
calculateChairs () {
// Size of seat at scale 1 is 32px
// w & h are normalised
let w = Math.round( this.w / this.scaleFactor );
let h = Math.round( this.h / this.scaleFactor );
const size = 33;
let side = Math.min( w, h ) + 20;
let heightTriangle = Math.floor( Math.sqrt( side ** 2 - ( Math.sqrt( side ** 2 * 2 ) / 2 ) ) )
let sideOffset = size / Math.sqrt( 2 );
let count = Math.floor( heightTriangle / ( sideOffset * 2 ) );
const angle = Math.PI / 4;
this.seats = {};
let details = { 'data': {}, 'id': this.id };
for ( let row = this.startingRow; row < count; row++ ) {
let nn = 2 + ( row - 1 ) * 2;
this.seats[ row ] = {};
details.data[ row ] = Math.floor( nn );
for ( let n = 0; n < nn; n++ ) {
let side = n * sideOffset;
if ( this.origin === 1 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; bottom: ${ ( side + 5 ) * this.scaleFactor }px; left: ${ ( row * sideOffset * 2 - side ) * this.scaleFactor }px; rotate: ${ angle }rad` };
} else if ( this.origin === 2 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; bottom: ${ ( side + 5 ) * this.scaleFactor }px; right: ${ ( row * sideOffset * 2 - side ) * this.scaleFactor }px; rotate: ${ Math.PI * 2 - angle }rad` };
} else if ( this.origin === 3 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; top: ${ ( side + 5 ) * this.scaleFactor }px; right: ${ ( row * sideOffset * 2 - side ) * this.scaleFactor }px; rotate: ${ angle + Math.PI }rad` };
} else if ( this.origin === 4 ) {
this.seats[ row ][ n ] = { 'style': `font-size: ${this.scaleFactor * 200}%; top: ${ ( side + 5 ) * this.scaleFactor }px; left: ${ ( row * sideOffset * 2 - side ) * this.scaleFactor }px; rotate: ${ Math.PI - angle }rad` };
}
}
}
this.$emit( 'seatingInfo', details );
},
setScaleFactor () {
for ( let row in this.seats ) {
for ( let seat in this.seats[ row ] ) {
let styles = this.seats[ row ][ seat ].style.substring( this.seats[ row ][ seat ].style.indexOf( ';' ) + 1 );
this.seats[ row ][ seat ].style = `font-size: ${this.scaleFactor * 200}%;` + styles;
}
}
}
},
watch: {
scaleFactor() {
this.setScaleFactor();
},
h() {
this.calculateChairs();
},
w() {
this.calculateChairs();
},
origin() {
this.calculateChairs();
},
startingRow() {
this.calculateChairs();
}
},
created() {
this.calculateChairs();
}
}
</script>

View File

@@ -0,0 +1,110 @@
<!--
* libreevent - stages.vue
*
* Created by Janis Hutz 05/12/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
-->
<template>
<div id="stages" class="stages">
<div id="rectangular" v-if="shape == 'rectangular'" class="stages" :style="style"></div>
<div id="trapezoid" v-else-if="shape == 'trapezoid'" class="stages"><div id="trapezoid-ingredient" :style="trapezoidStyle"><div id="trapezoid-line"></div></div></div>
<div id="circular" v-else-if="shape == 'circular'" class="stages"><div id="circular-ingredient" :style="circularStyle"></div></div>
</div>
</template>
<style scoped>
.stages {
height: 100%;
width: 100%;
}
#rectangular {
border-color: black;
border-width: 2px;
background-color: var( --popup-color );
}
#circular, #trapezoid {
overflow: hidden;
}
#trapezoid-ingredient {
display: flex;
justify-content: center;
align-items: flex-end;
height: 200%;
width: 200%;
position: relative;
bottom: 50%;
right: 50%;
}
#trapezoid-line {
border: black solid 1px;
height: 50%;
width: 100%;
display: block;
background-color: var( --popup-color );
}
#circular-ingredient {
border: solid black 2px;
border-radius: 100%;
height: 199%;
width: 199%;
position: relative;
background-color: var( --popup-color );
}
</style>
<script>
export default {
name: 'stagesSeatplanComponent',
props: {
origin: {
type: Number,
"default": 1,
},
shape: {
type: String,
"default": "rectangular",
},
},
data() {
return {
style: 'border-style: none none solid none',
circularStyle: 'top: 0; left 100%;',
trapezoidStyle: 'rotate: 45deg',
}
},
methods: {
updateOrigin () {
if ( this.origin === 1 ) {
this.style = 'border-style: none none solid none';
this.circularStyle = 'top: 0; right: 100%;';
} else if ( this.origin === 2 ) {
this.style = 'border-style: none solid none none';
this.circularStyle = 'top: 0; right: 0;';
} else if ( this.origin === 3 ) {
this.style = 'border-style: solid none none none';
this.circularStyle = 'top: -100%; right: 0;';
} else if ( this.origin === 4 ) {
this.style = 'border-style: none none none solid';
this.circularStyle = 'top: -100%; right: 100%;';
}
}
},
watch: {
origin ( value ) {
this.updateOrigin();
}
},
created() {
this.updateOrigin();
}
}
</script>

View File

@@ -0,0 +1,109 @@
<!--
* libreevent - standing.vue
*
* Created by Janis Hutz 05/12/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
-->
<template>
<div id="stages" class="stages">
<div id="rectangular" v-if="shape == 'rectangular'" class="stages" :style="style"></div>
<div id="trapezoid" v-else-if="shape == 'trapezoid'" class="stages"><div id="trapezoid-ingredient" :style="trapezoidStyle"><div id="trapezoid-line"></div></div></div>
<div id="circular" v-else-if="shape == 'circular'" class="stages"><div id="circular-ingredient" :style="circularStyle"></div></div>
</div>
</template>
<style scoped>
.stages {
height: 100%;
width: 100%;
}
#rectangular {
border-color: black;
border-width: 2px;
}
#circular, #trapezoid {
overflow: hidden;
}
#trapezoid-ingredient {
display: flex;
justify-content: center;
align-items: center;
height: 200%;
width: 200%;
position: relative;
bottom: 50%;
right: 50%;
}
#trapezoid-line {
border: black solid 1px;
height: 50%;
width: 100%;
display: block;
background-color: var( --popup-color );
}
#circular-ingredient {
border: solid black 2px;
border-radius: 100%;
height: 199%;
width: 199%;
position: relative;
background-color: var( --popup-color );
}
</style>
<script>
export default {
name: 'stagesSeatplanComponent',
props: {
origin: {
type: Number,
"default": 1,
},
shape: {
type: String,
"default": "rectangular",
},
},
data() {
return {
style: 'border-style: none none solid none',
circularStyle: 'top: 0; left 100%;',
trapezoidStyle: 'rotate: 45deg',
}
},
methods: {
updateOrigin () {
if ( this.origin === 1 ) {
this.style = 'border-style: none none solid none';
this.circularStyle = 'top: 0; right: 100%;';
} else if ( this.origin === 2 ) {
this.style = 'border-style: none solid none none';
this.circularStyle = 'top: 0; right: 0;';
} else if ( this.origin === 3 ) {
this.style = 'border-style: solid none none none';
this.circularStyle = 'top: -100%; right: 0;';
} else if ( this.origin === 4 ) {
this.style = 'border-style: none none none solid';
this.circularStyle = 'top: -100%; right: 100%;';
}
}
},
watch: {
origin ( value ) {
this.updateOrigin();
}
},
created() {
this.updateOrigin();
}
}
</script>

View File

@@ -0,0 +1,69 @@
<!--
* libreevent - textField.vue
*
* Created by Janis Hutz 07/01/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
-->
<template>
<div id="textFields">
<p :style="style">{{ text }}</p>
</div>
</template>
<script>
export default {
name: 'textFieldSeatplanComponent',
props: {
origin: {
type: Number,
"default": 1,
},
text: {
type: String,
"default": "Untitled",
},
textSize: {
type: Number,
"default": 20,
},
scaleFactor: {
type: Number,
"default": 1,
},
colour: {
type: String,
"default": '#000000',
}
},
data() {
return {
style: 'font-size: 20pt; rotate: 0deg; color: #000000',
}
},
methods: {
updateStyle () {
this.style = `font-size: ${ this.scaleFactor * this.textSize }pt; rotate: ${ 90 * this.origin - 90 }deg; color: ${this.colour}`;
}
},
watch: {
origin ( value ) {
this.updateStyle();
},
scaleFactor ( value ) {
this.updateStyle();
},
colour ( value ) {
this.updateStyle();
},
textSize ( value ) {
this.updateStyle();
}
},
created() {
this.updateStyle();
}
}
</script>

View File

@@ -9,11 +9,11 @@
<template>
<div id="window">
<!-- TODO: Add additional div with v-if to check if a location has been selected and warn if not so. -->
<div class="parent" id="parent">
<h2>Seat plan: {{ event.name }}</h2>
<div class="parent" id="parent" @wheel="( e ) => { handleScroll( e ); }" @mousemove="( e ) => { handleDrag( e ); }" @mousedown="( e ) => { setOffset( e ); }">
<div class="content-parent">
<Vue3DraggableResizable v-for="draggable in draggables" :initW="draggable.w" :initH="draggable.h" :x="draggable.x" :y="draggable.y" :w="draggable.w" :h="draggable.h"
:active="false" :draggable="false" :resizable="false" :parent="true" @contextmenu="( e ) => { e.preventDefault(); }" class="draggable-box">
:active="false" :draggable="false" :resizable="false" :parent="true" class="draggable-box">
<circularSeatplanComponent v-if="draggable.shape == 'circular' && draggable.type == 'seat'" :scale-factor="scaleFactor" :w="draggable.w" :h="draggable.h" :origin="draggable.origin" :starting-row="draggable.startingRow"></circularSeatplanComponent>
<trapezoidSeatplanComponent v-else-if="draggable.shape == 'trapezoid' && draggable.type == 'seat'" :scale-factor="scaleFactor" :w="draggable.w" :h="draggable.h" :origin="draggable.origin" :starting-row="draggable.startingRow"></trapezoidSeatplanComponent>
<rectangularSeatplanComponent v-else-if="draggable.shape == 'rectangular' && draggable.type == 'seat'" :scale-factor="scaleFactor" :w="draggable.w" :h="draggable.h" :origin="draggable.origin"></rectangularSeatplanComponent>
@@ -23,18 +23,23 @@
</Vue3DraggableResizable>
</div>
</div>
<div class="toolbar">
<button title="Zoom in [+]" @click="zoom( 0.2 )"><span class="material-symbols-outlined">zoom_in</span></button>
<button title="Reset zoom [=]" @click="zoom( 1 );"><span class="material-symbols-outlined">center_focus_strong</span></button>
<button title="Zoom out [-]" @click="zoom( -0.2 )"><span class="material-symbols-outlined">zoom_out</span></button>
</div>
<notifications ref="notification" location="topleft"></notifications>
</div>
</template>
<script>
import Vue3DraggableResizable from 'vue3-draggable-resizable';
import circularSeatplanComponent from '@/components/seatplan/seatplanComponents/seats/circular.vue';
import rectangularSeatplanComponent from '@/components/seatplan/seatplanComponents/seats/rectangular.vue';
import trapezoidSeatplanComponent from '@/components/seatplan/seatplanComponents/seats/trapezoid.vue';
import stagesSeatplanComponent from '@/components/seatplan/seatplanComponents/stages.vue';
import standingSeatplanComponent from '@/components/seatplan/seatplanComponents/standing.vue';
import textFieldSeatplanComponent from '@/components/seatplan/seatplanComponents/textField.vue';
import circularSeatplanComponent from '@/components/seatplan/userApp/seatplanComponents/seats/circular.vue';
import rectangularSeatplanComponent from '@/components/seatplan/userApp/seatplanComponents/seats/rectangular.vue';
import trapezoidSeatplanComponent from '@/components/seatplan/userApp/seatplanComponents/seats/trapezoid.vue';
import stagesSeatplanComponent from '@/components/seatplan/userApp/seatplanComponents/stages.vue';
import standingSeatplanComponent from '@/components/seatplan/userApp/seatplanComponents/standing.vue';
import textFieldSeatplanComponent from '@/components/seatplan/userApp/seatplanComponents/textField.vue';
import notifications from '@/components/notifications/notifications.vue';
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css';
@@ -54,12 +59,14 @@
return {
active: 0,
draggables: { 1: { 'x': 100, 'y':100, 'h': 100, 'w': 250, 'active': false, 'draggable': true, 'resizable': true, 'id': 1, 'origin': 1, 'shape':'rectangular', 'type': 'seat', 'startingRow': 1, 'seatCountingStartingPoint': 1, 'sector': 'A', 'text': { 'text': 'TestText', 'textSize': 20, 'colour': '#20FFFF' } }, 'ticketCount': 1 },
event: { 'name': 'TestEvent2', 'location': 'TestLocation2', 'date': '2023-07-15', 'RoomName': 'TestRoom2', 'currency': 'CHF', 'categories': { '1': { 'price': { '1':25, '2':35 }, 'bg': 'black', 'fg': 'white', 'name': 'Category 1' }, '2': { 'price': { '1':15, '2':20 }, 'bg': 'green', 'fg': 'white', 'name': 'Category 2' } }, 'ageGroups': { '1':{ 'id': 1, 'name':'Child', 'age':'0 - 15.99' }, '2':{ 'id': 2, 'name': 'Adult', 'age': null } }, 'ageGroupCount': 2, 'maxTickets': 2 },
available: { 'redo': false, 'undo': false },
scaleFactor: 1,
sizePoll: null,
prevSize: { 'h': window.innerHeight, 'w': window.innerWidth },
zoomFactor: 1,
historyPos: 0,
standardDeviation: { 'currentTop': 0, 'currentLeft': 0 },
movePos: { 'top': 0, 'left': 0, 'isMoving': false, 'isSet': false },
generalSettings: { 'namingScheme': 'numeric' },
}
},
@@ -85,22 +92,7 @@
- Ctrl + Y: Redo
*/
document.onkeydown = function ( event ) {
if ( event.key === 'Delete' ) {
event.preventDefault();
self.deleteSelected();
} else if ( event.ctrlKey && event.key === 's' ) {
event.preventDefault();
self.saveDraft();
} else if ( ( event.ctrlKey && event.key === 'y' ) ) {
event.preventDefault();
self.historyOp( 'redo' );
} else if ( event.ctrlKey && event.key === 'z' ) {
event.preventDefault();
self.historyOp( 'undo' );
} else if ( event.ctrlKey && event.key === 'i' ) {
event.preventDefault();
self.addNewElement();
} else if ( event.key === '+' ) {
if ( event.key === '+' ) {
self.zoom( 0.2 );
} else if ( event.key === '-' ) {
self.zoom( -0.2 );
@@ -110,7 +102,9 @@
};
this.loadSeatplan();
// TODO: Add warning for untested browsers & suboptimal window sizes!
sessionStorage.setItem( 'seatplan', JSON.stringify( this.scaleDown( this.draggables ) ) );
// TODO: remove scaleDown function again once backend is up
// TODO: Optimise for odd screen sizes and aspect ratios
},
eventHandler ( e ) {
if ( this.prevSize.h != window.innerHeight || this.prevSize.w != window.innerWidth ) {
@@ -118,6 +112,56 @@
this.loadSeatplan();
}
},
handleScroll ( e ) {
e.preventDefault();
if ( e.deltaY > 0 ) {
this.zoom( 0.2 );
} else {
this.zoom( -0.2 );
}
},
setOffset( e ) {
this.standardDeviation.currentLeft = e.clientX;
this.standardDeviation.currentTop = e.clientY;
},
handleDrag ( e ) {
if ( e.buttons === 1 ) {
let parent = document.getElementById( 'parent' );
if ( !this.movePos.isSet ) {
this.movePos.left = parent.scrollWidth - parent.scrollLeft;
this.movePos.top = parent.scrollHeight - parent.scrollTop;
this.movePos.isSet = true;
}
this.movePos.isMoving = true;
e.preventDefault();
let valueTop = parent.scrollHeight - ( e.clientY - this.standardDeviation.currentTop + this.movePos.top );
let valueLeft = parent.scrollWidth - ( e.clientX - this.standardDeviation.currentLeft + this.movePos.left );
parent.scrollTop = valueTop > 0 ? valueTop : 0;
parent.scrollLeft = valueLeft > 0 ? valueLeft : 0;
} else {
if ( this.movePos.isMoving ) {
let parent = document.getElementById( 'parent' );
this.movePos.left = parent.scrollWidth - parent.scrollLeft;
this.movePos.top = parent.scrollHeight - parent.scrollTop;
this.movePos.isMoving = false;
}
};
},
scaleDown ( valueArray ) {
const allowedAttributes = [ 'w', 'h', 'x', 'y' ]
let returnArray = {};
for ( let entry in valueArray ) {
returnArray[ entry ] = {};
for ( let attributes in valueArray[ entry ] ) {
if ( allowedAttributes.includes( attributes ) ) {
returnArray[ entry ][ attributes ] = Math.round( ( valueArray[ entry ][ attributes ] / this.scaleFactor ) * 1000 ) / 1000;
} else {
returnArray[ entry ][ attributes ] = valueArray[ entry ][ attributes ];
}
}
}
return returnArray;
},
loadSeatplan () {
/*
Calculate scale factor (this adds support for differently sized screens)
@@ -134,7 +178,6 @@
this.draggables = this.scaleUp( JSON.parse( sessionStorage.getItem( 'seatplan' ) ) );
}
for ( let element in this.draggables ) {
if ( this.draggables[ element ].active ) {
this.draggables[ element ].active = false;
@@ -142,7 +185,7 @@
}
},
scaleUp ( valueArray ) {
const allowedAttributes = [ 'w', 'h', 'x', 'y' ]
const allowedAttributes = [ 'w', 'h', 'x', 'y' ];
let returnArray = {};
for ( let entry in valueArray ) {
returnArray[ entry ] = {};
@@ -156,11 +199,6 @@
}
return returnArray;
},
handleUpdate ( value ) {
this.draggables = value;
this.selectedObject = value;
this.saveHistory();
},
zoom ( scale ) {
if ( scale == 1 ) {
this.zoomFactor = 1;
@@ -168,11 +206,7 @@
this.loadSeatplan();
} else {
if ( ( this.zoomFactor < 0.3 && scale < 0 ) || ( this.zoomFactor > 2.9 && scale > 0 ) ) {
if ( this.zoomFactor < 0.3 ) {
this.$refs.notification.createNotification( 'Minimum zoom factor reached', 5, 'warning', 'normal' );
} else {
this.$refs.notification.createNotification( 'Maximum zoom factor reached', 5, 'warning', 'normal' );
}
} else {
this.zoomFactor += scale;
}
@@ -193,10 +227,10 @@
<style scoped>
.parent {
height: 90vh;
height: 80vh;
aspect-ratio: 16 / 9;
top: 7.5vh;
left: 3vw;
top: 17vh;
left: 10vw;
position: absolute;
border: black 1px solid;
user-select: none;
@@ -206,7 +240,7 @@
}
.draggable-box {
cursor: all-scroll;
cursor: default;
}
.properties {
@@ -232,13 +266,9 @@
.toolbar {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: absolute;
top: 7.5vh;
left: 0.5vw;
height: 90vh;
position: fixed;
top: 17vh;
left: 10.5vw;
}
.toolbar button {
margin-top: 10%;

View File

@@ -22,7 +22,7 @@
</style>
<script>
import seatplan from '@/components/seatplan.vue';
import seatplan from '@/components/seatplan/userApp/userWindow.vue';
import noseatplan from '@/components/noseatplan.vue';
export default {