Added improvements to advanced rail system components.
This commit is contained in:
parent
3c9554ebba
commit
cb8eed835a
|
@ -0,0 +1,166 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1280"
|
||||||
|
height="640"
|
||||||
|
viewBox="0 0 338.66666 169.33334"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||||
|
sodipodi:docname="banner.svg"
|
||||||
|
inkscape:export-filename="/home/andrew/Pictures/railsignalbanner.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="-19.654761 : -18.142858 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="338.66666 : 84.66667 : 1"
|
||||||
|
inkscape:persp3d-origin="169.33333 : 56.444447 : 1"
|
||||||
|
id="perspective815" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.7"
|
||||||
|
inkscape:cx="845.17179"
|
||||||
|
inkscape:cy="205.3419"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1009"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-127.66666)">
|
||||||
|
<rect
|
||||||
|
style="fill:#659a54;fill-opacity:1;stroke:none;stroke-width:12.70000076;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect870"
|
||||||
|
width="338.66666"
|
||||||
|
height="169.33333"
|
||||||
|
x="0"
|
||||||
|
y="127.66666" />
|
||||||
|
<rect
|
||||||
|
style="fill:#454e44;fill-opacity:1;stroke:none;stroke-width:12.70000076;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect911"
|
||||||
|
width="338.66666"
|
||||||
|
height="111.125"
|
||||||
|
x="-1.110223e-16"
|
||||||
|
y="185.875" />
|
||||||
|
<g
|
||||||
|
id="g852"
|
||||||
|
transform="rotate(90,151.19047,228.96429)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path835"
|
||||||
|
d="m 122.84226,146.37648 h 92.98215"
|
||||||
|
style="fill:none;stroke:#4a2b00;stroke-width:12.69999981;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#4a2b00;stroke-width:12.69999981;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 122.84226,212.9003 h 92.98215"
|
||||||
|
id="path837"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path839"
|
||||||
|
d="m 122.84226,246.1622 h 92.98215"
|
||||||
|
style="fill:none;stroke:#4a2b00;stroke-width:12.69999981;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#4a2b00;stroke-width:12.69999981;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 122.84226,179.63839 h 92.98215"
|
||||||
|
id="path841"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path843"
|
||||||
|
d="m 122.84226,279.42411 h 92.98215"
|
||||||
|
style="fill:none;stroke:#4a2b00;stroke-width:12.69999981;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path831"
|
||||||
|
d="M 148.35565,291.70833 V 129.93452"
|
||||||
|
style="fill:none;stroke:#989898;stroke-width:8.46666718;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#989898;stroke-width:8.46666718;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 190.31102,291.70833 V 129.93452"
|
||||||
|
id="path833"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<flowRoot
|
||||||
|
xml:space="preserve"
|
||||||
|
id="flowRoot913"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:#102f07;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
transform="matrix(0.57599614,0,0,0.57599614,-10.203222,101.60397)"><flowRegion
|
||||||
|
id="flowRegion915"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#102f07;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"><rect
|
||||||
|
id="rect917"
|
||||||
|
width="1102.8572"
|
||||||
|
height="162.85715"
|
||||||
|
x="51.42857"
|
||||||
|
y="34.285713"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#102f07;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /></flowRegion><flowPara
|
||||||
|
id="flowPara919"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:96px;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono Bold';stroke:#102f07;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">Rail Signal</flowPara></flowRoot> <g
|
||||||
|
id="g933"
|
||||||
|
transform="translate(123.59822)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path921"
|
||||||
|
d="m 169.33333,245.97321 v 46.49107"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:16.93333435;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<rect
|
||||||
|
ry="2.6458333"
|
||||||
|
rx="2.6458333"
|
||||||
|
y="196.08035"
|
||||||
|
x="152.13544"
|
||||||
|
height="51.026794"
|
||||||
|
width="34.395802"
|
||||||
|
id="rect923"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:#bababa;stroke-width:4.23333359;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<circle
|
||||||
|
r="6.0476193"
|
||||||
|
cy="212.33333"
|
||||||
|
cx="169.33333"
|
||||||
|
id="path925"
|
||||||
|
style="fill:#1cd500;fill-opacity:1;stroke:none;stroke-width:8.46666718;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<circle
|
||||||
|
style="fill:#d50000;fill-opacity:1;stroke:none;stroke-width:8.46666718;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="circle927"
|
||||||
|
cx="169.33333"
|
||||||
|
cy="228.5863"
|
||||||
|
r="6.0476193" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.2 KiB |
|
@ -98,6 +98,18 @@ export function removeComponent(rs, id) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function updateComponent(rs, component) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios.patch(`${API_URL}/rs/${rs.id}/c/${component.id}`, component)
|
||||||
|
.then(() => {
|
||||||
|
refreshComponents(rs)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject);
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function updateSwitchConfiguration(rs, sw, configId) {
|
export function updateSwitchConfiguration(rs, sw, configId) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios.post(
|
axios.post(
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function removeRailSystem(rsStore, id) {
|
||||||
axios.delete(`${API_URL}/rs/${id}`)
|
axios.delete(`${API_URL}/rs/${id}`)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (rsStore.selectedRailSystem !== null && rsStore.selectedRailSystem.id === id) {
|
if (rsStore.selectedRailSystem !== null && rsStore.selectedRailSystem.id === id) {
|
||||||
rsStore.selectRailSystem(null);
|
rsStore.selectedRailSystem = null;
|
||||||
}
|
}
|
||||||
refreshRailSystems(rsStore)
|
refreshRailSystems(rsStore)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8" id="railSystemMapCanvasContainer">
|
<div class="col-md-8" id="railSystemMapCanvasContainer">
|
||||||
<canvas id="railSystemMapCanvas" height="800">
|
<canvas id="railSystemMapCanvas" height="600">
|
||||||
Your browser doesn't support canvas.
|
Your browser doesn't support canvas.
|
||||||
</canvas>
|
</canvas>
|
||||||
</div>
|
</div>
|
||||||
<q-scroll-area class="col-md-4" v-if="railSystem.selectedComponents.length > 0">
|
<q-scroll-area class="col-md-4" v-if="railSystem.selectedComponents.length > 0">
|
||||||
<div class="row" v-for="component in railSystem.selectedComponents" :key="component.id">
|
<div class="row" v-for="component in railSystem.selectedComponents" :key="component.id">
|
||||||
<div class="col full-width">
|
<div class="col full-width">
|
||||||
<selected-component-view :component="component" :rail-system="railSystem" />
|
<selected-component-view :component="component"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -182,7 +182,6 @@ import { RailSystem } from "src/api/railSystems";
|
||||||
import {draw, initMap} from "src/render/mapRenderer";
|
import {draw, initMap} from "src/render/mapRenderer";
|
||||||
import SelectedComponentView from "components/rs/SelectedComponentView.vue";
|
import SelectedComponentView from "components/rs/SelectedComponentView.vue";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
import { createComponent } from "src/api/components";
|
|
||||||
import AddComponentDialog from "components/rs/add_component/AddComponentDialog.vue";
|
import AddComponentDialog from "components/rs/add_component/AddComponentDialog.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -1,184 +1,37 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="q-pa-md">
|
<label-component-view
|
||||||
<div class="text-h6">{{component.name}}</div>
|
:label="component"
|
||||||
<q-list bordered>
|
v-if="component.type === 'LABEL'"
|
||||||
<q-item clickable>
|
/>
|
||||||
<q-item-section>
|
<signal-component-view
|
||||||
<q-item-label>{{component.type}}</q-item-label>
|
:signal="component"
|
||||||
<q-item-label caption>Id: {{component.id}}</q-item-label>
|
v-if="component.type === 'SIGNAL'"
|
||||||
</q-item-section>
|
/>
|
||||||
<q-item-section v-if="component.online === true" top side>
|
<segment-boundary-component-view
|
||||||
<q-chip color="positive" text-color="white">Online</q-chip>
|
:segment-boundary="component"
|
||||||
</q-item-section>
|
v-if="component.type === 'SEGMENT_BOUNDARY'"
|
||||||
<q-item-section v-if="component.online === false" top side>
|
/>
|
||||||
<q-chip color="negative" text-color="white">Offline</q-chip>
|
<switch-component-view
|
||||||
</q-item-section>
|
:sw="component"
|
||||||
</q-item>
|
v-if="component.type === 'SWITCH'"
|
||||||
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>Position</q-item-label>
|
|
||||||
<q-item-label caption>
|
|
||||||
X: {{component.position.x}},
|
|
||||||
Y: {{component.position.y}},
|
|
||||||
Z: {{component.position.z}}
|
|
||||||
</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
|
|
||||||
<!-- Signal info -->
|
|
||||||
<q-expansion-item
|
|
||||||
id="signalInfo"
|
|
||||||
label="Signal Information"
|
|
||||||
v-if="component.type === 'SIGNAL'"
|
|
||||||
:content-inset-level="0.5"
|
|
||||||
switch-toggle-side
|
|
||||||
expand-separator
|
|
||||||
>
|
|
||||||
<q-list>
|
|
||||||
<segment-list-item v-for="segment in [component.segment]" :key="segment.id" :segment="segment" />
|
|
||||||
</q-list>
|
|
||||||
</q-expansion-item>
|
|
||||||
|
|
||||||
<!-- Path node info -->
|
|
||||||
<q-expansion-item
|
|
||||||
label="Connected Nodes"
|
|
||||||
v-if="component.connectedNodes !== undefined && component.connectedNodes !== null"
|
|
||||||
:content-inset-level="0.5"
|
|
||||||
switch-toggle-side
|
|
||||||
expand-separator
|
|
||||||
class="q-gutter-md"
|
|
||||||
>
|
|
||||||
<q-list>
|
|
||||||
<q-item
|
|
||||||
v-for="node in component.connectedNodes"
|
|
||||||
:key="node.id"
|
|
||||||
clickable
|
|
||||||
v-ripple
|
|
||||||
@click="select(node)"
|
|
||||||
>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>{{node.name}}</q-item-label>
|
|
||||||
<q-item-label caption>Id: {{node.id}}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-expansion-item>
|
|
||||||
|
|
||||||
<!-- Segment boundary info -->
|
|
||||||
<q-expansion-item
|
|
||||||
label="Connected Segments"
|
|
||||||
v-if="component.type === 'SEGMENT_BOUNDARY'"
|
|
||||||
:content-inset-level="0.5"
|
|
||||||
switch-toggle-side
|
|
||||||
expand-separator
|
|
||||||
>
|
|
||||||
<q-list>
|
|
||||||
<segment-list-item v-for="segment in component.segments" :key="segment.id" :segment="segment"/>
|
|
||||||
</q-list>
|
|
||||||
</q-expansion-item>
|
|
||||||
|
|
||||||
<!-- Switch info -->
|
|
||||||
<q-expansion-item
|
|
||||||
label="Switch Information"
|
|
||||||
v-if="component.type === 'SWITCH'"
|
|
||||||
:content-inset-level="0.5"
|
|
||||||
switch-toggle-side
|
|
||||||
expand-separator
|
|
||||||
>
|
|
||||||
<q-list>
|
|
||||||
<q-item
|
|
||||||
v-for="config in component.possibleConfigurations"
|
|
||||||
:key="config.id"
|
|
||||||
>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label class="q-gutter-sm">
|
|
||||||
<q-chip
|
|
||||||
v-for="node in config.nodes"
|
|
||||||
:key="node.id"
|
|
||||||
dense
|
|
||||||
size="sm"
|
|
||||||
:label="node.name"
|
|
||||||
clickable
|
|
||||||
@click="select(node)"
|
|
||||||
/>
|
/>
|
||||||
</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section v-if="component.activeConfiguration === null || component.activeConfiguration.id !== config.id" side>
|
|
||||||
<q-btn dense size="sm" color="positive" @click="setActiveSwitchConfig(component, config.id)">Set Active</q-btn>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-expansion-item>
|
|
||||||
|
|
||||||
<q-item>
|
|
||||||
<q-item-section side>
|
|
||||||
<q-btn color="warning" label="Remove" size="sm" @click="remove(component)"/>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { RailSystem } from "src/api/railSystems";
|
import SignalComponentView from "components/rs/component_views/SignalComponentView.vue";
|
||||||
import { useRailSystemsStore } from "stores/railSystemsStore";
|
import SegmentBoundaryComponentView from "components/rs/component_views/SegmentBoundaryComponentView.vue";
|
||||||
import SegmentListItem from "components/rs/SegmentListItem.vue";
|
import LabelComponentView from "components/rs/component_views/LabelComponentView.vue";
|
||||||
import { useQuasar } from "quasar";
|
import SwitchComponentView from "components/rs/component_views/SwitchComponentView.vue";
|
||||||
import { removeComponent, updateSwitchConfiguration } from "src/api/components";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "SelectedComponentView",
|
name: "SelectedComponentView",
|
||||||
components: { SegmentListItem },
|
components: {
|
||||||
setup() {
|
SwitchComponentView,
|
||||||
const rsStore = useRailSystemsStore();
|
LabelComponentView, SegmentBoundaryComponentView, SignalComponentView },
|
||||||
const quasar = useQuasar();
|
|
||||||
return {rsStore, quasar};
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
component: {
|
component: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
|
||||||
railSystem: {
|
|
||||||
type: RailSystem,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
select(component) {
|
|
||||||
const c = this.rsStore.selectedRailSystem.components.find(cp => cp.id === component.id);
|
|
||||||
if (c) {
|
|
||||||
this.rsStore.selectedRailSystem.selectedComponents.length = 0;
|
|
||||||
this.rsStore.selectedRailSystem.selectedComponents.push(c);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
remove(component) {
|
|
||||||
this.quasar.dialog({
|
|
||||||
title: "Confirm Removal",
|
|
||||||
message: "Are you sure you want to remove this component? This cannot be undone.",
|
|
||||||
cancel: true
|
|
||||||
}).onOk(() => {
|
|
||||||
removeComponent(this.railSystem, component.id)
|
|
||||||
.then(() => {
|
|
||||||
this.quasar.notify({
|
|
||||||
color: "positive",
|
|
||||||
message: "Component has been removed."
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
this.quasar.notify({
|
|
||||||
color: "negative",
|
|
||||||
message: "An error occurred: " + error.response.data.message
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
setActiveSwitchConfig(sw, configId) {
|
|
||||||
updateSwitchConfiguration(this.railSystem, sw, configId);
|
|
||||||
},
|
|
||||||
isConfigActive(sw, config) {
|
|
||||||
return sw.activeConfiguration !== null && sw.activeConfiguration.id === config.id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
<template>
|
||||||
|
<div class="q-pa-md">
|
||||||
|
<div class="text-h6">{{component.name}}</div>
|
||||||
|
<q-list bordered>
|
||||||
|
<q-item clickable>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{component.type}}</q-item-label>
|
||||||
|
<q-item-label caption>Id: {{component.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section v-if="component.online === true" top side>
|
||||||
|
<q-chip color="positive" text-color="white">Online</q-chip>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section v-if="component.online === false" top side>
|
||||||
|
<q-chip color="negative" text-color="white">Offline</q-chip>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item clickable>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Position</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
X: {{component.position.x}},
|
||||||
|
Y: {{component.position.y}},
|
||||||
|
Z: {{component.position.z}}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-separator/>
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
|
<q-item>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-btn color="negative" label="Remove" size="sm" @click="remove(component)"/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {removeComponent} from "src/api/components";
|
||||||
|
import {useQuasar} from "quasar";
|
||||||
|
import {useRailSystemsStore} from "stores/railSystemsStore";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "BaseComponentView",
|
||||||
|
props: {
|
||||||
|
component: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const rsStore = useRailSystemsStore();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
return {rsStore, quasar};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
select(component) {
|
||||||
|
const c = this.rsStore.selectedRailSystem.components.find(cp => cp.id === component.id);
|
||||||
|
if (c) {
|
||||||
|
this.rsStore.selectedRailSystem.selectedComponents.length = 0;
|
||||||
|
this.rsStore.selectedRailSystem.selectedComponents.push(c);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
remove(component) {
|
||||||
|
this.quasar.dialog({
|
||||||
|
title: "Confirm Removal",
|
||||||
|
message: "Are you sure you want to remove this component? This cannot be undone.",
|
||||||
|
cancel: true
|
||||||
|
}).onOk(() => {
|
||||||
|
removeComponent(this.railSystem, component.id)
|
||||||
|
.then(() => {
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "positive",
|
||||||
|
message: "Component has been removed."
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "negative",
|
||||||
|
message: "An error occurred: " + error.response.data.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<base-component-view :component="label">
|
||||||
|
<q-item-label header>Label</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{label.text}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</base-component-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BaseComponentView from "components/rs/component_views/BaseComponentView.vue";
|
||||||
|
export default {
|
||||||
|
name: "LabelComponentView",
|
||||||
|
components: {BaseComponentView},
|
||||||
|
props: {
|
||||||
|
label: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,125 @@
|
||||||
|
<template>
|
||||||
|
<q-item-label header>Connected Path Nodes</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label class="q-gutter-sm">
|
||||||
|
<q-chip
|
||||||
|
v-for="node in pathNode.connectedNodes"
|
||||||
|
:key="node.id"
|
||||||
|
dense
|
||||||
|
size="sm"
|
||||||
|
:label="node.name"
|
||||||
|
/>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense v-if="editable">
|
||||||
|
<q-btn size="sm" color="accent" label="Edit Connected Nodes" @click="showDialog"/>
|
||||||
|
<q-dialog v-model="dialog.visible" style="min-width: 400px" @hide="reset">
|
||||||
|
<q-card>
|
||||||
|
<q-form @submit="onSubmit" @reset="reset">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h6">Edit Connected Nodes</div>
|
||||||
|
<p>
|
||||||
|
Update the nodes that this path node is connected to. These
|
||||||
|
connections define how the system understands your rail network,
|
||||||
|
and are used for routing and analytics.
|
||||||
|
</p>
|
||||||
|
<p v-if="pathNode.type ==='SEGMENT_BOUNDARY'">
|
||||||
|
You're editing a <strong>segment boundary</strong> node. This
|
||||||
|
means that you can only have at most <strong>2</strong> nodes
|
||||||
|
connected to it.
|
||||||
|
</p>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<q-select
|
||||||
|
v-model="dialog.selectedNodes"
|
||||||
|
:options="getEligibleNodes()"
|
||||||
|
multiple
|
||||||
|
:option-value="node => node"
|
||||||
|
:option-label="node => node.name"
|
||||||
|
use-chips
|
||||||
|
stack-label
|
||||||
|
label="Nodes"
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions align="right" class="text-primary">
|
||||||
|
<q-btn flat label="Cancel" type="reset" @click="dialog.visible = false"/>
|
||||||
|
<q-btn flat label="Edit" type="submit"/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-form>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {useRailSystemsStore} from "stores/railSystemsStore";
|
||||||
|
import {useQuasar} from "quasar";
|
||||||
|
import {updateComponent} from "src/api/components";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "PathNodeItem",
|
||||||
|
props: {
|
||||||
|
pathNode: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
editable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const rsStore = useRailSystemsStore();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
return {rsStore, quasar};
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialog: {
|
||||||
|
visible: false,
|
||||||
|
selectedNodes: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showDialog() {
|
||||||
|
this.dialog.selectedNodes = this.pathNode.connectedNodes.slice();
|
||||||
|
this.dialog.visible = true;
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
this.dialog.selectedNodes.length = 0;
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
const data = {...this.pathNode};
|
||||||
|
data.connectedNodes = this.dialog.selectedNodes;
|
||||||
|
updateComponent(this.rsStore.selectedRailSystem, data)
|
||||||
|
.then(() => {
|
||||||
|
this.dialog.visible = false;
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "positive",
|
||||||
|
message: "Path node updated."
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "negative",
|
||||||
|
message: "An error occurred: " + error.response.data.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getEligibleNodes() {
|
||||||
|
return this.rsStore.selectedRailSystem.components.filter(c => {
|
||||||
|
return (c.connectedNodes !== null && c.connectedNodes !== undefined) &&
|
||||||
|
this.dialog.selectedNodes.findIndex(node => node.id === c.id) === -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<base-component-view :component="segmentBoundary">
|
||||||
|
<q-item-label header>Connected Segments</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section
|
||||||
|
v-for="segment in segmentBoundary.segments"
|
||||||
|
:key="segment.id"
|
||||||
|
>
|
||||||
|
<q-item-label>{{segment.name}}</q-item-label>
|
||||||
|
<q-item-label caption>ID: {{segment.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-separator/>
|
||||||
|
<path-node-item :path-node="segmentBoundary" :editable="true"/>
|
||||||
|
</base-component-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BaseComponentView from "components/rs/component_views/BaseComponentView.vue";
|
||||||
|
import PathNodeItem from "components/rs/component_views/PathNodeItem.vue";
|
||||||
|
export default {
|
||||||
|
name: "SegmentBoundaryComponentView",
|
||||||
|
components: {PathNodeItem, BaseComponentView},
|
||||||
|
props: {
|
||||||
|
segmentBoundary: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<template>
|
||||||
|
<base-component-view :component="signal">
|
||||||
|
<q-item-label header>Connected to Segment</q-item-label>
|
||||||
|
<segment-list-item :segment="signal.segment"/>
|
||||||
|
</base-component-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BaseComponentView from "components/rs/component_views/BaseComponentView.vue";
|
||||||
|
import SegmentListItem from "components/rs/SegmentListItem.vue";
|
||||||
|
export default {
|
||||||
|
name: "SignalComponentView",
|
||||||
|
components: {SegmentListItem, BaseComponentView},
|
||||||
|
props: {
|
||||||
|
signal: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,200 @@
|
||||||
|
<template>
|
||||||
|
<base-component-view :component="sw">
|
||||||
|
<q-item-label header>Switch Configurations</q-item-label>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="config in sw.possibleConfigurations"
|
||||||
|
:key="config.id"
|
||||||
|
dense
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label class="q-gutter-sm">
|
||||||
|
<q-chip
|
||||||
|
v-for="node in config.nodes"
|
||||||
|
:key="node.id"
|
||||||
|
dense
|
||||||
|
size="sm"
|
||||||
|
:label="node.name"
|
||||||
|
clickable
|
||||||
|
/>
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label caption>Configuration #{{config.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section v-if="!isConfigActive(config)" side top>
|
||||||
|
<q-btn dense size="sm" color="positive" @click="setActiveSwitchConfig(config.id)">Set Active</q-btn>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-btn size="sm" color="accent" label="Edit Configurations" @click="showDialog"/>
|
||||||
|
<q-dialog v-model="dialog.visible" style="min-width: 400px" @hide="reset">
|
||||||
|
<q-card>
|
||||||
|
<q-form @submit="onSubmit" @reset="reset">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h6">Edit Switch Configurations</div>
|
||||||
|
<p>
|
||||||
|
Edit the possible configurations for this switch.
|
||||||
|
</p>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row">
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="config in dialog.configurations"
|
||||||
|
:key="config.key"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>
|
||||||
|
<q-chip
|
||||||
|
v-for="node in config.nodes"
|
||||||
|
:key="node.id"
|
||||||
|
:label="node.name"
|
||||||
|
/>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-btn size="12px" flat dense round icon="delete" @click="removeConfig(config)"/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<q-select
|
||||||
|
v-model="dialog.pathNode1"
|
||||||
|
:options="getEligibleSwitchNodes(dialog.pathNode2)"
|
||||||
|
:option-value="node => node"
|
||||||
|
:option-label="node => node.name"
|
||||||
|
label="First Path Node"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<q-select
|
||||||
|
v-model="dialog.pathNode2"
|
||||||
|
:options="getEligibleSwitchNodes(dialog.pathNode1)"
|
||||||
|
:option-value="node => node"
|
||||||
|
:option-label="node => node.name"
|
||||||
|
label="Second Path Node"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<q-btn label="Add Configuration" @click="addConfiguration" v-if="canAddConfig(dialog.pathNode1, dialog.pathNode2)"/>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions align="right" class="text-primary">
|
||||||
|
<q-btn flat label="Cancel" type="reset" @click="dialog.visible = false"/>
|
||||||
|
<q-btn flat label="Edit" type="submit"/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-form>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
<q-separator/>
|
||||||
|
<path-node-item :path-node="sw"/>
|
||||||
|
</base-component-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BaseComponentView from "components/rs/component_views/BaseComponentView.vue";
|
||||||
|
import {updateComponent, updateSwitchConfiguration} from "src/api/components";
|
||||||
|
import PathNodeItem from "components/rs/component_views/PathNodeItem.vue";
|
||||||
|
import {useRailSystemsStore} from "stores/railSystemsStore";
|
||||||
|
import {useQuasar} from "quasar";
|
||||||
|
export default {
|
||||||
|
name: "SwitchComponentView",
|
||||||
|
components: {PathNodeItem, BaseComponentView},
|
||||||
|
props: {
|
||||||
|
sw: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const rsStore = useRailSystemsStore();
|
||||||
|
const quasar = useQuasar();
|
||||||
|
return {rsStore, quasar};
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialog: {
|
||||||
|
visible: false,
|
||||||
|
configurations: [],
|
||||||
|
pathNode1: null,
|
||||||
|
pathNode2: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setActiveSwitchConfig(configId) {
|
||||||
|
updateSwitchConfiguration(this.railSystem, this.sw, configId);
|
||||||
|
},
|
||||||
|
isConfigActive(config) {
|
||||||
|
return this.sw.activeConfiguration !== null && this.sw.activeConfiguration.id === config.id;
|
||||||
|
},
|
||||||
|
showDialog() {
|
||||||
|
this.dialog.configurations = this.sw.possibleConfigurations.slice();
|
||||||
|
this.dialog.configurations.forEach(cfg => {
|
||||||
|
cfg.key = cfg.nodes[0].id + '_' + cfg.nodes[1].id
|
||||||
|
});
|
||||||
|
this.dialog.visible = true;
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
this.dialog.pathNode1 = null;
|
||||||
|
this.dialog.pathNode2 = null;
|
||||||
|
this.dialog.configurations.length = 0;
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
const data = {...this.sw};
|
||||||
|
data.possibleConfigurations = this.dialog.configurations;
|
||||||
|
data.activeConfiguration = null;
|
||||||
|
updateComponent(this.rsStore.selectedRailSystem, data)
|
||||||
|
.then(() => {
|
||||||
|
this.dialog.visible = false;
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "positive",
|
||||||
|
message: "Switch configurations updated."
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "negative",
|
||||||
|
message: "An error occurred: " + error.response.data.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getEligibleSwitchNodes(exclude) {
|
||||||
|
return this.rsStore.selectedRailSystem.components.filter(c => {
|
||||||
|
return (c.connectedNodes !== undefined && c.connectedNodes !== null) &&
|
||||||
|
(exclude === null || c.id !== exclude.id);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
canAddConfig(n1, n2) {
|
||||||
|
return this.dialog.configurations.length < 2 &&
|
||||||
|
n1 !== null && n2 !== null &&
|
||||||
|
n1.id !== n2.id &&
|
||||||
|
!this.dialog.configurations.some(config => {
|
||||||
|
return config.nodes.every(node => {
|
||||||
|
return node.id === n1.id || node.id === n2.id;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addConfiguration() {
|
||||||
|
this.dialog.configurations.push({
|
||||||
|
nodes: [this.dialog.pathNode1, this.dialog.pathNode2],
|
||||||
|
key: this.dialog.pathNode1.id + '_' + this.dialog.pathNode2.id
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeConfig(config) {
|
||||||
|
const idx = this.dialog.configurations.findIndex(cfg => cfg.key === config.key);
|
||||||
|
if (idx === -1) return;
|
||||||
|
this.dialog.configurations.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -26,22 +26,12 @@
|
||||||
bordered
|
bordered
|
||||||
>
|
>
|
||||||
<rail-systems-list :rail-systems="rsStore.railSystems" />
|
<rail-systems-list :rail-systems="rsStore.railSystems" />
|
||||||
<q-item
|
<q-item clickable v-ripple :to="'/'">
|
||||||
clickable
|
|
||||||
v-ripple
|
|
||||||
:to="'/'"
|
|
||||||
@click="rsStore.selectRailSystem(null)"
|
|
||||||
>
|
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>Home</q-item-label>
|
<q-item-label>Home</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item
|
<q-item clickable v-ripple :to="'/about'">
|
||||||
clickable
|
|
||||||
v-ripple
|
|
||||||
:to="'/about'"
|
|
||||||
@click="rsStore.selectRailSystem(null)"
|
|
||||||
>
|
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>About</q-item-label>
|
<q-item-label>About</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
@ -68,7 +58,6 @@ export default defineComponent({
|
||||||
setup () {
|
setup () {
|
||||||
const rsStore = useRailSystemsStore()
|
const rsStore = useRailSystemsStore()
|
||||||
const leftDrawerOpen = ref(false)
|
const leftDrawerOpen = ref(false)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rsStore,
|
rsStore,
|
||||||
leftDrawerOpen,
|
leftDrawerOpen,
|
||||||
|
|
|
@ -71,8 +71,11 @@ function drawDebugInfo(ctx) {
|
||||||
"Scale factor: " + getScaleFactor(),
|
"Scale factor: " + getScaleFactor(),
|
||||||
`(x = ${lastWorldPoint.x.toFixed(2)}, y = ${lastWorldPoint.y.toFixed(2)}, z = ${lastWorldPoint.z.toFixed(2)})`,
|
`(x = ${lastWorldPoint.x.toFixed(2)}, y = ${lastWorldPoint.y.toFixed(2)}, z = ${lastWorldPoint.z.toFixed(2)})`,
|
||||||
`Components: ${railSystem.components.length}`,
|
`Components: ${railSystem.components.length}`,
|
||||||
`Hovered elements: ${hoveredElements.length}`
|
`Hovered components: ${hoveredElements.length}`
|
||||||
]
|
]
|
||||||
|
for (let i = 0; i < hoveredElements.length; i++) {
|
||||||
|
lines.push(" " + hoveredElements[i].name);
|
||||||
|
}
|
||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
ctx.fillText(lines[i], 10, 20 + (i * 15));
|
ctx.fillText(lines[i], 10, 20 + (i * 15));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
import {defineStore} from "pinia";
|
import {defineStore} from "pinia";
|
||||||
import { refreshSegments } from "../api/segments";
|
|
||||||
import { refreshComponents } from "../api/components";
|
|
||||||
import { closeWebsocketConnection, establishWebsocketConnection } from "../api/websocket";
|
|
||||||
import { refreshRailSystems } from "src/api/railSystems";
|
|
||||||
import { refreshLinkTokens } from "src/api/linkTokens";
|
|
||||||
import { refreshSettings } from "src/api/settings";
|
|
||||||
|
|
||||||
export const useRailSystemsStore = defineStore('RailSystemsStore', {
|
export const useRailSystemsStore = defineStore('RailSystemsStore', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
|
@ -16,45 +10,5 @@ export const useRailSystemsStore = defineStore('RailSystemsStore', {
|
||||||
* @type {RailSystem | null}
|
* @type {RailSystem | null}
|
||||||
*/
|
*/
|
||||||
selectedRailSystem: null
|
selectedRailSystem: null
|
||||||
}),
|
})
|
||||||
actions: {
|
|
||||||
/**
|
|
||||||
* Updates the selected rail system.
|
|
||||||
* @param rsId {Number | null} The new rail system id.
|
|
||||||
* @returns {Promise} A promise that resolves when the new rail system is
|
|
||||||
* fully loaded and ready.
|
|
||||||
*/
|
|
||||||
selectRailSystem(rsId) {
|
|
||||||
// Close any existing websocket connections prior to refreshing.
|
|
||||||
const wsClosePromises = [];
|
|
||||||
if (this.selectedRailSystem !== null) {
|
|
||||||
wsClosePromises.push(closeWebsocketConnection(this.selectedRailSystem));
|
|
||||||
}
|
|
||||||
if (rsId === null) return Promise.all(wsClosePromises);
|
|
||||||
return new Promise(resolve => {
|
|
||||||
Promise.all(wsClosePromises).then(() => {
|
|
||||||
refreshRailSystems(this).then(() => {
|
|
||||||
const rs = this.railSystems.find(r => r.id === rsId);
|
|
||||||
console.log(rs);
|
|
||||||
const updatePromises = [];
|
|
||||||
updatePromises.push(refreshSegments(rs));
|
|
||||||
updatePromises.push(refreshComponents(rs));
|
|
||||||
updatePromises.push(refreshLinkTokens(rs));
|
|
||||||
updatePromises.push(refreshSettings(rs));
|
|
||||||
updatePromises.push(establishWebsocketConnection(rs));
|
|
||||||
Promise.all(updatePromises).then(() => {
|
|
||||||
this.selectedRailSystem = rs;
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
rsId() {
|
|
||||||
if (this.selectedRailSystem === null) return null;
|
|
||||||
return this.selectedRailSystem.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue