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

Merged '46-widgets-no-sim-model'

This commit is contained in:
Ricardo Hernandez-Montoya 2017-04-21 14:16:21 +02:00
commit 219f2f8c74
13 changed files with 289 additions and 303 deletions

View file

@ -1,5 +1,5 @@
/**
* File: edit-widget-value.js
* File: edit-widget-image-control.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 04.03.2017
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
@ -12,7 +12,7 @@ import { FormGroup, FormControl, ControlLabel, Button } from 'react-bootstrap';
import AppDispatcher from '../../app-dispatcher';
class EditImageWidget extends Component {
class EditImageWidgetControl extends Component {
constructor(props) {
super(props);
@ -68,4 +68,4 @@ class EditImageWidget extends Component {
}
}
export default EditImageWidget;
export default EditImageWidgetControl;

View file

@ -1,85 +0,0 @@
/**
* File: edit-widget-plot.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 13.03.2017
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
**********************************************************************************/
import React, { Component } from 'react';
import { FormGroup, FormControl, ControlLabel, Checkbox, HelpBlock } from 'react-bootstrap';
class EditPlotWidget extends Component {
constructor(props) {
super(props);
this.state = {
widget: {
simulator: '',
signals: [],
time: 0
}
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
}
handleSignalChange(e, index) {
var signals = this.state.widget.signals;
if (e.target.checked) {
// add signal
signals.push(index);
} else {
// remove signal
const pos = signals.indexOf(index);
if (pos > -1) {
signals.splice(pos, 1);
}
}
this.props.handleChange({ target: { id: 'signals', value: signals } });
}
render() {
// get selected simulation model
var simulationModel = {};
if (this.props.simulation) {
this.props.simulation.models.forEach((model) => {
if (model.simulation === this.state.widget.simulation) {
simulationModel = model;
}
});
}
return (
<div>
<FormGroup controlId="time">
<ControlLabel>Time</ControlLabel>
<FormControl type="number" min="1" max="300" placeholder="Enter time" value={this.state.widget.time} onChange={(e) => this.props.handleChange(e)} />
<HelpBlock>Time in seconds</HelpBlock>
</FormGroup>
<FormGroup controlId="simulator">
<ControlLabel>Simulator</ControlLabel>
<FormControl componentClass="select" placeholder="Select simulator" value={this.state.widget.simulator} onChange={(e) => this.props.handleChange(e)}>
{this.props.simulation.models.map((model, index) => (
<option key={index} value={model.simulator}>{model.name}</option>
))}
</FormControl>
</FormGroup>
<FormGroup>
<ControlLabel>Signals</ControlLabel>
{simulationModel.mapping.map((signal, index) => (
<Checkbox key={index} checked={this.state.widget.signals.indexOf(index) !== -1} onChange={(e) => this.handleSignalChange(e, index)}>{signal.name}</Checkbox>
))}
</FormGroup>
</div>
);
}
}
export default EditPlotWidget;

View file

@ -27,24 +27,29 @@ class EditWidgetSignalControl extends Component {
}
render() {
// get selected simulation model
var simulationModel = {};
let signalsToRender = [];
if (this.props.simulation) {
this.props.simulation.models.forEach((model) => {
if (model.simulation === this.state.widget.simulation) {
simulationModel = model;
}
});
// get selected simulation model
const simulationModel = this.props.simulation.models.find( model => model.simulation === this.state.widget.simulation );
// If simulation model update the signals to render
signalsToRender = simulationModel? simulationModel.mapping : [];
}
return (
<FormGroup controlId="signal">
<ControlLabel>Signal</ControlLabel>
<FormControl componentClass="select" placeholder="Select signal" value={this.state.widget.signal} onChange={(e) => this.props.handleChange(e)}>
{simulationModel.mapping.map((signal, index) => (
<option key={index} value={index}>{simulationModel.mapping[index].name}</option>
))}
{
signalsToRender.length === 0 ? (
<option disabled value style={{ display: 'none' }}>No signals available.</option>
) : (
signalsToRender.map((signal, index) => (
<option key={index} value={index}>{signal.name}</option>
))
)
}
</FormControl>
</FormGroup>
);

View file

@ -8,7 +8,7 @@
**********************************************************************************/
import React, { Component } from 'react';
import { FormGroup, Checkbox, ControlLabel } from 'react-bootstrap';
import { FormGroup, Checkbox, ControlLabel, FormControl } from 'react-bootstrap';
class EditWidgetSignalsControl extends Component {
constructor(props) {
@ -39,27 +39,32 @@ class EditWidgetSignalsControl extends Component {
new_signals = signals.filter( (idx) => idx !== index );
}
this.props.handleChange({ target: { id: 'preselectedSignals', value: new_signals } });
this.props.handleChange({ target: { id: this.props.controlId, value: new_signals } });
}
render() {
// get selected simulation model
var simulationModel = {};
let signalsToRender = [];
if (this.props.simulation) {
this.props.simulation.models.forEach((model) => {
if (model.simulation === this.state.widget.simulation) {
simulationModel = model;
}
});
}
// get selected simulation model
const simulationModel = this.props.simulation.models.find( model => model.simulation === this.state.widget.simulation );
// If simulation model update the signals to render
signalsToRender = simulationModel? simulationModel.mapping : [];
}
return (
<FormGroup>
<ControlLabel>Signals</ControlLabel>
{simulationModel.mapping.map((signal, index) => (
<Checkbox key={index} checked={this.state.widget.preselectedSignals.indexOf(index) !== -1} onChange={(e) => this.handleSignalChange(e.target.checked, index)}>{signal.name}</Checkbox>
))}
{
signalsToRender.length === 0 ? (
<FormControl.Static>No signals available.</FormControl.Static>
) : (
signalsToRender.map((signal, index) => (
<Checkbox key={index} checked={this.state.widget.preselectedSignals.indexOf(index) !== -1} onChange={(e) => this.handleSignalChange(e.target.checked, index)}>{signal.name}</Checkbox>
))
)
}
</FormGroup>
);
}

View file

@ -31,10 +31,15 @@ class EditWidgetSimulatorControl extends Component {
return (
<FormGroup controlId="simulator">
<ControlLabel>Simulator</ControlLabel>
<FormControl componentClass="select" placeholder="Select simulator" value={this.state.widget.simulator} onChange={(e) => this.props.handleChange(e)}>
{this.props.simulation.models.map((model, index) => (
<FormControl componentClass="select" placeholder="Select simulator" value={this.state.widget.simulator || '' } onChange={(e) => this.props.handleChange(e)}>
{
this.props.simulation.models.length === 0? (
<option disabled value style={{ display: 'none' }}> No simulators available. </option>
) : (
this.props.simulation.models.map((model, index) => (
<option key={index} value={model.simulator}>{model.name}</option>
))}
)))
}
</FormControl>
</FormGroup>
);

View file

@ -0,0 +1,40 @@
/**
* File: edit-widget-time-control.js
* Author: Ricardo Hernandez-Montoya <rhernandez@gridhound.de>
* Date: 13.04.2017
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
**********************************************************************************/
import React, { Component } from 'react';
import { FormGroup, FormControl, ControlLabel, HelpBlock } from 'react-bootstrap';
class EditWidgetTimeControl extends Component {
constructor(props) {
super(props);
this.state = {
widget: {
time: 0
}
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
}
render() {
return (
<FormGroup controlId="time">
<ControlLabel>Time</ControlLabel>
<FormControl type="number" min="1" max="300" placeholder="Enter time" value={this.state.widget.time} onChange={(e) => this.props.handleChange(e)} />
<HelpBlock>Time in seconds</HelpBlock>
</FormGroup>
);
}
}
export default EditWidgetTimeControl;

View file

@ -1,64 +0,0 @@
/**
* File: edit-widget-value.js
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
* Date: 04.03.2017
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
**********************************************************************************/
import React, { Component } from 'react';
import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
class EditValueWidget extends Component {
constructor(props) {
super(props);
this.state = {
widget: {
simulator: '',
signal: 0
}
};
}
componentWillReceiveProps(nextProps) {
this.setState({ widget: nextProps.widget });
}
render() {
// get selected simulation model
var simulationModel = {};
if (this.props.simulation) {
this.props.simulation.models.forEach((model) => {
if (model.simulation === this.state.widget.simulation) {
simulationModel = model;
}
});
}
return (
<div>
<FormGroup controlId="simulator">
<ControlLabel>Simulator</ControlLabel>
<FormControl componentClass="select" placeholder="Select simulator" value={this.state.widget.simulator} onChange={(e) => this.props.handleChange(e)}>
{this.props.simulation.models.map((model, index) => (
<option key={index} value={model.simulator}>{model.name}</option>
))}
</FormControl>
</FormGroup>
<FormGroup controlId="signal">
<ControlLabel>Signal</ControlLabel>
<FormControl componentClass="select" placeholder="Select signal" value={this.state.widget.signal} onChange={(e) => this.props.handleChange(e)}>
{simulationModel.mapping.map((signal, index) => (
<option key={index} value={index}>{simulationModel.mapping[index].name}</option>
))}
</FormControl>
</FormGroup>
</div>
);
}
}
export default EditValueWidget;

View file

@ -12,10 +12,8 @@ import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
import Dialog from './dialog';
import EditValueWidget from './edit-widget-value';
import EditPlotWidget from './edit-widget-plot';
import EditTableWidget from './edit-widget-table';
import EditImageWidget from './edit-widget-image';
import EditWidgetTimeControl from './edit-widget-time-control';
import EditImageWidgetControl from './edit-widget-image-control';
import EditWidgetSimulatorControl from './edit-widget-simulator-control';
import EditWidgetSignalControl from './edit-widget-signal-control';
import EditWidgetSignalsControl from './edit-widget-signals-control';
@ -53,8 +51,6 @@ class EditWidgetDialog extends Component {
var update = this.state.temporal;
update[e.target.id] = e.target.value;
this.setState({ temporal: update });
//console.log(this.state.widget);
}
resetState() {
@ -77,20 +73,29 @@ class EditWidgetDialog extends Component {
}
render() {
// get widget part
var widgetDialog = null;
// Use a list to concatenate the controls according to the widget type
var dialogControls = [];
if (this.props.widget) {
if (this.props.widget.type === 'Value') {
widgetDialog = <EditValueWidget widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />;
dialogControls.push(
<EditWidgetSimulatorControl key={1} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />,
<EditWidgetSignalsControl key={2} controlId={'signals'} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />
)
} else if (this.props.widget.type === 'Plot') {
widgetDialog = <EditPlotWidget widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />;
dialogControls.push(
<EditWidgetTimeControl key={1} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />,
<EditWidgetSimulatorControl key={2} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />,
<EditWidgetSignalsControl key={3} controlId={'signals'} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />
)
} else if (this.props.widget.type === 'Table') {
widgetDialog = <EditTableWidget widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />;
dialogControls.push(
<EditWidgetSimulatorControl key={1} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />
)
} else if (this.props.widget.type === 'Image') {
widgetDialog = <EditImageWidget widget={this.state.temporal} files={this.props.files} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />;
dialogControls.push(
<EditImageWidgetControl key={1} widget={this.state.temporal} files={this.props.files} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e, index) => this.handleChange(e, index)} />
)
} else if (this.props.widget.type === 'Gauge') {
dialogControls.push(
<EditWidgetSimulatorControl key={1} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />,
@ -99,7 +104,7 @@ class EditWidgetDialog extends Component {
} else if (this.props.widget.type === 'PlotTable') {
dialogControls.push(
<EditWidgetSimulatorControl key={1} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />,
<EditWidgetSignalsControl key={2} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />
<EditWidgetSignalsControl key={2} controlId={'preselectedSignals'} widget={this.state.temporal} validate={(id) => this.validateForm(id)} simulation={this.props.simulation} handleChange={(e) => this.handleChange(e)} />
)
} else if (this.props.widget.type === 'Slider') {
dialogControls.push(
@ -117,7 +122,6 @@ class EditWidgetDialog extends Component {
<FormControl.Feedback />
</FormGroup>
{ dialogControls }
{widgetDialog}
</form>
</Dialog>
);

View file

@ -0,0 +1,108 @@
/**
* File: widget-factory.js
* Description: A factory to create and pre-configure widgets
* Author: Ricardo Hernandez-Montoya <rhernandez@gridhound.de>
* Date: 02.03.2017
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
**********************************************************************************/
import WidgetSlider from './widget-slider';
class WidgetFactory {
static createWidgetOfType(type, position, defaultSimulator = null) {
let widget = {
name: 'Name',
type: type,
width: 100,
height: 100,
x: position.x,
y: position.y,
z: 0
};
// set type specific properties
switch(type) {
case 'Value':
widget.simulator = defaultSimulator;
widget.signal = 0;
widget.minWidth = 70;
widget.minHeight = 20;
widget.width = 120;
widget.height = 70;
break;
case 'Plot':
widget.simulator = defaultSimulator;
widget.signals = [ 0 ];
widget.time = 60;
widget.minWidth = 400;
widget.minHeight = 200;
widget.width = 400;
widget.height = 200;
break;
case 'Table':
widget.simulator = defaultSimulator;
widget.minWidth = 300;
widget.minHeight = 200;
widget.width = 400;
widget.height = 200;
break;
case 'Label':
widget.minWidth = 70;
widget.minHeight = 20;
break;
case 'PlotTable':
widget.simulator = defaultSimulator;
widget.preselectedSignals = [];
widget.signals = []; // initialize selected signals
widget.minWidth = 400;
widget.minHeight = 300;
widget.width = 500;
widget.height = 500;
widget.time = 60;
break;
case 'Image':
widget.minWidth = 100;
widget.minHeight = 100;
widget.width = 200;
widget.height = 200;
break;
case 'Button':
widget.minWidth = 100;
widget.minHeight = 50;
widget.width = 100;
widget.height = 100;
break;
case 'NumberInput':
widget.minWidth = 200;
widget.minHeight = 50;
widget.width = 200;
widget.height = 50;
break;
case 'Slider':
widget.minWidth = 380;
widget.minHeight = 30;
widget.width = 400;
widget.height = 50;
widget.orientation = WidgetSlider.OrientationTypes.HORIZONTAL.value; // Assign default orientation
break;
case 'Gauge':
widget.simulator = defaultSimulator;
widget.signal = 0;
widget.minWidth = 200;
widget.minHeight = 150;
widget.width = 200;
widget.height = 150;
break;
default:
widget.width = 100;
widget.height = 100;
}
return widget;
}
}
export default WidgetFactory;

View file

@ -58,22 +58,27 @@ class WidgetPlotTable extends Component {
return (model.simulator === simulator);
});
// Create checkboxes using the signal indices from simulation model
const preselectedSignals = simulationModel.mapping.reduce(
// Loop through simulation model signals
(accum, model_signal, signal_index) => {
// Append them if they belong to the current selected type
if (nextProps.widget.preselectedSignals.indexOf(signal_index) > -1) {
accum.push(
{
index: signal_index,
name: model_signal.name
}
)
}
return accum;
}, []);
this.setState({ preselectedSignals: preselectedSignals });
let preselectedSignals = [];
// Proceed if a simulation model is available
if (simulationModel) {
// Create checkboxes using the signal indices from simulation model
preselectedSignals = simulationModel.mapping.reduce(
// Loop through simulation model signals
(accum, model_signal, signal_index) => {
// Append them if they belong to the current selected type
if (nextProps.widget.preselectedSignals.indexOf(signal_index) > -1) {
accum.push(
{
index: signal_index,
name: model_signal.name
}
)
}
return accum;
}, []);
}
this.setState({ preselectedSignals: preselectedSignals });
}
updateSignalSelection(signal_index, checked) {

View file

@ -15,25 +15,29 @@ import PlotLegend from './widget-plot/plot-legend';
class WidgetPlot extends Component {
render() {
if (this.props.simulation == null) {
return (<div>Empty</div>);
const simulator = this.props.widget.simulator;
const simulation = this.props.simulation;
let legendSignals = [];
let simulatorData = [];
// Proceed if a simulation with models and a simulator are available
if (simulator && simulation && simulation.models.length > 0) {
const model = simulation.models.find( (model) => model.simulator === simulator );
const chosenSignals = this.props.widget.signals;
simulatorData = this.props.data[simulator];
// Query the signals that will be displayed in the legend
legendSignals = model.mapping.reduce( (accum, model_signal, signal_index) => {
if (chosenSignals.includes(signal_index)) {
accum.push({ index: signal_index, name: model_signal.name });
}
return accum;
}, []);
}
let simulator = this.props.widget.simulator;
let simulation = this.props.simulation;
let model = simulation.models.find( (model) => model.simulator === simulator );
let chosenSignals = this.props.widget.signals;
let simulatorData = this.props.data[simulator];
// Query the signals that will be displayed in the legend
let legendSignals = model.mapping.reduce( (accum, model_signal, signal_index) => {
if (chosenSignals.includes(signal_index)) {
accum.push({ index: signal_index, name: model_signal.name });
}
return accum;
}, []);
return (
<div className="plot-widget" ref="wrapper">
<h4>{this.props.widget.name}</h4>

View file

@ -12,6 +12,7 @@ import { Container } from 'flux/utils';
import { Button } from 'react-bootstrap';
import { ContextMenu, MenuItem } from 'react-contextmenu';
import WidgetFactory from '../components/widget-factory';
import ToolboxItem from '../components/toolbox-item';
import Dropzone from '../components/dropzone';
import Widget from './widget';
@ -22,8 +23,8 @@ import ProjectStore from '../stores/project-store';
import SimulationStore from '../stores/simulation-store';
import FileStore from '../stores/file-store';
import AppDispatcher from '../app-dispatcher';
import WidgetSlider from '../components/widget-slider';
import NotificationsDataManager from '../data-managers/notifications-data-manager';
import NotificationsFactory from '../data-managers/notifications-factory';
class Visualization extends Component {
static getStores() {
@ -131,85 +132,19 @@ class Visualization extends Component {
}
handleDrop(item, position) {
// add new widget
var widget = {
name: 'Name',
type: item.name,
width: 100,
height: 100,
x: position.x,
y: position.y,
z: 0
};
// set type specific properties
if (item.name === 'Value') {
widget.simulator = this.state.simulation.models[0].simulator;
widget.signal = 0;
widget.minWidth = 70;
widget.minHeight = 20;
widget.width = 120;
widget.height = 70;
} else if (item.name === 'Plot') {
widget.simulator = this.state.simulation.models[0].simulator;
widget.signals = [ 0 ];
widget.time = 60;
widget.minWidth = 400;
widget.minHeight = 200;
widget.width = 400;
widget.height = 200;
} else if (item.name === 'Table') {
widget.simulator = this.state.simulation.models[0].simulator;
widget.minWidth = 300;
widget.minHeight = 200;
widget.width = 400;
widget.height = 200;
} else if (item.name === 'Label') {
widget.minWidth = 70;
widget.minHeight = 20;
} else if (item.name === 'PlotTable') {
widget.simulator = this.state.simulation.models[0].simulator;
widget.preselectedSignals = [];
widget.signals = []; // initialize selected signals
widget.minWidth = 400;
widget.minHeight = 300;
widget.width = 500;
widget.height = 500;
widget.time = 60
} else if (item.name === 'Image') {
widget.minWidth = 100;
widget.minHeight = 100;
widget.width = 200;
widget.height = 200;
} else if (item.name === 'Button') {
widget.minWidth = 100;
widget.minHeight = 50;
widget.width = 100;
widget.height = 100;
} else if (item.name === 'NumberInput') {
widget.minWidth = 200;
widget.minHeight = 50;
widget.width = 200;
widget.height = 50;
} else if (item.name === 'Slider') {
// Set dimensions and constraints as Horizontal
widget.minWidth = 150;
widget.minHeight = 50;
widget.maxHeight = 51;
widget.maxWidth = 1000;
widget.width = 400;
widget.height = 50;
widget.orientation = WidgetSlider.OrientationTypes.HORIZONTAL.value; // Assign default orientation
} else if (item.name === 'Gauge') {
widget.simulator = this.state.simulation.models[0].simulator;
widget.signal = 0;
widget.minWidth = 150;
widget.minHeight = 150;
widget.width = 200;
widget.height = 200;
widget.lockedAspectRatio = true;
let widget = null;
let defaultSimulator = null;
if (this.state.simulation.models && this.state.simulation.models.length === 0) {
NotificationsDataManager.addNotification(NotificationsFactory.NO_SIM_MODEL_AVAILABLE);
} else {
defaultSimulator = this.state.simulation.models[0].simulator;
}
// create new widget
widget = WidgetFactory.createWidgetOfType(item.name, position, defaultSimulator);
var new_widgets = this.state.visualization.widgets;
var widget_key = this.getNewWidgetKey();

View file

@ -0,0 +1,24 @@
/**
* File: notifications-factory.js
* Description: An unique source of pre-defined notifications that are displayed
* throughout the application.
* Author: Ricardo Hernandez-Montoya <rhernandez@gridhound.de>
* Date: 13.04.2017
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
**********************************************************************************/
class NotificationsFactory {
static get NO_SIM_MODEL_AVAILABLE() {
return {
title: 'No simulation model available',
message: 'Consider defining a simulation model in the simulators section.',
level: 'warning'
};
}
}
export default NotificationsFactory;