mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	fix: cleanup edit application a bit
This commit is contained in:
		
							parent
							
								
									130110f5a4
								
							
						
					
					
						commit
						987fce309c
					
				| @ -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> | ||||
|  | ||||
| @ -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 ( | ||||
|  | ||||
							
								
								
									
										46
									
								
								frontend/src/component/application/application-update.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								frontend/src/component/application/application-update.jsx
									
									
									
									
									
										Normal 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; | ||||
							
								
								
									
										104
									
								
								frontend/src/component/application/application-view.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								frontend/src/component/application/application-view.jsx
									
									
									
									
									
										Normal 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; | ||||
							
								
								
									
										35
									
								
								frontend/src/component/application/stateful-textfield.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								frontend/src/component/application/stateful-textfield.js
									
									
									
									
									
										Normal 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; | ||||
| @ -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 { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user