"Delete" action better with browser history (i.e. back button now works correctly with the Delete dialog).

This commit is contained in:
Tomas Bures 2017-06-09 12:01:01 +02:00
parent ed5b81b6e6
commit 1d1355df34
4 changed files with 41 additions and 22 deletions

View file

@ -68,10 +68,19 @@ class Breadcrumb extends Component {
renderElement(breadcrumbElem) { renderElement(breadcrumbElem) {
if (breadcrumbElem.isActive) { if (breadcrumbElem.isActive) {
return <li key={breadcrumbElem.idx} className="active">{breadcrumbElem.title}</li>; return <li key={breadcrumbElem.idx} className="active">{breadcrumbElem.title}</li>;
} else if (breadcrumbElem.externalLink) { } else if (breadcrumbElem.externalLink) {
return <li key={breadcrumbElem.idx}><a href={breadcrumbElem.externalLink}>{breadcrumbElem.title}</a></li>; return <li key={breadcrumbElem.idx}><a href={breadcrumbElem.externalLink}>{breadcrumbElem.title}</a></li>;
} else if (breadcrumbElem.link) { } else if (breadcrumbElem.link) {
return <li key={breadcrumbElem.idx}><Link to={breadcrumbElem.link}>{breadcrumbElem.title}</Link></li>; let link;
if (typeof breadcrumbElem.link === 'function') {
link = breadcrumbElem.link(this.props.match);
} else {
link = breadcrumbElem.link;
}
return <li key={breadcrumbElem.idx}><Link to={link}>{breadcrumbElem.title}</Link></li>;
} else { } else {
return <li key={breadcrumbElem.idx}>{breadcrumbElem.title}</li>; return <li key={breadcrumbElem.idx}>{breadcrumbElem.title}</li>;
} }
@ -182,6 +191,10 @@ class SectionContent extends Component {
this.props.history.push(path); this.props.history.push(path);
} }
navigateBack() {
this.props.history.goBack();
}
navigateToWithFlashMessage(path, severity, text) { navigateToWithFlashMessage(path, severity, text) {
this.props.history.push(path); this.props.history.push(path);
this.setFlashMessage(severity, text); this.setFlashMessage(severity, text);
@ -309,6 +322,10 @@ function withPageHelpers(target) {
return this.context.sectionContent.navigateTo(path); return this.context.sectionContent.navigateTo(path);
} }
inst.navigateBack = function() {
return this.context.sectionContent.navigateBack();
}
inst.navigateToWithFlashMessage = function(path, severity, text) { inst.navigateToWithFlashMessage = function(path, severity, text) {
return this.context.sectionContent.navigateToWithFlashMessage(path, severity, text); return this.context.sectionContent.navigateToWithFlashMessage(path, severity, text);
} }

View file

@ -109,9 +109,9 @@ class TreeTable extends Component {
const linksContainer = jQuery('<span class="mt-action-links"/>'); const linksContainer = jQuery('<span class="mt-action-links"/>');
const links = actionLinks.map(({label, link}) => { const links = actionLinks.map(({label, link}) => {
const lnkHtml = ReactDOMServer.renderToStaticMarkup(<a href="#">{label}</a>); const lnkHtml = ReactDOMServer.renderToStaticMarkup(<a href="">{label}</a>);
const lnk = jQuery(lnkHtml); const lnk = jQuery(lnkHtml);
lnk.click(() => this.navigateTo(link(node.key))); lnk.click((evt) => { evt.preventDefault(); this.navigateTo(link(node.key)) });
linksContainer.append(lnk); linksContainer.append(lnk);
}); });

View file

@ -17,19 +17,30 @@ export default class CUD extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {};
if (props.edit) {
this.state.nsId = parseInt(props.match.params.nsId);
}
this.initFormState(); this.initFormState();
this.hasChildren = false; this.hasChildren = false;
} }
isEditGlobal() { isEditGlobal() {
return this.nsId === 1; return this.state.nsId === 1;
}
isDelete() {
return this.props.match.params.action === 'delete';
} }
removeNsIdSubtree(data) { removeNsIdSubtree(data) {
for (let idx = 0; idx < data.length; idx++) { for (let idx = 0; idx < data.length; idx++) {
const entry = data[idx]; const entry = data[idx];
if (entry.key === this.nsId) { if (entry.key === this.state.nsId) {
if (entry.children.length > 0) { if (entry.children.length > 0) {
this.hasChildren = true; this.hasChildren = true;
} }
@ -64,16 +75,13 @@ export default class CUD extends Component {
@withAsyncErrorHandler @withAsyncErrorHandler
async loadFormValues() { async loadFormValues() {
await this.getFormValuesFromURL(`/namespaces/rest/namespaces/${this.nsId}`, data => { await this.getFormValuesFromURL(`/namespaces/rest/namespaces/${this.state.nsId}`, data => {
if (data.parent) data.parent = data.parent.toString(); if (data.parent) data.parent = data.parent.toString();
}); });
} }
componentDidMount() { componentDidMount() {
const edit = this.props.edit; if (this.props.edit) {
if (edit) {
this.nsId = parseInt(this.props.match.params.nsId);
this.loadFormValues(); this.loadFormValues();
} else { } else {
this.populateFormValues({ this.populateFormValues({
@ -113,7 +121,7 @@ export default class CUD extends Component {
let sendMethod, url; let sendMethod, url;
if (edit) { if (edit) {
sendMethod = FormSendMethod.PUT; sendMethod = FormSendMethod.PUT;
url = `/namespaces/rest/namespaces/${this.nsId}` url = `/namespaces/rest/namespaces/${this.state.nsId}`
} else { } else {
sendMethod = FormSendMethod.POST; sendMethod = FormSendMethod.POST;
url = '/namespaces/rest/namespaces' url = '/namespaces/rest/namespaces'
@ -151,15 +159,11 @@ export default class CUD extends Component {
} }
async showDeleteModal() { async showDeleteModal() {
this.setState({ this.navigateTo(`/namespaces/edit/${this.state.nsId}/delete`);
deleteConfirmationShown: true
});
} }
async hideDeleteModal() { async hideDeleteModal() {
this.setState({ this.navigateTo(`/namespaces/edit/${this.state.nsId}`);
deleteConfirmationShown: false
});
} }
async performDelete() { async performDelete() {
@ -171,7 +175,7 @@ export default class CUD extends Component {
this.disableForm(); this.disableForm();
this.setFormStatusMessage('info', t('Deleting namespace...')); this.setFormStatusMessage('info', t('Deleting namespace...'));
await axios.delete(`/namespaces/rest/namespaces/${this.nsId}`); await axios.delete(`/namespaces/rest/namespaces/${this.state.nsId}`);
this.navigateToWithFlashMessage('/namespaces', 'success', t('Namespace deleted')); this.navigateToWithFlashMessage('/namespaces', 'success', t('Namespace deleted'));
@ -194,12 +198,11 @@ export default class CUD extends Component {
render() { render() {
const t = this.props.t; const t = this.props.t;
const edit = this.props.edit; const edit = this.props.edit;
const deleteConfirmationShown = this.state.deleteConfirmationShown;
return ( return (
<div> <div>
{!this.isEditGlobal() && !this.hasChildren && edit && {!this.isEditGlobal() && !this.hasChildren && edit &&
<ModalDialog hidden={!deleteConfirmationShown} title={t('Confirm deletion')} onCloseAsync={::this.hideDeleteModal} buttons={[ <ModalDialog hidden={!this.isDelete()} title={t('Confirm deletion')} onCloseAsync={::this.hideDeleteModal} buttons={[
{ label: t('No'), className: 'btn-primary', onClickAsync: ::this.hideDeleteModal }, { label: t('No'), className: 'btn-primary', onClickAsync: ::this.hideDeleteModal },
{ label: t('Yes'), className: 'btn-danger', onClickAsync: ::this.performDelete } { label: t('Yes'), className: 'btn-danger', onClickAsync: ::this.performDelete }
]}> ]}>

View file

@ -21,12 +21,11 @@ const getStructure = t => ({
children: { children: {
'edit' : { 'edit' : {
title: t('Edit Namespace'), title: t('Edit Namespace'),
params: [':nsId'], params: [':nsId', ':action?'],
render: props => (<CUD edit {...props} />) render: props => (<CUD edit {...props} />)
}, },
'create' : { 'create' : {
title: t('Create Namespace'), title: t('Create Namespace'),
link: '/namespaces/create',
render: props => (<CUD {...props} />) render: props => (<CUD {...props} />)
} }
} }