improve seatplan editor significantly

This commit is contained in:
2023-06-10 11:39:59 +02:00
parent 62b5b33b88
commit f517786655
6 changed files with 97 additions and 19 deletions

View File

@@ -11,8 +11,8 @@
</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200">
<script defer src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<link rel="stylesheet" href="coloris.min.css">
<script defer src="coloris.min.js"></script>
<link rel="stylesheet" href="/coloris.min.css">
<script defer src="/coloris.min.js"></script>
</head>
<body>

View File

@@ -14,36 +14,53 @@
<tr>
<td>Position X:</td>
<td>
<input type="number" min="20" v-model="internal[ active ].x" @focusout="resubmit()">
<input type="number" min="20" v-model="internal[ active ].x" @change="resubmit()">
</td>
</tr>
<tr>
<td>Position Y:</td>
<td>
<input type="number" min="20" v-model="internal[ active ].y" @focusout="resubmit()">
<input type="number" min="20" v-model="internal[ active ].y" @change="resubmit()">
</td>
</tr>
<tr>
<td>Width:</td>
<td>
<input type="number" min="20" v-model="internal[ active ].w" @focusout="resubmit()">
<input type="number" min="20" v-model="internal[ active ].w" @change="resubmit()">
</td>
</tr>
<tr>
<td>Height:</td>
<td>
<input type="number" min="20" v-model="internal[ active ].h" @focusout="resubmit()">
<input type="number" min="20" v-model="internal[ active ].h" @change="resubmit()">
</td>
</tr>
<tr>
<td>Starting row:</td>
<td>
<input type="number" min="1" max="20" v-model="internal[ active ].startingRow" @change="resubmit()">
</td>
</tr>
<tr>
<td>Origin:</td>
<td>
<input type="number" min="1" max="4" v-model="internal[ active ].origin" @focusout="resubmit()">
<input type="number" min="1" max="4" v-model="internal[ active ].origin" @change="resubmit()">
</td>
</tr>
<tr>
<td>Type:</td>
<td>
<select min="20" v-model="internal[ active ].type" @change="resubmit()">
<option value="seat">Seat</option>
<option value="stand">Stand</option>
<option value="stage">Stage</option>
</select>
</td>
</tr>
<tr>
<td>Shape:</td>
<td><select min="20" v-model="internal[ active ].shape" @change="resubmit()">
<td>
<select min="20" v-model="internal[ active ].shape" @change="resubmit()">
<option value="rectangular">Rectangular</option>
<option value="trapezoid">Trapezoid</option>
<option value="circular">Circular</option>

View File

@@ -13,11 +13,11 @@
<div class="parent">
<div class="content-parent">
<Vue3DraggableResizable v-for="draggable in draggables" :initW="draggable.w" :initH="draggable.h" v-model:x="draggable.x" v-model:y="draggable.y" v-model:w="draggable.w" v-model:h="draggable.h"
v-model:active="draggable.active" :draggable="draggable.draggable" :resizable="draggable.resizable" :parent="true" @activated="activateComponent( draggable.id );"
v-model:active="draggable.active" v-model:draggable="draggable.draggable" :resizable="draggable.resizable" :parent="true" @activated="activateComponent( draggable.id );"
@drag-end="saveHistory();" @resize-end="saveHistory();" @contextmenu="( e ) => { e.preventDefault(); }" class="draggable-box">
<circularSeatplanComponent v-if="draggable.shape == 'circular' && draggable.kind == 'seat'" :scale-factor="scaleFactor" :w="draggable.w" :h="draggable.h" :origin="draggable.origin"></circularSeatplanComponent>
<trapezoidSeatplanComponent v-if="draggable.shape == 'trapezoid' && draggable.kind == 'seat'" :scale-factor="scaleFactor" :w="draggable.w" :h="draggable.h" :origin="draggable.origin"></trapezoidSeatplanComponent>
<rectangularSeatplanComponent v-if="draggable.shape == 'rectangular' && draggable.kind == 'seat'" :scale-factor="scaleFactor" :w="draggable.w" :h="draggable.h" :origin="draggable.origin"></rectangularSeatplanComponent>
<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-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-if="draggable.shape == 'rectangular' && draggable.type == 'seat'" :scale-factor="scaleFactor" :w="draggable.w" :h="draggable.h" :origin="draggable.origin"></rectangularSeatplanComponent>
</Vue3DraggableResizable>
</div>
</div>
@@ -26,6 +26,8 @@
<button v-else disabled>Undo</button>
<button v-if="available.redo" @click="historyOp( 'redo' )">Redo</button>
<button v-else disabled>Redo</button>
<button @click="zoom( 1.2 )">+</button>
<button @click="zoom( 0.8 )">-</button>
<button @click="addNewElement()">Add</button>
<button @click="deleteSelected()">Delete</button>
</div>
@@ -52,11 +54,12 @@
data() {
return {
active: 0,
draggables: { 1: { 'x': 100, 'y':100, 'h': 100, 'w': 250, 'active': false, 'draggable': true, 'resizable': true, 'id': 1, 'origin': 1, 'categories': { 1: 0 }, 'shape':'rectangular', 'kind': 'seat' } },
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 } },
available: { 'redo': false, 'undo': false },
scaleFactor: 1,
sizePoll: null,
prevSize: { 'h': window.innerHeight, 'w': window.innerWidth },
zoomFactor: 1,
}
},
methods: {
@@ -71,6 +74,7 @@
*/
runHook () {
let self = this;
this.zoomFactor = sessionStorage.getItem( 'zoom' ) ? sessionStorage.getItem( 'zoom' ) : 1;
/*
Keybinds:
@@ -100,8 +104,6 @@
this.loadSeatplan();
// TODO: build Zoom function (including touch gesture support)
if ( !sessionStorage.getItem( 'seatplan-history' ) ) {
sessionStorage.setItem( 'seatplan-history', JSON.stringify( { '1': this.scaleDown( this.draggables ) } ) );
}
@@ -118,6 +120,7 @@
}
let supportedBrowser = [];
this.save();
// TODO: Add warning for untested browsers & suboptimal window sizes!
},
eventHandler ( e ) {
@@ -131,8 +134,9 @@
Calculate scale factor (this adds support for differently sized screens)
900px is the "default" height
*/
let height = $( document ).height() * 0.8;
this.scaleFactor = height / 900;
this.scaleFactor = ( height / 900 ) * this.zoomFactor;
/*
Load seatplan
*/
@@ -231,7 +235,7 @@
sessionStorage.setItem( 'seatplan', JSON.stringify( this.scaleDown( this.draggables ) ) );
},
addNewElement () {
this.draggables[ Object.keys( this.draggables ).length + 1 ] = { 'x': 100, 'y':100, 'h': 100, 'w': 250, 'active': false, 'draggable': true, 'resizable': true, 'id': Object.keys( this.draggables ).length + 1, 'origin': 1, 'categories': { 1: 0 }, 'shape':'rectangular', 'kind': 'seat' };
this.draggables[ Object.keys( this.draggables ).length + 1 ] = { 'x': 100, 'y':100, 'h': 100, 'w': 250, 'active': false, 'draggable': true, 'resizable': true, 'id': Object.keys( this.draggables ).length + 1, 'origin': 1, 'shape':'rectangular', 'type': 'seat', 'startingRow': 1 };
this.saveHistory();
},
deleteSelected () {
@@ -245,6 +249,12 @@
this.draggables = value;
this.selectedObject = value;
this.saveHistory();
},
zoom ( scale ) {
this.zoomFactor = this.zoomFactor * scale;
sessionStorage.setItem( 'zoom', this.zoomFactor );
this.scaleFactor = this.scaleFactor * scale;
this.draggables = this.scaleUp( JSON.parse( sessionStorage.getItem( 'seatplan' ) ) );
}
},
created () {

View File

@@ -41,6 +41,10 @@ export default {
type: Number,
"default": 1,
},
startingRow: {
type: Number,
"default": 1,
}
},
data () {
return {
@@ -56,7 +60,7 @@ export default {
const size = 33;
let count = Math.min( Math.floor( w / size ), Math.floor( h / size ) );
this.seats = {};
for ( let row = 0; row < count; row++ ) {
for ( let row = this.startingRow; row < count; row++ ) {
let nn = row * ( Math.PI / 2 );
let r = row * size;
this.seats[ row ] = {};
@@ -95,6 +99,9 @@ export default {
},
origin() {
this.calculateChairs();
},
startingRow() {
this.calculateChairs();
}
},
created() {

View File

@@ -41,6 +41,10 @@ export default {
type: Number,
"default": 1,
},
startingRow: {
type: Number,
"default": 1,
}
},
data () {
return {
@@ -60,7 +64,7 @@ export default {
let count = Math.floor( heightTriangle / ( sideOffset * 2 ) );
const angle = Math.PI / 4;
this.seats = {};
for ( let row = 0; row < count; row++ ) {
for ( let row = this.startingRow; row < count; row++ ) {
let nn = 2 + ( row - 1 ) * 2;
this.seats[ row ] = {};
for ( let n = 0; n < nn; n++ ) {
@@ -98,6 +102,9 @@ export default {
},
origin() {
this.calculateChairs();
},
startingRow() {
this.calculateChairs();
}
},
created() {

View File

@@ -0,0 +1,37 @@
<!--
* 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="stages">
<div id="rectangular" v-if="origin == 'rectangular'"></div>
<div id="trapezoid" v-if="origin == 'trapezoid'"></div>
<div id="circular" v-if="origin == 'circular'"></div>
</div>
</template>
<style scoped>
</style>
<script>
export default {
name: 'stagesSeatplanComponent',
props: {
origin: {
type: Number,
"default": 1,
},
origin: {
type: String,
"default": "rectangular",
},
}
}
</script>