1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

fix: cleanup edit application a bit

This commit is contained in:
Ivar Conradi Østhus 2020-09-24 20:32:38 +02:00
parent 130110f5a4
commit 987fce309c
6 changed files with 207 additions and 182 deletions

View File

@ -92,6 +92,7 @@ exports[`renders correctly with permissions 1`] = `
>
<react-mdl-Cell
col={6}
hidePhone={true}
phone={12}
tablet={4}
>
@ -199,8 +200,7 @@ exports[`renders correctly with permissions 1`] = `
subtitle={
<span>
123.123.123.123
last seen at
last seen at
<small>
02/23/2017, 03:56:49 PM
</small>
@ -263,6 +263,7 @@ exports[`renders correctly without permission 1`] = `
>
<react-mdl-Cell
col={6}
hidePhone={true}
phone={12}
tablet={4}
>
@ -360,8 +361,7 @@ exports[`renders correctly without permission 1`] = `
subtitle={
<span>
123.123.123.123
last seen at
last seen at
<small>
02/23/2017, 03:56:49 PM
</small>

View File

@ -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 (
<Textfield
style={{ width: '100%' }}
label={this.props.label}
floatingLabel
rows={this.props.rows}
value={this.state.value}
onChange={this.setValue}
onBlur={this.props.onBlur}
/>
);
}
}
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 <ProgressBar indeterminate />;
}
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 ? (
<Grid style={{ margin: 0 }}>
<Cell col={6} tablet={4} phone={12}>
<h6> Toggles</h6>
<hr />
<List>
{seenToggles.map(({ name, description, enabled, notFound }, i) =>
notFound ? (
<ListItem twoLine key={i}>
{hasPermission(CREATE_FEATURE) ? (
<ListItemContent icon={'report'} subtitle={'Missing, want to create?'}>
<Link to={`/features/create?name=${name}`}>{name}</Link>
</ListItemContent>
) : (
<ListItemContent icon={'report'} subtitle={'Missing'}>
{name}
</ListItemContent>
)}
</ListItem>
) : (
<ListItem twoLine key={i}>
<ListItemContent
icon={
<span>
<Switch disabled checked={!!enabled} />
</span>
}
subtitle={shorten(description, 60)}
>
<Link to={`/features/view/${name}`}>{shorten(name, 50)}</Link>
</ListItemContent>
</ListItem>
)
)}
</List>
</Cell>
<Cell col={6} tablet={4} phone={12}>
<h6>Implemented strategies</h6>
<hr />
<List>
{strategies.map(({ name, description, notFound }, i) =>
notFound ? (
<ListItem twoLine key={`${name}-${i}`}>
{hasPermission(CREATE_STRATEGY) ? (
<ListItemContent icon={'report'} subtitle={'Missing, want to create?'}>
<Link to={`/strategies/create?name=${name}`}>{name}</Link>
</ListItemContent>
) : (
<ListItemContent icon={'report'} subtitle={'Missing'}>
{name}
</ListItemContent>
)}
</ListItem>
) : (
<ListItem twoLine key={`${name}-${i}`}>
<ListItemContent icon={'extension'} subtitle={shorten(description, 60)}>
<Link to={`/strategies/view/${name}`}>{shorten(name, 50)}</Link>
</ListItemContent>
</ListItem>
)
)}
</List>
</Cell>
<Cell col={12} tablet={12}>
<h6>{instances.length} Instances registered</h6>
<hr />
<List>
{instances.map(({ instanceId, clientIp, lastSeen, sdkVersion }, i) => (
<ListItem key={i} twoLine>
<ListItemContent
icon="timeline"
subtitle={
<span>
{clientIp} last seen at{' '}
<small>{this.formatFullDateTime(lastSeen)}</small>
</span>
}
>
{instanceId} {sdkVersion ? `(${sdkVersion})` : ''}
</ListItemContent>
</ListItem>
))}
</List>
</Cell>
</Grid>
<ApplicationView
strategies={strategies}
instances={instances}
seenToggles={seenToggles}
hasPermission={hasPermission}
formatFullDateTime={this.formatFullDateTime}
/>
) : (
<Grid>
<Cell col={6} tablet={12}>
<StatefulTextfield
value={url}
label="URL"
type="url"
onBlur={e => storeApplicationMetaData(appName, 'url', e.target.value)}
/>
<br />
<StatefulTextfield
value={description}
label="Description"
rows={5}
onBlur={e => storeApplicationMetaData(appName, 'description', e.target.value)}
/>
</Cell>
<Cell col={6} tablet={12}>
<MySelect
label="Icon"
options={icons.map(v => ({ key: v, label: v }))}
value={icon}
onChange={e => storeApplicationMetaData(appName, 'icon', e.target.value)}
filled
/>
<StatefulTextfield
value={color}
label="Color"
onBlur={e => storeApplicationMetaData(appName, 'color', e.target.value)}
/>
</Cell>
</Grid>
<ApplicationUpdate application={application} storeApplicationMetaData={storeApplicationMetaData} />
);
return (

View File

@ -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 (
<Grid>
<Cell col={12}>
<MySelect
label="Icon"
options={icons.map(v => ({ key: v, label: v }))}
value={icon || 'apps'}
onChange={e => storeApplicationMetaData(appName, 'icon', e.target.value)}
filled
/>
<StatefulTextfield
value={url}
label="Application URL"
placeholder="https://example.com"
type="url"
onBlur={e => storeApplicationMetaData(appName, 'url', e.target.value)}
/>
<br />
<StatefulTextfield
value={description}
label="Description"
rows={2}
onBlur={e => storeApplicationMetaData(appName, 'description', e.target.value)}
/>
</Cell>
</Grid>
);
}
ApplicationUpdate.propTypes = {
application: PropTypes.object.isRequired,
storeApplicationMetaData: PropTypes.func.isRequired,
};
export default ApplicationUpdate;

View File

@ -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 (
<Grid style={{ margin: 0 }}>
<Cell col={6} tablet={4} phone={12} hidePhone>
<h6> Toggles</h6>
<hr />
<List>
{seenToggles.map(({ name, description, enabled, notFound }, i) =>
notFound ? (
<ListItem twoLine key={i}>
{hasPermission(CREATE_FEATURE) ? (
<ListItemContent icon={'report'} subtitle={'Missing, want to create?'}>
<Link to={`/features/create?name=${name}`}>{name}</Link>
</ListItemContent>
) : (
<ListItemContent icon={'report'} subtitle={'Missing'}>
{name}
</ListItemContent>
)}
</ListItem>
) : (
<ListItem twoLine key={i}>
<ListItemContent
icon={
<span>
<Switch disabled checked={!!enabled} />
</span>
}
subtitle={shorten(description, 60)}
>
<Link to={`/features/view/${name}`}>{shorten(name, 50)}</Link>
</ListItemContent>
</ListItem>
)
)}
</List>
</Cell>
<Cell col={6} tablet={4} phone={12}>
<h6>Implemented strategies</h6>
<hr />
<List>
{strategies.map(({ name, description, notFound }, i) =>
notFound ? (
<ListItem twoLine key={`${name}-${i}`}>
{hasPermission(CREATE_STRATEGY) ? (
<ListItemContent icon={'report'} subtitle={'Missing, want to create?'}>
<Link to={`/strategies/create?name=${name}`}>{name}</Link>
</ListItemContent>
) : (
<ListItemContent icon={'report'} subtitle={'Missing'}>
{name}
</ListItemContent>
)}
</ListItem>
) : (
<ListItem twoLine key={`${name}-${i}`}>
<ListItemContent icon={'extension'} subtitle={shorten(description, 60)}>
<Link to={`/strategies/view/${name}`}>{shorten(name, 50)}</Link>
</ListItemContent>
</ListItem>
)
)}
</List>
</Cell>
<Cell col={12} tablet={12}>
<h6>{instances.length} Instances registered</h6>
<hr />
<List>
{instances.map(({ instanceId, clientIp, lastSeen, sdkVersion }, i) => (
<ListItem key={i} twoLine>
<ListItemContent
icon="timeline"
subtitle={
<span>
{clientIp} last seen at <small>{formatFullDateTime(lastSeen)}</small>
</span>
}
>
{instanceId} {sdkVersion ? `(${sdkVersion})` : ''}
</ListItemContent>
</ListItem>
))}
</List>
</Cell>
</Grid>
);
}
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;

View File

@ -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 (
<Textfield
style={{ width: '100%' }}
label={label}
placeholder={placeholder}
floatingLabel
rows={rows}
value={localValue}
onChange={onChange}
onBlur={onBlur}
/>
);
}
StatefulTextfield.propTypes = {
value: PropTypes.string,
label: PropTypes.string,
placeholder: PropTypes.string,
rows: PropTypes.number,
onBlur: PropTypes.func.isRequired,
};
export default StatefulTextfield;

View File

@ -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 {