mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feature: Add support for permission system in unleash frontend
refactored PermissionComponent to pure component fixed feature-list-item-component
This commit is contained in:
		
							parent
							
								
									1eb8fc0464
								
							
						
					
					
						commit
						aad612d3d6
					
				| @ -1,47 +1,21 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { ADMIN } from '../../permissions'; | ||||
| 
 | ||||
| class PermissionComponent extends Component { | ||||
|     static propTypes = { | ||||
|         user: PropTypes.object, | ||||
|         component: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), | ||||
|         others: PropTypes.object, | ||||
|         denied: PropTypes.object, | ||||
|         granted: PropTypes.object, | ||||
|         otherwise: PropTypes.node, | ||||
|         permission: PropTypes.string, | ||||
|         children: PropTypes.node, | ||||
|     }; | ||||
| 
 | ||||
|     render() { | ||||
|         const { user, otherwise, component: Component, permission, granted, denied, children, ...others } = this.props; | ||||
|         let grantedComponent = Component; | ||||
|         let deniedCompoinent = otherwise || ''; | ||||
| 
 | ||||
|         if (granted || denied) { | ||||
|             grantedComponent = ( | ||||
|                 <Component {...others} {...granted || {}}> | ||||
|                     {children} | ||||
|                 </Component> | ||||
|             ); | ||||
|             deniedCompoinent = ( | ||||
|                 <Component {...others} {...denied || {}}> | ||||
|                     {children} | ||||
|                 </Component> | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         if (!user) return deniedCompoinent; | ||||
|         if ( | ||||
|             !user.permissions || | ||||
|             user.permissions.indexOf(ADMIN) !== -1 || | ||||
|             user.permissions.indexOf(permission) !== -1 | ||||
|         ) { | ||||
|             return grantedComponent; | ||||
|         } | ||||
|         return deniedCompoinent; | ||||
| const PermissionComponent = ({ user, permission, component, otherwise }) => { | ||||
|     if ( | ||||
|         user && | ||||
|         (!user.permissions || user.permissions.indexOf(ADMIN) !== -1 || user.permissions.indexOf(permission) !== -1) | ||||
|     ) { | ||||
|         return component; | ||||
|     } | ||||
| } | ||||
|     return otherwise || ''; | ||||
| }; | ||||
| 
 | ||||
| PermissionComponent.propTypes = { | ||||
|     user: PropTypes.object, | ||||
|     component: PropTypes.node, | ||||
|     otherwise: PropTypes.node, | ||||
|     permission: PropTypes.string, | ||||
| }; | ||||
| 
 | ||||
| export default PermissionComponent; | ||||
|  | ||||
| @ -22,7 +22,7 @@ exports[`renders correctly with one feature 1`] = ` | ||||
|   > | ||||
|     <react-mdl-Switch | ||||
|       checked={false} | ||||
|       disabled={true} | ||||
|       disabled={false} | ||||
|       onChange={[Function]} | ||||
|       title="Toggle Another" | ||||
|     /> | ||||
|  | ||||
| @ -1,8 +1,12 @@ | ||||
| import React from 'react'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
| import { createStore } from 'redux'; | ||||
| import { Provider } from 'react-redux'; | ||||
| import { Map as $Map } from 'immutable'; | ||||
| 
 | ||||
| import Feature from './../feature-list-item-component'; | ||||
| import renderer from 'react-test-renderer'; | ||||
| import { UPDATE_FEATURE } from '../../../permissions'; | ||||
| 
 | ||||
| jest.mock('react-mdl'); | ||||
| 
 | ||||
| @ -21,19 +25,22 @@ test('renders correctly with one feature', () => { | ||||
|         ], | ||||
|         createdAt: '2018-02-04T20:27:52.127Z', | ||||
|     }; | ||||
|     const store = { user: new $Map({ profile: { permissions: [UPDATE_FEATURE] } }) }; | ||||
|     const featureMetrics = { lastHour: {}, lastMinute: {}, seenApps: {} }; | ||||
|     const settings = { sort: 'name' }; | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter> | ||||
|             <Feature | ||||
|                 key={0} | ||||
|                 settings={settings} | ||||
|                 metricsLastHour={featureMetrics.lastHour[feature.name]} | ||||
|                 metricsLastMinute={featureMetrics.lastMinute[feature.name]} | ||||
|                 feature={feature} | ||||
|                 toggleFeature={jest.fn()} | ||||
|             /> | ||||
|         </MemoryRouter> | ||||
|         <Provider store={createStore(state => state, store)}> | ||||
|             <MemoryRouter> | ||||
|                 <Feature | ||||
|                     key={0} | ||||
|                     settings={settings} | ||||
|                     metricsLastHour={featureMetrics.lastHour[feature.name]} | ||||
|                     metricsLastMinute={featureMetrics.lastMinute[feature.name]} | ||||
|                     feature={feature} | ||||
|                     toggleFeature={jest.fn()} | ||||
|                 /> | ||||
|             </MemoryRouter> | ||||
|         </Provider> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
|  | ||||
| @ -3,6 +3,8 @@ import PropTypes from 'prop-types'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { Switch, Chip, ListItem, ListItemAction, Icon } from 'react-mdl'; | ||||
| import Progress from './progress'; | ||||
| import PermissionComponent from '../common/permission-container'; | ||||
| import { UPDATE_FEATURE } from '../../permissions'; | ||||
| import { calc, styles as commonStyles } from '../common'; | ||||
| 
 | ||||
| import styles from './feature.scss'; | ||||
| @ -14,7 +16,6 @@ const Feature = ({ | ||||
|     metricsLastHour = { yes: 0, no: 0, isFallback: true }, | ||||
|     metricsLastMinute = { yes: 0, no: 0, isFallback: true }, | ||||
|     revive, | ||||
|     updateable, | ||||
| }) => { | ||||
|     const { name, description, enabled, strategies } = feature; | ||||
|     const { showLastHour = false } = settings; | ||||
| @ -42,12 +43,26 @@ const Feature = ({ | ||||
|                 <Progress strokeWidth={15} percentage={percent} isFallback={isStale} /> | ||||
|             </span> | ||||
|             <span className={styles.listItemToggle}> | ||||
|                 <Switch | ||||
|                     disabled={!updateable || toggleFeature === undefined} | ||||
|                     title={`Toggle ${name}`} | ||||
|                     key="left-actions" | ||||
|                     onChange={() => toggleFeature(name)} | ||||
|                     checked={enabled} | ||||
|                 <PermissionComponent | ||||
|                     permission={UPDATE_FEATURE} | ||||
|                     component={ | ||||
|                         <Switch | ||||
|                             disabled={toggleFeature === undefined} | ||||
|                             title={`Toggle ${name}`} | ||||
|                             key="left-actions" | ||||
|                             onChange={() => toggleFeature(name)} | ||||
|                             checked={enabled} | ||||
|                         /> | ||||
|                     } | ||||
|                     otherwise={ | ||||
|                         <Switch | ||||
|                             disabled | ||||
|                             title={`Toggle ${name}`} | ||||
|                             key="left-actions" | ||||
|                             onChange={() => toggleFeature(name)} | ||||
|                             checked={enabled} | ||||
|                         /> | ||||
|                     } | ||||
|                 /> | ||||
|             </span> | ||||
|             <span className={['mdl-list__item-primary-content', styles.listItemLink].join(' ')}> | ||||
| @ -60,10 +75,16 @@ const Feature = ({ | ||||
|                 {strategyChips} | ||||
|                 {summaryChip} | ||||
|             </span> | ||||
|             {updateable && revive ? ( | ||||
|                 <ListItemAction onClick={() => revive(feature.name)}> | ||||
|                     <Icon name="undo" /> | ||||
|                 </ListItemAction> | ||||
|             {revive ? ( | ||||
|                 <PermissionComponent | ||||
|                     permission={UPDATE_FEATURE} | ||||
|                     component={ | ||||
|                         <ListItemAction onClick={() => revive(feature.name)}> | ||||
|                             <Icon name="undo" /> | ||||
|                         </ListItemAction> | ||||
|                     } | ||||
|                     otherwise={<span />} | ||||
|                 /> | ||||
|             ) : ( | ||||
|                 <span /> | ||||
|             )} | ||||
|  | ||||
| @ -8,10 +8,10 @@ import { HeaderTitle } from '../../common'; | ||||
| class StrategiesSectionComponent extends React.Component { | ||||
|     static propTypes = { | ||||
|         strategies: PropTypes.array.isRequired, | ||||
|         addStrategy: PropTypes.func.isRequired, | ||||
|         removeStrategy: PropTypes.func.isRequired, | ||||
|         updateStrategy: PropTypes.func.isRequired, | ||||
|         fetchStrategies: PropTypes.func.isRequired, | ||||
|         addStrategy: PropTypes.func, | ||||
|         removeStrategy: PropTypes.func, | ||||
|         updateStrategy: PropTypes.func, | ||||
|         fetchStrategies: PropTypes.func, | ||||
|     }; | ||||
| 
 | ||||
|     componentWillMount() { | ||||
|  | ||||
| @ -155,20 +155,29 @@ export default class ViewFeatureToggleComponent extends React.Component { | ||||
|                     {this.isFeatureView ? ( | ||||
|                         <PermissionComponent | ||||
|                             permission={UPDATE_FEATURE} | ||||
|                             component={Textfield} | ||||
|                             granted={{ | ||||
|                                 onChange: v => setValue('description', v), | ||||
|                                 onBlur: updateFeatureToggle, | ||||
|                             }} | ||||
|                             denied={{ | ||||
|                                 disabled: true, | ||||
|                             }} | ||||
|                             floatingLabel | ||||
|                             style={{ width: '100%' }} | ||||
|                             rows={1} | ||||
|                             label="Description" | ||||
|                             required | ||||
|                             value={featureToggle.description} | ||||
|                             component={ | ||||
|                                 <Textfield | ||||
|                                     floatingLabel | ||||
|                                     style={{ width: '100%' }} | ||||
|                                     rows={1} | ||||
|                                     label="Description" | ||||
|                                     required | ||||
|                                     value={featureToggle.description} | ||||
|                                     onChange={v => setValue('description', v)} | ||||
|                                     onBlur={updateFeatureToggle} | ||||
|                                 /> | ||||
|                             } | ||||
|                             otherwise={ | ||||
|                                 <Textfield | ||||
|                                     disabled | ||||
|                                     floatingLabel | ||||
|                                     style={{ width: '100%' }} | ||||
|                                     rows={1} | ||||
|                                     label="Description" | ||||
|                                     required | ||||
|                                     value={featureToggle.description} | ||||
|                                 /> | ||||
|                             } | ||||
|                         /> | ||||
|                     ) : ( | ||||
|                         <Textfield | ||||
| @ -194,19 +203,27 @@ export default class ViewFeatureToggleComponent extends React.Component { | ||||
|                     <span style={{ paddingRight: '24px' }}> | ||||
|                         <PermissionComponent | ||||
|                             permission={UPDATE_FEATURE} | ||||
|                             component={Switch} | ||||
|                             granted={{ | ||||
|                                 disabled: !this.isFeatureView, | ||||
|                             }} | ||||
|                             denied={{ | ||||
|                                 disabled: true, | ||||
|                             }} | ||||
|                             ripple | ||||
|                             checked={featureToggle.enabled} | ||||
|                             onChange={() => toggleFeature(featureToggle.name)} | ||||
|                         > | ||||
|                             {featureToggle.enabled ? 'Enabled' : 'Disabled'} | ||||
|                         </PermissionComponent> | ||||
|                             component={ | ||||
|                                 <Switch | ||||
|                                     disabled={!this.isFeatureView} | ||||
|                                     ripple | ||||
|                                     checked={featureToggle.enabled} | ||||
|                                     onChange={() => toggleFeature(featureToggle.name)} | ||||
|                                 > | ||||
|                                     {featureToggle.enabled ? 'Enabled' : 'Disabled'} | ||||
|                                 </Switch> | ||||
|                             } | ||||
|                             otherwise={ | ||||
|                                 <Switch | ||||
|                                     disabled | ||||
|                                     ripple | ||||
|                                     checked={featureToggle.enabled} | ||||
|                                     onChange={() => toggleFeature(featureToggle.name)} | ||||
|                                 > | ||||
|                                     {featureToggle.enabled ? 'Enabled' : 'Disabled'} | ||||
|                                 </Switch> | ||||
|                             } | ||||
|                         /> | ||||
|                     </span> | ||||
| 
 | ||||
|                     {this.isFeatureView ? ( | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user