From b5b2d7bc69723b1279559bb7afb4158fd922294d Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Tue, 28 Mar 2017 11:26:29 +0200 Subject: [PATCH 1/6] Fix project and simulator-data new dialog Check in dialogs if default item for checkbox exists and add validation --- src/components/dialog/new-project.js | 15 ++++++++++++--- src/components/dialog/new-simulation-model.js | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/components/dialog/new-project.js b/src/components/dialog/new-project.js index 6abc0c8..ae08024 100644 --- a/src/components/dialog/new-project.js +++ b/src/components/dialog/new-project.js @@ -43,21 +43,30 @@ class NewProjectDialog extends Component { } resetState() { - this.setState({ name: '', simulation: this.props.simulations[0]._id }); + this.setState({ + name: '', + simulation: this.props.simulations[0] != null ? this.props.simulations[0]._id : '' + }); } validateForm(target) { // check all controls var name = true; + var simulation = true; if (this.state.name === '') { name = false; } - this.valid = name; + if (this.state.simulation === '') { + simulation = false; + } + + this.valid = name && simulation; // return state to control if (target === 'name') return name ? "success" : "error"; + else if (target === 'simulation') return simulation ? "success" : "error"; } render() { @@ -69,7 +78,7 @@ class NewProjectDialog extends Component { this.handleChange(e)} /> - + Simulation this.handleChange(e)}> {this.props.simulations.map(simulation => ( diff --git a/src/components/dialog/new-simulation-model.js b/src/components/dialog/new-simulation-model.js index cb3ca63..e8cf8aa 100644 --- a/src/components/dialog/new-simulation-model.js +++ b/src/components/dialog/new-simulation-model.js @@ -72,28 +72,39 @@ class NewSimulationModelDialog extends Component { } resetState() { - this.setState({ name: '', simulator: this.props.simulators[0]._id, length: '1', mapping: [ { name: 'Signal', type: 'Type' } ] }); + this.setState({ + name: '', + simulator: this.props.simulators[0] != null ? this.props.simulators[0]._id : '', + length: '1', + mapping: [ { name: 'Signal', type: 'Type' } ] + }); } validateForm(target) { // check all controls var name = true; var length = true; + var simulator = true; if (this.state.name === '') { name = false; } + if (this.state.simulator === '') { + simulator = false; + } + // test if simulatorid is a number (in a string, not type of number) if (!/^\d+$/.test(this.state.length)) { length = false; } - this.valid = name && length; + this.valid = name && length && simulator; // return state to control if (target === 'name') return name ? "success" : "error"; else if (target === 'length') return length ? "success" : "error"; + else if (target === 'simulator') return simulator ? "success" : "error"; } render() { From 36ca3d2a846a5c47df5732c0252a961fca983243 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Tue, 11 Apr 2017 14:54:16 +0200 Subject: [PATCH 2/6] Sort project's visualizations list --- src/containers/project.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/containers/project.js b/src/containers/project.js index 910eebe..3b4b30c 100644 --- a/src/containers/project.js +++ b/src/containers/project.js @@ -126,13 +126,11 @@ class Visualizations extends Component { var visualizations = []; if (this.state.visualizations && this.state.project.visualizations) { - this.state.visualizations.forEach((visualization) => { - this.state.project.visualizations.forEach((id) => { - if (visualization._id === id) { - visualizations.push(visualization); - } - }); - }); + visualizations = this.state.visualizations.filter( + (visualization) => this.state.project.visualizations.includes(visualization._id) + ).sort( + (visA, visB) => visA.name.localeCompare(visB.name) + ); } return ( From 08c082c0bc1007dfccbdc794d152565a9e7a0f36 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Tue, 11 Apr 2017 17:23:17 +0200 Subject: [PATCH 3/6] Fixed correct visualization deletion --- src/containers/project.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/project.js b/src/containers/project.js index 3b4b30c..2440bb4 100644 --- a/src/containers/project.js +++ b/src/containers/project.js @@ -106,7 +106,7 @@ class Visualizations extends Component { AppDispatcher.dispatch({ type: 'visualizations/start-remove', - data: this.state.modalVisualization + data: this.state.modalData }); } @@ -139,7 +139,7 @@ class Visualizations extends Component { - this.setState({ editModal: true, modalData: this.state.visualizations[index] })} onDelete={index => this.setState({ deleteModal: true, modalData: this.state.visualizations[index] })} /> + this.setState({ editModal: true, modalData: visualizations[index] })} onDelete={(index) => this.setState({ deleteModal: true, modalData: visualizations[index] })} />
From 5f7488c265892560ee751eb6c27080c62a5e2875 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Wed, 12 Apr 2017 12:38:42 +0200 Subject: [PATCH 4/6] Fixed issue #45, visualization now shows when created --- src/containers/project.js | 79 ++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/containers/project.js b/src/containers/project.js index 2440bb4..2ea79d2 100644 --- a/src/containers/project.js +++ b/src/containers/project.js @@ -15,7 +15,7 @@ import AppDispatcher from '../app-dispatcher'; import ProjectStore from '../stores/project-store'; import VisualizationStore from '../stores/visualization-store'; -import Table from '../components/table'; +import CustomTable from '../components/table'; import TableColumn from '../components/table-column'; import NewVisualzationDialog from '../components/dialog/new-visualization'; import EditVisualizationDialog from '../components/dialog/edit-visualization'; @@ -25,66 +25,70 @@ class Visualizations extends Component { return [ ProjectStore, VisualizationStore ]; } - static calculateState(prevState) { + static calculateState(prevState, props) { + + let currentProjects = ProjectStore.getState(); + let currentVisualizations = VisualizationStore.getState(); + if (prevState) { + var projectUpdate = prevState.project; + + // Compare content of the visualizations array, reload projects if changed + if (JSON.stringify(prevState.visualizations) !== JSON.stringify(currentVisualizations)) { + Visualizations.loadProjects(); + } + + // Compare content of the projects array, update visualizations if changed + if (JSON.stringify(prevState.projects) !== JSON.stringify(currentProjects)) { + projectUpdate = Visualizations.findProjectInState(currentProjects, props.params.project); + Visualizations.loadVisualizations(projectUpdate.visualizations); + } + return { - projects: ProjectStore.getState(), - visualizations: VisualizationStore.getState(), + projects: currentProjects, + visualizations: currentVisualizations, newModal: prevState.newModal, deleteModal: prevState.deleteModal, editModal: prevState.editModal, modalData: prevState.modalData, - project: prevState.project, - reload: prevState.reload + project: projectUpdate }; } else { return { - projects: ProjectStore.getState(), - visualizations: VisualizationStore.getState(), + projects: currentProjects, + visualizations: currentVisualizations, newModal: false, deleteModal: false, editModal: false, modalData: {}, - project: {}, - reload: false + project: {} }; } } - componentWillMount() { + static findProjectInState(projects, projectId) { + return projects.find((project) => project._id === projectId); + } + + static loadProjects() { AppDispatcher.dispatch({ type: 'projects/start-load' }); } - componentDidUpdate() { - if (this.state.project._id !== this.props.params.project /*|| this.state.reload*/) { - this.reloadProject(); - - if (this.state.reload) { - this.setState({ reload: false }); - } - } + static loadVisualizations(visualizations) { + AppDispatcher.dispatch({ + type: 'visualizations/start-load', + data: visualizations + }); } - reloadProject() { - // select project by param id - this.state.projects.forEach((project) => { - if (project._id === this.props.params.project) { - // JSON.parse(JSON.stringify(obj)) = deep clone to make also copy of widget objects inside - this.setState({ project: JSON.parse(JSON.stringify(project)) }); - - // load visualizations - AppDispatcher.dispatch({ - type: 'visualizations/start-load', - data: project.visualizations - }); - } - }); + componentWillMount() { + Visualizations.loadProjects(); } closeNewModal(data) { @@ -98,7 +102,7 @@ class Visualizations extends Component { }); } - this.setState({ newModal: false, reload: data != null }); + this.setState({ newModal: false }); } confirmDeleteModal() { @@ -124,7 +128,6 @@ class Visualizations extends Component { render() { // get visualizations for this project var visualizations = []; - if (this.state.visualizations && this.state.project.visualizations) { visualizations = this.state.visualizations.filter( (visualization) => this.state.project.visualizations.includes(visualization._id) @@ -137,10 +140,10 @@ class Visualizations extends Component {

{this.state.project.name}

- + this.setState({ editModal: true, modalData: visualizations[index] })} onDelete={(index) => this.setState({ deleteModal: true, modalData: visualizations[index] })} /> -
+ @@ -167,4 +170,4 @@ class Visualizations extends Component { } } -export default Container.create(Visualizations); +export default Container.create(Visualizations, {withProps: true}); From bc8bdca83984d302570d0737038ecb42b565b65c Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Wed, 12 Apr 2017 14:58:43 +0200 Subject: [PATCH 5/6] Issue #45: fixed visualizations load after redirect from projects --- src/containers/project.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/containers/project.js b/src/containers/project.js index 2ea79d2..5ba98bd 100644 --- a/src/containers/project.js +++ b/src/containers/project.js @@ -29,7 +29,7 @@ class Visualizations extends Component { let currentProjects = ProjectStore.getState(); let currentVisualizations = VisualizationStore.getState(); - + if (prevState) { var projectUpdate = prevState.project; @@ -56,6 +56,13 @@ class Visualizations extends Component { project: projectUpdate }; } else { + + let initialProject = Visualizations.findProjectInState(currentProjects, props.params.project); + // If projects have been loaded already but visualizations not (redirect from Projects page) + if (initialProject && (!currentVisualizations || currentVisualizations.length === 0)) { + Visualizations.loadVisualizations(initialProject.visualizations); + } + return { projects: currentProjects, visualizations: currentVisualizations, @@ -65,7 +72,7 @@ class Visualizations extends Component { editModal: false, modalData: {}, - project: {} + project: initialProject || {} }; } } From a1ac2c4aa66055501966111a8af67e8ffbef8a91 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Thu, 13 Apr 2017 08:59:38 +0200 Subject: [PATCH 6/6] Add docker-compose production files --- docker-compose.yml | 24 ++++++++++++++++++++++++ nginx/villas.conf | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 docker-compose.yml create mode 100644 nginx/villas.conf diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..afdd7a7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +version: "2" + +services: + frontend: + image: nginx:stable + volumes: + - ./nginx:/etc/nginx/conf.d/ + - ./build:/www + links: + - backend + ports: + - "80:80" + - "443:443" + + backend: + image: villasweb-backend + links: + - database + + database: + image: mongo:latest + volumes: + - /opt/database:/data/db + diff --git a/nginx/villas.conf b/nginx/villas.conf new file mode 100644 index 0000000..f3417de --- /dev/null +++ b/nginx/villas.conf @@ -0,0 +1,32 @@ +server { + listen 80 default_server; + server_name VILLASweb; + + # backend location + location /api/ { + proxy_redirect off; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # rewrite url to exclude /api on context broker side + rewrite ^/api/?(.*) /api/v1/$1 break; + + proxy_pass http://backend:4000/; + } + + # frontend location + location / { + root /www; + } + + # error pages + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html; + } + + error_page 500 502 503 504 50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +}