Added Switch dialog, and link token creation.
This commit is contained in:
parent
2cc3c2259a
commit
c0c036d223
|
@ -30,7 +30,7 @@ export function getLinkTokens(rs) {
|
||||||
/**
|
/**
|
||||||
* Creates a new link token.
|
* Creates a new link token.
|
||||||
* @param {RailSystem} rs
|
* @param {RailSystem} rs
|
||||||
* @param {LinkToken} data
|
* @param {{label: String, componentIds: Number[]}} data
|
||||||
* @return {Promise<string>} A promise that resolves to the token that was created.
|
* @return {Promise<string>} A promise that resolves to the token that was created.
|
||||||
*/
|
*/
|
||||||
export function createLinkToken(rs, data) {
|
export function createLinkToken(rs, data) {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
>
|
>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>{{railSystem.name}}</q-item-label>
|
<q-item-label>{{railSystem.name}}</q-item-label>
|
||||||
<q-item-label caption>Id: {{railSystem.id}}</q-item-label>
|
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -16,19 +16,19 @@
|
||||||
</div>
|
</div>
|
||||||
<q-page-sticky position="bottom-right" :offset="[25, 25]">
|
<q-page-sticky position="bottom-right" :offset="[25, 25]">
|
||||||
<q-fab icon="add" direction="up" color="accent">
|
<q-fab icon="add" direction="up" color="accent">
|
||||||
<q-fab-action @click="addSignalDialog = true">
|
<q-fab-action @click="addSignalData.toggle = true">
|
||||||
<q-icon><img src="~assets/icons/signal_icon.svg"/></q-icon>
|
<q-icon><img src="~assets/icons/signal_icon.svg"/></q-icon>
|
||||||
<q-tooltip>Add Signal</q-tooltip>
|
<q-tooltip>Add Signal</q-tooltip>
|
||||||
</q-fab-action>
|
</q-fab-action>
|
||||||
<q-fab-action @click="addSegmentBoundaryDialog = true">
|
<q-fab-action @click="addSegmentBoundaryData.toggle = true">
|
||||||
<q-icon><img src="~assets/icons/segment-boundary_icon.svg"/></q-icon>
|
<q-icon><img src="~assets/icons/segment-boundary_icon.svg"/></q-icon>
|
||||||
<q-tooltip>Add Segment Boundary</q-tooltip>
|
<q-tooltip>Add Segment Boundary</q-tooltip>
|
||||||
</q-fab-action>
|
</q-fab-action>
|
||||||
<q-fab-action @click="addSwitchDialog = true">
|
<q-fab-action @click="addSwitchData.toggle = true">
|
||||||
<q-icon><img src="~assets/icons/switch_icon.svg"/></q-icon>
|
<q-icon><img src="~assets/icons/switch_icon.svg"/></q-icon>
|
||||||
<q-tooltip>Add Switch</q-tooltip>
|
<q-tooltip>Add Switch</q-tooltip>
|
||||||
</q-fab-action>
|
</q-fab-action>
|
||||||
<q-fab-action @click="addLabelDialog = true">
|
<q-fab-action @click="addLabelData.toggle = true">
|
||||||
<q-icon><img src="~assets/icons/label_icon.svg"/></q-icon>
|
<q-icon><img src="~assets/icons/label_icon.svg"/></q-icon>
|
||||||
<q-tooltip>Add Label</q-tooltip>
|
<q-tooltip>Add Label</q-tooltip>
|
||||||
</q-fab-action>
|
</q-fab-action>
|
||||||
|
@ -36,174 +36,145 @@
|
||||||
</q-page-sticky>
|
</q-page-sticky>
|
||||||
|
|
||||||
<!-- Add Signal Dialog -->
|
<!-- Add Signal Dialog -->
|
||||||
<q-dialog v-model="addSignalDialog" style="min-width: 400px" @hide="resetAll">
|
<add-component-dialog
|
||||||
<q-card>
|
v-model="addSignalData"
|
||||||
<q-form @submit="onAddSignalSubmit" @reset="resetAll">
|
type="SIGNAL"
|
||||||
<q-card-section>
|
:rail-system="railSystem"
|
||||||
<div class="text-h6">Add Signal</div>
|
title="Add Signal"
|
||||||
<p>
|
success-message="Signal added."
|
||||||
Add a signal to the rail system.
|
>
|
||||||
</p>
|
<template #subtitle>
|
||||||
</q-card-section>
|
<p>
|
||||||
<q-card-section>
|
Add a signal to the rail system.
|
||||||
<q-input
|
</p>
|
||||||
label="Name"
|
</template>
|
||||||
type="text"
|
<template #default>
|
||||||
v-model="addComponentData.name"
|
<q-card-section>
|
||||||
/>
|
<q-select
|
||||||
<div class="row">
|
v-model="addSignalData.segment"
|
||||||
<q-input
|
:options="railSystem.segments"
|
||||||
label="X"
|
option-value="id"
|
||||||
type="number"
|
option-label="name"
|
||||||
class="col-sm-4"
|
label="Segment"
|
||||||
v-model="addComponentData.position.x"
|
/>
|
||||||
/>
|
</q-card-section>
|
||||||
<q-input
|
</template>
|
||||||
label="Y"
|
</add-component-dialog>
|
||||||
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 -->
|
<!-- Add Segment boundary -->
|
||||||
<q-dialog v-model="addSegmentBoundaryDialog" style="min-width: 400px" @hide="resetAll">
|
<add-component-dialog
|
||||||
<q-card>
|
title="Add Segment Boundary"
|
||||||
<q-form @submit="onAddSegmentBoundarySubmit" @reset="resetAll">
|
success-message="Segment boundary added."
|
||||||
<q-card-section>
|
:rail-system="railSystem"
|
||||||
<div class="text-h6">Add Segment Boundary</div>
|
type="SEGMENT_BOUNDARY"
|
||||||
<p>
|
v-model="addSegmentBoundaryData"
|
||||||
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
|
<template #subtitle>
|
||||||
the system. For example, a train may move from a junction segment to
|
<p>
|
||||||
a main line. This boundary is a place where a detector component can
|
Add a segment boundary to the rail system.
|
||||||
update the system as trains pass.
|
</p>
|
||||||
</p>
|
</template>
|
||||||
</q-card-section>
|
<template #default>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-select
|
||||||
label="Name"
|
v-model="addSegmentBoundaryData.segments"
|
||||||
type="text"
|
:options="railSystem.segments"
|
||||||
v-model="addComponentData.name"
|
multiple
|
||||||
/>
|
:option-value="segment => segment"
|
||||||
<div class="row">
|
:option-label="segment => segment.name"
|
||||||
<q-input
|
label="Segments"
|
||||||
label="X"
|
/>
|
||||||
type="number"
|
</q-card-section>
|
||||||
class="col-sm-4"
|
</template>
|
||||||
v-model="addComponentData.position.x"
|
</add-component-dialog>
|
||||||
/>
|
|
||||||
<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 -->
|
<!-- Add Switch dialog -->
|
||||||
<q-dialog v-model="addSwitchDialog" @hide="resetAll"></q-dialog>
|
<add-component-dialog
|
||||||
|
title="Add Switch"
|
||||||
|
success-message="Switch added."
|
||||||
|
:rail-system="railSystem"
|
||||||
|
type="SWITCH"
|
||||||
|
v-model="addSwitchData"
|
||||||
|
>
|
||||||
|
<template #subtitle>
|
||||||
|
<p>
|
||||||
|
Add a switch to the rail system.
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
<template #default>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row">
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="config in addSwitchData.possibleConfigurations"
|
||||||
|
: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>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Add Label dialog -->
|
<div class="row">
|
||||||
<q-dialog v-model="addLabelDialog" style="min-width: 400px" @hide="resetAll">
|
<div class="col-sm-6">
|
||||||
<q-card>
|
<q-select
|
||||||
<q-form @submit="onAddLabelSubmit" @reset="resetAll">
|
v-model="addSwitchData.pathNode1"
|
||||||
<q-card-section>
|
:options="getEligibleSwitchNodes()"
|
||||||
<div class="text-h6">Add Label</div>
|
:option-value="segment => segment"
|
||||||
<p>
|
:option-label="segment => segment.name"
|
||||||
Add a label to the rail system as a piece of text on the map. Labels
|
label="First Path Node"
|
||||||
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>
|
</div>
|
||||||
</q-card-section>
|
<div class="col-sm-6">
|
||||||
<q-card-section>
|
<q-select
|
||||||
<q-input
|
v-model="addSwitchData.pathNode2"
|
||||||
label="Label Text"
|
:options="getEligibleSwitchNodes()"
|
||||||
type="text"
|
:option-value="segment => segment"
|
||||||
v-model="addLabelData.text"
|
:option-label="segment => segment.name"
|
||||||
/>
|
label="Second Path Node"
|
||||||
</q-card-section>
|
/>
|
||||||
<q-card-actions align="right" class="text-primary">
|
</div>
|
||||||
<q-btn flat label="Cancel" type="reset" @click="addLabelDialog = false"/>
|
</div>
|
||||||
<q-btn flat label="Add Label" type="submit"/>
|
<div class="row">
|
||||||
</q-card-actions>
|
<q-btn label="Add Configuration" color="primary" @click="addSwitchConfiguration"/>
|
||||||
</q-form>
|
</div>
|
||||||
</q-card>
|
|
||||||
</q-dialog>
|
</q-card-section>
|
||||||
|
</template>
|
||||||
|
</add-component-dialog>
|
||||||
|
|
||||||
|
<!-- Add Label dialog -->
|
||||||
|
<add-component-dialog
|
||||||
|
title="Add Label"
|
||||||
|
success-message="Added label."
|
||||||
|
:rail-system="railSystem"
|
||||||
|
type="LABEL"
|
||||||
|
v-model="addLabelData"
|
||||||
|
>
|
||||||
|
<template #subtitle>
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
|
<template #default>
|
||||||
|
<q-card-section>
|
||||||
|
<q-input
|
||||||
|
label="Label Text"
|
||||||
|
type="text"
|
||||||
|
v-model="addLabelData.text"
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
|
</template>
|
||||||
|
</add-component-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -212,10 +183,11 @@ 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 { createComponent } from "src/api/components";
|
||||||
|
import AddComponentDialog from "components/rs/add_component/AddComponentDialog.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MapView",
|
name: "MapView",
|
||||||
components: { SelectedComponentView },
|
components: { AddComponentDialog, SelectedComponentView },
|
||||||
setup() {
|
setup() {
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
return {quasar};
|
return {quasar};
|
||||||
|
@ -228,23 +200,39 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
addSignalDialog: false,
|
addSignalData: {
|
||||||
addSegmentBoundaryDialog: false,
|
|
||||||
addSwitchDialog: false,
|
|
||||||
addLabelDialog: false,
|
|
||||||
addComponentData: {
|
|
||||||
name: "",
|
name: "",
|
||||||
position: {
|
position: {
|
||||||
x: 0, y: 0, z: 0
|
x: 0, y: 0, z: 0
|
||||||
}
|
},
|
||||||
},
|
segment: null,
|
||||||
addSignalData: {
|
toggle: false
|
||||||
segment: null
|
|
||||||
},
|
},
|
||||||
addSegmentBoundaryData: {
|
addSegmentBoundaryData: {
|
||||||
segments: []
|
name: "",
|
||||||
|
position: {
|
||||||
|
x: 0, y: 0, z: 0
|
||||||
|
},
|
||||||
|
toggle: false,
|
||||||
|
segments: [],
|
||||||
|
connectedNodes: []
|
||||||
|
},
|
||||||
|
addSwitchData: {
|
||||||
|
name: "",
|
||||||
|
position: {
|
||||||
|
x: 0, y: 0, z: 0
|
||||||
|
},
|
||||||
|
toggle: false,
|
||||||
|
possibleConfigurations: [],
|
||||||
|
// Utility properties for the UI for adding configurations.
|
||||||
|
pathNode1: null,
|
||||||
|
pathNode2: null
|
||||||
},
|
},
|
||||||
addLabelData: {
|
addLabelData: {
|
||||||
|
position: {
|
||||||
|
x: 0, y: 0, z: 0
|
||||||
|
},
|
||||||
|
toggle: false,
|
||||||
text: ""
|
text: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,50 +252,38 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onAddSignalSubmit() {
|
getEligibleSwitchNodes() {
|
||||||
const data = {...this.addComponentData, ...this.addSignalData};
|
return this.railSystem.components.filter(component => {
|
||||||
data.type = "SIGNAL";
|
return component.connectedNodes !== undefined && component.connectedNodes !== null;
|
||||||
this.attemptCreateComponent(data, "Signal added.", () => this.addSignalDialog = false);
|
});
|
||||||
},
|
},
|
||||||
onAddSegmentBoundarySubmit() {
|
addSwitchConfiguration() {
|
||||||
const data = {...this.addComponentData, ...this.addSegmentBoundaryData};
|
if (
|
||||||
data.type = "SEGMENT_BOUNDARY";
|
this.addSwitchData.pathNode1 === null ||
|
||||||
this.attemptCreateComponent(data, "Segment boundary added.", () => this.addSegmentBoundaryDialog = false);
|
this.addSwitchData.pathNode2 === null ||
|
||||||
},
|
this.addSwitchData.pathNode1.id === this.addSwitchData.pathNode2.id ||
|
||||||
segmentBoundarySegmentsValid() {
|
this.addSwitchData.possibleConfigurations.some(config => {
|
||||||
const set = new Set(this.addSegmentBoundaryData.segments);
|
// Check if there's already a configuration containing both of these nodes.
|
||||||
return set.size === 2 && set.size === this.addSegmentBoundaryData.segments.length;
|
return config.nodes.every(node =>
|
||||||
},
|
node.id === this.addSwitchData.pathNode1.id ||
|
||||||
onAddLabelSubmit() {
|
node.id === this.addSwitchData.pathNode2.id);
|
||||||
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({
|
||||||
this.quasar.notify({
|
color: "warning",
|
||||||
color: "negative",
|
message: "Invalid switch configuration."
|
||||||
message: "An error occurred: " + error.response.data.message
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// All good!
|
||||||
|
this.addSwitchData.possibleConfigurations.push({
|
||||||
|
nodes: [
|
||||||
|
this.addSwitchData.pathNode1,
|
||||||
|
this.addSwitchData.pathNode2
|
||||||
|
],
|
||||||
|
// A unique key, just for the frontend to use. This is not used by the API.
|
||||||
|
key: this.addSwitchData.pathNode1.id + "_" + this.addSwitchData.pathNode2.id
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
id="signalInfo"
|
id="signalInfo"
|
||||||
label="Signal Information"
|
label="Signal Information"
|
||||||
v-if="component.type === 'SIGNAL'"
|
v-if="component.type === 'SIGNAL'"
|
||||||
content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
switch-toggle-side
|
switch-toggle-side
|
||||||
expand-separator
|
expand-separator
|
||||||
>
|
>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
label="Connected Nodes"
|
label="Connected Nodes"
|
||||||
v-if="component.connectedNodes !== undefined && component.connectedNodes !== null"
|
v-if="component.connectedNodes !== undefined && component.connectedNodes !== null"
|
||||||
content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
switch-toggle-side
|
switch-toggle-side
|
||||||
expand-separator
|
expand-separator
|
||||||
class="q-gutter-md"
|
class="q-gutter-md"
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
label="Connected Segments"
|
label="Connected Segments"
|
||||||
v-if="component.type === 'SEGMENT_BOUNDARY'"
|
v-if="component.type === 'SEGMENT_BOUNDARY'"
|
||||||
content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
switch-toggle-side
|
switch-toggle-side
|
||||||
expand-separator
|
expand-separator
|
||||||
>
|
>
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
label="Switch Information"
|
label="Switch Information"
|
||||||
v-if="component.type === 'SWITCH'"
|
v-if="component.type === 'SWITCH'"
|
||||||
content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
switch-toggle-side
|
switch-toggle-side
|
||||||
expand-separator
|
expand-separator
|
||||||
>
|
>
|
||||||
|
@ -86,14 +86,16 @@
|
||||||
:key="config.id"
|
:key="config.id"
|
||||||
>
|
>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label class="q-gutter-md">
|
<q-item-label class="q-gutter-sm">
|
||||||
<q-btn
|
<q-chip
|
||||||
v-for="node in config.nodes"
|
v-for="node in config.nodes"
|
||||||
:key="node.id"
|
:key="node.id"
|
||||||
dense
|
dense
|
||||||
size="sm"
|
size="sm"
|
||||||
:label="node.name"
|
:label="node.name"
|
||||||
:color="component.activeConfiguration && component.activeConfiguration.id === config.id ? 'primary' : 'secondary'"
|
:color="component.activeConfiguration && component.activeConfiguration.id === config.id ? 'primary' : 'secondary'"
|
||||||
|
:text-color="'white'"
|
||||||
|
clickable
|
||||||
@click="select(node)"
|
@click="select(node)"
|
||||||
/>
|
/>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-expansion-item
|
<link-tokens-view :rail-system="railSystem"/>
|
||||||
expand-separator
|
|
||||||
label="Component Links"
|
|
||||||
caption="Link components to your system."
|
|
||||||
>
|
|
||||||
<link-tokens-view :rail-system="railSystem"/>
|
|
||||||
</q-expansion-item>
|
|
||||||
</q-list>
|
</q-list>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
<template>
|
||||||
|
<q-dialog v-model="componentData.toggle" style="min-width: 400px" @hide="onReset">
|
||||||
|
<q-card>
|
||||||
|
<q-form @submit="onSubmit" @reset="onReset" @change="onChange">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h6">{{title}}</div>
|
||||||
|
<slot name="subtitle"></slot>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<q-input
|
||||||
|
label="Name"
|
||||||
|
type="text"
|
||||||
|
v-model="componentData.name"
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
<div class="row">
|
||||||
|
<q-input
|
||||||
|
label="X"
|
||||||
|
type="number"
|
||||||
|
class="col-sm-4"
|
||||||
|
v-model="componentData.position.x"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
label="Y"
|
||||||
|
type="number"
|
||||||
|
class="col-sm-4"
|
||||||
|
v-model="componentData.position.y"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
label="Z"
|
||||||
|
type="number"
|
||||||
|
class="col-sm-4"
|
||||||
|
v-model="componentData.position.z"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<slot :component-data="componentData"></slot>
|
||||||
|
<q-card-actions align="right" class="text-primary">
|
||||||
|
<q-btn flat label="Cancel" type="reset" @click="componentData.toggle = false"/>
|
||||||
|
<q-btn flat label="Add" type="submit"/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-form>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { createComponent } from "src/api/components";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import { RailSystem } from "src/api/railSystems";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "AddComponentDialog",
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
railSystem: {
|
||||||
|
type: RailSystem,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
successMessage: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const quasar = useQuasar();
|
||||||
|
return {quasar};
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
componentData: this.modelValue
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSubmit() {
|
||||||
|
const postData = {type: this.type, ...this.componentData};
|
||||||
|
createComponent(this.railSystem, postData)
|
||||||
|
.then(() => {
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "positive",
|
||||||
|
message: this.successMessage
|
||||||
|
});
|
||||||
|
this.componentData.toggle = false;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "negative",
|
||||||
|
message: "An error occurred: " + error.response.data.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onReset() {
|
||||||
|
this.componentData.name = "";
|
||||||
|
this.componentData.position.x = 0;
|
||||||
|
this.componentData.position.y = 0;
|
||||||
|
this.componentData.position.z = 0;
|
||||||
|
this.$emit("reset");
|
||||||
|
},
|
||||||
|
onChange() {
|
||||||
|
this.$emit("update:modelValue", this.componentData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,68 @@
|
||||||
|
<template>
|
||||||
|
<add-component-dialog
|
||||||
|
v-model="addSignalData"
|
||||||
|
type="SIGNAL"
|
||||||
|
:rail-system="railSystem"
|
||||||
|
title="Add Signal"
|
||||||
|
success-message="Signal added."
|
||||||
|
@reset="onReset"
|
||||||
|
>
|
||||||
|
<template #subtitle>
|
||||||
|
<p>
|
||||||
|
Add a signal to the rail system.
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
<template #default>
|
||||||
|
<q-card-section>
|
||||||
|
<q-select
|
||||||
|
v-model="addSignalData.segment"
|
||||||
|
:options="railSystem.segments"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
label="Segment"
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
|
</template>
|
||||||
|
</add-component-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { RailSystem } from "src/api/railSystems";
|
||||||
|
import AddComponentDialog from "components/rs/add_component/AddComponentDialog.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "AddSignalDialog",
|
||||||
|
components: {AddComponentDialog},
|
||||||
|
props: {
|
||||||
|
railSystem: {
|
||||||
|
type: RailSystem,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addSignalData: {
|
||||||
|
name: "",
|
||||||
|
position: {
|
||||||
|
x: 0, y: 0, z: 0
|
||||||
|
},
|
||||||
|
segment: null,
|
||||||
|
toggle: this.modelValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onReset() {
|
||||||
|
this.addSignalData.segment = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,26 +1,98 @@
|
||||||
<template>
|
<template>
|
||||||
<q-list>
|
<q-expansion-item
|
||||||
<q-item>
|
expand-separator
|
||||||
<q-item-section side>
|
label="Component Links"
|
||||||
<q-btn label="Add Link" color="positive" />
|
caption="Link components to your system."
|
||||||
</q-item-section>
|
@before-show="refreshLinkTokens"
|
||||||
</q-item>
|
switch-toggle-side
|
||||||
<q-item
|
:content-inset-level="0.5"
|
||||||
v-for="token in linkTokens"
|
>
|
||||||
:key="token.id"
|
<q-list>
|
||||||
>
|
<q-item
|
||||||
<q-item-section>
|
v-for="token in linkTokens"
|
||||||
<q-item-label>{{token.name}}</q-item-label>
|
:key="token.id"
|
||||||
<q-item-label caption>{{token.id}}</q-item-label>
|
>
|
||||||
</q-item-section>
|
<q-item-section>
|
||||||
</q-item>
|
<q-item-label>{{token.label}}</q-item-label>
|
||||||
</q-list>
|
<q-item-label caption>{{token.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="linkTokens.length === 0">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>There are no link tokens. Add one via the <em>Add Link</em> button below.</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-separator/>
|
||||||
|
|
||||||
|
<q-item>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-btn label="Add Link" color="primary" @click="addTokenDialog = true" />
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-expansion-item>
|
||||||
|
|
||||||
|
<q-dialog v-model="addTokenDialog" style="min-width: 400px;" @hide="onReset">
|
||||||
|
<q-card>
|
||||||
|
<q-form @submit="onSubmit" @reset="onReset">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h6">Add Link Token</div>
|
||||||
|
<p>
|
||||||
|
Create a new link token that gives external components access to
|
||||||
|
this rail system's live data streams. Use a link token to let signals
|
||||||
|
in your system get real-time updates, and to let segment boundaries
|
||||||
|
send real-time status updates as trains move.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You will be shown the link token <strong>only once</strong> when the
|
||||||
|
token is first created. If you lose it, you will need to delete the
|
||||||
|
token and create a new one.
|
||||||
|
</p>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<q-input
|
||||||
|
label="Label"
|
||||||
|
type="text"
|
||||||
|
v-model="addTokenData.label"
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
<q-select
|
||||||
|
label="Components"
|
||||||
|
multiple
|
||||||
|
v-model="addTokenData.selectedComponents"
|
||||||
|
:options="getEligibleComponents()"
|
||||||
|
:option-value="component => component.id"
|
||||||
|
:option-label="component => component.name"
|
||||||
|
use-chips
|
||||||
|
stack-label
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-section v-if="token">
|
||||||
|
<q-banner class="bg-primary text-white">
|
||||||
|
<p>
|
||||||
|
Link token created: <code class="text-bold">{{token}}</code>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Copy this token now; it won't be shown again.
|
||||||
|
</p>
|
||||||
|
</q-banner>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-actions align="right" class="text-primary">
|
||||||
|
<q-btn flat label="Close" type="reset" @click="addTokenDialog = false"/>
|
||||||
|
<q-btn flat label="Add" type="submit" v-if="!token"/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-form>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { RailSystem } from "src/api/railSystems";
|
import { RailSystem } from "src/api/railSystems";
|
||||||
import { getLinkTokens } from "src/api/linkTokens";
|
import { createLinkToken, getLinkTokens } from "src/api/linkTokens";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "LinkTokensView",
|
name: "LinkTokensView",
|
||||||
|
@ -30,15 +102,53 @@ export default {
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const quasar = useQuasar();
|
||||||
|
return {quasar};
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
linkTokens: [],
|
linkTokens: [],
|
||||||
addTokenDialog: false
|
addTokenDialog: false,
|
||||||
|
addTokenData: {
|
||||||
|
label: "",
|
||||||
|
selectedComponents: [],
|
||||||
|
componentIds: []
|
||||||
|
},
|
||||||
|
token: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
methods: {
|
||||||
getLinkTokens(this.railSystem)
|
refreshLinkTokens() {
|
||||||
.then(tokens => this.linkTokens = tokens);
|
getLinkTokens(this.railSystem)
|
||||||
|
.then(tokens => {
|
||||||
|
this.linkTokens = tokens;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getEligibleComponents() {
|
||||||
|
return this.railSystem.components.filter(component => {
|
||||||
|
return component.type === "SIGNAL" || component.type === "SEGMENT_BOUNDARY" || component.type === "SWITCH";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
this.addTokenData.componentIds = this.addTokenData.selectedComponents.map(c => c.id);
|
||||||
|
createLinkToken(this.railSystem, this.addTokenData)
|
||||||
|
.then(token => {
|
||||||
|
this.token = token;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.quasar.notify({
|
||||||
|
color: "negative",
|
||||||
|
message: "An error occurred: " + error.response.data.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onReset() {
|
||||||
|
this.addTokenData.name = "";
|
||||||
|
this.addTokenData.selectedComponents.length = 0;
|
||||||
|
this.addTokenData.componentIds.length = 0;
|
||||||
|
this.token = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -40,7 +40,9 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
panel: "map",
|
panel: "map",
|
||||||
railSystem: null
|
railSystem: null,
|
||||||
|
|
||||||
|
linkTokens: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
Loading…
Reference in New Issue