1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/web/ synced 2025-03-09 00:00:01 +01:00

Merge branch 'feature_addUser' into 'develop'

Feature add/remove user to/from scenario

See merge request acs/public/villas/web!58
This commit is contained in:
Sonja Happ 2020-06-24 09:07:57 +02:00
commit eba8dcc29d
4 changed files with 184 additions and 21 deletions

View file

@ -18,12 +18,28 @@
import ScenariosDataManager from './scenarios-data-manager';
import ArrayStore from '../common/array-store';
import NotificationsDataManager from "../common/data-managers/notifications-data-manager";
class ScenarioStore extends ArrayStore{
constructor() {
super('scenarios', ScenariosDataManager);
}
// store function, called when calls to backend have returned
// save users after they are loaded ('getUsers' call)
storeUsers(state, action) {
let scenarioID = action.scenarioID;
state.forEach((element, index, array) => {
if (element.id === scenarioID) {
array[index]["users"] = action.users;
}
})
this.__emitChange();
return state;
}
reduce(state, action) {
switch (action.type) {
@ -57,6 +73,34 @@ class ScenarioStore extends ArrayStore{
return super.reduce(state, action);
}
case 'scenarios/start-load-users':
this.dataManager.getUsers(action.token, action.data);
return super.reduce(state, action);
case 'scenarios/users-loaded':
return this.storeUsers(state, action);
case 'scenarios/add-user':
this.dataManager.addUser(action.token, action.data, action.username);
return super.reduce(state, action);
case 'scenarios/remove-user':
this.dataManager.deleteUser(action.token, action.data, action.username)
return super.reduce(state, action);
case 'scenarios/users-error':
if (action.error && !action.error.handled && action.error.response) {
const SCENARIO_USERS_ERROR_NOTIFICATION = {
title: 'Failed to modify scenario users ',
message: action.error.response.body.message,
level: 'error'
};
NotificationsDataManager.addNotification(SCENARIO_USERS_ERROR_NOTIFICATION);
}
return super.reduce(state, action);
default:
return super.reduce(state, action);
}

View file

@ -17,7 +17,8 @@
import React from 'react';
import { Container } from 'flux/utils';
import { Button } from 'react-bootstrap';
import { Button, InputGroup, FormControl } from 'react-bootstrap';
import FileSaver from 'file-saver';
import ScenarioStore from './scenario-store';
@ -77,7 +78,6 @@ class Scenario extends React.Component {
let signals = SignalStore.getState();
return {
scenario,
sessionToken,
@ -101,10 +101,14 @@ class Scenario extends React.Component {
deleteDashboardModal: false,
importDashboardModal: false,
modalDashboardData: {},
deleteUserName: '',
deleteUserModal: false,
}
}
componentDidMount() {
//load selected scenario
AppDispatcher.dispatch({
type: 'scenarios/start-load',
@ -112,6 +116,13 @@ class Scenario extends React.Component {
token: this.state.sessionToken
});
AppDispatcher.dispatch({
type: 'scenarios/start-load-users',
data: this.state.scenario.id,
token: this.state.sessionToken
});
// load ICs to enable that component configs and dashboards work with them
AppDispatcher.dispatch({
type: 'ics/start-load',
@ -119,12 +130,35 @@ class Scenario extends React.Component {
});
}
/* ##############################################
* User modification methods
############################################## */
addUser() {
AppDispatcher.dispatch({
type: 'scenarios/add-user',
data: this.state.scenario.id,
username: this.userToAdd,
token: this.state.sessionToken
});
}
closeDeleteUserModal() {
this.setState({ deleteUserModal: false });
AppDispatcher.dispatch({
type: 'scenarios/remove-user',
data: this.state.scenario.id,
username: this.state.deleteUserName,
token: this.state.sessionToken
});
}
/* ##############################################
* Component Configuration modification methods
############################################## */
addConfig(){
addConfig() {
const config = {
scenarioID: this.state.scenario.id,
name: 'New Component Configuration',
@ -140,8 +174,8 @@ class Scenario extends React.Component {
}
closeEditConfigModal(data){
this.setState({ editConfigModal : false });
closeEditConfigModal(data) {
this.setState({ editConfigModal: false });
if (data) {
AppDispatcher.dispatch({
@ -166,7 +200,7 @@ class Scenario extends React.Component {
});
}
importConfig(data){
importConfig(data) {
this.setState({ importConfigModal: false });
if (data == null) {
@ -274,7 +308,7 @@ class Scenario extends React.Component {
getICName(icID) {
for (let ic of this.state.ics) {
if (ic.id === icID) {
return ic.name || ic.uuid;
return ic.name || ic.uuid;
}
}
}
@ -284,7 +318,7 @@ class Scenario extends React.Component {
############################################## */
closeNewDashboardModal(data) {
this.setState({ newDashboardModal : false });
this.setState({ newDashboardModal: false });
if (data) {
let newDashboard = data;
// add default grid value and scenarioID
@ -299,7 +333,7 @@ class Scenario extends React.Component {
}
}
closeDeleteDashboardModal(confirmDelete){
closeDeleteDashboardModal(confirmDelete) {
this.setState({ deleteDashboardModal: false });
if (confirmDelete === false) {
@ -362,7 +396,7 @@ class Scenario extends React.Component {
* File modification methods
############################################## */
getFileName(id){
getFileName(id) {
for (let file of this.state.files) {
if (file.id === id) {
return file.name;
@ -387,12 +421,14 @@ class Scenario extends React.Component {
return <div className='section'>
<h1>{this.state.scenario.name}</h1>
{/*Component Configurations table*/}
<h2 style={tableHeadingStyle}>Component Configurations</h2>
<Table data={this.state.configs}>
<TableColumn checkbox onChecked={(index, event) => this.onConfigChecked(index, event)} width='30' />
<TableColumn title='Name' dataKey='name' />
<TableColumn title='Selected configuration file' dataKey='selectedFileID' modifier={(selectedFileID) => this.getFileName(selectedFileID)}/>
<TableColumn title='Selected configuration file' dataKey='selectedFileID' modifier={(selectedFileID) => this.getFileName(selectedFileID)} />
<TableColumn
title='# Output Signals'
dataKey='outputLength'
@ -428,7 +464,7 @@ class Scenario extends React.Component {
{ id: '1', title: 'Stop', data: { action: 'stop' } },
{ id: '2', title: 'Pause', data: { action: 'pause' } },
{ id: '3', title: 'Resume', data: { action: 'resume' } }
]}/>
]} />
</div>
<div style={{ float: 'right' }}>
@ -489,10 +525,42 @@ class Scenario extends React.Component {
<div style={{ clear: 'both' }} />
<NewDashboardDialog show={this.state.newDashboardModal} onClose={data => this.closeNewDashboardModal(data)}/>
<ImportDashboardDialog show={this.state.importDashboardModal} onClose={data => this.closeImportDashboardModal(data)} />
<NewDashboardDialog show={this.state.newDashboardModal} onClose={data => this.closeNewDashboardModal(data)} />
<ImportDashboardDialog show={this.state.importDashboardModal} onClose={data => this.closeImportDashboardModal(data)} />
<DeleteDialog title="dashboard" name={this.state.modalDashboardData.name} show={this.state.deleteDashboardModal} onClose={(e) => this.closeDeleteDashboardModal(e)}/>
<DeleteDialog title="dashboard" name={this.state.modalDashboardData.name} show={this.state.deleteDashboardModal} onClose={(e) => this.closeDeleteDashboardModal(e)} />
{/*Scenario Users table*/}
<h2 style={tableHeadingStyle}>Users sharing this scenario</h2>
<div>
<Table data={this.state.scenario.users}>
<TableColumn title='Name' dataKey='username' link='/users/' linkKey='id' />
<TableColumn title='Mail' dataKey='mail' />
<TableColumn
title=''
width='200'
deleteButton
onDelete={(index) => this.setState({ deleteUserModal: true, deleteUserName: this.state.scenario.users[index].username, modalUserIndex: index })}
/>
</Table>
<InputGroup style={{ width: 400, float: 'right' }}>
<FormControl
placeholder="Username"
onChange={(e) => this.userToAdd = e.target.value}
/>
<InputGroup.Append>
<Button
type="submit"
onClick={() => this.addUser()}>
Add User
</Button>
</InputGroup.Append>
</InputGroup><br/><br/>
</div>
<DeleteDialog title="user from scenario:" name={this.state.deleteUserName} show={this.state.deleteUserModal} onClose={(c) => this.closeDeleteUserModal(c)} />
</div>;

View file

@ -17,21 +17,72 @@
import RestDataManager from '../common/data-managers/rest-data-manager';
import AppDispatcher from "../common/app-dispatcher";
import RestAPI from '../common/api/rest-api';
class ScenariosDataManager extends RestDataManager {
constructor() {
super('scenario', '/scenarios');
this.onLoad = this.onScenariosLoad
this.onLoad = this.onScenariosLoad
}
onScenariosLoad(data, token){
getUsers(token, id) {
RestAPI.get(this.makeURL('/scenarios/' + id + '/users'), token).then(response => {
AppDispatcher.dispatch({
type: 'scenarios/users-loaded',
users: response.users,
scenarioID: id
});
}).catch(error => {
AppDispatcher.dispatch({
type: 'scenarios/users-error',
error: error
})
})
}
addUser(token, id, username) {
let path = id + '/user';
RestAPI.put(this.requestURL('load/add', path, '?username=' + username), null, token).then(response => {
AppDispatcher.dispatch({
type: 'scenarios/start-load-users',
data: id,
token: token
});
}).catch(error => {
AppDispatcher.dispatch({
type: 'scenarios/users-error',
error: error
})
})
}
deleteUser(token, id, username) {
let path = id + '/user';
RestAPI.delete(this.makeURL(this.url + '/' + path + '?username=' + username), token).then(response => {
AppDispatcher.dispatch({
type: 'scenarios/start-load-users',
data: id,
token: token
});
}).catch(error => {
AppDispatcher.dispatch({
type: 'scenarios/users-error',
error: error
})
})
}
onScenariosLoad(data, token) {
if (!Array.isArray(data)) {
data = [data];
}
for (let scenario of data){
for (let scenario of data) {
AppDispatcher.dispatch({
type: 'configs/start-load',
token: token,
@ -47,7 +98,7 @@ class ScenariosDataManager extends RestDataManager {
AppDispatcher.dispatch({
type: 'files/start-load',
token: token,
param: '?scenarioID='+scenario.id,
param: '?scenarioID=' + scenario.id,
});
}
}

View file

@ -30,7 +30,8 @@ class LoginStore extends ReduceStore {
return {
currentUser: null,
token: null,
loginMessage: null
loginMessage: null,
scenarioUsers: null
};
}
@ -76,7 +77,6 @@ class LoginStore extends ReduceStore {
// If it was an error and hasn't been handled, the credentials must have been wrong.
state = Object.assign({}, state, { loginMessage: 'Wrong credentials! Please try again.' });
}
return state;
default: