-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Description
Currently, the canLeave function determines whether it is possible to leave the entity master or the entity centre. The canLeave function is invoked whenever an exit from the entity master or entity centre occurs (for example, when closing the dialog, navigating between compound menu items, navigating between entities in the EGI with an open entity master, or switching between alternative views in the entity centre).
The current implementation of the canLeave function in the entity master checks whether the entity is dirty. As a result of this check, a toast notification may be displayed to the user stating: "Please save or cancel changes." In the entity centre, the canLeave function checks whether the EGI or alternative views can be left and returns the appropriate value.
The canLeave function provides a way for developers to customize the entity master closing logic. To empower the user with these capabilities, the following steps should be taken:
-
1. Introduce an
ICustomisableCanLeaveinterface to be implemented by functional entities. This interface should define the following methods:-
boolean canLeave()to indicate whether the entity master represented by the functional entity can be left. -
String cannotLeaveReason()to return a message explaining to the user why the entity master cannot be left and prompting them chose of the available actions. -
CanLeaveOption canLeaveOption()to provide a set of available options for the user to choose whether to leave without taking further action or to cancel the leave attempt entirely. At the moment only 2 alternatives are envisaged, but more may be added in the future (CanLeaveOptioncan be an enum):YES_NO_CANCEL— this option is applicable to situations where there is an underlying entity with unsaved changes; three buttons with specific roles are required in this case:
Yes– indicates that the user wants to leave the entity master and save any changes to the underlying entity.
No– indicates that the user wants to leave the entity master without saving any change the underlying entity.
Cancel– indicates that the user does not want to leave the entity master in order to review the change.YES_NO— this options is applicable to situations where the underlying entity cannot be changed (e.g. master with centre), but the business logic determines that the attempt to leave the master is premature, and the user should do something on that master before leaving it; two buttons with specific roles are required in this case:
Yes– indicates that the user wants to leave the entity master regardless of the reason returned bycannotLeaveReason().
No– indicates that the user does not want to leave the entity master.
-
-
2. Enhance the JS method
canLeave, so that it presents a prompt dialog the default configurationYES_NO_CANCLE. This issue item is plaaned for future. -
3. Enhance the JS method
canLeave, so that it saves the entity if the action entity representing the master implementsICustomisableCanLeave, and uses the result of the save action to determine whether the master can be left based on the result ofboolean canLeave(), and if not — display a prompt dialog with the message returned bycannotLeaveReasonand the option returned bycanLeaveOption. -
4. Make the JS method
canLeaveasynchronous, and update all places where this method is invoked to handle the asynchronous behavior accordingly. -
5. Implement each set of buttons and their roles that correspond to options
YES_NO_CANCELandYES_NO.
Change overview
The changes introduced in this issue enable developers to provide custom logic when leaving an entity master. This logic can be customised by enhancing an entity with the ICustomisableCanLeave interface and implementing the save method in the corresponding companion object.
For Developers
When a user leaves or closes an entity master, the standard canLeave logic checks whether the entity supports custom leave logic. If supported, the customCanLeave method implemented in tg-entity-master-behaviour is invoked. This method sends an AJAX request to the server.
Because this operation is asynchronous, the standard canLeave method must also be asynchronous. Consequently, all methods that invoke canLeave must either:
- Be asynchronous, or
- Properly handle the
Promisereturned bycanLeave.
When overriding canLeave, developers must ensure that:
- A resolved Promise is returned if the user is allowed to leave the entity master.
- A rejected Promise is returned if the user is not allowed to leave.
Server-Side Behaviour and Authorisation
The server resource handling the AJAX request sent by customCanLeave invokes the save method of the corresponding companion object.
The save method is typically annotated with @Authorise. If the user is not authorised to invoke this method, an authorisation error is thrown, preventing the user from leaving the entity master. This behaviour is not always desirable.
To allow users to leave an entity master even if they are not authorised to save it, developers should:
- Remove the
@Authoriseannotation from thesavemethod. - Implement authorisation logic manually inside the method.
This ensures that no errors are thrown when an unauthorised user attempts to leave the entity master.
Detecting Leave vs Save Actions
To determine whether the save method was invoked due to a leave action or a normal save operation, developers should check the leaveReason property of the entity passed to the save method.
- If
leaveReasonis empty, the method was invoked due to a normal save action. - If
leaveReasonis present, the method was invoked because the user is leaving the entity master.
The leaveReason property may have one of the following values:
-
CLOSED— indicates that the user closed the entity master. This may occur when:- Closing the dialog containing the entity master, or
- Navigating to another entity.
-
NAVIGATED— indicates that the user navigated away from the menu item containing the entity master.
Example Implementation
@Override
@SessionRequired
public <EntityType> save(final <EntityType> entity) {
final Result authorisationResult = authModel.authorise(<EntityType>.class);
if (entity.leaveReason().isPresent()) {
if (!authorisationResult.isSuccessful()) {
entity.setCanLeave(true);
} else {
// Custom can-leave logic:
// Set required properties to determine whether the user can leave.
// Also set the reason why the user cannot leave and required actions.
}
} else if (!authorisationResult.isSuccessful()) {
throw authorisationResult;
}
return super.save(entity);
}Expected outcome
The canLeave method becomes customizable and controlled by server-side logic rather than just client-side, allowing functional entities to define leave behavior and present confirmation dialogs with appropriate options to the user.
Future work
- Enhancing the
canLeavemethod to prompt the user to decide whether to save changes or not has revealed another issue related to continuations. Since continuation execution is represented bytg-ui-action, it does not return aPromisethat can be passed back to thecloseDialogmethod in thetg-custom-action-dialogelement. As a result, the dialog containing the master that triggered the continuation during the save process is closed before the continuation is executed.
This behavior should be investigated and handled properly to ensure that the dialog is not closed until all continuations have been fully executed.