mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Use 120 as width in prettier (#90)
This commit is contained in:
		
							parent
							
								
									b176d63f56
								
							
						
					
					
						commit
						8ef9def08c
					
				| @ -5,6 +5,15 @@ | |||||||
|         "finn-prettier" |         "finn-prettier" | ||||||
|     ], |     ], | ||||||
|     "rules": { |     "rules": { | ||||||
|         "no-shadow": 0 |         "no-shadow": 0, | ||||||
|  |         "prettier/prettier": [ | ||||||
|  |             2, | ||||||
|  |             { | ||||||
|  |                 "tabWidth": 4, | ||||||
|  |                 "singleQuote": true, | ||||||
|  |                 "trailingComma": "es5", | ||||||
|  |                 "printWidth": 120 | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ | |||||||
|     "env": { |     "env": { | ||||||
|         "browser": true, |         "browser": true, | ||||||
|         "commonjs": true, |         "commonjs": true, | ||||||
| 	    "es6": true |         "es6": true | ||||||
|     }, |     }, | ||||||
|     "globals": { |     "globals": { | ||||||
|         "process": false |         "process": false | ||||||
| @ -23,6 +23,15 @@ | |||||||
|     }, |     }, | ||||||
|     "rules": { |     "rules": { | ||||||
|         "no-shadow": 0, |         "no-shadow": 0, | ||||||
|         "react/sort-comp": 0 |         "react/sort-comp": 0, | ||||||
|  |         "prettier/prettier": [ | ||||||
|  |             2, | ||||||
|  |             { | ||||||
|  |                 "tabWidth": 4, | ||||||
|  |                 "singleQuote": true, | ||||||
|  |                 "trailingComma": "es5", | ||||||
|  |                 "printWidth": 120 | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -89,18 +89,10 @@ export default class App extends Component { | |||||||
|         return ( |         return ( | ||||||
|             <span> |             <span> | ||||||
|                 {result.map((entry, index) => ( |                 {result.map((entry, index) => ( | ||||||
|                     <span |                     <span key={entry.link + index} className={index > 0 ? 'mdl-layout--large-screen-only' : ''}> | ||||||
|                         key={entry.link + index} |  | ||||||
|                         className={ |  | ||||||
|                             index > 0 ? 'mdl-layout--large-screen-only' : '' |  | ||||||
|                         } |  | ||||||
|                     > |  | ||||||
|                         {index > 0 ? ' › ' : null} |                         {index > 0 ? ' › ' : null} | ||||||
|                         <Link |                         <Link | ||||||
|                             className={[ |                             className={[styles.headerTitleLink, 'mdl-color-text--primary-contrast'].join(' ')} | ||||||
|                                 styles.headerTitleLink, |  | ||||||
|                                 'mdl-color-text--primary-contrast', |  | ||||||
|                             ].join(' ')} |  | ||||||
|                             to={entry.link} |                             to={entry.link} | ||||||
|                         > |                         > | ||||||
|                             {entry.name} |                             {entry.name} | ||||||
| @ -113,21 +105,13 @@ export default class App extends Component { | |||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         const shouldUpdateScroll = (prevRouterProps, { location }) => { |         const shouldUpdateScroll = (prevRouterProps, { location }) => { | ||||||
|             if ( |             if (prevRouterProps && location.pathname !== prevRouterProps.location.pathname) { | ||||||
|                 prevRouterProps && |  | ||||||
|                 location.pathname !== prevRouterProps.location.pathname |  | ||||||
|             ) { |  | ||||||
|                 return location.action === 'POP'; |                 return location.action === 'POP'; | ||||||
|             } else { |             } else { | ||||||
|                 return [0, 0]; |                 return [0, 0]; | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         const createListItem = ( |         const createListItem = (path, caption, icon, isDrawerNavigation = false) => { | ||||||
|             path, |  | ||||||
|             caption, |  | ||||||
|             icon, |  | ||||||
|             isDrawerNavigation = false |  | ||||||
|         ) => { |  | ||||||
|             const linkColor = |             const linkColor = | ||||||
|                 isDrawerNavigation && this.context.router.isActive(path) |                 isDrawerNavigation && this.context.router.isActive(path) | ||||||
|                     ? 'mdl-color-text--black' |                     ? 'mdl-color-text--black' | ||||||
| @ -137,20 +121,11 @@ export default class App extends Component { | |||||||
|                     ? 'mdl-color-text--black' |                     ? 'mdl-color-text--black' | ||||||
|                     : 'mdl-color-text--grey-600'; |                     : 'mdl-color-text--grey-600'; | ||||||
|             return ( |             return ( | ||||||
|                 <Link |                 <Link to={path} className={isDrawerNavigation && [styles.navigationLink, linkColor].join(' ')}> | ||||||
|                     to={path} |  | ||||||
|                     className={ |  | ||||||
|                         isDrawerNavigation && |  | ||||||
|                         [styles.navigationLink, linkColor].join(' ') |  | ||||||
|                     } |  | ||||||
|                 > |  | ||||||
|                     {icon && ( |                     {icon && ( | ||||||
|                         <Icon |                         <Icon | ||||||
|                             name={icon} |                             name={icon} | ||||||
|                             className={ |                             className={isDrawerNavigation && [styles.navigationIcon, iconColor].join(' ')} | ||||||
|                                 isDrawerNavigation && |  | ||||||
|                                 [styles.navigationIcon, iconColor].join(' ') |  | ||||||
|                             } |  | ||||||
|                         /> |                         /> | ||||||
|                     )} |                     )} | ||||||
|                     {caption} |                     {caption} | ||||||
| @ -168,79 +143,32 @@ export default class App extends Component { | |||||||
|                         </Navigation> |                         </Navigation> | ||||||
|                     </Header> |                     </Header> | ||||||
|                     <Drawer className="mdl-color--white"> |                     <Drawer className="mdl-color--white"> | ||||||
|                         <span |                         <span className={[styles.drawerTitle, 'mdl-layout-title'].join(' ')}> | ||||||
|                             className={[ |                             <img src="public/logo.png" width="32" height="32" className={styles.drawerTitleLogo} /> | ||||||
|                                 styles.drawerTitle, |                             <span className={styles.drawerTitleText}>Unleash</span> | ||||||
|                                 'mdl-layout-title', |  | ||||||
|                             ].join(' ')} |  | ||||||
|                         > |  | ||||||
|                             <img |  | ||||||
|                                 src="public/logo.png" |  | ||||||
|                                 width="32" |  | ||||||
|                                 height="32" |  | ||||||
|                                 className={styles.drawerTitleLogo} |  | ||||||
|                             /> |  | ||||||
|                             <span className={styles.drawerTitleText}> |  | ||||||
|                                 Unleash |  | ||||||
|                             </span> |  | ||||||
|                         </span> |                         </span> | ||||||
|                         <hr /> |                         <hr /> | ||||||
|                         <Navigation className={styles.navigation}> |                         <Navigation className={styles.navigation}> | ||||||
|                             {createListItem( |                             {createListItem('/features', 'Feature Toggles', 'list', true)} | ||||||
|                                 '/features', |                             {createListItem('/strategies', 'Strategies', 'extension', true)} | ||||||
|                                 'Feature Toggles', |                             {createListItem('/history', 'Event History', 'history', true)} | ||||||
|                                 'list', |                             {createListItem('/archive', 'Archived Toggles', 'archive', true)} | ||||||
|                                 true |                             {createListItem('/applications', 'Applications', 'apps', true)} | ||||||
|                             )} |  | ||||||
|                             {createListItem( |  | ||||||
|                                 '/strategies', |  | ||||||
|                                 'Strategies', |  | ||||||
|                                 'extension', |  | ||||||
|                                 true |  | ||||||
|                             )} |  | ||||||
|                             {createListItem( |  | ||||||
|                                 '/history', |  | ||||||
|                                 'Event History', |  | ||||||
|                                 'history', |  | ||||||
|                                 true |  | ||||||
|                             )} |  | ||||||
|                             {createListItem( |  | ||||||
|                                 '/archive', |  | ||||||
|                                 'Archived Toggles', |  | ||||||
|                                 'archive', |  | ||||||
|                                 true |  | ||||||
|                             )} |  | ||||||
|                             {createListItem( |  | ||||||
|                                 '/applications', |  | ||||||
|                                 'Applications', |  | ||||||
|                                 'apps', |  | ||||||
|                                 true |  | ||||||
|                             )} |  | ||||||
|                         </Navigation> |                         </Navigation> | ||||||
|                         <hr /> |                         <hr /> | ||||||
|                         <Navigation className={styles.navigation}> |                         <Navigation className={styles.navigation}> | ||||||
|                             <a |                             <a | ||||||
|                                 href="https://github.com/Unleash" |                                 href="https://github.com/Unleash" | ||||||
|                                 target="_blank" |                                 target="_blank" | ||||||
|                                 className={[ |                                 className={[styles.navigationLink, 'mdl-color-text--grey-900'].join(' ')} | ||||||
|                                     styles.navigationLink, |  | ||||||
|                                     'mdl-color-text--grey-900', |  | ||||||
|                                 ].join(' ')} |  | ||||||
|                             > |                             > | ||||||
|                                 <i |                                 <i | ||||||
|                                     className={[ |                                     className={['material-icons', styles.navigationIcon, styles.iconGitHub].join(' ')} | ||||||
|                                         'material-icons', |  | ||||||
|                                         styles.navigationIcon, |  | ||||||
|                                         styles.iconGitHub, |  | ||||||
|                                     ].join(' ')} |  | ||||||
|                                 />GitHub |                                 />GitHub | ||||||
|                             </a> |                             </a> | ||||||
|                         </Navigation> |                         </Navigation> | ||||||
|                     </Drawer> |                     </Drawer> | ||||||
|                     <ScrollContainer |                     <ScrollContainer scrollKey="container" shouldUpdateScroll={shouldUpdateScroll}> | ||||||
|                         scrollKey="container" |  | ||||||
|                         shouldUpdateScroll={shouldUpdateScroll} |  | ||||||
|                     > |  | ||||||
|                         <Content className="mdl-color--grey-50"> |                         <Content className="mdl-color--grey-50"> | ||||||
|                             <Grid noSpacing className={styles.content}> |                             <Grid noSpacing className={styles.content}> | ||||||
|                                 <Cell col={12}> |                                 <Cell col={12}> | ||||||
| @ -252,54 +180,27 @@ export default class App extends Component { | |||||||
|                                 <FooterSection type="middle"> |                                 <FooterSection type="middle"> | ||||||
|                                     <FooterDropDownSection title="Menu"> |                                     <FooterDropDownSection title="Menu"> | ||||||
|                                         <FooterLinkList> |                                         <FooterLinkList> | ||||||
|                                             {createListItem( |                                             {createListItem('/features', 'Feature Toggles')} | ||||||
|                                                 '/features', |                                             {createListItem('/strategies', 'Strategies')} | ||||||
|                                                 'Feature Toggles' |                                             {createListItem('/history', 'Event History')} | ||||||
|                                             )} |                                             {createListItem('/archive', 'Archived Toggles')} | ||||||
|                                             {createListItem( |                                             {createListItem('/applications', 'Applications')} | ||||||
|                                                 '/strategies', |  | ||||||
|                                                 'Strategies' |  | ||||||
|                                             )} |  | ||||||
|                                             {createListItem( |  | ||||||
|                                                 '/history', |  | ||||||
|                                                 'Event History' |  | ||||||
|                                             )} |  | ||||||
|                                             {createListItem( |  | ||||||
|                                                 '/archive', |  | ||||||
|                                                 'Archived Toggles' |  | ||||||
|                                             )} |  | ||||||
|                                             {createListItem( |  | ||||||
|                                                 '/applications', |  | ||||||
|                                                 'Applications' |  | ||||||
|                                             )} |  | ||||||
|                                         </FooterLinkList> |                                         </FooterLinkList> | ||||||
|                                     </FooterDropDownSection> |                                     </FooterDropDownSection> | ||||||
|                                     <FooterDropDownSection title="Clients"> |                                     <FooterDropDownSection title="Clients"> | ||||||
|                                         <FooterLinkList> |                                         <FooterLinkList> | ||||||
|                                             <a href="https://github.com/Unleash/unleash-client-node/"> |                                             <a href="https://github.com/Unleash/unleash-client-node/">Node.js</a> | ||||||
|                                                 Node.js |                                             <a href="https://github.com/Unleash/unleash-client-java/">Java</a> | ||||||
|                                             </a> |                                             <a href="https://github.com/Unleash/unleash-client-go/">Go</a> | ||||||
|                                             <a href="https://github.com/Unleash/unleash-client-java/"> |  | ||||||
|                                                 Java |  | ||||||
|                                             </a> |  | ||||||
|                                             <a href="https://github.com/Unleash/unleash-client-go/"> |  | ||||||
|                                                 Go |  | ||||||
|                                             </a> |  | ||||||
|                                         </FooterLinkList> |                                         </FooterLinkList> | ||||||
|                                     </FooterDropDownSection> |                                     </FooterDropDownSection> | ||||||
|                                 </FooterSection> |                                 </FooterSection> | ||||||
|                                 <FooterSection type="bottom" logo="Unleash"> |                                 <FooterSection type="bottom" logo="Unleash"> | ||||||
|                                     <FooterLinkList> |                                     <FooterLinkList> | ||||||
|                                         <a |                                         <a href="https://github.com/Unleash/unleash/" target="_blank"> | ||||||
|                                             href="https://github.com/Unleash/unleash/" |  | ||||||
|                                             target="_blank" |  | ||||||
|                                         > |  | ||||||
|                                             GitHub |                                             GitHub | ||||||
|                                         </a> |                                         </a> | ||||||
|                                         <a |                                         <a href="https://finn.no" target="_blank"> | ||||||
|                                             href="https://finn.no" |  | ||||||
|                                             target="_blank" |  | ||||||
|                                         > |  | ||||||
|                                             <small>A product by</small> FINN.no |                                             <small>A product by</small> FINN.no | ||||||
|                                         </a> |                                         </a> | ||||||
|                                     </FooterLinkList> |                                     </FooterLinkList> | ||||||
|  | |||||||
| @ -6,9 +6,7 @@ import renderer from 'react-test-renderer'; | |||||||
| jest.mock('react-mdl'); | jest.mock('react-mdl'); | ||||||
| 
 | 
 | ||||||
| test('renders correctly if no application', () => { | test('renders correctly if no application', () => { | ||||||
|     const tree = renderer |     const tree = renderer.create(<ClientApplications fetchApplication={jest.fn()} />).toJSON(); | ||||||
|         .create(<ClientApplications fetchApplication={jest.fn()} />) |  | ||||||
|         .toJSON(); |  | ||||||
| 
 | 
 | ||||||
|     expect(tree).toMatchSnapshot(); |     expect(tree).toMatchSnapshot(); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -61,16 +61,7 @@ class ClientApplications extends PureComponent { | |||||||
|             return <ProgressBar indeterminate />; |             return <ProgressBar indeterminate />; | ||||||
|         } |         } | ||||||
|         const { application, storeApplicationMetaData } = this.props; |         const { application, storeApplicationMetaData } = this.props; | ||||||
|         const { |         const { appName, instances, strategies, seenToggles, url, description, icon = 'apps', color } = application; | ||||||
|             appName, |  | ||||||
|             instances, |  | ||||||
|             strategies, |  | ||||||
|             seenToggles, |  | ||||||
|             url, |  | ||||||
|             description, |  | ||||||
|             icon = 'apps', |  | ||||||
|             color, |  | ||||||
|         } = application; |  | ||||||
| 
 | 
 | ||||||
|         const content = |         const content = | ||||||
|             this.state.activeTab === 0 ? ( |             this.state.activeTab === 0 ? ( | ||||||
| @ -83,17 +74,8 @@ class ClientApplications extends PureComponent { | |||||||
|                                 ({ name, description, enabled, notFound }, i) => |                                 ({ name, description, enabled, notFound }, i) => | ||||||
|                                     notFound ? ( |                                     notFound ? ( | ||||||
|                                         <ListItem twoLine key={i}> |                                         <ListItem twoLine key={i}> | ||||||
|                                             <ListItemContent |                                             <ListItemContent icon={'report'} subtitle={'Missing, want to create?'}> | ||||||
|                                                 icon={'report'} |                                                 <Link to={`/features/create?name=${name}`}>{name}</Link> | ||||||
|                                                 subtitle={ |  | ||||||
|                                                     'Missing, want to create?' |  | ||||||
|                                                 } |  | ||||||
|                                             > |  | ||||||
|                                                 <Link |  | ||||||
|                                                     to={`/features/create?name=${name}`} |  | ||||||
|                                                 > |  | ||||||
|                                                     {name} |  | ||||||
|                                                 </Link> |  | ||||||
|                                             </ListItemContent> |                                             </ListItemContent> | ||||||
|                                         </ListItem> |                                         </ListItem> | ||||||
|                                     ) : ( |                                     ) : ( | ||||||
| @ -101,22 +83,12 @@ class ClientApplications extends PureComponent { | |||||||
|                                             <ListItemContent |                                             <ListItemContent | ||||||
|                                                 icon={ |                                                 icon={ | ||||||
|                                                     <span> |                                                     <span> | ||||||
|                                                         <Switch |                                                         <Switch disabled checked={!!enabled} /> | ||||||
|                                                             disabled |  | ||||||
|                                                             checked={!!enabled} |  | ||||||
|                                                         /> |  | ||||||
|                                                     </span> |                                                     </span> | ||||||
|                                                 } |                                                 } | ||||||
|                                                 subtitle={shorten( |                                                 subtitle={shorten(description, 60)} | ||||||
|                                                     description, |  | ||||||
|                                                     60 |  | ||||||
|                                                 )} |  | ||||||
|                                             > |                                             > | ||||||
|                                                 <Link |                                                 <Link to={`/features/view/${name}`}>{shorten(name, 50)}</Link> | ||||||
|                                                     to={`/features/view/${name}`} |  | ||||||
|                                                 > |  | ||||||
|                                                     {shorten(name, 50)} |  | ||||||
|                                                 </Link> |  | ||||||
|                                             </ListItemContent> |                                             </ListItemContent> | ||||||
|                                         </ListItem> |                                         </ListItem> | ||||||
|                                     ) |                                     ) | ||||||
| @ -131,33 +103,14 @@ class ClientApplications extends PureComponent { | |||||||
|                                 ({ name, description, notFound }, i) => |                                 ({ name, description, notFound }, i) => | ||||||
|                                     notFound ? ( |                                     notFound ? ( | ||||||
|                                         <ListItem twoLine key={`${name}-${i}`}> |                                         <ListItem twoLine key={`${name}-${i}`}> | ||||||
|                                             <ListItemContent |                                             <ListItemContent icon={'report'} subtitle={'Missing, want to create?'}> | ||||||
|                                                 icon={'report'} |                                                 <Link to={`/strategies/create?name=${name}`}>{name}</Link> | ||||||
|                                                 subtitle={ |  | ||||||
|                                                     'Missing, want to create?' |  | ||||||
|                                                 } |  | ||||||
|                                             > |  | ||||||
|                                                 <Link |  | ||||||
|                                                     to={`/strategies/create?name=${name}`} |  | ||||||
|                                                 > |  | ||||||
|                                                     {name} |  | ||||||
|                                                 </Link> |  | ||||||
|                                             </ListItemContent> |                                             </ListItemContent> | ||||||
|                                         </ListItem> |                                         </ListItem> | ||||||
|                                     ) : ( |                                     ) : ( | ||||||
|                                         <ListItem twoLine key={`${name}-${i}`}> |                                         <ListItem twoLine key={`${name}-${i}`}> | ||||||
|                                             <ListItemContent |                                             <ListItemContent icon={'extension'} subtitle={shorten(description, 60)}> | ||||||
|                                                 icon={'extension'} |                                                 <Link to={`/strategies/view/${name}`}>{shorten(name, 50)}</Link> | ||||||
|                                                 subtitle={shorten( |  | ||||||
|                                                     description, |  | ||||||
|                                                     60 |  | ||||||
|                                                 )} |  | ||||||
|                                             > |  | ||||||
|                                                 <Link |  | ||||||
|                                                     to={`/strategies/view/${name}`} |  | ||||||
|                                                 > |  | ||||||
|                                                     {shorten(name, 50)} |  | ||||||
|                                                 </Link> |  | ||||||
|                                             </ListItemContent> |                                             </ListItemContent> | ||||||
|                                         </ListItem> |                                         </ListItem> | ||||||
|                                     ) |                                     ) | ||||||
| @ -168,32 +121,20 @@ class ClientApplications extends PureComponent { | |||||||
|                         <h6>{instances.length} Instances registered</h6> |                         <h6>{instances.length} Instances registered</h6> | ||||||
|                         <hr /> |                         <hr /> | ||||||
|                         <List> |                         <List> | ||||||
|                             {instances.map( |                             {instances.map(({ instanceId, clientIp, lastSeen, sdkVersion }, i) => ( | ||||||
|                                 ( |                                 <ListItem key={i} twoLine> | ||||||
|                                     { |                                     <ListItemContent | ||||||
|                                         instanceId, |                                         icon="timeline" | ||||||
|                                         clientIp, |                                         subtitle={ | ||||||
|                                         lastSeen, |                                             <span> | ||||||
|                                         sdkVersion, |                                                 {clientIp} last seen at <small>{formatFullDateTime(lastSeen)}</small> | ||||||
|                                     }, |                                             </span> | ||||||
|                                     i |                                         } | ||||||
|                                 ) => ( |                                     > | ||||||
|                                     <ListItem key={i} twoLine> |                                         {instanceId} {sdkVersion ? `(${sdkVersion})` : ''} | ||||||
|                                         <ListItemContent |                                     </ListItemContent> | ||||||
|                                             icon="timeline" |                                 </ListItem> | ||||||
|                                             subtitle={ |                             ))} | ||||||
|                                                 <span> |  | ||||||
|                                                     {clientIp} last seen at{' '} |  | ||||||
|                                                     <small>{formatFullDateTime(lastSeen)}</small> |  | ||||||
|                                                 </span> |  | ||||||
|                                             } |  | ||||||
|                                         > |  | ||||||
|                                             {instanceId}{' '} |  | ||||||
|                                             {sdkVersion ? `(${sdkVersion})` : ''} |  | ||||||
|                                         </ListItemContent> |  | ||||||
|                                     </ListItem> |  | ||||||
|                                 ) |  | ||||||
|                             )} |  | ||||||
|                         </List> |                         </List> | ||||||
|                     </Cell> |                     </Cell> | ||||||
|                 </Grid> |                 </Grid> | ||||||
| @ -206,46 +147,26 @@ class ClientApplications extends PureComponent { | |||||||
|                         <StatefulTextfield |                         <StatefulTextfield | ||||||
|                             value={url} |                             value={url} | ||||||
|                             label="URL" |                             label="URL" | ||||||
|                             onBlur={e => |                             onBlur={e => storeApplicationMetaData(appName, 'url', e.target.value)} | ||||||
|                                 storeApplicationMetaData( |  | ||||||
|                                     appName, |  | ||||||
|                                     'url', |  | ||||||
|                                     e.target.value |  | ||||||
|                                 )} |  | ||||||
|                         /> |                         /> | ||||||
|                         <br /> |                         <br /> | ||||||
|                         <StatefulTextfield |                         <StatefulTextfield | ||||||
|                             value={description} |                             value={description} | ||||||
|                             label="Description" |                             label="Description" | ||||||
|                             rows={5} |                             rows={5} | ||||||
|                             onBlur={e => |                             onBlur={e => storeApplicationMetaData(appName, 'description', e.target.value)} | ||||||
|                                 storeApplicationMetaData( |  | ||||||
|                                     appName, |  | ||||||
|                                     'description', |  | ||||||
|                                     e.target.value |  | ||||||
|                                 )} |  | ||||||
|                         /> |                         /> | ||||||
|                     </Cell> |                     </Cell> | ||||||
|                     <Cell col={6} tablet={12}> |                     <Cell col={6} tablet={12}> | ||||||
|                         <StatefulTextfield |                         <StatefulTextfield | ||||||
|                             value={icon} |                             value={icon} | ||||||
|                             label="Select icon" |                             label="Select icon" | ||||||
|                             onBlur={e => |                             onBlur={e => storeApplicationMetaData(appName, 'icon', e.target.value)} | ||||||
|                                 storeApplicationMetaData( |  | ||||||
|                                     appName, |  | ||||||
|                                     'icon', |  | ||||||
|                                     e.target.value |  | ||||||
|                                 )} |  | ||||||
|                         /> |                         /> | ||||||
|                         <StatefulTextfield |                         <StatefulTextfield | ||||||
|                             value={color} |                             value={color} | ||||||
|                             label="Select color" |                             label="Select color" | ||||||
|                             onBlur={e => |                             onBlur={e => storeApplicationMetaData(appName, 'color', e.target.value)} | ||||||
|                                 storeApplicationMetaData( |  | ||||||
|                                     appName, |  | ||||||
|                                     'color', |  | ||||||
|                                     e.target.value |  | ||||||
|                                 )} |  | ||||||
|                         /> |                         /> | ||||||
|                     </Cell> |                     </Cell> | ||||||
|                 </Grid> |                 </Grid> | ||||||
| @ -253,13 +174,7 @@ class ClientApplications extends PureComponent { | |||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <Card shadow={0} className={commonStyles.fullwidth}> |             <Card shadow={0} className={commonStyles.fullwidth}> | ||||||
|                 <CardTitle |                 <CardTitle style={{ paddingTop: '24px', paddingRight: '64px', wordBreak: 'break-all' }}> | ||||||
|                     style={{ |  | ||||||
|                         paddingTop: '24px', |  | ||||||
|                         paddingRight: '64px', |  | ||||||
|                         wordBreak: 'break-all', |  | ||||||
|                     }} |  | ||||||
|                 > |  | ||||||
|                     <Icon name={icon} /> {appName} |                     <Icon name={icon} /> {appName} | ||||||
|                 </CardTitle> |                 </CardTitle> | ||||||
|                 {description && <CardText>{description}</CardText>} |                 {description && <CardText>{description}</CardText>} | ||||||
|  | |||||||
| @ -1,9 +1,6 @@ | |||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import ApplicationEdit from './application-edit-component'; | import ApplicationEdit from './application-edit-component'; | ||||||
| import { | import { fetchApplication, storeApplicationMetaData } from '../../store/application/actions'; | ||||||
|     fetchApplication, |  | ||||||
|     storeApplicationMetaData, |  | ||||||
| } from '../../store/application/actions'; |  | ||||||
| 
 | 
 | ||||||
| const mapStateToProps = (state, props) => { | const mapStateToProps = (state, props) => { | ||||||
|     let application = state.applications.getIn(['apps', props.appName]); |     let application = state.applications.getIn(['apps', props.appName]); | ||||||
|  | |||||||
| @ -2,9 +2,7 @@ import { connect } from 'react-redux'; | |||||||
| import ApplicationList from './application-list-component'; | import ApplicationList from './application-list-component'; | ||||||
| import { fetchAll } from '../../store/application/actions'; | import { fetchAll } from '../../store/application/actions'; | ||||||
| 
 | 
 | ||||||
| const mapStateToProps = state => ({ | const mapStateToProps = state => ({ applications: state.applications.get('list').toJS() }); | ||||||
|     applications: state.applications.get('list').toJS(), |  | ||||||
| }); |  | ||||||
| 
 | 
 | ||||||
| const Container = connect(mapStateToProps, { fetchAll })(ApplicationList); | const Container = connect(mapStateToProps, { fetchAll })(ApplicationList); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -103,7 +103,6 @@ exports[`renders correctly with no archived toggles 1`] = ` | |||||||
|     /> |     /> | ||||||
|     <br /> |     <br /> | ||||||
|     No archived feature toggles, go see  |     No archived feature toggles, go see  | ||||||
|       |  | ||||||
|     <a |     <a | ||||||
|       onClick={[Function]} |       onClick={[Function]} | ||||||
|       style={Object {}} |       style={Object {}} | ||||||
|  | |||||||
| @ -16,8 +16,7 @@ const archive = [ | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         name: 'adin-pay-platform-sch-payment', |         name: 'adin-pay-platform-sch-payment', | ||||||
|         description: |         description: 'Enables use of schibsted payment from order-payment-management', | ||||||
|             'Enables use of schibsted payment from order-payment-management', |  | ||||||
|         enabled: true, |         enabled: true, | ||||||
|         strategies: [{ name: 'default', parameters: {} }], |         strategies: [{ name: 'default', parameters: {} }], | ||||||
|         createdAt: '2016-08-03T12:41:35.631Z', |         createdAt: '2016-08-03T12:41:35.631Z', | ||||||
| @ -26,17 +25,13 @@ const archive = [ | |||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| test('renders correctly with no archived toggles', () => { | test('renders correctly with no archived toggles', () => { | ||||||
|     const tree = renderer |     const tree = renderer.create(<ArchiveList fetchArchive={jest.fn()} archive={[]} />).toJSON(); | ||||||
|         .create(<ArchiveList fetchArchive={jest.fn()} archive={[]} />) |  | ||||||
|         .toJSON(); |  | ||||||
| 
 | 
 | ||||||
|     expect(tree).toMatchSnapshot(); |     expect(tree).toMatchSnapshot(); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('renders correctly with archived toggles', () => { | test('renders correctly with archived toggles', () => { | ||||||
|     const tree = renderer |     const tree = renderer.create(<ArchiveList fetchArchive={jest.fn()} archive={archive} />).toJSON(); | ||||||
|         .create(<ArchiveList fetchArchive={jest.fn()} archive={archive} />) |  | ||||||
|         .toJSON(); |  | ||||||
| 
 | 
 | ||||||
|     expect(tree).toMatchSnapshot(); |     expect(tree).toMatchSnapshot(); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -10,8 +10,6 @@ const mapStateToProps = state => { | |||||||
|     }; |     }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const ArchiveListContainer = connect(mapStateToProps, { fetchArchive, revive })( | const ArchiveListContainer = connect(mapStateToProps, { fetchArchive, revive })(ListComponent); | ||||||
|     ListComponent |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| export default ArchiveListContainer; | export default ArchiveListContainer; | ||||||
|  | |||||||
| @ -17,20 +17,12 @@ class ArchiveList extends Component { | |||||||
|             <Card shadow={0} className={commonStyles.fullwidth}> |             <Card shadow={0} className={commonStyles.fullwidth}> | ||||||
|                 {archive.length > 0 ? ( |                 {archive.length > 0 ? ( | ||||||
|                     <div className={commonStyles.horisontalScroll}> |                     <div className={commonStyles.horisontalScroll}> | ||||||
|                         <DataTable |                         <DataTable rows={archive} className={commonStyles.fullwidth} style={{ border: 0 }}> | ||||||
|                             rows={archive} |  | ||||||
|                             className={commonStyles.fullwidth} |  | ||||||
|                             style={{ border: 0 }} |  | ||||||
|                         > |  | ||||||
|                             <TableHeader |                             <TableHeader | ||||||
|                                 style={{ width: '25px' }} |                                 style={{ width: '25px' }} | ||||||
|                                 name="reviveName" |                                 name="reviveName" | ||||||
|                                 cellFormatter={reviveName => ( |                                 cellFormatter={reviveName => ( | ||||||
|                                     <IconButton |                                     <IconButton colored name="undo" onClick={() => revive(reviveName)} /> | ||||||
|                                         colored |  | ||||||
|                                         name="undo" |  | ||||||
|                                         onClick={() => revive(reviveName)} |  | ||||||
|                                     /> |  | ||||||
|                                 )} |                                 )} | ||||||
|                             > |                             > | ||||||
|                                 Revive |                                 Revive | ||||||
| @ -50,14 +42,9 @@ class ArchiveList extends Component { | |||||||
|                     </div> |                     </div> | ||||||
|                 ) : ( |                 ) : ( | ||||||
|                     <div className={commonStyles.emptyState}> |                     <div className={commonStyles.emptyState}> | ||||||
|                         <Icon |                         <Icon name="archive" className="mdl-color-text--grey-300" style={{ fontSize: '56px' }} /> | ||||||
|                             name="archive" |  | ||||||
|                             className="mdl-color-text--grey-300" |  | ||||||
|                             style={{ fontSize: '56px' }} |  | ||||||
|                         /> |  | ||||||
|                         <br /> |                         <br /> | ||||||
|                         No archived feature toggles, go see{' '} |                         No archived feature toggles, go see <Link to="/features">active toggles here</Link> | ||||||
|                         <Link to="/features">active toggles here</Link> |  | ||||||
|                     </div> |                     </div> | ||||||
|                 )} |                 )} | ||||||
|             </Card> |             </Card> | ||||||
|  | |||||||
| @ -6,14 +6,7 @@ import renderer from 'react-test-renderer'; | |||||||
| jest.mock('react-mdl'); | jest.mock('react-mdl'); | ||||||
| 
 | 
 | ||||||
| test('renders correctly with no clientInstances', () => { | test('renders correctly with no clientInstances', () => { | ||||||
|     const tree = renderer |     const tree = renderer.create(<ClientStrategies fetchClientInstances={jest.fn()} clientInstances={[]} />).toJSON(); | ||||||
|         .create( |  | ||||||
|             <ClientStrategies |  | ||||||
|                 fetchClientInstances={jest.fn()} |  | ||||||
|                 clientInstances={[]} |  | ||||||
|             /> |  | ||||||
|         ) |  | ||||||
|         .toJSON(); |  | ||||||
| 
 | 
 | ||||||
|     expect(tree).toMatchSnapshot(); |     expect(tree).toMatchSnapshot(); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -16,11 +16,7 @@ class ClientStrategies extends Component { | |||||||
|         const source = this.props.clientInstances; |         const source = this.props.clientInstances; | ||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <DataTable |             <DataTable style={{ width: '100%' }} rows={source} selectable={false}> | ||||||
|                 style={{ width: '100%' }} |  | ||||||
|                 rows={source} |  | ||||||
|                 selectable={false} |  | ||||||
|             > |  | ||||||
|                 <TableHeader name="instanceId">Instance ID</TableHeader> |                 <TableHeader name="instanceId">Instance ID</TableHeader> | ||||||
|                 <TableHeader name="appName">Application name</TableHeader> |                 <TableHeader name="appName">Application name</TableHeader> | ||||||
|                 <TableHeader name="clientIp">IP</TableHeader> |                 <TableHeader name="clientIp">IP</TableHeader> | ||||||
|  | |||||||
| @ -2,12 +2,8 @@ import { connect } from 'react-redux'; | |||||||
| import ClientInstances from './client-instance-component'; | import ClientInstances from './client-instance-component'; | ||||||
| import { fetchClientInstances } from '../../store/client-instance-actions'; | import { fetchClientInstances } from '../../store/client-instance-actions'; | ||||||
| 
 | 
 | ||||||
| const mapStateToProps = state => ({ | const mapStateToProps = state => ({ clientInstances: state.clientInstances.toJS() }); | ||||||
|     clientInstances: state.clientInstances.toJS(), |  | ||||||
| }); |  | ||||||
| 
 | 
 | ||||||
| const StrategiesContainer = connect(mapStateToProps, { fetchClientInstances })( | const StrategiesContainer = connect(mapStateToProps, { fetchClientInstances })(ClientInstances); | ||||||
|     ClientInstances |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| export default StrategiesContainer; | export default StrategiesContainer; | ||||||
|  | |||||||
| @ -1,44 +1,22 @@ | |||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import { Link } from 'react-router'; | import { Link } from 'react-router'; | ||||||
| import { | import { List, ListItem, ListItemContent, Button, Icon, Switch, MenuItem } from 'react-mdl'; | ||||||
|     List, |  | ||||||
|     ListItem, |  | ||||||
|     ListItemContent, |  | ||||||
|     Button, |  | ||||||
|     Icon, |  | ||||||
|     Switch, |  | ||||||
|     MenuItem, |  | ||||||
| } from 'react-mdl'; |  | ||||||
| import styles from './common.scss'; | import styles from './common.scss'; | ||||||
| 
 | 
 | ||||||
| export { styles }; | export { styles }; | ||||||
| 
 | 
 | ||||||
| export const shorten = (str, len = 50) => | export const shorten = (str, len = 50) => (str && str.length > len ? `${str.substring(0, len)}...` : str); | ||||||
|     str && str.length > len ? `${str.substring(0, len)}...` : str; |  | ||||||
| 
 | 
 | ||||||
| export const AppsLinkList = ({ apps }) => ( | export const AppsLinkList = ({ apps }) => ( | ||||||
|     <List> |     <List> | ||||||
|         {apps.length > 0 && |         {apps.length > 0 && | ||||||
|             apps.map(({ appName, description = '-', icon = 'apps' }) => ( |             apps.map(({ appName, description = '-', icon = 'apps' }) => ( | ||||||
|                 <ListItem twoLine key={appName}> |                 <ListItem twoLine key={appName}> | ||||||
|                     <span |                     <span className="mdl-list__item-primary-content" style={{ minWidth: 0 }}> | ||||||
|                         className="mdl-list__item-primary-content" |  | ||||||
|                         style={{ minWidth: 0 }} |  | ||||||
|                     > |  | ||||||
|                         <Icon name={icon} className="mdl-list__item-avatar" /> |                         <Icon name={icon} className="mdl-list__item-avatar" /> | ||||||
|                         <Link |                         <Link to={`/applications/${appName}`} className={[styles.listLink, styles.truncate].join(' ')}> | ||||||
|                             to={`/applications/${appName}`} |  | ||||||
|                             className={[styles.listLink, styles.truncate].join( |  | ||||||
|                                 ' ' |  | ||||||
|                             )} |  | ||||||
|                         > |  | ||||||
|                             {appName} |                             {appName} | ||||||
|                             <span |                             <span className={['mdl-list__item-sub-title', styles.truncate].join(' ')}> | ||||||
|                                 className={[ |  | ||||||
|                                     'mdl-list__item-sub-title', |  | ||||||
|                                     styles.truncate, |  | ||||||
|                                 ].join(' ')} |  | ||||||
|                             > |  | ||||||
|                                 {description} |                                 {description} | ||||||
|                             </span> |                             </span> | ||||||
|                         </Link> |                         </Link> | ||||||
| @ -62,9 +40,7 @@ export const HeaderTitle = ({ title, actions, subtitle }) => ( | |||||||
|             {subtitle && <small>{subtitle}</small>} |             {subtitle && <small>{subtitle}</small>} | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         {actions && ( |         {actions && <div style={{ flex: '1', textAlign: 'right' }}>{actions}</div>} | ||||||
|             <div style={{ flex: '1', textAlign: 'right' }}>{actions}</div> |  | ||||||
|         )} |  | ||||||
|     </div> |     </div> | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| @ -84,24 +60,13 @@ export const FormButtons = ({ submitText = 'Create', onCancel }) => ( | |||||||
|             {submitText} |             {submitText} | ||||||
|         </Button> |         </Button> | ||||||
|           |           | ||||||
|         <Button |         <Button type="cancel" ripple raised onClick={onCancel} style={{ float: 'right' }}> | ||||||
|             type="cancel" |  | ||||||
|             ripple |  | ||||||
|             raised |  | ||||||
|             onClick={onCancel} |  | ||||||
|             style={{ float: 'right' }} |  | ||||||
|         > |  | ||||||
|             <Icon name="cancel" />    Cancel |             <Icon name="cancel" />    Cancel | ||||||
|         </Button> |         </Button> | ||||||
|     </div> |     </div> | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| export const SwitchWithLabel = ({ | export const SwitchWithLabel = ({ onChange, checked, children, ...switchProps }) => ( | ||||||
|     onChange, |  | ||||||
|     checked, |  | ||||||
|     children, |  | ||||||
|     ...switchProps |  | ||||||
| }) => ( |  | ||||||
|     <span className={styles.switchWithLabel}> |     <span className={styles.switchWithLabel}> | ||||||
|         <span className={styles.label}>{children}</span> |         <span className={styles.label}>{children}</span> | ||||||
|         <span className={styles.switch}> |         <span className={styles.switch}> | ||||||
| @ -141,12 +106,7 @@ export function getIcon(type) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const IconLink = ({ url, icon }) => ( | export const IconLink = ({ url, icon }) => ( | ||||||
|     <a |     <a href={url} target="_blank" rel="noopener" className="mdl-color-text--grey-600"> | ||||||
|         href={url} |  | ||||||
|         target="_blank" |  | ||||||
|         rel="noopener" |  | ||||||
|         className="mdl-color-text--grey-600" |  | ||||||
|     > |  | ||||||
|         <Icon name={icon} /> |         <Icon name={icon} /> | ||||||
|     </a> |     </a> | ||||||
| ); | ); | ||||||
| @ -158,17 +118,8 @@ export const DropdownButton = ({ label, id }) => ( | |||||||
|     </Button> |     </Button> | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| export const MenuItemWithIcon = ({ | export const MenuItemWithIcon = ({ icon, label, disabled, ...menuItemProps }) => ( | ||||||
|     icon, |     <MenuItem disabled={disabled} style={{ display: 'flex', alignItems: 'center' }} {...menuItemProps}> | ||||||
|     label, |  | ||||||
|     disabled, |  | ||||||
|     ...menuItemProps |  | ||||||
| }) => ( |  | ||||||
|     <MenuItem |  | ||||||
|         disabled={disabled} |  | ||||||
|         style={{ display: 'flex', alignItems: 'center' }} |  | ||||||
|         {...menuItemProps} |  | ||||||
|     > |  | ||||||
|         <Icon name={icon} style={{ paddingRight: '16px' }} /> |         <Icon name={icon} style={{ paddingRight: '16px' }} /> | ||||||
|         {label} |         {label} | ||||||
|     </MenuItem> |     </MenuItem> | ||||||
| @ -176,11 +127,7 @@ export const MenuItemWithIcon = ({ | |||||||
| 
 | 
 | ||||||
| const badNumbers = [NaN, Infinity, -Infinity]; | const badNumbers = [NaN, Infinity, -Infinity]; | ||||||
| export function calc(value, total, decimal) { | export function calc(value, total, decimal) { | ||||||
|     if ( |     if (typeof value !== 'number' || typeof total !== 'number' || typeof decimal !== 'number') { | ||||||
|         typeof value !== 'number' || |  | ||||||
|         typeof total !== 'number' || |  | ||||||
|         typeof decimal !== 'number' |  | ||||||
|     ) { |  | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,5 +7,4 @@ const dateTimeOptions = { | |||||||
|     second: '2-digit', |     second: '2-digit', | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const formatFullDateTime = v => | export const formatFullDateTime = v => new Date(v).toLocaleString('nb-NO', dateTimeOptions); | ||||||
|     new Date(v).toLocaleString('nb-NO', dateTimeOptions); |  | ||||||
|  | |||||||
| @ -8,13 +8,7 @@ const ErrorComponent = ({ errors, ...props }) => { | |||||||
|     const error = showError ? errors[0] : undefined; |     const error = showError ? errors[0] : undefined; | ||||||
|     const muteError = () => props.muteError(error); |     const muteError = () => props.muteError(error); | ||||||
|     return ( |     return ( | ||||||
|         <Snackbar |         <Snackbar action="Dismiss" active={showError} onActionClick={muteError} onTimeout={muteError} timeout={10000}> | ||||||
|             action="Dismiss" |  | ||||||
|             active={showError} |  | ||||||
|             onActionClick={muteError} |  | ||||||
|             onTimeout={muteError} |  | ||||||
|             timeout={10000} |  | ||||||
|         > |  | ||||||
|             <Icon name="question_answer" /> {error} |             <Icon name="question_answer" /> {error} | ||||||
|         </Snackbar> |         </Snackbar> | ||||||
|     ); |     ); | ||||||
|  | |||||||
| @ -17,23 +17,13 @@ const Feature = ({ | |||||||
|     const { name, description, enabled, strategies } = feature; |     const { name, description, enabled, strategies } = feature; | ||||||
| 
 | 
 | ||||||
|     const { showLastHour = false } = settings; |     const { showLastHour = false } = settings; | ||||||
|     const isStale = showLastHour |     const isStale = showLastHour ? metricsLastHour.isFallback : metricsLastMinute.isFallback; | ||||||
|         ? metricsLastHour.isFallback |  | ||||||
|         : metricsLastMinute.isFallback; |  | ||||||
| 
 | 
 | ||||||
|     const percent = |     const percent = | ||||||
|         1 * |         1 * | ||||||
|         (showLastHour |         (showLastHour | ||||||
|             ? calc( |             ? calc(metricsLastHour.yes, metricsLastHour.yes + metricsLastHour.no, 0) | ||||||
|                   metricsLastHour.yes, |             : calc(metricsLastMinute.yes, metricsLastMinute.yes + metricsLastMinute.no, 0)); | ||||||
|                   metricsLastHour.yes + metricsLastHour.no, |  | ||||||
|                   0 |  | ||||||
|               ) |  | ||||||
|             : calc( |  | ||||||
|                   metricsLastMinute.yes, |  | ||||||
|                   metricsLastMinute.yes + metricsLastMinute.no, |  | ||||||
|                   0 |  | ||||||
|               )); |  | ||||||
| 
 | 
 | ||||||
|     const strategiesToShow = Math.min(strategies.length, 3); |     const strategiesToShow = Math.min(strategies.length, 3); | ||||||
|     const remainingStrategies = strategies.length - strategiesToShow; |     const remainingStrategies = strategies.length - strategiesToShow; | ||||||
| @ -45,18 +35,12 @@ const Feature = ({ | |||||||
|                 {s.name} |                 {s.name} | ||||||
|             </Chip> |             </Chip> | ||||||
|         )); |         )); | ||||||
|     const summaryChip = remainingStrategies > 0 && ( |     const summaryChip = remainingStrategies > 0 && <Chip className={styles.strategyChip}>+{remainingStrategies}</Chip>; | ||||||
|         <Chip className={styles.strategyChip}>+{remainingStrategies}</Chip> |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|         <ListItem twoLine> |         <ListItem twoLine> | ||||||
|             <span className={styles.listItemMetric}> |             <span className={styles.listItemMetric}> | ||||||
|                 <Progress |                 <Progress strokeWidth={15} percentage={percent} isFallback={isStale} /> | ||||||
|                     strokeWidth={15} |  | ||||||
|                     percentage={percent} |  | ||||||
|                     isFallback={isStale} |  | ||||||
|                 /> |  | ||||||
|             </span> |             </span> | ||||||
|             <span className={styles.listItemToggle}> |             <span className={styles.listItemToggle}> | ||||||
|                 <Switch |                 <Switch | ||||||
| @ -66,36 +50,16 @@ const Feature = ({ | |||||||
|                     checked={enabled} |                     checked={enabled} | ||||||
|                 /> |                 /> | ||||||
|             </span> |             </span> | ||||||
|             <span |             <span className={['mdl-list__item-primary-content', styles.listItemLink].join(' ')}> | ||||||
|                 className={[ |  | ||||||
|                     'mdl-list__item-primary-content', |  | ||||||
|                     styles.listItemLink, |  | ||||||
|                 ].join(' ')} |  | ||||||
|             > |  | ||||||
|                 <Link |                 <Link | ||||||
|                     to={`/features/view/${name}`} |                     to={`/features/view/${name}`} | ||||||
|                     className={[ |                     className={[commonStyles.listLink, commonStyles.truncate].join(' ')} | ||||||
|                         commonStyles.listLink, |  | ||||||
|                         commonStyles.truncate, |  | ||||||
|                     ].join(' ')} |  | ||||||
|                 > |                 > | ||||||
|                     {name} |                     {name} | ||||||
|                     <span |                     <span className={['mdl-list__item-sub-title', commonStyles.truncate].join(' ')}>{description}</span> | ||||||
|                         className={[ |  | ||||||
|                             'mdl-list__item-sub-title', |  | ||||||
|                             commonStyles.truncate, |  | ||||||
|                         ].join(' ')} |  | ||||||
|                     > |  | ||||||
|                         {description} |  | ||||||
|                     </span> |  | ||||||
|                 </Link> |                 </Link> | ||||||
|             </span> |             </span> | ||||||
|             <span |             <span className={[styles.listItemStrategies, commonStyles.hideLt920].join(' ')}> | ||||||
|                 className={[ |  | ||||||
|                     styles.listItemStrategies, |  | ||||||
|                     commonStyles.hideLt920, |  | ||||||
|                 ].join(' ')} |  | ||||||
|             > |  | ||||||
|                 {strategyChips} |                 {strategyChips} | ||||||
|                 {summaryChip} |                 {summaryChip} | ||||||
|             </span> |             </span> | ||||||
|  | |||||||
| @ -1,9 +1,6 @@ | |||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import { hashHistory } from 'react-router'; | import { hashHistory } from 'react-router'; | ||||||
| import { | import { createFeatureToggles, validateName } from '../../store/feature-actions'; | ||||||
|     createFeatureToggles, |  | ||||||
|     validateName, |  | ||||||
| } from '../../store/feature-actions'; |  | ||||||
| import { createMapper, createActions } from '../input-helpers'; | import { createMapper, createActions } from '../input-helpers'; | ||||||
| import FormAddComponent from './form-add-component'; | import FormAddComponent from './form-add-component'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -92,10 +92,7 @@ class AddFeatureToggleComponent extends Component { | |||||||
|                     /> |                     /> | ||||||
| 
 | 
 | ||||||
|                     <br /> |                     <br /> | ||||||
|                     <FormButtons |                     <FormButtons submitText={editmode ? 'Update' : 'Create'} onCancel={onCancel} /> | ||||||
|                         submitText={editmode ? 'Update' : 'Create'} |  | ||||||
|                         onCancel={onCancel} |  | ||||||
|                     /> |  | ||||||
|                 </section> |                 </section> | ||||||
|             </form> |             </form> | ||||||
|         ); |         ); | ||||||
|  | |||||||
| @ -10,9 +10,7 @@ class AddStrategy extends React.Component { | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     addStrategy = strategyName => { |     addStrategy = strategyName => { | ||||||
|         const selectedStrategy = this.props.strategies.find( |         const selectedStrategy = this.props.strategies.find(s => s.name === strategyName); | ||||||
|             s => s.name === strategyName |  | ||||||
|         ); |  | ||||||
|         const parameters = {}; |         const parameters = {}; | ||||||
| 
 | 
 | ||||||
|         selectedStrategy.parameters.forEach(({ name }) => { |         selectedStrategy.parameters.forEach(({ name }) => { | ||||||
| @ -37,14 +35,7 @@ class AddStrategy extends React.Component { | |||||||
|             backgroundColor: 'rgb(247, 248, 255)', |             backgroundColor: 'rgb(247, 248, 255)', | ||||||
|         }; |         }; | ||||||
|         return ( |         return ( | ||||||
|             <div |             <div style={{ position: 'relative', width: '25px', height: '25px', display: 'inline-block' }}> | ||||||
|                 style={{ |  | ||||||
|                     position: 'relative', |  | ||||||
|                     width: '25px', |  | ||||||
|                     height: '25px', |  | ||||||
|                     display: 'inline-block', |  | ||||||
|                 }} |  | ||||||
|             > |  | ||||||
|                 <IconButton |                 <IconButton | ||||||
|                     name="add" |                     name="add" | ||||||
|                     id="strategies-add" |                     id="strategies-add" | ||||||
| @ -53,20 +44,10 @@ class AddStrategy extends React.Component { | |||||||
|                     title="Add Strategy" |                     title="Add Strategy" | ||||||
|                     onClick={this.stopPropagation} |                     onClick={this.stopPropagation} | ||||||
|                 /> |                 /> | ||||||
|                 <Menu |                 <Menu target="strategies-add" valign="bottom" align="right" ripple style={menuStyle}> | ||||||
|                     target="strategies-add" |  | ||||||
|                     valign="bottom" |  | ||||||
|                     align="right" |  | ||||||
|                     ripple |  | ||||||
|                     style={menuStyle} |  | ||||||
|                 > |  | ||||||
|                     <MenuItem disabled>Add Strategy:</MenuItem> |                     <MenuItem disabled>Add Strategy:</MenuItem> | ||||||
|                     {this.props.strategies.map(s => ( |                     {this.props.strategies.map(s => ( | ||||||
|                         <MenuItem |                         <MenuItem key={s.name} title={s.description} onClick={() => this.addStrategy(s.name)}> | ||||||
|                             key={s.name} |  | ||||||
|                             title={s.description} |  | ||||||
|                             onClick={() => this.addStrategy(s.name)} |  | ||||||
|                         > |  | ||||||
|                             {s.name} |                             {s.name} | ||||||
|                         </MenuItem> |                         </MenuItem> | ||||||
|                     ))} |                     ))} | ||||||
|  | |||||||
| @ -15,13 +15,7 @@ class StrategiesList extends React.Component { | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         const { |         const { strategies, configuredStrategies, moveStrategy, removeStrategy, updateStrategy } = this.props; | ||||||
|             strategies, |  | ||||||
|             configuredStrategies, |  | ||||||
|             moveStrategy, |  | ||||||
|             removeStrategy, |  | ||||||
|             updateStrategy, |  | ||||||
|         } = this.props; |  | ||||||
| 
 | 
 | ||||||
|         if (!configuredStrategies || configuredStrategies.length === 0) { |         if (!configuredStrategies || configuredStrategies.length === 0) { | ||||||
|             return <i style={{ color: 'red' }}>No strategies added</i>; |             return <i style={{ color: 'red' }}>No strategies added</i>; | ||||||
| @ -35,14 +29,10 @@ class StrategiesList extends React.Component { | |||||||
|                 moveStrategy={moveStrategy} |                 moveStrategy={moveStrategy} | ||||||
|                 removeStrategy={removeStrategy.bind(null, i)} |                 removeStrategy={removeStrategy.bind(null, i)} | ||||||
|                 updateStrategy={updateStrategy.bind(null, i)} |                 updateStrategy={updateStrategy.bind(null, i)} | ||||||
|                 strategyDefinition={strategies.find( |                 strategyDefinition={strategies.find(s => s.name === strategy.name)} | ||||||
|                     s => s.name === strategy.name |  | ||||||
|                 )} |  | ||||||
|             /> |             /> | ||||||
|         )); |         )); | ||||||
|         return ( |         return <div style={{ display: 'flex', flexWrap: 'wrap' }}>{blocks}</div>; | ||||||
|             <div style={{ display: 'flex', flexWrap: 'wrap' }}>{blocks}</div> |  | ||||||
|         ); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -25,10 +25,7 @@ class StrategiesSection extends React.Component { | |||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <div> |             <div> | ||||||
|                 <HeaderTitle |                 <HeaderTitle title="Activation strategies" actions={<AddStrategy {...this.props} />} /> | ||||||
|                     title="Activation strategies" |  | ||||||
|                     actions={<AddStrategy {...this.props} />} |  | ||||||
|                 /> |  | ||||||
|                 <StrategiesList {...this.props} /> |                 <StrategiesList {...this.props} /> | ||||||
|             </div> |             </div> | ||||||
|         ); |         ); | ||||||
|  | |||||||
| @ -1,16 +1,6 @@ | |||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import { | import { Textfield, Button, Card, CardTitle, CardText, CardActions, CardMenu, IconButton, Icon } from 'react-mdl'; | ||||||
|     Textfield, |  | ||||||
|     Button, |  | ||||||
|     Card, |  | ||||||
|     CardTitle, |  | ||||||
|     CardText, |  | ||||||
|     CardActions, |  | ||||||
|     CardMenu, |  | ||||||
|     IconButton, |  | ||||||
|     Icon, |  | ||||||
| } from 'react-mdl'; |  | ||||||
| import { DragSource, DropTarget } from 'react-dnd'; | import { DragSource, DropTarget } from 'react-dnd'; | ||||||
| import { Link } from 'react-router'; | import { Link } from 'react-router'; | ||||||
| import StrategyInputPercentage from './strategy-input-percentage'; | import StrategyInputPercentage from './strategy-input-percentage'; | ||||||
| @ -91,25 +81,17 @@ class StrategyConfigure extends React.Component { | |||||||
|             return parameters.map(({ name, type, description, required }) => { |             return parameters.map(({ name, type, description, required }) => { | ||||||
|                 let value = this.props.strategy.parameters[name]; |                 let value = this.props.strategy.parameters[name]; | ||||||
|                 if (type === 'percentage') { |                 if (type === 'percentage') { | ||||||
|                     if ( |                     if (value == null || (typeof value === 'string' && value === '')) { | ||||||
|                         value == null || |  | ||||||
|                         (typeof value === 'string' && value === '') |  | ||||||
|                     ) { |  | ||||||
|                         this.setConfig(name, 50); |                         this.setConfig(name, 50); | ||||||
|                     } |                     } | ||||||
|                     return ( |                     return ( | ||||||
|                         <div key={name}> |                         <div key={name}> | ||||||
|                             <StrategyInputPercentage |                             <StrategyInputPercentage | ||||||
|                                 name={name} |                                 name={name} | ||||||
|                                 onChange={this.handleConfigChange.bind( |                                 onChange={this.handleConfigChange.bind(this, name)} | ||||||
|                                     this, |  | ||||||
|                                     name |  | ||||||
|                                 )} |  | ||||||
|                                 value={1 * value} |                                 value={1 * value} | ||||||
|                             /> |                             /> | ||||||
|                             {description && ( |                             {description && <p className={styles.helpText}>{description}</p>} | ||||||
|                                 <p className={styles.helpText}>{description}</p> |  | ||||||
|                             )} |  | ||||||
|                         </div> |                         </div> | ||||||
|                     ); |                     ); | ||||||
|                 } else if (type === 'list') { |                 } else if (type === 'list') { | ||||||
| @ -122,14 +104,8 @@ class StrategyConfigure extends React.Component { | |||||||
|                     } |                     } | ||||||
|                     return ( |                     return ( | ||||||
|                         <div key={name}> |                         <div key={name}> | ||||||
|                             <StrategyInputList |                             <StrategyInputList name={name} list={list} setConfig={this.setConfig} /> | ||||||
|                                 name={name} |                             {description && <p className={styles.helpText}>{description}</p>} | ||||||
|                                 list={list} |  | ||||||
|                                 setConfig={this.setConfig} |  | ||||||
|                             /> |  | ||||||
|                             {description && ( |  | ||||||
|                                 <p className={styles.helpText}>{description}</p> |  | ||||||
|                             )} |  | ||||||
|                         </div> |                         </div> | ||||||
|                     ); |                     ); | ||||||
|                 } else if (type === 'number') { |                 } else if (type === 'number') { | ||||||
| @ -143,15 +119,10 @@ class StrategyConfigure extends React.Component { | |||||||
|                                 style={{ width: '100%' }} |                                 style={{ width: '100%' }} | ||||||
|                                 name={name} |                                 name={name} | ||||||
|                                 label={name} |                                 label={name} | ||||||
|                                 onChange={this.handleConfigChange.bind( |                                 onChange={this.handleConfigChange.bind(this, name)} | ||||||
|                                     this, |  | ||||||
|                                     name |  | ||||||
|                                 )} |  | ||||||
|                                 value={value} |                                 value={value} | ||||||
|                             /> |                             /> | ||||||
|                             {description && ( |                             {description && <p className={styles.helpText}>{description}</p>} | ||||||
|                                 <p className={styles.helpText}>{description}</p> |  | ||||||
|                             )} |  | ||||||
|                         </div> |                         </div> | ||||||
|                     ); |                     ); | ||||||
|                 } else { |                 } else { | ||||||
| @ -164,15 +135,10 @@ class StrategyConfigure extends React.Component { | |||||||
|                                 required={required} |                                 required={required} | ||||||
|                                 name={name} |                                 name={name} | ||||||
|                                 label={name} |                                 label={name} | ||||||
|                                 onChange={this.handleConfigChange.bind( |                                 onChange={this.handleConfigChange.bind(this, name)} | ||||||
|                                     this, |  | ||||||
|                                     name |  | ||||||
|                                 )} |  | ||||||
|                                 value={value} |                                 value={value} | ||||||
|                             /> |                             /> | ||||||
|                             {description && ( |                             {description && <p className={styles.helpText}>{description}</p>} | ||||||
|                                 <p className={styles.helpText}>{description}</p> |  | ||||||
|                             )} |  | ||||||
|                         </div> |                         </div> | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
| @ -182,31 +148,18 @@ class StrategyConfigure extends React.Component { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         const { |         const { isDragging, connectDragPreview, connectDragSource, connectDropTarget } = this.props; | ||||||
|             isDragging, |  | ||||||
|             connectDragPreview, |  | ||||||
|             connectDragSource, |  | ||||||
|             connectDropTarget, |  | ||||||
|         } = this.props; |  | ||||||
| 
 | 
 | ||||||
|         let item; |         let item; | ||||||
|         if (this.props.strategyDefinition) { |         if (this.props.strategyDefinition) { | ||||||
|             const inputFields = this.renderInputFields( |             const inputFields = this.renderInputFields(this.props.strategyDefinition); | ||||||
|                 this.props.strategyDefinition |  | ||||||
|             ); |  | ||||||
|             const { name } = this.props.strategy; |             const { name } = this.props.strategy; | ||||||
|             item = ( |             item = ( | ||||||
|                 <Card |                 <Card shadow={0} className={styles.card} style={{ opacity: isDragging ? '0.1' : '1' }}> | ||||||
|                     shadow={0} |  | ||||||
|                     className={styles.card} |  | ||||||
|                     style={{ opacity: isDragging ? '0.1' : '1' }} |  | ||||||
|                 > |  | ||||||
|                     <CardTitle className={styles.cardTitle}> |                     <CardTitle className={styles.cardTitle}> | ||||||
|                         <Icon name="extension" /> {name} |                         <Icon name="extension" /> {name} | ||||||
|                     </CardTitle> |                     </CardTitle> | ||||||
|                     <CardText> |                     <CardText>{this.props.strategyDefinition.description}</CardText> | ||||||
|                         {this.props.strategyDefinition.description} |  | ||||||
|                     </CardText> |  | ||||||
|                     {inputFields && ( |                     {inputFields && ( | ||||||
|                         <CardActions border style={{ padding: '20px' }}> |                         <CardActions border style={{ padding: '20px' }}> | ||||||
|                             {inputFields} |                             {inputFields} | ||||||
| @ -214,18 +167,10 @@ class StrategyConfigure extends React.Component { | |||||||
|                     )} |                     )} | ||||||
| 
 | 
 | ||||||
|                     <CardMenu className="mdl-color-text--white"> |                     <CardMenu className="mdl-color-text--white"> | ||||||
|                         <Link |                         <Link title="View strategy" to={`/strategies/view/${name}`} className={styles.editLink}> | ||||||
|                             title="View strategy" |  | ||||||
|                             to={`/strategies/view/${name}`} |  | ||||||
|                             className={styles.editLink} |  | ||||||
|                         > |  | ||||||
|                             <Icon name="link" /> |                             <Icon name="link" /> | ||||||
|                         </Link> |                         </Link> | ||||||
|                         <IconButton |                         <IconButton title="Remove strategy from toggle" name="delete" onClick={this.handleRemove} /> | ||||||
|                             title="Remove strategy from toggle" |  | ||||||
|                             name="delete" |  | ||||||
|                             onClick={this.handleRemove} |  | ||||||
|                         /> |  | ||||||
|                         {connectDragSource( |                         {connectDragSource( | ||||||
|                             <span className={styles.reorderIcon}> |                             <span className={styles.reorderIcon}> | ||||||
|                                 <Icon name="reorder" /> |                                 <Icon name="reorder" /> | ||||||
| @ -241,17 +186,10 @@ class StrategyConfigure extends React.Component { | |||||||
|                     <CardTitle>"{name}" deleted?</CardTitle> |                     <CardTitle>"{name}" deleted?</CardTitle> | ||||||
|                     <CardText> |                     <CardText> | ||||||
|                         The strategy "{name}" does not exist on this server. |                         The strategy "{name}" does not exist on this server. | ||||||
|                         <Link to={`/strategies/create?name=${name}`}> |                         <Link to={`/strategies/create?name=${name}`}>Want to create it now?</Link> | ||||||
|                             Want to create it now? |  | ||||||
|                         </Link> |  | ||||||
|                     </CardText> |                     </CardText> | ||||||
|                     <CardActions> |                     <CardActions> | ||||||
|                         <Button |                         <Button onClick={this.handleRemove} label="remove strategy" accent raised> | ||||||
|                             onClick={this.handleRemove} |  | ||||||
|                             label="remove strategy" |  | ||||||
|                             accent |  | ||||||
|                             raised |  | ||||||
|                         > |  | ||||||
|                             Remove |                             Remove | ||||||
|                         </Button> |                         </Button> | ||||||
|                     </CardActions> |                     </CardActions> | ||||||
| @ -259,9 +197,7 @@ class StrategyConfigure extends React.Component { | |||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return connectDropTarget( |         return connectDropTarget(connectDragPreview(<div className={styles.item}>{item}</div>)); | ||||||
|             connectDragPreview(<div className={styles.item}>{item}</div>) |  | ||||||
|         ); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -46,10 +46,7 @@ export default class InputList extends Component { | |||||||
|     onClose(index) { |     onClose(index) { | ||||||
|         const { name, list, setConfig } = this.props; |         const { name, list, setConfig } = this.props; | ||||||
|         list[index] = null; |         list[index] = null; | ||||||
|         setConfig( |         setConfig(name, list.length === 1 ? '' : list.filter(Boolean).join(',')); | ||||||
|             name, |  | ||||||
|             list.length === 1 ? '' : list.filter(Boolean).join(',') |  | ||||||
|         ); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
| @ -58,11 +55,7 @@ export default class InputList extends Component { | |||||||
|             <div> |             <div> | ||||||
|                 <p>{name}</p> |                 <p>{name}</p> | ||||||
|                 {list.map((entryValue, index) => ( |                 {list.map((entryValue, index) => ( | ||||||
|                     <Chip |                     <Chip key={index + entryValue} style={{ marginRight: '3px' }} onClose={() => this.onClose(index)}> | ||||||
|                         key={index + entryValue} |  | ||||||
|                         style={{ marginRight: '3px' }} |  | ||||||
|                         onClose={() => this.onClose(index)} |  | ||||||
|                     > |  | ||||||
|                         {entryValue} |                         {entryValue} | ||||||
|                     </Chip> |                     </Chip> | ||||||
|                 ))} |                 ))} | ||||||
| @ -79,11 +72,7 @@ export default class InputList extends Component { | |||||||
|                     <IconButton |                     <IconButton | ||||||
|                         name="add" |                         name="add" | ||||||
|                         raised |                         raised | ||||||
|                         style={{ |                         style={{ flex: 1, flexGrow: 0, margin: '20px 0 0 10px' }} | ||||||
|                             flex: 1, |  | ||||||
|                             flexGrow: 0, |  | ||||||
|                             margin: '20px 0 0 10px', |  | ||||||
|                         }} |  | ||||||
|                         onClick={this.setValue} |                         onClick={this.setValue} | ||||||
|                     /> |                     /> | ||||||
|                 </div> |                 </div> | ||||||
|  | |||||||
| @ -13,13 +13,6 @@ export default ({ name, value, onChange }) => ( | |||||||
|         <div style={labelStyle}> |         <div style={labelStyle}> | ||||||
|             {name}: {value}% |             {name}: {value}% | ||||||
|         </div> |         </div> | ||||||
|         <Slider |         <Slider min={0} max={100} defaultValue={value} value={value} onChange={onChange} label={name} /> | ||||||
|             min={0} |  | ||||||
|             max={100} |  | ||||||
|             defaultValue={value} |  | ||||||
|             value={value} |  | ||||||
|             onChange={onChange} |  | ||||||
|             label={name} |  | ||||||
|         /> |  | ||||||
|     </div> |     </div> | ||||||
| ); | ); | ||||||
|  | |||||||
| @ -2,22 +2,9 @@ import React from 'react'; | |||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import Feature from './feature-list-item-component'; | import Feature from './feature-list-item-component'; | ||||||
| import { Link } from 'react-router'; | import { Link } from 'react-router'; | ||||||
| import { | import { Icon, FABButton, Textfield, Menu, MenuItem, Card, CardActions, List } from 'react-mdl'; | ||||||
|     Icon, |  | ||||||
|     FABButton, |  | ||||||
|     Textfield, |  | ||||||
|     Menu, |  | ||||||
|     MenuItem, |  | ||||||
|     Card, |  | ||||||
|     CardActions, |  | ||||||
|     List, |  | ||||||
| } from 'react-mdl'; |  | ||||||
| 
 | 
 | ||||||
| import { | import { MenuItemWithIcon, DropdownButton, styles as commonStyles } from '../common'; | ||||||
|     MenuItemWithIcon, |  | ||||||
|     DropdownButton, |  | ||||||
|     styles as commonStyles, |  | ||||||
| } from '../common'; |  | ||||||
| import styles from './feature.scss'; | import styles from './feature.scss'; | ||||||
| 
 | 
 | ||||||
| export default class FeatureListComponent extends React.PureComponent { | export default class FeatureListComponent extends React.PureComponent { | ||||||
| @ -47,10 +34,7 @@ export default class FeatureListComponent extends React.PureComponent { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     toggleMetrics() { |     toggleMetrics() { | ||||||
|         this.props.updateSetting( |         this.props.updateSetting('showLastHour', !this.props.settings.showLastHour); | ||||||
|             'showLastHour', |  | ||||||
|             !this.props.settings.showLastHour |  | ||||||
|         ); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     setFilter(v) { |     setFilter(v) { | ||||||
| @ -62,12 +46,7 @@ export default class FeatureListComponent extends React.PureComponent { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         const { |         const { features, toggleFeature, featureMetrics, settings } = this.props; | ||||||
|             features, |  | ||||||
|             toggleFeature, |  | ||||||
|             featureMetrics, |  | ||||||
|             settings, |  | ||||||
|         } = this.props; |  | ||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <div> |             <div> | ||||||
| @ -81,32 +60,16 @@ export default class FeatureListComponent extends React.PureComponent { | |||||||
|                         label="Search" |                         label="Search" | ||||||
|                         style={{ width: '100%' }} |                         style={{ width: '100%' }} | ||||||
|                     /> |                     /> | ||||||
|                     <Link |                     <Link to="/features/create" className={styles.toolbarButton}> | ||||||
|                         to="/features/create" |  | ||||||
|                         className={styles.toolbarButton} |  | ||||||
|                     > |  | ||||||
|                         <FABButton accent title="Create feature toggle"> |                         <FABButton accent title="Create feature toggle"> | ||||||
|                             <Icon name="add" /> |                             <Icon name="add" /> | ||||||
|                         </FABButton> |                         </FABButton> | ||||||
|                     </Link> |                     </Link> | ||||||
|                 </div> |                 </div> | ||||||
|                 <Card |                 <Card shadow={0} className={commonStyles.fullwidth} style={{ overflow: 'visible' }}> | ||||||
|                     shadow={0} |  | ||||||
|                     className={commonStyles.fullwidth} |  | ||||||
|                     style={{ overflow: 'visible' }} |  | ||||||
|                 > |  | ||||||
|                     <CardActions> |                     <CardActions> | ||||||
|                         <DropdownButton |                         <DropdownButton id="metric" label={`Last ${settings.showLastHour ? 'hour' : 'minute'}`} /> | ||||||
|                             id="metric" |                         <Menu target="metric" onClick={() => this.toggleMetrics()} style={{ width: '168px' }}> | ||||||
|                             label={`Last ${settings.showLastHour |  | ||||||
|                                 ? 'hour' |  | ||||||
|                                 : 'minute'}`} |  | ||||||
|                         /> |  | ||||||
|                         <Menu |  | ||||||
|                             target="metric" |  | ||||||
|                             onClick={() => this.toggleMetrics()} |  | ||||||
|                             style={{ width: '168px' }} |  | ||||||
|                         > |  | ||||||
|                             <MenuItemWithIcon |                             <MenuItemWithIcon | ||||||
|                                 icon="hourglass_empty" |                                 icon="hourglass_empty" | ||||||
|                                 disabled={!settings.showLastHour} |                                 disabled={!settings.showLastHour} | ||||||
| @ -120,46 +83,25 @@ export default class FeatureListComponent extends React.PureComponent { | |||||||
|                                 label="Last hour" |                                 label="Last hour" | ||||||
|                             /> |                             /> | ||||||
|                         </Menu> |                         </Menu> | ||||||
|                         <DropdownButton |                         <DropdownButton id="sorting" label={`By ${settings.sort}`} /> | ||||||
|                             id="sorting" |  | ||||||
|                             label={`By ${settings.sort}`} |  | ||||||
|                         /> |  | ||||||
|                         <Menu |                         <Menu | ||||||
|                             target="sorting" |                             target="sorting" | ||||||
|                             onClick={e => |                             onClick={e => this.setSort(e.target.getAttribute('data-target'))} | ||||||
|                                 this.setSort( |  | ||||||
|                                     e.target.getAttribute('data-target') |  | ||||||
|                                 )} |  | ||||||
|                             style={{ width: '168px' }} |                             style={{ width: '168px' }} | ||||||
|                         > |                         > | ||||||
|                             <MenuItem |                             <MenuItem disabled={settings.sort === 'name'} data-target="name"> | ||||||
|                                 disabled={settings.sort === 'name'} |  | ||||||
|                                 data-target="name" |  | ||||||
|                             > |  | ||||||
|                                 Name |                                 Name | ||||||
|                             </MenuItem> |                             </MenuItem> | ||||||
|                             <MenuItem |                             <MenuItem disabled={settings.sort === 'enabled'} data-target="enabled"> | ||||||
|                                 disabled={settings.sort === 'enabled'} |  | ||||||
|                                 data-target="enabled" |  | ||||||
|                             > |  | ||||||
|                                 Enabled |                                 Enabled | ||||||
|                             </MenuItem> |                             </MenuItem> | ||||||
|                             <MenuItem |                             <MenuItem disabled={settings.sort === 'created'} data-target="created"> | ||||||
|                                 disabled={settings.sort === 'created'} |  | ||||||
|                                 data-target="created" |  | ||||||
|                             > |  | ||||||
|                                 Created |                                 Created | ||||||
|                             </MenuItem> |                             </MenuItem> | ||||||
|                             <MenuItem |                             <MenuItem disabled={settings.sort === 'strategies'} data-target="strategies"> | ||||||
|                                 disabled={settings.sort === 'strategies'} |  | ||||||
|                                 data-target="strategies" |  | ||||||
|                             > |  | ||||||
|                                 Strategies |                                 Strategies | ||||||
|                             </MenuItem> |                             </MenuItem> | ||||||
|                             <MenuItem |                             <MenuItem disabled={settings.sort === 'metrics'} data-target="metrics"> | ||||||
|                                 disabled={settings.sort === 'metrics'} |  | ||||||
|                                 data-target="metrics" |  | ||||||
|                             > |  | ||||||
|                                 Metrics |                                 Metrics | ||||||
|                             </MenuItem> |                             </MenuItem> | ||||||
|                         </Menu> |                         </Menu> | ||||||
| @ -170,12 +112,8 @@ export default class FeatureListComponent extends React.PureComponent { | |||||||
|                             <Feature |                             <Feature | ||||||
|                                 key={i} |                                 key={i} | ||||||
|                                 settings={settings} |                                 settings={settings} | ||||||
|                                 metricsLastHour={ |                                 metricsLastHour={featureMetrics.lastHour[feature.name]} | ||||||
|                                     featureMetrics.lastHour[feature.name] |                                 metricsLastMinute={featureMetrics.lastMinute[feature.name]} | ||||||
|                                 } |  | ||||||
|                                 metricsLastMinute={ |  | ||||||
|                                     featureMetrics.lastMinute[feature.name] |  | ||||||
|                                 } |  | ||||||
|                                 feature={feature} |                                 feature={feature} | ||||||
|                                 toggleFeature={toggleFeature} |                                 toggleFeature={toggleFeature} | ||||||
|                             /> |                             /> | ||||||
|  | |||||||
| @ -1,8 +1,5 @@ | |||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import { | import { toggleFeature, fetchFeatureToggles } from '../../store/feature-actions'; | ||||||
|     toggleFeature, |  | ||||||
|     fetchFeatureToggles, |  | ||||||
| } from '../../store/feature-actions'; |  | ||||||
| import { fetchFeatureMetrics } from '../../store/feature-metrics-actions'; | import { fetchFeatureMetrics } from '../../store/feature-metrics-actions'; | ||||||
| import { updateSettingForGroup } from '../../store/settings/actions'; | import { updateSettingForGroup } from '../../store/settings/actions'; | ||||||
| 
 | 
 | ||||||
| @ -33,9 +30,7 @@ const mapStateToProps = state => { | |||||||
|             a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1 |             a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1 | ||||||
|         ); |         ); | ||||||
|     } else if (settings.sort === 'created') { |     } else if (settings.sort === 'created') { | ||||||
|         features = features.sort( |         features = features.sort((a, b) => (new Date(a.createdAt) > new Date(b.createdAt) ? -1 : 1)); | ||||||
|             (a, b) => (new Date(a.createdAt) > new Date(b.createdAt) ? -1 : 1) |  | ||||||
|         ); |  | ||||||
|     } else if (settings.sort === 'name') { |     } else if (settings.sort === 'name') { | ||||||
|         features = features.sort((a, b) => { |         features = features.sort((a, b) => { | ||||||
|             if (a.name < b.name) { |             if (a.name < b.name) { | ||||||
| @ -47,13 +42,9 @@ const mapStateToProps = state => { | |||||||
|             return 0; |             return 0; | ||||||
|         }); |         }); | ||||||
|     } else if (settings.sort === 'strategies') { |     } else if (settings.sort === 'strategies') { | ||||||
|         features = features.sort( |         features = features.sort((a, b) => (a.strategies.length > b.strategies.length ? -1 : 1)); | ||||||
|             (a, b) => (a.strategies.length > b.strategies.length ? -1 : 1) |  | ||||||
|         ); |  | ||||||
|     } else if (settings.sort === 'metrics') { |     } else if (settings.sort === 'metrics') { | ||||||
|         const target = settings.showLastHour |         const target = settings.showLastHour ? featureMetrics.lastHour : featureMetrics.lastMinute; | ||||||
|             ? featureMetrics.lastHour |  | ||||||
|             : featureMetrics.lastMinute; |  | ||||||
| 
 | 
 | ||||||
|         features = features.sort((a, b) => { |         features = features.sort((a, b) => { | ||||||
|             if (!target[a.name]) { |             if (!target[a.name]) { | ||||||
| @ -83,8 +74,6 @@ const mapDispatchToProps = { | |||||||
|     updateSetting: updateSettingForGroup('feature'), |     updateSetting: updateSettingForGroup('feature'), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FeatureListContainer = connect(mapStateToProps, mapDispatchToProps)( | const FeatureListContainer = connect(mapStateToProps, mapDispatchToProps)(FeatureListComponent); | ||||||
|     FeatureListComponent |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| export default FeatureListContainer; | export default FeatureListContainer; | ||||||
|  | |||||||
| @ -12,10 +12,7 @@ const StrategyChipItem = ({ strategy }) => ( | |||||||
|         <ChipContact className="mdl-color--blue-grey mdl-color-text--white"> |         <ChipContact className="mdl-color--blue-grey mdl-color-text--white"> | ||||||
|             <Icon style={{ marginTop: '3px' }} name="link" /> |             <Icon style={{ marginTop: '3px' }} name="link" /> | ||||||
|         </ChipContact> |         </ChipContact> | ||||||
|         <Link |         <Link to={`/strategies/view/${strategy.name}`} className="mdl-color-text--blue-grey"> | ||||||
|             to={`/strategies/view/${strategy.name}`} |  | ||||||
|             className="mdl-color-text--blue-grey" |  | ||||||
|         > |  | ||||||
|             {strategy.name} |             {strategy.name} | ||||||
|         </Link> |         </Link> | ||||||
|     </Chip> |     </Chip> | ||||||
| @ -25,9 +22,7 @@ const StrategyChipItem = ({ strategy }) => ( | |||||||
| const StrategiesList = ({ strategies }) => ( | const StrategiesList = ({ strategies }) => ( | ||||||
|     <div style={{ verticalAlign: 'middle', paddingTop: '14px' }}> |     <div style={{ verticalAlign: 'middle', paddingTop: '14px' }}> | ||||||
|         With {strategies.length > 1 ? 'strategies' : 'strategy'}{' '} |         With {strategies.length > 1 ? 'strategies' : 'strategy'}{' '} | ||||||
|         {strategies.map((strategy, i) => ( |         {strategies.map((strategy, i) => <StrategyChipItem key={i} strategy={strategy} />)} | ||||||
|             <StrategyChipItem key={i} strategy={strategy} /> |  | ||||||
|         ))} |  | ||||||
|     </div> |     </div> | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| @ -59,10 +54,8 @@ export default class MetricComponent extends React.Component { | |||||||
|             seenApps = [], |             seenApps = [], | ||||||
|         } = metrics; |         } = metrics; | ||||||
| 
 | 
 | ||||||
|         const lastHourPercent = |         const lastHourPercent = 1 * calc(lastHour.yes, lastHour.yes + lastHour.no, 0); | ||||||
|             1 * calc(lastHour.yes, lastHour.yes + lastHour.no, 0); |         const lastMinutePercent = 1 * calc(lastMinute.yes, lastMinute.yes + lastMinute.no, 0); | ||||||
|         const lastMinutePercent = |  | ||||||
|             1 * calc(lastMinute.yes, lastMinute.yes + lastMinute.no, 0); |  | ||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <div style={{ padding: '16px' }}> |             <div style={{ padding: '16px' }}> | ||||||
| @ -75,9 +68,7 @@ export default class MetricComponent extends React.Component { | |||||||
|                             animatePercentageText |                             animatePercentageText | ||||||
|                         /> |                         /> | ||||||
|                         {lastMinute.isFallback ? ( |                         {lastMinute.isFallback ? ( | ||||||
|                             <p className="mdl-color-text--grey-500"> |                             <p className="mdl-color-text--grey-500">No metrics available</p> | ||||||
|                                 No metrics available |  | ||||||
|                             </p> |  | ||||||
|                         ) : ( |                         ) : ( | ||||||
|                             <p> |                             <p> | ||||||
|                                 <strong>Last minute</strong> |                                 <strong>Last minute</strong> | ||||||
| @ -86,14 +77,9 @@ export default class MetricComponent extends React.Component { | |||||||
|                         )} |                         )} | ||||||
|                     </Cell> |                     </Cell> | ||||||
|                     <Cell col={4} tablet={4} phone={12}> |                     <Cell col={4} tablet={4} phone={12}> | ||||||
|                         <Progress |                         <Progress percentage={lastHourPercent} isFallback={lastHour.isFallback} /> | ||||||
|                             percentage={lastHourPercent} |  | ||||||
|                             isFallback={lastHour.isFallback} |  | ||||||
|                         /> |  | ||||||
|                         {lastHour.isFallback ? ( |                         {lastHour.isFallback ? ( | ||||||
|                             <p className="mdl-color-text--grey-500"> |                             <p className="mdl-color-text--grey-500">No metrics available</p> | ||||||
|                                 No metrics available |  | ||||||
|                             </p> |  | ||||||
|                         ) : ( |                         ) : ( | ||||||
|                             <p> |                             <p> | ||||||
|                                 <strong>Last hour</strong> |                                 <strong>Last hour</strong> | ||||||
| @ -115,20 +101,14 @@ export default class MetricComponent extends React.Component { | |||||||
|                                 /> |                                 /> | ||||||
|                                 <div> |                                 <div> | ||||||
|                                     <small> |                                     <small> | ||||||
|                                         <strong> |                                         <strong>Not used in an app in the last hour.</strong> | ||||||
|                                             Not used in an app in the last hour. |                                         This might be due to your client implementation is not reporting usage. | ||||||
|                                         </strong> |  | ||||||
|                                         This might be due to your client |  | ||||||
|                                         implementation is not reporting usage. |  | ||||||
|                                     </small> |                                     </small> | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
|                         )} |                         )} | ||||||
|                         <AppsLinkList apps={seenApps} /> |                         <AppsLinkList apps={seenApps} /> | ||||||
|                         <span> |                         <span>Created {formatFullDateTime(featureToggle.createdAt)}</span> | ||||||
|                             Created{' '} |  | ||||||
|                             {formatFullDateTime(featureToggle.createdAt)} |  | ||||||
|                         </span> |  | ||||||
|                     </Cell> |                     </Cell> | ||||||
|                 </Grid> |                 </Grid> | ||||||
|                 <hr /> |                 <hr /> | ||||||
|  | |||||||
| @ -1,9 +1,6 @@ | |||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| 
 | 
 | ||||||
| import { | import { fetchFeatureMetrics, fetchSeenApps } from '../../store/feature-metrics-actions'; | ||||||
|     fetchFeatureMetrics, |  | ||||||
|     fetchSeenApps, |  | ||||||
| } from '../../store/feature-metrics-actions'; |  | ||||||
| 
 | 
 | ||||||
| import MatricComponent from './metric-component'; | import MatricComponent from './metric-component'; | ||||||
| 
 | 
 | ||||||
| @ -18,10 +15,7 @@ function getMetricsForToggle(state, toggleName) { | |||||||
|     } |     } | ||||||
|     if (state.featureMetrics.hasIn(['lastHour', toggleName])) { |     if (state.featureMetrics.hasIn(['lastHour', toggleName])) { | ||||||
|         result.lastHour = state.featureMetrics.getIn(['lastHour', toggleName]); |         result.lastHour = state.featureMetrics.getIn(['lastHour', toggleName]); | ||||||
|         result.lastMinute = state.featureMetrics.getIn([ |         result.lastMinute = state.featureMetrics.getIn(['lastMinute', toggleName]); | ||||||
|             'lastMinute', |  | ||||||
|             toggleName, |  | ||||||
|         ]); |  | ||||||
|     } |     } | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  | |||||||
| @ -41,9 +41,7 @@ class Progress extends Component { | |||||||
|         const TOTAL_ANIMATION_TIME = 5000; |         const TOTAL_ANIMATION_TIME = 5000; | ||||||
|         const diff = start > target ? -(start - target) : target - start; |         const diff = start > target ? -(start - target) : target - start; | ||||||
|         const perCycle = TOTAL_ANIMATION_TIME / diff; |         const perCycle = TOTAL_ANIMATION_TIME / diff; | ||||||
|         const cyclesCounter = Math.round( |         const cyclesCounter = Math.round(Math.abs(TOTAL_ANIMATION_TIME / perCycle)); | ||||||
|             Math.abs(TOTAL_ANIMATION_TIME / perCycle) |  | ||||||
|         ); |  | ||||||
|         const perCycleTime = Math.round(Math.abs(perCycle)); |         const perCycleTime = Math.round(Math.abs(perCycle)); | ||||||
| 
 | 
 | ||||||
|         return { |         return { | ||||||
| @ -95,9 +93,7 @@ class Progress extends Component { | |||||||
|         const diameter = Math.PI * 2 * radius; |         const diameter = Math.PI * 2 * radius; | ||||||
|         const progressStyle = { |         const progressStyle = { | ||||||
|             strokeDasharray: `${diameter}px ${diameter}px`, |             strokeDasharray: `${diameter}px ${diameter}px`, | ||||||
|             strokeDashoffset: `${(100 - this.state.percentage) / |             strokeDashoffset: `${(100 - this.state.percentage) / 100 * diameter}px`, | ||||||
|                 100 * |  | ||||||
|                 diameter}px`, |  | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         return isFallback ? ( |         return isFallback ? ( | ||||||
| @ -113,9 +109,7 @@ class Progress extends Component { | |||||||
|         ) : ( |         ) : ( | ||||||
|             <svg viewBox="0 0 100 100"> |             <svg viewBox="0 0 100 100"> | ||||||
|                 <path |                 <path | ||||||
|                     className={[styles.trail, 'mdl-color-text--grey-300'].join( |                     className={[styles.trail, 'mdl-color-text--grey-300'].join(' ')} | ||||||
|                         ' ' |  | ||||||
|                     )} |  | ||||||
|                     d={pathDescription} |                     d={pathDescription} | ||||||
|                     strokeWidth={strokeWidth} |                     strokeWidth={strokeWidth} | ||||||
|                     fillOpacity={0} |                     fillOpacity={0} | ||||||
|  | |||||||
| @ -1,16 +1,6 @@ | |||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import { | import { Tabs, Tab, ProgressBar, Button, Card, CardTitle, CardText, CardActions, Switch } from 'react-mdl'; | ||||||
|     Tabs, |  | ||||||
|     Tab, |  | ||||||
|     ProgressBar, |  | ||||||
|     Button, |  | ||||||
|     Card, |  | ||||||
|     CardTitle, |  | ||||||
|     CardText, |  | ||||||
|     CardActions, |  | ||||||
|     Switch, |  | ||||||
| } from 'react-mdl'; |  | ||||||
| import { hashHistory, Link } from 'react-router'; | import { hashHistory, Link } from 'react-router'; | ||||||
| 
 | 
 | ||||||
| import HistoryComponent from '../history/history-list-toggle-container'; | import HistoryComponent from '../history/history-list-toggle-container'; | ||||||
| @ -90,9 +80,7 @@ export default class ViewFeatureToggleComponent extends React.Component { | |||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const activeTabId = TABS[this.props.activeTab] |         const activeTabId = TABS[this.props.activeTab] ? TABS[this.props.activeTab] : TABS.view; | ||||||
|             ? TABS[this.props.activeTab] |  | ||||||
|             : TABS.view; |  | ||||||
|         const tabContent = this.getTabContent(activeTab); |         const tabContent = this.getTabContent(activeTab); | ||||||
| 
 | 
 | ||||||
|         const removeToggle = () => { |         const removeToggle = () => { | ||||||
| @ -106,16 +94,8 @@ export default class ViewFeatureToggleComponent extends React.Component { | |||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <Card |             <Card shadow={0} className={commonStyles.fullwidth} style={{ overflow: 'visible' }}> | ||||||
|                 shadow={0} |                 <CardTitle style={{ paddingTop: '24px', wordBreak: 'break-all' }}>{featureToggle.name}</CardTitle> | ||||||
|                 className={commonStyles.fullwidth} |  | ||||||
|                 style={{ overflow: 'visible' }} |  | ||||||
|             > |  | ||||||
|                 <CardTitle |  | ||||||
|                     style={{ paddingTop: '24px', wordBreak: 'break-all' }} |  | ||||||
|                 > |  | ||||||
|                     {featureToggle.name} |  | ||||||
|                 </CardTitle> |  | ||||||
|                 <CardText>{featureToggle.description}</CardText> |                 <CardText>{featureToggle.description}</CardText> | ||||||
|                 <CardActions |                 <CardActions | ||||||
|                     border |                     border | ||||||
| @ -145,22 +125,9 @@ export default class ViewFeatureToggleComponent extends React.Component { | |||||||
|                     tabBarProps={{ style: { width: '100%' } }} |                     tabBarProps={{ style: { width: '100%' } }} | ||||||
|                     className="mdl-color--grey-100" |                     className="mdl-color--grey-100" | ||||||
|                 > |                 > | ||||||
|                     <Tab |                     <Tab onClick={() => this.goToTab('view', featureToggleName)}>Metrics</Tab> | ||||||
|                         onClick={() => this.goToTab('view', featureToggleName)} |                     <Tab onClick={() => this.goToTab('edit', featureToggleName)}>Edit</Tab> | ||||||
|                     > |                     <Tab onClick={() => this.goToTab('history', featureToggleName)}>History</Tab> | ||||||
|                         Metrics |  | ||||||
|                     </Tab> |  | ||||||
|                     <Tab |  | ||||||
|                         onClick={() => this.goToTab('edit', featureToggleName)} |  | ||||||
|                     > |  | ||||||
|                         Edit |  | ||||||
|                     </Tab> |  | ||||||
|                     <Tab |  | ||||||
|                         onClick={() => |  | ||||||
|                             this.goToTab('history', featureToggleName)} |  | ||||||
|                     > |  | ||||||
|                         History |  | ||||||
|                     </Tab> |  | ||||||
|                 </Tabs> |                 </Tabs> | ||||||
|                 {tabContent} |                 {tabContent} | ||||||
|             </Card> |             </Card> | ||||||
|  | |||||||
| @ -1,19 +1,13 @@ | |||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| 
 | 
 | ||||||
| import { | import { fetchFeatureToggles, toggleFeature, removeFeatureToggle } from '../../store/feature-actions'; | ||||||
|     fetchFeatureToggles, |  | ||||||
|     toggleFeature, |  | ||||||
|     removeFeatureToggle, |  | ||||||
| } from '../../store/feature-actions'; |  | ||||||
| 
 | 
 | ||||||
| import ViewToggleComponent from './view-component'; | import ViewToggleComponent from './view-component'; | ||||||
| 
 | 
 | ||||||
| export default connect( | export default connect( | ||||||
|     (state, props) => ({ |     (state, props) => ({ | ||||||
|         features: state.features.toJS(), |         features: state.features.toJS(), | ||||||
|         featureToggle: state.features |         featureToggle: state.features.toJS().find(toggle => toggle.name === props.featureToggleName), | ||||||
|             .toJS() |  | ||||||
|             .find(toggle => toggle.name === props.featureToggleName), |  | ||||||
|         activeTab: props.activeTab, |         activeTab: props.activeTab, | ||||||
|     }), |     }), | ||||||
|     { |     { | ||||||
|  | |||||||
| @ -9,8 +9,6 @@ const mapStateToProps = state => { | |||||||
|     }; |     }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const HistoryListContainer = connect(mapStateToProps, { fetchHistory })( | const HistoryListContainer = connect(mapStateToProps, { fetchHistory })(HistoryComponent); | ||||||
|     HistoryComponent |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| export default HistoryListContainer; | export default HistoryListContainer; | ||||||
|  | |||||||
| @ -84,18 +84,12 @@ class HistoryItem extends PureComponent { | |||||||
|             changes = entry.diffs.map(buildDiff); |             changes = entry.diffs.map(buildDiff); | ||||||
|         } else { |         } else { | ||||||
|             // Just show the data if there is no diff yet. |             // Just show the data if there is no diff yet. | ||||||
|             changes = ( |             changes = <div className={KLASSES.N}>{JSON.stringify(entry.data, null, 2)}</div>; | ||||||
|                 <div className={KLASSES.N}> |  | ||||||
|                     {JSON.stringify(entry.data, null, 2)} |  | ||||||
|                 </div> |  | ||||||
|             ); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <pre style={{ overflowX: 'auto', overflowY: 'hidden' }}> |             <pre style={{ overflowX: 'auto', overflowY: 'hidden' }}> | ||||||
|                 <code className="smalltext man"> |                 <code className="smalltext man">{changes.length === 0 ? '(no changes)' : changes}</code> | ||||||
|                     {changes.length === 0 ? '(no changes)' : changes} |  | ||||||
|                 </code> |  | ||||||
|             </pre> |             </pre> | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -2,11 +2,7 @@ import React, { Component } from 'react'; | |||||||
| import HistoryItemDiff from './history-item-diff'; | import HistoryItemDiff from './history-item-diff'; | ||||||
| import HistoryItemJson from './history-item-json'; | import HistoryItemJson from './history-item-json'; | ||||||
| import { Table, TableHeader } from 'react-mdl'; | import { Table, TableHeader } from 'react-mdl'; | ||||||
| import { | import { DataTableHeader, SwitchWithLabel, styles as commonStyles } from '../common'; | ||||||
|     DataTableHeader, |  | ||||||
|     SwitchWithLabel, |  | ||||||
|     styles as commonStyles, |  | ||||||
| } from '../common'; |  | ||||||
| import { formatFullDateTime } from '../common/util'; | import { formatFullDateTime } from '../common/util'; | ||||||
| 
 | 
 | ||||||
| import styles from './history.scss'; | import styles from './history.scss'; | ||||||
| @ -26,11 +22,7 @@ class HistoryList extends Component { | |||||||
|         const truncateTableCell = v => ( |         const truncateTableCell = v => ( | ||||||
|             <span |             <span | ||||||
|                 className={commonStyles.truncate} |                 className={commonStyles.truncate} | ||||||
|                 style={{ |                 style={{ display: 'inline-block', verticalAlign: 'middle', width: '100%' }} | ||||||
|                     display: 'inline-block', |  | ||||||
|                     verticalAlign: 'middle', |  | ||||||
|                     width: '100%', |  | ||||||
|                 }} |  | ||||||
|             > |             > | ||||||
|                 {v} |                 {v} | ||||||
|             </span> |             </span> | ||||||
| @ -39,9 +31,7 @@ class HistoryList extends Component { | |||||||
|         let entries; |         let entries; | ||||||
| 
 | 
 | ||||||
|         if (showData) { |         if (showData) { | ||||||
|             entries = history.map(entry => ( |             entries = history.map(entry => <HistoryItemJson key={`log${entry.id}`} entry={entry} />); | ||||||
|                 <HistoryItemJson key={`log${entry.id}`} entry={entry} /> |  | ||||||
|             )); |  | ||||||
|         } else { |         } else { | ||||||
|             entries = ( |             entries = ( | ||||||
|                 <Table |                 <Table | ||||||
| @ -55,33 +45,16 @@ class HistoryList extends Component { | |||||||
|                         ) |                         ) | ||||||
|                     )} |                     )} | ||||||
|                     className={commonStyles.fullwidth} |                     className={commonStyles.fullwidth} | ||||||
|                     style={{ |                     style={{ border: 0, tableLayout: 'fixed', minWidth: '840px' }} | ||||||
|                         border: 0, |  | ||||||
|                         tableLayout: 'fixed', |  | ||||||
|                         minWidth: '840px', |  | ||||||
|                     }} |  | ||||||
|                 > |                 > | ||||||
|                     <TableHeader |                     <TableHeader name="type" cellFormatter={truncateTableCell} style={{ width: '136px' }}> | ||||||
|                         name="type" |  | ||||||
|                         cellFormatter={truncateTableCell} |  | ||||||
|                         style={{ width: '136px' }} |  | ||||||
|                     > |  | ||||||
|                         Type |                         Type | ||||||
|                     </TableHeader> |                     </TableHeader> | ||||||
|                     <TableHeader |                     <TableHeader name="createdBy" cellFormatter={truncateTableCell} style={{ width: '115px' }}> | ||||||
|                         name="createdBy" |  | ||||||
|                         cellFormatter={truncateTableCell} |  | ||||||
|                         style={{ width: '115px' }} |  | ||||||
|                     > |  | ||||||
|                         User |                         User | ||||||
|                     </TableHeader> |                     </TableHeader> | ||||||
|                     <TableHeader name="diff">Diff</TableHeader> |                     <TableHeader name="diff">Diff</TableHeader> | ||||||
|                     <TableHeader |                     <TableHeader numeric name="createdAt" cellFormatter={formatFullDateTime} style={{ width: '165px' }}> | ||||||
|                         numeric |  | ||||||
|                         name="createdAt" |  | ||||||
|                         cellFormatter={formatFullDateTime} |  | ||||||
|                         style={{ width: '165px' }} |  | ||||||
|                     > |  | ||||||
|                         Time |                         Time | ||||||
|                     </TableHeader> |                     </TableHeader> | ||||||
|                 </Table> |                 </Table> | ||||||
| @ -93,10 +66,7 @@ class HistoryList extends Component { | |||||||
|                 <DataTableHeader |                 <DataTableHeader | ||||||
|                     title={this.props.title} |                     title={this.props.title} | ||||||
|                     actions={ |                     actions={ | ||||||
|                         <SwitchWithLabel |                         <SwitchWithLabel checked={showData} onChange={this.toggleShowDiff.bind(this)}> | ||||||
|                             checked={showData} |  | ||||||
|                             onChange={this.toggleShowDiff.bind(this)} |  | ||||||
|                         > |  | ||||||
|                             Full events |                             Full events | ||||||
|                         </SwitchWithLabel> |                         </SwitchWithLabel> | ||||||
|                     } |                     } | ||||||
|  | |||||||
| @ -52,44 +52,23 @@ export function createActions({ id, prepare = v => v }) { | |||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|                 setValue(key, value) { |                 setValue(key, value) { | ||||||
|                     dispatch( |                     dispatch(createSet({ id: getId(id, ownProps), key, value })); | ||||||
|                         createSet({ id: getId(id, ownProps), key, value }) |  | ||||||
|                     ); |  | ||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|                 pushToList(key, value) { |                 pushToList(key, value) { | ||||||
|                     dispatch( |                     dispatch(createPush({ id: getId(id, ownProps), key, value })); | ||||||
|                         createPush({ id: getId(id, ownProps), key, value }) |  | ||||||
|                     ); |  | ||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|                 removeFromList(key, index) { |                 removeFromList(key, index) { | ||||||
|                     dispatch( |                     dispatch(createPop({ id: getId(id, ownProps), key, index })); | ||||||
|                         createPop({ id: getId(id, ownProps), key, index }) |  | ||||||
|                     ); |  | ||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|                 moveItem(key, index, toIndex) { |                 moveItem(key, index, toIndex) { | ||||||
|                     dispatch( |                     dispatch(createMove({ id: getId(id, ownProps), key, index, toIndex })); | ||||||
|                         createMove({ |  | ||||||
|                             id: getId(id, ownProps), |  | ||||||
|                             key, |  | ||||||
|                             index, |  | ||||||
|                             toIndex, |  | ||||||
|                         }) |  | ||||||
|                     ); |  | ||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|                 updateInList(key, index, newValue, merge = false) { |                 updateInList(key, index, newValue, merge = false) { | ||||||
|                     dispatch( |                     dispatch(createUp({ id: getId(id, ownProps), key, index, newValue, merge })); | ||||||
|                         createUp({ |  | ||||||
|                             id: getId(id, ownProps), |  | ||||||
|                             key, |  | ||||||
|                             index, |  | ||||||
|                             newValue, |  | ||||||
|                             merge, |  | ||||||
|                         }) |  | ||||||
|                     ); |  | ||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|                 incValue(key) { |                 incValue(key) { | ||||||
|  | |||||||
| @ -13,19 +13,12 @@ const prepare = (methods, dispatch) => { | |||||||
|         // clean
 |         // clean
 | ||||||
|         const parameters = (input.parameters || []) |         const parameters = (input.parameters || []) | ||||||
|             .filter(name => !!name) |             .filter(name => !!name) | ||||||
|             .map( |             .map(({ name, type = 'string', description = '', required = false }) => ({ | ||||||
|                 ({ |                 name, | ||||||
|                     name, |                 type, | ||||||
|                     type = 'string', |                 description, | ||||||
|                     description = '', |                 required, | ||||||
|                     required = false, |             })); | ||||||
|                 }) => ({ |  | ||||||
|                     name, |  | ||||||
|                     type, |  | ||||||
|                     description, |  | ||||||
|                     required, |  | ||||||
|                 }) |  | ||||||
|             ); |  | ||||||
| 
 | 
 | ||||||
|         createStrategy({ |         createStrategy({ | ||||||
|             name: input.name, |             name: input.name, | ||||||
|  | |||||||
| @ -1,15 +1,7 @@ | |||||||
| import React, { Component } from 'react'; | import React, { Component } from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||
| import { | import { Textfield, IconButton, Menu, MenuItem, Checkbox, Grid, Cell } from 'react-mdl'; | ||||||
|     Textfield, |  | ||||||
|     IconButton, |  | ||||||
|     Menu, |  | ||||||
|     MenuItem, |  | ||||||
|     Checkbox, |  | ||||||
|     Grid, |  | ||||||
|     Cell, |  | ||||||
| } from 'react-mdl'; |  | ||||||
| import { FormButtons } from '../common'; | import { FormButtons } from '../common'; | ||||||
| 
 | 
 | ||||||
| const trim = value => { | const trim = value => { | ||||||
| @ -25,13 +17,7 @@ function gerArrayWithEntries(num) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const Parameter = ({ set, input = {}, index }) => ( | const Parameter = ({ set, input = {}, index }) => ( | ||||||
|     <div |     <div style={{ background: '#f1f1f1', padding: '16px 20px', marginBottom: '20px' }}> | ||||||
|         style={{ |  | ||||||
|             background: '#f1f1f1', |  | ||||||
|             padding: '16px 20px', |  | ||||||
|             marginBottom: '20px', |  | ||||||
|         }} |  | ||||||
|     > |  | ||||||
|         <Textfield |         <Textfield | ||||||
|             style={{ width: '50%' }} |             style={{ width: '50%' }} | ||||||
|             floatingLabel |             floatingLabel | ||||||
| @ -46,8 +32,7 @@ const Parameter = ({ set, input = {}, index }) => ( | |||||||
|                 style={{ |                 style={{ | ||||||
|                     borderRadius: '2px', |                     borderRadius: '2px', | ||||||
|                     cursor: 'pointer', |                     cursor: 'pointer', | ||||||
|                     boxShadow: |                     boxShadow: '0 2px 2px 0 rgba(0,0,0,.04),0 3px 1px -2px rgba(0,0,0,.1),0 1px 5px 0 rgba(0,0,0,.12)', | ||||||
|                         '0 2px 2px 0 rgba(0,0,0,.04),0 3px 1px -2px rgba(0,0,0,.1),0 1px 5px 0 rgba(0,0,0,.12)', |  | ||||||
|                     marginLeft: '10px', |                     marginLeft: '10px', | ||||||
|                     border: '1px solid #f1f1f1', |                     border: '1px solid #f1f1f1', | ||||||
|                     backgroundColor: 'white', |                     backgroundColor: 'white', | ||||||
| @ -55,22 +40,13 @@ const Parameter = ({ set, input = {}, index }) => ( | |||||||
|                 }} |                 }} | ||||||
|             > |             > | ||||||
|                 {input.type || 'string'} |                 {input.type || 'string'} | ||||||
|                 <IconButton |                 <IconButton name="arrow_drop_down" onClick={evt => evt.preventDefault()} /> | ||||||
|                     name="arrow_drop_down" |  | ||||||
|                     onClick={evt => evt.preventDefault()} |  | ||||||
|                 /> |  | ||||||
|             </span> |             </span> | ||||||
|             <Menu target={`${index}-type-menu`} align="right"> |             <Menu target={`${index}-type-menu`} align="right"> | ||||||
|                 <MenuItem onClick={() => set({ type: 'string' })}> |                 <MenuItem onClick={() => set({ type: 'string' })}>string</MenuItem> | ||||||
|                     string |                 <MenuItem onClick={() => set({ type: 'percentage' })}>percentage</MenuItem> | ||||||
|                 </MenuItem> |  | ||||||
|                 <MenuItem onClick={() => set({ type: 'percentage' })}> |  | ||||||
|                     percentage |  | ||||||
|                 </MenuItem> |  | ||||||
|                 <MenuItem onClick={() => set({ type: 'list' })}>list</MenuItem> |                 <MenuItem onClick={() => set({ type: 'list' })}>list</MenuItem> | ||||||
|                 <MenuItem onClick={() => set({ type: 'number' })}> |                 <MenuItem onClick={() => set({ type: 'number' })}>number</MenuItem> | ||||||
|                     number |  | ||||||
|                 </MenuItem> |  | ||||||
|             </Menu> |             </Menu> | ||||||
|         </div> |         </div> | ||||||
|         <Textfield |         <Textfield | ||||||
| @ -95,8 +71,7 @@ const EditHeader = () => ( | |||||||
|     <div> |     <div> | ||||||
|         <h4 style={{ marginTop: '16px' }}>Edit strategy</h4> |         <h4 style={{ marginTop: '16px' }}>Edit strategy</h4> | ||||||
|         <p style={{ background: '#ffb7b7', padding: '16px 20px' }}> |         <p style={{ background: '#ffb7b7', padding: '16px 20px' }}> | ||||||
|             Be carefull! Changing a strategy definition might also require |             Be carefull! Changing a strategy definition might also require changes to the implementation in the clients. | ||||||
|             changes to the implementation in the clients. |  | ||||||
|         </p> |         </p> | ||||||
|     </div> |     </div> | ||||||
| ); | ); | ||||||
| @ -110,12 +85,7 @@ const CreateHeader = () => ( | |||||||
| const Parameters = ({ input = [], count = 0, updateInList }) => ( | const Parameters = ({ input = [], count = 0, updateInList }) => ( | ||||||
|     <div> |     <div> | ||||||
|         {gerArrayWithEntries(count).map((v, i) => ( |         {gerArrayWithEntries(count).map((v, i) => ( | ||||||
|             <Parameter |             <Parameter key={i} set={v => updateInList('parameters', i, v, true)} index={i} input={input[i]} /> | ||||||
|                 key={i} |  | ||||||
|                 set={v => updateInList('parameters', i, v, true)} |  | ||||||
|                 index={i} |  | ||||||
|                 input={input[i]} |  | ||||||
|             /> |  | ||||||
|         ))} |         ))} | ||||||
|     </div> |     </div> | ||||||
| ); | ); | ||||||
| @ -139,24 +109,13 @@ class AddStrategy extends Component { | |||||||
|         if (this.props.initCallRequired === true) { |         if (this.props.initCallRequired === true) { | ||||||
|             this.props.init(this.props.input); |             this.props.init(this.props.input); | ||||||
|             if (this.props.input.parameters) { |             if (this.props.input.parameters) { | ||||||
|                 this.props.setValue( |                 this.props.setValue('_params', this.props.input.parameters.length); | ||||||
|                     '_params', |  | ||||||
|                     this.props.input.parameters.length |  | ||||||
|                 ); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         const { |         const { input, setValue, updateInList, incValue, onCancel, editmode = false, onSubmit } = this.props; | ||||||
|             input, |  | ||||||
|             setValue, |  | ||||||
|             updateInList, |  | ||||||
|             incValue, |  | ||||||
|             onCancel, |  | ||||||
|             editmode = false, |  | ||||||
|             onSubmit, |  | ||||||
|         } = this.props; |  | ||||||
| 
 | 
 | ||||||
|         return ( |         return ( | ||||||
|             <Grid className="mdl-color--white"> |             <Grid className="mdl-color--white"> | ||||||
| @ -170,8 +129,7 @@ class AddStrategy extends Component { | |||||||
|                             required |                             required | ||||||
|                             disabled={editmode} |                             disabled={editmode} | ||||||
|                             pattern="^[0-9a-zA-Z\.\-]+$" |                             pattern="^[0-9a-zA-Z\.\-]+$" | ||||||
|                             onChange={({ target }) => |                             onChange={({ target }) => setValue('name', trim(target.value))} | ||||||
|                                 setValue('name', trim(target.value))} |  | ||||||
|                             value={input.name} |                             value={input.name} | ||||||
|                         /> |                         /> | ||||||
|                         <br /> |                         <br /> | ||||||
| @ -181,15 +139,10 @@ class AddStrategy extends Component { | |||||||
|                             rows={1} |                             rows={1} | ||||||
|                             label="Description" |                             label="Description" | ||||||
|                             name="description" |                             name="description" | ||||||
|                             onChange={({ target }) => |                             onChange={({ target }) => setValue('description', target.value)} | ||||||
|                                 setValue('description', target.value)} |  | ||||||
|                             value={input.description} |                             value={input.description} | ||||||
|                         /> |                         /> | ||||||
|                         <Parameters |                         <Parameters input={input.parameters} count={input._params} updateInList={updateInList} /> | ||||||
|                             input={input.parameters} |  | ||||||
|                             count={input._params} |  | ||||||
|                             updateInList={updateInList} |  | ||||||
|                         /> |  | ||||||
|                         <IconButton |                         <IconButton | ||||||
|                             raised |                             raised | ||||||
|                             name="add" |                             name="add" | ||||||
| @ -202,10 +155,7 @@ class AddStrategy extends Component { | |||||||
|                          Add parameter |                          Add parameter | ||||||
|                         <br /> |                         <br /> | ||||||
|                         <hr /> |                         <hr /> | ||||||
|                         <FormButtons |                         <FormButtons submitText={editmode ? 'Update' : 'Create'} onCancel={onCancel} /> | ||||||
|                             submitText={editmode ? 'Update' : 'Create'} |  | ||||||
|                             onCancel={onCancel} |  | ||||||
|                         /> |  | ||||||
|                     </form> |                     </form> | ||||||
|                 </Cell> |                 </Cell> | ||||||
|             </Grid> |             </Grid> | ||||||
|  | |||||||
| @ -28,19 +28,12 @@ const prepare = (methods, dispatch) => { | |||||||
|         // clean
 |         // clean
 | ||||||
|         const parameters = (input.parameters || []) |         const parameters = (input.parameters || []) | ||||||
|             .filter(name => !!name) |             .filter(name => !!name) | ||||||
|             .map( |             .map(({ name, type = 'string', description = '', required = false }) => ({ | ||||||
|                 ({ |                 name, | ||||||
|                     name, |                 type, | ||||||
|                     type = 'string', |                 description, | ||||||
|                     description = '', |                 required, | ||||||
|                     required = false, |             })); | ||||||
|                 }) => ({ |  | ||||||
|                     name, |  | ||||||
|                     type, |  | ||||||
|                     description, |  | ||||||
|                     required, |  | ||||||
|                 }) |  | ||||||
|             ); |  | ||||||
| 
 | 
 | ||||||
|         updateStrategy({ |         updateStrategy({ | ||||||
|             name: input.name, |             name: input.name, | ||||||
|  | |||||||
| @ -2,14 +2,7 @@ import React, { Component } from 'react'; | |||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import { Link } from 'react-router'; | import { Link } from 'react-router'; | ||||||
| 
 | 
 | ||||||
| import { | import { List, ListItem, ListItemContent, IconButton, Grid, Cell } from 'react-mdl'; | ||||||
|     List, |  | ||||||
|     ListItem, |  | ||||||
|     ListItemContent, |  | ||||||
|     IconButton, |  | ||||||
|     Grid, |  | ||||||
|     Cell, |  | ||||||
| } from 'react-mdl'; |  | ||||||
| import { HeaderTitle } from '../common'; | import { HeaderTitle } from '../common'; | ||||||
| 
 | 
 | ||||||
| class StrategiesListComponent extends Component { | class StrategiesListComponent extends Component { | ||||||
| @ -33,10 +26,7 @@ class StrategiesListComponent extends Component { | |||||||
|                             <IconButton |                             <IconButton | ||||||
|                                 raised |                                 raised | ||||||
|                                 name="add" |                                 name="add" | ||||||
|                                 onClick={() => |                                 onClick={() => this.context.router.push('/strategies/create')} | ||||||
|                                     this.context.router.push( |  | ||||||
|                                         '/strategies/create' |  | ||||||
|                                     )} |  | ||||||
|                                 title="Add new strategy" |                                 title="Add new strategy" | ||||||
|                             /> |                             /> | ||||||
|                         } |                         } | ||||||
| @ -45,24 +35,15 @@ class StrategiesListComponent extends Component { | |||||||
|                         {strategies.length > 0 ? ( |                         {strategies.length > 0 ? ( | ||||||
|                             strategies.map((strategy, i) => ( |                             strategies.map((strategy, i) => ( | ||||||
|                                 <ListItem key={i} twoLine> |                                 <ListItem key={i} twoLine> | ||||||
|                                     <ListItemContent |                                     <ListItemContent icon="extension" subtitle={strategy.description}> | ||||||
|                                         icon="extension" |                                         <Link to={`/strategies/view/${strategy.name}`}> | ||||||
|                                         subtitle={strategy.description} |  | ||||||
|                                     > |  | ||||||
|                                         <Link |  | ||||||
|                                             to={`/strategies/view/${strategy.name}`} |  | ||||||
|                                         > |  | ||||||
|                                             <strong>{strategy.name}</strong> |                                             <strong>{strategy.name}</strong> | ||||||
|                                         </Link> |                                         </Link> | ||||||
|                                     </ListItemContent> |                                     </ListItemContent> | ||||||
|                                     {strategy.editable === false ? ( |                                     {strategy.editable === false ? ( | ||||||
|                                         '' |                                         '' | ||||||
|                                     ) : ( |                                     ) : ( | ||||||
|                                         <IconButton |                                         <IconButton name="delete" onClick={() => removeStrategy(strategy)} /> | ||||||
|                                             name="delete" |  | ||||||
|                                             onClick={() => |  | ||||||
|                                                 removeStrategy(strategy)} |  | ||||||
|                                         /> |  | ||||||
|                                     )} |                                     )} | ||||||
|                                 </ListItem> |                                 </ListItem> | ||||||
|                             )) |                             )) | ||||||
|  | |||||||
| @ -20,8 +20,6 @@ const mapDispatchToProps = dispatch => ({ | |||||||
|     fetchStrategies: () => fetchStrategies()(dispatch), |     fetchStrategies: () => fetchStrategies()(dispatch), | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const StrategiesListContainer = connect(mapStateToProps, mapDispatchToProps)( | const StrategiesListContainer = connect(mapStateToProps, mapDispatchToProps)(StrategiesListComponent); | ||||||
|     StrategiesListComponent |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| export default StrategiesListContainer; | export default StrategiesListContainer; | ||||||
|  | |||||||
| @ -13,15 +13,8 @@ class ShowStrategyComponent extends PureComponent { | |||||||
|     renderParameters(params) { |     renderParameters(params) { | ||||||
|         if (params) { |         if (params) { | ||||||
|             return params.map(({ name, type, description, required }, i) => ( |             return params.map(({ name, type, description, required }, i) => ( | ||||||
|                 <ListItem |                 <ListItem twoLine key={`${name}-${i}`} title={required ? 'Required' : ''}> | ||||||
|                     twoLine |                     <ListItemContent avatar={required ? 'add' : ' '} subtitle={description}> | ||||||
|                     key={`${name}-${i}`} |  | ||||||
|                     title={required ? 'Required' : ''} |  | ||||||
|                 > |  | ||||||
|                     <ListItemContent |  | ||||||
|                         avatar={required ? 'add' : ' '} |  | ||||||
|                         subtitle={description} |  | ||||||
|                     > |  | ||||||
|                         {name} <small>({type})</small> |                         {name} <small>({type})</small> | ||||||
|                     </ListItemContent> |                     </ListItemContent> | ||||||
|                 </ListItem> |                 </ListItem> | ||||||
|  | |||||||
| @ -54,9 +54,7 @@ export default class StrategyDetails extends Component { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         const activeTabId = TABS[this.props.activeTab] |         const activeTabId = TABS[this.props.activeTab] ? TABS[this.props.activeTab] : TABS.view; | ||||||
|             ? TABS[this.props.activeTab] |  | ||||||
|             : TABS.view; |  | ||||||
|         const strategy = this.props.strategy; |         const strategy = this.props.strategy; | ||||||
|         if (!strategy) { |         if (!strategy) { | ||||||
|             return <ProgressBar indeterminate />; |             return <ProgressBar indeterminate />; | ||||||
| @ -67,17 +65,12 @@ export default class StrategyDetails extends Component { | |||||||
|         return ( |         return ( | ||||||
|             <Grid className="mdl-color--white"> |             <Grid className="mdl-color--white"> | ||||||
|                 <Cell col={12}> |                 <Cell col={12}> | ||||||
|                     <HeaderTitle |                     <HeaderTitle title={strategy.name} subtitle={strategy.description} /> | ||||||
|                         title={strategy.name} |  | ||||||
|                         subtitle={strategy.description} |  | ||||||
|                     /> |  | ||||||
|                     {strategy.editable === false ? ( |                     {strategy.editable === false ? ( | ||||||
|                         '' |                         '' | ||||||
|                     ) : ( |                     ) : ( | ||||||
|                         <Tabs activeTab={activeTabId} ripple> |                         <Tabs activeTab={activeTabId} ripple> | ||||||
|                             <Tab onClick={() => this.goToTab('view')}> |                             <Tab onClick={() => this.goToTab('view')}>Details</Tab> | ||||||
|                                 Details |  | ||||||
|                             </Tab> |  | ||||||
|                             <Tab onClick={() => this.goToTab('edit')}>Edit</Tab> |                             <Tab onClick={() => this.goToTab('edit')}>Edit</Tab> | ||||||
|                         </Tabs> |                         </Tabs> | ||||||
|                     )} |                     )} | ||||||
|  | |||||||
| @ -5,17 +5,10 @@ import { fetchAll } from '../../store/application/actions'; | |||||||
| import { fetchFeatureToggles } from '../../store/feature-actions'; | import { fetchFeatureToggles } from '../../store/feature-actions'; | ||||||
| 
 | 
 | ||||||
| const mapStateToProps = (state, props) => { | const mapStateToProps = (state, props) => { | ||||||
|     let strategy = state.strategies |     let strategy = state.strategies.get('list').find(n => n.name === props.strategyName); | ||||||
|         .get('list') |     const applications = state.applications.get('list').filter(app => app.strategies.includes(props.strategyName)); | ||||||
|         .find(n => n.name === props.strategyName); |  | ||||||
|     const applications = state.applications |  | ||||||
|         .get('list') |  | ||||||
|         .filter(app => app.strategies.includes(props.strategyName)); |  | ||||||
|     const toggles = state.features.filter( |     const toggles = state.features.filter( | ||||||
|         toggle => |         toggle => toggle.get('strategies').findIndex(s => s.name === props.strategyName) > -1 | ||||||
|             toggle |  | ||||||
|                 .get('strategies') |  | ||||||
|                 .findIndex(s => s.name === props.strategyName) > -1 |  | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     return { |     return { | ||||||
|  | |||||||
| @ -15,11 +15,7 @@ export default class ShowUserComponent extends React.Component { | |||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         return ( |         return ( | ||||||
|             <a |             <a className="mdl-navigation__link" href="#edit-user" onClick={this.openEdit}> | ||||||
|                 className="mdl-navigation__link" |  | ||||||
|                 href="#edit-user" |  | ||||||
|                 onClick={this.openEdit} |  | ||||||
|             > |  | ||||||
|                 <Tooltip label={this.props.user.userName || 'Unknown'} large> |                 <Tooltip label={this.props.user.userName || 'Unknown'} large> | ||||||
|                     <Icon name="account_circle" /> |                     <Icon name="account_circle" /> | ||||||
|                 </Tooltip> |                 </Tooltip> | ||||||
|  | |||||||
| @ -39,25 +39,17 @@ class EditUserComponent extends React.Component { | |||||||
|     render() { |     render() { | ||||||
|         return ( |         return ( | ||||||
|             <div> |             <div> | ||||||
|                 <Modal |                 <Modal isOpen={this.props.user.showDialog} contentLabel="test" style={customStyles}> | ||||||
|                     isOpen={this.props.user.showDialog} |  | ||||||
|                     contentLabel="test" |  | ||||||
|                     style={customStyles} |  | ||||||
|                 > |  | ||||||
|                     <h2>Action required</h2> |                     <h2>Action required</h2> | ||||||
|                     <div> |                     <div> | ||||||
|                         <p> |                         <p>You have to specify a username to use Unleash. This will allow us to track your changes.</p> | ||||||
|                             You have to specify a username to use Unleash. This |  | ||||||
|                             will allow us to track your changes. |  | ||||||
|                         </p> |  | ||||||
|                         <form onSubmit={this.handleSubmit}> |                         <form onSubmit={this.handleSubmit}> | ||||||
|                             <Textfield |                             <Textfield | ||||||
|                                 label="Username" |                                 label="Username" | ||||||
|                                 name="username" |                                 name="username" | ||||||
|                                 required |                                 required | ||||||
|                                 value={this.props.user.userName} |                                 value={this.props.user.userName} | ||||||
|                                 onChange={e => |                                 onChange={e => this.props.updateUserName(e.target.value)} | ||||||
|                                     this.props.updateUserName(e.target.value)} |  | ||||||
|                             /> |                             /> | ||||||
|                             <br /> |                             <br /> | ||||||
|                             <Button raised accent> |                             <Button raised accent> | ||||||
|  | |||||||
| @ -4,10 +4,7 @@ const URI = 'api/admin/features'; | |||||||
| 
 | 
 | ||||||
| function validateToggle(featureToggle) { | function validateToggle(featureToggle) { | ||||||
|     return new Promise((resolve, reject) => { |     return new Promise((resolve, reject) => { | ||||||
|         if ( |         if (!featureToggle.strategies || featureToggle.strategies.length === 0) { | ||||||
|             !featureToggle.strategies || |  | ||||||
|             featureToggle.strategies.length === 0 |  | ||||||
|         ) { |  | ||||||
|             reject(new Error('You must add at least one activation strategy')); |             reject(new Error('You must add at least one activation strategy')); | ||||||
|         } else { |         } else { | ||||||
|             resolve(featureToggle); |             resolve(featureToggle); | ||||||
|  | |||||||
| @ -1,9 +1,7 @@ | |||||||
| const defaultErrorMessage = 'Unexptected exception when talking to unleash-api'; | const defaultErrorMessage = 'Unexptected exception when talking to unleash-api'; | ||||||
| 
 | 
 | ||||||
| function extractJoiMsg(body) { | function extractJoiMsg(body) { | ||||||
|     return body.details.length > 0 |     return body.details.length > 0 ? body.details[0].message : defaultErrorMessage; | ||||||
|         ? body.details[0].message |  | ||||||
|         : defaultErrorMessage; |  | ||||||
| } | } | ||||||
| function extractLegacyMsg(body) { | function extractLegacyMsg(body) { | ||||||
|     return body && body.length > 0 ? body[0].msg : defaultErrorMessage; |     return body && body.length > 0 ? body[0].msg : defaultErrorMessage; | ||||||
| @ -14,10 +12,7 @@ export function throwIfNotSuccess(response) { | |||||||
|         if (response.status > 399 && response.status < 404) { |         if (response.status > 399 && response.status < 404) { | ||||||
|             return new Promise((resolve, reject) => { |             return new Promise((resolve, reject) => { | ||||||
|                 response.json().then(body => { |                 response.json().then(body => { | ||||||
|                     const errorMsg = |                     const errorMsg = body && body.isJoi ? extractJoiMsg(body) : extractLegacyMsg(body); | ||||||
|                         body && body.isJoi |  | ||||||
|                             ? extractJoiMsg(body) |  | ||||||
|                             : extractLegacyMsg(body); |  | ||||||
|                     let error = new Error(errorMsg); |                     let error = new Error(errorMsg); | ||||||
|                     error.statusCode = response.status; |                     error.statusCode = response.status; | ||||||
|                     reject(error); |                     reject(error); | ||||||
|  | |||||||
| @ -4,13 +4,7 @@ import 'react-mdl/extra/material.js'; | |||||||
| 
 | 
 | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import ReactDOM from 'react-dom'; | import ReactDOM from 'react-dom'; | ||||||
| import { | import { applyRouterMiddleware, Router, Route, IndexRedirect, hashHistory } from 'react-router'; | ||||||
|     applyRouterMiddleware, |  | ||||||
|     Router, |  | ||||||
|     Route, |  | ||||||
|     IndexRedirect, |  | ||||||
|     hashHistory, |  | ||||||
| } from 'react-router'; |  | ||||||
| import { useScroll } from 'react-router-scroll'; | import { useScroll } from 'react-router-scroll'; | ||||||
| import { Provider } from 'react-redux'; | import { Provider } from 'react-redux'; | ||||||
| import thunkMiddleware from 'redux-thunk'; | import thunkMiddleware from 'redux-thunk'; | ||||||
| @ -33,60 +27,31 @@ import ApplicationView from './page/applications/view'; | |||||||
| 
 | 
 | ||||||
| let composeEnhancers; | let composeEnhancers; | ||||||
| 
 | 
 | ||||||
| if ( | if (process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) { | ||||||
|     process.env.NODE_ENV !== 'production' && |  | ||||||
|     window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ |  | ||||||
| ) { |  | ||||||
|     composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__; |     composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__; | ||||||
| } else { | } else { | ||||||
|     composeEnhancers = compose; |     composeEnhancers = compose; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const unleashStore = createStore( | const unleashStore = createStore(store, composeEnhancers(applyMiddleware(thunkMiddleware))); | ||||||
|     store, |  | ||||||
|     composeEnhancers(applyMiddleware(thunkMiddleware)) |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| // "pageTitle" and "link" attributes are for internal usage only | // "pageTitle" and "link" attributes are for internal usage only | ||||||
| 
 | 
 | ||||||
| ReactDOM.render( | ReactDOM.render( | ||||||
|     <Provider store={unleashStore}> |     <Provider store={unleashStore}> | ||||||
|         <Router |         <Router history={hashHistory} render={applyRouterMiddleware(useScroll())}> | ||||||
|             history={hashHistory} |  | ||||||
|             render={applyRouterMiddleware(useScroll())} |  | ||||||
|         > |  | ||||||
|             <Route path="/" component={App}> |             <Route path="/" component={App}> | ||||||
|                 <IndexRedirect to="/features" /> |                 <IndexRedirect to="/features" /> | ||||||
| 
 | 
 | ||||||
|                 <Route pageTitle="Feature Toggles" link="/features"> |                 <Route pageTitle="Feature Toggles" link="/features"> | ||||||
|                     <Route |                     <Route pageTitle="Feature toggles" path="/features" component={Features} /> | ||||||
|                         pageTitle="Feature toggles" |                     <Route pageTitle="New" path="/features/create" component={CreateFeatureToggle} /> | ||||||
|                         path="/features" |                     <Route pageTitle=":name" path="/features/:activeTab/:name" component={ViewFeatureToggle} /> | ||||||
|                         component={Features} |  | ||||||
|                     /> |  | ||||||
|                     <Route |  | ||||||
|                         pageTitle="New" |  | ||||||
|                         path="/features/create" |  | ||||||
|                         component={CreateFeatureToggle} |  | ||||||
|                     /> |  | ||||||
|                     <Route |  | ||||||
|                         pageTitle=":name" |  | ||||||
|                         path="/features/:activeTab/:name" |  | ||||||
|                         component={ViewFeatureToggle} |  | ||||||
|                     /> |  | ||||||
|                 </Route> |                 </Route> | ||||||
| 
 | 
 | ||||||
|                 <Route pageTitle="Strategies" link="/strategies"> |                 <Route pageTitle="Strategies" link="/strategies"> | ||||||
|                     <Route |                     <Route pageTitle="Strategies" path="/strategies" component={Strategies} /> | ||||||
|                         pageTitle="Strategies" |                     <Route pageTitle="New" path="/strategies/create" component={CreateStrategies} /> | ||||||
|                         path="/strategies" |  | ||||||
|                         component={Strategies} |  | ||||||
|                     /> |  | ||||||
|                     <Route |  | ||||||
|                         pageTitle="New" |  | ||||||
|                         path="/strategies/create" |  | ||||||
|                         component={CreateStrategies} |  | ||||||
|                     /> |  | ||||||
|                     <Route |                     <Route | ||||||
|                         pageTitle=":strategyName" |                         pageTitle=":strategyName" | ||||||
|                         path="/strategies/:activeTab/:strategyName" |                         path="/strategies/:activeTab/:strategyName" | ||||||
| @ -95,34 +60,14 @@ ReactDOM.render( | |||||||
|                 </Route> |                 </Route> | ||||||
| 
 | 
 | ||||||
|                 <Route pageTitle="Event History" link="/history"> |                 <Route pageTitle="Event History" link="/history"> | ||||||
|                     <Route |                     <Route pageTitle="Event history" path="/history" component={HistoryPage} /> | ||||||
|                         pageTitle="Event history" |                     <Route pageTitle=":toggleName" path="/history/:toggleName" component={HistoryTogglePage} /> | ||||||
|                         path="/history" |  | ||||||
|                         component={HistoryPage} |  | ||||||
|                     /> |  | ||||||
|                     <Route |  | ||||||
|                         pageTitle=":toggleName" |  | ||||||
|                         path="/history/:toggleName" |  | ||||||
|                         component={HistoryTogglePage} |  | ||||||
|                     /> |  | ||||||
|                 </Route> |                 </Route> | ||||||
| 
 | 
 | ||||||
|                 <Route |                 <Route pageTitle="Archived Toggles" path="/archive" component={Archive} /> | ||||||
|                     pageTitle="Archived Toggles" |  | ||||||
|                     path="/archive" |  | ||||||
|                     component={Archive} |  | ||||||
|                 /> |  | ||||||
|                 <Route pageTitle="Applications" link="/applications"> |                 <Route pageTitle="Applications" link="/applications"> | ||||||
|                     <Route |                     <Route pageTitle="Applications" path="/applications" component={Applications} /> | ||||||
|                         pageTitle="Applications" |                     <Route pageTitle=":name" path="/applications/:name" component={ApplicationView} /> | ||||||
|                         path="/applications" |  | ||||||
|                         component={Applications} |  | ||||||
|                     /> |  | ||||||
|                     <Route |  | ||||||
|                         pageTitle=":name" |  | ||||||
|                         path="/applications/:name" |  | ||||||
|                         component={ApplicationView} |  | ||||||
|                     /> |  | ||||||
|                 </Route> |                 </Route> | ||||||
|             </Route> |             </Route> | ||||||
|         </Router> |         </Router> | ||||||
|  | |||||||
| @ -2,9 +2,7 @@ import React from 'react'; | |||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import ApplicationEditComponent from '../../component/application/application-edit-container'; | import ApplicationEditComponent from '../../component/application/application-edit-container'; | ||||||
| 
 | 
 | ||||||
| const render = ({ params }) => ( | const render = ({ params }) => <ApplicationEditComponent appName={params.name} />; | ||||||
|     <ApplicationEditComponent appName={params.name} /> |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| render.propTypes = { | render.propTypes = { | ||||||
|     params: PropTypes.object.isRequired, |     params: PropTypes.object.isRequired, | ||||||
|  | |||||||
| @ -9,11 +9,6 @@ export default class Features extends PureComponent { | |||||||
| 
 | 
 | ||||||
|     render() { |     render() { | ||||||
|         const { params } = this.props; |         const { params } = this.props; | ||||||
|         return ( |         return <ViewFeatureToggle featureToggleName={params.name} activeTab={params.activeTab} />; | ||||||
|             <ViewFeatureToggle |  | ||||||
|                 featureToggleName={params.name} |  | ||||||
|                 activeTab={params.activeTab} |  | ||||||
|             /> |  | ||||||
|         ); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,9 +2,7 @@ import React from 'react'; | |||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import HistoryListToggle from '../../component/history/history-list-toggle-container'; | import HistoryListToggle from '../../component/history/history-list-toggle-container'; | ||||||
| 
 | 
 | ||||||
| const render = ({ params }) => ( | const render = ({ params }) => <HistoryListToggle toggleName={params.toggleName} />; | ||||||
|     <HistoryListToggle toggleName={params.toggleName} /> |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| render.propTypes = { | render.propTypes = { | ||||||
|     params: PropTypes.object.isRequired, |     params: PropTypes.object.isRequired, | ||||||
|  | |||||||
| @ -2,12 +2,7 @@ import React from 'react'; | |||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import ShowStrategy from '../../component/strategies/strategy-details-container'; | import ShowStrategy from '../../component/strategies/strategy-details-container'; | ||||||
| 
 | 
 | ||||||
| const render = ({ params }) => ( | const render = ({ params }) => <ShowStrategy strategyName={params.strategyName} activeTab={params.activeTab} />; | ||||||
|     <ShowStrategy |  | ||||||
|         strategyName={params.strategyName} |  | ||||||
|         activeTab={params.activeTab} |  | ||||||
|     /> |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| render.propTypes = { | render.propTypes = { | ||||||
|     params: PropTypes.object.isRequired, |     params: PropTypes.object.isRequired, | ||||||
|  | |||||||
| @ -2,8 +2,7 @@ import api from '../../data/applications-api'; | |||||||
| 
 | 
 | ||||||
| export const RECEIVE_ALL_APPLICATIONS = 'RECEIVE_ALL_APPLICATIONS'; | export const RECEIVE_ALL_APPLICATIONS = 'RECEIVE_ALL_APPLICATIONS'; | ||||||
| export const ERROR_RECEIVE_ALL_APPLICATIONS = 'ERROR_RECEIVE_ALL_APPLICATIONS'; | export const ERROR_RECEIVE_ALL_APPLICATIONS = 'ERROR_RECEIVE_ALL_APPLICATIONS'; | ||||||
| export const ERROR_UPDATING_APPLICATION_DATA = | export const ERROR_UPDATING_APPLICATION_DATA = 'ERROR_UPDATING_APPLICATION_DATA'; | ||||||
|     'ERROR_UPDATING_APPLICATION_DATA'; |  | ||||||
| 
 | 
 | ||||||
| export const RECEIVE_APPLICATION = 'RECEIVE_APPLICATION'; | export const RECEIVE_APPLICATION = 'RECEIVE_APPLICATION'; | ||||||
| 
 | 
 | ||||||
| @ -17,10 +16,7 @@ const recieveApplication = json => ({ | |||||||
|     value: json, |     value: json, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const errorReceiveApplications = ( | const errorReceiveApplications = (statusCode, type = ERROR_RECEIVE_ALL_APPLICATIONS) => ({ | ||||||
|     statusCode, |  | ||||||
|     type = ERROR_RECEIVE_ALL_APPLICATIONS |  | ||||||
| ) => ({ |  | ||||||
|     type, |     type, | ||||||
|     statusCode, |     statusCode, | ||||||
| }); | }); | ||||||
| @ -37,14 +33,7 @@ export function storeApplicationMetaData(appName, key, value) { | |||||||
|     return dispatch => |     return dispatch => | ||||||
|         api |         api | ||||||
|             .storeApplicationMetaData(appName, key, value) |             .storeApplicationMetaData(appName, key, value) | ||||||
|             .catch(error => |             .catch(error => dispatch(errorReceiveApplications(error, ERROR_UPDATING_APPLICATION_DATA))); | ||||||
|                 dispatch( |  | ||||||
|                     errorReceiveApplications( |  | ||||||
|                         error, |  | ||||||
|                         ERROR_UPDATING_APPLICATION_DATA |  | ||||||
|                     ) |  | ||||||
|                 ) |  | ||||||
|             ); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function fetchApplication(appName) { | export function fetchApplication(appName) { | ||||||
|  | |||||||
| @ -8,10 +8,7 @@ function getInitState() { | |||||||
| const store = (state = getInitState(), action) => { | const store = (state = getInitState(), action) => { | ||||||
|     switch (action.type) { |     switch (action.type) { | ||||||
|         case RECEIVE_APPLICATION: |         case RECEIVE_APPLICATION: | ||||||
|             return state.setIn( |             return state.setIn(['apps', action.value.appName], new Map(action.value)); | ||||||
|                 ['apps', action.value.appName], |  | ||||||
|                 new Map(action.value) |  | ||||||
|             ); |  | ||||||
|         case RECEIVE_ALL_APPLICATIONS: |         case RECEIVE_ALL_APPLICATIONS: | ||||||
|             return state.set('list', new List(action.value.applications)); |             return state.set('list', new List(action.value.applications)); | ||||||
|         default: |         default: | ||||||
|  | |||||||
| @ -8,9 +8,7 @@ function getInitState() { | |||||||
| const archiveStore = (state = getInitState(), action) => { | const archiveStore = (state = getInitState(), action) => { | ||||||
|     switch (action.type) { |     switch (action.type) { | ||||||
|         case REVIVE_TOGGLE: |         case REVIVE_TOGGLE: | ||||||
|             return state.update('list', list => |             return state.update('list', list => list.filter(item => item.name !== action.value)); | ||||||
|                 list.filter(item => item.name !== action.value) |  | ||||||
|             ); |  | ||||||
|         case RECEIVE_ARCHIVE: |         case RECEIVE_ARCHIVE: | ||||||
|             return state.set('list', new List(action.value)); |             return state.set('list', new List(action.value)); | ||||||
|         default: |         default: | ||||||
|  | |||||||
| @ -7,11 +7,7 @@ import { | |||||||
|     ERROR_UPDATE_FEATURE_TOGGLE, |     ERROR_UPDATE_FEATURE_TOGGLE, | ||||||
| } from './feature-actions'; | } from './feature-actions'; | ||||||
| 
 | 
 | ||||||
| import { | import { ERROR_UPDATING_STRATEGY, ERROR_CREATING_STRATEGY, ERROR_RECEIVE_STRATEGIES } from './strategy/actions'; | ||||||
|     ERROR_UPDATING_STRATEGY, |  | ||||||
|     ERROR_CREATING_STRATEGY, |  | ||||||
|     ERROR_RECEIVE_STRATEGIES, |  | ||||||
| } from './strategy/actions'; |  | ||||||
| 
 | 
 | ||||||
| const debug = require('debug')('unleash:error-store'); | const debug = require('debug')('unleash:error-store'); | ||||||
| 
 | 
 | ||||||
| @ -40,9 +36,7 @@ const strategies = (state = getInitState(), action) => { | |||||||
|         case ERROR_RECEIVE_STRATEGIES: |         case ERROR_RECEIVE_STRATEGIES: | ||||||
|             return addErrorIfNotAlreadyInList(state, action.error.message); |             return addErrorIfNotAlreadyInList(state, action.error.message); | ||||||
|         case MUTE_ERROR: |         case MUTE_ERROR: | ||||||
|             return state.update('list', list => |             return state.update('list', list => list.remove(list.indexOf(action.error))); | ||||||
|                 list.remove(list.indexOf(action.error)) |  | ||||||
|             ); |  | ||||||
|         default: |         default: | ||||||
|             return state; |             return state; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -85,9 +85,7 @@ export function requestUpdateFeatureToggle(featureToggle) { | |||||||
| 
 | 
 | ||||||
|         return api |         return api | ||||||
|             .update(featureToggle) |             .update(featureToggle) | ||||||
|             .then(() => |             .then(() => dispatch({ type: UPDATE_FEATURE_TOGGLE, featureToggle })) | ||||||
|                 dispatch({ type: UPDATE_FEATURE_TOGGLE, featureToggle }) |  | ||||||
|             ) |  | ||||||
|             .catch(dispatchAndThrow(dispatch, ERROR_UPDATE_FEATURE_TOGGLE)); |             .catch(dispatchAndThrow(dispatch, ERROR_UPDATE_FEATURE_TOGGLE)); | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @ -98,9 +96,7 @@ export function removeFeatureToggle(featureToggleName) { | |||||||
| 
 | 
 | ||||||
|         return api |         return api | ||||||
|             .remove(featureToggleName) |             .remove(featureToggleName) | ||||||
|             .then(() => |             .then(() => dispatch({ type: REMOVE_FEATURE_TOGGLE, featureToggleName })) | ||||||
|                 dispatch({ type: REMOVE_FEATURE_TOGGLE, featureToggleName }) |  | ||||||
|             ) |  | ||||||
|             .catch(dispatchAndThrow(dispatch, ERROR_REMOVE_FEATURE_TOGGLE)); |             .catch(dispatchAndThrow(dispatch, ERROR_REMOVE_FEATURE_TOGGLE)); | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,14 +1,8 @@ | |||||||
| import { Map as $Map, fromJS } from 'immutable'; | import { Map as $Map, fromJS } from 'immutable'; | ||||||
| 
 | 
 | ||||||
| import { | import { RECEIVE_FEATURE_METRICS, RECEIVE_SEEN_APPS } from './feature-metrics-actions'; | ||||||
|     RECEIVE_FEATURE_METRICS, |  | ||||||
|     RECEIVE_SEEN_APPS, |  | ||||||
| } from './feature-metrics-actions'; |  | ||||||
| 
 | 
 | ||||||
| const metrics = ( | const metrics = (state = fromJS({ lastHour: {}, lastMinute: {}, seenApps: {} }), action) => { | ||||||
|     state = fromJS({ lastHour: {}, lastMinute: {}, seenApps: {} }), |  | ||||||
|     action |  | ||||||
| ) => { |  | ||||||
|     switch (action.type) { |     switch (action.type) { | ||||||
|         case RECEIVE_SEEN_APPS: |         case RECEIVE_SEEN_APPS: | ||||||
|             return state.set('seenApps', new $Map(action.value)); |             return state.set('seenApps', new $Map(action.value)); | ||||||
|  | |||||||
| @ -16,9 +16,7 @@ const features = (state = new List([]), action) => { | |||||||
|             return state.push(new $Map(action.featureToggle)); |             return state.push(new $Map(action.featureToggle)); | ||||||
|         case REMOVE_FEATURE_TOGGLE: |         case REMOVE_FEATURE_TOGGLE: | ||||||
|             debug(REMOVE_FEATURE_TOGGLE, action); |             debug(REMOVE_FEATURE_TOGGLE, action); | ||||||
|             return state.filter( |             return state.filter(toggle => toggle.get('name') !== action.featureToggleName); | ||||||
|                 toggle => toggle.get('name') !== action.featureToggleName |  | ||||||
|             ); |  | ||||||
|         case TOGGLE_FEATURE_TOGGLE: |         case TOGGLE_FEATURE_TOGGLE: | ||||||
|             debug(TOGGLE_FEATURE_TOGGLE, action); |             debug(TOGGLE_FEATURE_TOGGLE, action); | ||||||
|             return state.map(toggle => { |             return state.map(toggle => { | ||||||
|  | |||||||
| @ -8,10 +8,7 @@ function getInitState() { | |||||||
| const historyStore = (state = getInitState(), action) => { | const historyStore = (state = getInitState(), action) => { | ||||||
|     switch (action.type) { |     switch (action.type) { | ||||||
|         case RECEIVE_HISTORY_FOR_TOGGLE: |         case RECEIVE_HISTORY_FOR_TOGGLE: | ||||||
|             return state.setIn( |             return state.setIn(['toggles', action.value.toggleName], new List(action.value.events)); | ||||||
|                 ['toggles', action.value.toggleName], |  | ||||||
|                 new List(action.value.events) |  | ||||||
|             ); |  | ||||||
|         case RECEIVE_HISTORY: |         case RECEIVE_HISTORY: | ||||||
|             return state.set('list', new List(action.value)); |             return state.set('list', new List(action.value)); | ||||||
|         default: |         default: | ||||||
|  | |||||||
| @ -9,41 +9,12 @@ export const actions = { | |||||||
|     MOVE: 'MOVE', |     MOVE: 'MOVE', | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const createInit = ({ id, value }) => ({ | export const createInit = ({ id, value }) => ({ type: actions.INIT, id, value }); | ||||||
|     type: actions.INIT, | export const createInc = ({ id, key }) => ({ type: actions.INCREMENT_VALUE, id, key }); | ||||||
|     id, | export const createSet = ({ id, key, value }) => ({ type: actions.SET_VALUE, id, key, value }); | ||||||
|     value, | export const createPush = ({ id, key, value }) => ({ type: actions.LIST_PUSH, id, key, value }); | ||||||
| }); | export const createPop = ({ id, key, index }) => ({ type: actions.LIST_POP, id, key, index }); | ||||||
| export const createInc = ({ id, key }) => ({ | export const createMove = ({ id, key, index, toIndex }) => ({ type: actions.MOVE, id, key, index, toIndex }); | ||||||
|     type: actions.INCREMENT_VALUE, |  | ||||||
|     id, |  | ||||||
|     key, |  | ||||||
| }); |  | ||||||
| export const createSet = ({ id, key, value }) => ({ |  | ||||||
|     type: actions.SET_VALUE, |  | ||||||
|     id, |  | ||||||
|     key, |  | ||||||
|     value, |  | ||||||
| }); |  | ||||||
| export const createPush = ({ id, key, value }) => ({ |  | ||||||
|     type: actions.LIST_PUSH, |  | ||||||
|     id, |  | ||||||
|     key, |  | ||||||
|     value, |  | ||||||
| }); |  | ||||||
| export const createPop = ({ id, key, index }) => ({ |  | ||||||
|     type: actions.LIST_POP, |  | ||||||
|     id, |  | ||||||
|     key, |  | ||||||
|     index, |  | ||||||
| }); |  | ||||||
| export const createMove = ({ id, key, index, toIndex }) => ({ |  | ||||||
|     type: actions.MOVE, |  | ||||||
|     id, |  | ||||||
|     key, |  | ||||||
|     index, |  | ||||||
|     toIndex, |  | ||||||
| }); |  | ||||||
| export const createUp = ({ id, key, index, newValue, merge }) => ({ | export const createUp = ({ id, key, index, newValue, merge }) => ({ | ||||||
|     type: actions.LIST_UP, |     type: actions.LIST_UP, | ||||||
|     id, |     id, | ||||||
|  | |||||||
| @ -7,5 +7,4 @@ export const updateSetting = (group, field, value) => ({ | |||||||
|     value, |     value, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| export const updateSettingForGroup = group => (field, value) => | export const updateSettingForGroup = group => (field, value) => updateSetting(group, field, value); | ||||||
|     updateSetting(group, field, value); |  | ||||||
|  | |||||||
| @ -15,10 +15,7 @@ function getInitState() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function updateSetting(state, action) { | function updateSetting(state, action) { | ||||||
|     const newState = state.updateIn( |     const newState = state.updateIn([action.group, action.field], () => action.value); | ||||||
|         [action.group, action.field], |  | ||||||
|         () => action.value |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     localStorage.setItem(SETTINGS, JSON.stringify(newState.toJSON())); |     localStorage.setItem(SETTINGS, JSON.stringify(newState.toJSON())); | ||||||
|     return newState; |     return newState; | ||||||
|  | |||||||
| @ -1,10 +1,5 @@ | |||||||
| import { List, Map as $Map } from 'immutable'; | import { List, Map as $Map } from 'immutable'; | ||||||
| import { | import { RECEIVE_STRATEGIES, REMOVE_STRATEGY, ADD_STRATEGY, UPDATE_STRATEGY } from './actions'; | ||||||
|     RECEIVE_STRATEGIES, |  | ||||||
|     REMOVE_STRATEGY, |  | ||||||
|     ADD_STRATEGY, |  | ||||||
|     UPDATE_STRATEGY, |  | ||||||
| } from './actions'; |  | ||||||
| 
 | 
 | ||||||
| function getInitState() { | function getInitState() { | ||||||
|     return new $Map({ list: new List() }); |     return new $Map({ list: new List() }); | ||||||
|  | |||||||
| @ -20,9 +20,7 @@ function readCookie() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function writeCookie(userName) { | function writeCookie(userName) { | ||||||
|     document.cookie = `${COOKIE_NAME}=${encodeURIComponent( |     document.cookie = `${COOKIE_NAME}=${encodeURIComponent(userName)}; expires=Thu, 18 Dec 2099 12:00:00 UTC`; | ||||||
|         userName |  | ||||||
|     )}; expires=Thu, 18 Dec 2099 12:00:00 UTC`;
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getInitState() { | function getInitState() { | ||||||
|  | |||||||
| @ -54,17 +54,14 @@ module.exports = { | |||||||
|                                 sourceMap: true, |                                 sourceMap: true, | ||||||
|                                 modules: true, |                                 modules: true, | ||||||
|                                 importLoaders: 1, |                                 importLoaders: 1, | ||||||
|                                 localIdentName: |                                 localIdentName: '[name]__[local]___[hash:base64:5]', | ||||||
|                                     '[name]__[local]___[hash:base64:5]', |  | ||||||
|                             }, |                             }, | ||||||
|                         }, |                         }, | ||||||
|                         { |                         { | ||||||
|                             loader: 'sass-loader', |                             loader: 'sass-loader', | ||||||
|                             options: { |                             options: { | ||||||
|                                 // data: '@import "theme/_config.scss";',
 |                                 // data: '@import "theme/_config.scss";',
 | ||||||
|                                 includePaths: [ |                                 includePaths: [path.resolve(__dirname, './src')], | ||||||
|                                     path.resolve(__dirname, './src'), |  | ||||||
|                                 ], |  | ||||||
|                             }, |                             }, | ||||||
|                         }, |                         }, | ||||||
|                     ], |                     ], | ||||||
| @ -72,10 +69,7 @@ module.exports = { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 test: /\.css$/, |                 test: /\.css$/, | ||||||
|                 loader: ExtractTextPlugin.extract({ |                 loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }), | ||||||
|                     fallback: 'style-loader', |  | ||||||
|                     use: 'css-loader', |  | ||||||
|                 }), |  | ||||||
|             }, |             }, | ||||||
|         ], |         ], | ||||||
|     }, |     }, | ||||||
|  | |||||||
| @ -1253,7 +1253,15 @@ chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: | |||||||
|     strip-ansi "^3.0.0" |     strip-ansi "^3.0.0" | ||||||
|     supports-color "^2.0.0" |     supports-color "^2.0.0" | ||||||
| 
 | 
 | ||||||
| chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: | chalk@^2.0.0, chalk@^2.0.1: | ||||||
|  |   version "2.0.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" | ||||||
|  |   dependencies: | ||||||
|  |     ansi-styles "^3.1.0" | ||||||
|  |     escape-string-regexp "^1.0.5" | ||||||
|  |     supports-color "^4.0.0" | ||||||
|  | 
 | ||||||
|  | chalk@^2.1.0: | ||||||
|   version "2.1.0" |   version "2.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" |   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" | ||||||
|   dependencies: |   dependencies: | ||||||
| @ -2465,10 +2473,14 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: | |||||||
|     mkdirp ">=0.5 0" |     mkdirp ">=0.5 0" | ||||||
|     rimraf "2" |     rimraf "2" | ||||||
| 
 | 
 | ||||||
| function-bind@^1.0.2, function-bind@^1.1.0: | function-bind@^1.0.2: | ||||||
|   version "1.1.0" |   version "1.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" |   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" | ||||||
| 
 | 
 | ||||||
|  | function-bind@^1.1.0: | ||||||
|  |   version "1.1.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" | ||||||
|  | 
 | ||||||
| functional-red-black-tree@^1.0.1: | functional-red-black-tree@^1.0.1: | ||||||
|   version "1.0.1" |   version "1.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" |   resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" | ||||||
| @ -3364,7 +3376,14 @@ js-tokens@^3.0.0: | |||||||
|   version "3.0.2" |   version "3.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" |   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" | ||||||
| 
 | 
 | ||||||
| js-yaml@^3.7.0, js-yaml@^3.9.1: | js-yaml@^3.7.0: | ||||||
|  |   version "3.9.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.0.tgz#4ffbbf25c2ac963b8299dc74da7e3740de1c18ce" | ||||||
|  |   dependencies: | ||||||
|  |     argparse "^1.0.7" | ||||||
|  |     esprima "^4.0.0" | ||||||
|  | 
 | ||||||
|  | js-yaml@^3.9.1: | ||||||
|   version "3.9.1" |   version "3.9.1" | ||||||
|   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" |   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" | ||||||
|   dependencies: |   dependencies: | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user