@sumaris-net/ngx-components 2.6.4 → 2.6.6-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/doc/changelog.md +6 -0
- package/esm2020/public_api.mjs +12 -2
- package/esm2020/src/app/admin/services/filter/person.filter.mjs +1 -1
- package/esm2020/src/app/admin/services/person.service.mjs +9 -1
- package/esm2020/src/app/admin/users/users.mjs +73 -67
- package/esm2020/src/app/core/account/account.page.mjs +1 -1
- package/esm2020/src/app/core/form/buttons/form-buttons-bar.component.mjs +44 -8
- package/esm2020/src/app/core/form/entity/editor.class.mjs +7 -7
- package/esm2020/src/app/core/form/entity/entity-editor-modal.class.mjs +4 -3
- package/esm2020/src/app/core/form/entity/entity-editor.class.mjs +6 -3
- package/esm2020/src/app/core/form/form.class.mjs +7 -2
- package/esm2020/src/app/core/form/form.utils.mjs +4 -1
- package/esm2020/src/app/core/form/properties/properties.table.mjs +1 -1
- package/esm2020/src/app/core/form/properties/testing/properties-form.test.mjs +2 -2
- package/esm2020/src/app/core/form/text-popover/text-popover.component.mjs +2 -2
- package/esm2020/src/app/core/graphql/graphql.service.mjs +6 -2
- package/esm2020/src/app/core/graphql/graphql.utils.mjs +1 -1
- package/esm2020/src/app/core/home/home.mjs +12 -10
- package/esm2020/src/app/core/install/install-upgrade-card.component.mjs +3 -2
- package/esm2020/src/app/core/menu/menu.component.mjs +80 -171
- package/esm2020/src/app/core/menu/menu.model.mjs +219 -7
- package/esm2020/src/app/core/menu/menu.module.mjs +27 -14
- package/esm2020/src/app/core/menu/menu.service.mjs +610 -11
- package/esm2020/src/app/core/menu/sub-menu-tab.directive.mjs +98 -0
- package/esm2020/src/app/core/menu/testing/menu-other.testing.mjs +48 -0
- package/esm2020/src/app/core/menu/testing/menu.testing.mjs +121 -0
- package/esm2020/src/app/core/menu/testing/menu.testing.module.mjs +79 -0
- package/esm2020/src/app/core/peer/select-peer.modal.mjs +3 -2
- package/esm2020/src/app/core/register/register-confirm.page.mjs +3 -3
- package/esm2020/src/app/core/register/register.form.mjs +21 -19
- package/esm2020/src/app/core/services/account.service.mjs +9 -15
- package/esm2020/src/app/core/services/base-entity-service.class.mjs +1 -1
- package/esm2020/src/app/core/services/base-graphql-service.class.mjs +2 -4
- package/esm2020/src/app/core/services/config.service.mjs +23 -22
- package/esm2020/src/app/core/services/crypto.service.mjs +14 -21
- package/esm2020/src/app/core/services/local-settings.service.mjs +12 -1
- package/esm2020/src/app/core/services/model/account.model.mjs +27 -2
- package/esm2020/src/app/core/services/model/config.model.mjs +1 -1
- package/esm2020/src/app/core/services/model/department.model.mjs +1 -1
- package/esm2020/src/app/core/services/model/entity.decorators.mjs +1 -1
- package/esm2020/src/app/core/services/model/entity.model.mjs +20 -35
- package/esm2020/src/app/core/services/model/filter.model.mjs +3 -1
- package/esm2020/src/app/core/services/model/peer.model.mjs +1 -1
- package/esm2020/src/app/core/services/model/person.model.mjs +5 -1
- package/esm2020/src/app/core/services/model/referential.model.mjs +3 -3
- package/esm2020/src/app/core/services/model/token.model.mjs +1 -1
- package/esm2020/src/app/core/services/model/tree-item-entity.model.mjs +199 -0
- package/esm2020/src/app/core/services/network.service.mjs +12 -8
- package/esm2020/src/app/core/services/network.utils.mjs +1 -1
- package/esm2020/src/app/core/services/platform.service.mjs +15 -16
- package/esm2020/src/app/core/services/storage/entities-storage.service.mjs +10 -10
- package/esm2020/src/app/core/services/testing/referential-filter.model.mjs +1 -1
- package/esm2020/src/app/core/services/validator/local-settings.validator.mjs +3 -3
- package/esm2020/src/app/core/settings/settings.page.mjs +2 -2
- package/esm2020/src/app/core/table/async-table.class.mjs +4 -3
- package/esm2020/src/app/core/table/entities-async-table-datasource.class.mjs +1 -1
- package/esm2020/src/app/core/table/entities-table-datasource.class.mjs +1 -1
- package/esm2020/src/app/core/table/table-select-columns.component.mjs +1 -1
- package/esm2020/src/app/core/table/table.class.mjs +19 -14
- package/esm2020/src/app/core/table/table.utils.mjs +6 -3
- package/esm2020/src/app/core/table/testing/table.testing.mjs +3 -2
- package/esm2020/src/app/shared/audio/audio.mjs +5 -5
- package/esm2020/src/app/shared/capacitor/plugins.mjs +1 -1
- package/esm2020/src/app/shared/dates.mjs +3 -1
- package/esm2020/src/app/shared/debug/debug.component.mjs +1 -1
- package/esm2020/src/app/shared/directives/autofocus.directive.mjs +5 -4
- package/esm2020/src/app/shared/directives/drag-and-drop.directive.mjs +1 -1
- package/esm2020/src/app/shared/directives/ng-var.directive.mjs +1 -1
- package/esm2020/src/app/shared/directives/resizable/resizable.directive.mjs +1 -1
- package/esm2020/src/app/shared/events.mjs +2 -1
- package/esm2020/src/app/shared/file/csv.utils.mjs +12 -14
- package/esm2020/src/app/shared/file/file.utils.mjs +2 -2
- package/esm2020/src/app/shared/file/images.utils.mjs +2 -2
- package/esm2020/src/app/shared/file/json.utils.mjs +3 -3
- package/esm2020/src/app/shared/file/uri.utils.mjs +2 -1
- package/esm2020/src/app/shared/form/field.component.mjs +28 -3
- package/esm2020/src/app/shared/forms.mjs +48 -30
- package/esm2020/src/app/shared/functions.mjs +7 -2
- package/esm2020/src/app/shared/geolocation/geolocation.utils.mjs +1 -1
- package/esm2020/src/app/shared/help/help.modal.mjs +1 -1
- package/esm2020/src/app/shared/image/gallery/image-gallery.component.mjs +9 -6
- package/esm2020/src/app/shared/image/gallery/testing/gallegry.model.testing.mjs +1 -1
- package/esm2020/src/app/shared/image/gallery/testing/gallery.service.testing.mjs +1 -1
- package/esm2020/src/app/shared/image/gallery/testing/gallery.testing.mjs +2 -2
- package/esm2020/src/app/shared/image/gallery/testing/gallery.testing.module.mjs +1 -1
- package/esm2020/src/app/shared/interceptors/progess.interceptor.mjs +1 -1
- package/esm2020/src/app/shared/logging/logger.model.mjs +1 -1
- package/esm2020/src/app/shared/logging/logging-service.class.mjs +2 -2
- package/esm2020/src/app/shared/logging/logging-service.config.mjs +1 -1
- package/esm2020/src/app/shared/material/autocomplete/material.autocomplete.mjs +10 -10
- package/esm2020/src/app/shared/material/autocomplete/material.autocomplete.utils.mjs +4 -6
- package/esm2020/src/app/shared/material/autocomplete/testing/autocomplete.test.mjs +1 -1
- package/esm2020/src/app/shared/material/badge/badge.directive.mjs +8 -3
- package/esm2020/src/app/shared/material/badge/badge.test.mjs +2 -2
- package/esm2020/src/app/shared/material/chips/material.chips.mjs +9 -10
- package/esm2020/src/app/shared/material/chips/testing/chips.test.mjs +3 -3
- package/esm2020/src/app/shared/material/datetime/material.date.mjs +2 -2
- package/esm2020/src/app/shared/material/datetime/material.dateshort.mjs +3 -3
- package/esm2020/src/app/shared/material/datetime/material.datetime.mjs +3 -3
- package/esm2020/src/app/shared/material/datetime/testing/mat-date-time.test.mjs +1 -1
- package/esm2020/src/app/shared/material/datetime/testing/mat-date.test.mjs +1 -1
- package/esm2020/src/app/shared/material/datetime/testing/mat-dateshort.test.mjs +1 -1
- package/esm2020/src/app/shared/material/duration/material.duration.mjs +3 -3
- package/esm2020/src/app/shared/material/latlong/material.latlong.mjs +5 -4
- package/esm2020/src/app/shared/material/latlong/testing/latlong.test.mjs +1 -1
- package/esm2020/src/app/shared/material/material.animations.mjs +41 -2
- package/esm2020/src/app/shared/material/material.testing.module.mjs +2 -2
- package/esm2020/src/app/shared/material/numpad/testing/numpad.test.mjs +1 -1
- package/esm2020/src/app/shared/material/swipe/testing/swipe.test.mjs +1 -1
- package/esm2020/src/app/shared/modules.mjs +2 -1
- package/esm2020/src/app/shared/named-filter/named-filter.model.mjs +1 -1
- package/esm2020/src/app/shared/observables.mjs +3 -2
- package/esm2020/src/app/shared/pipes/colors.pipe.mjs +3 -1
- package/esm2020/src/app/shared/pipes/date-format.pipe.mjs +1 -1
- package/esm2020/src/app/shared/pipes/form.pipes.mjs +1 -1
- package/esm2020/src/app/shared/pipes/property.pipes.mjs +1 -1
- package/esm2020/src/app/shared/pipes/translate-context.pipe.mjs +1 -1
- package/esm2020/src/app/shared/platforms.mjs +1 -1
- package/esm2020/src/app/shared/services/memory-entity-service.class.mjs +3 -1
- package/esm2020/src/app/shared/services/startable-observable-service.class.mjs +5 -6
- package/esm2020/src/app/shared/services/startable-service.class.mjs +1 -1
- package/esm2020/src/app/shared/services/translate-context.service.mjs +11 -13
- package/esm2020/src/app/shared/services/validator-service.class.mjs +1 -1
- package/esm2020/src/app/shared/shared-routing.module.mjs +2 -1
- package/esm2020/src/app/shared/shared.testing.module.mjs +16 -8
- package/esm2020/src/app/shared/storage/storage-explorer.component.mjs +3 -3
- package/esm2020/src/app/shared/storage/storage-explorer.module.mjs +5 -18
- package/esm2020/src/app/shared/storage/storage-explorer.testing-routing.module.mjs +35 -0
- package/esm2020/src/app/shared/storage/storage-explorer.testing.module.mjs +33 -0
- package/esm2020/src/app/shared/storage/storage.service.mjs +3 -3
- package/esm2020/src/app/shared/storage/storage.utils.mjs +1 -1
- package/esm2020/src/app/shared/testing/observable.test.mjs +2 -2
- package/esm2020/src/app/shared/testing/tests.page.mjs +1 -1
- package/esm2020/src/app/shared/toast/toast.testing.mjs +1 -1
- package/esm2020/src/app/shared/toast/toasts.mjs +2 -2
- package/esm2020/src/app/shared/toolbar/toolbar.mjs +1 -1
- package/esm2020/src/app/shared/upload-file/testing/upload-file.testing.mjs +2 -1
- package/esm2020/src/app/shared/upload-file/upload-file.component.mjs +1 -1
- package/esm2020/src/app/shared/validator/form-error-adapter.class.mjs +5 -5
- package/esm2020/src/app/shared/validator/validators.mjs +10 -3
- package/esm2020/src/app/shared/version/versions.mjs +2 -2
- package/esm2020/src/app/social/job/progression/job-progression.icon.mjs +2 -2
- package/esm2020/src/app/social/job/progression/job-progression.model.mjs +1 -1
- package/esm2020/src/app/social/job/progression/job-progression.service.mjs +1 -1
- package/esm2020/src/app/social/job/testing/job-progression.testing.mjs +1 -1
- package/esm2020/src/app/social/job/testing/job-progression.testing.service.mjs +3 -3
- package/esm2020/src/app/social/message/message.form.mjs +11 -8
- package/esm2020/src/app/social/message/message.modal.mjs +1 -1
- package/esm2020/src/app/social/message/message.model.mjs +1 -1
- package/esm2020/src/app/social/message/message.service.mjs +2 -2
- package/esm2020/src/app/social/social.module.mjs +2 -2
- package/esm2020/src/app/social/user-event/testing/user-event.testing.mjs +5 -5
- package/esm2020/src/app/social/user-event/testing/user-event.testing.model.mjs +1 -1
- package/esm2020/src/app/social/user-event/testing/user-event.testing.service.mjs +1 -1
- package/esm2020/src/app/social/user-event/user-event.model.mjs +1 -1
- package/esm2020/src/app/social/user-event/user-event.service.mjs +4 -3
- package/fesm2015/sumaris-net.ngx-components.mjs +2758 -1263
- package/fesm2015/sumaris-net.ngx-components.mjs.map +1 -1
- package/fesm2020/sumaris-net.ngx-components.mjs +2687 -1223
- package/fesm2020/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +8 -9
- package/public_api.d.ts +11 -1
- package/src/app/admin/services/person.service.d.ts +5 -0
- package/src/app/admin/users/users.d.ts +4 -2
- package/src/app/core/form/buttons/form-buttons-bar.component.d.ts +14 -2
- package/src/app/core/form/entity/entity-editor-modal.class.d.ts +1 -0
- package/src/app/core/form/form.class.d.ts +2 -0
- package/src/app/core/form/form.utils.d.ts +4 -1
- package/src/app/core/form/text-popover/text-popover.component.d.ts +2 -1
- package/src/app/core/graphql/graphql.service.d.ts +5 -4
- package/src/app/core/graphql/graphql.utils.d.ts +2 -2
- package/src/app/core/home/home.d.ts +11 -10
- package/src/app/core/install/install-upgrade-card.component.d.ts +3 -2
- package/src/app/core/menu/menu.component.d.ts +29 -26
- package/src/app/core/menu/menu.model.d.ts +123 -6
- package/src/app/core/menu/menu.module.d.ts +8 -4
- package/src/app/core/menu/menu.service.d.ts +76 -5
- package/src/app/core/menu/sub-menu-tab.directive.d.ts +29 -0
- package/src/app/core/menu/testing/menu-other.testing.d.ts +15 -0
- package/src/app/core/menu/testing/menu.testing.d.ts +43 -0
- package/src/app/core/menu/testing/menu.testing.module.d.ts +12 -0
- package/src/app/core/peer/select-peer.modal.d.ts +4 -3
- package/src/app/core/register/register.form.d.ts +3 -2
- package/src/app/core/services/account.service.d.ts +4 -3
- package/src/app/core/services/config.service.d.ts +5 -3
- package/src/app/core/services/crypto.service.d.ts +7 -7
- package/src/app/core/services/local-settings.service.d.ts +1 -0
- package/src/app/core/services/model/account.model.d.ts +7 -1
- package/src/app/core/services/model/entity.model.d.ts +5 -8
- package/src/app/core/services/model/filter.model.d.ts +2 -0
- package/src/app/core/services/model/person.model.d.ts +1 -0
- package/src/app/core/services/model/tree-item-entity.model.d.ts +53 -0
- package/src/app/core/services/network.service.d.ts +4 -3
- package/src/app/core/services/platform.service.d.ts +4 -5
- package/src/app/core/services/storage/entities-storage.service.d.ts +3 -3
- package/src/app/core/settings/settings.page.d.ts +5 -5
- package/src/app/core/table/async-table.class.d.ts +1 -0
- package/src/app/core/table/table.class.d.ts +5 -1
- package/src/app/core/table/testing/table.testing.d.ts +1 -0
- package/src/app/shared/dates.d.ts +2 -0
- package/src/app/shared/events.d.ts +1 -0
- package/src/app/shared/file/uri.utils.d.ts +1 -0
- package/src/app/shared/form/field.component.d.ts +1 -0
- package/src/app/shared/forms.d.ts +4 -1
- package/src/app/shared/functions.d.ts +1 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +1 -0
- package/src/app/shared/material/badge/badge.directive.d.ts +1 -1
- package/src/app/shared/material/datetime/material.dateshort.d.ts +1 -1
- package/src/app/shared/material/latlong/material.latlong.d.ts +1 -0
- package/src/app/shared/material/material.animations.d.ts +2 -0
- package/src/app/shared/modules.d.ts +1 -0
- package/src/app/shared/observables.d.ts +1 -0
- package/src/app/shared/pipes/translate-context.pipe.d.ts +1 -1
- package/src/app/shared/services/memory-entity-service.class.d.ts +2 -0
- package/src/app/shared/services/startable-observable-service.class.d.ts +1 -1
- package/src/app/shared/services/translate-context.service.d.ts +2 -2
- package/src/app/shared/services/validator-service.class.d.ts +1 -0
- package/src/app/shared/shared-routing.module.d.ts +1 -0
- package/src/app/shared/shared.testing.module.d.ts +3 -2
- package/src/app/shared/storage/storage-explorer.component.d.ts +2 -2
- package/src/app/shared/storage/storage-explorer.module.d.ts +5 -8
- package/src/app/shared/storage/storage-explorer.testing-routing.module.d.ts +9 -0
- package/src/app/shared/storage/storage-explorer.testing.module.d.ts +10 -0
- package/src/app/shared/storage/storage.service.d.ts +0 -1
- package/src/app/shared/upload-file/testing/upload-file.testing.d.ts +1 -0
- package/src/app/shared/validator/validators.d.ts +4 -0
- package/src/app/social/user-event/user-event.model.d.ts +1 -2
- package/src/assets/i18n/en-US.json +1 -0
- package/src/assets/i18n/en.json +1 -0
- package/src/assets/i18n/fr.json +10 -1
- package/src/assets/manifest.json +1 -1
- package/src/theme/_ngx-components.scss +2 -1
|
@@ -1,13 +1,72 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
import { BehaviorSubject, Subject } from 'rxjs';
|
|
1
|
+
import { EventEmitter, Inject, Injectable, InjectionToken, Optional } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject, combineLatest, from, merge, mergeMap, Subject } from 'rxjs';
|
|
3
|
+
import { MenuItem, MenuItems } from './menu.model';
|
|
4
|
+
import { NavigationEnd } from '@angular/router';
|
|
5
|
+
import { ENVIRONMENT } from '../../../environments/environment.class';
|
|
6
|
+
import { DateUtils } from '../../shared/dates';
|
|
7
|
+
import { distinctUntilChanged, filter, map, throttleTime } from 'rxjs/operators';
|
|
8
|
+
import { CORE_CONFIG_OPTIONS } from '../services/config/core.config';
|
|
9
|
+
import { isEmptyArray, isNil, isNotEmptyArray, isNotNil, isNotNilOrBlank, toBoolean } from '../../shared/functions';
|
|
10
|
+
import { StartableObservableService } from '../../shared/services/startable-observable-service.class';
|
|
11
|
+
import { firstNotNilPromise } from '../../shared/observables';
|
|
12
|
+
import { TreeItemEntityUtils } from '../services/model/tree-item-entity.model';
|
|
13
|
+
import { AboutModal } from '../about/about.modal';
|
|
3
14
|
import * as i0 from "@angular/core";
|
|
15
|
+
import * as i1 from "../services/local-settings.service";
|
|
16
|
+
import * as i2 from "../services/config.service";
|
|
17
|
+
import * as i3 from "../services/account.service";
|
|
18
|
+
import * as i4 from "@angular/router";
|
|
19
|
+
import * as i5 from "@ionic/angular";
|
|
20
|
+
import * as i6 from "@ngx-translate/core";
|
|
21
|
+
import * as i7 from "../../../environments/environment.class";
|
|
22
|
+
import * as i8 from "./menu.model";
|
|
4
23
|
export const DEFAULT_MENU_SHOW_WHEN = 'lg';
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
24
|
+
export const APP_MENU_ITEMS = new InjectionToken('menuItems');
|
|
25
|
+
export const APP_MENU_OPTIONS = new InjectionToken('menuOptions');
|
|
26
|
+
export class MenuService extends StartableObservableService {
|
|
27
|
+
constructor(settings, configService, accountService, router, modalCtrl, alertController, navController, translate, environment, options, staticItems) {
|
|
28
|
+
super(settings);
|
|
29
|
+
this.settings = settings;
|
|
30
|
+
this.configService = configService;
|
|
31
|
+
this.accountService = accountService;
|
|
32
|
+
this.router = router;
|
|
33
|
+
this.modalCtrl = modalCtrl;
|
|
34
|
+
this.alertController = alertController;
|
|
35
|
+
this.navController = navController;
|
|
36
|
+
this.translate = translate;
|
|
37
|
+
this.environment = environment;
|
|
38
|
+
this.accountChanges = new BehaviorSubject(undefined);
|
|
39
|
+
this.onPinned = new EventEmitter(true);
|
|
40
|
+
this._detachedSubItems = [];
|
|
41
|
+
this._itemCounter = 0;
|
|
42
|
+
this._logPrefix = '[menu-service] ';
|
|
8
43
|
this._$opened = new Subject();
|
|
9
44
|
this._$splitPaneWhen = new BehaviorSubject(DEFAULT_MENU_SHOW_WHEN);
|
|
10
45
|
this._$enabled = new BehaviorSubject(true);
|
|
46
|
+
this._$listenRoute = new BehaviorSubject(false);
|
|
47
|
+
this._options = {
|
|
48
|
+
...options,
|
|
49
|
+
subMenu: {
|
|
50
|
+
disableIcon: false,
|
|
51
|
+
savePinned: true,
|
|
52
|
+
...(options?.subMenu || {}),
|
|
53
|
+
// Force disable on mobile
|
|
54
|
+
enable: options?.subMenu?.enable !== false && !this.settings.mobile,
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
this._$enableSubMenu = new BehaviorSubject(this._options.subMenu.enable);
|
|
58
|
+
this._debug = !environment.production;
|
|
59
|
+
this._detachedSubItems = [];
|
|
60
|
+
this._staticItems = (staticItems || []).map(source => {
|
|
61
|
+
const target = this.fromObject({ static: true, ...source }, { computeId: true, fillParent: true, fillDefaultFromParent: true });
|
|
62
|
+
const detachedItems = TreeItemEntityUtils.deleteRecursively(target, (item) => item.static !== true);
|
|
63
|
+
if (detachedItems?.length) {
|
|
64
|
+
console.debug(this._logPrefix + 'Detached init items', detachedItems);
|
|
65
|
+
detachedItems.forEach(item => this._detachToParent(item));
|
|
66
|
+
this._detachedSubItems.push(...detachedItems);
|
|
67
|
+
}
|
|
68
|
+
return target;
|
|
69
|
+
});
|
|
11
70
|
}
|
|
12
71
|
get opened() {
|
|
13
72
|
return this._$opened.asObservable();
|
|
@@ -18,12 +77,21 @@ export class MenuService {
|
|
|
18
77
|
get enabled() {
|
|
19
78
|
return this._$enabled.asObservable();
|
|
20
79
|
}
|
|
21
|
-
|
|
22
|
-
this._$
|
|
80
|
+
get subMenuEnabled() {
|
|
81
|
+
return this._$enableSubMenu.value;
|
|
82
|
+
}
|
|
83
|
+
get subItems() {
|
|
84
|
+
return (this.data || []).reduce((res, rootElement) => res.concat(rootElement.children), []);
|
|
85
|
+
}
|
|
86
|
+
get _staticSubItems() {
|
|
87
|
+
return (this._staticItems || []).reduce((res, rootElement) => res.concat(rootElement.children), []);
|
|
23
88
|
}
|
|
24
89
|
enable(value) {
|
|
25
90
|
this._$enabled.next(value);
|
|
26
91
|
}
|
|
92
|
+
enableSubMenu(value) {
|
|
93
|
+
this._$enableSubMenu.next(value);
|
|
94
|
+
}
|
|
27
95
|
setSplitPaneShowWhen(value) {
|
|
28
96
|
if (this._$splitPaneWhen.value !== value) {
|
|
29
97
|
this._$splitPaneWhen.next(value);
|
|
@@ -37,19 +105,550 @@ export class MenuService {
|
|
|
37
105
|
this._$splitPaneWhen.next(DEFAULT_MENU_SHOW_WHEN);
|
|
38
106
|
}
|
|
39
107
|
}
|
|
108
|
+
fromObject(source, opts) {
|
|
109
|
+
const target = MenuItem.fromObject(source, { withChildren: false });
|
|
110
|
+
// Compute id if need
|
|
111
|
+
if (opts?.computeId && isNil(target.id))
|
|
112
|
+
target.id = this._computeNewId();
|
|
113
|
+
// Remove icon if disabled
|
|
114
|
+
if (this._options.subMenu.disableIcon) {
|
|
115
|
+
Object.assign(target, { icon: undefined, matIcon: undefined, matSvgIcon: undefined });
|
|
116
|
+
}
|
|
117
|
+
// Recursive
|
|
118
|
+
target.children = (source.children || []).map((json) => this.fromObject(json, { ...opts, fillParent: false }));
|
|
119
|
+
// Fill parent (once, when the full tree is ready)
|
|
120
|
+
if (opts?.fillParent) {
|
|
121
|
+
TreeItemEntityUtils.treeFillParent(target);
|
|
122
|
+
// Fill defaults from the parent (once filled)
|
|
123
|
+
if (opts?.fillDefaultFromParent) {
|
|
124
|
+
TreeItemEntityUtils.visit(target, (item) => {
|
|
125
|
+
if (!item.parent)
|
|
126
|
+
return; // Skip if no parent
|
|
127
|
+
item.parentPath = item.parentPath || item.parent.path;
|
|
128
|
+
item.parentPathParams = item.parentPathParams || item.parent.pathParams;
|
|
129
|
+
item.static = toBoolean(item.static, item.parent.static);
|
|
130
|
+
// Compute path, from parent path + action
|
|
131
|
+
if (!item.path && !!item.action) {
|
|
132
|
+
item.path = item.parent.path;
|
|
133
|
+
item.pathParams = (typeof item.action === 'string') ? { action: item.action } : { actionId: item.id.toString(), actionTitle: item.title };
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return target;
|
|
139
|
+
}
|
|
140
|
+
createSubMenu(source) {
|
|
141
|
+
if (!this.subMenuEnabled)
|
|
142
|
+
return null; // Skip if disabled
|
|
143
|
+
const target = this.fromObject(source);
|
|
144
|
+
// Check if exists
|
|
145
|
+
if (this.started) {
|
|
146
|
+
const existingItem = this._findExistingItem(target);
|
|
147
|
+
if (existingItem)
|
|
148
|
+
return existingItem;
|
|
149
|
+
}
|
|
150
|
+
// Create
|
|
151
|
+
if (isNil(target.id))
|
|
152
|
+
target.id = this._computeNewId();
|
|
153
|
+
return target;
|
|
154
|
+
}
|
|
155
|
+
async addSubMenuItems(sources, opts) {
|
|
156
|
+
if (!this.started)
|
|
157
|
+
await this.ready();
|
|
158
|
+
if (!this.subMenuEnabled)
|
|
159
|
+
return; // Skip
|
|
160
|
+
return sources.map(source => this._addSubMenuItem(this.fromObject(source), opts));
|
|
161
|
+
}
|
|
162
|
+
async addSubMenuItem(item, opts) {
|
|
163
|
+
if (!this.started)
|
|
164
|
+
await this.ready();
|
|
165
|
+
if (!this.subMenuEnabled)
|
|
166
|
+
return; // Skip
|
|
167
|
+
return this._addSubMenuItem(this.fromObject(item), opts);
|
|
168
|
+
}
|
|
169
|
+
async removeSubMenuItems(items) {
|
|
170
|
+
if (!this.started)
|
|
171
|
+
await this.ready();
|
|
172
|
+
return (items || []).map(item => this._removeSubMenuItem(this.fromObject(item)));
|
|
173
|
+
}
|
|
174
|
+
async removeSubMenuItem(item) {
|
|
175
|
+
if (!this.started)
|
|
176
|
+
await this.ready();
|
|
177
|
+
return this._removeSubMenuItem(this.fromObject(item));
|
|
178
|
+
}
|
|
179
|
+
togglePinned(source) {
|
|
180
|
+
const item = (source instanceof MenuItem) ? source : this._findExistingItem(this.fromObject(source));
|
|
181
|
+
// Skip if not found
|
|
182
|
+
if (!item) {
|
|
183
|
+
if (this._debug)
|
|
184
|
+
console.warn(this._logPrefix + `Sub menu {${source.path}} cannot be found - unable to toggle pinned!`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Skip if static
|
|
188
|
+
if (item.static)
|
|
189
|
+
return;
|
|
190
|
+
// Unpinned
|
|
191
|
+
if (item.pinned) {
|
|
192
|
+
item.pinned = false;
|
|
193
|
+
if (!item.detached) {
|
|
194
|
+
this._detachedSubItems = [
|
|
195
|
+
...this._detachedSubItems,
|
|
196
|
+
...this._detachSubMenuItems()
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Pinned
|
|
201
|
+
else {
|
|
202
|
+
item.pinned = true;
|
|
203
|
+
}
|
|
204
|
+
this.onPinned.emit(item);
|
|
205
|
+
}
|
|
206
|
+
async executeAction(event, item) {
|
|
207
|
+
const action = item?.action;
|
|
208
|
+
if (!action)
|
|
209
|
+
return; // skip
|
|
210
|
+
if (typeof action === 'string') {
|
|
211
|
+
switch (action) {
|
|
212
|
+
case 'logout':
|
|
213
|
+
await this.logout();
|
|
214
|
+
break;
|
|
215
|
+
case 'about':
|
|
216
|
+
await this.openAboutModal();
|
|
217
|
+
break;
|
|
218
|
+
case 'expand':
|
|
219
|
+
await this.toggleExpandableItem(item);
|
|
220
|
+
if (item.path) {
|
|
221
|
+
await this.navController.navigateRoot(item.path, {
|
|
222
|
+
queryParams: item.pathParams
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
default: {
|
|
227
|
+
if (item.path) {
|
|
228
|
+
await this.navController.navigateRoot(item.path, {
|
|
229
|
+
queryParams: item.pathParams
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
throw new Error('Unknown action: ' + action);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else if (typeof action === 'function') {
|
|
239
|
+
action(event);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async logout() {
|
|
243
|
+
const translations = await this.translate.instant([
|
|
244
|
+
'AUTH.LOGOUT.CONFIRM_TITLE',
|
|
245
|
+
'AUTH.LOGOUT.CONFIRM_MESSAGE',
|
|
246
|
+
'COMMON.BTN_CANCEL',
|
|
247
|
+
'AUTH.LOGOUT.BTN_CONFIRM',
|
|
248
|
+
]);
|
|
249
|
+
const alert = await this.alertController.create({
|
|
250
|
+
header: translations['AUTH.LOGOUT.CONFIRM_TITLE'],
|
|
251
|
+
message: translations['AUTH.LOGOUT.CONFIRM_MESSAGE'],
|
|
252
|
+
buttons: [
|
|
253
|
+
{
|
|
254
|
+
text: translations['COMMON.BTN_CANCEL'],
|
|
255
|
+
role: 'cancel',
|
|
256
|
+
cssClass: 'secondary',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
text: translations['AUTH.LOGOUT.BTN_CONFIRM'],
|
|
260
|
+
cssClass: 'ion-color-primary',
|
|
261
|
+
handler: () => {
|
|
262
|
+
this.accountService.logout();
|
|
263
|
+
// Back to home
|
|
264
|
+
setTimeout(() => this.navController.navigateRoot('/'), 100);
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
});
|
|
269
|
+
await alert.present();
|
|
270
|
+
}
|
|
271
|
+
async openAboutModal() {
|
|
272
|
+
const modal = await this.modalCtrl.create({ component: AboutModal });
|
|
273
|
+
return modal.present();
|
|
274
|
+
}
|
|
275
|
+
async toggleExpandableItem(item) {
|
|
276
|
+
if (!item.expanded) {
|
|
277
|
+
if (this._debug)
|
|
278
|
+
console.debug(this._logPrefix + 'Expand item', item);
|
|
279
|
+
item.matIcon = 'expand_less';
|
|
280
|
+
// Try to attach some item
|
|
281
|
+
this._detachedSubItems
|
|
282
|
+
.filter(childItem => !!this._findParent(childItem, [item]))
|
|
283
|
+
.forEach(childItem => this._attachMenuToParent(item, childItem));
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
item.matIcon = 'expand_more';
|
|
287
|
+
this._detachedSubItems = [
|
|
288
|
+
...this._detachedSubItems,
|
|
289
|
+
...this._detachSubMenuItems({ path: '/', params: {} }, item.children)
|
|
290
|
+
];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
40
293
|
_markAsOpened() {
|
|
41
294
|
this._$opened.next(true);
|
|
42
295
|
}
|
|
43
296
|
_markAsClosed() {
|
|
44
297
|
this._$opened.next(false);
|
|
45
298
|
}
|
|
299
|
+
async ngOnStart() {
|
|
300
|
+
console.info(`${this._logPrefix}Starting...`);
|
|
301
|
+
// Restore sub items from settings
|
|
302
|
+
await this.settings.ready();
|
|
303
|
+
const settingsSubItems = this.settings.getPageSettings('menu', 'sub-items');
|
|
304
|
+
if (isNotEmptyArray(settingsSubItems)) {
|
|
305
|
+
console.debug(this._logPrefix + 'Restoring pinned items from settings...', settingsSubItems);
|
|
306
|
+
this._detachedSubItems = settingsSubItems.map(source => this.fromObject(source, { computeId: true, fillParent: true }));
|
|
307
|
+
}
|
|
308
|
+
const accountEvent$ = merge(from(this.accountService.ready()), this.accountService.onLogin, this.accountService.onLogout.pipe(map(_ => null))).pipe(map(account => isNotNil(account?.id) ? account : null), distinctUntilChanged((a1, a2) => DateUtils.isSame(a1?.updateDate, a2?.updateDate)));
|
|
309
|
+
this.registerSubscription(
|
|
310
|
+
// Combine config and account events
|
|
311
|
+
combineLatest([
|
|
312
|
+
this.configService.config,
|
|
313
|
+
accountEvent$
|
|
314
|
+
]).subscribe(([config, account]) => {
|
|
315
|
+
if (this._debug)
|
|
316
|
+
console.debug(`${this._logPrefix}Received config or account event. Refreshing items...`, account);
|
|
317
|
+
// Load all items
|
|
318
|
+
const items = this._loadMenuItems(config, account);
|
|
319
|
+
// Emit new root items
|
|
320
|
+
this.dataSubject.next(items);
|
|
321
|
+
// Emit account changes event
|
|
322
|
+
this.accountChanges.next(account);
|
|
323
|
+
}));
|
|
324
|
+
this.registerSubscription(merge(this.accountChanges.pipe(map(() => MenuItems.parsePathWithQuery(this.router.routerState.snapshot.url))), this._$listenRoute.pipe(filter(listen => listen === true && this.started), mergeMap(_ => this.router.events), filter(event => event instanceof NavigationEnd), map((event) => MenuItems.parsePathWithQuery(event.url)))).pipe(throttleTime(250))
|
|
325
|
+
.subscribe(pathParam => {
|
|
326
|
+
const detachedSubItems = this._detachSubMenuItems(pathParam);
|
|
327
|
+
if (detachedSubItems?.length) {
|
|
328
|
+
this._detachedSubItems = [
|
|
329
|
+
...this._detachedSubItems,
|
|
330
|
+
...detachedSubItems
|
|
331
|
+
];
|
|
332
|
+
if (this._debug)
|
|
333
|
+
console.debug(`${this._logPrefix}Newly detached items: `, detachedSubItems);
|
|
334
|
+
}
|
|
335
|
+
}));
|
|
336
|
+
// Save pinned items
|
|
337
|
+
this.registerSubscription(this.onPinned
|
|
338
|
+
.subscribe(item => {
|
|
339
|
+
// Collect pinned elements, the serialize it (without id)
|
|
340
|
+
const pinnedSubItems = this.subItems.filter(i => i.isPinned())
|
|
341
|
+
.map(item => item.asObject({ withChildren: true, keepLocalId: false }));
|
|
342
|
+
if (pinnedSubItems.length && this._debug)
|
|
343
|
+
console.debug(this._logPrefix + `Saving ${pinnedSubItems.length} pinned items, in local settings`, pinnedSubItems);
|
|
344
|
+
this.settings.savePageSetting('menu', pinnedSubItems, 'sub-items');
|
|
345
|
+
}));
|
|
346
|
+
return firstNotNilPromise(this.dataSubject);
|
|
347
|
+
}
|
|
348
|
+
_loadMenuItems(config, account) {
|
|
349
|
+
if (this._debug)
|
|
350
|
+
console.debug(`${this._logPrefix}Loading menu items...`);
|
|
351
|
+
// Save previous children of root items
|
|
352
|
+
const detachedSubItems = (this.subItems || []).concat(this._staticSubItems || [])
|
|
353
|
+
.reduce((res, rootItem) => {
|
|
354
|
+
const children = rootItem.children;
|
|
355
|
+
if (isEmptyArray(children))
|
|
356
|
+
return res;
|
|
357
|
+
// Detach all root children
|
|
358
|
+
rootItem.children = [];
|
|
359
|
+
children.forEach(child => child.parent = null);
|
|
360
|
+
// Return root children
|
|
361
|
+
return res.concat(children);
|
|
362
|
+
}, this._detachedSubItems || []);
|
|
363
|
+
// Reset base root items (clean items added by config)
|
|
364
|
+
let items = this._staticItems.slice();
|
|
365
|
+
// Concat config's items
|
|
366
|
+
const configValue = config?.getProperty(CORE_CONFIG_OPTIONS.MENU_ITEMS);
|
|
367
|
+
if (isNotNilOrBlank(configValue)) {
|
|
368
|
+
try {
|
|
369
|
+
const configItems = JSON.parse(configValue);
|
|
370
|
+
items = (configItems || []).reduce((res, source) => {
|
|
371
|
+
// Normalize the item
|
|
372
|
+
const item = this.fromObject(source, { computeId: true });
|
|
373
|
+
// Skip is already loaded
|
|
374
|
+
if (res.find((i) => MenuItems.isSame(i, item)))
|
|
375
|
+
return res;
|
|
376
|
+
// Reuse existing id, if possible
|
|
377
|
+
const existingItem = this.data?.find((i) => MenuItems.isSame(i, item));
|
|
378
|
+
if (existingItem) {
|
|
379
|
+
item.id = existingItem.id;
|
|
380
|
+
}
|
|
381
|
+
if (item.after) {
|
|
382
|
+
const index = res.findIndex(i => i.title === item.after);
|
|
383
|
+
if (index !== -1) {
|
|
384
|
+
return res.slice(0, index + 1)
|
|
385
|
+
.concat(item)
|
|
386
|
+
.concat(res.slice(index + 1));
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
else if (item.before) {
|
|
390
|
+
const index = res.findIndex(i => i.title === item.before);
|
|
391
|
+
if (index !== -1) {
|
|
392
|
+
return res.slice(0, index)
|
|
393
|
+
.concat(item)
|
|
394
|
+
.concat(res.slice(index));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return res.concat(item);
|
|
398
|
+
}, items);
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
console.error(`${this._logPrefix}Invalid value for option '${CORE_CONFIG_OPTIONS.MENU_ITEMS.key}'. Expected an array of menu item`, err);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Filter item using account rights
|
|
405
|
+
const opts = { debug: this._debug };
|
|
406
|
+
items = items
|
|
407
|
+
.filter(item => MenuItems.checkIfVisible(item, account, config, opts))
|
|
408
|
+
.map(item => {
|
|
409
|
+
// Replace title using a config property
|
|
410
|
+
if (isNotNilOrBlank(item.titleProperty) && config) {
|
|
411
|
+
item.title = config.properties[item.titleProperty] || item.title;
|
|
412
|
+
}
|
|
413
|
+
return item;
|
|
414
|
+
});
|
|
415
|
+
if (this._debug)
|
|
416
|
+
console.debug(`${this._logPrefix}Found ${items.length} visible root items...`);
|
|
417
|
+
// Re-attach sub menu items
|
|
418
|
+
if (this.subMenuEnabled && detachedSubItems.length) {
|
|
419
|
+
if (account) {
|
|
420
|
+
this._addSubMenuItems(detachedSubItems, { skipIfExists: false, availableParents: detachedSubItems.concat(items) });
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
this._detachedSubItems = detachedSubItems;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
this._detachedSubItems = [];
|
|
428
|
+
}
|
|
429
|
+
return items;
|
|
430
|
+
}
|
|
431
|
+
_addSubMenuItems(sources, opts) {
|
|
432
|
+
return sources.map(source => this._addSubMenuItem(source, opts));
|
|
433
|
+
}
|
|
434
|
+
_addSubMenuItem(newItem, opts) {
|
|
435
|
+
opts = {
|
|
436
|
+
skipIfExists: true,
|
|
437
|
+
...opts,
|
|
438
|
+
};
|
|
439
|
+
const pathParam = MenuItems.parsePathWithQuery(this.router.routerState.snapshot.url);
|
|
440
|
+
// Find if item already exists
|
|
441
|
+
const existingItem = this._findExistingItem(newItem, opts?.availableParents);
|
|
442
|
+
if (existingItem) {
|
|
443
|
+
// No changes
|
|
444
|
+
if (opts.skipIfExists && MenuItems.isSame(existingItem, newItem) && existingItem.visible) {
|
|
445
|
+
// DEBUG
|
|
446
|
+
if (this._debug)
|
|
447
|
+
console.debug(`${this._logPrefix}Skipping sub item (same visible item already exist)`, newItem);
|
|
448
|
+
return existingItem;
|
|
449
|
+
}
|
|
450
|
+
if (this._debug)
|
|
451
|
+
console.debug(`${this._logPrefix}Updating existing sub item #`, existingItem.id);
|
|
452
|
+
// Replace existing item, but keep the existing id
|
|
453
|
+
if (newItem !== existingItem) {
|
|
454
|
+
newItem.id = existingItem.id;
|
|
455
|
+
newItem.$children = existingItem.$children;
|
|
456
|
+
newItem.pinned = existingItem.pinned;
|
|
457
|
+
newItem.static = existingItem.static;
|
|
458
|
+
if (newItem.pinned || newItem.static || existingItem.expanded) {
|
|
459
|
+
// If loading, keep existing title if pinned (avoid to show skeleton)
|
|
460
|
+
newItem.title = newItem.title || existingItem.title;
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
newItem.title = isNotNil(newItem.title) ? newItem.title : existingItem.title;
|
|
464
|
+
}
|
|
465
|
+
// Auto set icon, for expand action
|
|
466
|
+
if (existingItem.action === 'expand') {
|
|
467
|
+
newItem.icon = null;
|
|
468
|
+
newItem.matIcon = existingItem.expanded ? 'expand_less' : 'expand_more';
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
// Generate item's id (if need)
|
|
473
|
+
else if (isNil(newItem.id)) {
|
|
474
|
+
newItem.id = this._computeNewId();
|
|
475
|
+
}
|
|
476
|
+
// Default icon for expand action
|
|
477
|
+
if (newItem.action === 'expand' && !newItem.matIcon) {
|
|
478
|
+
newItem.matIcon = 'expand_more';
|
|
479
|
+
}
|
|
480
|
+
// If visible, get the parent where to attach the item
|
|
481
|
+
const parent = this._findParent(newItem, opts?.availableParents);
|
|
482
|
+
if (parent && parent.expanded) {
|
|
483
|
+
// Attach item to parent
|
|
484
|
+
this._attachMenuToParent(parent, newItem);
|
|
485
|
+
// Update detached items :
|
|
486
|
+
// - excluded new item
|
|
487
|
+
// - attach and exclude those than can be attached to the new item
|
|
488
|
+
// Search in detached items one have newItem as parent
|
|
489
|
+
if (newItem.expanded) {
|
|
490
|
+
const ancestor = newItem.ancestor;
|
|
491
|
+
this._detachedSubItems = this._detachedSubItems.concat(...newItem.children)
|
|
492
|
+
.reduce((res, item) => {
|
|
493
|
+
// Excluded newly add item
|
|
494
|
+
if (item.id === newItem.id)
|
|
495
|
+
return res;
|
|
496
|
+
// If some detached can be attached to the new item: do it
|
|
497
|
+
if (MenuItems.checkIfSubMenuVisible(item, pathParam)) {
|
|
498
|
+
const parent = this._findParent(item, [ancestor]);
|
|
499
|
+
if (parent) {
|
|
500
|
+
// Update item's children
|
|
501
|
+
const detachedChildren = this._detachSubMenuItems(pathParam, item.children || []);
|
|
502
|
+
// Attach item
|
|
503
|
+
this._attachMenuToParent(parent, item);
|
|
504
|
+
// Remember detached children
|
|
505
|
+
return res.concat(...detachedChildren);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
// Detach (if need)
|
|
509
|
+
this._detachToParent(item);
|
|
510
|
+
// Add to detached items
|
|
511
|
+
return res.concat(item);
|
|
512
|
+
}, []);
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
// Remove from detached elements
|
|
516
|
+
this._detachedSubItems = this._detachedSubItems.filter(item => item.id !== newItem.id);
|
|
517
|
+
// Detach children
|
|
518
|
+
newItem.children.forEach(item => this._detachToParent(item));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
else {
|
|
522
|
+
// Add or update detached item
|
|
523
|
+
const detachedIndex = isNotNil(newItem.id) ? this._detachedSubItems.findIndex(item => item.id === newItem.id) : -1;
|
|
524
|
+
if (detachedIndex !== -1) {
|
|
525
|
+
this._detachedSubItems[detachedIndex] = newItem;
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
this._detachedSubItems.push(newItem);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
// Start listening route
|
|
532
|
+
if (!this._$listenRoute.value)
|
|
533
|
+
this._$listenRoute.next(true);
|
|
534
|
+
return newItem;
|
|
535
|
+
}
|
|
536
|
+
_computeNewId() {
|
|
537
|
+
return this._itemCounter++;
|
|
538
|
+
}
|
|
539
|
+
_removeSubMenuItem(item) {
|
|
540
|
+
const existingItem = this._findExistingItem(item);
|
|
541
|
+
if (existingItem) {
|
|
542
|
+
this._detachToParent(existingItem);
|
|
543
|
+
return existingItem;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
_detachSubMenuItems(currentPathParam, subItems) {
|
|
547
|
+
currentPathParam = currentPathParam ? currentPathParam : MenuItems.parsePathWithQuery(this.router.routerState.snapshot.url.toString());
|
|
548
|
+
return (subItems || this.subItems)
|
|
549
|
+
.reduce((res, subItem) => {
|
|
550
|
+
// Not visible => should be detach
|
|
551
|
+
if (!MenuItems.checkIfSubMenuVisible(subItem, currentPathParam)) {
|
|
552
|
+
this._detachToParent(subItem);
|
|
553
|
+
return res.concat(subItem);
|
|
554
|
+
}
|
|
555
|
+
// Visible: check children
|
|
556
|
+
return res.concat(this._detachSubMenuItems(currentPathParam, subItem.children));
|
|
557
|
+
}, []);
|
|
558
|
+
}
|
|
559
|
+
_detachToParent(item) {
|
|
560
|
+
if (!item?.parent)
|
|
561
|
+
return; // Skip if already detached
|
|
562
|
+
let children = item.parent.children || [];
|
|
563
|
+
// Remove from parent children
|
|
564
|
+
const indexInParent = children.indexOf(item);
|
|
565
|
+
if (indexInParent !== -1) {
|
|
566
|
+
children = children.slice(); // Copy original array, because it can be used in a loop
|
|
567
|
+
children.splice(indexInParent, 1);
|
|
568
|
+
item.parent.children = children;
|
|
569
|
+
}
|
|
570
|
+
item.parent = null;
|
|
571
|
+
}
|
|
572
|
+
_findExistingItem(searchItem, items, recursive = true) {
|
|
573
|
+
items = items || [...this._detachedSubItems, ...this.data];
|
|
574
|
+
if (!items.length)
|
|
575
|
+
return undefined; // Not found
|
|
576
|
+
for (const item of items) {
|
|
577
|
+
if (MenuItems.isSameIdOrPathAndParams(searchItem, item))
|
|
578
|
+
return item;
|
|
579
|
+
if (recursive && item.children) {
|
|
580
|
+
const child = this._findExistingItem(searchItem, item.children);
|
|
581
|
+
if (child)
|
|
582
|
+
return child;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
_findParent(childItem, availableParents) {
|
|
588
|
+
if (!childItem?.path)
|
|
589
|
+
return undefined;
|
|
590
|
+
if (childItem.parent)
|
|
591
|
+
return childItem.parent;
|
|
592
|
+
availableParents = availableParents || [...this._detachedSubItems, ...this.data];
|
|
593
|
+
return availableParents.reduce((res, item) => {
|
|
594
|
+
if (!item?.path)
|
|
595
|
+
return res;
|
|
596
|
+
// A found item already match with the menuItem.parentPath : keep it as it
|
|
597
|
+
// There is a found candidate that already match the current candidate : keep it
|
|
598
|
+
if (MenuItems.isParent(childItem, res))
|
|
599
|
+
return res;
|
|
600
|
+
// If the menu item has explicit parentPath and its path and path param are the same as the candidate : use it as parent
|
|
601
|
+
if (MenuItems.isParent(childItem, item))
|
|
602
|
+
return item;
|
|
603
|
+
if (!res && item.children?.length) {
|
|
604
|
+
return this._findParent(childItem, item.children);
|
|
605
|
+
}
|
|
606
|
+
return res;
|
|
607
|
+
}, undefined);
|
|
608
|
+
}
|
|
609
|
+
;
|
|
610
|
+
_attachMenuToParent(parent, child) {
|
|
611
|
+
if (this._debug)
|
|
612
|
+
console.debug(`${this._logPrefix}Attach sub-menu {${MenuItems.getUrl(child)}} to parent {${MenuItems.getUrl(parent)}}`);
|
|
613
|
+
// Avoid to keep identical menu item (we replace it with the new child menu item)
|
|
614
|
+
//if (!parent?.$children) parent.$children = new BehaviorSubject<MenuItem[]>([]);
|
|
615
|
+
const children = parent.children || [];
|
|
616
|
+
const existingIndex = children.findIndex(item => MenuItems.isSameIdOrPathAndParams(item, child));
|
|
617
|
+
// Update existing element
|
|
618
|
+
if (existingIndex !== -1) {
|
|
619
|
+
if (children[existingIndex] !== child) {
|
|
620
|
+
children[existingIndex] = child;
|
|
621
|
+
parent.children = children;
|
|
622
|
+
child.parent = parent;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
children.push(child);
|
|
627
|
+
// Sort by tab (or id)
|
|
628
|
+
parent.children = children.sort(MenuItems.sortByTabOrId);
|
|
629
|
+
child.parent = parent;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
46
632
|
}
|
|
47
|
-
MenuService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
633
|
+
MenuService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MenuService, deps: [{ token: i1.LocalSettingsService }, { token: i2.ConfigService }, { token: i3.AccountService }, { token: i4.Router }, { token: i5.ModalController }, { token: i5.AlertController }, { token: i5.NavController }, { token: i6.TranslateService }, { token: ENVIRONMENT }, { token: APP_MENU_OPTIONS, optional: true }, { token: APP_MENU_ITEMS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
48
634
|
MenuService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MenuService, providedIn: 'root' });
|
|
49
635
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MenuService, decorators: [{
|
|
50
636
|
type: Injectable,
|
|
51
637
|
args: [{
|
|
52
|
-
providedIn: 'root'
|
|
638
|
+
providedIn: 'root', deps: [ENVIRONMENT]
|
|
53
639
|
}]
|
|
54
|
-
}] }
|
|
55
|
-
|
|
640
|
+
}], ctorParameters: function () { return [{ type: i1.LocalSettingsService }, { type: i2.ConfigService }, { type: i3.AccountService }, { type: i4.Router }, { type: i5.ModalController }, { type: i5.AlertController }, { type: i5.NavController }, { type: i6.TranslateService }, { type: i7.Environment, decorators: [{
|
|
641
|
+
type: Inject,
|
|
642
|
+
args: [ENVIRONMENT]
|
|
643
|
+
}] }, { type: i8.MenuOptions, decorators: [{
|
|
644
|
+
type: Optional
|
|
645
|
+
}, {
|
|
646
|
+
type: Inject,
|
|
647
|
+
args: [APP_MENU_OPTIONS]
|
|
648
|
+
}] }, { type: undefined, decorators: [{
|
|
649
|
+
type: Optional
|
|
650
|
+
}, {
|
|
651
|
+
type: Inject,
|
|
652
|
+
args: [APP_MENU_ITEMS]
|
|
653
|
+
}] }]; } });
|
|
654
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb3JlL21lbnUvbWVudS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNGLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsRyxPQUFPLEVBQWEsUUFBUSxFQUFFLFNBQVMsRUFBZSxNQUFNLGNBQWMsQ0FBQztBQUMzRSxPQUFPLEVBQUUsYUFBYSxFQUFVLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFlLFdBQVcsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ25GLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUlqRixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNyRSxPQUFPLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVwSCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSwwREFBMEQsQ0FBQztBQUN0RyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUc5RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUcvRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7Ozs7Ozs7QUFHbEQs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LDZCQUNoQixjQUFjOzRHQTNCekIsV0FBVyxjQUZWLE1BQU07MkZBRVAsV0FBVztrQkFIdkIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQztpQkFDeEM7OzBCQTBCSSxNQUFNOzJCQUFDLFdBQVc7OzBCQUNsQixRQUFROzswQkFBSSxNQUFNOzJCQUFDLGdCQUFnQjs7MEJBQ25DLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsY0FBYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV2ZW50RW1pdHRlciwgSW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3Rpb25Ub2tlbiwgT3B0aW9uYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgZnJvbSwgbWVyZ2UsIG1lcmdlTWFwLCBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBJTWVudUl0ZW0sIE1lbnVJdGVtLCBNZW51SXRlbXMsIE1lbnVPcHRpb25zIH0gZnJvbSAnLi9tZW51Lm1vZGVsJztcbmltcG9ydCB7IE5hdmlnYXRpb25FbmQsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBFbnZpcm9ubWVudCwgRU5WSVJPTk1FTlQgfSBmcm9tICcuLi8uLi8uLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQuY2xhc3MnO1xuaW1wb3J0IHsgRGF0ZVV0aWxzIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2RhdGVzJztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIG1hcCwgdGhyb3R0bGVUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQWNjb3VudFNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9hY2NvdW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgQ29uZmlnU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2NvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9zZXJ2aWNlcy9tb2RlbC9jb25maWcubW9kZWwnO1xuaW1wb3J0IHsgQ09SRV9DT05GSUdfT1BUSU9OUyB9IGZyb20gJy4uL3NlcnZpY2VzL2NvbmZpZy9jb3JlLmNvbmZpZyc7XG5pbXBvcnQgeyBpc0VtcHR5QXJyYXksIGlzTmlsLCBpc05vdEVtcHR5QXJyYXksIGlzTm90TmlsLCBpc05vdE5pbE9yQmxhbmssIHRvQm9vbGVhbiB9IGZyb20gJy4uLy4uL3NoYXJlZC9mdW5jdGlvbnMnO1xuaW1wb3J0IHsgQWNjb3VudCB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL2FjY291bnQubW9kZWwnO1xuaW1wb3J0IHsgU3RhcnRhYmxlT2JzZXJ2YWJsZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zaGFyZWQvc2VydmljZXMvc3RhcnRhYmxlLW9ic2VydmFibGUtc2VydmljZS5jbGFzcyc7XG5pbXBvcnQgeyBmaXJzdE5vdE5pbFByb21pc2UgfSBmcm9tICcuLi8uLi9zaGFyZWQvb2JzZXJ2YWJsZXMnO1xuaW1wb3J0IHsgSWNvblJlZiB9IGZyb20gJy4uLy4uL3NoYXJlZC90eXBlcyc7XG5pbXBvcnQgeyBMb2NhbFNldHRpbmdzU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2xvY2FsLXNldHRpbmdzLnNlcnZpY2UnO1xuaW1wb3J0IHsgVHJlZUl0ZW1FbnRpdHlVdGlscyB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL3RyZWUtaXRlbS1lbnRpdHkubW9kZWwnO1xuaW1wb3J0IHsgQWxlcnRDb250cm9sbGVyLCBNb2RhbENvbnRyb2xsZXIsIE5hdkNvbnRyb2xsZXIgfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBBYm91dE1vZGFsIH0gZnJvbSAnLi4vYWJvdXQvYWJvdXQubW9kYWwnO1xuXG5leHBvcnQgdHlwZSBTcGxpdFBhbmVTaG93V2hlbiA9IGJvb2xlYW4gfCAnbGcnO1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfTUVOVV9TSE9XX1dIRU46IFNwbGl0UGFuZVNob3dXaGVuID0gJ2xnJztcbmV4cG9ydCBjb25zdCBBUFBfTUVOVV9JVEVNUyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxJTWVudUl0ZW1bXT4oJ21lbnVJdGVtcycpO1xuZXhwb3J0IGNvbnN0IEFQUF9NRU5VX09QVElPTlMgPSBuZXcgSW5qZWN0aW9uVG9rZW48TWVudU9wdGlvbnM+KCdtZW51T3B0aW9ucycpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVudVBhdGhQYXJhbSB7XG4gIHBhdGg6IHN0cmluZztcbiAgcGFyYW1zOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfTtcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsIGRlcHM6IFtFTlZJUk9OTUVOVF1cbn0pXG5leHBvcnQgY2xhc3MgTWVudVNlcnZpY2UgZXh0ZW5kcyBTdGFydGFibGVPYnNlcnZhYmxlU2VydmljZTxNZW51SXRlbVtdPiB7XG5cbiAgcmVhZG9ubHkgYWNjb3VudENoYW5nZXMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PEFjY291bnQ+KHVuZGVmaW5lZCk7XG4gIHJlYWRvbmx5IG9uUGlubmVkID0gbmV3IEV2ZW50RW1pdHRlcjxNZW51SXRlbT4odHJ1ZSk7XG5cbiAgcHJpdmF0ZSBfc3RhdGljSXRlbXM6IE1lbnVJdGVtW107XG4gIHByaXZhdGUgX2RldGFjaGVkU3ViSXRlbXM6IE1lbnVJdGVtW10gPSBbXTtcbiAgcHJpdmF0ZSBfaXRlbUNvdW50ZXIgPSAwO1xuICBwcml2YXRlIHJlYWRvbmx5IF9vcHRpb25zOiBNZW51T3B0aW9ucztcbiAgcHJpdmF0ZSByZWFkb25seSBfbG9nUHJlZml4ID0gJ1ttZW51LXNlcnZpY2VdICc7XG4gIHByaXZhdGUgcmVhZG9ubHkgXyRvcGVuZWQgPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IF8kc3BsaXRQYW5lV2hlbiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8U3BsaXRQYW5lU2hvd1doZW4+KERFRkFVTFRfTUVOVV9TSE9XX1dIRU4pO1xuICBwcml2YXRlIHJlYWRvbmx5IF8kZW5hYmxlZCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4odHJ1ZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgXyRlbmFibGVTdWJNZW51OiBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj47XG4gIHByaXZhdGUgcmVhZG9ubHkgXyRsaXN0ZW5Sb3V0ZSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBzZXR0aW5nczogTG9jYWxTZXR0aW5nc1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGFjY291bnRTZXJ2aWNlOiBBY2NvdW50U2VydmljZSxcbiAgICBwcm90ZWN0ZWQgcm91dGVyOiBSb3V0ZXIsXG4gICAgcHJvdGVjdGVkIG1vZGFsQ3RybDogTW9kYWxDb250cm9sbGVyLFxuICAgIHByb3RlY3RlZCBhbGVydENvbnRyb2xsZXI6IEFsZXJ0Q29udHJvbGxlcixcbiAgICBwcm90ZWN0ZWQgbmF2Q29udHJvbGxlcjogTmF2Q29udHJvbGxlcixcbiAgICBwcm90ZWN0ZWQgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgIEBJbmplY3QoRU5WSVJPTk1FTlQpIHByb3RlY3RlZCBlbnZpcm9ubWVudDogRW52aXJvbm1lbnQsXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChBUFBfTUVOVV9PUFRJT05TKSBvcHRpb25zPzogTWVudU9wdGlvbnMsXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChBUFBfTUVOVV9JVEVNUykgc3RhdGljSXRlbXM/OiBJTWVudUl0ZW1bXVxuICApIHtcbiAgICBzdXBlcihzZXR0aW5ncyk7XG4gICAgdGhpcy5fb3B0aW9ucyA9IHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBzdWJNZW51OiB7XG4gICAgICAgIGRpc2FibGVJY29uOiBmYWxzZSxcbiAgICAgICAgc2F2ZVBpbm5lZDogdHJ1ZSxcbiAgICAgICAgLi4uKG9wdGlvbnM/LnN1Yk1lbnUgfHwge30pLFxuICAgICAgICAvLyBGb3JjZSBkaXNhYmxlIG9uIG1vYmlsZVxuICAgICAgICBlbmFibGU6IG9wdGlvbnM/LnN1Yk1lbnU/LmVuYWJsZSAhPT0gZmFsc2UgJiYgIXRoaXMuc2V0dGluZ3MubW9iaWxlLFxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5fJGVuYWJsZVN1Yk1lbnUgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KHRoaXMuX29wdGlvbnMuc3ViTWVudS5lbmFibGUpO1xuICAgIHRoaXMuX2RlYnVnID0gIWVudmlyb25tZW50LnByb2R1Y3Rpb247XG5cbiAgICB0aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zID0gW107XG4gICAgdGhpcy5fc3RhdGljSXRlbXMgPSAoc3RhdGljSXRlbXMgfHwgW10pLm1hcChzb3VyY2UgPT4ge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5mcm9tT2JqZWN0KHtzdGF0aWM6IHRydWUsIC4uLnNvdXJjZX0sIHtjb21wdXRlSWQ6IHRydWUsIGZpbGxQYXJlbnQ6IHRydWUsIGZpbGxEZWZhdWx0RnJvbVBhcmVudDogdHJ1ZX0pO1xuXG4gICAgICBjb25zdCBkZXRhY2hlZEl0ZW1zID0gVHJlZUl0ZW1FbnRpdHlVdGlscy5kZWxldGVSZWN1cnNpdmVseSh0YXJnZXQsIChpdGVtKSA9PiBpdGVtLnN0YXRpYyAhPT0gdHJ1ZSk7XG4gICAgICBpZiAoZGV0YWNoZWRJdGVtcz8ubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUuZGVidWcodGhpcy5fbG9nUHJlZml4ICsgJ0RldGFjaGVkIGluaXQgaXRlbXMnLCBkZXRhY2hlZEl0ZW1zKTtcbiAgICAgICAgZGV0YWNoZWRJdGVtcy5mb3JFYWNoKGl0ZW0gPT4gdGhpcy5fZGV0YWNoVG9QYXJlbnQoaXRlbSkpO1xuXG4gICAgICAgIHRoaXMuX2RldGFjaGVkU3ViSXRlbXMucHVzaCguLi5kZXRhY2hlZEl0ZW1zKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgb3BlbmVkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLl8kb3BlbmVkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgZ2V0IHNwbGl0UGFuZVdoZW4oKTogT2JzZXJ2YWJsZTxTcGxpdFBhbmVTaG93V2hlbj4ge1xuICAgIHJldHVybiB0aGlzLl8kc3BsaXRQYW5lV2hlbi5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIGdldCBlbmFibGVkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLl8kZW5hYmxlZC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIGdldCBzdWJNZW51RW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fJGVuYWJsZVN1Yk1lbnUudmFsdWU7XG4gIH1cblxuICBnZXQgc3ViSXRlbXMoKTogTWVudUl0ZW1bXSB7XG4gICAgcmV0dXJuICh0aGlzLmRhdGEgfHwgW10pLnJlZHVjZSgocmVzLCByb290RWxlbWVudCkgPT4gcmVzLmNvbmNhdChyb290RWxlbWVudC5jaGlsZHJlbiksIFtdKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IF9zdGF0aWNTdWJJdGVtcygpOiBNZW51SXRlbVtdIHtcbiAgICByZXR1cm4gKHRoaXMuX3N0YXRpY0l0ZW1zIHx8IFtdKS5yZWR1Y2UoKHJlcywgcm9vdEVsZW1lbnQpID0+IHJlcy5jb25jYXQocm9vdEVsZW1lbnQuY2hpbGRyZW4pLCBbXSk7XG4gIH1cblxuICBlbmFibGUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl8kZW5hYmxlZC5uZXh0KHZhbHVlKTtcbiAgfVxuXG4gIGVuYWJsZVN1Yk1lbnUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl8kZW5hYmxlU3ViTWVudS5uZXh0KHZhbHVlKTtcbiAgfVxuXG4gIHNldFNwbGl0UGFuZVNob3dXaGVuKHZhbHVlOiBTcGxpdFBhbmVTaG93V2hlbikge1xuICAgIGlmICh0aGlzLl8kc3BsaXRQYW5lV2hlbi52YWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgIHRoaXMuXyRzcGxpdFBhbmVXaGVuLm5leHQodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHRvZ2dsZVNwbGl0UGFuZVdoZW4oKSB7XG4gICAgaWYgKHRoaXMuXyRzcGxpdFBhbmVXaGVuLnZhbHVlICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy5fJHNwbGl0UGFuZVdoZW4ubmV4dChmYWxzZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5fJHNwbGl0UGFuZVdoZW4ubmV4dChERUZBVUxUX01FTlVfU0hPV19XSEVOKTtcbiAgICB9XG4gIH1cblxuICBmcm9tT2JqZWN0KHNvdXJjZTogYW55LCBvcHRzPzoge3dpdGhDaGlsZHJlbj86IGJvb2xlYW47IGNvbXB1dGVJZD86IGJvb2xlYW47IGZpbGxQYXJlbnQ/OiBib29sZWFuOyBmaWxsRGVmYXVsdEZyb21QYXJlbnQ/OiBib29sZWFufSk6IE1lbnVJdGVtIHtcbiAgICBjb25zdCB0YXJnZXQgPSBNZW51SXRlbS5mcm9tT2JqZWN0KHNvdXJjZSwge3dpdGhDaGlsZHJlbjogZmFsc2V9KTtcbiAgICAvLyBDb21wdXRlIGlkIGlmIG5lZWRcbiAgICBpZiAob3B0cz8uY29tcHV0ZUlkICYmIGlzTmlsKHRhcmdldC5pZCkpIHRhcmdldC5pZCA9IHRoaXMuX2NvbXB1dGVOZXdJZCgpO1xuXG4gICAgLy8gUmVtb3ZlIGljb24gaWYgZGlzYWJsZWRcbiAgICBpZiAodGhpcy5fb3B0aW9ucy5zdWJNZW51LmRpc2FibGVJY29uKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRhcmdldCwgPEljb25SZWY+e2ljb246IHVuZGVmaW5lZCwgbWF0SWNvbjogdW5kZWZpbmVkLCBtYXRTdmdJY29uOiB1bmRlZmluZWR9KTtcbiAgICB9XG5cbiAgICAvLyBSZWN1cnNpdmVcbiAgICB0YXJnZXQuY2hpbGRyZW4gPSAoc291cmNlLmNoaWxkcmVuIHx8IFtdKS5tYXAoKGpzb246IGFueSkgPT4gdGhpcy5mcm9tT2JqZWN0KGpzb24sIHsuLi5vcHRzLCBmaWxsUGFyZW50OiBmYWxzZX0pKTtcblxuICAgIC8vIEZpbGwgcGFyZW50IChvbmNlLCB3aGVuIHRoZSBmdWxsIHRyZWUgaXMgcmVhZHkpXG4gICAgaWYgKG9wdHM/LmZpbGxQYXJlbnQpIHtcbiAgICAgIFRyZWVJdGVtRW50aXR5VXRpbHMudHJlZUZpbGxQYXJlbnQodGFyZ2V0KTtcblxuICAgICAgLy8gRmlsbCBkZWZhdWx0cyBmcm9tIHRoZSBwYXJlbnQgKG9uY2UgZmlsbGVkKVxuICAgICAgaWYgKG9wdHM/LmZpbGxEZWZhdWx0RnJvbVBhcmVudCkge1xuICAgICAgICBUcmVlSXRlbUVudGl0eVV0aWxzLnZpc2l0KHRhcmdldCwgKGl0ZW0pID0+IHtcbiAgICAgICAgICBpZiAoIWl0ZW0ucGFyZW50KSByZXR1cm47IC8vIFNraXAgaWYgbm8gcGFyZW50XG4gICAgICAgICAgaXRlbS5wYXJlbnRQYXRoID0gaXRlbS5wYXJlbnRQYXRoIHx8IGl0ZW0ucGFyZW50LnBhdGg7XG4gICAgICAgICAgaXRlbS5wYXJlbnRQYXRoUGFyYW1zID0gaXRlbS5wYXJlbnRQYXRoUGFyYW1zIHx8IGl0ZW0ucGFyZW50LnBhdGhQYXJhbXM7XG4gICAgICAgICAgaXRlbS5zdGF0aWMgPSB0b0Jvb2xlYW4oaXRlbS5zdGF0aWMsIGl0ZW0ucGFyZW50LnN0YXRpYyk7XG4gICAgICAgICAgLy8gQ29tcHV0ZSBwYXRoLCBmcm9tIHBhcmVudCBwYXRoICsgYWN0aW9uXG4gICAgICAgICAgaWYgKCFpdGVtLnBhdGggJiYgISFpdGVtLmFjdGlvbikge1xuICAgICAgICAgICAgaXRlbS5wYXRoID0gaXRlbS5wYXJlbnQucGF0aDtcbiAgICAgICAgICAgIGl0ZW0ucGF0aFBhcmFtcyA9ICh0eXBlb2YgaXRlbS5hY3Rpb24gPT09ICdzdHJpbmcnKSA/IHthY3Rpb246IGl0ZW0uYWN0aW9ufSA6IHthY3Rpb25JZDogaXRlbS5pZC50b1N0cmluZygpLCBhY3Rpb25UaXRsZTogaXRlbS50aXRsZX07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cblxuXG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfVxuXG4gIGNyZWF0ZVN1Yk1lbnUoc291cmNlOiBQYXJ0aWFsPElNZW51SXRlbT4pOiBNZW51SXRlbSB7XG4gICAgaWYgKCF0aGlzLnN1Yk1lbnVFbmFibGVkKSByZXR1cm4gbnVsbDsgLy8gU2tpcCBpZiBkaXNhYmxlZFxuXG4gICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5mcm9tT2JqZWN0KHNvdXJjZSk7XG5cbiAgICAvLyBDaGVjayBpZiBleGlzdHNcbiAgICBpZiAodGhpcy5zdGFydGVkKSB7XG4gICAgICBjb25zdCBleGlzdGluZ0l0ZW0gPSB0aGlzLl9maW5kRXhpc3RpbmdJdGVtKHRhcmdldCk7XG4gICAgICBpZiAoZXhpc3RpbmdJdGVtKSByZXR1cm4gZXhpc3RpbmdJdGVtO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZVxuICAgIGlmIChpc05pbCh0YXJnZXQuaWQpKSB0YXJnZXQuaWQgPSB0aGlzLl9jb21wdXRlTmV3SWQoKTtcblxuICAgIHJldHVybiB0YXJnZXQ7XG4gIH1cblxuICBhc3luYyBhZGRTdWJNZW51SXRlbXMoc291cmNlczogSU1lbnVJdGVtW10sIG9wdHM/OiB7c2tpcElmRXhpc3RzPzogYm9vbGVhbn0pIHtcbiAgICBpZiAoIXRoaXMuc3RhcnRlZCkgYXdhaXQgdGhpcy5yZWFkeSgpO1xuICAgIGlmICghdGhpcy5zdWJNZW51RW5hYmxlZCkgcmV0dXJuOyAvLyBTa2lwXG4gICAgcmV0dXJuIHNvdXJjZXMubWFwKHNvdXJjZSA9PiB0aGlzLl9hZGRTdWJNZW51SXRlbSh0aGlzLmZyb21PYmplY3Qoc291cmNlKSwgb3B0cykpO1xuICB9XG5cbiAgYXN5bmMgYWRkU3ViTWVudUl0ZW0oaXRlbTogSU1lbnVJdGVtLCBvcHRzPzoge3NraXBJZkV4aXN0cz86IGJvb2xlYW59KSB7XG4gICAgaWYgKCF0aGlzLnN0YXJ0ZWQpIGF3YWl0IHRoaXMucmVhZHkoKTtcbiAgICBpZiAoIXRoaXMuc3ViTWVudUVuYWJsZWQpIHJldHVybjsgLy8gU2tpcFxuICAgIHJldHVybiB0aGlzLl9hZGRTdWJNZW51SXRlbSh0aGlzLmZyb21PYmplY3QoaXRlbSksIG9wdHMpO1xuICB9XG5cbiAgYXN5bmMgcmVtb3ZlU3ViTWVudUl0ZW1zKGl0ZW1zOiBJTWVudUl0ZW1bXSkge1xuICAgIGlmICghdGhpcy5zdGFydGVkKSBhd2FpdCB0aGlzLnJlYWR5KCk7XG4gICAgcmV0dXJuIChpdGVtcyB8fCBbXSkubWFwKGl0ZW0gPT4gdGhpcy5fcmVtb3ZlU3ViTWVudUl0ZW0odGhpcy5mcm9tT2JqZWN0KGl0ZW0pKSk7XG4gIH1cblxuICBhc3luYyByZW1vdmVTdWJNZW51SXRlbShpdGVtOiBJTWVudUl0ZW0pIHtcbiAgICBpZiAoIXRoaXMuc3RhcnRlZCkgYXdhaXQgdGhpcy5yZWFkeSgpO1xuICAgIHJldHVybiB0aGlzLl9yZW1vdmVTdWJNZW51SXRlbSh0aGlzLmZyb21PYmplY3QoaXRlbSkpO1xuICB9XG5cbiAgdG9nZ2xlUGlubmVkKHNvdXJjZTogSU1lbnVJdGVtKSB7XG4gICAgY29uc3QgaXRlbSA9IChzb3VyY2UgaW5zdGFuY2VvZiBNZW51SXRlbSkgPyBzb3VyY2UgOiB0aGlzLl9maW5kRXhpc3RpbmdJdGVtKHRoaXMuZnJvbU9iamVjdChzb3VyY2UpKTtcblxuICAgIC8vIFNraXAgaWYgbm90IGZvdW5kXG4gICAgaWYgKCFpdGVtKSB7XG4gICAgICBpZiAodGhpcy5fZGVidWcpIGNvbnNvbGUud2Fybih0aGlzLl9sb2dQcmVmaXggKyBgU3ViIG1lbnUgeyR7c291cmNlLnBhdGh9fSBjYW5ub3QgYmUgZm91bmQgLSB1bmFibGUgdG8gdG9nZ2xlIHBpbm5lZCFgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBTa2lwIGlmIHN0YXRpY1xuICAgIGlmIChpdGVtLnN0YXRpYykgcmV0dXJuO1xuXG4gICAgLy8gVW5waW5uZWRcbiAgICBpZiAoaXRlbS5waW5uZWQpIHtcbiAgICAgIGl0ZW0ucGlubmVkID0gZmFsc2U7XG4gICAgICBpZiAoIWl0ZW0uZGV0YWNoZWQpIHtcblxuICAgICAgICB0aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zID0gW1xuICAgICAgICAgIC4uLnRoaXMuX2RldGFjaGVkU3ViSXRlbXMsXG4gICAgICAgICAgLi4udGhpcy5fZGV0YWNoU3ViTWVudUl0ZW1zKClcbiAgICAgICAgXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBQaW5uZWRcbiAgICBlbHNlIHtcbiAgICAgIGl0ZW0ucGlubmVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLm9uUGlubmVkLmVtaXQoaXRlbSk7XG4gIH1cblxuXG4gIGFzeW5jIGV4ZWN1dGVBY3Rpb24oZXZlbnQ6IEV2ZW50LCBpdGVtOiBNZW51SXRlbSkge1xuICAgIGNvbnN0IGFjdGlvbiA9IGl0ZW0/LmFjdGlvbjtcbiAgICBpZiAoIWFjdGlvbikgcmV0dXJuOyAvLyBza2lwXG4gICAgaWYgKHR5cGVvZiBhY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICBzd2l0Y2ggKGFjdGlvbiBhcyBzdHJpbmcpIHtcbiAgICAgICAgY2FzZSAnbG9nb3V0JzpcbiAgICAgICAgICBhd2FpdCB0aGlzLmxvZ291dCgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdhYm91dCc6XG4gICAgICAgICAgYXdhaXQgdGhpcy5vcGVuQWJvdXRNb2RhbCgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdleHBhbmQnOlxuICAgICAgICAgIGF3YWl0IHRoaXMudG9nZ2xlRXhwYW5kYWJsZUl0ZW0oaXRlbSk7XG4gICAgICAgICAgaWYgKGl0ZW0ucGF0aCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5uYXZDb250cm9sbGVyLm5hdmlnYXRlUm9vdChpdGVtLnBhdGgsIHtcbiAgICAgICAgICAgICAgcXVlcnlQYXJhbXM6IGl0ZW0ucGF0aFBhcmFtc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgaWYgKGl0ZW0ucGF0aCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5uYXZDb250cm9sbGVyLm5hdmlnYXRlUm9vdChpdGVtLnBhdGgsIHtcbiAgICAgICAgICAgICAgcXVlcnlQYXJhbXM6IGl0ZW0ucGF0aFBhcmFtc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGFjdGlvbjogJyArIGFjdGlvbik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBhY3Rpb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIChhY3Rpb24gYXMgdW5rbm93biBhcyBhbnkpKGV2ZW50KTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBsb2dvdXQoKSB7XG4gICAgY29uc3QgdHJhbnNsYXRpb25zID0gYXdhaXQgdGhpcy50cmFuc2xhdGUuaW5zdGFudChbXG4gICAgICAnQVVUSC5MT0dPVVQuQ09ORklSTV9USVRMRScsXG4gICAgICAnQVVUSC5MT0dPVVQuQ09ORklSTV9NRVNTQUdFJyxcbiAgICAgICdDT01NT04uQlROX0NBTkNFTCcsXG4gICAgICAnQVVUSC5MT0dPVVQuQlROX0NPTkZJUk0nLFxuICAgIF0pO1xuICAgIGNvbnN0IGFsZXJ0ID0gYXdhaXQgdGhpcy5hbGVydENvbnRyb2xsZXIuY3JlYXRlKHtcbiAgICAgIGhlYWRlcjogdHJhbnNsYXRpb25zWydBVVRILkxPR09VVC5DT05GSVJNX1RJVExFJ10sXG4gICAgICBtZXNzYWdlOiB0cmFuc2xhdGlvbnNbJ0FVVEguTE9HT1VULkNPTkZJUk1fTUVTU0FHRSddLFxuICAgICAgYnV0dG9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX0NBTkNFTCddLFxuICAgICAgICAgIHJvbGU6ICdjYW5jZWwnLFxuICAgICAgICAgIGNzc0NsYXNzOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQVVUSC5MT0dPVVQuQlROX0NPTkZJUk0nXSxcbiAgICAgICAgICBjc3NDbGFzczogJ2lvbi1jb2xvci1wcmltYXJ5JyxcbiAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmFjY291bnRTZXJ2aWNlLmxvZ291dCgpO1xuXG4gICAgICAgICAgICAvLyBCYWNrIHRvIGhvbWVcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5uYXZDb250cm9sbGVyLm5hdmlnYXRlUm9vdCgnLycpLCAxMDApO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgYWxlcnQucHJlc2VudCgpO1xuICB9XG5cbiAgYXN5bmMgb3BlbkFib3V0TW9kYWwoKSB7XG4gICAgY29uc3QgbW9kYWwgPSBhd2FpdCB0aGlzLm1vZGFsQ3RybC5jcmVhdGUoeyBjb21wb25lbnQ6IEFib3V0TW9kYWwgfSk7XG4gICAgcmV0dXJuIG1vZGFsLnByZXNlbnQoKTtcbiAgfVxuXG4gIGFzeW5jIHRvZ2dsZUV4cGFuZGFibGVJdGVtKGl0ZW06IE1lbnVJdGVtKSB7XG4gICAgaWYgKCFpdGVtLmV4cGFuZGVkKSB7XG4gICAgICBpZiAodGhpcy5fZGVidWcpIGNvbnNvbGUuZGVidWcodGhpcy5fbG9nUHJlZml4ICsgJ0V4cGFuZCBpdGVtJywgaXRlbSk7XG5cbiAgICAgIGl0ZW0ubWF0SWNvbiA9ICdleHBhbmRfbGVzcyc7XG5cbiAgICAgIC8vIFRyeSB0byBhdHRhY2ggc29tZSBpdGVtXG4gICAgICB0aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zXG4gICAgICAgIC5maWx0ZXIoY2hpbGRJdGVtID0+ICEhdGhpcy5fZmluZFBhcmVudChjaGlsZEl0ZW0sIFtpdGVtXSkpXG4gICAgICAgIC5mb3JFYWNoKGNoaWxkSXRlbSA9PiB0aGlzLl9hdHRhY2hNZW51VG9QYXJlbnQoaXRlbSwgY2hpbGRJdGVtKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgaXRlbS5tYXRJY29uID0gJ2V4cGFuZF9tb3JlJztcblxuICAgICAgdGhpcy5fZGV0YWNoZWRTdWJJdGVtcyA9IFtcbiAgICAgICAgLi4udGhpcy5fZGV0YWNoZWRTdWJJdGVtcyxcbiAgICAgICAgLi4udGhpcy5fZGV0YWNoU3ViTWVudUl0ZW1zKHtwYXRoOiAnLycsIHBhcmFtczoge319LCBpdGVtLmNoaWxkcmVuKVxuICAgICAgXTtcbiAgICB9XG4gIH1cblxuICBfbWFya0FzT3BlbmVkKCkge1xuICAgIHRoaXMuXyRvcGVuZWQubmV4dCh0cnVlKTtcbiAgfVxuXG4gIF9tYXJrQXNDbG9zZWQoKSB7XG4gICAgdGhpcy5fJG9wZW5lZC5uZXh0KGZhbHNlKTtcbiAgfVxuXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG5nT25TdGFydCgpIHtcbiAgICBjb25zb2xlLmluZm8oYCR7dGhpcy5fbG9nUHJlZml4fVN0YXJ0aW5nLi4uYCk7XG5cbiAgICAvLyBSZXN0b3JlIHN1YiBpdGVtcyBmcm9tIHNldHRpbmdzXG4gICAgYXdhaXQgdGhpcy5zZXR0aW5ncy5yZWFkeSgpO1xuICAgIGNvbnN0IHNldHRpbmdzU3ViSXRlbXM6IElNZW51SXRlbVtdID0gdGhpcy5zZXR0aW5ncy5nZXRQYWdlU2V0dGluZ3MoJ21lbnUnLCAnc3ViLWl0ZW1zJyk7XG4gICAgaWYgKGlzTm90RW1wdHlBcnJheShzZXR0aW5nc1N1Ykl0ZW1zKSkge1xuICAgICAgY29uc29sZS5kZWJ1Zyh0aGlzLl9sb2dQcmVmaXggKyAnUmVzdG9yaW5nIHBpbm5lZCBpdGVtcyBmcm9tIHNldHRpbmdzLi4uJywgc2V0dGluZ3NTdWJJdGVtcyk7XG4gICAgICB0aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zID0gc2V0dGluZ3NTdWJJdGVtcy5tYXAoc291cmNlID0+IHRoaXMuZnJvbU9iamVjdChzb3VyY2UsIHtjb21wdXRlSWQ6IHRydWUsIGZpbGxQYXJlbnQ6IHRydWV9KSk7XG4gICAgfVxuXG4gICAgY29uc3QgYWNjb3VudEV2ZW50JCA9IG1lcmdlKFxuICAgICAgZnJvbSh0aGlzLmFjY291bnRTZXJ2aWNlLnJlYWR5KCkpLFxuICAgICAgdGhpcy5hY2NvdW50U2VydmljZS5vbkxvZ2luLFxuICAgICAgdGhpcy5hY2NvdW50U2VydmljZS5vbkxvZ291dC5waXBlKFxuICAgICAgICBtYXAoXyA9PiBudWxsKVxuICAgICAgKVxuICAgICkucGlwZShcbiAgICAgIG1hcChhY2NvdW50ID0+IGlzTm90TmlsKGFjY291bnQ/LmlkKSA/IGFjY291bnQgOiBudWxsKSxcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKChhMSwgYTIpID0+IERhdGVVdGlscy5pc1NhbWUoYTE/LnVwZGF0ZURhdGUsIGEyPy51cGRhdGVEYXRlKSlcbiAgICApO1xuXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbihcbiAgICAgIC8vIENvbWJpbmUgY29uZmlnIGFuZCBhY2NvdW50IGV2ZW50c1xuICAgICAgY29tYmluZUxhdGVzdChbXG4gICAgICAgIHRoaXMuY29uZmlnU2VydmljZS5jb25maWcsXG4gICAgICAgIGFjY291bnRFdmVudCRcbiAgICAgIF0pLnN1YnNjcmliZSgoW2NvbmZpZywgYWNjb3VudF0pID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX2RlYnVnKSBjb25zb2xlLmRlYnVnKGAke3RoaXMuX2xvZ1ByZWZpeH1SZWNlaXZlZCBjb25maWcgb3IgYWNjb3VudCBldmVudC4gUmVmcmVzaGluZyBpdGVtcy4uLmAsIGFjY291bnQpO1xuXG4gICAgICAgIC8vIExvYWQgYWxsIGl0ZW1zXG4gICAgICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5fbG9hZE1lbnVJdGVtcyhjb25maWcsIGFjY291bnQpO1xuXG4gICAgICAgIC8vIEVtaXQgbmV3IHJvb3QgaXRlbXNcbiAgICAgICAgdGhpcy5kYXRhU3ViamVjdC5uZXh0KGl0ZW1zKTtcblxuICAgICAgICAvLyBFbWl0IGFjY291bnQgY2hhbmdlcyBldmVudFxuICAgICAgICB0aGlzLmFjY291bnRDaGFuZ2VzLm5leHQoYWNjb3VudCk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgbWVyZ2UoXG4gICAgICAgIHRoaXMuYWNjb3VudENoYW5nZXMucGlwZShcbiAgICAgICAgICBtYXAoKCkgPT4gTWVudUl0ZW1zLnBhcnNlUGF0aFdpdGhRdWVyeSh0aGlzLnJvdXRlci5yb3V0ZXJTdGF0ZS5zbmFwc2hvdC51cmwpKVxuICAgICAgICApLFxuICAgICAgICB0aGlzLl8kbGlzdGVuUm91dGUucGlwZShcbiAgICAgICAgICBmaWx0ZXIobGlzdGVuID0+IGxpc3RlbiA9PT0gdHJ1ZSAmJiB0aGlzLnN0YXJ0ZWQpLFxuICAgICAgICAgIG1lcmdlTWFwKF8gPT4gdGhpcy5yb3V0ZXIuZXZlbnRzKSxcbiAgICAgICAgICBmaWx0ZXIoZXZlbnQgPT4gZXZlbnQgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRW5kKSxcbiAgICAgICAgICBtYXAoKGV2ZW50OiBOYXZpZ2F0aW9uRW5kKSA9PiBNZW51SXRlbXMucGFyc2VQYXRoV2l0aFF1ZXJ5KGV2ZW50LnVybCkpLFxuICAgICAgICApXG4gICAgICApLnBpcGUoXG4gICAgICAgIHRocm90dGxlVGltZSgyNTApXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKHBhdGhQYXJhbSA9PiB7XG4gICAgICAgIGNvbnN0IGRldGFjaGVkU3ViSXRlbXMgPSB0aGlzLl9kZXRhY2hTdWJNZW51SXRlbXMocGF0aFBhcmFtKTtcbiAgICAgICAgaWYgKGRldGFjaGVkU3ViSXRlbXM/Lmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuX2RldGFjaGVkU3ViSXRlbXMgPSBbXG4gICAgICAgICAgICAuLi50aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zLFxuICAgICAgICAgICAgLi4uZGV0YWNoZWRTdWJJdGVtc1xuICAgICAgICAgIF07XG5cbiAgICAgICAgICBpZiAodGhpcy5fZGVidWcpIGNvbnNvbGUuZGVidWcoYCR7dGhpcy5fbG9nUHJlZml4fU5ld2x5IGRldGFjaGVkIGl0ZW1zOiBgLCBkZXRhY2hlZFN1Ykl0ZW1zKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG5cbiAgICAvLyBTYXZlIHBpbm5lZCBpdGVtc1xuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLm9uUGlubmVkXG4gICAgICAgIC5zdWJzY3JpYmUoaXRlbSA9PiB7XG5cbiAgICAgICAgICAvLyBDb2xsZWN0IHBpbm5lZCBlbGVtZW50cywgdGhlIHNlcmlhbGl6ZSBpdCAod2l0aG91dCBpZClcbiAgICAgICAgICBjb25zdCBwaW5uZWRTdWJJdGVtcyA9IHRoaXMuc3ViSXRlbXMuZmlsdGVyKGkgPT4gaS5pc1Bpbm5lZCgpKVxuICAgICAgICAgICAgLm1hcChpdGVtID0+IGl0ZW0uYXNPYmplY3Qoe3dpdGhDaGlsZHJlbjogdHJ1ZSwga2VlcExvY2FsSWQ6IGZhbHNlfSkpO1xuXG4gICAgICAgICAgaWYgKHBpbm5lZFN1Ykl0ZW1zLmxlbmd0aCAmJiB0aGlzLl9kZWJ1ZykgY29uc29sZS5kZWJ1Zyh0aGlzLl9sb2dQcmVmaXggKyBgU2F2aW5nICR7cGlubmVkU3ViSXRlbXMubGVuZ3RofSBwaW5uZWQgaXRlbXMsIGluIGxvY2FsIHNldHRpbmdzYCwgcGlubmVkU3ViSXRlbXMpO1xuICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc2F2ZVBhZ2VTZXR0aW5nKCdtZW51JywgcGlubmVkU3ViSXRlbXMsICdzdWItaXRlbXMnKTtcbiAgICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIGZpcnN0Tm90TmlsUHJvbWlzZSh0aGlzLmRhdGFTdWJqZWN0KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvYWRNZW51SXRlbXMoY29uZmlnOiBDb25maWd1cmF0aW9ufG51bGwsIGFjY291bnQ6IEFjY291bnR8bnVsbCkge1xuICAgIGlmICh0aGlzLl9kZWJ1ZykgY29uc29sZS5kZWJ1ZyhgJHt0aGlzLl9sb2dQcmVmaXh9TG9hZGluZyBtZW51IGl0ZW1zLi4uYCk7XG5cbiAgICAvLyBTYXZlIHByZXZpb3VzIGNoaWxkcmVuIG9mIHJvb3QgaXRlbXNcbiAgICBjb25zdCBkZXRhY2hlZFN1Ykl0ZW1zID0gKHRoaXMuc3ViSXRlbXMgfHwgW10pLmNvbmNhdCh0aGlzLl9zdGF0aWNTdWJJdGVtcyB8fCBbXSlcbiAgICAgIC5yZWR1Y2UoKHJlcywgcm9vdEl0ZW0pID0+IHtcbiAgICAgICAgY29uc3QgY2hpbGRyZW4gPSByb290SXRlbS5jaGlsZHJlbjtcbiAgICAgICAgaWYgKGlzRW1wdHlBcnJheShjaGlsZHJlbikpIHJldHVybiByZXM7XG4gICAgICAgIC8vIERldGFjaCBhbGwgcm9vdCBjaGlsZHJlblxuICAgICAgICByb290SXRlbS5jaGlsZHJlbiA9IFtdO1xuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IGNoaWxkLnBhcmVudCA9IG51bGwpO1xuICAgICAgICAvLyBSZXR1cm4gcm9vdCBjaGlsZHJlblxuICAgICAgICByZXR1cm4gcmVzLmNvbmNhdChjaGlsZHJlbik7XG4gICAgICB9LCB0aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zIHx8IFtdKTtcblxuICAgIC8vIFJlc2V0IGJhc2Ugcm9vdCBpdGVtcyAoY2xlYW4gaXRlbXMgYWRkZWQgYnkgY29uZmlnKVxuICAgIGxldCBpdGVtczogTWVudUl0ZW1bXSA9IHRoaXMuX3N0YXRpY0l0ZW1zLnNsaWNlKCk7XG5cbiAgICAvLyBDb25jYXQgY29uZmlnJ3MgaXRlbXNcbiAgICBjb25zdCBjb25maWdWYWx1ZTogc3RyaW5nID0gY29uZmlnPy5nZXRQcm9wZXJ0eShDT1JFX0NPTkZJR19PUFRJT05TLk1FTlVfSVRFTVMpO1xuICAgIGlmIChpc05vdE5pbE9yQmxhbmsoY29uZmlnVmFsdWUpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjb25maWdJdGVtcyA9IEpTT04ucGFyc2UoY29uZmlnVmFsdWUpIGFzIElNZW51SXRlbVtdO1xuICAgICAgICBpdGVtcyA9IChjb25maWdJdGVtcyB8fCBbXSkucmVkdWNlKChyZXM6IE1lbnVJdGVtW10sIHNvdXJjZSkgPT4ge1xuXG4gICAgICAgICAgLy8gTm9ybWFsaXplIHRoZSBpdGVtXG4gICAgICAgICAgY29uc3QgaXRlbSA9IHRoaXMuZnJvbU9iamVjdChzb3VyY2UsIHtjb21wdXRlSWQ6IHRydWV9KTtcblxuICAgICAgICAgIC8vIFNraXAgaXMgYWxyZWFkeSBsb2FkZWRcbiAgICAgICAgICBpZiAocmVzLmZpbmQoKGkpID0+IE1lbnVJdGVtcy5pc1NhbWUoaSwgaXRlbSkpKSByZXR1cm4gcmVzO1xuXG4gICAgICAgICAgLy8gUmV1c2UgZXhpc3RpbmcgaWQsIGlmIHBvc3NpYmxlXG4gICAgICAgICAgY29uc3QgZXhpc3RpbmdJdGVtID0gdGhpcy5kYXRhPy5maW5kKChpKSA9PiBNZW51SXRlbXMuaXNTYW1lKGksIGl0ZW0pKTtcbiAgICAgICAgICBpZiAoZXhpc3RpbmdJdGVtKSB7XG4gICAgICAgICAgICBpdGVtLmlkID0gZXhpc3RpbmdJdGVtLmlkO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpdGVtLmFmdGVyKSB7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHJlcy5maW5kSW5kZXgoaSA9PiBpLnRpdGxlID09PSBpdGVtLmFmdGVyKTtcbiAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlcy5zbGljZSgwLCBpbmRleCArIDEpXG4gICAgICAgICAgICAgICAgLmNvbmNhdChpdGVtKVxuICAgICAgICAgICAgICAgIC5jb25jYXQocmVzLnNsaWNlKGluZGV4ICsgMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChpdGVtLmJlZm9yZSkge1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSByZXMuZmluZEluZGV4KGkgPT4gaS50aXRsZSA9PT0gaXRlbS5iZWZvcmUpO1xuICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzLnNsaWNlKDAsIGluZGV4KVxuICAgICAgICAgICAgICAgIC5jb25jYXQoaXRlbSlcbiAgICAgICAgICAgICAgICAuY29uY2F0KHJlcy5zbGljZShpbmRleCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzLmNvbmNhdChpdGVtKTtcbiAgICAgICAgfSwgaXRlbXMpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYCR7dGhpcy5fbG9nUHJlZml4fUludmFsaWQgdmFsdWUgZm9yIG9wdGlvbiAnJHtDT1JFX0NPTkZJR19PUFRJT05TLk1FTlVfSVRFTVMua2V5fScuIEV4cGVjdGVkIGFuIGFycmF5IG9mIG1lbnUgaXRlbWAsIGVycik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmlsdGVyIGl0ZW0gdXNpbmcgYWNjb3VudCByaWdodHNcbiAgICBjb25zdCBvcHRzID0ge2RlYnVnOiB0aGlzLl9kZWJ1Z307XG4gICAgaXRlbXMgPSBpdGVtc1xuICAgICAgLmZpbHRlcihpdGVtID0+IE1lbnVJdGVtcy5jaGVja0lmVmlzaWJsZShpdGVtLCBhY2NvdW50LCBjb25maWcsIG9wdHMpKVxuICAgICAgLm1hcChpdGVtID0+IHtcbiAgICAgICAgLy8gUmVwbGFjZSB0aXRsZSB1c2luZyBhIGNvbmZpZyBwcm9wZXJ0eVxuICAgICAgICBpZiAoaXNOb3ROaWxPckJsYW5rKGl0ZW0udGl0bGVQcm9wZXJ0eSkgJiYgY29uZmlnKSB7XG4gICAgICAgICAgaXRlbS50aXRsZSA9IGNvbmZpZy5wcm9wZXJ0aWVzW2l0ZW0udGl0bGVQcm9wZXJ0eV0gfHwgaXRlbS50aXRsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgfSk7XG5cbiAgICBpZiAodGhpcy5fZGVidWcpIGNvbnNvbGUuZGVidWcoYCR7dGhpcy5fbG9nUHJlZml4fUZvdW5kICR7aXRlbXMubGVuZ3RofSB2aXNpYmxlIHJvb3QgaXRlbXMuLi5gKTtcblxuICAgIC8vIFJlLWF0dGFjaCBzdWIgbWVudSBpdGVtc1xuICAgIGlmICh0aGlzLnN1Yk1lbnVFbmFibGVkICYmIGRldGFjaGVkU3ViSXRlbXMubGVuZ3RoKSB7XG4gICAgICBpZiAoYWNjb3VudCkge1xuICAgICAgICB0aGlzLl9hZGRTdWJNZW51SXRlbXMoZGV0YWNoZWRTdWJJdGVtcywge3NraXBJZkV4aXN0czogZmFsc2UsIGF2YWlsYWJsZVBhcmVudHM6IGRldGFjaGVkU3ViSXRlbXMuY29uY2F0KGl0ZW1zKX0pO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRoaXMuX2RldGFjaGVkU3ViSXRlbXMgPSBkZXRhY2hlZFN1Ykl0ZW1zO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuX2RldGFjaGVkU3ViSXRlbXMgPSBbXTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXRlbXM7XG4gIH1cblxuICBwcml2YXRlIF9hZGRTdWJNZW51SXRlbXMoc291cmNlczogTWVudUl0ZW1bXSwgb3B0cz86IHtza2lwSWZFeGlzdHM/OiBib29sZWFuOyBhdmFpbGFibGVQYXJlbnRzPzogTWVudUl0ZW1bXX0pIHtcbiAgICByZXR1cm4gc291cmNlcy5tYXAoc291cmNlID0+IHRoaXMuX2FkZFN1Yk1lbnVJdGVtKHNvdXJjZSwgb3B0cykpO1xuICB9XG5cbiAgcHJpdmF0ZSBfYWRkU3ViTWVudUl0ZW0obmV3SXRlbTogTWVudUl0ZW0sIG9wdHM/OiB7c2tpcElmRXhpc3RzPzogYm9vbGVhbjsgYXZhaWxhYmxlUGFyZW50cz86IE1lbnVJdGVtW119KSB7XG4gICAgb3B0cyA9IHtcbiAgICAgIHNraXBJZkV4aXN0czogdHJ1ZSxcbiAgICAgIC4uLm9wdHMsXG4gICAgfTtcblxuICAgIGNvbnN0IHBhdGhQYXJhbSA9IE1lbnVJdGVtcy5wYXJzZVBhdGhXaXRoUXVlcnkodGhpcy5yb3V0ZXIucm91dGVyU3RhdGUuc25hcHNob3QudXJsKTtcblxuICAgIC8vIEZpbmQgaWYgaXRlbSBhbHJlYWR5IGV4aXN0c1xuICAgIGNvbnN0IGV4aXN0aW5nSXRlbSA9IHRoaXMuX2ZpbmRFeGlzdGluZ0l0ZW0obmV3SXRlbSwgb3B0cz8uYXZhaWxhYmxlUGFyZW50cyk7XG4gICAgaWYgKGV4aXN0aW5nSXRlbSkge1xuICAgICAgLy8gTm8gY2hhbmdlc1xuICAgICAgaWYgKG9wdHMuc2tpcElmRXhpc3RzICYmIE1lbnVJdGVtcy5pc1NhbWUoZXhpc3RpbmdJdGVtLCBuZXdJdGVtKSAmJiBleGlzdGluZ0l0ZW0udmlzaWJsZSkge1xuICAgICAgICAvLyBERUJVR1xuICAgICAgICBpZiAodGhpcy5fZGVidWcpIGNvbnNvbGUuZGVidWcoYCR7dGhpcy5fbG9nUHJlZml4fVNraXBwaW5nIHN1YiBpdGVtIChzYW1lIHZpc2libGUgaXRlbSBhbHJlYWR5IGV4aXN0KWAsIG5ld0l0ZW0pO1xuICAgICAgICByZXR1cm4gZXhpc3RpbmdJdGVtO1xuICAgICAgfVxuXG5cbiAgICAgIGlmICh0aGlzLl9kZWJ1ZykgY29uc29sZS5kZWJ1ZyhgJHt0aGlzLl9sb2dQcmVmaXh9VXBkYXRpbmcgZXhpc3Rpbmcgc3ViIGl0ZW0gI2AsIGV4aXN0aW5nSXRlbS5pZCk7XG5cbiAgICAgIC8vIFJlcGxhY2UgZXhpc3RpbmcgaXRlbSwgYnV0IGtlZXAgdGhlIGV4aXN0aW5nIGlkXG4gICAgICBpZiAobmV3SXRlbSAhPT0gZXhpc3RpbmdJdGVtKSB7XG4gICAgICAgIG5ld0l0ZW0uaWQgPSBleGlzdGluZ0l0ZW0uaWQ7XG4gICAgICAgIG5ld0l0ZW0uJGNoaWxkcmVuID0gZXhpc3RpbmdJdGVtLiRjaGlsZHJlbjtcbiAgICAgICAgbmV3SXRlbS5waW5uZWQgPSBleGlzdGluZ0l0ZW0ucGlubmVkO1xuICAgICAgICBuZXdJdGVtLnN0YXRpYyA9IGV4aXN0aW5nSXRlbS5zdGF0aWM7XG4gICAgICAgIGlmIChuZXdJdGVtLnBpbm5lZCB8fCBuZXdJdGVtLnN0YXRpYyB8fCBleGlzdGluZ0l0ZW0uZXhwYW5kZWQpIHtcbiAgICAgICAgICAvLyBJZiBsb2FkaW5nLCBrZWVwIGV4aXN0aW5nIHRpdGxlIGlmIHBpbm5lZCAoYXZvaWQgdG8gc2hvdyBza2VsZXRvbilcbiAgICAgICAgICBuZXdJdGVtLnRpdGxlID0gbmV3SXRlbS50aXRsZSB8fCBleGlzdGluZ0l0ZW0udGl0bGU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgbmV3SXRlbS50aXRsZSA9IGlzTm90TmlsKG5ld0l0ZW0udGl0bGUpID8gbmV3SXRlbS50aXRsZSA6IGV4aXN0aW5nSXRlbS50aXRsZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBBdXRvIHNldCBpY29uLCBmb3IgZXhwYW5kIGFjdGlvblxuICAgICAgICBpZiAoZXhpc3RpbmdJdGVtLmFjdGlvbiA9PT0gJ2V4cGFuZCcpIHtcbiAgICAgICAgICBuZXdJdGVtLmljb24gPSBudWxsO1xuICAgICAgICAgIG5ld0l0ZW0ubWF0SWNvbiA9IGV4aXN0aW5nSXRlbS5leHBhbmRlZCA/ICdleHBhbmRfbGVzcycgOiAnZXhwYW5kX21vcmUnO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gR2VuZXJhdGUgaXRlbSdzIGlkIChpZiBuZWVkKVxuICAgIGVsc2UgaWYgKGlzTmlsKG5ld0l0ZW0uaWQpKSB7XG4gICAgICBuZXdJdGVtLmlkID0gdGhpcy5fY29tcHV0ZU5ld0lkKCk7XG4gICAgfVxuXG4gICAgLy8gRGVmYXVsdCBpY29uIGZvciBleHBhbmQgYWN0aW9uXG4gICAgaWYgKG5ld0l0ZW0uYWN0aW9uID09PSAnZXhwYW5kJyAmJiAhbmV3SXRlbS5tYXRJY29uKSB7XG4gICAgICBuZXdJdGVtLm1hdEljb24gPSAnZXhwYW5kX21vcmUnO1xuICAgIH1cblxuICAgIC8vIElmIHZpc2libGUsIGdldCB0aGUgcGFyZW50IHdoZXJlIHRvIGF0dGFjaCB0aGUgaXRlbVxuICAgIGNvbnN0IHBhcmVudCA9IHRoaXMuX2ZpbmRQYXJlbnQobmV3SXRlbSwgb3B0cz8uYXZhaWxhYmxlUGFyZW50cyk7XG4gICAgaWYgKHBhcmVudCAmJiBwYXJlbnQuZXhwYW5kZWQpIHtcbiAgICAgIC8vIEF0dGFjaCBpdGVtIHRvIHBhcmVudFxuICAgICAgdGhpcy5fYXR0YWNoTWVudVRvUGFyZW50KHBhcmVudCwgbmV3SXRlbSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBkZXRhY2hlZCBpdGVtcyA6XG4gICAgICAvLyAtIGV4Y2x1ZGVkIG5ldyBpdGVtXG4gICAgICAvLyAtIGF0dGFjaCBhbmQgZXhjbHVkZSB0aG9zZSB0aGFuIGNhbiBiZSBhdHRhY2hlZCB0byB0aGUgbmV3IGl0ZW1cbiAgICAgIC8vIFNlYXJjaCBpbiBkZXRhY2hlZCBpdGVtcyBvbmUgaGF2ZSBuZXdJdGVtIGFzIHBhcmVudFxuICAgICAgaWYgKG5ld0l0ZW0uZXhwYW5kZWQpIHtcbiAgICAgICAgY29uc3QgYW5jZXN0b3IgPSBuZXdJdGVtLmFuY2VzdG9yO1xuICAgICAgICB0aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zID0gdGhpcy5fZGV0YWNoZWRTdWJJdGVtcy5jb25jYXQoLi4ubmV3SXRlbS5jaGlsZHJlbilcbiAgICAgICAgICAucmVkdWNlKChyZXMsIGl0ZW0pID0+IHtcbiAgICAgICAgICAgIC8vIEV4Y2x1ZGVkIG5ld2x5IGFkZCBpdGVtXG4gICAgICAgICAgICBpZiAoaXRlbS5pZCA9PT0gbmV3SXRlbS5pZCkgcmV0dXJuIHJlcztcblxuICAgICAgICAgICAgLy8gSWYgc29tZSBkZXRhY2hlZCBjYW4gYmUgYXR0YWNoZWQgdG8gdGhlIG5ldyBpdGVtOiBkbyBpdFxuICAgICAgICAgICAgaWYgKE1lbnVJdGVtcy5jaGVja0lmU3ViTWVudVZpc2libGUoaXRlbSwgcGF0aFBhcmFtKSkge1xuXG4gICAgICAgICAgICAgIGNvbnN0IHBhcmVudCA9IHRoaXMuX2ZpbmRQYXJlbnQoaXRlbSwgW2FuY2VzdG9yXSk7XG4gICAgICAgICAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgaXRlbSdzIGNoaWxkcmVuXG4gICAgICAgICAgICAgICAgY29uc3QgZGV0YWNoZWRDaGlsZHJlbiA9IHRoaXMuX2RldGFjaFN1Yk1lbnVJdGVtcyhwYXRoUGFyYW0sIGl0ZW0uY2hpbGRyZW4gfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgLy8gQXR0YWNoIGl0ZW1cbiAgICAgICAgICAgICAgICB0aGlzLl9hdHRhY2hNZW51VG9QYXJlbnQocGFyZW50LCBpdGVtKTtcblxuICAgICAgICAgICAgICAgIC8vIFJlbWVtYmVyIGRldGFjaGVkIGNoaWxkcmVuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5jb25jYXQoLi4uZGV0YWNoZWRDaGlsZHJlbik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRGV0YWNoIChpZiBuZWVkKVxuICAgICAgICAgICAgdGhpcy5fZGV0YWNoVG9QYXJlbnQoaXRlbSk7XG5cbiAgICAgICAgICAgIC8vIEFkZCB0byBkZXRhY2hlZCBpdGVtc1xuICAgICAgICAgICAgcmV0dXJuIHJlcy5jb25jYXQoaXRlbSk7XG4gICAgICAgICAgfSwgW10pO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIFJlbW92ZSBmcm9tIGRldGFjaGVkIGVsZW1lbnRzXG4gICAgICAgIHRoaXMuX2RldGFjaGVkU3ViSXRlbXMgPSB0aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zLmZpbHRlcihpdGVtID0+IGl0ZW0uaWQgIT09IG5ld0l0ZW0uaWQpO1xuXG4gICAgICAgIC8vIERldGFjaCBjaGlsZHJlblxuICAgICAgICBuZXdJdGVtLmNoaWxkcmVuLmZvckVhY2goaXRlbSA9PiB0aGlzLl9kZXRhY2hUb1BhcmVudChpdGVtKSk7XG5cbiAgICAgIH1cblxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIC8vIEFkZCBvciB1cGRhdGUgZGV0YWNoZWQgaXRlbVxuICAgICAgY29uc3QgZGV0YWNoZWRJbmRleCA9IGlzTm90TmlsKG5ld0l0ZW0uaWQpID8gdGhpcy5fZGV0YWNoZWRTdWJJdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBuZXdJdGVtLmlkKSA6IC0xO1xuICAgICAgaWYgKGRldGFjaGVkSW5kZXggIT09IC0xKSB7XG4gICAgICAgIHRoaXMuX2RldGFjaGVkU3ViSXRlbXNbZGV0YWNoZWRJbmRleF0gPSBuZXdJdGVtO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRoaXMuX2RldGFjaGVkU3ViSXRlbXMucHVzaChuZXdJdGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTdGFydCBsaXN0ZW5pbmcgcm91dGVcbiAgICBpZiAoIXRoaXMuXyRsaXN0ZW5Sb3V0ZS52YWx1ZSkgdGhpcy5fJGxpc3RlblJvdXRlLm5leHQodHJ1ZSk7XG5cbiAgICByZXR1cm4gbmV3SXRlbTtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbXB1dGVOZXdJZCgpIHtcbiAgICByZXR1cm4gdGhpcy5faXRlbUNvdW50ZXIrKztcbiAgfVxuXG4gIHByaXZhdGUgX3JlbW92ZVN1Yk1lbnVJdGVtKGl0ZW06IE1lbnVJdGVtKSB7XG4gICAgY29uc3QgZXhpc3RpbmdJdGVtID0gdGhpcy5fZmluZEV4aXN0aW5nSXRlbShpdGVtKTtcbiAgICBpZiAoZXhpc3RpbmdJdGVtKSB7XG4gICAgICB0aGlzLl9kZXRhY2hUb1BhcmVudChleGlzdGluZ0l0ZW0pO1xuICAgICAgcmV0dXJuIGV4aXN0aW5nSXRlbTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9kZXRhY2hTdWJNZW51SXRlbXMoY3VycmVudFBhdGhQYXJhbT86IE1lbnVQYXRoUGFyYW0sIHN1Ykl0ZW1zPzogTWVudUl0ZW1bXSkge1xuICAgIGN1cnJlbnRQYXRoUGFyYW0gPSBjdXJyZW50UGF0aFBhcmFtID8gY3VycmVudFBhdGhQYXJhbSA6IE1lbnVJdGVtcy5wYXJzZVBhdGhXaXRoUXVlcnkodGhpcy5yb3V0ZXIucm91dGVyU3RhdGUuc25hcHNob3QudXJsLnRvU3RyaW5nKCkpO1xuICAgIHJldHVybiAoc3ViSXRlbXMgfHwgdGhpcy5zdWJJdGVtcylcbiAgICAgIC5yZWR1Y2UoKHJlcywgc3ViSXRlbSkgPT4ge1xuXG4gICAgICAgIC8vIE5vdCB2aXNpYmxlID0+IHNob3VsZCBiZSBkZXRhY2hcbiAgICAgICAgaWYgKCFNZW51SXRlbXMuY2hlY2tJZlN1Yk1lbnVWaXNpYmxlKHN1Ykl0ZW0sIGN1cnJlbnRQYXRoUGFyYW0pKSB7XG5cbiAgICAgICAgICB0aGlzLl9kZXRhY2hUb1BhcmVudChzdWJJdGVtKTtcblxuICAgICAgICAgIHJldHVybiByZXMuY29uY2F0KHN1Ykl0ZW0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIFZpc2libGU6IGNoZWNrIGNoaWxkcmVuXG4gICAgICAgIHJldHVybiByZXMuY29uY2F0KFxuICAgICAgICAgIHRoaXMuX2RldGFjaFN1Yk1lbnVJdGVtcyhjdXJyZW50UGF0aFBhcmFtLCBzdWJJdGVtLmNoaWxkcmVuKVxuICAgICAgICApO1xuICAgICAgfSwgW10pO1xuICB9XG5cbiAgcHJpdmF0ZSBfZGV0YWNoVG9QYXJlbnQoaXRlbTogTWVudUl0ZW0pIHtcbiAgICBpZiAoIWl0ZW0/LnBhcmVudCkgcmV0dXJuOyAvLyBTa2lwIGlmIGFscmVhZHkgZGV0YWNoZWRcbiAgICBsZXQgY2hpbGRyZW4gPSBpdGVtLnBhcmVudC5jaGlsZHJlbiB8fCBbXTtcblxuICAgIC8vIFJlbW92ZSBmcm9tIHBhcmVudCBjaGlsZHJlblxuICAgIGNvbnN0IGluZGV4SW5QYXJlbnQgPSBjaGlsZHJlbi5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChpbmRleEluUGFyZW50ICE9PSAtMSkge1xuICAgICAgY2hpbGRyZW4gPSBjaGlsZHJlbi5zbGljZSgpOyAvLyBDb3B5IG9yaWdpbmFsIGFycmF5LCBiZWNhdXNlIGl0IGNhbiBiZSB1c2VkIGluIGEgbG9vcFxuICAgICAgY2hpbGRyZW4uc3BsaWNlKGluZGV4SW5QYXJlbnQsIDEpO1xuICAgICAgaXRlbS5wYXJlbnQuY2hpbGRyZW4gPSBjaGlsZHJlbjtcbiAgICB9XG5cbiAgICBpdGVtLnBhcmVudCA9IG51bGw7XG4gIH1cblxuICBwcml2YXRlIF9maW5kRXhpc3RpbmdJdGVtKHNlYXJjaEl0ZW06IElNZW51SXRlbSwgaXRlbXM/OiBNZW51SXRlbVtdLCByZWN1cnNpdmUgPSB0cnVlKTogTWVudUl0ZW0ge1xuICAgIGl0ZW1zID0gaXRlbXMgfHwgWy4uLnRoaXMuX2RldGFjaGVkU3ViSXRlbXMsIC4uLnRoaXMuZGF0YV07XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIHJldHVybiB1bmRlZmluZWQ7IC8vIE5vdCBmb3VuZFxuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgaWYgKE1lbnVJdGVtcy5pc1NhbWVJZE9yUGF0aEFuZFBhcmFtcyhzZWFyY2hJdGVtLCBpdGVtKSkgcmV0dXJuIGl0ZW07XG4gICAgICBpZiAocmVjdXJzaXZlICYmIGl0ZW0uY2hpbGRyZW4pIHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSB0aGlzLl9maW5kRXhpc3RpbmdJdGVtKHNlYXJjaEl0ZW0sIGl0ZW0uY2hpbGRyZW4pO1xuICAgICAgICBpZiAoY2hpbGQpIHJldHVybiBjaGlsZDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIF9maW5kUGFyZW50KGNoaWxkSXRlbTogTWVudUl0ZW0sIGF2YWlsYWJsZVBhcmVudHM/OiBNZW51SXRlbVtdKTogTWVudUl0ZW0ge1xuICAgIGlmICghY2hpbGRJdGVtPy5wYXRoKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChjaGlsZEl0ZW0ucGFyZW50KSByZXR1cm4gY2hpbGRJdGVtLnBhcmVudDtcblxuICAgIGF2YWlsYWJsZVBhcmVudHMgPSBhdmFpbGFibGVQYXJlbnRzIHx8IFsuLi50aGlzLl9kZXRhY2hlZFN1Ykl0ZW1zLCAuLi50aGlzLmRhdGFdO1xuXG4gICAgcmV0dXJuIGF2YWlsYWJsZVBhcmVudHMucmVkdWNlKChyZXMsIGl0ZW0pID0+IHtcbiAgICAgIGlmICghaXRlbT8ucGF0aCkgcmV0dXJuIHJlcztcblxuICAgICAgLy8gQSBmb3VuZCBpdGVtIGFscmVhZHkgbWF0Y2ggd2l0aCB0aGUgbWVudUl0ZW0ucGFyZW50UGF0aCA6IGtlZXAgaXQgYXMgaXRcbiAgICAgIC8vIFRoZXJlIGlzIGEgZm91bmQgY2FuZGlkYXRlIHRoYXQgYWxyZWFkeSBtYXRjaCB0aGUgY3VycmVudCBjYW5kaWRhdGUgOiBrZWVwIGl0XG4gICAgICBpZiAoTWVudUl0ZW1zLmlzUGFyZW50KGNoaWxkSXRlbSwgcmVzKSkgcmV0dXJuIHJlcztcblxuICAgICAgLy8gSWYgdGhlIG1lbnUgaXRlbSBoYXMgZXhwbGljaXQgcGFyZW50UGF0aCBhbmQgaXRzIHBhdGggYW5kIHBhdGggcGFyYW0gYXJlIHRoZSBzYW1lIGFzIHRoZSBjYW5kaWRhdGUgIDogdXNlIGl0IGFzIHBhcmVudFxuICAgICAgaWYgKE1lbnVJdGVtcy5pc1BhcmVudChjaGlsZEl0ZW0sIGl0ZW0pKSByZXR1cm4gaXRlbTtcblxuICAgICAgaWYgKCFyZXMgJiYgaXRlbS5jaGlsZHJlbj8ubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9maW5kUGFyZW50KGNoaWxkSXRlbSwgaXRlbS5jaGlsZHJlbik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXM7XG4gICAgfSwgdW5kZWZpbmVkKTtcbiAgfTtcblxuICBwcml2YXRlIF9hdHRhY2hNZW51VG9QYXJlbnQocGFyZW50OiBNZW51SXRlbSwgY2hpbGQ6IE1lbnVJdGVtKSB7XG5cbiAgICBpZiAodGhpcy5fZGVidWcpIGNvbnNvbGUuZGVidWcoYCR7dGhpcy5fbG9nUHJlZml4fUF0dGFjaCBzdWItbWVudSB7JHtNZW51SXRlbXMuZ2V0VXJsKGNoaWxkKX19IHRvIHBhcmVudCB7JHtNZW51SXRlbXMuZ2V0VXJsKHBhcmVudCl9fWApO1xuXG4gICAgLy8gQXZvaWQgdG8ga2VlcCBpZGVudGljYWwgbWVudSBpdGVtICh3ZSByZXBsYWNlIGl0IHdpdGggdGhlIG5ldyBjaGlsZCBtZW51IGl0ZW0pXG4gICAgLy9pZiAoIXBhcmVudD8uJGNoaWxkcmVuKSBwYXJlbnQuJGNoaWxkcmVuID0gbmV3IEJlaGF2aW9yU3ViamVjdDxNZW51SXRlbVtdPihbXSk7XG4gICAgY29uc3QgY2hpbGRyZW4gPSBwYXJlbnQuY2hpbGRyZW4gfHwgW107XG4gICAgY29uc3QgZXhpc3RpbmdJbmRleCA9IGNoaWxkcmVuLmZpbmRJbmRleChpdGVtID0+IE1lbnVJdGVtcy5pc1NhbWVJZE9yUGF0aEFuZFBhcmFtcyhpdGVtLCBjaGlsZCkpO1xuXG4gICAgLy8gVXBkYXRlIGV4aXN0aW5nIGVsZW1lbnRcbiAgICBpZiAoZXhpc3RpbmdJbmRleCAhPT0gLTEpIHtcbiAgICAgIGlmIChjaGlsZHJlbltleGlzdGluZ0luZGV4XSAhPT0gY2hpbGQpIHtcbiAgICAgICAgY2hpbGRyZW5bZXhpc3RpbmdJbmRleF0gPSBjaGlsZDtcbiAgICAgICAgcGFyZW50LmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgICAgIGNoaWxkLnBhcmVudCA9IHBhcmVudDtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBjaGlsZHJlbi5wdXNoKGNoaWxkKTtcblxuICAgICAgLy8gU29ydCBieSB0YWIgKG9yIGlkKVxuICAgICAgcGFyZW50LmNoaWxkcmVuID0gY2hpbGRyZW4uc29ydChNZW51SXRlbXMuc29ydEJ5VGFiT3JJZCk7XG4gICAgICBjaGlsZC5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgfVxuICB9XG5cbn1cbiJdfQ==
|