mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-15 01:16:22 +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
|
<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