gentics-ui-core
Version:
This is the common core framework for the Gentics CMS and Mesh UI, and other Angular applications.
266 lines • 31.2 kB
JavaScript
import { ComponentFactoryResolver, Injectable, Optional, SkipSelf } from '@angular/core';
import { OverlayHostService } from '../overlay-host/overlay-host.service';
import { DynamicModalWrapper } from './dynamic-modal-wrapper.component';
import { ModalDialog } from './modal-dialog.component';
import { BlankModal } from './blank-modal.component';
import * as i0 from "@angular/core";
import * as i1 from "../overlay-host/overlay-host.service";
/**
* A promise-based service for creating modal windows and dialogs.
* Depends on the [`<gtx-overlay-host>`](#/overlay-host) being present in the app.
*
* ## Return Values
* All the public methods return the `IModalInstance` object:
*
* ```
* interface IModalInstance {
* instance: IModalDialog;
* element: HTMLElement;
* open: () => Promise<any>;
* }
* ```
* Calling the `open()` method returns a promise which will be resolved when the modal is closed
* or rejected when a button is set to `shouldReject` or the modal calls the passed error handler.
*
* ## `.dialog()`
* To create a basic dialog modal, use the `.dialog()` method. This accepts an `IDialogConfig` object:
*
* ```TypeScript
* interface IDialogConfig {
* title: string;
* body?: string;
* buttons: {
* label: string;
* type?: 'default' | 'secondary' | 'success'| 'warning' | 'alert';
* flat?: boolean;
* // If specified, will be returned as the
* // value of the resolved promise (or the reason if rejected).
* returnValue?: any;
* // If true, clicking the button will cause
* // the promise to reject rather than resolve
* shouldReject?: boolean;
* }[];
* ```
*
* Example:
* ```TypeScript
* modalService.dialog({
* title: 'Are you sure?',
* body: 'Do you <em>really</em> want to delete this thing?',
* buttons: [
* { label: 'Delete', type: 'alert', returnValue: true },
* { label: 'Cancel', type: 'secondary', shouldReject: true }
* ]
* }).then(modal => modal.open())
* .then(result => console.log('deleting...'))
* .catch(() => console.log('cancelled');
* ```
*
* ## `.fromComponent()`
* For more complex modals, a component can be passed to the `.fromComponent()` method which will then be
* placed inside a modal window. The component must implement the IModalDialog interface, which allows the
* ModalService to hook into a `closeFn` & `cancelFn` so it knows to close the modal and resolve the promise.
* To forward errors from the modal to the caller, implement `registerErrorFn` from the IModalDialog interface.
*
* Example:
* ```TypeScript
* @Component({
* selector: 'my-modal-form',
* template: '...' // some big form
* })
* export class MyModalForm implements IModalDialog {
* // IModalDialog interface members
* closeFn: (val: any) => void;
* cancelFn: (val?: any) => void;
* registerCloseFn(close: (val: any) => void): void {
* this.closeFn = close;
* }
* registerCancelFn(cancel: (val?: any) => void): void {
* this.cancelFn = cancel;
* }
*
* someLocalVariable: string;
*
* // Bound to the form's submit event.
* onSubmitClick() : void {
* this.closeFn(this.form.value);
* }
*
* // Bound to the "cancel" button in the template
* onCancelClick(): void {
* this.cancelFn();
* }
* }
* ```
* The above component could then be used as follows:
* ```TypeScript
* modalService.fromComponent(MyModalForm, {}, { someLocalVariable: 'foo' })
* .then(modal => modal.open())
* .then(result => console.log(result));
* ```
*
* ## Modal Options
* All public methods take an optional options parameter to describe the behavior and appearance of the modal window
* itself:
* ```TypeScript
* interface IModalOptions {
* onOpen?: Function;
* onClose?: Function;
* closeOnOverlayClick?: boolean;
* closeOnEscape?: boolean;
* width?: string;
* padding?: boolean;
* modalBodyClass?: string;
* }
* ```
*/
export class ModalService {
constructor(componentFactoryResolver, overlayHostService, _parentModalService = null) {
this.componentFactoryResolver = componentFactoryResolver;
this._parentModalService = _parentModalService;
this.openModalComponents = [];
this.getHostViewContainer = () => overlayHostService.getHostView();
}
/**
* Returns an array of ComponentRefs for each currently-opened modal.
*/
get openModals() {
return this._parentModalService ? this._parentModalService.openModals : this.openModalComponents;
}
/**
* Create a new modal instance containing the specified component, optionally specifying "locals" which
* will be defined on the component instance with the given value.
*/
fromComponent(component, options, locals) {
let modal = this.wrapComponentInModal(component, options, locals);
return Promise.resolve(modal);
}
/**
* Create a new modal by appending the elementRef to a blank modal window. Primarily used internally
* for the implementation of the declarative [Modal](#/modal) component.
*/
fromElement(elementRef, options) {
return this.wrapComponentInModal(BlankModal, options)
.then(modal => {
modal.element.appendChild(elementRef.nativeElement);
return modal;
});
}
/**
* Creates and displays a standard modal dialog.
*/
dialog(config, options) {
return this.wrapComponentInModal(ModalDialog, options)
.then(modal => {
modal.instance.setConfig(config);
return modal;
});
}
wrapComponentInModal(component, options, locals) {
return this.createModalWrapper(options)
.then(modalWrapper => {
const componentRef = modalWrapper.injectContent(component);
const dialog = componentRef.instance;
if (locals !== undefined) {
for (let key in locals) {
dialog[key] = locals[key];
}
componentRef.changeDetectorRef.markForCheck();
}
this.checkModalDialogInterface(dialog);
return {
instance: dialog,
element: componentRef.location.nativeElement,
open: () => {
this.invokeOnOpenCallback(options);
this.openModals.push(componentRef);
componentRef.onDestroy(() => {
const index = this.openModals.indexOf(componentRef);
if (-1 < index) {
this.openModals.splice(index, 1);
}
});
modalWrapper.open();
return this.createPromiseFromDialog(modalWrapper, dialog);
}
};
});
}
/**
* Ensure that the component passed in implements IModalDialog.
*/
checkModalDialogInterface(dialog) {
const conforms = typeof dialog.registerCancelFn === 'function' && typeof dialog.registerCloseFn === 'function';
if (!conforms) {
throw new Error('ModalService#wrapComponentInModal(): Component must implement IModalDialog.');
}
}
/**
* Creates the DynamicModalWrapper in place in the DOM and returns a reference to the
* created component.
*/
createModalWrapper(options) {
return this.getHostViewContainer()
.then(hostViewContainer => {
let modalFactoryFactory = this.componentFactoryResolver.resolveComponentFactory(DynamicModalWrapper);
if (!hostViewContainer) {
throw new Error('No OverlayHost present, add a <gtx-overlay-host> element!');
}
const ref = hostViewContainer.createComponent(modalFactoryFactory);
return this.getConfiguredModalWrapper(ref, options);
});
}
/**
* Decorate the ModalWrapper instance with the dismissFn and return that instance.
*/
getConfiguredModalWrapper(wrapperComponentRef, options) {
let modalWrapper = wrapperComponentRef.instance;
modalWrapper.dismissFn = () => {
this.invokeOnCloseCallback(options);
wrapperComponentRef.destroy();
};
modalWrapper.setOptions(options);
return modalWrapper;
}
/**
* Returns a promise which is bound to the closeFn and cancelFn of the dialog instance,
* and will be resolved/rejected when either of those methods are invoked.
*/
createPromiseFromDialog(modalWrapper, dialog) {
return new Promise((resolve, reject) => {
dialog.registerCloseFn((value) => {
modalWrapper.dismissFn();
resolve(value);
});
dialog.registerCancelFn((value) => {
modalWrapper.dismissFn();
});
if (dialog.registerErrorFn) {
dialog.registerErrorFn((err) => {
reject(err);
modalWrapper.dismissFn();
});
}
});
}
invokeOnOpenCallback(options) {
if (options && options.onOpen && typeof options.onOpen === 'function') {
options.onOpen();
}
}
invokeOnCloseCallback(options) {
if (options && options.onClose && typeof options.onClose === 'function') {
options.onClose();
}
}
}
/** @nocollapse */ ModalService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: ModalService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i1.OverlayHostService }, { token: ModalService, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ ModalService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: ModalService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: ModalService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i1.OverlayHostService }, { type: ModalService, decorators: [{
type: Optional
}, {
type: SkipSelf
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL21vZGFsL21vZGFsLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVILHdCQUF3QixFQUV4QixVQUFVLEVBR1YsUUFBUSxFQUNSLFFBQVEsRUFDWCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSxzQ0FBc0MsQ0FBQztBQUN4RSxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSxtQ0FBbUMsQ0FBQztBQUN0RSxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLHlCQUF5QixDQUFDOzs7QUFHbkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRHRztBQUVILE1BQU0sT0FBTyxZQUFZO0lBWXJCLFlBQW9CLHdCQUFrRCxFQUMxRCxrQkFBc0MsRUFDTixzQkFBb0MsSUFBSTtRQUZoRSw2QkFBd0IsR0FBeEIsd0JBQXdCLENBQTBCO1FBRTFCLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUFaNUUsd0JBQW1CLEdBQWlDLEVBQUUsQ0FBQztRQWEzRCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsR0FBRyxFQUFFLENBQUMsa0JBQWtCLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDdkUsQ0FBQztJQVhEOztPQUVHO0lBQ0gsSUFBVyxVQUFVO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUM7SUFDckcsQ0FB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QWUsQ0FBQyxDQUFDLEtBQVUsRUFBRSxFQUFFO2dCQUNsQyxZQUFZLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3pCLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNuQixDQUFDLENBQUMsQ0FBQztZQUVILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEtBQVUsRUFBRSxFQUFFO2dCQUNuQyxZQUFZLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDN0IsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLE1BQU0sQ0FBQyxlQUFlLEVBQUU7Z0JBQ3hCLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFVLEVBQUUsRUFBRTtvQkFDbEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNaLFlBQVksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDN0IsQ0FBQyxDQUFDLENBQUM7YUFDTjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLG9CQUFvQixDQUFDLE9BQXNCO1FBQy9DLElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxPQUFPLENBQUMsTUFBTSxLQUFLLFVBQVUsRUFBRTtZQUNuRSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDcEI7SUFDTCxDQUFDO0lBRU8scUJBQXFCLENBQUMsT0FBc0I7UUFDaEQsSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sSUFBSSxPQUFPLE9BQU8sQ0FBQyxPQUFPLEtBQUssVUFBVSxFQUFFO1lBQ3JFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNyQjtJQUNMLENBQUM7OzRIQS9KUSxZQUFZLDRGQWM0QyxZQUFZO2dJQWRwRSxZQUFZOzJGQUFaLFlBQVk7a0JBRHhCLFVBQVU7a0lBZTBELFlBQVk7MEJBQWhFLFFBQVE7OzBCQUFJLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIENvbXBvbmVudFJlZixcbiAgICBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgRWxlbWVudFJlZixcbiAgICBJbmplY3RhYmxlLFxuICAgIFZpZXdDb250YWluZXJSZWYsXG4gICAgVHlwZSxcbiAgICBPcHRpb25hbCxcbiAgICBTa2lwU2VsZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7T3ZlcmxheUhvc3RTZXJ2aWNlfSBmcm9tICcuLi9vdmVybGF5LWhvc3Qvb3ZlcmxheS1ob3N0LnNlcnZpY2UnO1xuaW1wb3J0IHtEeW5hbWljTW9kYWxXcmFwcGVyfSBmcm9tICcuL2R5bmFtaWMtbW9kYWwtd3JhcHBlci5jb21wb25lbnQnO1xuaW1wb3J0IHtNb2RhbERpYWxvZ30gZnJvbSAnLi9tb2RhbC1kaWFsb2cuY29tcG9uZW50JztcbmltcG9ydCB7QmxhbmtNb2RhbH0gZnJvbSAnLi9ibGFuay1tb2RhbC5jb21wb25lbnQnO1xuaW1wb3J0IHtJTW9kYWxJbnN0YW5jZSwgSURpYWxvZ0NvbmZpZywgSU1vZGFsRGlhbG9nLCBJTW9kYWxPcHRpb25zfSBmcm9tICcuL21vZGFsLWludGVyZmFjZXMnO1xuXG4vKipcbiAqIEEgcHJvbWlzZS1iYXNlZCBzZXJ2aWNlIGZvciBjcmVhdGluZyBtb2RhbCB3aW5kb3dzIGFuZCBkaWFsb2dzLlxuICogRGVwZW5kcyBvbiB0aGUgW2A8Z3R4LW92ZXJsYXktaG9zdD5gXSgjL292ZXJsYXktaG9zdCkgYmVpbmcgcHJlc2VudCBpbiB0aGUgYXBwLlxuICpcbiAqICMjIFJldHVybiBWYWx1ZXNcbiAqIEFsbCB0aGUgcHVibGljIG1ldGhvZHMgcmV0dXJuIHRoZSBgSU1vZGFsSW5zdGFuY2VgIG9iamVjdDpcbiAqXG4gKiBgYGBcbiAqIGludGVyZmFjZSBJTW9kYWxJbnN0YW5jZSB7XG4gKiAgICAgaW5zdGFuY2U6IElNb2RhbERpYWxvZztcbiAqICAgICBlbGVtZW50OiBIVE1MRWxlbWVudDtcbiAqICAgICBvcGVuOiAoKSA9PiBQcm9taXNlPGFueT47XG4gKiB9XG4gKiBgYGBcbiAqIENhbGxpbmcgdGhlIGBvcGVuKClgIG1ldGhvZCByZXR1cm5zIGEgcHJvbWlzZSB3aGljaCB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIG1vZGFsIGlzIGNsb3NlZFxuICogb3IgcmVqZWN0ZWQgd2hlbiBhIGJ1dHRvbiBpcyBzZXQgdG8gYHNob3VsZFJlamVjdGAgb3IgdGhlIG1vZGFsIGNhbGxzIHRoZSBwYXNzZWQgZXJyb3IgaGFuZGxlci5cbiAqXG4gKiAjIyBgLmRpYWxvZygpYFxuICogVG8gY3JlYXRlIGEgYmFzaWMgZGlhbG9nIG1vZGFsLCB1c2UgdGhlIGAuZGlhbG9nKClgIG1ldGhvZC4gVGhpcyBhY2NlcHRzIGFuIGBJRGlhbG9nQ29uZmlnYCBvYmplY3Q6XG4gKlxuICogYGBgVHlwZVNjcmlwdFxuICogaW50ZXJmYWNlIElEaWFsb2dDb25maWcge1xuICogICB0aXRsZTogc3RyaW5nO1xuICogICBib2R5Pzogc3RyaW5nO1xuICogICBidXR0b25zOiB7XG4gKiAgICAgICBsYWJlbDogc3RyaW5nO1xuICogICAgICAgdHlwZT86ICdkZWZhdWx0JyB8ICdzZWNvbmRhcnknIHwgJ3N1Y2Nlc3MnfCAnd2FybmluZycgfCAnYWxlcnQnO1xuICogICAgICAgZmxhdD86IGJvb2xlYW47XG4gKiAgICAgICAvLyBJZiBzcGVjaWZpZWQsIHdpbGwgYmUgcmV0dXJuZWQgYXMgdGhlXG4gKiAgICAgICAvLyB2YWx1ZSBvZiB0aGUgcmVzb2x2ZWQgcHJvbWlzZSAob3IgdGhlIHJlYXNvbiBpZiByZWplY3RlZCkuXG4gKiAgICAgICByZXR1cm5WYWx1ZT86IGFueTtcbiAqICAgICAgIC8vIElmIHRydWUsIGNsaWNraW5nIHRoZSBidXR0b24gd2lsbCBjYXVzZVxuICogICAgICAgLy8gdGhlIHByb21pc2UgdG8gcmVqZWN0IHJhdGhlciB0aGFuIHJlc29sdmVcbiAqICAgICAgIHNob3VsZFJlamVjdD86IGJvb2xlYW47XG4gKiB9W107XG4gKiBgYGBcbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgVHlwZVNjcmlwdFxuICogbW9kYWxTZXJ2aWNlLmRpYWxvZyh7XG4gKiAgIHRpdGxlOiAnQXJlIHlvdSBzdXJlPycsXG4gKiAgIGJvZHk6ICdEbyB5b3UgPGVtPnJlYWxseTwvZW0+IHdhbnQgdG8gZGVsZXRlIHRoaXMgdGhpbmc/JyxcbiAqICAgYnV0dG9uczogW1xuICogICAgIHsgbGFiZWw6ICdEZWxldGUnLCB0eXBlOiAnYWxlcnQnLCByZXR1cm5WYWx1ZTogdHJ1ZSB9LFxuICogICAgIHsgbGFiZWw6ICdDYW5jZWwnLCB0eXBlOiAnc2Vjb25kYXJ5Jywgc2hvdWxkUmVqZWN0OiB0cnVlIH1cbiAqICAgXVxuICogfSkudGhlbihtb2RhbCA9PiBtb2RhbC5vcGVuKCkpXG4gKiAgIC50aGVuKHJlc3VsdCA9PiBjb25zb2xlLmxvZygnZGVsZXRpbmcuLi4nKSlcbiAqICAgLmNhdGNoKCgpID0+IGNvbnNvbGUubG9nKCdjYW5jZWxsZWQnKTtcbiAqIGBgYFxuICpcbiAqICMjIGAuZnJvbUNvbXBvbmVudCgpYFxuICogRm9yIG1vcmUgY29tcGxleCBtb2RhbHMsIGEgY29tcG9uZW50IGNhbiBiZSBwYXNzZWQgdG8gdGhlIGAuZnJvbUNvbXBvbmVudCgpYCBtZXRob2Qgd2hpY2ggd2lsbCB0aGVuIGJlXG4gKiBwbGFjZWQgaW5zaWRlIGEgbW9kYWwgd2luZG93LiBUaGUgY29tcG9uZW50IG11c3QgaW1wbGVtZW50IHRoZSBJTW9kYWxEaWFsb2cgaW50ZXJmYWNlLCB3aGljaCBhbGxvd3MgdGhlXG4gKiBNb2RhbFNlcnZpY2UgdG8gaG9vayBpbnRvIGEgYGNsb3NlRm5gICYgYGNhbmNlbEZuYCBzbyBpdCBrbm93cyB0byBjbG9zZSB0aGUgbW9kYWwgYW5kIHJlc29sdmUgdGhlIHByb21pc2UuXG4gKiBUbyBmb3J3YXJkIGVycm9ycyBmcm9tIHRoZSBtb2RhbCB0byB0aGUgY2FsbGVyLCBpbXBsZW1lbnQgYHJlZ2lzdGVyRXJyb3JGbmAgZnJvbSB0aGUgSU1vZGFsRGlhbG9nIGludGVyZmFjZS5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgVHlwZVNjcmlwdFxuICogQENvbXBvbmVudCh7XG4gKiAgIHNlbGVjdG9yOiAnbXktbW9kYWwtZm9ybScsXG4gKiAgIHRlbXBsYXRlOiAnLi4uJyAvLyBzb21lIGJpZyBmb3JtXG4gKiB9KVxuICogZXhwb3J0IGNsYXNzIE15TW9kYWxGb3JtIGltcGxlbWVudHMgSU1vZGFsRGlhbG9nIHtcbiAqICAgLy8gSU1vZGFsRGlhbG9nIGludGVyZmFjZSBtZW1iZXJzXG4gKiAgIGNsb3NlRm46ICh2YWw6IGFueSkgPT4gdm9pZDtcbiAqICAgY2FuY2VsRm46ICh2YWw/OiBhbnkpID0+IHZvaWQ7XG4gKiAgIHJlZ2lzdGVyQ2xvc2VGbihjbG9zZTogKHZhbDogYW55KSA9PiB2b2lkKTogdm9pZCB7XG4gKiAgICAgICB0aGlzLmNsb3NlRm4gPSBjbG9zZTtcbiAqICAgfVxuICogICByZWdpc3RlckNhbmNlbEZuKGNhbmNlbDogKHZhbD86IGFueSkgPT4gdm9pZCk6IHZvaWQge1xuICogICAgICAgdGhpcy5jYW5jZWxGbiA9IGNhbmNlbDtcbiAqICAgfVxuICpcbiAqICAgc29tZUxvY2FsVmFyaWFibGU6IHN0cmluZztcbiAqXG4gKiAgIC8vIEJvdW5kIHRvIHRoZSBmb3JtJ3Mgc3VibWl0IGV2ZW50LlxuICogICBvblN1Ym1pdENsaWNrKCkgOiB2b2lkIHtcbiAqICAgICAgdGhpcy5jbG9zZUZuKHRoaXMuZm9ybS52YWx1ZSk7XG4gKiAgIH1cbiAqXG4gKiAgIC8vIEJvdW5kIHRvIHRoZSBcImNhbmNlbFwiIGJ1dHRvbiBpbiB0aGUgdGVtcGxhdGVcbiAqICAgb25DYW5jZWxDbGljaygpOiB2b2lkIHtcbiAqICAgICAgdGhpcy5jYW5jZWxGbigpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqIFRoZSBhYm92ZSBjb21wb25lbnQgY291bGQgdGhlbiBiZSB1c2VkIGFzIGZvbGxvd3M6XG4gKiBgYGBUeXBlU2NyaXB0XG4gKiBtb2RhbFNlcnZpY2UuZnJvbUNvbXBvbmVudChNeU1vZGFsRm9ybSwge30sIHsgc29tZUxvY2FsVmFyaWFibGU6ICdmb28nIH0pXG4gKiAgIC50aGVuKG1vZGFsID0+IG1vZGFsLm9wZW4oKSlcbiAqICAgLnRoZW4ocmVzdWx0ID0+IGNvbnNvbGUubG9nKHJlc3VsdCkpO1xuICogYGBgXG4gKlxuICogIyMgTW9kYWwgT3B0aW9uc1xuICogQWxsIHB1YmxpYyBtZXRob2RzIHRha2UgYW4gb3B0aW9uYWwgb3B0aW9ucyBwYXJhbWV0ZXIgdG8gZGVzY3JpYmUgdGhlIGJlaGF2aW9yIGFuZCBhcHBlYXJhbmNlIG9mIHRoZSBtb2RhbCB3aW5kb3dcbiAqIGl0c2VsZjpcbiAqIGBgYFR5cGVTY3JpcHRcbiAqIGludGVyZmFjZSBJTW9kYWxPcHRpb25zIHtcbiAqICAgICBvbk9wZW4/OiBGdW5jdGlvbjtcbiAqICAgICBvbkNsb3NlPzogRnVuY3Rpb247XG4gKiAgICAgY2xvc2VPbk92ZXJsYXlDbGljaz86IGJvb2xlYW47XG4gKiAgICAgY2xvc2VPbkVzY2FwZT86IGJvb2xlYW47XG4gKiAgICAgd2lkdGg/OiBzdHJpbmc7XG4gKiAgICAgcGFkZGluZz86IGJvb2xlYW47XG4gKiAgICAgbW9kYWxCb2R5Q2xhc3M/OiBzdHJpbmc7XG4gKiB9XG4gKiBgYGBcbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE1vZGFsU2VydmljZSB7XG5cbiAgICBwcml2YXRlIG9wZW5Nb2RhbENvbXBvbmVudHM6IENvbXBvbmVudFJlZjxJTW9kYWxEaWFsb2c+W10gPSBbXTtcbiAgICBwcml2YXRlIGdldEhvc3RWaWV3Q29udGFpbmVyOiAoKSA9PiBQcm9taXNlPFZpZXdDb250YWluZXJSZWY+O1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBhcnJheSBvZiBDb21wb25lbnRSZWZzIGZvciBlYWNoIGN1cnJlbnRseS1vcGVuZWQgbW9kYWwuXG4gICAgICovXG4gICAgcHVibGljIGdldCBvcGVuTW9kYWxzKCk6IENvbXBvbmVudFJlZjxJTW9kYWxEaWFsb2c+W10ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcGFyZW50TW9kYWxTZXJ2aWNlID8gdGhpcy5fcGFyZW50TW9kYWxTZXJ2aWNlLm9wZW5Nb2RhbHMgOiB0aGlzLm9wZW5Nb2RhbENvbXBvbmVudHM7XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb21wb25lbnRGYWN0b3J5UmVzb2x2ZXI6IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcixcbiAgICAgICAgICAgICAgICBvdmVybGF5SG9zdFNlcnZpY2U6IE92ZXJsYXlIb3N0U2VydmljZSxcbiAgICAgICAgICAgICAgICBAT3B0aW9uYWwoKSBAU2tpcFNlbGYoKSBwcml2YXRlIF9wYXJlbnRNb2RhbFNlcnZpY2U6IE1vZGFsU2VydmljZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5nZXRIb3N0Vmlld0NvbnRhaW5lciA9ICgpID0+IG92ZXJsYXlIb3N0U2VydmljZS5nZXRIb3N0VmlldygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBtb2RhbCBpbnN0YW5jZSBjb250YWluaW5nIHRoZSBzcGVjaWZpZWQgY29tcG9uZW50LCBvcHRpb25hbGx5IHNwZWNpZnlpbmcgXCJsb2NhbHNcIiB3aGljaFxuICAgICAqIHdpbGwgYmUgZGVmaW5lZCBvbiB0aGUgY29tcG9uZW50IGluc3RhbmNlIHdpdGggdGhlIGdpdmVuIHZhbHVlLlxuICAgICAqL1xuICAgIHB1YmxpYyBmcm9tQ29tcG9uZW50PFQgZXh0ZW5kcyBJTW9kYWxEaWFsb2c+KGNvbXBvbmVudDogVHlwZTxUPixcbiAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zPzogSU1vZGFsT3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbHM/OiB7IFtLIGluIGtleW9mIFRdPzogVFtLXSB9KTogUHJvbWlzZTxJTW9kYWxJbnN0YW5jZTxUPj4ge1xuICAgICAgICBsZXQgbW9kYWwgPSB0aGlzLndyYXBDb21wb25lbnRJbk1vZGFsKGNvbXBvbmVudCwgb3B0aW9ucywgbG9jYWxzKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShtb2RhbCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbmV3IG1vZGFsIGJ5IGFwcGVuZGluZyB0aGUgZWxlbWVudFJlZiB0byBhIGJsYW5rIG1vZGFsIHdpbmRvdy4gUHJpbWFyaWx5IHVzZWQgaW50ZXJuYWxseVxuICAgICAqIGZvciB0aGUgaW1wbGVtZW50YXRpb24gb2YgdGhlIGRlY2xhcmF0aXZlIFtNb2RhbF0oIy9tb2RhbCkgY29tcG9uZW50LlxuICAgICAqL1xuICAgIHB1YmxpYyBmcm9tRWxlbWVudChlbGVtZW50UmVmOiBFbGVtZW50UmVmLCBvcHRpb25zPzogSU1vZGFsT3B0aW9ucyk6IFByb21pc2U8SU1vZGFsSW5zdGFuY2U8QmxhbmtNb2RhbD4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JhcENvbXBvbmVudEluTW9kYWwoQmxhbmtNb2RhbCwgb3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKG1vZGFsID0+IHtcbiAgICAgICAgICAgICAgICBtb2RhbC5lbGVtZW50LmFwcGVuZENoaWxkKGVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vZGFsO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbmQgZGlzcGxheXMgYSBzdGFuZGFyZCBtb2RhbCBkaWFsb2cuXG4gICAgICovXG4gICAgcHVibGljIGRpYWxvZyhjb25maWc6IElEaWFsb2dDb25maWcsIG9wdGlvbnM/OiBJTW9kYWxPcHRpb25zKTogUHJvbWlzZTxJTW9kYWxJbnN0YW5jZTxNb2RhbERpYWxvZz4+IHtcbiAgICAgICByZXR1cm4gdGhpcy53cmFwQ29tcG9uZW50SW5Nb2RhbChNb2RhbERpYWxvZywgb3B0aW9ucylcbiAgICAgICAgICAgLnRoZW4obW9kYWwgPT4ge1xuICAgICAgICAgICAgICAgbW9kYWwuaW5zdGFuY2Uuc2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICAgICAgICAgICByZXR1cm4gbW9kYWw7XG4gICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgd3JhcENvbXBvbmVudEluTW9kYWw8VCBleHRlbmRzIElNb2RhbERpYWxvZz4oY29tcG9uZW50OiBUeXBlPFQ+LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucz86IElNb2RhbE9wdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbHM/OiB7IFtrZXk6IHN0cmluZ106IGFueSB9KTogUHJvbWlzZTxJTW9kYWxJbnN0YW5jZTxUPj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVNb2RhbFdyYXBwZXI8VD4ob3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKG1vZGFsV3JhcHBlciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29tcG9uZW50UmVmID0gbW9kYWxXcmFwcGVyLmluamVjdENvbnRlbnQoY29tcG9uZW50KTtcbiAgICAgICAgICAgICAgICBjb25zdCBkaWFsb2cgPSBjb21wb25lbnRSZWYuaW5zdGFuY2U7XG4gICAgICAgICAgICAgICAgaWYgKGxvY2FscyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiBsb2NhbHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICg8YW55PiBkaWFsb2cpW2tleV0gPSBsb2NhbHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRSZWYuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tNb2RhbERpYWxvZ0ludGVyZmFjZShkaWFsb2cpO1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGluc3RhbmNlOiBkaWFsb2cgYXMgYW55LFxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBjb21wb25lbnRSZWYubG9jYXRpb24ubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgb3BlbjogKCk6IFByb21pc2U8YW55PiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9rZU9uT3BlbkNhbGxiYWNrKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVuTW9kYWxzLnB1c2goY29tcG9uZW50UmVmKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFJlZi5vbkRlc3Ryb3koKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5vcGVuTW9kYWxzLmluZGV4T2YoY29tcG9uZW50UmVmKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoLTEgPCBpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW5Nb2RhbHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZGFsV3JhcHBlci5vcGVuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVQcm9taXNlRnJvbURpYWxvZyhtb2RhbFdyYXBwZXIsIGRpYWxvZyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5zdXJlIHRoYXQgdGhlIGNvbXBvbmVudCBwYXNzZWQgaW4gaW1wbGVtZW50cyBJTW9kYWxEaWFsb2cuXG4gICAgICovXG4gICAgcHJpdmF0ZSBjaGVja01vZGFsRGlhbG9nSW50ZXJmYWNlKGRpYWxvZzogSU1vZGFsRGlhbG9nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbmZvcm1zID0gdHlwZW9mIGRpYWxvZy5yZWdpc3RlckNhbmNlbEZuID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkaWFsb2cucmVnaXN0ZXJDbG9zZUZuID09PSAnZnVuY3Rpb24nO1xuICAgICAgICBpZiAoIWNvbmZvcm1zKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vZGFsU2VydmljZSN3cmFwQ29tcG9uZW50SW5Nb2RhbCgpOiBDb21wb25lbnQgbXVzdCBpbXBsZW1lbnQgSU1vZGFsRGlhbG9nLicpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgRHluYW1pY01vZGFsV3JhcHBlciBpbiBwbGFjZSBpbiB0aGUgRE9NIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZVxuICAgICAqIGNyZWF0ZWQgY29tcG9uZW50LlxuICAgICAqL1xuICAgIHByaXZhdGUgY3JlYXRlTW9kYWxXcmFwcGVyPFQgZXh0ZW5kcyBJTW9kYWxEaWFsb2c+KG9wdGlvbnM/OiBJTW9kYWxPcHRpb25zKTogUHJvbWlzZTxEeW5hbWljTW9kYWxXcmFwcGVyPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEhvc3RWaWV3Q29udGFpbmVyKClcbiAgICAgICAgICAgIC50aGVuKGhvc3RWaWV3Q29udGFpbmVyID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgbW9kYWxGYWN0b3J5RmFjdG9yeSA9IHRoaXMuY29tcG9uZW50RmFjdG9yeVJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KER5bmFtaWNNb2RhbFdyYXBwZXIpO1xuICAgICAgICAgICAgICAgIGlmICghaG9zdFZpZXdDb250YWluZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBPdmVybGF5SG9zdCBwcmVzZW50LCBhZGQgYSA8Z3R4LW92ZXJsYXktaG9zdD4gZWxlbWVudCEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgcmVmID0gaG9zdFZpZXdDb250YWluZXIuY3JlYXRlQ29tcG9uZW50KG1vZGFsRmFjdG9yeUZhY3RvcnkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldENvbmZpZ3VyZWRNb2RhbFdyYXBwZXIocmVmLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlY29yYXRlIHRoZSBNb2RhbFdyYXBwZXIgaW5zdGFuY2Ugd2l0aCB0aGUgZGlzbWlzc0ZuIGFuZCByZXR1cm4gdGhhdCBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBwcml2YXRlIGdldENvbmZpZ3VyZWRNb2RhbFdyYXBwZXI8VCBleHRlbmRzIElNb2RhbERpYWxvZz4od3JhcHBlckNvbXBvbmVudFJlZjogQ29tcG9uZW50UmVmPER5bmFtaWNNb2RhbFdyYXBwZXI+LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zPzogSU1vZGFsT3B0aW9ucyk6IER5bmFtaWNNb2RhbFdyYXBwZXIge1xuICAgICAgICBsZXQgbW9kYWxXcmFwcGVyID0gd3JhcHBlckNvbXBvbmVudFJlZi5pbnN0YW5jZTtcbiAgICAgICAgbW9kYWxXcmFwcGVyLmRpc21pc3NGbiA9ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW52b2tlT25DbG9zZUNhbGxiYWNrKG9wdGlvbnMpO1xuICAgICAgICAgICAgd3JhcHBlckNvbXBvbmVudFJlZi5kZXN0cm95KCk7XG4gICAgICAgIH07XG4gICAgICAgIG1vZGFsV3JhcHBlci5zZXRPcHRpb25zKG9wdGlvbnMpO1xuICAgICAgICByZXR1cm4gbW9kYWxXcmFwcGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBwcm9taXNlIHdoaWNoIGlzIGJvdW5kIHRvIHRoZSBjbG9zZUZuIGFuZCBjYW5jZWxGbiBvZiB0aGUgZGlhbG9nIGluc3RhbmNlLFxuICAgICAqIGFuZCB3aWxsIGJlIHJlc29sdmVkL3JlamVjdGVkIHdoZW4gZWl0aGVyIG9mIHRob3NlIG1ldGhvZHMgYXJlIGludm9rZWQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBjcmVhdGVQcm9taXNlRnJvbURpYWxvZzxUIGV4dGVuZHMgSU1vZGFsRGlhbG9nPihtb2RhbFdyYXBwZXI6IER5bmFtaWNNb2RhbFdyYXBwZXIsIGRpYWxvZzogSU1vZGFsRGlhbG9nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGRpYWxvZy5yZWdpc3RlckNsb3NlRm4oKHZhbHVlOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBtb2RhbFdyYXBwZXIuZGlzbWlzc0ZuKCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZGlhbG9nLnJlZ2lzdGVyQ2FuY2VsRm4oKHZhbHVlOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBtb2RhbFdyYXBwZXIuZGlzbWlzc0ZuKCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKGRpYWxvZy5yZWdpc3RlckVycm9yRm4pIHtcbiAgICAgICAgICAgICAgICBkaWFsb2cucmVnaXN0ZXJFcnJvckZuKChlcnI6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICBtb2RhbFdyYXBwZXIuZGlzbWlzc0ZuKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW52b2tlT25PcGVuQ2FsbGJhY2sob3B0aW9uczogSU1vZGFsT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLm9uT3BlbiAmJiB0eXBlb2Ygb3B0aW9ucy5vbk9wZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIG9wdGlvbnMub25PcGVuKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGludm9rZU9uQ2xvc2VDYWxsYmFjayhvcHRpb25zOiBJTW9kYWxPcHRpb25zKTogdm9pZCB7XG4gICAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMub25DbG9zZSAmJiB0eXBlb2Ygb3B0aW9ucy5vbkNsb3NlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBvcHRpb25zLm9uQ2xvc2UoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==