Feature: #89061 - Introduce Notification Actions

See forge#89061

Description

Notifications rendered by the TYPO3/CMS/Backend/Notification module are now able to render action buttons. Each notification method (info(), success() etc) accepts an array of actions, each action is described by a label and a pre-defined action type, containing a callback.

However, notifications flagged with a duration will still disappear, unless an action is taken.

Example:

require([
  'TYPO3/CMS/Backend/ActionButton/ImmediateAction',
  'TYPO3/CMS/Backend/ActionButton/DeferredAction',
  'TYPO3/CMS/Backend/Notification'
], function(ImmediateAction, DeferredAction, Notification) {
  const immediateActionCallback = new ImmediateAction(function () { /* your action code */ });
  Notification.info(
    'Great! We are almost done here...',
    'Common default settings have been applied based on your previous input.',
    0,
    [
      {label: 'Show settings', action: immediateActionCallback}
    ]
  );
});
Copied!

ImmediateAction

An action of type ImmediateAction (TYPO3/CMS/Backend/ActionButtons/ImmediateAction) is executed directly on click and closes the notification. This action type is suitable for e.g. linking to a backend module.

The class accepts a callback method executing very simple logic.

Example:

const immediateActionCallback = new ImmediateAction(function () {
  require(['TYPO3/CMS/Backend/ModuleMenu'], function (ModuleMenu) {
    ModuleMenu.App.showModule('web_layout');
  });
});
Copied!

DeferredAction

An action of type DeferredAction (TYPO3/CMS/Backend/ActionButtons/DeferredAction) is recommended when a long-lasting task is executed, e.g. an AJAX request.

This class accepts a callback method which must return either a resolved or rejected promise.

The DeferredAction replaces the action button with a spinner icon to indicate a task will take some time. It's still possible to dismiss a notification, which will not stop the execution.

Example:

const deferredActionCallback = new DeferredAction(function () {
  const myAction = async function() {
    return await 'something';
  }

  return myAction();
});

const anotherDeferredActionCallback = new DeferredAction(function () {
  // do some old-fashioned jQuery stuff
  return Promise.resolve($.ajax(/* AJAX configuration */));
});
Copied!