- {this.props.children}
+
+
+
+
+
+ {this.props.children}
-
+
- ) : this.props.children;
+ ) : (
+ this.props.children
+ );
}
-});
+}
export default connect(state => state.global)(App);
diff --git a/ui/src/components/common/Error.js b/ui/src/components/common/Error.js
index 6cfad925c2..994fb390ec 100644
--- a/ui/src/components/common/Error.js
+++ b/ui/src/components/common/Error.js
@@ -1,22 +1,21 @@
import React from 'react';
import { connect } from 'react-redux';
import { Panel, Button } from 'react-bootstrap';
-const ErrorPage = React.createClass({
- getInitialState() {
- return {
- alertVisible: false,
- status: '',
- details: ''
- }
- },
+class ErrorPage extends React.Component {
+ state = {
+ alertVisible: false,
+ status: '',
+ details: ''
+ };
+
componentWillReceiveProps(nextProps) {
let status = '';
let details = '';
- if(nextProps.exception != null && nextProps.exception.response != null){
- status = nextProps.exception.response.status + ' - ' + nextProps.exception.response.statusText;
+ if (nextProps.exception != null && nextProps.exception.response != null) {
+ status = `${nextProps.exception.response.status} - ${nextProps.exception.response.statusText}`;
details = JSON.stringify(nextProps.exception.response.text);
- }else {
+ } else {
details = nextProps.exception;
}
this.setState({
@@ -24,10 +23,12 @@ const ErrorPage = React.createClass({
status,
details
});
- },
- handleAlertDismiss() {
- this.setState({alertVisible: false});
- },
+ }
+
+ handleAlertDismiss = () => {
+ this.setState({ alertVisible: false });
+ };
+
render() {
if (this.state.alertVisible) {
return (
@@ -35,14 +36,15 @@ const ErrorPage = React.createClass({
{this.state.details}
-
+
If you think this is not expected, file a bug with workflow admins.
);
- }else {
- return (
);
}
+ return
;
}
-});
+}
export default connect(state => state.workflow)(ErrorPage);
diff --git a/ui/src/components/common/LeftMenu.js b/ui/src/components/common/LeftMenu.js
index eaeb9aedaa..981fa30dab 100644
--- a/ui/src/components/common/LeftMenu.js
+++ b/ui/src/components/common/LeftMenu.js
@@ -1,143 +1,155 @@
import React from 'react';
-import { Link } from 'react-router'
+import { Link } from 'react-router';
import { connect } from 'react-redux';
const menuPaths = {
- Workflow: [{
- header: true,
- label: 'Executions',
- href: '/events',
- icon: 'fa-star'
- },{
- label: 'All',
- href: '/workflow',
- icon: 'fa-circle-thin'
- },{
- label: 'Running',
- href: '/workflow?status=RUNNING',
- icon: 'fa-play-circle'
- },{
- label: 'Failed',
- href: '/workflow?status=FAILED&h=48',
- icon: 'fa-warning'
- },{
- label: 'Timed Out',
- href: '/workflow?status=TIMED_OUT&h=48',
- icon: 'fa-clock-o'
- },{
- label: 'Terminated',
- href: '/workflow?status=TERMINATED&h=48',
- icon: 'fa-ban'
- },{
- label: 'Completed',
- href: '/workflow?status=COMPLETED&h=48',
- icon: 'fa-bullseye'
- },{
- header: true,
- label: 'Metadata',
- href: '/events',
- icon: 'fa-star'
- },{
- label: 'Workflow Defs',
- href: '/workflow/metadata',
- icon: 'fa-code-fork'
- },{
- label: 'Tasks',
- href: '/workflow/metadata/tasks',
- icon: 'fa-tasks'
- },{
- header: true,
- label: 'Workflow Events',
- href: '/events',
- icon: 'fa-star'
- },{
- label: 'Event Handlers',
- href: '/events',
- icon: 'fa-star'
- },{
- header: true,
- label: 'Task Queues',
- href: '/events',
- icon: 'fa-star'
- },{
- label: 'Poll Data',
- href: '/workflow/queue/data',
- icon: 'fa-exchange'
- }]
+ Workflow: [
+ {
+ header: true,
+ label: 'Executions',
+ href: '/events',
+ icon: 'fa-star'
+ },
+ {
+ label: 'All',
+ href: '/workflow',
+ icon: 'fa-circle-thin'
+ },
+ {
+ label: 'Running',
+ href: '/workflow?status=RUNNING',
+ icon: 'fa-play-circle'
+ },
+ {
+ label: 'Failed',
+ href: '/workflow?status=FAILED&h=48',
+ icon: 'fa-warning'
+ },
+ {
+ label: 'Timed Out',
+ href: '/workflow?status=TIMED_OUT&h=48',
+ icon: 'fa-clock-o'
+ },
+ {
+ label: 'Terminated',
+ href: '/workflow?status=TERMINATED&h=48',
+ icon: 'fa-ban'
+ },
+ {
+ label: 'Completed',
+ href: '/workflow?status=COMPLETED&h=48',
+ icon: 'fa-bullseye'
+ },
+ {
+ header: true,
+ label: 'Metadata',
+ href: '/events',
+ icon: 'fa-star'
+ },
+ {
+ label: 'Workflow Defs',
+ href: '/workflow/metadata',
+ icon: 'fa-code-fork'
+ },
+ {
+ label: 'Tasks',
+ href: '/workflow/metadata/tasks',
+ icon: 'fa-tasks'
+ },
+ {
+ header: true,
+ label: 'Workflow Events',
+ href: '/events',
+ icon: 'fa-star'
+ },
+ {
+ label: 'Event Handlers',
+ href: '/events',
+ icon: 'fa-star'
+ },
+ {
+ header: true,
+ label: 'Task Queues',
+ href: '/events',
+ icon: 'fa-star'
+ },
+ {
+ label: 'Poll Data',
+ href: '/workflow/queue/data',
+ icon: 'fa-exchange'
+ }
+ ]
};
-const LeftMenu = React.createClass({
-
- getInitialState() {
- return {
- sys: {},
- minimize: false
- };
- },
- handleResize(e) {
- this.setState({windowWidth: window.innerWidth, minimize: window.innerWidth < 600});
- },
+class LeftMenu extends React.Component {
+ state = {
+ minimize: false,
+ loading: false
+ };
componentDidMount() {
- window.addEventListener('resize', this.handleResize);
- },
+ window.addEventListener('resize', this.handleResize);
+ }
+
+ componentWillReceiveProps({ fetching: loading, minimize }) {
+ this.setState({ loading, minimize });
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener('resize', this.handleResize);
+ }
- componentWillUnmount() {
- window.removeEventListener('resize', this.handleResize);
- },
- componentWillReceiveProps(nextProps) {
- this.state.loading = nextProps.fetching;
- this.state.version = nextProps.version;
- this.state.minimize = nextProps.minimize;
- },
+ handleResize = () => {
+ this.setState({ minimize: window.innerWidth < 600 });
+ };
render() {
- let minimize = this.state.minimize;
- let appName = 'Workflow';
- const width = minimize?'50px':'176px';
+ const { minimize } = this.state;
+ const { appName = 'Workflow' } = this.props;
- if (this.props.appName) {
- appName = this.props.appName;
- }
- let display = minimize?'none':'';
- let menuItems = [];
+ const width = minimize ? '50px' : '176px';
+
+ const display = minimize ? 'none' : '';
+ const menuItems = [];
let keyVal = 0;
- menuPaths[appName].map((cv, i, arr) => {
- let iconClass = 'fa ' + cv['icon'];
- if(cv['header'] == true) {
- menuItems.push((
+
+ // eslint-disable-next-line array-callback-return
+ menuPaths[appName].map(cv => {
+ const iconClass = `fa ${cv.icon}`;
+ if (cv.header === true) {
+ menuItems.push(
-
{cv['label']}
+
+ {cv.label}
+
- ));
+ );
} else {
- menuItems.push((
-
-
-
-
- {cv['label']}
-
-
+ menuItems.push(
+
+
+
+ {cv.label}
+
- ));
+ );
}
});
return (
-
+
-
- {menuItems}
-
+
{menuItems}
);
}
-
-});
+}
export default connect(state => state.workflow)(LeftMenu);
diff --git a/ui/src/components/event/EventExecs.js b/ui/src/components/event/EventExecs.js
index 5a00ebfe43..a63b353923 100644
--- a/ui/src/components/event/EventExecs.js
+++ b/ui/src/components/event/EventExecs.js
@@ -1,29 +1,26 @@
import React from 'react';
-import { Table, Grid, Row, Col } from 'react-bootstrap';
import { connect } from 'react-redux';
-import { getEventHandlers } from '../../actions/WorkflowActions';
import Typeahead from 'react-bootstrap-typeahead';
+import { Table, Grid, Row, Col } from 'react-bootstrap';
+import { getEventHandlers } from '../../actions/WorkflowActions';
+
+class EventExecs extends React.Component {
+ state = {
+ events: [],
+ eventTypes: []
+ };
-const EventExecs = React.createClass({
- getInitialState() {
- return {
- events: [],
- executions: [],
- eventTypes: []
- }
- },
- componentWillMount(){
+ componentWillMount() {
this.props.dispatch(getEventHandlers());
- //this.props.dispatch(getEvents());
- },
- componentWillReceiveProps(nextProps) {
- this.state.executions = nextProps.executions;
- this.state.events = nextProps.events;
- },
+ }
+
+ componentWillReceiveProps({ events }) {
+ this.setState({ events });
+ }
+
render() {
- let executions = this.state.executions;
- let events = this.state.events;
- let eventTypes = [];
+ const { events } = this.state;
+ const eventTypes = [];
events.forEach(event => {
eventTypes.push(event.event);
});
@@ -32,27 +29,33 @@ const EventExecs = React.createClass({
Event Executions
Search for Event Executions
-
+
-
+
-
+
-
-
-
-
- Something here |
-
-
+
+
);
}
-});
+}
export default connect(state => state.workflow)(EventExecs);
diff --git a/ui/src/components/event/EventList.js b/ui/src/components/event/EventList.js
index dc4cbb72fc..739dab0481 100644
--- a/ui/src/components/event/EventList.js
+++ b/ui/src/components/event/EventList.js
@@ -1,119 +1,180 @@
+/* eslint-disable react/no-unescaped-entities */
import React from 'react';
import { Popover, OverlayTrigger, Table } from 'react-bootstrap';
import { connect } from 'react-redux';
import { getEventHandlers } from '../../actions/WorkflowActions';
-const Events = React.createClass({
- getInitialState() {
- return {
- events: []
- }
- },
- componentWillMount(){
+class Events extends React.Component {
+ state = {
+ events: []
+ };
+
+ componentWillMount() {
this.props.dispatch(getEventHandlers());
- },
+ }
+
componentWillReceiveProps(nextProps) {
this.state.events = nextProps.events || [];
- },
+ }
+
render() {
- var wfs = this.state.events;
+ const { events: wfs } = this.state;
function helpName() {
- return (
-
- Unique name identifying the event handler.
-
-
- }>);
+ return (
+
+ Unique name identifying the event handler.
+
+ }
+ >
+
+
+
+
+ );
}
function helpQueue() {
- //
- return (
-
-
Name of the Queue which the handler listens to. The supported queue systems are SQS and Conductor.
-
The name is prefixed by the source (sqs, conductor). e.g. sqs:sqs_queue_name
-
For SQS this is the name of the queue and NOT the URI of the queue.
-
For Conductor the name is same as 'sink' name provided for Event tasks.
-
-
- }>);
+ return (
+
+
+
+ Name of the Queue which the handler listens to. The supported queue systems are SQS and{' '}
+ Conductor.
+
+
The name is prefixed by the source (sqs, conductor). e.g. sqs:sqs_queue_name
+
For SQS this is the name of the queue and NOT the URI of the queue.
+
For Conductor the name is same as 'sink' name provided for Event tasks.
+
+
+ }
+ >
+
+
+
+
+ );
}
function helpCond() {
- //
- return (
-
-
An expression that can be evaluated with the payload in the queue.
-
The Actions are executed ONLY when the expression evaluation returns True
-
The expression follows Javascript for syntax
-
An empty / null expression is evaluated to True
-
-
- }>);
+ return (
+
+
+
An expression that can be evaluated with the payload in the queue.
+
The Actions are executed ONLY when the expression evaluation returns True
+
The expression follows Javascript for syntax
+
An empty / null expression is evaluated to True
+
+
+ }
+ >
+
+
+
+
+ );
}
function helpActions() {
- //
- return (
-
-
Set of actions that are taken when a message arrives with payload that matches the condition.
-
Supported Actions are: start_workflow, complete_task and fail_task
-
For the detailed documentation on the syntax and parameters for each of these actions, visit the doumentation link
-
-
- }>);
+ return (
+
+
+
Set of actions that are taken when a message arrives with payload that matches the condition.
+
Supported Actions are: start_workflow, complete_task and fail_task
+
+ For the detailed documentation on the syntax and parameters for each of these actions, visit the
+ doumentation link
+
+
+
+ }
+ >
+
+
+
+
+ );
+ }
+ function nameMaker(cell, row) {
+ return (
+
+
+
{JSON.stringify(row, null, 2)}
+
+
+ }
+ >
+ {cell}
+
+ );
}
- function nameMaker(cell, row){
- return (
-
{JSON.stringify(row, null, 2)}
-
- }>{cell});
- };
function getActions(eh) {
- let trs = [];
- let actions = eh.actions || [];
+ const trs = [];
+ const actions = eh.actions || [];
actions.forEach(action => {
- let row = {action.action}{JSON.stringify(action[action.action], null, 2)}
+ const row = {action.action}{JSON.stringify(action[action.action], null, 2)}
;
trs.push(row);
});
return {trs}
;
}
function tableBody(events) {
- let trs = [];
+ const trs = [];
events.forEach(eh => {
- let row =
- {nameMaker(eh.name, eh)} |
- {eh.event} |
- {eh.condition} |
- {getActions(eh)} |
- {eh.active?'Yes':'No'} |
-
;
- let actionRows = {getActions(eh)} |
+ const row = (
+
+ {nameMaker(eh.name, eh)} |
+ {eh.event} |
+ {eh.condition} |
+ {getActions(eh)} |
+ {eh.active ? 'Yes' : 'No'} |
+
+ );
+
trs.push(row);
});
- return {trs}
+ return {trs};
}
return (
Event Handlers
-
-
-
- Name {helpName()} |
- Event / Queue {helpQueue()} |
- Condition {helpCond()} |
- Actions {helpActions()} |
- Active? |
-
-
+
+
+
+ Name {helpName()} |
+ Event / Queue {helpQueue()} |
+ Condition {helpCond()} |
+ Actions {helpActions()} |
+ Active? |
+
+
{tableBody(wfs)}
);
}
-});
+}
+
export default connect(state => state.workflow)(Events);
diff --git a/ui/src/components/workflow/WorkflowMetaList.js b/ui/src/components/workflow/WorkflowMetaList.js
index 2bb6c4ebd3..609d8eede2 100644
--- a/ui/src/components/workflow/WorkflowMetaList.js
+++ b/ui/src/components/workflow/WorkflowMetaList.js
@@ -1,53 +1,65 @@
import React from 'react';
import { Link } from 'react-router';
-import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table';
import { connect } from 'react-redux';
+import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import { getWorkflowDefs } from '../../actions/WorkflowActions';
-const WorkflowMetaList = React.createClass({
- getInitialState() {
- return {
- name: '',
- version: '',
- workflows: []
- }
- },
- componentWillMount(){
+class WorkflowMetaList extends React.Component {
+ state = {
+ workflows: []
+ };
+
+ componentWillMount() {
this.props.dispatch(getWorkflowDefs());
- },
- componentWillReceiveProps(nextProps){
- this.state.workflows = nextProps.workflows;
+ }
+
+ componentWillReceiveProps({ workflows }) {
+ this.setState({ workflows });
+ }
- },
render() {
- var wfs = this.state.workflows;
+ const { workflows } = this.state;
- function jsonMaker(cell, row){
+ function jsonMaker(cell) {
return JSON.stringify(cell);
- };
+ }
- function taskMaker(cell, row){
- if(cell == null){
+ function taskMaker(cell) {
+ if (cell == null) {
return '';
}
- return JSON.stringify(cell.map(task => {return task.name;}));
- };
+ return JSON.stringify(
+ cell.map(task => {
+ return task.name;
+ })
+ );
+ }
- function nameMaker(cell, row){
- return ({row.name} / {row.version});
- };
+ function nameMaker(cell, row) {
+ return (
+
+ {row.name} / {row.version}
+
+ );
+ }
return (
Workflows
-
- Name/Version
- Input Parameters
- Tasks
-
+
+
+ Name/Version
+
+
+ Input Parameters
+
+
+ Tasks
+
+
);
}
-});
+}
export default connect(state => state.workflow)(WorkflowMetaList);
diff --git a/ui/src/components/workflow/executions/WorkflowAction.js b/ui/src/components/workflow/executions/WorkflowAction.js
index 8ebb3e6351..0968d1cc5a 100644
--- a/ui/src/components/workflow/executions/WorkflowAction.js
+++ b/ui/src/components/workflow/executions/WorkflowAction.js
@@ -1,142 +1,133 @@
import React from 'react';
import { Button, ButtonGroup, OverlayTrigger, Popover } from 'react-bootstrap';
import { connect } from 'react-redux';
-import { terminateWorkflow, restartWorfklow, retryWorfklow, pauseWorfklow, resumeWorfklow } from '../../../actions/WorkflowActions';
+import {
+ terminateWorkflow,
+ restartWorfklow,
+ retryWorfklow,
+ pauseWorfklow,
+ resumeWorfklow
+} from '../../../actions/WorkflowActions';
+
+class WorkflowAction extends React.Component {
+ terminate = () => {
+ this.props.dispatch(terminateWorkflow(this.props.workflowId));
+ };
+
+ restart = () => {
+ this.props.dispatch(restartWorfklow(this.props.workflowId));
+ };
+
+ retry = () => {
+ this.props.dispatch(retryWorfklow(this.props.workflowId));
+ };
+
+ pause = () => {
+ this.props.dispatch(pauseWorfklow(this.props.workflowId));
+ };
+
+ resume = () => {
+ this.props.dispatch(resumeWorfklow(this.props.workflowId));
+ };
-const WorkflowAction = React.createClass({
- getInitialState() {
- return {
- terminating: false,
- rerunning: false,
- restarting: false,
- retrying: false,
- pausing: false,
- resuming: false
- };
- },
render() {
- const tt_term = (
+ const ttTerm = (
- Terminate workflow execution. All running tasks will be cancelled.
+ Terminate workflow execution. All running tasks will be cancelled.
);
- const tt_restart = (
+
+ const ttRestart = (
Restart the workflow from the begining (First Task)
);
- const tt_retry = (
+
+ const ttRetry = (
Retry the last failed task and put workflow in running state
);
- const tt_pause = (
+
+ const ttPause = (
- Pauses workflow execution. No new tasks will be scheduled until workflow has been resumed.
+ Pauses workflow execution. No new tasks will be scheduled until workflow has been resumed.
);
- const tt_resume = (
+
+ const ttResume = (
Resume workflow execution
);
-
- const {
- terminating,
- restarting,
- retrying,
- pausing,
- resuming
- } = this.props;
- if(this.props.workflowStatus == 'RUNNING'){
+ const { terminating, restarting, retrying, pausing, resuming } = this.props;
+ if (this.props.workflowStatus === 'RUNNING') {
return (
-
+
-
-
-
);
-
- }if(this.props.workflowStatus == 'COMPLETED'){
+ }
+ if (this.props.workflowStatus === 'COMPLETED') {
return (
-
- {restarting ? () : 'Restart'}
-
+
+
+ {restarting ? : 'Restart'}
+
);
- }else if(this.props.workflowStatus == 'FAILED' || this.props.workflowStatus == 'TERMINATED'){
+ } else if (this.props.workflowStatus === 'FAILED' || this.props.workflowStatus === 'TERMINATED') {
return (
-
- {restarting ? () : 'Restart'}
+
+
+ {restarting ? : 'Restart'}
-
- {retrying ? () : 'Retry'}
+
+
+ {retrying ? : 'Retry'}
-
- );
- }else if(this.props.workflowStatus == 'PAUSED'){
- return (
-
-
- {resuming ? () : 'Resume'}
-
-
-
+
);
- }else {
-
+ } else if (this.props.workflowStatus === 'PAUSED') {
return (
-
- {restarting ? () : 'Restart'}
+
+
+ {resuming ? : 'Resume'}
);
-
}
- },
- terminate(){
- this.setState({terminating: true});
- this.props.dispatch(terminateWorkflow(this.props.workflowId));
- },
- rerun(){
- this.setState({rerunning: true});
- },
- restart(){
- this.setState({restarting: true});
- this.props.dispatch(restartWorfklow(this.props.workflowId));
- },
- retry(){
- this.setState({retrying: true});
- this.props.dispatch(retryWorfklow(this.props.workflowId));
- },
- pause(){
- this.setState({pausing: true});
- this.props.dispatch(pauseWorfklow(this.props.workflowId));
- },
- resume(){
- this.setState({resuming: true});
- this.props.dispatch(resumeWorfklow(this.props.workflowId));
+ return (
+
+
+
+ {restarting ? : 'Restart'}
+
+
+
+ );
}
-});
+}
export default connect(state => state.workflow)(WorkflowAction);
diff --git a/ui/src/components/workflow/executions/WorkflowList.js b/ui/src/components/workflow/executions/WorkflowList.js
index 7c1326b137..6ad7229be9 100644
--- a/ui/src/components/workflow/executions/WorkflowList.js
+++ b/ui/src/components/workflow/executions/WorkflowList.js
@@ -1,296 +1,400 @@
+/* eslint-disable no-restricted-globals */
+
import React from 'react';
import { Link } from 'react-router';
-import { Input, Button, Panel, Popover, OverlayTrigger, ButtonGroup, Grid, Row, Col } from 'react-bootstrap';
-import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table';
import { connect } from 'react-redux';
-import { searchWorkflows, getWorkflowDefs } from '../../../actions/WorkflowActions';
import Typeahead from 'react-bootstrap-typeahead';
+import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
+import { Input, Button, Panel, Popover, OverlayTrigger, ButtonGroup, Grid, Row, Col } from 'react-bootstrap';
+import { searchWorkflows, getWorkflowDefs } from '../../../actions/WorkflowActions';
function linkMaker(cell) {
- return {cell};
+ return {cell};
}
function zeroPad(num) {
- return ('0' + num).slice(-2);
+ return `0${num}`.slice(-2);
}
-function formatDate(cell){
- if(cell == null || !cell.split) {
- return '';
- }
- let c = cell.split("T");
- let time = c[1].split(":");
- let hh = zeroPad(time[0]);
- let mm = zeroPad(time[1]);
- let ss = zeroPad(time[2].replace("Z",""));
+function formatDate(cell) {
+ if (cell == null || !cell.split) {
+ return '';
+ }
+ const c = cell.split('T');
+ const time = c[1].split(':');
+ const hh = zeroPad(time[0]);
+ const mm = zeroPad(time[1]);
+ const ss = zeroPad(time[2].replace('Z', ''));
- let dt = c[0] + "T" + hh + ":" + mm + ":" + ss + "Z";
+ const dt = `${c[0]}T${hh}:${mm}:${ss}Z`;
- if(dt == null || dt === ''){
- return '';
- }
+ if (dt == null || dt === '') {
+ return '';
+ }
- return new Date(dt).toLocaleString('en-US');
+ return new Date(dt).toLocaleString('en-US');
}
-function miniDetails(cell, row){
- return (
- {row.reasonForIncompletion == null?'':{row.reasonForIncompletion}
}
- Input
- {row.input}
-
Output
+function miniDetails(cell, row) {
+ return (
+
+
+
+ {row.reasonForIncompletion == null ? (
+ ''
+ ) : (
+
+ {row.reasonForIncompletion}
+
+
+ )}
+
+ Input
+
+
+ {row.input}
+
+
+ Output
+
{row.output}
-
-
-
- }>details);
+
+
+
+ }
+ >
+ details
+
+
+ );
}
-const Workflow = React.createClass({
- getInitialState() {
- let workflowTypes = this.props.location.query.workflowTypes;
- if(workflowTypes != null && workflowTypes != '') {
- workflowTypes = workflowTypes.split(',');
- }else {
- workflowTypes = [];
- }
- let status = this.props.location.query.status;
- if(status != null && status != '') {
- status = status.split(',');
- }else {
- status = [];
- }
- let search = this.props.location.query.q;
- if(search == null || search == 'undefined' || search == '') {
- search = '';
- }
- let st = this.props.location.query.start;
- let start = 0;
- if(!isNaN(st)) {
- start = parseInt(st);
- }
+class Workflow extends React.Component {
+ constructor(props) {
+ super(props);
+ const {
+ location: {
+ query: { workflowTypes = '', q = '', status = '', start = 0 }
+ }
+ } = props;
- return {
- search: search,
- workflowTypes: workflowTypes,
- status: status,
+ this.state = {
+ search: q === 'undefined' || q === '' ? '' : q,
+ workflowTypes: workflowTypes === '' ? [] : workflowTypes.split(','),
+ status: status !== '' ? status.split(',') : [],
h: this.props.location.query.h,
workflows: [],
update: true,
fullstr: true,
- start: start
- }
- },
- componentWillMount(){
+ start: !isNaN(start, 10) ? parseInt(start, 10) : start
+ };
+ }
+
+ componentWillMount() {
this.props.dispatch(getWorkflowDefs());
this.doDispatch();
- },
- componentWillReceiveProps(nextProps) {
- let workflowDefs = nextProps.workflows;
- workflowDefs = workflowDefs ? workflowDefs : [];
- workflowDefs = workflowDefs.map(workflowDef => workflowDef.name);
-
- let search = nextProps.location.query.q;
- if(search == null || search == 'undefined' || search == '') {
- search = '';
- }
- let h = nextProps.location.query.h;
- if(isNaN(h)) {
- h = '';
- }
- let start = nextProps.location.query.start;
- if(isNaN(start)) {
- start = 0;
+ }
+
+ componentWillReceiveProps({
+ workflows = [],
+ location: {
+ query: { h, start, status = '', q }
}
- let status = nextProps.location.query.status;
- if(status != null && status != '') {
- status = status.split(',');
- }else {
- status = [];
+ }) {
+ const workflowDefs = workflows.map(workflowDef => workflowDef.name);
+
+ let search = q;
+ if (search == null || search === 'undefined' || search === '') {
+ search = '';
}
let update = true;
- update = this.state.search != search;
- update = update || (this.state.h != h);
- update = update || (this.state.start != start);
- update = update || (this.state.status.join(',') != status.join(','));
+ update = this.state.search !== search;
+ update = update || this.state.h !== h;
+ update = update || this.state.start !== start;
this.setState({
- search : search,
- h : h,
- update : update,
- status : status,
- workflows : workflowDefs,
- start : start
+ search,
+ h: isNaN(h, 10) ? '' : h,
+ update,
+ status: status !== '' ? status.split(',') : [],
+ workflows: workflowDefs,
+ start: isNaN(start, 10) ? 0 : start
});
this.refreshResults();
- },
- searchBtnClick() {
+ }
+
+ searchBtnClick = () => {
this.state.update = true;
this.refreshResults();
- },
- refreshResults() {
- if(this.state.update) {
+ };
+
+ refreshResults = () => {
+ if (this.state.update) {
this.state.update = false;
this.urlUpdate();
this.doDispatch();
}
- },
- urlUpdate() {
- let q = this.state.search;
- let h = this.state.h;
- let workflowTypes = this.state.workflowTypes;
- let status = this.state.status;
- let start = this.state.start;
- this.props.history.pushState(null, "/workflow?q=" + q + "&h=" + h + "&workflowTypes=" + workflowTypes + "&status=" + status + "&start=" + start);
- },
- doDispatch() {
- let search = '';
- if(this.state.search != '') {
- search = this.state.search;
- }
- let h = this.state.h;
- let query = [];
+ };
+
+ urlUpdate = () => {
+ const { workflowTypes, status, start, h, search: q } = this.state;
+
+ this.props.history.pushState(
+ null,
+ `/workflow?q=${q}&h=${h}&workflowTypes=${workflowTypes}&status=${status}&start=${start}`
+ );
+ };
- if(this.state.workflowTypes.length > 0) {
- query.push('workflowType IN (' + this.state.workflowTypes.join(',') + ') ');
+ doDispatch = () => {
+ const { search = '' } = this.state;
+ const query = [];
+
+ if (this.state.workflowTypes.length > 0) {
+ query.push(`workflowType IN (${this.state.workflowTypes.join(',')}) `);
}
- if(this.state.status.length > 0) {
- query.push('status IN (' + this.state.status.join(',') + ') ');
+ if (this.state.status.length > 0) {
+ query.push(`status IN (${this.state.status.join(',')}) `);
}
- this.props.dispatch(searchWorkflows(query.join(' AND '), search, this.state.h, this.state.fullstr, this.state.start));
- },
- workflowTypeChange(workflowTypes) {
+ this.props.dispatch(
+ searchWorkflows(query.join(' AND '), search, this.state.h, this.state.fullstr, this.state.start)
+ );
+ };
+
+ workflowTypeChange = workflowTypes => {
this.state.update = true;
this.state.workflowTypes = workflowTypes;
this.refreshResults();
- },
- statusChange(status) {
+ };
+
+ statusChange = status => {
this.state.update = true;
this.state.status = status;
this.refreshResults();
- },
- nextPage() {
- this.state.start = 100 + parseInt(this.state.start);
+ };
+
+ nextPage = () => {
+ this.state.start = 100 + parseInt(this.state.start, 10);
this.state.update = true;
this.refreshResults();
- },
- prevPage() {
- this.state.start = parseInt(this.state.start) - 100;
- if(this.state.start < 0) {
- this.state.start = 0;
+ };
+
+ prevPage = () => {
+ this.state.start = parseInt(this.state.start, 10) - 100;
+ if (this.state.start < 0) {
+ this.state.start = 0;
}
this.state.update = true;
this.refreshResults();
- },
- searchChange(e){
- let val = e.target.value;
+ };
+
+ searchChange = e => {
+ const val = e.target.value;
this.setState({ search: val });
- },
- hourChange(e){
+ };
+
+ hourChange = e => {
this.state.update = true;
this.state.h = e.target.value;
this.refreshResults();
- },
- keyPress(e){
- if(e.key == 'Enter'){
- this.state.update = true;
- var q = e.target.value;
- this.setState({search: q});
- this.refreshResults();
- }
- },
- prefChange(e) {
+ };
+
+ keyPress = e => {
+ if (e.key == 'Enter') {
+ this.state.update = true;
+ var q = e.target.value;
+ this.setState({ search: q });
+ this.refreshResults();
+ }
+ };
+
+ prefChange = e => {
this.setState({
- fullstr:e.target.checked
+ fullstr: e.target.checked
});
this.state.update = true;
this.refreshResults();
- },
- render() {
+ };
+
+ render() {
let wfs = [];
let filteredWfs = [];
- let totalHits = 0;
+ let totalHits = 0;
let found = 0;
- if(this.props.data.hits) {
+ if (this.props.data.hits) {
wfs = this.props.data.hits;
totalHits = this.props.data.totalHits;
found = wfs.length;
}
- let start = parseInt(this.state.start);
+ const start = parseInt(this.state.start);
let max = start + 100;
- if(found < 100) {
+ if (found < 100) {
max = start + found;
}
- const workflowNames = this.state.workflows?this.state.workflows:[];
- const statusList = ['RUNNING','COMPLETED','FAILED','TIMED_OUT','TERMINATED','PAUSED'];
+ const workflowNames = this.state.workflows ? this.state.workflows : [];
+ const statusList = ['RUNNING', 'COMPLETED', 'FAILED', 'TIMED_OUT', 'TERMINATED', 'PAUSED'];
- //secondary filter to match sure we only show workflows that match the the status
+ // secondary filter to match sure we only show workflows that match the the status
var currentStatusArray = this.state.status;
- if(currentStatusArray.length>0 && wfs.length>0) {
- filteredWfs = wfs.filter( function (wf) {
- return currentStatusArray.includes(wf.status); //remove wft if status doesn't match search
- });
+ if (currentStatusArray.length > 0 && wfs.length > 0) {
+ filteredWfs = wfs.filter(wf => currentStatusArray.includes(wf.status));
} else {
- filteredWfs = wfs;
+ filteredWfs = wfs;
}
return (
-
Total Workflows Found: {totalHits}, Displaying {this.state.start} to {max}
-
- {parseInt(this.state.start) >= 100? Previous Page:''}
- {parseInt(this.state.start) + 100 <= totalHits? Next Page :''}
+
+ Total Workflows Found: {totalHits}, Displaying {this.state.start} to {max}
-
- Workflow
- Workflow ID
- Status
- Start Time
- Last Updated
- End Time
- Failure Reason
- Failed Tasks
- Input
-
+
+ {parseInt(this.state.start, 10) >= 100 ? (
+
+ Previous Page
+
+ ) : (
+ ''
+ )}
+ {parseInt(this.state.start, 10) + 100 <= totalHits ? (
+
+ Next Page
+
+ ) : (
+ ''
+ )}
+
+
+
+ Workflow
+
+
+ Workflow ID
+
+
+ Status
+
+
+ Start Time
+
+
+ Last Updated
+
+
+ End Time
+
+
+ Failure Reason
+
+
+ Failed Tasks
+
+
+ Input
+
+
+
+
-
+
+
);
}
-});
+}
export default connect(state => state.workflow)(Workflow);
diff --git a/ui/src/components/workflow/queues/QueueList.js b/ui/src/components/workflow/queues/QueueList.js
index 288a0b77bf..a0af22a3bc 100644
--- a/ui/src/components/workflow/queues/QueueList.js
+++ b/ui/src/components/workflow/queues/QueueList.js
@@ -1,50 +1,53 @@
import React from 'react';
import moment from 'moment';
-import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table';
+import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import { connect } from 'react-redux';
import { getQueueData } from '../../../actions/WorkflowActions';
-const QueueListList = React.createClass({
- getInitialState() {
- return {
- name: '',
- version: '',
- queueData: []
- }
- },
- componentWillMount(){
+class QueueListList extends React.Component {
+ state = {
+ queueData: []
+ };
+
+ componentWillMount() {
this.props.dispatch(getQueueData());
- },
- componentWillReceiveProps(nextProps){
- this.state.queueData = nextProps.queueData;
- },
+ }
+
+ componentWillReceiveProps({ queueData }) {
+ this.setState({ queueData });
+ }
+
render() {
- var wfs = this.state.queueData;
+ const { queueData } = this.state;
- function formatName(cell, row){
- var name = row.queueName;
- if(row.domain != null){
- name = name + " (" + row.domain + ")";
- }
- return name;
- };
+ function formatName(_, { queueName, domain }) {
+ return domain != null ? `${queueName} (${domain})` : queueName;
+ }
- function formatDate(cell, row){
+ function formatDate(_, row) {
return moment(row.lastPollTime).fromNow();
- };
+ }
return (
Queues
-
- Name (Domain)
- Size
- Last Poll Time
- Last Polled By
-
+
+
+ Name (Domain)
+
+
+ Size
+
+
+ Last Poll Time
+
+
+ Last Polled By
+
+
);
}
-});
+}
export default connect(state => state.workflow)(QueueListList);
diff --git a/ui/src/components/workflow/tasks/TasksMetaList.js b/ui/src/components/workflow/tasks/TasksMetaList.js
index 725c263662..cda83ba9ad 100644
--- a/ui/src/components/workflow/tasks/TasksMetaList.js
+++ b/ui/src/components/workflow/tasks/TasksMetaList.js
@@ -1,72 +1,132 @@
import React from 'react';
import { Input, Popover, OverlayTrigger } from 'react-bootstrap';
-import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table';
+import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import { connect } from 'react-redux';
import { getTaskDefs } from '../../../actions/WorkflowActions';
-const TaskMetaList = React.createClass({
- getInitialState() {
- return {
- name: '',
- version: '',
- taskDefs: []
- }
- },
- componentWillMount(){
+class TaskMetaList extends React.Component {
+ state = {
+ taskDefs: []
+ };
+
+ componentWillMount() {
this.props.dispatch(getTaskDefs());
- },
- componentWillReceiveProps(nextProps){
- this.state.taskDefs = nextProps.taskDefs;
+ }
+
+ componentWillReceiveProps({ taskDefs }) {
+ this.setState({ taskDefs });
+ }
- },
render() {
- var wfs = this.state.taskDefs;
+ const { taskDefs } = this.state;
- function retries(cell, row){
- if(row.retryLogic == 'FIXED') {
- return row.retryLogic + ' (' + row.retryDelaySeconds + ' seconds)';
- }
+ const retries = (_, row) => {
+ return row.retryLogic === 'FIXED' ? `${row.retryLogic} (${row.retryDelaySeconds} seconds)` : '';
};
- function editor(cell, row){
- return (
-
-
- }>{cell});
- };
+ function editor(cell, row) {
+ return (
+
+
+
+
+
+ }
+ >
+ {cell}
+
+ );
+ }
return (
Task Definitions
-
- Name/Version
- Owner App
- Timeout Policy
- Timeout Seconds
- Response Timeout Seconds
- Retry Count
- Concurrent Exec Limit
- Retry Logic
-
+
+
+ Name/Version
+
+
+ Owner App
+
+
+ Timeout Policy
+
+
+ Timeout Seconds
+
+
+ Response Timeout Seconds
+
+
+ Retry Count
+
+
+ Concurrent Exec Limit
+
+
+ Retry Logic
+
+
);
}
-});
+}
export default connect(state => state.workflow)(TaskMetaList);
diff --git a/ui/src/server.js b/ui/src/server.js
index a3ba4c3883..1c310f3f0e 100644
--- a/ui/src/server.js
+++ b/ui/src/server.js
@@ -3,7 +3,7 @@ import express from 'express';
import Bunyan from 'bunyan';
import MiddlewareIndex from './api/middleware';
-let log = Bunyan.createLogger({ src: true, name: 'Conductor UI' });
+const log = Bunyan.createLogger({ src: true, name: 'Conductor UI' });
const wfeAPI = require('./api/wfe');
const sysAPI = require('./api/sys');
@@ -20,33 +20,32 @@ class Main {
this.startServer(app);
}
- preMiddlewareConfig(app, middlewareIndex) {
+ preMiddlewareConfig = (app, middlewareIndex) => {
middlewareIndex.before(app);
- }
+ };
- routesConfig(app) {
- log.info('Serving static ' + process.cwd());
+ routesConfig = app => {
+ log.info(`Serving static ${process.cwd()}`);
app.use(express.static('public'));
app.use('/api/wfe', wfeAPI);
app.use('/api/sys', sysAPI);
app.use('/api/events', eventsAPI);
- }
+ };
- postMiddlewareConfig(app, middlewareIndex) {
+ postMiddlewareConfig = (app, middlewareIndex) => {
middlewareIndex.after(app);
- }
+ };
- startServer(app) {
- let server = app.listen(process.env.NODE_PORT || 5000, function() {
- var host = server.address().address;
- var port = server.address().port;
- log.info('Workflow UI listening at http://%s:%s', host, port);
+ startServer = app => {
+ const server = app.listen(process.env.NODE_PORT || 5000, () => {
+ const { address, port } = server.address();
+ log.info('Workflow UI listening at http://%s:%s', address, port);
if (process.send) {
process.send('online');
}
});
- }
+ };
}
const main = new Main();
diff --git a/ui/test/filters.test.js b/ui/test/filters.test.js
index cbd9783839..1a5eb03da6 100644
--- a/ui/test/filters.test.js
+++ b/ui/test/filters.test.js
@@ -1,11 +1,12 @@
+/* eslint-disable no-undef */
import assert from 'assert';
import AuthFilter from '../src/api/middleware/filters/authFilter';
-describe('Filters', function() {
- describe('Pre Middleware', function() {
+describe('Filters', () => {
+ describe('Pre Middleware', () => {
const authFilter = new AuthFilter();
- it('should add token to req and call next', function() {
+ it('should add token to req and call next', () => {
const middleware = [];
// Create Mock App
@@ -33,7 +34,7 @@ describe('Filters', function() {
});
});
- it('should bypass add auth token if auth header not present and call next', function() {
+ it('should bypass add auth token if auth header not present and call next', () => {
const middleware = [];
// Create Mock App