mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: Should be possible to remove applications
https://github.com/Unleash/unleash/issues/634
This commit is contained in:
		
							parent
							
								
									a097a90dbe
								
							
						
					
					
						commit
						b1d30b045e
					
				@ -23,7 +23,7 @@ exports[`renders correctly with permissions 1`] = `
 | 
				
			|||||||
    <react-mdl-Icon
 | 
					    <react-mdl-Icon
 | 
				
			||||||
      name="apps"
 | 
					      name="apps"
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
     
 | 
					     
 | 
				
			||||||
    test-app
 | 
					    test-app
 | 
				
			||||||
  </react-mdl-CardTitle>
 | 
					  </react-mdl-CardTitle>
 | 
				
			||||||
  <react-mdl-CardText>
 | 
					  <react-mdl-CardText>
 | 
				
			||||||
@ -41,6 +41,26 @@ exports[`renders correctly with permissions 1`] = `
 | 
				
			|||||||
      />
 | 
					      />
 | 
				
			||||||
    </a>
 | 
					    </a>
 | 
				
			||||||
  </react-mdl-CardMenu>
 | 
					  </react-mdl-CardMenu>
 | 
				
			||||||
 | 
					  <div>
 | 
				
			||||||
 | 
					    <react-mdl-CardActions
 | 
				
			||||||
 | 
					      border={true}
 | 
				
			||||||
 | 
					      style={
 | 
				
			||||||
 | 
					        Object {
 | 
				
			||||||
 | 
					          "alignItems": "center",
 | 
				
			||||||
 | 
					          "display": "flex",
 | 
				
			||||||
 | 
					          "justifyContent": "space-between",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <span />
 | 
				
			||||||
 | 
					      <react-mdl-Button
 | 
				
			||||||
 | 
					        accent={true}
 | 
				
			||||||
 | 
					        onClick={[Function]}
 | 
				
			||||||
 | 
					        title="Delete application"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        Delete
 | 
				
			||||||
 | 
					      </react-mdl-Button>
 | 
				
			||||||
 | 
					    </react-mdl-CardActions>
 | 
				
			||||||
    <hr />
 | 
					    <hr />
 | 
				
			||||||
    <react-mdl-Tabs
 | 
					    <react-mdl-Tabs
 | 
				
			||||||
      activeTab={0}
 | 
					      activeTab={0}
 | 
				
			||||||
@ -62,6 +82,7 @@ exports[`renders correctly with permissions 1`] = `
 | 
				
			|||||||
        Edit
 | 
					        Edit
 | 
				
			||||||
      </react-mdl-Tab>
 | 
					      </react-mdl-Tab>
 | 
				
			||||||
    </react-mdl-Tabs>
 | 
					    </react-mdl-Tabs>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
  <react-mdl-Grid
 | 
					  <react-mdl-Grid
 | 
				
			||||||
    style={
 | 
					    style={
 | 
				
			||||||
      Object {
 | 
					      Object {
 | 
				
			||||||
@ -214,7 +235,7 @@ exports[`renders correctly without permission 1`] = `
 | 
				
			|||||||
    <react-mdl-Icon
 | 
					    <react-mdl-Icon
 | 
				
			||||||
      name="apps"
 | 
					      name="apps"
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
     
 | 
					     
 | 
				
			||||||
    test-app
 | 
					    test-app
 | 
				
			||||||
  </react-mdl-CardTitle>
 | 
					  </react-mdl-CardTitle>
 | 
				
			||||||
  <react-mdl-CardText>
 | 
					  <react-mdl-CardText>
 | 
				
			||||||
@ -232,7 +253,6 @@ exports[`renders correctly without permission 1`] = `
 | 
				
			|||||||
      />
 | 
					      />
 | 
				
			||||||
    </a>
 | 
					    </a>
 | 
				
			||||||
  </react-mdl-CardMenu>
 | 
					  </react-mdl-CardMenu>
 | 
				
			||||||
  <hr />
 | 
					 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  <react-mdl-Grid
 | 
					  <react-mdl-Grid
 | 
				
			||||||
    style={
 | 
					    style={
 | 
				
			||||||
 | 
				
			|||||||
@ -4,9 +4,11 @@ import PropTypes from 'prop-types';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { Link } from 'react-router-dom';
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 | 
					    Button,
 | 
				
			||||||
    Grid,
 | 
					    Grid,
 | 
				
			||||||
    Cell,
 | 
					    Cell,
 | 
				
			||||||
    Card,
 | 
					    Card,
 | 
				
			||||||
 | 
					    CardActions,
 | 
				
			||||||
    CardTitle,
 | 
					    CardTitle,
 | 
				
			||||||
    CardText,
 | 
					    CardText,
 | 
				
			||||||
    CardMenu,
 | 
					    CardMenu,
 | 
				
			||||||
@ -64,7 +66,9 @@ class ClientApplications extends PureComponent {
 | 
				
			|||||||
        application: PropTypes.object,
 | 
					        application: PropTypes.object,
 | 
				
			||||||
        location: PropTypes.object,
 | 
					        location: PropTypes.object,
 | 
				
			||||||
        storeApplicationMetaData: PropTypes.func.isRequired,
 | 
					        storeApplicationMetaData: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					        deleteApplication: PropTypes.func.isRequired,
 | 
				
			||||||
        hasPermission: PropTypes.func.isRequired,
 | 
					        hasPermission: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					        history: PropTypes.object.isRequired,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(props) {
 | 
					    constructor(props) {
 | 
				
			||||||
@ -78,6 +82,14 @@ class ClientApplications extends PureComponent {
 | 
				
			|||||||
    formatFullDateTime(v) {
 | 
					    formatFullDateTime(v) {
 | 
				
			||||||
        return formatFullDateTimeWithLocale(v, this.props.location.locale);
 | 
					        return formatFullDateTimeWithLocale(v, this.props.location.locale);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    deleteApplication = async evt => {
 | 
				
			||||||
 | 
					        evt.preventDefault();
 | 
				
			||||||
 | 
					        const { deleteApplication, appName } = this.props;
 | 
				
			||||||
 | 
					        await deleteApplication(appName);
 | 
				
			||||||
 | 
					        this.props.history.push('/applications');
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        if (!this.props.application) {
 | 
					        if (!this.props.application) {
 | 
				
			||||||
            return <ProgressBar indeterminate />;
 | 
					            return <ProgressBar indeterminate />;
 | 
				
			||||||
@ -173,9 +185,6 @@ class ClientApplications extends PureComponent {
 | 
				
			|||||||
                </Grid>
 | 
					                </Grid>
 | 
				
			||||||
            ) : (
 | 
					            ) : (
 | 
				
			||||||
                <Grid>
 | 
					                <Grid>
 | 
				
			||||||
                    <Cell col={12}>
 | 
					 | 
				
			||||||
                        <h5>Edit app meta data</h5>
 | 
					 | 
				
			||||||
                    </Cell>
 | 
					 | 
				
			||||||
                    <Cell col={6} tablet={12}>
 | 
					                    <Cell col={6} tablet={12}>
 | 
				
			||||||
                        <StatefulTextfield
 | 
					                        <StatefulTextfield
 | 
				
			||||||
                            value={url}
 | 
					                            value={url}
 | 
				
			||||||
@ -194,7 +203,7 @@ class ClientApplications extends PureComponent {
 | 
				
			|||||||
                    <Cell col={6} tablet={12}>
 | 
					                    <Cell col={6} tablet={12}>
 | 
				
			||||||
                        <MySelect
 | 
					                        <MySelect
 | 
				
			||||||
                            label="Icon"
 | 
					                            label="Icon"
 | 
				
			||||||
                            options={icons.map(v => ({ name: v, label: v }))}
 | 
					                            options={icons.map(v => ({ key: v, label: v }))}
 | 
				
			||||||
                            value={icon}
 | 
					                            value={icon}
 | 
				
			||||||
                            onChange={e => storeApplicationMetaData(appName, 'icon', e.target.value)}
 | 
					                            onChange={e => storeApplicationMetaData(appName, 'icon', e.target.value)}
 | 
				
			||||||
                            filled
 | 
					                            filled
 | 
				
			||||||
@ -211,7 +220,7 @@ class ClientApplications extends PureComponent {
 | 
				
			|||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <Card shadow={0} className={commonStyles.fullwidth}>
 | 
					            <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} />
 | 
					                    <Icon name={icon || 'apps'} />
 | 
				
			||||||
                     {appName}
 | 
					                     {appName}
 | 
				
			||||||
                </CardTitle>
 | 
					                </CardTitle>
 | 
				
			||||||
                {description && <CardText>{description}</CardText>}
 | 
					                {description && <CardText>{description}</CardText>}
 | 
				
			||||||
@ -220,8 +229,22 @@ class ClientApplications extends PureComponent {
 | 
				
			|||||||
                        <IconLink url={url} icon="link" />
 | 
					                        <IconLink url={url} icon="link" />
 | 
				
			||||||
                    </CardMenu>
 | 
					                    </CardMenu>
 | 
				
			||||||
                )}
 | 
					                )}
 | 
				
			||||||
                <hr />
 | 
					 | 
				
			||||||
                {hasPermission(UPDATE_APPLICATION) ? (
 | 
					                {hasPermission(UPDATE_APPLICATION) ? (
 | 
				
			||||||
 | 
					                    <div>
 | 
				
			||||||
 | 
					                        <CardActions
 | 
				
			||||||
 | 
					                            border
 | 
				
			||||||
 | 
					                            style={{
 | 
				
			||||||
 | 
					                                display: 'flex',
 | 
				
			||||||
 | 
					                                alignItems: 'center',
 | 
				
			||||||
 | 
					                                justifyContent: 'space-between',
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            <span />
 | 
				
			||||||
 | 
					                            <Button accent title="Delete application" onClick={this.deleteApplication}>
 | 
				
			||||||
 | 
					                                Delete
 | 
				
			||||||
 | 
					                            </Button>
 | 
				
			||||||
 | 
					                        </CardActions>
 | 
				
			||||||
 | 
					                        <hr />
 | 
				
			||||||
                        <Tabs
 | 
					                        <Tabs
 | 
				
			||||||
                            activeTab={this.state.activeTab}
 | 
					                            activeTab={this.state.activeTab}
 | 
				
			||||||
                            onChange={tabId => this.setState({ activeTab: tabId })}
 | 
					                            onChange={tabId => this.setState({ activeTab: tabId })}
 | 
				
			||||||
@ -232,6 +255,7 @@ class ClientApplications extends PureComponent {
 | 
				
			|||||||
                            <Tab>Details</Tab>
 | 
					                            <Tab>Details</Tab>
 | 
				
			||||||
                            <Tab>Edit</Tab>
 | 
					                            <Tab>Edit</Tab>
 | 
				
			||||||
                        </Tabs>
 | 
					                        </Tabs>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
                ) : (
 | 
					                ) : (
 | 
				
			||||||
                    ''
 | 
					                    ''
 | 
				
			||||||
                )}
 | 
					                )}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { connect } from 'react-redux';
 | 
					import { connect } from 'react-redux';
 | 
				
			||||||
import ApplicationEdit from './application-edit-component';
 | 
					import ApplicationEdit from './application-edit-component';
 | 
				
			||||||
import { fetchApplication, storeApplicationMetaData } from './../../store/application/actions';
 | 
					import { fetchApplication, storeApplicationMetaData, deleteApplication } from './../../store/application/actions';
 | 
				
			||||||
import { hasPermission } from '../../permissions';
 | 
					import { hasPermission } from '../../permissions';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mapStateToProps = (state, props) => {
 | 
					const mapStateToProps = (state, props) => {
 | 
				
			||||||
@ -19,6 +19,7 @@ const mapStateToProps = (state, props) => {
 | 
				
			|||||||
const Constainer = connect(mapStateToProps, {
 | 
					const Constainer = connect(mapStateToProps, {
 | 
				
			||||||
    fetchApplication,
 | 
					    fetchApplication,
 | 
				
			||||||
    storeApplicationMetaData,
 | 
					    storeApplicationMetaData,
 | 
				
			||||||
 | 
					    deleteApplication,
 | 
				
			||||||
})(ApplicationEdit);
 | 
					})(ApplicationEdit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Constainer;
 | 
					export default Constainer;
 | 
				
			||||||
 | 
				
			|||||||
@ -34,9 +34,18 @@ function storeApplicationMetaData(appName, key, value) {
 | 
				
			|||||||
    }).then(throwIfNotSuccess);
 | 
					    }).then(throwIfNotSuccess);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function deleteApplication(appName) {
 | 
				
			||||||
 | 
					    return fetch(`${URI}/${appName}`, {
 | 
				
			||||||
 | 
					        method: 'DELETE',
 | 
				
			||||||
 | 
					        headers,
 | 
				
			||||||
 | 
					        credentials: 'include',
 | 
				
			||||||
 | 
					    }).then(throwIfNotSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    fetchApplication,
 | 
					    fetchApplication,
 | 
				
			||||||
    fetchAll,
 | 
					    fetchAll,
 | 
				
			||||||
    fetchApplicationsWithStrategyName,
 | 
					    fetchApplicationsWithStrategyName,
 | 
				
			||||||
    storeApplicationMetaData,
 | 
					    storeApplicationMetaData,
 | 
				
			||||||
 | 
					    deleteApplication,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -2,10 +2,11 @@ import React from 'react';
 | 
				
			|||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import ApplicationEditComponent from '../../component/application/application-edit-container';
 | 
					import ApplicationEditComponent from '../../component/application/application-edit-container';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const render = ({ match: { params } }) => <ApplicationEditComponent appName={params.name} />;
 | 
					const render = ({ match: { params }, history }) => <ApplicationEditComponent appName={params.name} history={history} />;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
render.propTypes = {
 | 
					render.propTypes = {
 | 
				
			||||||
    match: PropTypes.object.isRequired,
 | 
					    match: PropTypes.object.isRequired,
 | 
				
			||||||
 | 
					    history: PropTypes.object.isRequired,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default render;
 | 
					export default render;
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,8 @@ export const ERROR_UPDATING_APPLICATION_DATA = 'ERROR_UPDATING_APPLICATION_DATA'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const RECEIVE_APPLICATION = 'RECEIVE_APPLICATION';
 | 
					export const RECEIVE_APPLICATION = 'RECEIVE_APPLICATION';
 | 
				
			||||||
export const UPDATE_APPLICATION_FIELD = 'UPDATE_APPLICATION_FIELD';
 | 
					export const UPDATE_APPLICATION_FIELD = 'UPDATE_APPLICATION_FIELD';
 | 
				
			||||||
 | 
					export const DELETE_APPLICATION = 'DELETE_APPLICATION';
 | 
				
			||||||
 | 
					export const ERROR_DELETE_APPLICATION = 'ERROR_DELETE_APPLICATION';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const recieveAllApplications = json => ({
 | 
					const recieveAllApplications = json => ({
 | 
				
			||||||
    type: RECEIVE_ALL_APPLICATIONS,
 | 
					    type: RECEIVE_ALL_APPLICATIONS,
 | 
				
			||||||
@ -41,3 +43,11 @@ export function fetchApplication(appName) {
 | 
				
			|||||||
            .then(json => dispatch(recieveApplication(json)))
 | 
					            .then(json => dispatch(recieveApplication(json)))
 | 
				
			||||||
            .catch(dispatchAndThrow(dispatch, ERROR_RECEIVE_ALL_APPLICATIONS));
 | 
					            .catch(dispatchAndThrow(dispatch, ERROR_RECEIVE_ALL_APPLICATIONS));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function deleteApplication(appName) {
 | 
				
			||||||
 | 
					    return dispatch =>
 | 
				
			||||||
 | 
					        api
 | 
				
			||||||
 | 
					            .deleteApplication(appName)
 | 
				
			||||||
 | 
					            .then(() => dispatch({ type: DELETE_APPLICATION, appName }))
 | 
				
			||||||
 | 
					            .catch(dispatchAndThrow(dispatch, ERROR_DELETE_APPLICATION));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import { fromJS, List, Map } from 'immutable';
 | 
					import { fromJS, List, Map } from 'immutable';
 | 
				
			||||||
import { RECEIVE_ALL_APPLICATIONS, RECEIVE_APPLICATION, UPDATE_APPLICATION_FIELD } from './actions';
 | 
					import { RECEIVE_ALL_APPLICATIONS, RECEIVE_APPLICATION, UPDATE_APPLICATION_FIELD, DELETE_APPLICATION } from './actions';
 | 
				
			||||||
import { USER_LOGOUT, USER_LOGIN } from '../user/actions';
 | 
					import { USER_LOGOUT, USER_LOGIN } from '../user/actions';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getInitState() {
 | 
					function getInitState() {
 | 
				
			||||||
@ -14,6 +14,11 @@ const store = (state = getInitState(), action) => {
 | 
				
			|||||||
            return state.set('list', new List(action.value.applications));
 | 
					            return state.set('list', new List(action.value.applications));
 | 
				
			||||||
        case UPDATE_APPLICATION_FIELD:
 | 
					        case UPDATE_APPLICATION_FIELD:
 | 
				
			||||||
            return state.setIn(['apps', action.appName, action.key], action.value);
 | 
					            return state.setIn(['apps', action.appName, action.key], action.value);
 | 
				
			||||||
 | 
					        case DELETE_APPLICATION: {
 | 
				
			||||||
 | 
					            const index = state.get('list').findIndex(item => item.appName === action.appName);
 | 
				
			||||||
 | 
					            const result = state.removeIn(['list', index]);
 | 
				
			||||||
 | 
					            return result.removeIn(['apps', action.appName]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        case USER_LOGOUT:
 | 
					        case USER_LOGOUT:
 | 
				
			||||||
        case USER_LOGIN:
 | 
					        case USER_LOGIN:
 | 
				
			||||||
            return getInitState();
 | 
					            return getInitState();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user