Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds notification for closed confirmation modal #4150

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ describe('Compound Container Tests', () => {
cy.on('window:confirm', (str) => {
expect(str).to.equal('Are you sure you want to do this?');
});
expect(stub.getCall(0)).to.be.calledWith('LuigiClient.uxManager().showConfirmationModal()');
expect(stub.getCall(0)).to.be.calledWith('LuigiClient.uxManager().showConfirmationModal() - confirmed');
});
});

Expand Down
2 changes: 1 addition & 1 deletion container/cypress/e2e/test-app/wc/wc-container.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ describe('Web Container Test', () => {
cy.on('window:confirm', (str) => {
expect(str).to.equal('Are you sure you want to do this?');
});
expect(stub.getCall(0)).to.be.calledWith('LuigiClient.uxManager().showConfirmationModal()');
expect(stub.getCall(0)).to.be.calledWith('LuigiClient.uxManager().showConfirmationModal() - confirmed');
});
});

Expand Down
14 changes: 14 additions & 0 deletions container/public/dist/custom-elements.json
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,13 @@
"text": "Event"
}
},
{
"name": "close-confirmation-modal-request",
"description": "Event passed to the micro frontend when confirmation modal is closed.",
"type": {
"text": "Event"
}
},
{
"name": "show-loading-indicator-request",
"description": "Event fired when the micro frontend requests to show a loading indicator.",
Expand Down Expand Up @@ -721,6 +728,13 @@
"text": "Event"
}
},
{
"name": "close-confirmation-modal-request",
"description": "Event passed to the micro frontend when confirmation modal is closed.",
"type": {
"text": "Event"
}
},
{
"name": "show-loading-indicator-request",
"description": "Event fired when the micro frontend requests to show a loading indicator.",
Expand Down
14 changes: 13 additions & 1 deletion container/src/LuigiContainer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
updateViewUrl = notInitFn('updateViewUrl');
closeAlert = notInitFn('closeAlert');
notifyAlertClosed = notInitFn('notifyAlertClosed');
notifyConfirmationModalClosed = notInitFn('notifyConfirmationModalClosed');
attributeChangedCallback(name, oldValue, newValue) {
if (this.containerInitialized) {
if (name === 'context') {
Expand Down Expand Up @@ -147,7 +148,7 @@
};

thisComponent.closeAlert = (id: string, dismissKey?: string) => {
thisComponent.notifyAlertClosed(id, dismissKey);
thisComponent.notifyAlertClosed(id, dismissKey);
};

thisComponent.notifyAlertClosed = (id: string, dismissKey?: string) => {
Expand All @@ -161,6 +162,17 @@
}
}

thisComponent.notifyConfirmationModalClosed = (result) => {
// check if thisComponent is in dom
if (thisComponent.isConnected) {
if (webcomponent) {
webcomponentService.notifyConfirmationModalClosed(!!result);
} else {
ContainerAPI.notifyConfirmationModalClosed(!!result, iframeHandle);
}
}
}

containerService.registerContainer(thisComponent);
webcomponentService.thisComponent = thisComponent;

Expand Down
10 changes: 10 additions & 0 deletions container/src/api/container-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ export class ContainerAPIFunctions {
const message = dismissKey ? { id, dismissKey } : { id };
containerService.sendCustomMessageToIframe(iframeHandle, message, LuigiInternalMessageID.ALERT_CLOSED);
}

/**
* Send a message to the microfrontend notifying the modal has been closed
* @param modalResult the result of the modal being closed
* @param iframeHandle the handle of the iframe to send the message to (optional)
*/
notifyConfirmationModalClosed = (modalResult: boolean, iframeHandle?: IframeHandle) => {
const message = { data: { confirmed: modalResult } };
containerService.sendCustomMessageToIframe(iframeHandle, message, LuigiInternalMessageID.CONFIRMATION_MODAL_CLOSED);
};
}

export const ContainerAPI = new ContainerAPIFunctions();
5 changes: 5 additions & 0 deletions container/src/constants/communication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export namespace Events {
*/
export const SHOW_CONFIRMATION_MODAL_REQUEST = 'show-confirmation-modal-request';

/**
* Event passed to the micro frontend when confirmation modal is closed.
*/
export const CONFIRMATION_MODAL_CLOSED = 'close-confirmation-modal-request';

/**
* Event fired when the micro frontend requests to show a loading indicator.
*/
Expand Down
4 changes: 4 additions & 0 deletions container/src/constants/internal-communication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export namespace LuigiInternalMessageID {
* A message emmitted from the Microfrontend when a request to show an confirmation modal is sent
*/
export const SHOW_CONFIRMATION_MODAL_REQUEST = 'luigi.ux.confirmationModal.show';
/**
* A message sent to the microfrontend to notify closing of a particular confirmation modal
*/
export const CONFIRMATION_MODAL_CLOSED = 'luigi.ux.confirmationModal.hide';
/**
* A message emmitted from the Microfrontend when a request to show loading indicator is sent
*/
Expand Down
3 changes: 3 additions & 0 deletions container/src/services/container.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ export class ContainerService {
case LuigiInternalMessageID.SHOW_CONFIRMATION_MODAL_REQUEST:
this.dispatch(Events.SHOW_CONFIRMATION_MODAL_REQUEST, targetCnt, event.data.data);
break;
case LuigiInternalMessageID.CONFIRMATION_MODAL_CLOSED:
this.dispatch(Events.CONFIRMATION_MODAL_CLOSED, targetCnt, event.data.data);
break;
case LuigiInternalMessageID.SHOW_LOADING_INDICATOR_REQUEST:
this.dispatch(Events.SHOW_LOADING_INDICATOR_REQUEST, targetCnt, event);
break;
Expand Down
14 changes: 13 additions & 1 deletion container/src/services/webcomponents.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {
export class WebComponentService {
containerService: ContainerService;
thisComponent: ContainerElement;
alertResolvers: Record<string, Function> = {};
alertResolvers: Record<string, (value: unknown) => void> = {};
alertIndex = 0;

constructor() {
Expand Down Expand Up @@ -725,4 +725,16 @@ export class WebComponentService {
console.log('Promise is not in the list.');
}
}

/**
* Responsible for notifying the microfrontend when modal has been closed
*
* @param {boolean} confirmed the result of the modal being closed
*
* @returns {void}
*
*/
notifyConfirmationModalClosed(confirmed = true) {
this.dispatchLuigiEvent(Events.CONFIRMATION_MODAL_CLOSED, { confirmed });
}
}
3 changes: 3 additions & 0 deletions container/test-app/compound/compoundClientAPI.html
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ <h3>
}
},
);
compoundContainer.addEventListener(MFEventID.CONFIRMATION_MODAL_CLOSED, (event) => {
console.log(MFEventID.CONFIRMATION_MODAL_CLOSED, event);
});
compoundContainer.addEventListener(
MFEventID.RUNTIME_ERROR_HANDLING_REQUEST,
(event) => {
Expand Down
8 changes: 7 additions & 1 deletion container/test-app/compound/helloWorldWC.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,15 @@ export default class extends HTMLElement {
.showConfirmationModal(settings)
.then(() => {
this.LuigiClient.uxManager().showAlert({
text: 'LuigiClient.uxManager().showConfirmationModal()',
text: 'LuigiClient.uxManager().showConfirmationModal() - confirmed',
type: 'info'
});
})
.catch(() => {
this.LuigiClient.uxManager().showAlert({
text: 'LuigiClient.uxManager().showConfirmationModal() - dissmissed',
type: 'warning'
});
});
});
}
Expand Down
11 changes: 8 additions & 3 deletions container/test-app/iframe/iframeContainer.html
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,14 @@ <h3>

luigiContainer.addEventListener(Events.SHOW_CONFIRMATION_MODAL_REQUEST, (event) => {
console.log(Events.SHOW_CONFIRMATION_MODAL_REQUEST, event);
alert(
'show-confirmation-modal message received: ' + JSON.stringify(event.detail),
);
const data = event.detail;
const val = confirm(data.body);
alert('show-confirmation-modal message received: ' + JSON.stringify(data));
luigiContainer.notifyConfirmationModalClosed(val);
});

luigiContainer.addEventListener(Events.CONFIRMATION_MODAL_CLOSED, (event) => {
console.log(Events.CONFIRMATION_MODAL_CLOSED, event);
});

luigiContainer.addEventListener(Events.SHOW_LOADING_INDICATOR_REQUEST, (event) => {
Expand Down
6 changes: 5 additions & 1 deletion container/test-app/iframe/microfrontend.html
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ <h1 id="title">Multi purpose demo page</h1>
buttonConfirm: 'Yes',
buttonDismiss: 'No',
};
LuigiClient.uxManager().showConfirmationModal(settings);

LuigiClient.uxManager()
.showConfirmationModal(settings)
.then(() => console.log('Modal confirmed'))
.catch(() => console.log('Modal dissmissed'));
}

function testShowLoadingIndicator() {
Expand Down
4 changes: 4 additions & 0 deletions container/test-app/wc/clientAPI.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,12 @@ <h3>
if (event.callback) {
event.callback(val);
}
luigiContainer.notifyConfirmationModalClosed(val);
},
);
luigiContainer.addEventListener(MFEventID.CONFIRMATION_MODAL_CLOSED, (event) => {
console.log(MFEventID.CONFIRMATION_MODAL_CLOSED, event);
});
luigiContainer.addEventListener(MFEventID.CUSTOM_MESSAGE, (event) => {
if (event.detail.id !== 'timer') {
alert(event.detail.data);
Expand Down
8 changes: 7 additions & 1 deletion container/test-app/wc/helloWorldWC.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,15 @@ export default class extends HTMLElement {
.showConfirmationModal(settings)
.then(() => {
this.LuigiClient.uxManager().showAlert({
text: 'LuigiClient.uxManager().showConfirmationModal()',
text: 'LuigiClient.uxManager().showConfirmationModal() - confirmed',
type: 'info'
});
})
.catch(() => {
this.LuigiClient.uxManager().showAlert({
text: 'LuigiClient.uxManager().showConfirmationModal() - dissmissed',
type: 'warning'
});
});
});
}
Expand Down
21 changes: 19 additions & 2 deletions container/test/api/container-api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ describe('Container Service', () => {
describe('closeAlert', () => {
const containerAPI = new ContainerAPIFunctions();

it('internal method properly called', () => {
it('notifyAlertClosed method properly called', () => {
// mock and spy
const id = 'some-id';
const dismissKey = 'key';
Expand All @@ -219,7 +219,7 @@ describe('Container Service', () => {
expect(spy).toHaveBeenCalledWith(iframeHandle, { id, dismissKey }, LuigiInternalMessageID.ALERT_CLOSED);
});

it('internal method properly called if no dismisskey', () => {
it('notifyAlertClosed method properly called if no dismisskey', () => {
// mock and spy
const id = 'some-id';
const iframeHandle = {
Expand All @@ -234,6 +234,23 @@ describe('Container Service', () => {
});
});

describe('notifyConfirmationModalClosed', () => {
const containerAPI = new ContainerAPIFunctions();

it.each([true, false])('notifyConfirmationModalClosed method properly called', (result) => {
// mock and spy
const iframeHandle = {
data: 'test'
} as unknown as IframeHandle;
containerService.sendCustomMessageToIframe = jest.fn();
const spy = jest.spyOn(containerService, 'sendCustomMessageToIframe');

containerAPI.notifyConfirmationModalClosed(result, iframeHandle);

expect(spy).toHaveBeenCalledWith(iframeHandle, { data: { confirmed: result } }, LuigiInternalMessageID.CONFIRMATION_MODAL_CLOSED);
});
});

describe('sendCustomMessage', () => {
const containerAPI = new ContainerAPIFunctions();

Expand Down
16 changes: 16 additions & 0 deletions container/test/services/webcomponents.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1800,3 +1800,19 @@ describe('resolveAlert', () => {
consoleSpy.mockRestore();
});
});

describe('notifyConfirmationModalClosed', () => {
it.each([true, false])('should dispatch LuigiEvent with modal result', (confirmed) => {
const service = new WebComponentService();

// mock and spy on functions
service.containerService.dispatch = jest.fn();
const dispatchEventSpy = jest.spyOn(service, 'dispatchLuigiEvent');

// act
service.notifyConfirmationModalClosed(confirmed);

// assert
expect(dispatchEventSpy).toHaveBeenCalledWith(Events.CONFIRMATION_MODAL_CLOSED, { confirmed });
});
});
5 changes: 5 additions & 0 deletions container/typings/constants/events.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export namespace Events {
*/
export const SHOW_CONFIRMATION_MODAL_REQUEST = 'show-confirmation-modal-request';

/**
* Event passed to the micro frontend when confirmation modal is closed.
*/
export const CONFIRMATION_MODAL_CLOSED = 'close-confirmation-modal-request';

/**
* Event fired when the micro frontend requests to show a loading indicator.
*/
Expand Down