From 4073e13428d295d9d69d9407609cd229f0dd25dc Mon Sep 17 00:00:00 2001 From: irismarie Date: Tue, 5 May 2020 17:05:39 +0200 Subject: [PATCH 1/9] Export data, see also #216 --- src/scenario/scenario.js | 35 ++++++++++++++------ src/scenario/scenarios.js | 68 +++++++++++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 15 deletions(-) diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 071c610..7b44f6c 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -40,10 +40,12 @@ import DeleteDialog from '../common/dialogs/delete-dialog'; import EditConfigDialog from "../componentconfig/edit-config"; import EditSignalMapping from "../signal/edit-signal-mapping"; import FileStore from "../file/file-store" +import WidgetStore from "../widget/widget-store"; class Scenario extends React.Component { + static getStores() { - return [ ScenarioStore, ConfigStore, DashboardStore, ICStore, LoginStore, SignalStore, FileStore]; + return [ ScenarioStore, ConfigStore, DashboardStore, ICStore, LoginStore, SignalStore, FileStore, WidgetStore]; } static calculateState(prevState, props) { @@ -96,7 +98,6 @@ class Scenario extends React.Component { } componentDidMount() { - //load selected scenario AppDispatcher.dispatch({ type: 'scenarios/start-load', @@ -108,25 +109,37 @@ class Scenario extends React.Component { AppDispatcher.dispatch({ type: 'configs/start-load', token: this.state.sessionToken, - param: '?scenarioID='+this.state.scenario.id, + param: '?scenarioID='+this.state.scenario.id }); // load dashboards of selected scenario AppDispatcher.dispatch({ type: 'dashboards/start-load', token: this.state.sessionToken, - param: '?scenarioID='+this.state.scenario.id, + param: '?scenarioID='+this.state.scenario.id }); // load ICs to enable that component configs work with them AppDispatcher.dispatch({ type: 'ics/start-load', - token: this.state.sessionToken, + token: this.state.sessionToken }); - - } + componentDidUpdate(prevProps, prevState) { + // load widgets when dashboard id(s) are available + if (this.state.dashboards.length !== prevState.dashboards.length) { + let dashboards = Object.assign([], this.state.dashboards); + dashboards.forEach(dboard => { + AppDispatcher.dispatch({ + type: 'widgets/start-load', + token: this.state.sessionToken, + param: '?dashboardID='+dboard.id + })}) + } + } + + /* ############################################## * Component Configuration modification methods ############################################## */ @@ -323,10 +336,14 @@ class Scenario extends React.Component { // filter properties const dashboard = Object.assign({}, this.state.dashboards[index]); - // TODO get elements recursively + let widgets = WidgetStore.getState().filter(w => w.dashboardID === parseInt(dashboard.id, 10)); + + var jsonObj = dashboard; + jsonObj["widgets"] = widgets; + // show save dialog - const blob = new Blob([JSON.stringify(dashboard, null, 2)], { type: 'application/json' }); + const blob = new Blob([JSON.stringify(jsonObj, null, 2)], { type: 'application/json' }); FileSaver.saveAs(blob, 'dashboard - ' + dashboard.name + '.json'); } diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index 8813190..4b1a5bd 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -23,6 +23,9 @@ import FileSaver from 'file-saver'; import AppDispatcher from '../common/app-dispatcher'; import ScenarioStore from './scenario-store'; import LoginStore from '../user/login-store'; +import DashboardStore from '../dashboard/dashboard-store'; +import WidgetStore from "../widget/widget-store"; +import ConfigStore from '../componentconfig/config-store'; import Icon from '../common/icon'; import Table from '../common/table'; @@ -33,17 +36,24 @@ import ImportScenarioDialog from './import-scenario'; import DeleteDialog from '../common/dialogs/delete-dialog'; + class Scenarios extends Component { + static getStores() { - return [ ScenarioStore, LoginStore ]; + return [ ScenarioStore, LoginStore, DashboardStore, WidgetStore, ConfigStore]; } static calculateState() { const scenarios = ScenarioStore.getState(); const sessionToken = LoginStore.getState().token; + let dashboards = DashboardStore.getState(); + let configs = ConfigStore.getState(); + return { scenarios, + dashboards, + configs, sessionToken, newModal: false, @@ -63,7 +73,37 @@ class Scenarios extends Component { }); } - componentDidUpdate() {} + componentDidUpdate(prevProps, prevState) { + // TODO check/change conditions + + // load dashboards when scanario(s) are available + if (this.state.scenarios.length !== prevState.scenarios.length) { + let scenarios = Object.assign([], this.state.scenarios); + scenarios.forEach(scenario => { + AppDispatcher.dispatch({ + type: 'dashboards/start-load', + token: this.state.sessionToken, + param: '?scenarioID='+scenario.id + }); + AppDispatcher.dispatch({ + type: 'scenarios/configs', + token: this.state.sessionToken, + param: '?scenarioID='+scenario.id + }); + }) + } + // load widgets when dashboard id(s) are available + if (this.state.dashboards.length !== prevState.dashboards.length) { + let dashboards = Object.assign([], this.state.dashboards); + dashboards.forEach(dboard => { + AppDispatcher.dispatch({ + type: 'widgets/start-load', + token: this.state.sessionToken, + param: '?dashboardID='+dboard.id + })}) + } + } + closeNewModal(data) { this.setState({ newModal : false }); @@ -150,14 +190,30 @@ class Scenarios extends Component { }; exportScenario(index) { - // filter properties let scenario = Object.assign({}, this.state.scenarios[index]); + let configs = this.state.configs.filter(config => config.scenarioID === scenario.id); + let dashboards = this.state.dashboards.filter(dashb => dashb.scenarioID === scenario.id); + + // create JSON object and add component configs delete scenario.id; + let jsonObj = scenario; + jsonObj["configs"] = configs; - // TODO request missing scenario parameters (Dashboards and component configs) recursively for export + // add Dashboards and Widgets to JSON object + let json_dashboards = dashboards; + json_dashboards.forEach((dboard) => { + let widgets = WidgetStore.getState().filter(w => w.dashboardID === parseInt(dboard.id, 10)); + widgets.forEach((widget) => { + delete widget.dashboardID; + }) + dboard["widgets"] = widgets; + delete dboard.scenarioID; + }); + jsonObj["dashboards"] = json_dashboards; - // show save dialog - const blob = new Blob([JSON.stringify(scenario, null, 2)], { type: 'application/json' }); + + // create JSON string and show save dialog + const blob = new Blob([JSON.stringify(jsonObj, null, 2)], { type: 'application/json' }); FileSaver.saveAs(blob, 'scenario - ' + scenario.name + '.json'); } From 730b3936716a39dbe1520e4588a4998595419c12 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Wed, 6 May 2020 11:06:04 +0200 Subject: [PATCH 2/9] small fix for configs dispatch and export function #216 --- src/scenario/scenarios.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index 4b1a5bd..db7555d 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -86,7 +86,7 @@ class Scenarios extends Component { param: '?scenarioID='+scenario.id }); AppDispatcher.dispatch({ - type: 'scenarios/configs', + type: 'configs/start-load', token: this.state.sessionToken, param: '?scenarioID='+scenario.id }); @@ -190,7 +190,8 @@ class Scenarios extends Component { }; exportScenario(index) { - let scenario = Object.assign({}, this.state.scenarios[index]); + console.log("exportScenario") + let scenario = this.state.scenarios[index]; let configs = this.state.configs.filter(config => config.scenarioID === scenario.id); let dashboards = this.state.dashboards.filter(dashb => dashb.scenarioID === scenario.id); From 967f17c4f3e6574ba8b1d915eb03080b2e763bf0 Mon Sep 17 00:00:00 2001 From: irismarie Date: Tue, 12 May 2020 20:45:54 +0200 Subject: [PATCH 3/9] Import Dashboard plus (#216): copy by value, delete IDs, restrict number of times loading data --- src/scenario/scenario.js | 45 ++++++++++++++++++++++++++++++--------- src/scenario/scenarios.js | 45 ++++++++++++++++++++------------------- 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 9c7d88a..005b859 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -140,15 +140,32 @@ class Scenario extends React.Component { } componentDidUpdate(prevProps, prevState) { - // load widgets when dashboard id(s) are available - if (this.state.dashboards.length !== prevState.dashboards.length) { - let dashboards = Object.assign([], this.state.dashboards); - dashboards.forEach(dboard => { - AppDispatcher.dispatch({ - type: 'widgets/start-load', - token: this.state.sessionToken, - param: '?dashboardID='+dboard.id - })}) + if (this.state.dashboards.length > prevState.dashboards.length) { + if (this.addWidgets) { // add widgets + // this can only be true after dashboard import, so there is only one dashboard + // (the newest) and this dashboards ID is used + let dashboardID = this.state.dashboards[this.state.dashboards.length - 1].id; + this.widgetsToAdd.forEach((widget) => { + widget.dashboardID = dashboardID; + AppDispatcher.dispatch({ + type: 'widgets/start-add', + data: widget, + token: this.state.sessionToken, + }) + }) + this.addWidgets = false; + this.widgetsToAdd = []; + } + else { // get widgets + let dashboards = Object.assign([], this.state.dashboards); + for (var i = prevState.dashboards.length; i < this.state.dashboards.length; i++) { + AppDispatcher.dispatch({ + type: 'widgets/start-load', + token: this.state.sessionToken, + param: '?dashboardID=' + dashboards[i].id + }) + } + } } } @@ -337,9 +354,17 @@ class Scenario extends React.Component { this.setState({ importDashboardModal: false }); if (data) { + let newDashboard = JSON.parse(JSON.stringify(data)); + newDashboard["scenarioID"] = this.state.scenario.id; + // temporarily store widget data until dashboard is created + if (data.widgets) { + this.addWidgets = true; + this.widgetsToAdd = data.widgets; + } + delete newDashboard.widgets; AppDispatcher.dispatch({ type: 'dashboards/start-add', - data, + data: newDashboard, token: this.state.sessionToken, }); } diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index db7555d..e054344 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -74,33 +74,32 @@ class Scenarios extends Component { } componentDidUpdate(prevProps, prevState) { - // TODO check/change conditions - - // load dashboards when scanario(s) are available - if (this.state.scenarios.length !== prevState.scenarios.length) { - let scenarios = Object.assign([], this.state.scenarios); - scenarios.forEach(scenario => { + // load dashboards when length of scanario array has increased + if (this.state.scenarios.length > prevState.scenarios.length) { + let scenarios = Object.assign([], this.state.scenarios); // copying neccessary? + for (var i = prevState.scenarios.length; i < scenarios.length; i++) { AppDispatcher.dispatch({ type: 'dashboards/start-load', token: this.state.sessionToken, - param: '?scenarioID='+scenario.id + param: '?scenarioID='+scenarios[i].id }); AppDispatcher.dispatch({ type: 'configs/start-load', token: this.state.sessionToken, - param: '?scenarioID='+scenario.id + param: '?scenarioID='+scenarios[i].id }); - }) + } } - // load widgets when dashboard id(s) are available - if (this.state.dashboards.length !== prevState.dashboards.length) { + // load widgets when length of dashboard array has increased + if (this.state.dashboards.length > prevState.dashboards.length) { let dashboards = Object.assign([], this.state.dashboards); - dashboards.forEach(dboard => { + for (var j = prevState.dashboards.length; j < dashboards.length; j++) { AppDispatcher.dispatch({ type: 'widgets/start-load', token: this.state.sessionToken, - param: '?dashboardID='+dboard.id - })}) + param: '?dashboardID='+dashboards[j].id + }) + } } } @@ -190,10 +189,11 @@ class Scenarios extends Component { }; exportScenario(index) { - console.log("exportScenario") - let scenario = this.state.scenarios[index]; - let configs = this.state.configs.filter(config => config.scenarioID === scenario.id); - let dashboards = this.state.dashboards.filter(dashb => dashb.scenarioID === scenario.id); + // copy by value by converting to JSON and back + // otherwise, IDs of state objects will be deleted + let scenario = JSON.parse(JSON.stringify(this.state.scenarios[index])); + let configs = JSON.parse(JSON.stringify(this.state.configs.filter(config => config.scenarioID === scenario.id))); + let dashboards = JSON.parse(JSON.stringify(this.state.dashboards.filter(dashb => dashb.scenarioID === scenario.id))); // create JSON object and add component configs delete scenario.id; @@ -201,16 +201,17 @@ class Scenarios extends Component { jsonObj["configs"] = configs; // add Dashboards and Widgets to JSON object - let json_dashboards = dashboards; - json_dashboards.forEach((dboard) => { - let widgets = WidgetStore.getState().filter(w => w.dashboardID === parseInt(dboard.id, 10)); + dashboards.forEach((dboard) => { + let widgets = JSON.parse(JSON.stringify(WidgetStore.getState().filter(w => w.dashboardID === parseInt(dboard.id, 10)))); widgets.forEach((widget) => { delete widget.dashboardID; + delete widget.id; }) dboard["widgets"] = widgets; delete dboard.scenarioID; + delete dboard.id; }); - jsonObj["dashboards"] = json_dashboards; + jsonObj["dashboards"] = dashboards; // create JSON string and show save dialog From fdb6a3105aff246c8f739ddf4aae88f6eeb4c5d2 Mon Sep 17 00:00:00 2001 From: irismarie Date: Wed, 20 May 2020 10:08:51 +0200 Subject: [PATCH 4/9] add scenario data after importing from file --- src/scenario/scenarios.js | 154 +++++++++++++++++++++++++++++--------- 1 file changed, 119 insertions(+), 35 deletions(-) diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index e054344..c00d8f6 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -40,7 +40,7 @@ import DeleteDialog from '../common/dialogs/delete-dialog'; class Scenarios extends Component { static getStores() { - return [ ScenarioStore, LoginStore, DashboardStore, WidgetStore, ConfigStore]; + return [ScenarioStore, LoginStore, DashboardStore, WidgetStore, ConfigStore]; } static calculateState() { @@ -74,46 +74,104 @@ class Scenarios extends Component { } componentDidUpdate(prevProps, prevState) { - // load dashboards when length of scanario array has increased + // when length of scenarios array has increased, either add data (after import) + // or load data (after export) if (this.state.scenarios.length > prevState.scenarios.length) { - let scenarios = Object.assign([], this.state.scenarios); // copying neccessary? - for (var i = prevState.scenarios.length; i < scenarios.length; i++) { - AppDispatcher.dispatch({ - type: 'dashboards/start-load', - token: this.state.sessionToken, - param: '?scenarioID='+scenarios[i].id - }); - AppDispatcher.dispatch({ - type: 'configs/start-load', - token: this.state.sessionToken, - param: '?scenarioID='+scenarios[i].id - }); + if (this.addDashboards || this.addConfigs) { + let scenarioID = this.state.scenarios[this.state.scenarios.length - 1].id; + + if (this.addDashboards) { + this.dashboardsToAdd.forEach((dashboard) => { + if (dashboard.widgets) { + this.addWidgets = true; + } + dashboard.scenarioID = scenarioID; + AppDispatcher.dispatch({ + type: 'dashboards/start-add', + token: this.state.sessionToken, + data: dashboard + }); + }) + this.addDashboards = false; + } + + if (this.addConfigs) { + this.configsToAdd.forEach((config) => { + config.scenarioID = scenarioID; + AppDispatcher.dispatch({ + type: 'configs/start-add', + token: this.state.sessionToken, + data: config + }) + }) + delete this.configsToAdd; + this.addConfigs = false; + } + + } + else { + let scenarios = Object.assign([], this.state.scenarios); // copying neccessary? + for (var i = prevState.scenarios.length; i < scenarios.length; i++) { + AppDispatcher.dispatch({ + type: 'dashboards/start-load', + token: this.state.sessionToken, + param: '?scenarioID=' + scenarios[i].id + }); + AppDispatcher.dispatch({ + type: 'configs/start-load', + token: this.state.sessionToken, + param: '?scenarioID=' + scenarios[i].id + }); + } } } - // load widgets when length of dashboard array has increased + + // when length of dashboards array has increased, either add widgets (after import) + // or load widgets (after export) if (this.state.dashboards.length > prevState.dashboards.length) { - let dashboards = Object.assign([], this.state.dashboards); - for (var j = prevState.dashboards.length; j < dashboards.length; j++) { - AppDispatcher.dispatch({ - type: 'widgets/start-load', - token: this.state.sessionToken, - param: '?dashboardID='+dashboards[j].id - }) + if (this.addWidgets && !this.addDashboards) { // add widget data + let dashboards = Object.assign([], this.state.dashboards); + for (var j = prevState.dashboards.length; j < dashboards.length; j++) { + let dboard = dashboards[j]; + let dboardID = dboard.id; + let dashboard = this.dashboardsToAdd.shift(); + if (dashboard.name !== dboard.name) { + console.log("Cannot add widgets, dashboard was not added as expected!"); + this.addWidgets = false; + return; + } + dashboard.widgets.forEach((widget) => { + widget.dashboardID = dboardID; + AppDispatcher.dispatch({ + type: 'widgets/start-add', + token: this.state.sessionToken, + data: widget + }); + }); + } + + if (this.dashboardsToAdd.length === 0) { + delete this.dashboardsToAdd; + this.addWidgets = false; + } } + else { // load widget data + let dashboards = Object.assign([], this.state.dashboards); + for (var j = prevState.dashboards.length; j < dashboards.length; j++) { + AppDispatcher.dispatch({ + type: 'widgets/start-load', + token: this.state.sessionToken, + param: '?dashboardID=' + dashboards[j].id + }) + } + } + } } closeNewModal(data) { - this.setState({ newModal : false }); - - if (data) { - AppDispatcher.dispatch({ - type: 'scenarios/start-add', - data, - token: this.state.sessionToken - }); - } + this.setState({ newModal: false }); } showDeleteModal(id) { @@ -136,6 +194,16 @@ class Scenarios extends Component { return; } + this.state.dashboards.forEach((dashboard) => { + if (dashboard.id === this.state.modalScenario.id) { + AppDispatcher.dispatch({ + type: 'dashboards/start-remove', + data: dashboard, + token: this.state.sessionToken + }) + } + }); + AppDispatcher.dispatch({ type: 'scenarios/start-remove', data: this.state.modalScenario, @@ -157,7 +225,7 @@ class Scenarios extends Component { } closeEditModal(data) { - this.setState({ editModal : false }); + this.setState({ editModal: false }); if (data != null) { AppDispatcher.dispatch({ @@ -172,10 +240,21 @@ class Scenarios extends Component { this.setState({ importModal: false }); if (data) { + let newScenario = JSON.parse(JSON.stringify(data)); + // temporarily store dashboard data until scenario is created + if (data.dashboards) { + this.addDashboards = true; + this.dashboardsToAdd = data.dashboards; + } + if (data.configs) { + this.addConfigs = true; + this.configsToAdd = data.configs; + } + delete newScenario.dashboards; AppDispatcher.dispatch({ type: 'scenarios/start-add', - data, - token: this.state.sessionToken + data: newScenario, + token: this.state.sessionToken, }); } } @@ -198,10 +277,15 @@ class Scenarios extends Component { // create JSON object and add component configs delete scenario.id; let jsonObj = scenario; + + configs.forEach((config) => { + delete config.id; + delete config.scenarioID; + }) jsonObj["configs"] = configs; // add Dashboards and Widgets to JSON object - dashboards.forEach((dboard) => { + dashboards.forEach((dboard) => { let widgets = JSON.parse(JSON.stringify(WidgetStore.getState().filter(w => w.dashboardID === parseInt(dboard.id, 10)))); widgets.forEach((widget) => { delete widget.dashboardID; From 06b091a73b71eba2d88cd0ba2e0b53b778771234 Mon Sep 17 00:00:00 2001 From: irismarie Date: Wed, 20 May 2020 10:10:11 +0200 Subject: [PATCH 5/9] add more values to state --- src/scenario/import-scenario.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scenario/import-scenario.js b/src/scenario/import-scenario.js index 1e454eb..90c33be 100644 --- a/src/scenario/import-scenario.js +++ b/src/scenario/import-scenario.js @@ -32,6 +32,7 @@ class ImportScenarioDialog extends React.Component { name: '', running: '', configs: [], + dashboards: [], startParameters: {} }; } @@ -94,7 +95,7 @@ class ImportScenarioDialog extends React.Component { self.imported = true; self.valid = true; - self.setState({ name: scenario.name, configs: scenario.configs, startParameters: scenario.startParameters, running: scenario.running }); + self.setState({ name: scenario.name, configs: scenario.configs, dashboards: scenario.dashboards, startParameters: scenario.startParameters, running: scenario.running }); }; reader.readAsText(file); From 704c36ab90b792a56354a631aa61518c851431dd Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Thu, 28 May 2020 11:27:21 +0200 Subject: [PATCH 6/9] Move import logic from Iris to RestDataManager and object stores (to be tested!) --- src/common/data-managers/rest-data-manager.js | 39 ++++++++++++++- src/componentconfig/config-store.js | 29 ++++++++++++ src/dashboard/dashboard-store.js | 37 ++++++++++++++- src/scenario/scenario-store.js | 47 ++++++++++++++++++- src/scenario/scenarios.js | 33 +++++++++++-- 5 files changed, 177 insertions(+), 8 deletions(-) diff --git a/src/common/data-managers/rest-data-manager.js b/src/common/data-managers/rest-data-manager.js index 271f4c6..5076fb8 100644 --- a/src/common/data-managers/rest-data-manager.js +++ b/src/common/data-managers/rest-data-manager.js @@ -133,16 +133,51 @@ class RestDataManager { } - add(object, token = null, param = null) { + add(object, token = null, param = null, subObjects = null) { var obj = {}; obj[this.type] = this.filterKeys(object); - RestAPI.post(this.requestURL('load/add',null,param), obj, token).then(response => { AppDispatcher.dispatch({ type: this.type + 's/added', data: response[this.type], token: token }); + + // check if POST is done for import of object and issue dispatches of sub-objects + if (subObjects !== null){ + // there are sub-objects to be added for an import + for (let objectType of subObjects){ + let type = Object.keys(objectType) // type can be dashboards, configs, widgets, ... + type = type[0]; + for (let newObj of objectType[type]){ + + // set the ID of the object that the sub-object shall be associated with + if(type === "configs" || type === "dashboards"){ + // the main object is a scenario + newObj.scenarioID = response[this.type].id + } else if (type === "widgets") { + // the main object is a dashboard + newObj.dashboardID = response[this.type].id + } else if (type === "signals") { + // the main object is a component configuration + newObj.configID = response[this.type].id + } + + console.log("Adding new object of type", type, "with content", newObj, "to object of type ", this.type, "with ID ", response[this.type].id) + // iterate over all objects of type 'type' add issue add dispatch + AppDispatcher.dispatch({ + type: type + '/start-add', + data: newObj, + token: token + }) + + } + } + + + } + + }).catch(error => { AppDispatcher.dispatch({ type: this.type + 's/add-error', diff --git a/src/componentconfig/config-store.js b/src/componentconfig/config-store.js index b67377d..990275d 100644 --- a/src/componentconfig/config-store.js +++ b/src/componentconfig/config-store.js @@ -33,6 +33,35 @@ class ConfigStore extends ArrayStore { ConfigsDataManager.loadFiles(action.token, action.data); return super.reduce(state, action); + case 'configs/start-add': + // Check if this is a recursive component config import or not + if (action.data.hasOwnProperty("outputMapping") || action.data.hasOwnProperty("inputMapping")) { + // import + let subObjects = [] + let outputMapping = {} + let inputMapping = {} + + if (action.data.hasOwnProperty("outputMapping")){ + outputMapping["signals"] = action.data.outputMapping + subObjects.push(outputMapping) + delete action.data.outputMapping; // remove outputMapping signals from config object + } + if (action.data.hasOwnProperty("inputMapping")){ + inputMapping["signals"] = action.data.inputMapping + subObjects.push(inputMapping) + delete action.data.inputMapping; // remove inputMapping signals from config object + } + + // action.data should now contain the config and no sub-objects + // sub-objects are treated in add method of RestDataManager + this.dataManager.add(action.data, action.token,action.param, subObjects); + return state + + } else { + // no import + return super.reduce(state, action); + } + default: return super.reduce(state, action); diff --git a/src/dashboard/dashboard-store.js b/src/dashboard/dashboard-store.js index 4e850ab..23b28d6 100644 --- a/src/dashboard/dashboard-store.js +++ b/src/dashboard/dashboard-store.js @@ -18,4 +18,39 @@ import ArrayStore from '../common/array-store'; import DashboardsDataManager from './dashboards-data-manager'; -export default new ArrayStore('dashboards', DashboardsDataManager); +class DashboardStore extends ArrayStore { + constructor() { + super('dashboards', DashboardsDataManager); + } + + reduce(state, action) { + switch (action.type) { + case 'dashboards/start-add': + + // Check if this is a recursive dashboard import or not + if (action.data.hasOwnProperty("widgets")) { + // import + let subObjects = [] + let widgets = {} + widgets["widgets"] = action.data.widgets + subObjects.push(widgets) + delete action.data.widgets; // remove widgets from dashboard object + + // action.data should now contain the dashboard and no sub-objects + // sub-objects are treated in add method of RestDataManager + this.dataManager.add(action.data, action.token,action.param, subObjects); + return state + + } else { + // no import + return super.reduce(state, action); + } + + default: + return super.reduce(state, action); + } + } + +} + +export default new DashboardStore(); diff --git a/src/scenario/scenario-store.js b/src/scenario/scenario-store.js index 777475c..6043b68 100644 --- a/src/scenario/scenario-store.js +++ b/src/scenario/scenario-store.js @@ -19,4 +19,49 @@ import ScenariosDataManager from './scenarios-data-manager'; import ArrayStore from '../common/array-store'; -export default new ArrayStore('scenarios', ScenariosDataManager); +class ScenarioStore extends ArrayStore{ + constructor() { + super('scenarios', ScenariosDataManager); + } + + reduce(state, action) { + switch (action.type) { + case 'scenarios/start-add': + + // Check if this is a recursive scenario import or not + if (action.data.hasOwnProperty("configs") || action.data.hasOwnProperty("dashboards")) { + // import + let subObjects = [] + let configs = {} + let dashboards = {} + + if (action.data.hasOwnProperty("configs")){ + configs["configs"] = action.data.configs + subObjects.push(configs) + delete action.data.configs; // remove configs from scenario object + } + if (action.data.hasOwnProperty("dashboards")){ + dashboards["dashboards"] = action.data.dashboards + subObjects.push(dashboards) + delete action.data.dashboards; // remove dashboards from scenario object + } + + // action.data should now contain the scenario and no sub-objects + // sub-objects are treated in add method of RestDataManager + this.dataManager.add(action.data, action.token,action.param, subObjects); + return state + + } else { + // no import + return super.reduce(state, action); + } + + default: + return super.reduce(state, action); + } + } + + +} + +export default new ScenarioStore(); diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index c00d8f6..19688bc 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -74,12 +74,27 @@ class Scenarios extends Component { } componentDidUpdate(prevProps, prevState) { + + for (let i = prevState.scenarios.length; i < this.state.scenarios.length; i++) { + AppDispatcher.dispatch({ + type: 'dashboards/start-load', + token: this.state.sessionToken, + param: '?scenarioID=' + this.state.scenarios[i].id + }); + AppDispatcher.dispatch({ + type: 'configs/start-load', + token: this.state.sessionToken, + param: '?scenarioID=' + this.state.scenarios[i].id + }); + } + // when length of scenarios array has increased, either add data (after import) // or load data (after export) + /* if (this.state.scenarios.length > prevState.scenarios.length) { if (this.addDashboards || this.addConfigs) { let scenarioID = this.state.scenarios[this.state.scenarios.length - 1].id; - + if (this.addDashboards) { this.dashboardsToAdd.forEach((dashboard) => { if (dashboard.widgets) { @@ -124,8 +139,11 @@ class Scenarios extends Component { }); } } + + } + // when length of dashboards array has increased, either add widgets (after import) // or load widgets (after export) if (this.state.dashboards.length > prevState.dashboards.length) { @@ -167,11 +185,16 @@ class Scenarios extends Component { } } + + + */ } closeNewModal(data) { this.setState({ newModal: false }); + + // TODO create dispatch here to add scenario to Backend database! } showDeleteModal(id) { @@ -240,9 +263,9 @@ class Scenarios extends Component { this.setState({ importModal: false }); if (data) { - let newScenario = JSON.parse(JSON.stringify(data)); + //let newScenario = JSON.parse(JSON.stringify(data)); // temporarily store dashboard data until scenario is created - if (data.dashboards) { + /*if (data.dashboards) { this.addDashboards = true; this.dashboardsToAdd = data.dashboards; } @@ -251,9 +274,11 @@ class Scenarios extends Component { this.configsToAdd = data.configs; } delete newScenario.dashboards; + */ + AppDispatcher.dispatch({ type: 'scenarios/start-add', - data: newScenario, + data: data, token: this.state.sessionToken, }); } From 01edd657104c0c8e71203527f7d12c1b0e09d1b5 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Fri, 29 May 2020 10:07:53 +0200 Subject: [PATCH 7/9] Scenario import and export working #216 --- src/common/data-managers/rest-data-manager.js | 5 +- src/componentconfig/config-store.js | 1 - src/componentconfig/configs-data-manager.js | 44 ++--- src/dashboard/dashboard-store.js | 1 + src/dashboard/dashboards-data-manager.js | 27 ++- src/scenario/import-scenario.js | 9 - src/scenario/scenario-store.js | 1 + src/scenario/scenarios-data-manager.js | 49 +++-- src/scenario/scenarios.js | 172 +++--------------- 9 files changed, 98 insertions(+), 211 deletions(-) diff --git a/src/common/data-managers/rest-data-manager.js b/src/common/data-managers/rest-data-manager.js index 5076fb8..fb23eff 100644 --- a/src/common/data-managers/rest-data-manager.js +++ b/src/common/data-managers/rest-data-manager.js @@ -99,7 +99,7 @@ class RestDataManager { }); if (this.onLoad != null) { - this.onLoad(data); + this.onLoad(data, token); } }).catch(error => { AppDispatcher.dispatch({ @@ -121,7 +121,7 @@ class RestDataManager { }); if (this.onLoad != null) { - this.onLoad(data); + this.onLoad(data, token); } }).catch(error => { AppDispatcher.dispatch({ @@ -163,7 +163,6 @@ class RestDataManager { newObj.configID = response[this.type].id } - console.log("Adding new object of type", type, "with content", newObj, "to object of type ", this.type, "with ID ", response[this.type].id) // iterate over all objects of type 'type' add issue add dispatch AppDispatcher.dispatch({ type: type + '/start-add', diff --git a/src/componentconfig/config-store.js b/src/componentconfig/config-store.js index 990275d..6a1911e 100644 --- a/src/componentconfig/config-store.js +++ b/src/componentconfig/config-store.js @@ -29,7 +29,6 @@ class ConfigStore extends ArrayStore { case 'configs/loaded': - ConfigsDataManager.loadSignals(action.token, action.data); ConfigsDataManager.loadFiles(action.token, action.data); return super.reduce(state, action); diff --git a/src/componentconfig/configs-data-manager.js b/src/componentconfig/configs-data-manager.js index c0ac6c9..64245a8 100644 --- a/src/componentconfig/configs-data-manager.js +++ b/src/componentconfig/configs-data-manager.js @@ -26,43 +26,35 @@ class ConfigDataManager extends RestDataManager { this.onLoad = this.onConfigsLoad; } - onConfigsLoad(data) { + onConfigsLoad(data, token) { if (!Array.isArray(data)) data = [ data ]; - for (let config of data) - this.loadICData(config); - } + for (let config of data) { - loadICData(config) { - AppDispatcher.dispatch({ - type: 'icData/prepare', - inputLength: parseInt(config.inputLength, 10), - outputLength: parseInt(config.outputLength, 10), - id: config.icID - }); - } + // prepare IC data + AppDispatcher.dispatch({ + type: 'icData/prepare', + inputLength: parseInt(config.inputLength, 10), + outputLength: parseInt(config.outputLength, 10), + id: config.icID + }); - loadSignals(token, configs){ - - for (let config of configs) { // request in signals - RestAPI.get(this.makeURL('/signals?direction=in&configID=' + config.id), token).then(response => { - AppDispatcher.dispatch({ - type: 'signals/loaded', - data: response.signals - }); + AppDispatcher.dispatch({ + type: 'signals/start-load', + token: token, + param: '?direction=in&configID=' + config.id, }); // request out signals - RestAPI.get(this.makeURL('/signals?direction=out&configID=' + config.id), token).then(response => { - AppDispatcher.dispatch({ - type: 'signals/loaded', - data: response.signals - }); + AppDispatcher.dispatch({ + type: 'signals/start-load', + token: token, + param: '?direction=out&configID=' + config.id, }); - } + } loadFiles(token, configs){ diff --git a/src/dashboard/dashboard-store.js b/src/dashboard/dashboard-store.js index 23b28d6..5219135 100644 --- a/src/dashboard/dashboard-store.js +++ b/src/dashboard/dashboard-store.js @@ -24,6 +24,7 @@ class DashboardStore extends ArrayStore { } reduce(state, action) { + switch (action.type) { case 'dashboards/start-add': diff --git a/src/dashboard/dashboards-data-manager.js b/src/dashboard/dashboards-data-manager.js index b35c58d..94c847f 100644 --- a/src/dashboard/dashboards-data-manager.js +++ b/src/dashboard/dashboards-data-manager.js @@ -16,5 +16,30 @@ ******************************************************************************/ import RestDataManager from '../common/data-managers/rest-data-manager'; +import AppDispatcher from "../common/app-dispatcher"; -export default new RestDataManager('dashboard', '/dashboards'); +class DashboardsDataManager extends RestDataManager{ + constructor() { + super('dashboard', '/dashboards'); + this.onLoad = this.onDashboardsLoad + } + + onDashboardsLoad(data, token){ + + if (!Array.isArray(data)) { + data = [data]; + } + + console.log("onDashboardsLoad"); + for (let dashboard of data){ + AppDispatcher.dispatch({ + type: 'widgets/start-load', + token: token, + param: '?dashboardID=' + dashboard.id + }); + } + } + +} + +export default new DashboardsDataManager(); diff --git a/src/scenario/import-scenario.js b/src/scenario/import-scenario.js index 90c33be..a6b9a23 100644 --- a/src/scenario/import-scenario.js +++ b/src/scenario/import-scenario.js @@ -52,15 +52,6 @@ class ImportScenarioDialog extends React.Component { } handleChange(e, index) { - /*if (e.target.id === 'icID') { - const configs = this.state.configs; - configs[index].icID = JSON.parse(e.target.value); - - this.setState({ configs: configs }); - - return; - }*/ - this.setState({ [e.target.id]: e.target.value }); // check all controls diff --git a/src/scenario/scenario-store.js b/src/scenario/scenario-store.js index 6043b68..15a14f3 100644 --- a/src/scenario/scenario-store.js +++ b/src/scenario/scenario-store.js @@ -26,6 +26,7 @@ class ScenarioStore extends ArrayStore{ reduce(state, action) { switch (action.type) { + case 'scenarios/start-add': // Check if this is a recursive scenario import or not diff --git a/src/scenario/scenarios-data-manager.js b/src/scenario/scenarios-data-manager.js index ec4a442..a59d9a4 100644 --- a/src/scenario/scenarios-data-manager.js +++ b/src/scenario/scenarios-data-manager.js @@ -16,41 +16,36 @@ ******************************************************************************/ import RestDataManager from '../common/data-managers/rest-data-manager'; -import RestAPI from "../common/api/rest-api"; import AppDispatcher from "../common/app-dispatcher"; class ScenariosDataManager extends RestDataManager { constructor() { super('scenario', '/scenarios'); + + this.onLoad = this.onScenariosLoad } - getComponentConfigs(token, id) { - RestAPI.get(this.makeURL('/scenarios/' + id + '/configs'), token).then(response => { - AppDispatcher.dispatch({ - type: 'scenarios/configs', - configs: response.configs - }); - }).catch(error => { - AppDispatcher.dispatch({ - type: 'scenarios/configs-error', - error: error - }); - }); - } + onScenariosLoad(data, token){ - getDashboards(token, id) { - RestAPI.get(this.makeURL('/scenarios/' + id + '/dashboards'), token).then(response => { - AppDispatcher.dispatch({ - type: 'scenarios/dashboards', - dashboards: response.dashboards - }); - }).catch(error => { - AppDispatcher.dispatch({ - type: 'scenarios/dashboards-error', - error: error - }); - }); - } + if (!Array.isArray(data)) { + data = [data]; + } + for (let scenario of data){ + AppDispatcher.dispatch({ + type: 'configs/start-load', + token: token, + param: '?scenarioID=' + scenario.id + }); + + AppDispatcher.dispatch({ + type: 'dashboards/start-load', + token: token, + param: '?scenarioID=' + scenario.id + }); + + // TODO add dispatch for files + } + } } export default new ScenariosDataManager(); diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index 19688bc..84fc34c 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -26,6 +26,7 @@ import LoginStore from '../user/login-store'; import DashboardStore from '../dashboard/dashboard-store'; import WidgetStore from "../widget/widget-store"; import ConfigStore from '../componentconfig/config-store'; +import SignalStore from '../signal/signal-store' import Icon from '../common/icon'; import Table from '../common/table'; @@ -40,21 +41,16 @@ import DeleteDialog from '../common/dialogs/delete-dialog'; class Scenarios extends Component { static getStores() { - return [ScenarioStore, LoginStore, DashboardStore, WidgetStore, ConfigStore]; + return [ScenarioStore, LoginStore, DashboardStore, WidgetStore, ConfigStore, SignalStore]; } static calculateState() { - const scenarios = ScenarioStore.getState(); - const sessionToken = LoginStore.getState().token; - - let dashboards = DashboardStore.getState(); - let configs = ConfigStore.getState(); return { - scenarios, - dashboards, - configs, - sessionToken, + scenarios: ScenarioStore.getState(), + dashboards: DashboardStore.getState(), + configs: ConfigStore.getState(), + sessionToken: LoginStore.getState().token, newModal: false, deleteModal: false, @@ -73,133 +69,20 @@ class Scenarios extends Component { }); } - componentDidUpdate(prevProps, prevState) { - - for (let i = prevState.scenarios.length; i < this.state.scenarios.length; i++) { - AppDispatcher.dispatch({ - type: 'dashboards/start-load', - token: this.state.sessionToken, - param: '?scenarioID=' + this.state.scenarios[i].id - }); - AppDispatcher.dispatch({ - type: 'configs/start-load', - token: this.state.sessionToken, - param: '?scenarioID=' + this.state.scenarios[i].id - }); - } - - // when length of scenarios array has increased, either add data (after import) - // or load data (after export) - /* - if (this.state.scenarios.length > prevState.scenarios.length) { - if (this.addDashboards || this.addConfigs) { - let scenarioID = this.state.scenarios[this.state.scenarios.length - 1].id; - - if (this.addDashboards) { - this.dashboardsToAdd.forEach((dashboard) => { - if (dashboard.widgets) { - this.addWidgets = true; - } - dashboard.scenarioID = scenarioID; - AppDispatcher.dispatch({ - type: 'dashboards/start-add', - token: this.state.sessionToken, - data: dashboard - }); - }) - this.addDashboards = false; - } - - if (this.addConfigs) { - this.configsToAdd.forEach((config) => { - config.scenarioID = scenarioID; - AppDispatcher.dispatch({ - type: 'configs/start-add', - token: this.state.sessionToken, - data: config - }) - }) - delete this.configsToAdd; - this.addConfigs = false; - } - - } - else { - let scenarios = Object.assign([], this.state.scenarios); // copying neccessary? - for (var i = prevState.scenarios.length; i < scenarios.length; i++) { - AppDispatcher.dispatch({ - type: 'dashboards/start-load', - token: this.state.sessionToken, - param: '?scenarioID=' + scenarios[i].id - }); - AppDispatcher.dispatch({ - type: 'configs/start-load', - token: this.state.sessionToken, - param: '?scenarioID=' + scenarios[i].id - }); - } - } - - - } - - - // when length of dashboards array has increased, either add widgets (after import) - // or load widgets (after export) - if (this.state.dashboards.length > prevState.dashboards.length) { - if (this.addWidgets && !this.addDashboards) { // add widget data - let dashboards = Object.assign([], this.state.dashboards); - for (var j = prevState.dashboards.length; j < dashboards.length; j++) { - let dboard = dashboards[j]; - let dboardID = dboard.id; - let dashboard = this.dashboardsToAdd.shift(); - if (dashboard.name !== dboard.name) { - console.log("Cannot add widgets, dashboard was not added as expected!"); - this.addWidgets = false; - return; - } - dashboard.widgets.forEach((widget) => { - widget.dashboardID = dboardID; - AppDispatcher.dispatch({ - type: 'widgets/start-add', - token: this.state.sessionToken, - data: widget - }); - }); - } - - if (this.dashboardsToAdd.length === 0) { - delete this.dashboardsToAdd; - this.addWidgets = false; - } - } - else { // load widget data - let dashboards = Object.assign([], this.state.dashboards); - for (var j = prevState.dashboards.length; j < dashboards.length; j++) { - AppDispatcher.dispatch({ - type: 'widgets/start-load', - token: this.state.sessionToken, - param: '?dashboardID=' + dashboards[j].id - }) - } - } - - } - - - */ - } - - closeNewModal(data) { + if(data) { + AppDispatcher.dispatch({ + type: 'scenarios/start-add', + data: data, + token: this.state.sessionToken, + }); + } this.setState({ newModal: false }); - - // TODO create dispatch here to add scenario to Backend database! } showDeleteModal(id) { // get scenario by id - var deleteScenario; + let deleteScenario; this.state.scenarios.forEach((scenario) => { if (scenario.id === id) { @@ -263,19 +146,6 @@ class Scenarios extends Component { this.setState({ importModal: false }); if (data) { - //let newScenario = JSON.parse(JSON.stringify(data)); - // temporarily store dashboard data until scenario is created - /*if (data.dashboards) { - this.addDashboards = true; - this.dashboardsToAdd = data.dashboards; - } - if (data.configs) { - this.addConfigs = true; - this.configsToAdd = data.configs; - } - delete newScenario.dashboards; - */ - AppDispatcher.dispatch({ type: 'scenarios/start-add', data: data, @@ -304,6 +174,20 @@ class Scenarios extends Component { let jsonObj = scenario; configs.forEach((config) => { + let signals = JSON.parse(JSON.stringify(SignalStore.getState().filter(s => s.configID === parseInt(config.id, 10)))); + signals.forEach((signal) => { + delete signal.configID; + delete signal.id; + }) + + // two separate lists for inputMapping and outputMapping + let inputSignals = signals.filter(s => s.direction === 'in'); + let outputSignals = signals.filter(s => s.direction === 'out'); + + // add signal mappings to config + config["inputMapping"] = inputSignals; + config["outputMapping"] = outputSignals; + delete config.id; delete config.scenarioID; }) From 342ed5d83d6163fb02e49f6720a7f598b3915ae4 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Fri, 29 May 2020 10:27:09 +0200 Subject: [PATCH 8/9] Dashboard import export working #216 --- src/dashboard/import-dashboard.js | 44 +++++++++++++------------------ 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/dashboard/import-dashboard.js b/src/dashboard/import-dashboard.js index b44e1f8..47e5216 100644 --- a/src/dashboard/import-dashboard.js +++ b/src/dashboard/import-dashboard.js @@ -67,27 +67,6 @@ class ImportDashboardDialog extends React.Component { // read IC const dashboard = JSON.parse(event.target.result); - /*let defaultIC = ""; - if (self.props.configs != null) { - defaultIC = self.props.configs[0].icID; - } - - dashboard.widgets.forEach(widget => { - switch (widget.type) { - case 'Value': - case 'Plot': - case 'Table': - case 'PlotTable': - case 'Gauge': - break; - - default: - break; - } - }); - - */ - self.imported = true; self.valid = true; self.setState({ name: dashboard.name, widgets: dashboard.widgets, grid: dashboard.grid }); @@ -107,21 +86,36 @@ class ImportDashboardDialog extends React.Component { this.valid = name; // return state to control - if (target === 'name') return name ? "success" : "error"; + if (target === 'name'){ + return name; + } } render() { return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> + this.onClose(c)} + onReset={() => this.resetState()} + valid={this.valid}>
Dashboard File this.loadFile(e.target.files)} /> - + Name - this.handleChange(e)} /> + this.handleChange(e)} + /> From 7241e2c01b9884ebf9c35c91c98403a42de13382 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Fri, 29 May 2020 11:33:49 +0200 Subject: [PATCH 9/9] Component Config import and export working #216 --- src/componentconfig/import-config.js | 65 +++++++++----- src/dashboard/dashboards-data-manager.js | 1 - src/scenario/scenario.js | 108 ++++++++--------------- src/scenario/scenarios.js | 2 + src/signal/signals-data-manager.js | 1 - 5 files changed, 83 insertions(+), 94 deletions(-) diff --git a/src/componentconfig/import-config.js b/src/componentconfig/import-config.js index 89c1986..b11a69e 100644 --- a/src/componentconfig/import-config.js +++ b/src/componentconfig/import-config.js @@ -17,18 +17,19 @@ import React from 'react'; import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; -import _ from 'lodash'; import Dialog from '../common/dialogs/dialog'; class ImportConfigDialog extends React.Component { imported = false; + valid = false; constructor(props) { super(props); this.state = { - config: {} + config: {}, + name: '', }; } @@ -39,12 +40,13 @@ class ImportConfigDialog extends React.Component { return; } - this.props.onClose(this.state.config); + this.props.onClose(this.state); } resetState = () => { this.setState({ - config: {} + config: {}, + name: '' }); this.imported = false; @@ -58,46 +60,65 @@ class ImportConfigDialog extends React.Component { } // create file reader - const reader = new FileReader(); - const self = this; + let reader = new FileReader(); + let self = this; reader.onload = event => { const config = JSON.parse(event.target.result); - config.icID = this.props.ics.length > 0 ? this.props.ics[0]._id : null; - self.imported = true; - - this.setState({ config: config }); + self.valid = true; + this.setState({name: config.name, config: config }); }; reader.readAsText(file); } - handleICChange = event => { - const config = this.state.config; + handleChange(e, index) { + this.setState({ [e.target.id]: e.target.value }); + } - config.icID = event.target.value; + validateForm(target) { + // check all controls + let name = true; - this.setState({ config: config }); + if (this.state.name === '') { + name = false; + } + this.valid = name; + + // return state to control + if (target === 'name'){ + return name; + } } render() { return ( - this.onClose(c)} onReset={this.resetState} valid={this.imported}> + this.onClose(c)} + onReset={() => this.resetState()} + valid={this.valid} >
Component Configuration File - - Infrastructure Component - - {this.props.ics.map(ic => ( - - ))} - + + Name + this.handleChange(e)} + /> +
diff --git a/src/dashboard/dashboards-data-manager.js b/src/dashboard/dashboards-data-manager.js index 94c847f..451d3bf 100644 --- a/src/dashboard/dashboards-data-manager.js +++ b/src/dashboard/dashboards-data-manager.js @@ -30,7 +30,6 @@ class DashboardsDataManager extends RestDataManager{ data = [data]; } - console.log("onDashboardsLoad"); for (let dashboard of data){ AppDispatcher.dispatch({ type: 'widgets/start-load', diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 005b859..ed20600 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -118,20 +118,6 @@ class Scenario extends React.Component { token: this.state.sessionToken }); - // load component configurations for selected scenario - AppDispatcher.dispatch({ - type: 'configs/start-load', - token: this.state.sessionToken, - param: '?scenarioID='+this.state.scenario.id - }); - - // load dashboards of selected scenario - AppDispatcher.dispatch({ - type: 'dashboards/start-load', - token: this.state.sessionToken, - param: '?scenarioID='+this.state.scenario.id - }); - // load ICs to enable that component configs and dashboards work with them AppDispatcher.dispatch({ type: 'ics/start-load', @@ -139,36 +125,6 @@ class Scenario extends React.Component { }); } - componentDidUpdate(prevProps, prevState) { - if (this.state.dashboards.length > prevState.dashboards.length) { - if (this.addWidgets) { // add widgets - // this can only be true after dashboard import, so there is only one dashboard - // (the newest) and this dashboards ID is used - let dashboardID = this.state.dashboards[this.state.dashboards.length - 1].id; - this.widgetsToAdd.forEach((widget) => { - widget.dashboardID = dashboardID; - AppDispatcher.dispatch({ - type: 'widgets/start-add', - data: widget, - token: this.state.sessionToken, - }) - }) - this.addWidgets = false; - this.widgetsToAdd = []; - } - else { // get widgets - let dashboards = Object.assign([], this.state.dashboards); - for (var i = prevState.dashboards.length; i < this.state.dashboards.length; i++) { - AppDispatcher.dispatch({ - type: 'widgets/start-load', - token: this.state.sessionToken, - param: '?dashboardID=' + dashboards[i].id - }) - } - } - } - } - /* ############################################## * Component Configuration modification methods @@ -223,33 +179,47 @@ class Scenario extends React.Component { }); } - importConfig(config){ + importConfig(data){ this.setState({ importConfigModal: false }); - if (config == null) { + if (data == null) { return; } - config.scenario = this.state.scenario.id; + let newConfig = JSON.parse(JSON.stringify(data.config)) + + newConfig["scenarioID"] = this.state.scenario.id; + newConfig.name = data.name; AppDispatcher.dispatch({ type: 'configs/start-add', - data: config, + data: newConfig, token: this.state.sessionToken }); - - this.setState({ scenario: {} }, () => { - AppDispatcher.dispatch({ - type: 'scenarios/start-load', - data: this.props.match.params.scenario, - token: this.state.sessionToken - }); - }); } exportConfig(index) { // filter properties - const config = Object.assign({}, this.state.configs[index]); + let config = JSON.parse(JSON.stringify(this.state.configs[index])); + + let signals = JSON.parse(JSON.stringify(SignalStore.getState().filter(s => s.configID === parseInt(config.id, 10)))); + signals.forEach((signal) => { + delete signal.configID; + delete signal.id; + }) + + // two separate lists for inputMapping and outputMapping + let inputSignals = signals.filter(s => s.direction === 'in'); + let outputSignals = signals.filter(s => s.direction === 'out'); + + // add signal mappings to config + config["inputMapping"] = inputSignals; + config["outputMapping"] = outputSignals; + + delete config.id; + delete config.scenarioID; + delete config.inputLength; + delete config.outputLength; // show save dialog const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' }); @@ -356,12 +326,7 @@ class Scenario extends React.Component { if (data) { let newDashboard = JSON.parse(JSON.stringify(data)); newDashboard["scenarioID"] = this.state.scenario.id; - // temporarily store widget data until dashboard is created - if (data.widgets) { - this.addWidgets = true; - this.widgetsToAdd = data.widgets; - } - delete newDashboard.widgets; + AppDispatcher.dispatch({ type: 'dashboards/start-add', data: newDashboard, @@ -372,16 +337,19 @@ class Scenario extends React.Component { exportDashboard(index) { // filter properties - const dashboard = Object.assign({}, this.state.dashboards[index]); + let dashboard = JSON.parse(JSON.stringify(this.state.dashboards[index])); - let widgets = WidgetStore.getState().filter(w => w.dashboardID === parseInt(dashboard.id, 10)); + let widgets = JSON.parse(JSON.stringify(WidgetStore.getState().filter(w => w.dashboardID === parseInt(dashboard.id, 10)))); + widgets.forEach((widget) => { + delete widget.dashboardID; + delete widget.id; + }) + dashboard["widgets"] = widgets; + delete dashboard.scenarioID; + delete dashboard.id; - - var jsonObj = dashboard; - jsonObj["widgets"] = widgets; - // show save dialog - const blob = new Blob([JSON.stringify(jsonObj, null, 2)], { type: 'application/json' }); + const blob = new Blob([JSON.stringify(dashboard, null, 2)], { type: 'application/json' }); FileSaver.saveAs(blob, 'dashboard - ' + dashboard.name + '.json'); } diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index 84fc34c..22711a7 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -190,6 +190,8 @@ class Scenarios extends Component { delete config.id; delete config.scenarioID; + delete config.inputLength; + delete config.outputLength; }) jsonObj["configs"] = configs; diff --git a/src/signal/signals-data-manager.js b/src/signal/signals-data-manager.js index 768bc7a..2e6cf98 100644 --- a/src/signal/signals-data-manager.js +++ b/src/signal/signals-data-manager.js @@ -27,7 +27,6 @@ class SignalsDataManager extends RestDataManager{ reloadConfig(token, data){ // request in signals - console.log("Reloading component config due to signal add/remove") RestAPI.get(this.makeURL('/configs/' + data.configID), token).then(response => { AppDispatcher.dispatch({ type: 'configs/edited',