Mosaico upgraded to 0.17.5
Work started on confirmation dialogs displayed when one navigates from a page with unsaved changes
This commit is contained in:
parent
4f77272042
commit
48dcf2c701
399 changed files with 4032 additions and 77702 deletions
|
@ -331,11 +331,41 @@ class PanelRoute extends Component {
|
|||
}
|
||||
|
||||
|
||||
export class BeforeUnloadListeners {
|
||||
constructor() {
|
||||
this.listeners = new Set();
|
||||
}
|
||||
|
||||
register(listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
deregister(listener) {
|
||||
this.listeners.delete(listener);
|
||||
}
|
||||
|
||||
shouldUnloadBeCancelled() {
|
||||
for (const lst of this.listeners) {
|
||||
if (lst.handler()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async shouldUnloadBeCancelledAsync() {
|
||||
for (const lst of this.listeners) {
|
||||
if (await lst.handlerAsync()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@withRouter
|
||||
@withComponentMixins([
|
||||
withTranslation,
|
||||
withErrorHandling
|
||||
])
|
||||
], ['onNavigationConfirmationDialog'])
|
||||
export class SectionContent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -348,6 +378,10 @@ export class SectionContent extends Component {
|
|||
// noinspection JSIgnoredPromiseFromCall
|
||||
this.closeFlashMessage();
|
||||
});
|
||||
|
||||
this.beforeUnloadListeners = new BeforeUnloadListeners();
|
||||
this.beforeUnloadHandler = ::this.onBeforeUnload;
|
||||
this.historyUnblock = null;
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
|
@ -355,6 +389,34 @@ export class SectionContent extends Component {
|
|||
root: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
onBeforeUnload(event) {
|
||||
if (this.beforeUnloadListeners.shouldUnloadBeCancelled()) {
|
||||
event.preventDefault();
|
||||
event.returnValue = '';
|
||||
}
|
||||
}
|
||||
|
||||
onNavigationConfirmationDialog(message, callback) {
|
||||
this.beforeUnloadListeners.shouldUnloadBeCancelledAsync().then(res => {
|
||||
if (res) {
|
||||
const allowTransition = window.confirm(message);
|
||||
callback(allowTransition);
|
||||
} else {
|
||||
callback(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('beforeunload', this.beforeUnloadHandler);
|
||||
this.historyUnblock = this.props.history.block('Changes you made may not be saved. Are you sure you want to leave this page?');
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('beforeunload', this.beforeUnloadHandler);
|
||||
this.historyUnblock();
|
||||
}
|
||||
|
||||
setFlashMessage(severity, text) {
|
||||
this.setState({
|
||||
flashMessageText: text,
|
||||
|
@ -381,6 +443,14 @@ export class SectionContent extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
registerBeforeUnloadHandlers(handlers) {
|
||||
this.beforeUnloadListeners.register(handlers);
|
||||
}
|
||||
|
||||
deregisterBeforeUnloadHandlers(handlers) {
|
||||
this.beforeUnloadListeners.deregister(handlers);
|
||||
}
|
||||
|
||||
errorHandler(error) {
|
||||
if (error instanceof interoperableErrors.NotLoggedInError) {
|
||||
if (window.location.pathname !== '/login') { // There may be multiple async requests failing at the same time. So we take the pathname only from the first one.
|
||||
|
@ -440,6 +510,8 @@ export class SectionContent extends Component {
|
|||
export class Section extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.getUserConfirmationHandler = ::this.onGetUserConfirmation;
|
||||
this.sectionContent = null;
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
|
@ -447,6 +519,10 @@ export class Section extends Component {
|
|||
root: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
onGetUserConfirmation(message, callback) {
|
||||
this.sectionContent.onNavigationConfirmationDialog(message, callback);
|
||||
}
|
||||
|
||||
render() {
|
||||
let structure = this.props.structure;
|
||||
if (typeof structure === 'function') {
|
||||
|
@ -454,8 +530,8 @@ export class Section extends Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<Router basename={getBaseDir()}>
|
||||
<SectionContent root={this.props.root} structure={structure} />
|
||||
<Router basename={getBaseDir()} getUserConfirmation={this.getUserConfirmationHandler}>
|
||||
<SectionContent wrappedComponentRef={node => this.sectionContent = node} root={this.props.root} structure={structure} />
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue