Added more component dialogs and component links to settings page.
|
@ -0,0 +1,82 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="label_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="-7.53551"
|
||||
inkscape:cy="167.89676"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 23.812499,294.90224 V 240.28468"
|
||||
id="path841"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.3499999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect843"
|
||||
width="38.364582"
|
||||
height="24.095985"
|
||||
x="23.812498"
|
||||
y="233.40552"
|
||||
rx="6.614583" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:4.23333334;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="M 31.372024,241.57922 H 54.475819"
|
||||
id="path845"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path847"
|
||||
d="M 31.479768,247.91032 H 54.583563"
|
||||
style="fill:none;stroke:#000000;stroke-width:4.23333311;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,79 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="segment-boundary_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="56.595604"
|
||||
inkscape:cy="134.48081"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 0.70544035,242.15266 H 28.234201 v 41.96132 H 1.1063446"
|
||||
id="path869"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path871"
|
||||
d="M 67.027893,284.11398 H 39.499132 v -41.96132 h 27.127856"
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 6.9392617,256.58521 H 60.794072"
|
||||
id="path873"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path875"
|
||||
d="M 6.9392617,269.68142 H 60.794072"
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,84 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="signal_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="97.668938"
|
||||
inkscape:cy="136.97831"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.35000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 33.866667,296.90549 V 276.77826"
|
||||
id="path815"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect817"
|
||||
width="33.866665"
|
||||
height="43.845234"
|
||||
x="16.933334"
|
||||
y="233.04643"
|
||||
rx="6.6145835" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path819"
|
||||
cx="33.866665"
|
||||
cy="245.50073"
|
||||
r="5.8586307" />
|
||||
<circle
|
||||
r="5.8586307"
|
||||
cy="262.60416"
|
||||
cx="33.866665"
|
||||
id="circle821"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,92 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="switch_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="34.945838"
|
||||
inkscape:cy="171.1685"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 33.866667,291.12006 V 259.31498"
|
||||
id="path838"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path840"
|
||||
d="M 33.866667,259.31498 56.356255,236.8254"
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 33.866667,259.31498 11.377087,236.8254"
|
||||
id="path842"
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path844"
|
||||
cx="13.554182"
|
||||
cy="238.06705"
|
||||
r="7.7508163" />
|
||||
<circle
|
||||
r="7.7508163"
|
||||
cy="238.06705"
|
||||
cx="54.713692"
|
||||
id="circle846"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle848"
|
||||
cx="33.866665"
|
||||
cy="287.79529"
|
||||
r="7.7508163" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
|
@ -5,17 +5,14 @@ export function refreshComponents(rs) {
|
|||
return new Promise((resolve, reject) => {
|
||||
axios.get(`${API_URL}/rs/${rs.id}/c`)
|
||||
.then(response => {
|
||||
const previousSelectedComponentId = rs.selectedComponent ? rs.selectedComponent.id : null;
|
||||
const previousSelectedComponentIds = rs.selectedComponents.map(c => c.id);
|
||||
rs.selectedComponents.length = 0;
|
||||
rs.components = response.data;
|
||||
if (previousSelectedComponentId !== null) {
|
||||
const previousComponent = rs.components.find(c => c.id === previousSelectedComponentId);
|
||||
if (previousComponent) {
|
||||
rs.selectedComponent = previousComponent;
|
||||
} else {
|
||||
rs.selectedComponent = null;
|
||||
}
|
||||
} else {
|
||||
rs.selectedComponent = null;
|
||||
for (let i = 0; i < previousSelectedComponentIds.length; i++) {
|
||||
const component = rs.components.find(c => c.id === previousSelectedComponentIds[i]);
|
||||
if (component) {
|
||||
rs.selectedComponents.push(component);
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
})
|
||||
|
@ -42,7 +39,7 @@ export function refreshSomeComponents(rs, components) {
|
|||
|
||||
export function getComponent(rs, id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.get(`${this.apiUrl}/rs/${rs.id}/c/${id}`)
|
||||
axios.get(`${API_URL}/rs/${rs.id}/c/${id}`)
|
||||
.then(response => resolve(response.data))
|
||||
.catch(reject);
|
||||
});
|
||||
|
@ -78,7 +75,8 @@ export function createComponent(rs, data) {
|
|||
.then(() => {
|
||||
const newComponent = rs.components.find(c => c.id === newComponentId);
|
||||
if (newComponent) {
|
||||
rs.selectedComponent = newComponent;
|
||||
rs.selectedComponents.length = 0;
|
||||
rs.selectedComponents.push(newComponent);
|
||||
}
|
||||
resolve();
|
||||
})
|
||||
|
|
|
@ -17,7 +17,7 @@ export class LinkToken {
|
|||
* @param {RailSystem} rs
|
||||
* @return {Promise<LinkToken[]>}
|
||||
*/
|
||||
export function getTokens(rs) {
|
||||
export function getLinkTokens(rs) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.get(`${API_URL}/rs/${rs.id}/lt`)
|
||||
.then(response => {
|
||||
|
@ -54,4 +54,4 @@ export function deleteToken(rs, tokenId) {
|
|||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ export class RailSystem {
|
|||
this.segments = [];
|
||||
this.components = [];
|
||||
this.websocket = null;
|
||||
this.selectedComponent = null;
|
||||
this.selectedComponents = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="label_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="-7.53551"
|
||||
inkscape:cy="167.89676"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 23.812499,294.90224 V 240.28468"
|
||||
id="path841"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.3499999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect843"
|
||||
width="38.364582"
|
||||
height="24.095985"
|
||||
x="23.812498"
|
||||
y="233.40552"
|
||||
rx="6.614583" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:4.23333334;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="M 31.372024,241.57922 H 54.475819"
|
||||
id="path845"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path847"
|
||||
d="M 31.479768,247.91032 H 54.583563"
|
||||
style="fill:none;stroke:#000000;stroke-width:4.23333311;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,79 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="segment-boundary_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="56.595604"
|
||||
inkscape:cy="134.48081"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 0.70544035,242.15266 H 28.234201 v 41.96132 H 1.1063446"
|
||||
id="path869"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path871"
|
||||
d="M 67.027893,284.11398 H 39.499132 v -41.96132 h 27.127856"
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 6.9392617,256.58521 H 60.794072"
|
||||
id="path873"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path875"
|
||||
d="M 6.9392617,269.68142 H 60.794072"
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,84 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="signal_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="97.668938"
|
||||
inkscape:cy="136.97831"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.35000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 33.866667,296.90549 V 276.77826"
|
||||
id="path815"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect817"
|
||||
width="33.866665"
|
||||
height="43.845234"
|
||||
x="16.933334"
|
||||
y="233.04643"
|
||||
rx="6.6145835" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path819"
|
||||
cx="33.866665"
|
||||
cy="245.50073"
|
||||
r="5.8586307" />
|
||||
<circle
|
||||
r="5.8586307"
|
||||
cy="262.60416"
|
||||
cx="33.866665"
|
||||
id="circle821"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,92 @@
|
|||
<?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="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="switch_icon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="34.945838"
|
||||
inkscape:cy="171.1685"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:pagecheckerboard="true"
|
||||
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,-229.26665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 33.866667,291.12006 V 259.31498"
|
||||
id="path838"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path840"
|
||||
d="M 33.866667,259.31498 56.356255,236.8254"
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.3499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 33.866667,259.31498 11.377087,236.8254"
|
||||
id="path842"
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path844"
|
||||
cx="13.554182"
|
||||
cy="238.06705"
|
||||
r="7.7508163" />
|
||||
<circle
|
||||
r="7.7508163"
|
||||
cy="238.06705"
|
||||
cx="54.713692"
|
||||
id="circle846"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.3499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle848"
|
||||
cx="33.866665"
|
||||
cy="287.79529"
|
||||
r="7.7508163" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<q-card>
|
||||
<q-form>
|
||||
<q-input
|
||||
label="Name"
|
||||
type="text"
|
||||
v-model="component.name"
|
||||
/>
|
||||
<q-input
|
||||
label="X"
|
||||
type="number"
|
||||
v-model="component.position.x"
|
||||
/>
|
||||
<q-input
|
||||
label="Y"
|
||||
type="number"
|
||||
v-model="component.position.y"
|
||||
/>
|
||||
<q-input
|
||||
label="Z"
|
||||
type="number"
|
||||
v-model="component.position.z"
|
||||
/>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AddComponentDialog",
|
||||
data() {
|
||||
return {
|
||||
component: {
|
||||
name: "",
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -1,54 +0,0 @@
|
|||
<template>
|
||||
<div class="flex">
|
||||
<div class="row full-width">
|
||||
<div class="col-md-6">
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="component in railSystem.components"
|
||||
:key="component.id"
|
||||
clickable
|
||||
v-ripple
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{component.name}}</q-item-label>
|
||||
<q-item-label caption>Id: {{component.id}}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side top>
|
||||
<q-item-label caption>x: {{component.position.x}}, y: {{component.position.y}}, z: {{component.position.z}}</q-item-label>
|
||||
<q-item-label caption>{{component.type}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<q-page-sticky position="bottom-right" :offset="[50, 18]">
|
||||
<q-fab
|
||||
icon="add"
|
||||
direction="up"
|
||||
color="accent"
|
||||
>
|
||||
<q-fab-action color="primary" label="Signal"/>
|
||||
<q-fab-action color="primary" label="Switch"/>
|
||||
<q-fab-action color="primary" label="Signal Boundary"/>
|
||||
</q-fab>
|
||||
</q-page-sticky>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { RailSystem } from "src/api/railSystems";
|
||||
|
||||
export default {
|
||||
name: "ComponentsView",
|
||||
props: {
|
||||
railSystem: {
|
||||
type: RailSystem,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -5,27 +5,250 @@
|
|||
Your browser doesn't support canvas.
|
||||
</canvas>
|
||||
</div>
|
||||
<div class="col-md-4" v-if="railSystem.selectedComponent">
|
||||
<selected-component-view :component="railSystem.selectedComponent" />
|
||||
</div>
|
||||
</div>
|
||||
<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="col full-width">
|
||||
<selected-component-view :component="component" :rail-system="railSystem" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</q-scroll-area>
|
||||
</div>
|
||||
<q-page-sticky position="bottom-right" :offset="[25, 25]">
|
||||
<q-fab icon="add" direction="up" color="accent">
|
||||
<q-fab-action @click="addSignalDialog = true">
|
||||
<q-icon><img src="~assets/icons/signal_icon.svg"/></q-icon>
|
||||
<q-tooltip>Add Signal</q-tooltip>
|
||||
</q-fab-action>
|
||||
<q-fab-action @click="addSegmentBoundaryDialog = true">
|
||||
<q-icon><img src="~assets/icons/segment-boundary_icon.svg"/></q-icon>
|
||||
<q-tooltip>Add Segment Boundary</q-tooltip>
|
||||
</q-fab-action>
|
||||
<q-fab-action @click="addSwitchDialog = true">
|
||||
<q-icon><img src="~assets/icons/switch_icon.svg"/></q-icon>
|
||||
<q-tooltip>Add Switch</q-tooltip>
|
||||
</q-fab-action>
|
||||
<q-fab-action @click="addLabelDialog = true">
|
||||
<q-icon><img src="~assets/icons/label_icon.svg"/></q-icon>
|
||||
<q-tooltip>Add Label</q-tooltip>
|
||||
</q-fab-action>
|
||||
</q-fab>
|
||||
</q-page-sticky>
|
||||
|
||||
<!-- Add Signal Dialog -->
|
||||
<q-dialog v-model="addSignalDialog" style="min-width: 400px" @hide="resetAll">
|
||||
<q-card>
|
||||
<q-form @submit="onAddSignalSubmit" @reset="resetAll">
|
||||
<q-card-section>
|
||||
<div class="text-h6">Add Signal</div>
|
||||
<p>
|
||||
Add a signal to the rail system.
|
||||
</p>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-input
|
||||
label="Name"
|
||||
type="text"
|
||||
v-model="addComponentData.name"
|
||||
/>
|
||||
<div class="row">
|
||||
<q-input
|
||||
label="X"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.x"
|
||||
/>
|
||||
<q-input
|
||||
label="Y"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.y"
|
||||
/>
|
||||
<q-input
|
||||
label="Z"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.z"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
v-model="addSignalData.segment"
|
||||
:options="railSystem.segments"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
label="Segment"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn flat label="Cancel" type="reset" @click="addSignalDialog = false"/>
|
||||
<q-btn flat label="Add Signal" type="submit"/>
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<!-- Add Segment boundary -->
|
||||
<q-dialog v-model="addSegmentBoundaryDialog" style="min-width: 400px" @hide="resetAll">
|
||||
<q-card>
|
||||
<q-form @submit="onAddSegmentBoundarySubmit" @reset="resetAll">
|
||||
<q-card-section>
|
||||
<div class="text-h6">Add Segment Boundary</div>
|
||||
<p>
|
||||
Add a segment boundary to the rail system. A segment boundary is a
|
||||
point where a train can cross between two segments, or "blocks" in
|
||||
the system. For example, a train may move from a junction segment to
|
||||
a main line. This boundary is a place where a detector component can
|
||||
update the system as trains pass.
|
||||
</p>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-input
|
||||
label="Name"
|
||||
type="text"
|
||||
v-model="addComponentData.name"
|
||||
/>
|
||||
<div class="row">
|
||||
<q-input
|
||||
label="X"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.x"
|
||||
/>
|
||||
<q-input
|
||||
label="Y"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.y"
|
||||
/>
|
||||
<q-input
|
||||
label="Z"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.z"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
v-model="addSegmentBoundaryData.segments"
|
||||
:options="railSystem.segments"
|
||||
multiple
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
label="Segments"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn flat label="Cancel" type="reset" @click="addSegmentBoundaryDialog = false"/>
|
||||
<q-btn flat label="Add Segment Boundary" type="submit"/>
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<!-- Add Switch dialog -->
|
||||
<q-dialog v-model="addSwitchDialog" @hide="resetAll"></q-dialog>
|
||||
|
||||
<!-- Add Label dialog -->
|
||||
<q-dialog v-model="addLabelDialog" style="min-width: 400px" @hide="resetAll">
|
||||
<q-card>
|
||||
<q-form @submit="onAddLabelSubmit" @reset="resetAll">
|
||||
<q-card-section>
|
||||
<div class="text-h6">Add Label</div>
|
||||
<p>
|
||||
Add a label to the rail system as a piece of text on the map. Labels
|
||||
are purely a visual component, and do not interact with the system
|
||||
in any way, besides being a helpful point of reference for users.
|
||||
</p>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-input
|
||||
label="Name"
|
||||
type="text"
|
||||
v-model="addComponentData.name"
|
||||
/>
|
||||
<div class="row">
|
||||
<q-input
|
||||
label="X"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.x"
|
||||
/>
|
||||
<q-input
|
||||
label="Y"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.y"
|
||||
/>
|
||||
<q-input
|
||||
label="Z"
|
||||
type="number"
|
||||
class="col-sm-4"
|
||||
v-model="addComponentData.position.z"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-input
|
||||
label="Label Text"
|
||||
type="text"
|
||||
v-model="addLabelData.text"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn flat label="Cancel" type="reset" @click="addLabelDialog = false"/>
|
||||
<q-btn flat label="Add Label" type="submit"/>
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { RailSystem } from "src/api/railSystems";
|
||||
import { draw, initMap } from "src/render/mapRenderer";
|
||||
import SelectedComponentView from "components/rs/SelectedComponentView.vue";
|
||||
import { useQuasar } from "quasar";
|
||||
import { createComponent } from "src/api/components";
|
||||
|
||||
export default {
|
||||
name: "MapView",
|
||||
components: { SelectedComponentView },
|
||||
setup() {
|
||||
const quasar = useQuasar();
|
||||
return {quasar};
|
||||
},
|
||||
props: {
|
||||
railSystem: {
|
||||
type: RailSystem,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addSignalDialog: false,
|
||||
addSegmentBoundaryDialog: false,
|
||||
addSwitchDialog: false,
|
||||
addLabelDialog: false,
|
||||
addComponentData: {
|
||||
name: "",
|
||||
position: {
|
||||
x: 0, y: 0, z: 0
|
||||
}
|
||||
},
|
||||
addSignalData: {
|
||||
segment: null
|
||||
},
|
||||
addSegmentBoundaryData: {
|
||||
segments: []
|
||||
},
|
||||
addLabelData: {
|
||||
text: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
initMap(this.railSystem);
|
||||
},
|
||||
|
@ -39,6 +262,53 @@ export default {
|
|||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onAddSignalSubmit() {
|
||||
const data = {...this.addComponentData, ...this.addSignalData};
|
||||
data.type = "SIGNAL";
|
||||
this.attemptCreateComponent(data, "Signal added.", () => this.addSignalDialog = false);
|
||||
},
|
||||
onAddSegmentBoundarySubmit() {
|
||||
const data = {...this.addComponentData, ...this.addSegmentBoundaryData};
|
||||
data.type = "SEGMENT_BOUNDARY";
|
||||
this.attemptCreateComponent(data, "Segment boundary added.", () => this.addSegmentBoundaryDialog = false);
|
||||
},
|
||||
segmentBoundarySegmentsValid() {
|
||||
const set = new Set(this.addSegmentBoundaryData.segments);
|
||||
return set.size === 2 && set.size === this.addSegmentBoundaryData.segments.length;
|
||||
},
|
||||
onAddLabelSubmit() {
|
||||
const data = {...this.addComponentData, ...this.addLabelData};
|
||||
data.type = "LABEL";
|
||||
this.attemptCreateComponent(data, "Label added.", () => this.addLabelDialog = false);
|
||||
},
|
||||
resetAll() {
|
||||
this.addComponentData.name = "";
|
||||
this.addComponentData.position.x = 0;
|
||||
this.addComponentData.position.y = 0;
|
||||
this.addComponentData.position.z = 0;
|
||||
this.addSignalDialog.segment = null;
|
||||
this.addSegmentBoundaryData.segments = [];
|
||||
this.addLabelData.text = "";
|
||||
},
|
||||
attemptCreateComponent(data, successMessage, successHandler) {
|
||||
createComponent(this.railSystem, data)
|
||||
.then(() => {
|
||||
this.quasar.notify({
|
||||
color: "positive",
|
||||
message: successMessage
|
||||
});
|
||||
successHandler();
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
this.quasar.notify({
|
||||
color: "negative",
|
||||
message: "An error occurred: " + error.response.data.message
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<q-item clickable v-ripple>
|
||||
<q-item-section>
|
||||
<q-item-label>{{segment.name}}</q-item-label>
|
||||
<q-item-label caption>Id: {{segment.id}}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side v-if="segment.occupied">
|
||||
<q-badge align="middle"></q-badge>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SegmentListItem",
|
||||
props: {
|
||||
segment: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -30,27 +30,18 @@
|
|||
expand-separator
|
||||
>
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="segment in [component.segment]"
|
||||
:key="segment.id"
|
||||
clickable
|
||||
v-ripple
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>Linked to segment: {{segment.name}}</q-item-label>
|
||||
<q-item-label caption>Id: {{segment.id}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<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="Path Node Information"
|
||||
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
|
||||
|
@ -70,24 +61,14 @@
|
|||
|
||||
<!-- Segment boundary info -->
|
||||
<q-expansion-item
|
||||
label="Segment Boundary Information"
|
||||
label="Connected Segments"
|
||||
v-if="component.type === 'SEGMENT_BOUNDARY'"
|
||||
content-inset-level="0.5"
|
||||
switch-toggle-side
|
||||
expand-separator
|
||||
>
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="segment in component.segments"
|
||||
:key="segment.id"
|
||||
clickable
|
||||
v-ripple
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{segment.name}}</q-item-label>
|
||||
<q-item-label caption>Id: {{segment.id}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<segment-list-item v-for="segment in component.segments" :key="segment.id" :segment="segment"/>
|
||||
</q-list>
|
||||
</q-expansion-item>
|
||||
|
||||
|
@ -120,6 +101,12 @@
|
|||
</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>
|
||||
|
@ -127,25 +114,56 @@
|
|||
<script>
|
||||
import { RailSystem } from "src/api/railSystems";
|
||||
import { useRailSystemsStore } from "stores/railSystemsStore";
|
||||
import SegmentListItem from "components/rs/SegmentListItem.vue";
|
||||
import { useQuasar } from "quasar";
|
||||
import { removeComponent } from "src/api/components";
|
||||
|
||||
export default {
|
||||
name: "SelectedComponentView",
|
||||
components: { SegmentListItem },
|
||||
setup() {
|
||||
const rsStore = useRailSystemsStore();
|
||||
return {rsStore};
|
||||
const quasar = useQuasar();
|
||||
return {rsStore, quasar};
|
||||
},
|
||||
props: {
|
||||
component: {
|
||||
type: Object,
|
||||
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.selectedComponent = 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
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>
|
||||
Settings view. Nothing here yet.
|
||||
</p>
|
||||
</div>
|
||||
<q-list>
|
||||
<q-expansion-item
|
||||
expand-separator
|
||||
label="Component Links"
|
||||
caption="Link components to your system."
|
||||
>
|
||||
<link-tokens-view :rail-system="railSystem"/>
|
||||
</q-expansion-item>
|
||||
</q-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { RailSystem } from "src/api/railSystems";
|
||||
import LinkTokensView from "components/rs/settings/LinkTokensView.vue";
|
||||
|
||||
export default {
|
||||
name: "SettingsView",
|
||||
components: { LinkTokensView },
|
||||
props: {
|
||||
railSystem: {
|
||||
type: RailSystem,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<q-list>
|
||||
<q-item>
|
||||
<q-item-section side>
|
||||
<q-btn label="Add Link" color="positive" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
v-for="token in linkTokens"
|
||||
:key="token.id"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{token.name}}</q-item-label>
|
||||
<q-item-label caption>{{token.id}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { RailSystem } from "src/api/railSystems";
|
||||
import { getLinkTokens } from "src/api/linkTokens";
|
||||
|
||||
export default {
|
||||
name: "LinkTokensView",
|
||||
props: {
|
||||
railSystem: {
|
||||
type: RailSystem,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
linkTokens: [],
|
||||
addTokenDialog: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
getLinkTokens(this.railSystem)
|
||||
.then(tokens => this.linkTokens = tokens);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -9,7 +9,6 @@
|
|||
>
|
||||
<q-tab name="map" label="Map"/>
|
||||
<q-tab name="segments" label="Segments"/>
|
||||
<q-tab name="components" label="Components"/>
|
||||
<q-tab name="settings" label="Settings"/>
|
||||
</q-tabs>
|
||||
<q-tab-panels v-model="panel">
|
||||
|
@ -19,9 +18,6 @@
|
|||
<q-tab-panel name="segments">
|
||||
<segments-view :rail-system="railSystem"/>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="components">
|
||||
<components-view :rail-system="railSystem"/>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="settings">
|
||||
<settings-view :rail-system="railSystem"/>
|
||||
</q-tab-panel>
|
||||
|
@ -36,12 +32,11 @@
|
|||
import { useRailSystemsStore } from "stores/railSystemsStore";
|
||||
import MapView from "components/rs/MapView.vue";
|
||||
import SegmentsView from "components/rs/SegmentsView.vue";
|
||||
import ComponentsView from "components/rs/ComponentsView.vue";
|
||||
import SettingsView from "components/rs/SettingsView.vue";
|
||||
|
||||
export default {
|
||||
name: "RailSystemPage",
|
||||
components: { SettingsView, ComponentsView, SegmentsView, MapView },
|
||||
components: { SettingsView, SegmentsView, MapView },
|
||||
data() {
|
||||
return {
|
||||
panel: "map",
|
||||
|
|
|
@ -19,6 +19,8 @@ export function drawComponent(ctx, worldTx, component) {
|
|||
drawSegmentBoundary(ctx, component);
|
||||
} else if (component.type === "SWITCH") {
|
||||
drawSwitch(ctx, component);
|
||||
} else if (component.type === "LABEL") {
|
||||
drawLabel(ctx, component);
|
||||
}
|
||||
|
||||
ctx.setTransform(tx.translate(0.75, -0.75));
|
||||
|
@ -99,6 +101,15 @@ function drawSwitch(ctx, sw) {
|
|||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawLabel(ctx, lbl) {
|
||||
ctx.fillStyle = "black";
|
||||
circle(ctx, 0, 0, 0.1);
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.font = "0.5px Sans-Serif";
|
||||
ctx.fillText(lbl.text, 0.1, -0.2);
|
||||
}
|
||||
|
||||
function drawOnlineIndicator(ctx, component) {
|
||||
ctx.lineWidth = 0.1;
|
||||
if (component.online) {
|
||||
|
|
|
@ -147,14 +147,11 @@ function getWorldTransform() {
|
|||
}
|
||||
|
||||
export function isComponentHovered(component) {
|
||||
for (let i = 0; i < hoveredElements.length; i++) {
|
||||
if (hoveredElements[i].id === component.id) return true;
|
||||
}
|
||||
return false;
|
||||
return hoveredElements.some(c => c.id === component.id);
|
||||
}
|
||||
|
||||
export function isComponentSelected(component) {
|
||||
return railSystem.selectedComponent !== null && railSystem.selectedComponent.id === component.id;
|
||||
return railSystem.selectedComponents.some(c => c.id === component.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,10 +206,11 @@ function onMouseUp() {
|
|||
mapTranslation.y += mapDragTranslation.y;
|
||||
finishedDrag = true;
|
||||
}
|
||||
if (hoveredElements.length === 1) {
|
||||
railSystem.selectedComponent = hoveredElements[0];
|
||||
if (hoveredElements.length > 0) {
|
||||
railSystem.selectedComponents.length = 0;
|
||||
railSystem.selectedComponents.push(...hoveredElements);
|
||||
} else if (!finishedDrag) {
|
||||
railSystem.selectedComponent = null;
|
||||
railSystem.selectedComponents.length = 0;
|
||||
}
|
||||
mapDragOrigin = null;
|
||||
mapDragTranslation = null;
|
||||
|
|
|
@ -3,7 +3,6 @@ package nl.andrewl.railsignalapi.rest.dto.component.in;
|
|||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import nl.andrewl.railsignalapi.model.component.Label;
|
||||
import nl.andrewl.railsignalapi.model.component.Position;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
@ -15,7 +14,7 @@ import javax.validation.constraints.NotNull;
|
|||
@JsonSubTypes.Type(value = SignalPayload.class, name = "SIGNAL"),
|
||||
@JsonSubTypes.Type(value = SwitchPayload.class, name = "SWITCH"),
|
||||
@JsonSubTypes.Type(value = SegmentBoundaryPayload.class, name = "SEGMENT_BOUNDARY"),
|
||||
@JsonSubTypes.Type(value = Label.class, name = "LABEL")
|
||||
@JsonSubTypes.Type(value = LabelPayload.class, name = "LABEL")
|
||||
})
|
||||
public abstract class ComponentPayload {
|
||||
@NotNull @NotBlank
|
||||
|
|