diff --git a/frontend/src/component/application/__tests__/__snapshots__/application-edit-component-test.js.snap b/frontend/src/component/application/__tests__/__snapshots__/application-edit-component-test.js.snap index ae68f436be..5c43b94965 100644 --- a/frontend/src/component/application/__tests__/__snapshots__/application-edit-component-test.js.snap +++ b/frontend/src/component/application/__tests__/__snapshots__/application-edit-component-test.js.snap @@ -92,6 +92,7 @@ exports[`renders correctly with permissions 1`] = ` > @@ -199,8 +200,7 @@ exports[`renders correctly with permissions 1`] = ` subtitle={ 123.123.123.123 - last seen at - + last seen at 02/23/2017, 03:56:49 PM @@ -263,6 +263,7 @@ exports[`renders correctly without permission 1`] = ` > @@ -360,8 +361,7 @@ exports[`renders correctly without permission 1`] = ` subtitle={ 123.123.123.123 - last seen at - + last seen at 02/23/2017, 03:56:49 PM diff --git a/frontend/src/component/application/application-edit-component.js b/frontend/src/component/application/application-edit-component.js index 46a6290406..648593967a 100644 --- a/frontend/src/component/application/application-edit-component.js +++ b/frontend/src/component/application/application-edit-component.js @@ -1,63 +1,13 @@ /* eslint react/no-multi-comp:off */ -import React, { Component, PureComponent } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { Link } from 'react-router-dom'; -import { - Button, - Grid, - Cell, - Card, - CardActions, - CardTitle, - CardText, - CardMenu, - List, - ListItem, - ListItemContent, - Textfield, - Icon, - ProgressBar, - Tabs, - Tab, - Switch, -} from 'react-mdl'; -import { IconLink, shorten, styles as commonStyles } from '../common'; +import { Button, Card, CardActions, CardTitle, CardText, CardMenu, Icon, ProgressBar, Tabs, Tab } from 'react-mdl'; +import { IconLink, styles as commonStyles } from '../common'; import { formatFullDateTimeWithLocale } from '../common/util'; -import { CREATE_FEATURE, CREATE_STRATEGY, UPDATE_APPLICATION } from '../../permissions'; -import icons from './icon-names'; -import MySelect from '../common/select'; - -class StatefulTextfield extends Component { - static propTypes = { - value: PropTypes.string, - label: PropTypes.string, - rows: PropTypes.number, - onBlur: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - this.state = { value: props.value }; - this.setValue = function setValue(e) { - this.setState({ value: e.target.value }); - }.bind(this); - } - - render() { - return ( - - ); - } -} +import { UPDATE_APPLICATION } from '../../permissions'; +import ApplicationView from './application-view'; +import ApplicationUpdate from './application-update'; class ClientApplications extends PureComponent { static propTypes = { @@ -71,17 +21,15 @@ class ClientApplications extends PureComponent { history: PropTypes.object.isRequired, }; - constructor(props) { - super(props); + constructor() { + super(); this.state = { activeTab: 0 }; } componentDidMount() { this.props.fetchApplication(this.props.appName); } - formatFullDateTime(v) { - return formatFullDateTimeWithLocale(v, this.props.location.locale); - } + formatFullDateTime = v => formatFullDateTimeWithLocale(v, this.props.location.locale); deleteApplication = async evt => { evt.preventDefault(); @@ -95,126 +43,19 @@ class ClientApplications extends PureComponent { return ; } const { application, storeApplicationMetaData, hasPermission } = this.props; - const { appName, instances, strategies, seenToggles, url, description, icon = 'apps', color } = application; + const { appName, instances, strategies, seenToggles, url, description, icon = 'apps' } = application; const content = this.state.activeTab === 0 ? ( - - -
Toggles
-
- - {seenToggles.map(({ name, description, enabled, notFound }, i) => - notFound ? ( - - {hasPermission(CREATE_FEATURE) ? ( - - {name} - - ) : ( - - {name} - - )} - - ) : ( - - - -
- } - subtitle={shorten(description, 60)} - > - {shorten(name, 50)} - - - ) - )} - - - -
Implemented strategies
-
- - {strategies.map(({ name, description, notFound }, i) => - notFound ? ( - - {hasPermission(CREATE_STRATEGY) ? ( - - {name} - - ) : ( - - {name} - - )} - - ) : ( - - - {shorten(name, 50)} - - - ) - )} - -
- -
{instances.length} Instances registered
-
- - {instances.map(({ instanceId, clientIp, lastSeen, sdkVersion }, i) => ( - - - {clientIp} last seen at{' '} - {this.formatFullDateTime(lastSeen)} -
- } - > - {instanceId} {sdkVersion ? `(${sdkVersion})` : ''} - - - ))} - - - + ) : ( - - - storeApplicationMetaData(appName, 'url', e.target.value)} - /> -
- storeApplicationMetaData(appName, 'description', e.target.value)} - /> -
- - ({ key: v, label: v }))} - value={icon} - onChange={e => storeApplicationMetaData(appName, 'icon', e.target.value)} - filled - /> - storeApplicationMetaData(appName, 'color', e.target.value)} - /> - -
+ ); return ( diff --git a/frontend/src/component/application/application-update.jsx b/frontend/src/component/application/application-update.jsx new file mode 100644 index 0000000000..9ab8ef7c69 --- /dev/null +++ b/frontend/src/component/application/application-update.jsx @@ -0,0 +1,46 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Grid, Cell } from 'react-mdl'; +import StatefulTextfield from './stateful-textfield'; +import icons from './icon-names'; +import MySelect from '../common/select'; + +function ApplicationUpdate({ application, storeApplicationMetaData }) { + const { appName, icon, url, description } = application; + + return ( + + + ({ key: v, label: v }))} + value={icon || 'apps'} + onChange={e => storeApplicationMetaData(appName, 'icon', e.target.value)} + filled + /> + storeApplicationMetaData(appName, 'url', e.target.value)} + /> + +
+ storeApplicationMetaData(appName, 'description', e.target.value)} + /> +
+
+ ); +} + +ApplicationUpdate.propTypes = { + application: PropTypes.object.isRequired, + storeApplicationMetaData: PropTypes.func.isRequired, +}; + +export default ApplicationUpdate; diff --git a/frontend/src/component/application/application-view.jsx b/frontend/src/component/application/application-view.jsx new file mode 100644 index 0000000000..e04e8fe18c --- /dev/null +++ b/frontend/src/component/application/application-view.jsx @@ -0,0 +1,104 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import { Grid, Cell, List, ListItem, ListItemContent, Switch } from 'react-mdl'; +import { shorten } from '../common'; +import { CREATE_FEATURE, CREATE_STRATEGY } from '../../permissions'; + +function ApplicationView({ seenToggles, hasPermission, strategies, instances, formatFullDateTime }) { + return ( + + +
Toggles
+
+ + {seenToggles.map(({ name, description, enabled, notFound }, i) => + notFound ? ( + + {hasPermission(CREATE_FEATURE) ? ( + + {name} + + ) : ( + + {name} + + )} + + ) : ( + + + + + } + subtitle={shorten(description, 60)} + > + {shorten(name, 50)} + + + ) + )} + +
+ +
Implemented strategies
+
+ + {strategies.map(({ name, description, notFound }, i) => + notFound ? ( + + {hasPermission(CREATE_STRATEGY) ? ( + + {name} + + ) : ( + + {name} + + )} + + ) : ( + + + {shorten(name, 50)} + + + ) + )} + +
+ +
{instances.length} Instances registered
+
+ + {instances.map(({ instanceId, clientIp, lastSeen, sdkVersion }, i) => ( + + + {clientIp} last seen at {formatFullDateTime(lastSeen)} + + } + > + {instanceId} {sdkVersion ? `(${sdkVersion})` : ''} + + + ))} + +
+
+ ); +} + +ApplicationView.propTypes = { + instances: PropTypes.array.isRequired, + seenToggles: PropTypes.array.isRequired, + strategies: PropTypes.array.isRequired, + hasPermission: PropTypes.func.isRequired, + formatFullDateTime: PropTypes.func.isRequired, +}; + +export default ApplicationView; diff --git a/frontend/src/component/application/stateful-textfield.js b/frontend/src/component/application/stateful-textfield.js new file mode 100644 index 0000000000..ae4918fcc6 --- /dev/null +++ b/frontend/src/component/application/stateful-textfield.js @@ -0,0 +1,35 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { Textfield } from 'react-mdl'; + +function StatefulTextfield({ value, label, placeholder, rows, onBlur }) { + const [localValue, setLocalValue] = useState(value); + + const onChange = e => { + e.preventDefault(); + setLocalValue(e.target.value); + }; + + return ( + + ); +} + +StatefulTextfield.propTypes = { + value: PropTypes.string, + label: PropTypes.string, + placeholder: PropTypes.string, + rows: PropTypes.number, + onBlur: PropTypes.func.isRequired, +}; + +export default StatefulTextfield; diff --git a/frontend/src/component/feature/list-component.jsx b/frontend/src/component/feature/list-component.jsx index ac62aa44d3..41b7ae871c 100644 --- a/frontend/src/component/feature/list-component.jsx +++ b/frontend/src/component/feature/list-component.jsx @@ -6,7 +6,6 @@ import { Icon, FABButton, Menu, MenuItem, Card, CardActions, List } from 'react- import Feature from './feature-list-item-component'; import { MenuItemWithIcon, DropdownButton, styles as commonStyles } from '../common'; import SearchField from '../common/search-field'; -import styles from './feature.scss'; import { CREATE_FEATURE } from '../../permissions'; export default class FeatureListComponent extends React.Component {