mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-10 01:16:39 +02: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
|
||||
name="apps"
|
||||
/>
|
||||
|
||||
|
||||
test-app
|
||||
</react-mdl-CardTitle>
|
||||
<react-mdl-CardText>
|
||||
@ -41,27 +41,48 @@ exports[`renders correctly with permissions 1`] = `
|
||||
/>
|
||||
</a>
|
||||
</react-mdl-CardMenu>
|
||||
<hr />
|
||||
<react-mdl-Tabs
|
||||
activeTab={0}
|
||||
className="mdl-color--grey-100"
|
||||
onChange={[Function]}
|
||||
ripple={true}
|
||||
tabBarProps={
|
||||
Object {
|
||||
"style": Object {
|
||||
"width": "100%",
|
||||
},
|
||||
<div>
|
||||
<react-mdl-CardActions
|
||||
border={true}
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
}
|
||||
>
|
||||
<react-mdl-Tab>
|
||||
Details
|
||||
</react-mdl-Tab>
|
||||
<react-mdl-Tab>
|
||||
Edit
|
||||
</react-mdl-Tab>
|
||||
</react-mdl-Tabs>
|
||||
>
|
||||
<span />
|
||||
<react-mdl-Button
|
||||
accent={true}
|
||||
onClick={[Function]}
|
||||
title="Delete application"
|
||||
>
|
||||
Delete
|
||||
</react-mdl-Button>
|
||||
</react-mdl-CardActions>
|
||||
<hr />
|
||||
<react-mdl-Tabs
|
||||
activeTab={0}
|
||||
className="mdl-color--grey-100"
|
||||
onChange={[Function]}
|
||||
ripple={true}
|
||||
tabBarProps={
|
||||
Object {
|
||||
"style": Object {
|
||||
"width": "100%",
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<react-mdl-Tab>
|
||||
Details
|
||||
</react-mdl-Tab>
|
||||
<react-mdl-Tab>
|
||||
Edit
|
||||
</react-mdl-Tab>
|
||||
</react-mdl-Tabs>
|
||||
</div>
|
||||
<react-mdl-Grid
|
||||
style={
|
||||
Object {
|
||||
@ -214,7 +235,7 @@ exports[`renders correctly without permission 1`] = `
|
||||
<react-mdl-Icon
|
||||
name="apps"
|
||||
/>
|
||||
|
||||
|
||||
test-app
|
||||
</react-mdl-CardTitle>
|
||||
<react-mdl-CardText>
|
||||
@ -232,7 +253,6 @@ exports[`renders correctly without permission 1`] = `
|
||||
/>
|
||||
</a>
|
||||
</react-mdl-CardMenu>
|
||||
<hr />
|
||||
|
||||
<react-mdl-Grid
|
||||
style={
|
||||
|
@ -4,9 +4,11 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
Button,
|
||||
Grid,
|
||||
Cell,
|
||||
Card,
|
||||
CardActions,
|
||||
CardTitle,
|
||||
CardText,
|
||||
CardMenu,
|
||||
@ -64,7 +66,9 @@ class ClientApplications extends PureComponent {
|
||||
application: PropTypes.object,
|
||||
location: PropTypes.object,
|
||||
storeApplicationMetaData: PropTypes.func.isRequired,
|
||||
deleteApplication: PropTypes.func.isRequired,
|
||||
hasPermission: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@ -78,6 +82,14 @@ class ClientApplications extends PureComponent {
|
||||
formatFullDateTime(v) {
|
||||
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() {
|
||||
if (!this.props.application) {
|
||||
return <ProgressBar indeterminate />;
|
||||
@ -173,9 +185,6 @@ class ClientApplications extends PureComponent {
|
||||
</Grid>
|
||||
) : (
|
||||
<Grid>
|
||||
<Cell col={12}>
|
||||
<h5>Edit app meta data</h5>
|
||||
</Cell>
|
||||
<Cell col={6} tablet={12}>
|
||||
<StatefulTextfield
|
||||
value={url}
|
||||
@ -194,7 +203,7 @@ class ClientApplications extends PureComponent {
|
||||
<Cell col={6} tablet={12}>
|
||||
<MySelect
|
||||
label="Icon"
|
||||
options={icons.map(v => ({ name: v, label: v }))}
|
||||
options={icons.map(v => ({ key: v, label: v }))}
|
||||
value={icon}
|
||||
onChange={e => storeApplicationMetaData(appName, 'icon', e.target.value)}
|
||||
filled
|
||||
@ -211,7 +220,7 @@ class ClientApplications extends PureComponent {
|
||||
return (
|
||||
<Card shadow={0} className={commonStyles.fullwidth}>
|
||||
<CardTitle style={{ paddingTop: '24px', paddingRight: '64px', wordBreak: 'break-all' }}>
|
||||
<Icon name={icon} />
|
||||
<Icon name={icon || 'apps'} />
|
||||
{appName}
|
||||
</CardTitle>
|
||||
{description && <CardText>{description}</CardText>}
|
||||
@ -220,18 +229,33 @@ class ClientApplications extends PureComponent {
|
||||
<IconLink url={url} icon="link" />
|
||||
</CardMenu>
|
||||
)}
|
||||
<hr />
|
||||
{hasPermission(UPDATE_APPLICATION) ? (
|
||||
<Tabs
|
||||
activeTab={this.state.activeTab}
|
||||
onChange={tabId => this.setState({ activeTab: tabId })}
|
||||
ripple
|
||||
tabBarProps={{ style: { width: '100%' } }}
|
||||
className="mdl-color--grey-100"
|
||||
>
|
||||
<Tab>Details</Tab>
|
||||
<Tab>Edit</Tab>
|
||||
</Tabs>
|
||||
<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
|
||||
activeTab={this.state.activeTab}
|
||||
onChange={tabId => this.setState({ activeTab: tabId })}
|
||||
ripple
|
||||
tabBarProps={{ style: { width: '100%' } }}
|
||||
className="mdl-color--grey-100"
|
||||
>
|
||||
<Tab>Details</Tab>
|
||||
<Tab>Edit</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { connect } from 'react-redux';
|
||||
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';
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
@ -19,6 +19,7 @@ const mapStateToProps = (state, props) => {
|
||||
const Constainer = connect(mapStateToProps, {
|
||||
fetchApplication,
|
||||
storeApplicationMetaData,
|
||||
deleteApplication,
|
||||
})(ApplicationEdit);
|
||||
|
||||
export default Constainer;
|
||||
|
@ -34,9 +34,18 @@ function storeApplicationMetaData(appName, key, value) {
|
||||
}).then(throwIfNotSuccess);
|
||||
}
|
||||
|
||||
function deleteApplication(appName) {
|
||||
return fetch(`${URI}/${appName}`, {
|
||||
method: 'DELETE',
|
||||
headers,
|
||||
credentials: 'include',
|
||||
}).then(throwIfNotSuccess);
|
||||
}
|
||||
|
||||
export default {
|
||||
fetchApplication,
|
||||
fetchAll,
|
||||
fetchApplicationsWithStrategyName,
|
||||
storeApplicationMetaData,
|
||||
deleteApplication,
|
||||
};
|
||||
|
@ -2,10 +2,11 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
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 = {
|
||||
match: PropTypes.object.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
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 UPDATE_APPLICATION_FIELD = 'UPDATE_APPLICATION_FIELD';
|
||||
export const DELETE_APPLICATION = 'DELETE_APPLICATION';
|
||||
export const ERROR_DELETE_APPLICATION = 'ERROR_DELETE_APPLICATION';
|
||||
|
||||
const recieveAllApplications = json => ({
|
||||
type: RECEIVE_ALL_APPLICATIONS,
|
||||
@ -41,3 +43,11 @@ export function fetchApplication(appName) {
|
||||
.then(json => dispatch(recieveApplication(json)))
|
||||
.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 { 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';
|
||||
|
||||
function getInitState() {
|
||||
@ -14,6 +14,11 @@ const store = (state = getInitState(), action) => {
|
||||
return state.set('list', new List(action.value.applications));
|
||||
case UPDATE_APPLICATION_FIELD:
|
||||
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_LOGIN:
|
||||
return getInitState();
|
||||
|
Loading…
Reference in New Issue
Block a user