UNPKG

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
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==