You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
622 lines
16 KiB
622 lines
16 KiB
{% extends 'standard_layout.html.twig' %}
|
|
|
|
|
|
{% block stylesheets %}
|
|
{{ parent() }}
|
|
<link rel="stylesheet" href="{{ asset("/css/nouislider.css") }}">
|
|
<style>
|
|
body {
|
|
margin-top: 30px;
|
|
margin-bottom: 30px;
|
|
background: #f2f2f2;
|
|
}
|
|
|
|
.canvas-container {
|
|
margin-right: auto;
|
|
margin-left: auto;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block javascripts %}
|
|
{{ parent() }}
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.11/fabric.min.js"></script>
|
|
|
|
<script src="{{ asset("/js/nouislider.js") }}"></script>
|
|
<script>
|
|
let canvas
|
|
let number
|
|
const grid = 30
|
|
const backgroundColor = '#f8f8f8'
|
|
const lineStroke = '#ebebeb'
|
|
const tableFill = 'rgba(150, 111, 51, 0.7)'
|
|
const tableStroke = '#694d23'
|
|
const tableShadow = 'rgba(0, 0, 0, 0.4) 3px 3px 7px'
|
|
const chairFill = 'rgba(67, 42, 4, 0.7)'
|
|
const chairStroke = '#32230b'
|
|
const chairShadow = 'rgba(0, 0, 0, 0.4) 3px 3px 7px'
|
|
const barFill = 'rgba(0, 93, 127, 0.7)'
|
|
const barStroke = '#003e54'
|
|
const barShadow = 'rgba(0, 0, 0, 0.4) 3px 3px 7px'
|
|
const barText = 'Bar'
|
|
const wallFill = 'rgba(136, 136, 136, 0.7)'
|
|
const wallStroke = '#686868'
|
|
const wallShadow = 'rgba(0, 0, 0, 0.4) 5px 5px 20px'
|
|
|
|
var photoUrlLandscape = 'https://images8.alphacoders.com/292/292379.jpg',
|
|
photoUrlPortrait = 'https://presspack.rte.ie/wp-content/blogs.dir/2/files/2015/04/AMC_TWD_Maggie_Portraits_4817_V1.jpg'
|
|
|
|
|
|
let widthEl = document.getElementById('width')
|
|
let heightEl = document.getElementById('height')
|
|
let canvasEl = document.getElementById('canvas')
|
|
|
|
function initCanvas() {
|
|
if (canvas) {
|
|
canvas.clear()
|
|
canvas.dispose()
|
|
}
|
|
|
|
canvas = new fabric.Canvas('canvas')
|
|
number = 1
|
|
canvas.backgroundColor = backgroundColor
|
|
// canvas.setBackgroundImage('https://presspack.rte.ie/wp-content/blogs.dir/2/files/2015/04/AMC_TWD_Maggie_Portraits_4817_V1.jpg', canvas.renderAll.bind(canvas));
|
|
|
|
|
|
for (let i = 0; i < (canvas.height / grid); i++) {
|
|
const lineX = new fabric.Line([ 0, i * grid, canvas.height, i * grid], {
|
|
stroke: lineStroke,
|
|
selectable: false,
|
|
type: 'line'
|
|
})
|
|
const lineY = new fabric.Line([ i * grid, 0, i * grid, canvas.height], {
|
|
stroke: lineStroke,
|
|
selectable: false,
|
|
type: 'line'
|
|
})
|
|
sendLinesToBack()
|
|
canvas.add(lineX)
|
|
canvas.add(lineY)
|
|
}
|
|
|
|
canvas.on('object:moving', function(e) {
|
|
snapToGrid(e.target)
|
|
})
|
|
|
|
canvas.on('object:scaling', function(e) {
|
|
if (e.target.scaleX > 5) {
|
|
e.target.scaleX = 5
|
|
}
|
|
if (e.target.scaleY > 5) {
|
|
e.target.scaleY = 5
|
|
}
|
|
if (!e.target.strokeWidthUnscaled && e.target.strokeWidth) {
|
|
e.target.strokeWidthUnscaled = e.target.strokeWidth
|
|
}
|
|
if (e.target.strokeWidthUnscaled) {
|
|
e.target.strokeWidth = e.target.strokeWidthUnscaled / e.target.scaleX
|
|
if (e.target.strokeWidth === e.target.strokeWidthUnscaled) {
|
|
e.target.strokeWidth = e.target.strokeWidthUnscaled / e.target.scaleY
|
|
}
|
|
}
|
|
})
|
|
|
|
canvas.on('object:modified', function(e) {
|
|
e.target.scaleX = e.target.scaleX >= 0.25 ? (Math.round(e.target.scaleX * 2) / 2) : 0.5
|
|
e.target.scaleY = e.target.scaleY >= 0.25 ? (Math.round(e.target.scaleY * 2) / 2) : 0.5
|
|
snapToGrid(e.target)
|
|
if (e.target.type === 'table') {
|
|
canvas.bringToFront(e.target)
|
|
}
|
|
else {
|
|
canvas.sendToBack(e.target)
|
|
}
|
|
sendLinesToBack()
|
|
})
|
|
|
|
canvas.observe('object:moving', function (e) {
|
|
checkBoudningBox(e)
|
|
})
|
|
canvas.observe('object:rotating', function (e) {
|
|
checkBoudningBox(e)
|
|
})
|
|
canvas.observe('object:scaling', function (e) {
|
|
checkBoudningBox(e)
|
|
})
|
|
}
|
|
$( document ).ready(function() {
|
|
let widthEl = document.getElementById('width')
|
|
let heightEl = document.getElementById('height')
|
|
let canvasEl = document.getElementById('canvas')
|
|
initCanvas();
|
|
|
|
|
|
document.querySelectorAll('.rectangle')[0].addEventListener('click', function() {
|
|
const o = addRect(0, 0, 60, 60)
|
|
canvas.setActiveObject(o)
|
|
});
|
|
|
|
document.querySelectorAll('.circle')[0].addEventListener('click', function() {
|
|
const o = addCircle(0, 0, 30)
|
|
canvas.setActiveObject(o)
|
|
});
|
|
|
|
document.querySelectorAll('.triangle')[0].addEventListener('click', function() {
|
|
const o = addTriangle(0, 0, 30)
|
|
canvas.setActiveObject(o)
|
|
});
|
|
|
|
document.querySelectorAll('.chair')[0].addEventListener('click', function() {
|
|
const o = addChair(0, 0)
|
|
canvas.setActiveObject(o)
|
|
});
|
|
|
|
document.querySelectorAll('.bar')[0].addEventListener('click', function() {
|
|
const o = addBar(0, 0, 180, 60)
|
|
canvas.setActiveObject(o)
|
|
});
|
|
|
|
document.querySelectorAll('.wall')[0].addEventListener('click', function() {
|
|
const o = addWall(0, 0, 60, 180)
|
|
canvas.setActiveObject(o)
|
|
});
|
|
|
|
document.querySelectorAll('.remove')[0].addEventListener('click', function() {
|
|
const o = canvas.getActiveObject()
|
|
if (o) {
|
|
o.remove()
|
|
canvas.remove(o)
|
|
canvas.discardActiveObject()
|
|
canvas.renderAll()
|
|
}
|
|
});
|
|
|
|
document.querySelectorAll('.customer-mode')[0].addEventListener('click', function() {
|
|
canvas.getObjects().map(o => {
|
|
o.hasControls = false
|
|
o.lockMovementX = true
|
|
o.lockMovementY = true
|
|
if (o.type === 'chair' || o.type === 'bar' || o.type === 'wall') {
|
|
o.selectable = false
|
|
}
|
|
o.borderColor = '#38A62E'
|
|
o.borderScaleFactor = 2.5
|
|
})
|
|
canvas.selection = false
|
|
canvas.hoverCursor = 'pointer'
|
|
canvas.discardActiveObject()
|
|
canvas.renderAll()
|
|
document.querySelectorAll('.admin-menu')[0].style.display = 'none'
|
|
document.querySelectorAll('.customer-menu')[0].style.display = 'block'
|
|
});
|
|
|
|
document.querySelectorAll('.admin-mode')[0].addEventListener('click', function() {
|
|
canvas.getObjects().map(o => {
|
|
o.hasControls = true
|
|
o.lockMovementX = false
|
|
o.lockMovementY = false
|
|
if (o.type === 'chair' || o.type === 'bar' || o.type === 'wall') {
|
|
o.selectable = true
|
|
}
|
|
o.borderColor = 'rgba(102, 153, 255, 0.75)'
|
|
o.borderScaleFactor = 1
|
|
})
|
|
canvas.selection = true
|
|
canvas.hoverCursor = 'move'
|
|
canvas.discardActiveObject()
|
|
canvas.renderAll()
|
|
document.querySelectorAll('.admin-menu')[0].style.display = 'block'
|
|
document.querySelectorAll('.customer-menu')[0].style.display = 'none'
|
|
});
|
|
document.querySelectorAll('.submit')[0].addEventListener('click', function() {
|
|
const obj = canvas.getActiveObject()
|
|
$('#modal').modal('show')
|
|
let modalText = 'You have not selected anything'
|
|
if (obj) {
|
|
modalText = 'You have selected table ' + obj.number + ', time: ' + formatTime(slider.noUiSlider.get())
|
|
}
|
|
document.querySelectorAll('#modal-table-id')[0].innerHTML = modalText
|
|
})
|
|
const slider = document.getElementById('slider')
|
|
noUiSlider.create(slider, {
|
|
start: 1200,
|
|
step: 15,
|
|
connect: 'lower',
|
|
range: {
|
|
min: 0,
|
|
max: 1425
|
|
}
|
|
})
|
|
|
|
const sliderValue = document.getElementById('slider-value')
|
|
slider.noUiSlider.on('update', function(values, handle) {
|
|
sliderValue.innerHTML = formatTime(values[handle])
|
|
});
|
|
addDefaultObjects();
|
|
widthEl.addEventListener('change', () => {
|
|
resizeCanvas()
|
|
initCanvas()
|
|
addDefaultObjects()
|
|
})
|
|
heightEl.addEventListener('change', () => {
|
|
resizeCanvas()
|
|
initCanvas()
|
|
addDefaultObjects()
|
|
});
|
|
resizeCanvas();
|
|
});
|
|
|
|
function resizeCanvas() {
|
|
widthEl = document.getElementById('width')
|
|
heightEl = document.getElementById('height')
|
|
canvasEl = document.getElementById('canvas')
|
|
|
|
canvasEl.width = widthEl.value ? widthEl.value : 1024
|
|
canvasEl.height = heightEl.value ? heightEl.value : 812
|
|
const canvasContainerEl = document.querySelectorAll('.canvas-container')[0]
|
|
canvasContainerEl.style.width = canvasEl.width
|
|
canvasContainerEl.style.height = canvasEl.height
|
|
}
|
|
|
|
function generateId() {
|
|
return Math.random().toString(36).substr(2, 8)
|
|
}
|
|
|
|
function addRect(left, top, width, height) {
|
|
const id = generateId()
|
|
const o = new fabric.Rect({
|
|
width: width,
|
|
height: height,
|
|
fill: tableFill,
|
|
stroke: tableStroke,
|
|
strokeWidth: 2,
|
|
shadow: tableShadow,
|
|
originX: 'center',
|
|
originY: 'center',
|
|
centeredRotation: true,
|
|
snapAngle: 45,
|
|
selectable: true
|
|
})
|
|
const t = new fabric.IText(number.toString(), {
|
|
fontFamily: 'Calibri',
|
|
fontSize: 14,
|
|
fill: '#fff',
|
|
textAlign: 'center',
|
|
originX: 'center',
|
|
originY: 'center'
|
|
})
|
|
const g = new fabric.Group([o, t], {
|
|
left: left,
|
|
top: top,
|
|
centeredRotation: true,
|
|
snapAngle: 45,
|
|
selectable: true,
|
|
type: 'table',
|
|
id: id,
|
|
number: number
|
|
})
|
|
canvas.add(g)
|
|
number++
|
|
return g
|
|
}
|
|
|
|
function addCircle(left, top, radius) {
|
|
const id = generateId()
|
|
const o = new fabric.Circle({
|
|
radius: radius,
|
|
fill: tableFill,
|
|
stroke: tableStroke,
|
|
strokeWidth: 2,
|
|
shadow: tableShadow,
|
|
originX: 'center',
|
|
originY: 'center',
|
|
centeredRotation: true
|
|
})
|
|
const t = new fabric.IText(number.toString(), {
|
|
fontFamily: 'Calibri',
|
|
fontSize: 14,
|
|
fill: '#fff',
|
|
textAlign: 'center',
|
|
originX: 'center',
|
|
originY: 'center'
|
|
})
|
|
const g = new fabric.Group([o, t], {
|
|
left: left,
|
|
top: top,
|
|
centeredRotation: true,
|
|
snapAngle: 45,
|
|
selectable: true,
|
|
type: 'table',
|
|
id: id,
|
|
number: number
|
|
})
|
|
canvas.add(g)
|
|
number++
|
|
return g
|
|
}
|
|
|
|
function addTriangle(left, top, radius) {
|
|
const id = generateId()
|
|
const o = new fabric.Triangle({
|
|
radius: radius,
|
|
fill: tableFill,
|
|
stroke: tableStroke,
|
|
strokeWidth: 2,
|
|
shadow: tableShadow,
|
|
originX: 'center',
|
|
originY: 'center',
|
|
centeredRotation: true
|
|
})
|
|
const t = new fabric.IText(number.toString(), {
|
|
fontFamily: 'Calibri',
|
|
fontSize: 14,
|
|
fill: '#fff',
|
|
textAlign: 'center',
|
|
originX: 'center',
|
|
originY: 'center'
|
|
})
|
|
const g = new fabric.Group([o, t], {
|
|
left: left,
|
|
top: top,
|
|
centeredRotation: true,
|
|
snapAngle: 45,
|
|
selectable: true,
|
|
type: 'table',
|
|
id: id,
|
|
number: number
|
|
})
|
|
canvas.add(g)
|
|
number++
|
|
return g
|
|
}
|
|
|
|
function addChair(left, top, width, height) {
|
|
const o = new fabric.Rect({
|
|
left: left,
|
|
top: top,
|
|
width: 30,
|
|
height: 30,
|
|
fill: chairFill,
|
|
stroke: chairStroke,
|
|
strokeWidth: 2,
|
|
shadow: chairShadow,
|
|
originX: 'left',
|
|
originY: 'top',
|
|
centeredRotation: true,
|
|
snapAngle: 45,
|
|
selectable: true,
|
|
type: 'chair',
|
|
id: generateId()
|
|
})
|
|
canvas.add(o)
|
|
return o
|
|
}
|
|
|
|
function addBar(left, top, width, height) {
|
|
const o = new fabric.Rect({
|
|
width: width,
|
|
height: height,
|
|
fill: barFill,
|
|
stroke: barStroke,
|
|
strokeWidth: 2,
|
|
shadow: barShadow,
|
|
originX: 'center',
|
|
originY: 'center',
|
|
type: 'bar',
|
|
id: generateId()
|
|
})
|
|
const t = new fabric.IText(barText, {
|
|
fontFamily: 'Calibri',
|
|
fontSize: 14,
|
|
fill: '#fff',
|
|
textAlign: 'center',
|
|
originX: 'center',
|
|
originY: 'center'
|
|
})
|
|
const g = new fabric.Group([o, t], {
|
|
left: left,
|
|
top: top,
|
|
centeredRotation: true,
|
|
snapAngle: 45,
|
|
selectable: true,
|
|
type: 'bar'
|
|
})
|
|
canvas.add(g)
|
|
return g
|
|
}
|
|
|
|
function addWall(left, top, width, height) {
|
|
const o = new fabric.Rect({
|
|
left: left,
|
|
top: top,
|
|
width: width,
|
|
height: height,
|
|
fill: wallFill,
|
|
stroke: wallStroke,
|
|
strokeWidth: 2,
|
|
shadow: wallShadow,
|
|
originX: 'left',
|
|
originY: 'top',
|
|
centeredRotation: true,
|
|
snapAngle: 45,
|
|
selectable: true,
|
|
type: 'wall',
|
|
id: generateId()
|
|
})
|
|
canvas.add(o)
|
|
return o
|
|
}
|
|
|
|
function snapToGrid(target) {
|
|
target.set({
|
|
left: Math.round(target.left / (grid / 2)) * grid / 2,
|
|
top: Math.round(target.top / (grid / 2)) * grid / 2
|
|
})
|
|
}
|
|
|
|
function checkBoudningBox(e) {
|
|
const obj = e.target
|
|
|
|
if (!obj) {
|
|
return
|
|
}
|
|
obj.setCoords()
|
|
|
|
const objBoundingBox = obj.getBoundingRect()
|
|
if (objBoundingBox.top < 0) {
|
|
obj.set('top', 0)
|
|
obj.setCoords()
|
|
}
|
|
if (objBoundingBox.left > canvas.width - objBoundingBox.width) {
|
|
obj.set('left', canvas.width - objBoundingBox.width)
|
|
obj.setCoords()
|
|
}
|
|
if (objBoundingBox.top > canvas.height - objBoundingBox.height) {
|
|
obj.set('top', canvas.height - objBoundingBox.height)
|
|
obj.setCoords()
|
|
}
|
|
if (objBoundingBox.left < 0) {
|
|
obj.set('left', 0)
|
|
obj.setCoords()
|
|
}
|
|
}
|
|
|
|
function sendLinesToBack() {
|
|
canvas.getObjects().map(o => {
|
|
if (o.type === 'line') {
|
|
canvas.sendToBack(o)
|
|
}
|
|
})
|
|
}
|
|
|
|
|
|
|
|
function formatTime(val) {
|
|
const hours = Math.floor(val / 60)
|
|
const minutes = val % 60
|
|
const englishHours = hours > 12 ? hours - 12 : hours
|
|
|
|
const normal = hours + ':' + minutes + (minutes === 0 ? '0' : '')
|
|
const english = englishHours + ':' + minutes + (minutes === 0 ? '0' : '') + ' ' + (hours > 12 ? 'PM' : 'AM')
|
|
|
|
return normal + ' (' + english + ')'
|
|
}
|
|
|
|
|
|
|
|
function addDefaultObjects() {
|
|
addChair(15, 105)
|
|
addChair(15, 135)
|
|
addChair(75, 105)
|
|
addChair(75, 135)
|
|
addChair(225, 75)
|
|
addChair(255, 75)
|
|
addChair(225, 135)
|
|
addChair(255, 135)
|
|
addChair(225, 195)
|
|
addChair(255, 195)
|
|
addChair(225, 255)
|
|
addChair(255, 255)
|
|
addChair(15, 195)
|
|
addChair(45, 195)
|
|
addChair(15, 255)
|
|
addChair(45, 255)
|
|
addChair(15, 315)
|
|
addChair(45, 315)
|
|
addChair(15, 375)
|
|
addChair(45, 375)
|
|
addChair(225, 315)
|
|
addChair(255, 315)
|
|
addChair(225, 375)
|
|
addChair(255, 375)
|
|
addChair(15, 435)
|
|
addChair(15, 495)
|
|
addChair(15, 555)
|
|
addChair(15, 615)
|
|
addChair(225, 615)
|
|
addChair(255, 615)
|
|
addChair(195, 495)
|
|
addChair(195, 525)
|
|
addChair(255, 495)
|
|
addChair(255, 525)
|
|
addChair(225, 675)
|
|
addChair(255, 675)
|
|
|
|
addRect(30, 90, 60, 90)
|
|
addRect(210, 90, 90, 60)
|
|
addRect(210, 210, 90, 60)
|
|
addRect(0, 210, 90, 60)
|
|
addRect(0, 330, 90, 60)
|
|
addRect(210, 330, 90, 60)
|
|
addRect(0, 450, 60, 60)
|
|
addRect(0, 570, 60, 60)
|
|
addRect(210, 480, 60, 90)
|
|
addRect(210, 630, 90, 60)
|
|
|
|
addBar(120, 0, 180, 60)
|
|
|
|
addWall(120, 510, 60, 60)
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
{% endblock %}
|
|
{% block sonata_page_content %}
|
|
<div class="container-fluid text-center">
|
|
<h1>Gestión de espacios</h1>
|
|
<div class="form-group admin-menu">
|
|
<div class="row">
|
|
<div class="col-sm-2 col-sm-offset-3 form-group">
|
|
<label>Ancho (px)</label>
|
|
<input type="number" id="width" class="form-control" value="1024" />
|
|
</div>
|
|
<div class="col-sm-2 form-group">
|
|
<label>Alto (px)</label>
|
|
<input type="number" id="height" class="form-control" value="812" />
|
|
</div>
|
|
<div class="col-sm-2 form-group">
|
|
<label> </label>
|
|
<br />
|
|
<button class="btn btn-primary">Guardar</button>
|
|
</div>
|
|
</div>
|
|
<div class="btn-group">
|
|
<button class="btn btn-primary rectangle">+ ▯ Mesa</button>
|
|
<button class="btn btn-primary circle">+ ◯ Mesa</button>
|
|
<button class="btn btn-primary triangle">+ △ Mesa</button>
|
|
<button class="btn btn-primary chair">+ Silla</button>
|
|
<button class="btn btn-primary bar">+ Bar</button>
|
|
<button class="btn btn-default wall">+ Muro</button>
|
|
<button class="btn btn-danger remove">Borrar</button>
|
|
<button class="btn btn-warning customer-mode">Modo Reserva</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group customer-menu" style="display: none;">
|
|
<div class="btn-group">
|
|
<button class="btn btn-success submit">Enviar reserva</button>
|
|
<button class="btn btn-warning admin-mode">Modo diseño</button>
|
|
</div>
|
|
<br />
|
|
<br />
|
|
<div id="slider"></div>
|
|
<div id="slider-value"></div>
|
|
</div>
|
|
|
|
<canvas id="canvas" width="1024" height="812"></canvas>
|
|
</div>
|
|
|
|
<div class="modal fade" id="modal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-body text-center">
|
|
<p id="modal-table-id"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock sonata_page_content %}
|