From e45b942f34f2c327c360da2d449b107115431a31 Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Fri, 20 May 2022 01:12:26 +0200 Subject: [PATCH] Added UI for creating link tokens, and improved component search api. --- railsignal-app/src/api/components.js | 21 ++++ railsignal-app/src/api/linkTokens.js | 57 +++++++++ railsignal-app/src/api/paths.js | 20 +++ railsignal-app/src/api/railSystems.js | 17 ++- railsignal-app/src/api/websocket.js | 12 +- railsignal-app/src/components/AppNavbar.vue | 1 + .../railsystem/CreateLinkTokenModal.vue | 115 ++++++++++++++++++ .../railsystem/RailSystemPropertiesView.vue | 27 +++- .../railsystem/util/ComponentSelector.vue | 106 ++++++++++++++++ railsignal-app/src/main.js | 15 +-- railsignal-app/src/stores/railSystemsStore.js | 10 +- .../rest/ComponentsApiController.java | 3 +- .../service/ComponentService.java | 10 +- 13 files changed, 382 insertions(+), 32 deletions(-) create mode 100644 railsignal-app/src/api/linkTokens.js create mode 100644 railsignal-app/src/components/railsystem/CreateLinkTokenModal.vue create mode 100644 railsignal-app/src/components/railsystem/util/ComponentSelector.vue diff --git a/railsignal-app/src/api/components.js b/railsignal-app/src/api/components.js index ecb5c76..57268cb 100644 --- a/railsignal-app/src/api/components.js +++ b/railsignal-app/src/api/components.js @@ -48,6 +48,27 @@ export function getComponent(rs, id) { }); } +/** + * Searches through the rail system's components. + * @param {RailSystem} rs + * @param {string|null} searchQuery + * @return {Promise} + */ +export function searchComponents(rs, searchQuery) { + return new Promise((resolve, reject) => { + const params = { + page: 0, + size: 25 + }; + if (searchQuery) params.q = searchQuery; + axios.get(`${API_URL}/rs/${rs.id}/c/search`, {params: params}) + .then(response => { + resolve(response.data); + }) + .catch(reject); + }); +} + export function createComponent(rs, data) { return new Promise((resolve, reject) => { axios.post(`${API_URL}/rs/${rs.id}/c`, data) diff --git a/railsignal-app/src/api/linkTokens.js b/railsignal-app/src/api/linkTokens.js new file mode 100644 index 0000000..38e601c --- /dev/null +++ b/railsignal-app/src/api/linkTokens.js @@ -0,0 +1,57 @@ +import {API_URL} from "./constants"; +import axios from "axios"; + +/** + * A token that's used by components to provide real-time up and down links. + */ +export class LinkToken { + constructor(data) { + this.id = data.id; + this.label = data.label; + this.components = data.components; + } +} + +/** + * Gets the list of link tokens in a rail system. + * @param {RailSystem} rs + * @return {Promise} + */ +export function getTokens(rs) { + return new Promise((resolve, reject) => { + axios.get(`${API_URL}/rs/${rs.id}/lt`) + .then(response => { + resolve(response.data.map(obj => new LinkToken(obj))); + }) + .catch(reject); + }); +} + +/** + * Creates a new link token. + * @param {RailSystem} rs + * @param {LinkToken} data + * @return {Promise} A promise that resolves to the token that was created. + */ +export function createLinkToken(rs, data) { + return new Promise((resolve, reject) => { + axios.post(`${API_URL}/rs/${rs.id}/lt`, data) + .then(response => { + resolve(response.data.token); + }) + .catch(reject); + }); +} + +/** + * Deletes a link token. + * @param {RailSystem} rs + * @param {Number} tokenId + */ +export function deleteToken(rs, tokenId) { + return new Promise((resolve, reject) => { + axios.delete(`${API_URL}/rs/${rs.id}/lt/${tokenId}`) + .then(resolve) + .catch(reject); + }); +} \ No newline at end of file diff --git a/railsignal-app/src/api/paths.js b/railsignal-app/src/api/paths.js index afd74f5..0e2db39 100644 --- a/railsignal-app/src/api/paths.js +++ b/railsignal-app/src/api/paths.js @@ -2,6 +2,12 @@ import axios from "axios"; import {API_URL} from "./constants"; import {refreshSomeComponents} from "./components"; +/** + * Updates the connections to a path node. + * @param {RailSystem} rs The rail system to which the node belongs. + * @param {Object} node The node to update. + * @returns {Promise} + */ export function updateConnections(rs, node) { return new Promise((resolve, reject) => { axios.patch( @@ -16,11 +22,25 @@ export function updateConnections(rs, node) { }); } +/** + * Adds a connection to a path node. + * @param {RailSystem} rs + * @param {Object} node + * @param {Object} other + * @returns {Promise} + */ export function addConnection(rs, node, other) { node.connectedNodes.push(other); return updateConnections(rs, node); } +/** + * Removes a connection from a path node. + * @param {RailSystem} rs + * @param {Object} node + * @param {Object} other + * @returns {Promise} + */ export function removeConnection(rs, node, other) { const idx = node.connectedNodes.findIndex(n => n.id === other.id); return new Promise((resolve, reject) => { diff --git a/railsignal-app/src/api/railSystems.js b/railsignal-app/src/api/railSystems.js index 10b8660..c01c1d9 100644 --- a/railsignal-app/src/api/railSystems.js +++ b/railsignal-app/src/api/railSystems.js @@ -1,11 +1,26 @@ import axios from "axios"; import {API_URL} from "./constants"; +export class RailSystem { + constructor(data) { + this.id = data.id; + this.name = data.name; + this.segments = []; + this.components = []; + this.websocket = null; + this.selectedComponent = null; + } +} + export function refreshRailSystems(rsStore) { return new Promise(resolve => { axios.get(`${API_URL}/rs`) .then(response => { - rsStore.railSystems = response.data; + const rsItems = response.data; + rsStore.railSystems.length = 0; + for (let i = 0; i < rsItems.length; i++) { + rsStore.railSystems.push(new RailSystem(rsItems[i])); + } resolve(); }) .catch(error => console.error(error)); diff --git a/railsignal-app/src/api/websocket.js b/railsignal-app/src/api/websocket.js index 3f4276d..741c548 100644 --- a/railsignal-app/src/api/websocket.js +++ b/railsignal-app/src/api/websocket.js @@ -1,9 +1,11 @@ import {WS_URL} from "./constants"; +/** + * Establishes a websocket connection to the given rail system. + * @param {RailSystem} rs + */ export function establishWebsocketConnection(rs) { - if (rs.websocket) { - rs.websocket.close(); - } + closeWebsocketConnection(rs); rs.websocket = new WebSocket(`${WS_URL}/${rs.id}`); rs.websocket.onopen = () => { console.log("Opened websocket connection to rail system " + rs.id); @@ -25,6 +27,10 @@ export function establishWebsocketConnection(rs) { }; } +/** + * Closes the websocket connection to a rail system, if possible. + * @param {RailSystem} rs + */ export function closeWebsocketConnection(rs) { if (rs.websocket) { rs.websocket.close(); diff --git a/railsignal-app/src/components/AppNavbar.vue b/railsignal-app/src/components/AppNavbar.vue index efc5878..b946953 100644 --- a/railsignal-app/src/components/AppNavbar.vue +++ b/railsignal-app/src/components/AppNavbar.vue @@ -15,6 +15,7 @@ id="railSystemSelect" v-model="rsStore.selectedRailSystem" class="form-select form-select-sm" + @change="rsStore.onSelectedRailSystemChanged()" >