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

Modal loading indicator and close Modal event #1578

Merged
merged 15 commits into from
Aug 26, 2020
Merged
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
6 changes: 6 additions & 0 deletions client/luigi-client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ export declare interface UxManager {
*/
hideLoadingIndicator: () => void;

/**
* Closes the currently opened micro frontend modal.
* @memberof uxManager
*/
closeCurrentModal: () => void;

/**
* This method informs the main application that there are unsaved changes in the current view in the iframe. For example, that can be a view with form fields which were edited but not submitted.
* @param {boolean} isDirty indicates if there are any unsaved changes on the current page or in the component
Expand Down
9 changes: 9 additions & 0 deletions client/src/uxManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ class UxManager extends LuigiClientBase {
hideLoadingIndicator() {
helpers.sendPostMessageToLuigiCore({ msg: 'luigi.hide-loading-indicator' });
}

/**
* Closes the currently opened micro frontend modal.
* @memberof uxManager
*/
closeCurrentModal() {
helpers.sendPostMessageToLuigiCore({ msg: 'luigi.close-modal' });
}

/**
* Adds a backdrop to block the top and side navigation. It is based on the Fundamental UI Modal, which you can use in your micro frontend to achieve the same behavior.
* @memberof uxManager
Expand Down
86 changes: 83 additions & 3 deletions core/src/Modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,42 @@ <h3 class="fd-dialog__title">{modalSettings.title}</h3>
<div class="fd-dialog__body">
<div class="iframeModalCtn"></div>
</div>
{#if showLoadingIndicator}
<div
in:fade="{{delay: 250, duration: 250}}"
out:fade="{{duration: 250}}"
class="fd-page spinnerContainer"
aria-hidden="false"
aria-label="Loading"
>
<div
class="fd-busy-indicator--m"
aria-hidden="false"
aria-label="Loading"
data-testid="luigi-loading-spinner"
>
<div class="fd-busy-indicator--circle-0"></div>
<div class="fd-busy-indicator--circle-1"></div>
<div class="fd-busy-indicator--circle-2"></div>
</div>
</div>
{/if}
</div>
</div>

<script>
import { afterUpdate, createEventDispatcher } from 'svelte';

import {
afterUpdate,
createEventDispatcher,
onMount,
onDestroy
} from 'svelte';
import { fade } from 'svelte/transition';
const dispatch = createEventDispatcher();

import { Navigation } from './navigation/services/navigation';
import {
EventListenerHelpers,
GenericHelpers,
IframeHelpers,
RoutingHelpers
Expand All @@ -44,6 +70,8 @@ <h3 class="fd-dialog__title">{modalSettings.title}</h3>
let nodeObject;
let pathData;
let nodeParams;
let iframeCreated = false;
let showLoadingIndicator = true;

const prepareNodeData = async path => {
const pathUrlRaw =
Expand All @@ -61,6 +89,9 @@ <h3 class="fd-dialog__title">{modalSettings.title}</h3>
};

const getNode = async path => {
if (iframeCreated) {
return;
}
if (isDataPrepared) {
const iframe = createIframeModal(nodeObject.viewUrl, {
context: pathData.context,
Expand All @@ -71,6 +102,7 @@ <h3 class="fd-dialog__title">{modalSettings.title}</h3>
modalIframe: iframe,
modalIframeData: { ...pathData, nodeParams }
});
iframeCreated = true;
} else {
await prepareNodeData(path);
}
Expand Down Expand Up @@ -112,6 +144,38 @@ <h3 class="fd-dialog__title">{modalSettings.title}</h3>
getNode(nodepath);
});

const onMessage = async e => {
if ('luigi.show-loading-indicator' === e.data.msg) {
showLoadingIndicator = true;
}

if ('luigi.hide-loading-indicator' === e.data.msg) {
showLoadingIndicator = false;
}

if ('luigi.get-context' === e.data.msg) {
const loadingIndicatorAutoHideEnabled =
!nodeObject ||
!nodeObject.loadingIndicator ||
nodeObject.loadingIndicator.hideAutomatically !== false;
if (loadingIndicatorAutoHideEnabled) {
showLoadingIndicator = false;
}
}

if ('luigi.close-modal' === e.data.msg) {
dispatch('close');
}
};

onMount(() => {
EventListenerHelpers.addEventListener('message', onMessage);
});

onDestroy(() => {
EventListenerHelpers.removeEventListener('message', onMessage);
});

// [svelte-upgrade suggestion]
// review these functions and remove unnecessary 'export' keywords
export function handleKeydown(event) {
Expand All @@ -135,7 +199,23 @@ <h3 class="fd-dialog__title">{modalSettings.title}</h3>
border: 0;
position: absolute;
}

.lui-modal-mf {
position: relative;
}
.spinnerContainer {
background: rgba(243, 244, 245, 0.8);
display: flex;
align-items: center;
justify-content: center;
position: absolute;
bottom: 0;
right: 0;
min-width: auto;
min-height: auto;
display: flex;
width: 100%;
height: 100%;
}
.fd-dialog {
&__content {
width: 80%;
Expand Down
7 changes: 7 additions & 0 deletions core/src/utilities/helpers/event-listener-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ class EventListenerHelpersClass {
window.addEventListener(type, listenerFn);
}

removeEventListener(type, listenerFn) {
this.listeners = this.listeners.filter(
l => !(l.type === type && l.listenerFn === listenerFn)
);
window.removeEventListener(type, listenerFn);
}

removeAllEventListeners() {
this.listeners.forEach(l => {
window.removeEventListener(l.type, l.listenerFn);
Expand Down
4 changes: 4 additions & 0 deletions docs/luigi-client-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,10 @@ Adds a backdrop with a loading indicator for the micro frontend frame. This over

Removes the loading indicator. Use it after calling [showLoadingIndicator()](#showLoadingIndicator) or to hide the indicator when you use the [loadingIndicator.hideAutomatically: false](navigation-parameters-reference.md#node-parameters) node configuration.

#### closeCurrentModal

Closes the currently opened micro frontend modal.

#### addBackdrop

Adds a backdrop to block the top and side navigation. It is based on the Fundamental UI Modal, which you can use in your micro frontend to achieve the same behavior.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,27 @@ describe('Modal Microfrontend', () => {
.should('not.be.visible');
});

it(`can be closed by the Luigi client`, () => {
cy.wrap($iframeBody)
.contains('rendered in a modal')
.click();

cy.wrap($iframeBody)
.get('[data-testid=modal-mf]')
.should('be.visible');

cy.get('[data-testid=modal-mf] iframe').then(ifr => {
cy.wrap(ifr[0].contentDocument)
.its('body')
.contains('Close modal')
.click();

cy.wrap($iframeBody)
.get('[data-testid=modal-mf]')
.should('not.be.visible');
});
});

it(`sets proper URL inside iframe`, () => {
cy.wrap($iframeBody)
.contains('rendered in a modal')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ <h1 *ngIf="projectId" class="fd-section__title">
<h1 *ngIf="!projectId" class="fd-section__title">Global Settings</h1>
</div>

<div class="fd-layout-panel">
<div class="fd-layout-panel fd-has-margin-bottom-small">
<div class="fd-layout-panel__header">
<div class="fd-layout-panel__head">
<h3 class="fd-layout-panel__title">
Expand Down Expand Up @@ -92,6 +92,21 @@ <h3 class="fd-layout-panel__title">
</div>
</div>
</div>

<div *ngIf="isModal" class="fd-layout-panel fd-has-margin-bottom-small">
<div class="fd-layout-panel__header">
<div class="fd-layout-panel__head">
<h3 class="fd-layout-panel__title">
LuigiClient Modal
</h3>
</div>
</div>
<div class="fd-layout-panel__body">
<button class="fd-button" (click)="uxManager().closeCurrentModal()">
Close modal
</button>
</div>
</div>
</section>
<section *ngIf="testFeatureToggleActive" class="fd-section">
<div class="fd-layout-panel">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import { Subscription } from 'rxjs';
})
export class SettingsComponent implements OnInit {
public linkManager = linkManager;
public uxManager = uxManager;
projectId: string;
groupId: string;
hasBack: boolean;
isModal: boolean;
nodeParams: NodeParams = null;
callbackValue = 'default value';
lcSubscription: Subscription;
Expand All @@ -44,6 +46,7 @@ export class SettingsComponent implements OnInit {

addInitListener(init => {
this.hasBack = linkManager().hasBack();
this.isModal = uxManager().isModal();
this.nodeParams =
Object.keys(getNodeParams()).length > 0 ? getNodeParams() : null;
let featureToggleList = getActiveFeatureToggles();
Expand Down