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