Ngiler SH3LL 360
Home
Information
Create File
Create Folder
:
/
home
/
tbf
/
tbfguest.tbf.ro
/
src
/
views
/
public
/
guests
/
Information Server
MySQL :
OFF
Perl :
OFF
CURL :
ON
WGET :
OFF
PKEXEC :
OFF
Directive
Local Value
IP Address
89.40.16.97
System
Linux server.atelieruldeit.ro 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64
User
tbf
PHP Version
7.3.33
Software
Apache
Doc root
Writable
close
Edit File :
Index.vue
| Size :
33.51
KB
Copy
<template> <div class="min-h-screen flex flex-col h-full"> <div v-if="loaded" class="flex flex-row h-full"> <div id="guestsContainer" class="w-[15rem]"> <!-- <div class="w-[15rem] grid grid-cols-2 gap-2 p-2"> <div v-for="guest in guests" :key="guest.id" class="col-span-1 aspect-square p-4 shadow-lg rounded-lg bg-blue-500 text-center text-white text-sm justify-center flex items-center"> {{ guest.name }} </div> </div> --> </div> <div id="diagramContainer" class="flex-1"></div> </div> <div class="fixed bottom-5 left-[1rem] isola z-20"> <button type="button" class="block text-white rounded-md px-3 py-2 text-sm font-medium bg-blue-500 hover:bg-blue-400" @click="addGuest"> <svg xmlns="http://www.w3.org/2000/svg" height="1.5em" viewBox="0 0 448 512"> <path fill="#FFFFFF" d="M248 72c0-13.3-10.7-24-24-24s-24 10.7-24 24V232H40c-13.3 0-24 10.7-24 24s10.7 24 24 24H200V440c0 13.3 10.7 24 24 24s24-10.7 24-24V280H408c13.3 0 24-10.7 24-24s-10.7-24-24-24H248V72z" /> </svg> </button> </div> <div class="fixed bottom-5 left-[7rem] isola z-20" v-if="selectedGuest"> <button type="button" class="block text-white rounded-md px-3 py-2 text-sm font-medium bg-red-500 hover:bg-red-400" @click="deleteGuest"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"> <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" /> </svg> </button> </div> <div class="fixed bottom-5 left-[10rem] isola z-20" v-if="selectedGuest"> <button type="button" class="block text-white rounded-md px-3 py-2 text-sm font-medium bg-blue-500 hover:bg-blue-400" @click="editGuest"> <svg xmlns="http://www.w3.org/2000/svg" height="1.5em" viewBox="0 0 512 512" fill="currentColor"> <path d="M454.6 45.3l12.1 12.1c12.5 12.5 12.5 32.8 0 45.3L440 129.4 382.6 72l26.7-26.7c12.5-12.5 32.8-12.5 45.3 0zM189 265.6l171-171L417.4 152l-171 171c-4.2 4.2-9.6 7.2-15.4 8.6l-65.6 15.1L180.5 281c1.3-5.8 4.3-11.2 8.6-15.4zm197.7-243L166.4 243c-8.5 8.5-14.4 19.2-17.1 30.9l-20.9 90.6c-1.2 5.4 .4 11 4.3 14.9s9.5 5.5 14.9 4.3l90.6-20.9c11.7-2.7 22.4-8.6 30.9-17.1L489.4 125.3c25-25 25-65.5 0-90.5L477.3 22.6c-25-25-65.5-25-90.5 0zM80 64C35.8 64 0 99.8 0 144V432c0 44.2 35.8 80 80 80H368c44.2 0 80-35.8 80-80V304c0-8.8-7.2-16-16-16s-16 7.2-16 16V432c0 26.5-21.5 48-48 48H80c-26.5 0-48-21.5-48-48V144c0-26.5 21.5-48 48-48H208c8.8 0 16-7.2 16-16s-7.2-16-16-16H80z" /> </svg> </button> </div> <div class="p-16 flex items-center justify-center h-full grow" v-if="!loaded"> <LoadingBigTBF :contentType="contentType" /> </div> </div> </template> <script> import LoadingBigTBF from "@/components/public/LoadingBigTBF.vue"; import go from "gojs"; import { SpecialDraggingTool, HorizontalTextRotatingTool, isPerson } from "@/helpers/guests/core.js"; import { useModalsStore } from "@/stores/modals.js"; var diagram = null; var guests = null; const $ = go.GraphObject.make; const mainElementsNo = 400; export default { inject: ["hideWidget", "onLoad"], components: { LoadingBigTBF, }, data() { return { loaded: false, selectedGuest: null, guestsData: [], // guestsData: [ // { key: "table_1", category: "Chair", name: "1", guests: {}, loc: "102.5 102.5" }, // { key: "table_2", category: "Chair", name: "2", guests: {}, loc: "327.5 102.5" }, // { key: "table_3", category: "Chair", name: "3", guests: {}, loc: "552.5 102.5" }, // { key: "table_4", category: "Chair", name: "4", guests: {}, loc: "777.5 102.5" }, // { key: "table_5", category: "Chair", name: "5", guests: {}, loc: "1002.5 102.5" }, // { key: "table_6", category: "Chair", name: "6", guests: {}, loc: "102.5 327.5" }, // { key: "table_7", category: "Chair", name: "7", guests: {}, loc: "327.5 327.5" }, // { key: "table_8", category: "Chair", name: "8", guests: {}, loc: "552.5 327.5" }, // { key: "table_9", category: "Chair", name: "9", guests: {}, loc: "777.5 327.5" }, // { key: "table_10", category: "Chair", name: "10", guests: {}, loc: "1002.5 327.5" }, // { key: "table_11", category: "Chair", name: "11", guests: {}, loc: "102.5 552.5" }, // { key: "table_12", category: "Chair", name: "12", guests: {}, loc: "327.5 552.5" }, // { key: "table_13", category: "Chair", name: "13", guests: {}, loc: "552.5 552.5" }, // { key: "table_14", category: "Chair", name: "14", guests: {}, loc: "777.5 552.5" }, // { key: "table_15", category: "Chair", name: "15", guests: {}, loc: "1002.5 552.5" }, // { key: "table_16", category: "Chair", name: "16", guests: {}, loc: "102.5 777.5" }, // { key: "table_17", category: "Chair", name: "17", guests: {}, loc: "327.5 777.5" }, // { key: "table_18", category: "Chair", name: "18", guests: {}, loc: "552.5 777.5" }, // { key: "table_19", category: "Chair", name: "19", guests: {}, loc: "777.5 777.5" }, // { key: "table_20", category: "Chair", name: "20", guests: {}, loc: "1002.5 777.5" }, // ], guestsList: [], realTimeModals: useModalsStore(), }; }, watch: { selectedGuest(newValue, oldValue) { if (newValue) { let thisGuest = this.guestsList.find((item) => item.id == newValue); // diagram.selection.each((n) => { // if (isPerson(n)) { // var node = this.guestsList.find((item) => item.id == n.key); // if (thisGuest.invitation_id == node.invitation_id) n.elements.first().stroke = "blue"; // else n.elements.first().stroke = null; // } // }); // guests.selection.each((n) => { // if (isPerson(n)) { // var node = this.guestsList.find((item) => item.id == n.key); // if (thisGuest.invitation_id == node.invitation_id) this.highlightGuest(n); // } // }); diagram.model.nodeDataArray.forEach((n) => { if (isPerson(n)) { var guest = this.guestsList.find((item) => item.id == n.key); var node = diagram.findNodeForKey(n.key); if (thisGuest && guest && thisGuest.invitation_id == guest.invitation_id) node.elements.first().stroke = "#458EF7"; else node.elements.first().stroke = null; } }); guests.model.nodeDataArray.forEach((n) => { if (isPerson(n)) { var guest = this.guestsList.find((item) => item.id == n.key); var node = guests.findNodeForKey(n.key); if (thisGuest && guest && thisGuest.invitation_id == guest.invitation_id) node.elements.first().stroke = "#458EF7"; else node.elements.first().stroke = null; } }); } else { diagram.model.nodeDataArray.forEach((n) => { if (isPerson(n)) { var node = diagram.findNodeForKey(n.key); node.elements.first().stroke = null; } }); guests.model.nodeDataArray.forEach((n) => { if (isPerson(n)) { var node = guests.findNodeForKey(n.key); node.elements.first().stroke = null; } }); } }, }, async mounted() { this.onLoad(() => { this.hideWidget(); }); await this.getGuests(); await this.getDiagramData(); }, methods: { async getGuests() { // this.guestsList = [ // { id: 1, name: "test 1 asdas dsa a", email: "test1@test.ro" }, // { id: 2, name: "test 2", email: "test1@test.ro" }, // { id: 3, name: "test 3", email: "test2@test.ro" }, // { id: 4, name: "test 4", email: "test2@test.ro" }, // { id: 5, name: "test 5", email: "test3@test.ro" }, // { id: 6, name: "test 6", email: "test3@test.ro" }, // { id: 7, name: "test 7", email: "test5@test.ro" }, // { id: 8, name: "test 8", email: "test5@test.ro" }, // ]; // this.loaded = true; await axios .get(`guests`) .then(({ data }) => { this.guestsList = data.data; // this.loaded = true; }) .catch((error) => { var responseError = error.response.data; }) .finally(() => {}); }, async getDiagramData(firstLoad = true) { await axios .get(`guests/arrangement`) .then(({ data }) => { if (data.data.arrangement) { let arrangement = JSON.parse(data.data.arrangement); console.log(arrangement); const seatsPerRow = 20; const seatsInBlock = 7; // numărul de scaune pe rând în bloc mare const seatsInMiddleBlock = 6; // numărul de scaune pe rând în blocul din mijloc const blockHeight = 4; // numărul de rânduri într-un bloc const spacingX = 100; // spațiul între scaune pe X const spacingY = 130; // spațiul între scaune pe Y const blockSpacingX = 143; // spațiul între blocuri pe X const blockSpacingY = 100; // spațiul între blocuri pe Y let tables = Array(mainElementsNo) .fill() .map((_, i) => { const rowNumber = Math.floor(i / seatsPerRow) + 1; const seatNumber = (i % seatsPerRow) + 1; // Determinăm în care bloc major ne aflăm (stânga, mijloc, dreapta) const majorBlock = Math.floor((seatNumber - 1) / (seatsInBlock + seatsInMiddleBlock + seatsInBlock)); // Calculăm poziția în cadrul blocului major const positionInMajorBlock = (seatNumber - 1) % (seatsInBlock + seatsInMiddleBlock + seatsInBlock); let x, y; // Calculăm coordonata Y (comună pentru toate blocurile) const blockSetIndex = Math.floor((rowNumber - 1) / blockHeight); const rowInBlock = (rowNumber - 1) % blockHeight; y = rowInBlock * spacingY + blockSetIndex * (blockHeight * spacingY + blockSpacingY); // Calculăm coordonata X în funcție de bloc if (positionInMajorBlock < seatsInBlock) { // Bloc stânga x = positionInMajorBlock * spacingX; } else if (positionInMajorBlock < seatsInBlock + seatsInMiddleBlock) { // Bloc mijloc x = seatsInBlock * spacingX + blockSpacingX + (positionInMajorBlock - seatsInBlock) * spacingX; } else { // Bloc dreapta x = seatsInBlock * spacingX + blockSpacingX + seatsInMiddleBlock * spacingX + blockSpacingX + (positionInMajorBlock - (seatsInBlock + seatsInMiddleBlock)) * spacingX; } // return arrangement.find((item) => item.key === `seat_R${i}_${i + 1}`) || { key: `seat_R${i}_${i + 1}`, category: "Chair", name: `${i + 1}`, guests: {} }; return ( arrangement.find((item) => item.key === `seat_R${rowNumber}_${seatNumber}`) || { key: `seat_R${rowNumber}_${seatNumber}`, category: "Chair", name: `R${rowNumber}-${seatNumber}`, guests: {}, loc: `${x} ${y}`, } ); }); this.guestsData = [...tables, ...arrangement.filter((item) => isPerson(item))]; } this.loaded = true; if (firstLoad) setTimeout(() => { this.initGo(); }, 100); }) .catch((error) => { var responseError = error.response.data; }) .finally(() => { // this.$emit("processIsLoaded"); }); }, addGuest() { this.realTimeModals.toggleShowModal("modal_add_update_guest", { crud: "create", callback: this.refreshGuestsData }); }, editGuest() { let guest = this.guestsList.find((item) => item.id == this.selectedGuest); if (guest) { let model = { email: guest.email, invitation_id: guest.invitation_id, guests: this.guestsList.filter((item) => item.invitation_id == guest.invitation_id), }; this.realTimeModals.toggleShowModal("modal_add_update_guest", { crud: "update", guest: model, callback: this.refreshDiagramData }); } }, async refreshGuestsData() { this.selectedGuest = null; await this.getGuests(); guests.model.nodeDataArray = this.guestsList .filter((item) => this.guestsData.find((g_item) => g_item.key == item.id) == null) .map((item) => { return { key: item.id, name: item.name }; }); }, async refreshDiagramData(deleted = []) { console.log(deleted); this.selectedGuest = null; await this.refreshGuestsData(); const model = diagram.model; model.nodeDataArray.forEach((n) => { if (isPerson(n)) { if (deleted.includes(n.key)) { // diagram.startTransaction(); this.unassignSeat(n); // var node = diagram.findNodeForKey(n.key); // console.log(node); // diagram.remove(node); // diagram.remove(diagram.findPartForKey(n.key)); // diagram.commitTransaction("deleted node"); // console.log(model.toJson()); } else { let thisGuest = this.guestsList.find((item) => item.id == n.key); if (thisGuest) model.setDataProperty(n, "name", thisGuest.name); } } }); deleted.forEach((item) => { var node = diagram.findNodeForKey(item); if (node) { diagram.startTransaction(); // this.unassignSeat(n); console.log(node); diagram.remove(node); // diagram.remove(diagram.findPartForKey(n.key)); diagram.commitTransaction("deleted node"); } }); // console.log(diagram.model.toJson()); this.saveDiagram(JSON.stringify(diagram.model.nodeDataArray)); }, deleteGuest() { this.realTimeModals.toggleShowModal("modal_confirm_alert", { modal_title: "Ești sigur că dorești să ștergi această invitatie impreuna cu toti invitatii?", modal_description: "Această acțiune este ireversibilă.", call_back: () => { let guest = this.guestsList.find((item) => item.id == this.selectedGuest); if (guest) { axios .delete(`guests/${guest.invitation_id}`) .then(({ data }) => { this.refreshDiagramData(this.guestsList.filter((item) => item.invitation_id == guest.invitation_id).map((item) => item.id)); }) .catch((error) => { var responseError = error.response.data; }) .finally(() => { // this.$emit("processIsLoaded"); }); } }, }); }, saveDiagram(nodeDataArray) { axios .post(`guests/arrangement`, { arrangement: nodeDataArray }) .then(({ data }) => {}) .catch((error) => { var responseError = error.response.data; }) .finally(() => { // this.$emit("processIsLoaded"); }); }, initGo() { diagram = new go.Diagram("diagramContainer", { allowDragOut: true, // to myGuests allowClipboard: false, draggingTool: $(SpecialDraggingTool), rotatingTool: null, //$(HorizontalTextRotatingTool), // For this sample, automatically show the state of the diagram's model on the page ModelChanged: (e) => { if (e.isTransactionFinished) { console.log(diagram.model.toJson()); this.saveDiagram(JSON.stringify(JSON.parse(diagram.model.toJson()).nodeDataArray)); // document.getElementById("savedModel").textContent = diagram.model.toJson(); } }, ChangedSelection: (e) => { if (e.diagram.selection.size > 0) { let item = e.diagram.selection.first(); guests.clearSelection(); if (isPerson(item)) { this.selectedGuest = item.key; } else this.selectedGuest = null; } else { this.selectedGuest = null; } }, "undoManager.isEnabled": true, }); diagram.nodeTemplateMap.add( "", // default template, for people $( go.Node, "Auto", { background: "transparent" }, // in front of all Tables // when selected is in foreground layer new go.Binding("layerName", "isSelected", (s) => (s ? "Foreground" : "")).ofObject(), { locationSpot: go.Spot.Center }, new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding("text", "name"), { // what to do when a drag-over or a drag-drop occurs on a Node representing a table mouseDragEnter: (e, node, prev) => { const dragCopy = node.diagram.toolManager.draggingTool.copiedParts; // could be copied from palette this.highlightSeats(node, dragCopy ? dragCopy : node.diagram.selection, true); }, mouseDragLeave: (e, node, next) => { const dragCopy = node.diagram.toolManager.draggingTool.copiedParts; this.highlightSeats(node, dragCopy ? dragCopy : node.diagram.selection, false); }, mouseDrop: (e, node) => { console.log(node.diagram); this.assignPeopleToSeats(node, node.diagram.selection, e.documentPoint); }, }, $(go.Shape, "Circle", { fill: "blanchedalmond", stroke: null }), $( go.Panel, "Viewbox", { desiredSize: new go.Size(50, 50) }, // new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify), $( go.TextBlock, { desiredSize: new go.Size(50, 50), font: "8pt Verdana, sans-serif", textAlign: "center", verticalAlignment: go.Spot.Center, stroke: "darkblue", }, new go.Binding("text", "", (data) => { let s = data.name; if (data.plus) s += " +" + data.plus.toString(); return s; }), ), ), ), ); diagram.nodeTemplateMap.add( "Chair", // $( go.Node, "Spot", this.chairStyle(), this.Seat(1, "0 0", "0 0"), ), ); diagram.nodeTemplateMap.add( "TableC8", // circular with 8 seats $( go.Node, "Spot", this.tableStyle(), $( go.Panel, "Spot", $( go.Shape, "Circle", { name: "TABLESHAPE", desiredSize: new go.Size(120, 120), fill: "burlywood", stroke: null }, new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify), new go.Binding("fill"), ), $(go.TextBlock, { editable: true, font: "bold 11pt Verdana, sans-serif" }, new go.Binding("text", "name").makeTwoWay(), new go.Binding("angle", "angle", (n) => -n)), ), this.Seat(1, "0.50 0", "0.5 1"), this.Seat(2, "0.85 0.15", "0.15 0.85"), this.Seat(3, "1 0.5", "0 0.5"), this.Seat(4, "0.85 0.85", "0.15 0.15"), this.Seat(5, "0.50 1", "0.5 0"), this.Seat(6, "0.15 0.85", "0.85 0.15"), this.Seat(7, "0 0.5", "1 0.5"), this.Seat(8, "0.15 0.15", "0.85 0.85"), ), ); diagram.nodeTemplateMap.add( "TableC10", // circular with 8 seats $( go.Node, "Spot", this.tableStyle(), $( go.Panel, "Spot", $( go.Shape, "Circle", { name: "TABLESHAPE", desiredSize: new go.Size(210, 210), fill: "burlywood", stroke: null }, new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify), new go.Binding("fill"), ), $(go.TextBlock, { editable: true, font: "bold 11pt Verdana, sans-serif" }, new go.Binding("text", "name").makeTwoWay(), new go.Binding("angle", "angle", (n) => -n)), ), this.Seat(1, "1 0.5"), this.Seat(2, "0.9045 0.7939"), this.Seat(3, "0.6545 0.9755"), this.Seat(4, "0.3455 0.9755"), this.Seat(5, "0.0955 0.7939"), this.Seat(6, "0.0 0.5"), this.Seat(7, "0.0955 0.2061"), this.Seat(8, "0.3455 0.0245"), this.Seat(9, "0.6545 0.0245"), this.Seat(10, "0.9045 0.2061"), ), ); diagram.mouseDrop = (e) => { // when the selection is dropped in the diagram's background, // make sure the selected people no longer belong to any table e.diagram.selection.each((n) => { if (isPerson(n)) { this.unassignSeat(n.data); guests.model.addNodeData(guests.model.copyNodeData(n.data)); } }); if (e.diagram.selection.any(this.isTable)) { return; } e.diagram.disableSelectionDeleted = true; e.diagram.commandHandler.deleteSelection(); e.diagram.disableSelectionDeleted = false; // guests.selection.each((n) => { // if (isPerson(n)) this.unassignSeat(n.data); // }); }; // to simulate a "move" from the Palette, the source Node must be deleted. diagram.addDiagramListener("ExternalObjectsDropped", (e) => { // if any Tables were dropped, don't delete from myGuests if (!e.subject.any(this.isTable)) { guests.commandHandler.deleteSelection(); } }); // put deleted people back in the myGuests diagram diagram.addDiagramListener("SelectionDeleted", (e) => { // no-op if deleted by myGuests' ExternalObjectsDropped listener if (diagram.disableSelectionDeleted) return; // e.subject is the myDiagram.selection collection e.subject.each((n) => { if (isPerson(n)) { guests.model.addNodeData(guests.model.copyNodeData(n.data)); } }); }); // create some initial tables diagram.model = new go.GraphLinksModel( this.guestsData, // Array(40) // .fill() // .map((_, i) => { // return this.guestsData.find((item) => item.key === `table_${i + 1}`) || { key: `table_${i + 1}`, category: "TableC8", name: `${i + 1}`, guests: {} }; // }), ); // this sample does not make use of any links // initialize the Palette guests = new go.Diagram("guestsContainer", { layout: $(go.GridLayout, { sorting: go.GridLayout.Ascending, // sort by Node.text value }), allowDragOut: true, // to myDiagram allowMove: false, ChangedSelection: (e) => { if (e.diagram.selection.size > 0) { diagram.clearSelection(); this.selectedGuest = e.diagram.selection.first().key; } else { this.selectedGuest = null; } }, }); guests.nodeTemplateMap = diagram.nodeTemplateMap; // specify the contents of the Palette guests.model = new go.GraphLinksModel( this.guestsList .filter((item) => this.guestsData.find((g_item) => g_item.key == item.id) == null) .map((item) => { return { key: item.id, name: item.name }; }), ); guests.model.undoManager = diagram.model.undoManager; // shared UndoManager! // To simulate a "move" from the Diagram back to the Palette, the source Node must be deleted. guests.addDiagramListener("ExternalObjectsDropped", (e) => { // e.subject is the myGuests.selection collection // if the user dragged a Table to the myGuests diagram, cancel the drag if (e.subject.any(this.isTable)) { diagram.currentTool.doCancel(); guests.currentTool.doCancel(); return; } diagram.selection.each((n) => { if (isPerson(n)) this.unassignSeat(n.data); }); diagram.disableSelectionDeleted = true; diagram.commandHandler.deleteSelection(); diagram.disableSelectionDeleted = false; guests.selection.each((n) => { if (isPerson(n)) this.unassignSeat(n.data); }); }); go.AnimationManager.defineAnimationEffect("location", (obj, startValue, endValue, easing, currentTime, duration, animationState) => { obj.location = new go.Point(easing(currentTime, startValue.x, endValue.x - startValue.x, duration), easing(currentTime, startValue.y, endValue.y - startValue.y, duration)); }); }, tableStyle() { return [ { background: "transparent" }, { layerName: "Background" }, // behind all Persons { locationSpot: go.Spot.Center, locationObjectName: "TABLESHAPE" }, new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), { rotatable: true }, new go.Binding("angle").makeTwoWay(), { // what to do when a drag-over or a drag-drop occurs on a Node representing a table mouseDragEnter: (e, node, prev) => { const dragCopy = node.diagram.toolManager.draggingTool.copiedParts; // could be copied from palette this.highlightSeats(node, dragCopy ? dragCopy : node.diagram.selection, true); }, mouseDragLeave: (e, node, next) => { const dragCopy = node.diagram.toolManager.draggingTool.copiedParts; this.highlightSeats(node, dragCopy ? dragCopy : node.diagram.selection, false); }, mouseDrop: (e, node) => this.assignPeopleToSeats(node, node.diagram.selection, e.documentPoint), }, ]; }, chairStyle() { return [ { background: "transparent" }, { layerName: "Background" }, // behind all Persons { locationSpot: go.Spot.Center, locationObjectName: "TABLESHAPE" }, new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), { rotatable: true }, new go.Binding("angle").makeTwoWay(), { // what to do when a drag-over or a drag-drop occurs on a Node representing a table mouseDragEnter: (e, node, prev) => { const dragCopy = node.diagram.toolManager.draggingTool.copiedParts; // could be copied from palette this.highlightSeats(node, dragCopy ? dragCopy : node.diagram.selection, true); }, mouseDragLeave: (e, node, next) => { const dragCopy = node.diagram.toolManager.draggingTool.copiedParts; this.highlightSeats(node, dragCopy ? dragCopy : node.diagram.selection, false); }, mouseDrop: (e, node) => this.assignPeopleToSeats(node, node.diagram.selection, e.documentPoint), }, ]; }, Seat(number, align, focus) { if (typeof align === "string") align = go.Spot.parse(align); if (!align || !align.isSpot()) align = go.Spot.Right; if (typeof focus === "string") focus = go.Spot.parse(focus); if (!focus || !focus.isSpot()) focus = align.opposite(); return $( go.Panel, "Spot", { name: number.toString(), alignment: align, alignmentFocus: focus }, $(go.Shape, "Circle", { name: "SEATSHAPE", desiredSize: new go.Size(70, 70), fill: "burlywood", stroke: "white", strokeWidth: 2 }, new go.Binding("fill")), // $(go.TextBlock, number.toString(), { font: "10pt Verdana, sans-serif" }, new go.Binding("angle", "angle", (n) => -n)), $(go.TextBlock, { font: "bold 11pt Verdana, sans-serif" }, new go.Binding("text", "name").makeTwoWay(), new go.Binding("angle", "angle", (n) => -n)), ); }, isTable(n) { return n !== null && n.category !== ""; }, // Highlight the empty and occupied seats at a "Table" Node highlightSeats(node, coll, show) { if (isPerson(node)) { // refer to the person's table instead node = node.diagram.findNodeForKey(node.data.table); if (node === null) return; } const it = coll.iterator; while (it.next()) { const n = it.key; // if dragging a Table, don't do any highlighting if (this.isTable(n)) return; } const guests = node.data.guests; for (const sit = node.elements; sit.next(); ) { const seat = sit.value; if (seat.name) { const num = parseFloat(seat.name); if (isNaN(num)) continue; const seatshape = seat.findObject("SEATSHAPE"); if (!seatshape) continue; if (show) { if (guests[seat.name]) { seatshape.stroke = "red"; } else { seatshape.stroke = "green"; } } else { seatshape.stroke = "white"; } } } }, highlightGuest(node) { if (isPerson(node)) { for (const guest = node.elements; guest.next(); ) { console.log(guest.value); guest.value.stroke = "pink"; // const seat = guest.value.findObject("SEATSHAPE"); // if (seat.name) { // const num = parseFloat(seat.name); // if (isNaN(num)) continue; // const seatshape = seat.findObject("SEATSHAPE"); // if (!seatshape) continue; // if (show) { // if (guests[seat.name]) { // seatshape.stroke = "red"; // } else { // seatshape.stroke = "green"; // } // } else { // seatshape.stroke = "white"; // } // } } } }, // Given a "Table" Node, assign seats for all of the people in the given collection of Nodes; // the optional Point argument indicates where the collection of people may have been dropped. assignPeopleToSeats(node, coll, pt) { if (isPerson(node)) { // refer to the person's table instead node = node.diagram.findNodeForKey(node.data.table); if (node === null) return; } if (coll.any(this.isTable)) { // if dragging a Table, don't allow it to be dropped onto another table diagram.currentTool.doCancel(); return; } // OK -- all Nodes are people, call assignSeat on each person data coll.each((n) => this.assignSeat(node, n.data, pt)); this.positionPeopleAtSeats(node); }, // Given a "Table" Node, assign one guest data to a seat at that table. // Also handles cases where the guest represents multiple people, because guest.plus > 0. // This tries to assign the unoccupied seat that is closest to the given point in document coordinates. assignSeat(node, guest, pt) { if (isPerson(node)) { // refer to the person's table instead node = node.diagram.findNodeForKey(node.data.table); if (node === null) return; } if (guest instanceof go.GraphObject) throw Error("A guest object must not be a GraphObject: " + guest.toString()); if (!(pt instanceof go.Point)) pt = node.location; // in case the guest used to be assigned to a different seat, perhaps at a different table this.unassignSeat(guest); const model = node.diagram.model; const guests = node.data.guests; // iterate over all seats in the Node to find one that is not occupied const closestseatname = this.findClosestUnoccupiedSeat(node, pt); if (closestseatname) { model.setDataProperty(guests, closestseatname, guest.key); model.setDataProperty(guest, "table", node.data.key); model.setDataProperty(guest, "seat", parseFloat(closestseatname)); } const plus = guest.plus; if (plus) { // represents several people // forget the "plus" info, since next we create N copies of the node/data guest.plus = undefined; model.updateTargetBindings(guest); for (let i = 0; i < plus; i++) { const copy = model.copyNodeData(guest); // don't copy the seat assignment of the first person copy.table = undefined; copy.seat = undefined; model.addNodeData(copy); this.assignSeat(node, copy, pt); } } }, // Declare that the guest represented by the data is no longer assigned to a seat at a table. // If the guest had been at a table, the guest is removed from the table's list of guests. unassignSeat(guest) { if (guest instanceof go.GraphObject) throw Error("A guest object must not be a GraphObject: " + guest.toString()); const model = diagram.model; // remove from any table that the guest is assigned to if (guest.table) { const table = model.findNodeDataForKey(guest.table); if (table) { const guests = table.guests; if (guests) model.setDataProperty(guests, guest.seat.toString(), undefined); } } model.setDataProperty(guest, "table", undefined); model.setDataProperty(guest, "seat", undefined); }, // Find the name of the unoccupied seat that is closest to the given Point. // This returns null if no seat is available at this table. findClosestUnoccupiedSeat(node, pt) { if (isPerson(node)) { // refer to the person's table instead node = node.diagram.findNodeForKey(node.data.table); if (node === null) return; } const guests = node.data.guests; let closestseatname = null; let closestseatdist = Infinity; // iterate over all seats in the Node to find one that is not occupied for (const sit = node.elements; sit.next(); ) { const seat = sit.value; if (seat.name) { const num = parseFloat(seat.name); if (isNaN(num)) continue; // not really a "seat" if (guests[seat.name]) continue; // already assigned const seatloc = seat.getDocumentPoint(go.Spot.Center); const seatdist = seatloc.distanceSquaredPoint(pt); if (seatdist < closestseatdist) { closestseatdist = seatdist; closestseatname = seat.name; } } } return closestseatname; }, // Position the nodes of all of the guests that are seated at this table // to be at their corresponding seat elements of the given "Table" Node. positionPeopleAtSeats(node) { if (isPerson(node)) { // refer to the person's table instead node = node.diagram.findNodeForKey(node.data.table); if (node === null) return; } const guests = node.data.guests; const model = node.diagram.model; for (let seatname in guests) { const guestkey = guests[seatname]; const guestdata = model.findNodeDataForKey(guestkey); this.positionPersonAtSeat(guestdata); } }, // Position a single guest Node to be at the location of the seat to which they are assigned. positionPersonAtSeat(guest) { if (guest instanceof go.GraphObject) throw Error("A guest object must not be a GraphObject: " + guest.toString()); if (!guest || !guest.table || !guest.seat) return; const table = diagram.findPartForKey(guest.table); const person = diagram.findPartForData(guest); const model = diagram.model; if (table && person) { const seat = table.findObject(guest.seat.toString()); const loc = seat.getDocumentPoint(go.Spot.Center); model.setDataProperty(guest, "loc", `${loc.x} ${loc.y}`); // animate movement, instead of: person.location = loc; const animation = new go.Animation(); animation.add(person, "location", person.location, loc); // animation.add(person, "width", 50, 40); // animation.add(person, "height", 50, 40); animation.start(); } }, }, }; </script>
Back