mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
Merge commit 'a1ac2c4aa66055501966111a8af67e8ffbef8a91' into additional-widgets
This commit is contained in:
commit
9fb8734b05
5 changed files with 136 additions and 52 deletions
24
docker-compose.yml
Normal file
24
docker-compose.yml
Normal file
|
@ -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
|
||||
|
32
nginx/villas.conf
Normal file
32
nginx/villas.conf
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 {
|
|||
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="simulation">
|
||||
<FormGroup controlId="simulation" validationState={this.validateForm('simulation')}>
|
||||
<ControlLabel>Simulation</ControlLabel>
|
||||
<FormControl componentClass="select" placeholder="Select simulation" value={this.state.simulation} onChange={(e) => this.handleChange(e)}>
|
||||
{this.props.simulations.map(simulation => (
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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,77 @@ 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 {
|
||||
|
||||
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: ProjectStore.getState(),
|
||||
visualizations: VisualizationStore.getState(),
|
||||
projects: currentProjects,
|
||||
visualizations: currentVisualizations,
|
||||
|
||||
newModal: false,
|
||||
deleteModal: false,
|
||||
editModal: false,
|
||||
modalData: {},
|
||||
|
||||
project: {},
|
||||
reload: false
|
||||
project: initialProject || {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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 +109,7 @@ class Visualizations extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
this.setState({ newModal: false, reload: data != null });
|
||||
this.setState({ newModal: false });
|
||||
}
|
||||
|
||||
confirmDeleteModal() {
|
||||
|
@ -106,7 +117,7 @@ class Visualizations extends Component {
|
|||
|
||||
AppDispatcher.dispatch({
|
||||
type: 'visualizations/start-remove',
|
||||
data: this.state.modalVisualization
|
||||
data: this.state.modalData
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -124,25 +135,22 @@ class Visualizations extends Component {
|
|||
render() {
|
||||
// get visualizations for this project
|
||||
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 (
|
||||
<div className='section'>
|
||||
<h1>{this.state.project.name}</h1>
|
||||
|
||||
<Table data={visualizations}>
|
||||
<CustomTable data={visualizations}>
|
||||
<TableColumn title='Name' dataKey='name' link='/visualizations/' linkKey='_id' />
|
||||
<TableColumn width='70' editButton deleteButton onEdit={index => this.setState({ editModal: true, modalData: this.state.visualizations[index] })} onDelete={index => this.setState({ deleteModal: true, modalData: this.state.visualizations[index] })} />
|
||||
</Table>
|
||||
<TableColumn width='70' editButton deleteButton onEdit={(index) => this.setState({ editModal: true, modalData: visualizations[index] })} onDelete={(index) => this.setState({ deleteModal: true, modalData: visualizations[index] })} />
|
||||
</CustomTable>
|
||||
|
||||
<Button onClick={() => this.setState({ newModal: true })}><Glyphicon glyph="plus" /> Visualization</Button>
|
||||
|
||||
|
@ -169,4 +177,4 @@ class Visualizations extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default Container.create(Visualizations);
|
||||
export default Container.create(Visualizations, {withProps: true});
|
||||
|
|
Loading…
Add table
Reference in a new issue