@valtimo/admin-settings 13.46.0 → 13.47.0
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/fesm2022/valtimo-admin-settings.mjs +770 -27
- package/fesm2022/valtimo-admin-settings.mjs.map +1 -1
- package/lib/components/admin-settings/admin-settings.component.d.ts +1 -0
- package/lib/components/admin-settings-menu-configuration/admin-settings-menu-configuration.component.d.ts +172 -0
- package/lib/constants/admin-settings.constants.d.ts +1 -0
- package/lib/constants/index.d.ts +1 -0
- package/lib/constants/menu-configuration.test-ids.d.ts +10 -0
- package/lib/models/index.d.ts +1 -0
- package/lib/models/menu-configuration.model.d.ts +22 -0
- package/package.json +1 -1
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, NgModule } from '@angular/core';
|
|
3
|
-
import * as i1$
|
|
2
|
+
import { Injectable, Input, ChangeDetectionStrategy, Component, signal, computed, EventEmitter, Output, NgModule } from '@angular/core';
|
|
3
|
+
import * as i1$2 from '@angular/router';
|
|
4
4
|
import { RouterModule } from '@angular/router';
|
|
5
5
|
import * as i6 from '@angular/common';
|
|
6
6
|
import { CommonModule, DatePipe } from '@angular/common';
|
|
7
7
|
import { AuthGuardService } from '@valtimo/security';
|
|
8
8
|
import * as i2 from '@valtimo/shared';
|
|
9
|
-
import { BaseApiService, ROLE_ADMIN } from '@valtimo/shared';
|
|
10
|
-
import * as
|
|
9
|
+
import { BaseApiService, IncludeFunction, ROLE_ADMIN } from '@valtimo/shared';
|
|
10
|
+
import * as i5 from '@ngx-translate/core';
|
|
11
11
|
import { TranslatePipe, TranslateModule } from '@ngx-translate/core';
|
|
12
12
|
import * as i4 from 'carbon-components-angular';
|
|
13
|
-
import { LayerModule, ButtonModule, FileUploaderModule, LoadingModule, IconModule, LinkModule, NotificationModule, ToggleModule,
|
|
14
|
-
import { catchError, of, BehaviorSubject, switchMap, map, tap, Subscription,
|
|
13
|
+
import { LayerModule, ButtonModule, FileUploaderModule, LoadingModule, IconModule, LinkModule, NotificationModule, ToggleModule, InputModule, ModalModule, SelectModule, TagModule, TabsModule, CheckboxModule, DatePickerInputModule, DatePickerModule, DropdownModule, ProgressBarModule } from 'carbon-components-angular';
|
|
14
|
+
import { catchError, of, BehaviorSubject, switchMap, map, tap, Subscription, merge, forkJoin, Subject, finalize, shareReplay, startWith, interval, takeWhile, takeUntil, take } from 'rxjs';
|
|
15
15
|
import * as i2$1 from '@valtimo/components';
|
|
16
|
-
import { ConfirmationModalModule, RenderInBodyComponent, ColorPickerComponent, MuuriDirectiveModule, ValtimoCdsModalDirective, TooltipIconModule, ViewType, CarbonListModule } from '@valtimo/components';
|
|
17
|
-
import * as
|
|
16
|
+
import { ConfirmationModalModule, RenderInBodyComponent, ColorPickerComponent, MuuriDirectiveModule, hasSavedMenuConfiguration, buildMenuConfigurationFromRuntimeMenu, serializeIncludeFunction, MENU_CONFIGURATION_VERSION, getMenuCatalogEntry, MENU_ITEM_CATALOG, DragDropListComponent, FitPageDirective, MdiIconSelectorComponent, TooltipModule, ValtimoCdsModalDirective, TooltipIconModule, ViewType, CarbonListModule } from '@valtimo/components';
|
|
17
|
+
import * as i1$1 from '@angular/forms';
|
|
18
18
|
import { Validators, ReactiveFormsModule } from '@angular/forms';
|
|
19
|
-
import { Upload16, TrashCan16, Reset16, Launch16 } from '@carbon/icons';
|
|
19
|
+
import { Upload16, TrashCan16, Reset16, Add16, Edit16, Locked16, Launch16 } from '@carbon/icons';
|
|
20
20
|
import * as i1 from '@angular/common/http';
|
|
21
21
|
import { HttpParams } from '@angular/common/http';
|
|
22
|
+
import { moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
|
|
23
|
+
import * as i8 from '@angular/cdk/scrolling';
|
|
24
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
25
|
+
import { toObservable, toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
26
|
+
import * as i3 from '@valtimo/plugin';
|
|
22
27
|
import * as i2$2 from '@valtimo/document';
|
|
23
28
|
|
|
24
29
|
/*
|
|
@@ -96,6 +101,7 @@ const ACCENT_COLOR_DEFINITIONS = [
|
|
|
96
101
|
*/
|
|
97
102
|
const ADMIN_SETTINGS_TABS = {
|
|
98
103
|
APPEARANCE: 'appearance',
|
|
104
|
+
MENU_CONFIGURATION: 'menu-configuration',
|
|
99
105
|
FEATURE_TOGGLES: 'feature-toggles',
|
|
100
106
|
};
|
|
101
107
|
|
|
@@ -142,6 +148,31 @@ const FEATURE_TOGGLE_DEFINITIONS = [
|
|
|
142
148
|
{ key: 'disableFormioTokenInLocalStorage' },
|
|
143
149
|
];
|
|
144
150
|
|
|
151
|
+
/*
|
|
152
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
153
|
+
*
|
|
154
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
155
|
+
* you may not use this file except in compliance with the License.
|
|
156
|
+
* You may obtain a copy of the License at
|
|
157
|
+
*
|
|
158
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
159
|
+
*
|
|
160
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
161
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
162
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
163
|
+
* See the License for the specific language governing permissions and
|
|
164
|
+
* limitations under the License.
|
|
165
|
+
*/
|
|
166
|
+
const MENU_CONFIGURATION_TEST_IDS = {
|
|
167
|
+
saveButton: 'menuConfigurationSaveButton',
|
|
168
|
+
resetButton: 'menuConfigurationResetButton',
|
|
169
|
+
structureList: 'menuConfigurationStructureList',
|
|
170
|
+
editorTitleInput: 'menuConfigurationEditorTitleInput',
|
|
171
|
+
editorLinkInput: 'menuConfigurationEditorLinkInput',
|
|
172
|
+
editorSaveButton: 'menuConfigurationEditorSaveButton',
|
|
173
|
+
editorCancelButton: 'menuConfigurationEditorCancelButton',
|
|
174
|
+
};
|
|
175
|
+
|
|
145
176
|
/*
|
|
146
177
|
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
147
178
|
*
|
|
@@ -316,8 +347,8 @@ class AdminSettingsLogoComponent {
|
|
|
316
347
|
reader.onerror = error => reject(error);
|
|
317
348
|
});
|
|
318
349
|
}
|
|
319
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsLogoComponent, deps: [{ token: AdminSettingsManagementApiService }, { token: i2$1.AdminSettingsService }, { token:
|
|
320
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsLogoComponent, isStandalone: true, selector: "valtimo-admin-settings-logo", inputs: { logoType: "logoType", titleTranslationKey: "titleTranslationKey" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<form\n *ngIf=\"{\n logo: logo$ | async,\n loading: loading$ | async,\n } as obs\"\n class=\"admin-settings-logo\"\n [formGroup]=\"formGroup\"\n [cdsLayer]=\"1\"\n>\n <h4 class=\"admin-settings-logo__title\">\n {{ titleTranslationKey | translate }}\n </h4>\n\n @if (obs.loading) {\n <div class=\"loading-container\"><cds-loading></cds-loading></div>\n } @else if (obs.logo) {\n <div class=\"admin-settings-logo__preview\" [attr.data-carbon-theme]=\"previewTheme\">\n <img\n class=\"admin-settings-logo__image\"\n [src]=\"getImageSrc(obs.logo.imageBase64)\"\n />\n </div>\n\n <div class=\"admin-settings-logo__buttons\">\n <button cdsButton=\"danger\" (click)=\"onDeleteButtonClick()\" [disabled]=\"formGroup.disabled\">\n {{ 'interface.delete' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n </div>\n } @else {\n <cds-file-uploader\n [accept]=\"ACCEPTED_FILES\"\n [multiple]=\"false\"\n buttonType=\"primary\"\n [title]=\"'adminSettings.appearance.logo.fileUploaderTitle' | translate\"\n [description]=\"'adminSettings.appearance.logo.fileUploaderDescription' | translate\"\n [buttonText]=\"'adminSettings.appearance.logo.fileUploaderButton' | translate\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n\n <div class=\"admin-settings-logo__buttons\">\n <button\n cdsButton=\"primary\"\n [disabled]=\"formGroup.disabled || formGroup.invalid || formGroup.pristine\"\n (click)=\"onSave()\"\n >\n {{ 'interface.upload' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n </div>\n }\n</form>\n\n<valtimo-render-in-body>\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"adminSettings.appearance.logo.deleteConfirmationModalText\"\n [showModalSubject$]=\"showDeleteConfirmationModal$\"\n titleTranslationKey=\"interface.delete\"\n (confirmEvent)=\"onDelete()\"\n ></valtimo-confirmation-modal>\n</valtimo-render-in-body>\n", styles: [".admin-settings-logo{display:flex;flex-direction:column;gap:16px;padding:16px;background-color:var(--cds-layer-01)}.admin-settings-logo__title{font-size:16px;line-height:24px;font-weight:600;margin-bottom:8px}.admin-settings-logo__preview{display:flex;justify-content:center;align-items:center;background-color:var(--cds-background);padding:24px;min-height:180px}.admin-settings-logo__image{max-width:100%;max-height:300px;object-fit:contain}.admin-settings-logo__buttons{display:flex;justify-content:flex-end;width:100%;margin-top:12px}.admin-settings-logo__buttons button[cdsButton]{min-width:100px}.loading-container{display:flex;width:100%;justify-content:center;align-items:center;min-height:180px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type:
|
|
350
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsLogoComponent, deps: [{ token: AdminSettingsManagementApiService }, { token: i2$1.AdminSettingsService }, { token: i1$1.FormBuilder }, { token: i4.IconService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
351
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsLogoComponent, isStandalone: true, selector: "valtimo-admin-settings-logo", inputs: { logoType: "logoType", titleTranslationKey: "titleTranslationKey" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<form\n *ngIf=\"{\n logo: logo$ | async,\n loading: loading$ | async,\n } as obs\"\n class=\"admin-settings-logo\"\n [formGroup]=\"formGroup\"\n [cdsLayer]=\"1\"\n>\n <h4 class=\"admin-settings-logo__title\">\n {{ titleTranslationKey | translate }}\n </h4>\n\n @if (obs.loading) {\n <div class=\"loading-container\"><cds-loading></cds-loading></div>\n } @else if (obs.logo) {\n <div class=\"admin-settings-logo__preview\" [attr.data-carbon-theme]=\"previewTheme\">\n <img\n class=\"admin-settings-logo__image\"\n [src]=\"getImageSrc(obs.logo.imageBase64)\"\n />\n </div>\n\n <div class=\"admin-settings-logo__buttons\">\n <button cdsButton=\"danger\" (click)=\"onDeleteButtonClick()\" [disabled]=\"formGroup.disabled\">\n {{ 'interface.delete' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n </div>\n } @else {\n <cds-file-uploader\n [accept]=\"ACCEPTED_FILES\"\n [multiple]=\"false\"\n buttonType=\"primary\"\n [title]=\"'adminSettings.appearance.logo.fileUploaderTitle' | translate\"\n [description]=\"'adminSettings.appearance.logo.fileUploaderDescription' | translate\"\n [buttonText]=\"'adminSettings.appearance.logo.fileUploaderButton' | translate\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n\n <div class=\"admin-settings-logo__buttons\">\n <button\n cdsButton=\"primary\"\n [disabled]=\"formGroup.disabled || formGroup.invalid || formGroup.pristine\"\n (click)=\"onSave()\"\n >\n {{ 'interface.upload' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n </div>\n }\n</form>\n\n<valtimo-render-in-body>\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"adminSettings.appearance.logo.deleteConfirmationModalText\"\n [showModalSubject$]=\"showDeleteConfirmationModal$\"\n titleTranslationKey=\"interface.delete\"\n (confirmEvent)=\"onDelete()\"\n ></valtimo-confirmation-modal>\n</valtimo-render-in-body>\n", styles: [".admin-settings-logo{display:flex;flex-direction:column;gap:16px;padding:16px;background-color:var(--cds-layer-01)}.admin-settings-logo__title{font-size:16px;line-height:24px;font-weight:600;margin-bottom:8px}.admin-settings-logo__preview{display:flex;justify-content:center;align-items:center;background-color:var(--cds-background);padding:24px;min-height:180px}.admin-settings-logo__image{max-width:100%;max-height:300px;object-fit:contain}.admin-settings-logo__buttons{display:flex;justify-content:flex-end;width:100%;margin-top:12px}.admin-settings-logo__buttons button[cdsButton]{min-width:100px}.loading-container{display:flex;width:100%;justify-content:center;align-items:center;min-height:180px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i4.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: FileUploaderModule }, { kind: "component", type: i4.FileUploader, selector: "cds-file-uploader, ibm-file-uploader", inputs: ["buttonText", "buttonType", "title", "description", "accept", "multiple", "skeleton", "size", "fileItemSize", "drop", "dropText", "fileUploaderId", "files", "disabled"], outputs: ["filesChange"] }, { kind: "ngmodule", type: LoadingModule }, { kind: "component", type: i4.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i2$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }, { kind: "component", type: RenderInBodyComponent, selector: "valtimo-render-in-body" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
321
352
|
}
|
|
322
353
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsLogoComponent, decorators: [{
|
|
323
354
|
type: Component,
|
|
@@ -333,7 +364,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
333
364
|
ConfirmationModalModule,
|
|
334
365
|
RenderInBodyComponent,
|
|
335
366
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<form\n *ngIf=\"{\n logo: logo$ | async,\n loading: loading$ | async,\n } as obs\"\n class=\"admin-settings-logo\"\n [formGroup]=\"formGroup\"\n [cdsLayer]=\"1\"\n>\n <h4 class=\"admin-settings-logo__title\">\n {{ titleTranslationKey | translate }}\n </h4>\n\n @if (obs.loading) {\n <div class=\"loading-container\"><cds-loading></cds-loading></div>\n } @else if (obs.logo) {\n <div class=\"admin-settings-logo__preview\" [attr.data-carbon-theme]=\"previewTheme\">\n <img\n class=\"admin-settings-logo__image\"\n [src]=\"getImageSrc(obs.logo.imageBase64)\"\n />\n </div>\n\n <div class=\"admin-settings-logo__buttons\">\n <button cdsButton=\"danger\" (click)=\"onDeleteButtonClick()\" [disabled]=\"formGroup.disabled\">\n {{ 'interface.delete' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n </div>\n } @else {\n <cds-file-uploader\n [accept]=\"ACCEPTED_FILES\"\n [multiple]=\"false\"\n buttonType=\"primary\"\n [title]=\"'adminSettings.appearance.logo.fileUploaderTitle' | translate\"\n [description]=\"'adminSettings.appearance.logo.fileUploaderDescription' | translate\"\n [buttonText]=\"'adminSettings.appearance.logo.fileUploaderButton' | translate\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n\n <div class=\"admin-settings-logo__buttons\">\n <button\n cdsButton=\"primary\"\n [disabled]=\"formGroup.disabled || formGroup.invalid || formGroup.pristine\"\n (click)=\"onSave()\"\n >\n {{ 'interface.upload' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n </div>\n }\n</form>\n\n<valtimo-render-in-body>\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"adminSettings.appearance.logo.deleteConfirmationModalText\"\n [showModalSubject$]=\"showDeleteConfirmationModal$\"\n titleTranslationKey=\"interface.delete\"\n (confirmEvent)=\"onDelete()\"\n ></valtimo-confirmation-modal>\n</valtimo-render-in-body>\n", styles: [".admin-settings-logo{display:flex;flex-direction:column;gap:16px;padding:16px;background-color:var(--cds-layer-01)}.admin-settings-logo__title{font-size:16px;line-height:24px;font-weight:600;margin-bottom:8px}.admin-settings-logo__preview{display:flex;justify-content:center;align-items:center;background-color:var(--cds-background);padding:24px;min-height:180px}.admin-settings-logo__image{max-width:100%;max-height:300px;object-fit:contain}.admin-settings-logo__buttons{display:flex;justify-content:flex-end;width:100%;margin-top:12px}.admin-settings-logo__buttons button[cdsButton]{min-width:100px}.loading-container{display:flex;width:100%;justify-content:center;align-items:center;min-height:180px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
336
|
-
}], ctorParameters: () => [{ type: AdminSettingsManagementApiService }, { type: i2$1.AdminSettingsService }, { type:
|
|
367
|
+
}], ctorParameters: () => [{ type: AdminSettingsManagementApiService }, { type: i2$1.AdminSettingsService }, { type: i1$1.FormBuilder }, { type: i4.IconService }], propDecorators: { logoType: [{
|
|
337
368
|
type: Input
|
|
338
369
|
}], titleTranslationKey: [{
|
|
339
370
|
type: Input
|
|
@@ -450,8 +481,8 @@ class AdminSettingsColorComponent {
|
|
|
450
481
|
}
|
|
451
482
|
return value;
|
|
452
483
|
}
|
|
453
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsColorComponent, deps: [{ token: AdminSettingsManagementApiService }, { token: i2$1.AdminSettingsService }, { token:
|
|
454
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsColorComponent, isStandalone: true, selector: "valtimo-admin-settings-color", ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<form\n *ngIf=\"{\n colors: colors$ | async,\n loading: loading$ | async,\n saving: saving$ | async,\n pickrI18n: pickrI18n$ | async,\n } as obs\"\n class=\"admin-settings-color\"\n [formGroup]=\"formGroup\"\n [cdsLayer]=\"1\"\n>\n <h4 class=\"admin-settings-color__title\">\n {{ 'adminSettings.appearance.colors.title' | translate }}\n </h4>\n\n <ng-template #infoNotification>\n <p>\n {{ 'adminSettings.appearance.colors.infoMessage' | translate }}\n\n <a [href]=\"DOCS_URL\" target=\"_blank\" rel=\"noopener noreferrer\" cdsLink>\n {{ 'adminSettings.appearance.colors.infoLinkText' | translate }}\n </a>\n </p>\n </ng-template>\n\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'info',\n title: '',\n template: infoNotification,\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n\n @if (obs.loading) {\n <div class=\"loading-container\"><cds-loading></cds-loading></div>\n } @else {\n <div class=\"admin-settings-color__grid\">\n @for (def of ACCENT_COLOR_DEFINITIONS; track def.cssVar) {\n <div class=\"admin-settings-color__field\">\n <valtimo-color-picker\n [formControlName]=\"def.cssVar\"\n [labelTranslationKey]=\"def.labelTranslationKey\"\n [config]=\"{opacity: false, lockOpacity: true}\"\n [i18n]=\"obs.pickrI18n\"\n (clearEvent)=\"onReset(def)\"\n ></valtimo-color-picker>\n\n <button\n cdsButton=\"ghost\"\n [disabled]=\"isDefaultColor(def)\"\n [iconOnly]=\"true\"\n size=\"sm\"\n (click)=\"onReset(def)\"\n class=\"admin-settings-color__reset\"\n >\n <svg cdsIcon=\"reset\" size=\"16\"></svg>\n </button>\n </div>\n }\n </div>\n\n <div class=\"admin-settings-color__buttons\">\n <button\n cdsButton=\"primary\"\n [disabled]=\"formGroup.disabled || formGroup.pristine || obs.saving\"\n (click)=\"onSave()\"\n >\n {{ 'interface.save' | translate }}\n </button>\n </div>\n }\n</form>\n", styles: [".admin-settings-color{display:flex;flex-direction:column;gap:16px;padding:16px;background-color:var(--cds-layer-01)}.admin-settings-color__title{font-size:16px;line-height:24px;font-weight:600;margin-bottom:8px}.admin-settings-color__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:16px}.admin-settings-color__field{display:flex;flex-direction:row;align-items:flex-end;gap:4px}.admin-settings-color__field valtimo-color-picker{flex:1;min-width:0}.admin-settings-color__reset{flex-shrink:0}.admin-settings-color__buttons{display:flex;justify-content:flex-end;width:100%;margin-top:12px}.admin-settings-color__buttons button[cdsButton]{min-width:100px}.loading-container{display:flex;width:100%;justify-content:center;align-items:center;min-height:180px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type:
|
|
484
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsColorComponent, deps: [{ token: AdminSettingsManagementApiService }, { token: i2$1.AdminSettingsService }, { token: i1$1.FormBuilder }, { token: i4.IconService }, { token: i5.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
485
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsColorComponent, isStandalone: true, selector: "valtimo-admin-settings-color", ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<form\n *ngIf=\"{\n colors: colors$ | async,\n loading: loading$ | async,\n saving: saving$ | async,\n pickrI18n: pickrI18n$ | async,\n } as obs\"\n class=\"admin-settings-color\"\n [formGroup]=\"formGroup\"\n [cdsLayer]=\"1\"\n>\n <h4 class=\"admin-settings-color__title\">\n {{ 'adminSettings.appearance.colors.title' | translate }}\n </h4>\n\n <ng-template #infoNotification>\n <p>\n {{ 'adminSettings.appearance.colors.infoMessage' | translate }}\n\n <a [href]=\"DOCS_URL\" target=\"_blank\" rel=\"noopener noreferrer\" cdsLink>\n {{ 'adminSettings.appearance.colors.infoLinkText' | translate }}\n </a>\n </p>\n </ng-template>\n\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'info',\n title: '',\n template: infoNotification,\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n\n @if (obs.loading) {\n <div class=\"loading-container\"><cds-loading></cds-loading></div>\n } @else {\n <div class=\"admin-settings-color__grid\">\n @for (def of ACCENT_COLOR_DEFINITIONS; track def.cssVar) {\n <div class=\"admin-settings-color__field\">\n <valtimo-color-picker\n [formControlName]=\"def.cssVar\"\n [labelTranslationKey]=\"def.labelTranslationKey\"\n [config]=\"{opacity: false, lockOpacity: true}\"\n [i18n]=\"obs.pickrI18n\"\n (clearEvent)=\"onReset(def)\"\n ></valtimo-color-picker>\n\n <button\n cdsButton=\"ghost\"\n [disabled]=\"isDefaultColor(def)\"\n [iconOnly]=\"true\"\n size=\"sm\"\n (click)=\"onReset(def)\"\n class=\"admin-settings-color__reset\"\n >\n <svg cdsIcon=\"reset\" size=\"16\"></svg>\n </button>\n </div>\n }\n </div>\n\n <div class=\"admin-settings-color__buttons\">\n <button\n cdsButton=\"primary\"\n [disabled]=\"formGroup.disabled || formGroup.pristine || obs.saving\"\n (click)=\"onSave()\"\n >\n {{ 'interface.save' | translate }}\n </button>\n </div>\n }\n</form>\n", styles: [".admin-settings-color{display:flex;flex-direction:column;gap:16px;padding:16px;background-color:var(--cds-layer-01)}.admin-settings-color__title{font-size:16px;line-height:24px;font-weight:600;margin-bottom:8px}.admin-settings-color__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:16px}.admin-settings-color__field{display:flex;flex-direction:row;align-items:flex-end;gap:4px}.admin-settings-color__field valtimo-color-picker{flex:1;min-width:0}.admin-settings-color__reset{flex-shrink:0}.admin-settings-color__buttons{display:flex;justify-content:flex-end;width:100%;margin-top:12px}.admin-settings-color__buttons button[cdsButton]{min-width:100px}.loading-container{display:flex;width:100%;justify-content:center;align-items:center;min-height:180px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i4.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: LoadingModule }, { kind: "component", type: i4.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "ngmodule", type: LinkModule }, { kind: "directive", type: i4.Link, selector: "[cdsLink], [ibmLink]", inputs: ["inline", "disabled"] }, { kind: "ngmodule", type: NotificationModule }, { kind: "component", type: i4.Notification, selector: "cds-notification, cds-inline-notification, ibm-notification, ibm-inline-notification", inputs: ["notificationObj"] }, { kind: "component", type: ColorPickerComponent, selector: "valtimo-color-picker", inputs: ["labelTranslationKey", "config", "i18n"], outputs: ["colorChangeEvent", "clearEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
455
486
|
}
|
|
456
487
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsColorComponent, decorators: [{
|
|
457
488
|
type: Component,
|
|
@@ -467,7 +498,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
467
498
|
NotificationModule,
|
|
468
499
|
ColorPickerComponent,
|
|
469
500
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<form\n *ngIf=\"{\n colors: colors$ | async,\n loading: loading$ | async,\n saving: saving$ | async,\n pickrI18n: pickrI18n$ | async,\n } as obs\"\n class=\"admin-settings-color\"\n [formGroup]=\"formGroup\"\n [cdsLayer]=\"1\"\n>\n <h4 class=\"admin-settings-color__title\">\n {{ 'adminSettings.appearance.colors.title' | translate }}\n </h4>\n\n <ng-template #infoNotification>\n <p>\n {{ 'adminSettings.appearance.colors.infoMessage' | translate }}\n\n <a [href]=\"DOCS_URL\" target=\"_blank\" rel=\"noopener noreferrer\" cdsLink>\n {{ 'adminSettings.appearance.colors.infoLinkText' | translate }}\n </a>\n </p>\n </ng-template>\n\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'info',\n title: '',\n template: infoNotification,\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n\n @if (obs.loading) {\n <div class=\"loading-container\"><cds-loading></cds-loading></div>\n } @else {\n <div class=\"admin-settings-color__grid\">\n @for (def of ACCENT_COLOR_DEFINITIONS; track def.cssVar) {\n <div class=\"admin-settings-color__field\">\n <valtimo-color-picker\n [formControlName]=\"def.cssVar\"\n [labelTranslationKey]=\"def.labelTranslationKey\"\n [config]=\"{opacity: false, lockOpacity: true}\"\n [i18n]=\"obs.pickrI18n\"\n (clearEvent)=\"onReset(def)\"\n ></valtimo-color-picker>\n\n <button\n cdsButton=\"ghost\"\n [disabled]=\"isDefaultColor(def)\"\n [iconOnly]=\"true\"\n size=\"sm\"\n (click)=\"onReset(def)\"\n class=\"admin-settings-color__reset\"\n >\n <svg cdsIcon=\"reset\" size=\"16\"></svg>\n </button>\n </div>\n }\n </div>\n\n <div class=\"admin-settings-color__buttons\">\n <button\n cdsButton=\"primary\"\n [disabled]=\"formGroup.disabled || formGroup.pristine || obs.saving\"\n (click)=\"onSave()\"\n >\n {{ 'interface.save' | translate }}\n </button>\n </div>\n }\n</form>\n", styles: [".admin-settings-color{display:flex;flex-direction:column;gap:16px;padding:16px;background-color:var(--cds-layer-01)}.admin-settings-color__title{font-size:16px;line-height:24px;font-weight:600;margin-bottom:8px}.admin-settings-color__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:16px}.admin-settings-color__field{display:flex;flex-direction:row;align-items:flex-end;gap:4px}.admin-settings-color__field valtimo-color-picker{flex:1;min-width:0}.admin-settings-color__reset{flex-shrink:0}.admin-settings-color__buttons{display:flex;justify-content:flex-end;width:100%;margin-top:12px}.admin-settings-color__buttons button[cdsButton]{min-width:100px}.loading-container{display:flex;width:100%;justify-content:center;align-items:center;min-height:180px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
470
|
-
}], ctorParameters: () => [{ type: AdminSettingsManagementApiService }, { type: i2$1.AdminSettingsService }, { type:
|
|
501
|
+
}], ctorParameters: () => [{ type: AdminSettingsManagementApiService }, { type: i2$1.AdminSettingsService }, { type: i1$1.FormBuilder }, { type: i4.IconService }, { type: i5.TranslateService }] });
|
|
471
502
|
|
|
472
503
|
/*
|
|
473
504
|
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
@@ -542,6 +573,701 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
542
573
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n@if (featureToggles$ | async; as toggles) {\n <div class=\"feature-toggles\">\n <div class=\"feature-toggles__list\">\n @if (searchEngine$ | async; as searchEngine) {\n <div class=\"feature-toggles__item\" [class.feature-toggles__item--disabled]=\"!searchEngine.available\">\n <div class=\"feature-toggles__info\">\n <span class=\"feature-toggles__title\">\n {{ 'adminSettings.featureToggles.searchEngine.useOpenSearch.title' | translate }}\n </span>\n <span class=\"feature-toggles__description\">\n @if (searchEngine.available) {\n {{ 'adminSettings.featureToggles.searchEngine.useOpenSearch.description' | translate }}\n } @else {\n {{ 'adminSettings.featureToggles.searchEngine.useOpenSearch.unavailable' | translate }}\n }\n </span>\n </div>\n <div class=\"feature-toggles__control\">\n <cds-toggle\n [checked]=\"searchEngine.active === 'OPENSEARCH'\"\n [onText]=\"'interface.on' | translate\"\n [offText]=\"'interface.off' | translate\"\n [size]=\"'sm'\"\n [disabled]=\"!searchEngine.available\"\n (checkedChange)=\"onSearchEngineChange($event)\"\n ></cds-toggle>\n </div>\n </div>\n }\n @for (definition of TOGGLE_DEFINITIONS; track definition.key) {\n <div class=\"feature-toggles__item\">\n <div class=\"feature-toggles__info\">\n <span class=\"feature-toggles__title\">\n {{ 'adminSettings.featureToggles.toggles.' + definition.key + '.title' | translate }}\n </span>\n\n <span class=\"feature-toggles__description\">\n {{ 'adminSettings.featureToggles.toggles.' + definition.key + '.description' | translate }}\n </span>\n </div>\n\n <div class=\"feature-toggles__control\">\n <cds-toggle\n [checked]=\"getEffectiveValue(definition, toggles)\"\n [onText]=\"'interface.on' | translate\"\n [offText]=\"'interface.off' | translate\"\n [size]=\"'sm'\"\n (checkedChange)=\"onToggleChange(definition, $event)\"\n ></cds-toggle>\n </div>\n </div>\n }\n </div>\n </div>\n}\n", styles: [".feature-toggles{width:100%}.feature-toggles__list{display:flex;flex-direction:column}.feature-toggles__item{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:16px 0;border-bottom:1px solid var(--cds-border-subtle)}.feature-toggles__item:last-child{border-bottom:none}.feature-toggles__item--disabled{opacity:.5}.feature-toggles__info{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.feature-toggles__title{font-size:14px;font-weight:600;color:var(--cds-text-primary)}.feature-toggles__description{font-size:12px;color:var(--cds-text-secondary)}.feature-toggles__control{display:flex;align-items:center;gap:12px;flex-shrink:0}.loading-container{display:flex;justify-content:center;padding:48px 0}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
543
574
|
}], ctorParameters: () => [{ type: AdminSettingsManagementApiService }, { type: i2$1.AdminSettingsService }, { type: i2.ConfigService }] });
|
|
544
575
|
|
|
576
|
+
/*
|
|
577
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
578
|
+
*
|
|
579
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
580
|
+
* you may not use this file except in compliance with the License.
|
|
581
|
+
* You may obtain a copy of the License at
|
|
582
|
+
*
|
|
583
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
584
|
+
*
|
|
585
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
586
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
587
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
588
|
+
* See the License for the specific language governing permissions and
|
|
589
|
+
* limitations under the License.
|
|
590
|
+
*/
|
|
591
|
+
class AdminSettingsMenuConfigurationComponent {
|
|
592
|
+
/**
|
|
593
|
+
* True when a `.valtimo-drag-drop-list` nested *inside* `drop` currently sits under the pointer.
|
|
594
|
+
* Such a deeper list is the more specific target, so `drop` should decline the item — this keeps a
|
|
595
|
+
* reorder inside a section from being hijacked by the enclosing (ancestor) list.
|
|
596
|
+
*/
|
|
597
|
+
_pointerOverDeeperList(drop) {
|
|
598
|
+
const nested = drop.element.nativeElement.querySelectorAll('.valtimo-drag-drop-list');
|
|
599
|
+
return Array.from(nested).some(list => {
|
|
600
|
+
const r = list.getBoundingClientRect();
|
|
601
|
+
return (this._pointer.x >= r.left &&
|
|
602
|
+
this._pointer.x <= r.right &&
|
|
603
|
+
this._pointer.y >= r.top &&
|
|
604
|
+
this._pointer.y <= r.bottom);
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
constructor(fb, adminSettingsService, pluginPageService, configService, translateService, iconService) {
|
|
608
|
+
this.fb = fb;
|
|
609
|
+
this.adminSettingsService = adminSettingsService;
|
|
610
|
+
this.pluginPageService = pluginPageService;
|
|
611
|
+
this.configService = configService;
|
|
612
|
+
this.translateService = translateService;
|
|
613
|
+
this.iconService = iconService;
|
|
614
|
+
this.testIds = MENU_CONFIGURATION_TEST_IDS;
|
|
615
|
+
this.$loading = signal(true);
|
|
616
|
+
this.$saving = signal(false);
|
|
617
|
+
this.$saved = signal(false);
|
|
618
|
+
this.$structure = signal([]);
|
|
619
|
+
/** Drives the post-save "reload now?" confirmation modal. */
|
|
620
|
+
this._$reloadModalOpen = signal(false);
|
|
621
|
+
this.reloadModalOpen$ = toObservable(this._$reloadModalOpen);
|
|
622
|
+
this.$pluginPages = signal([]);
|
|
623
|
+
/** True while a drag is in progress, so the panels can desaturate the sections that cannot receive it. */
|
|
624
|
+
this.$dragging = signal(false);
|
|
625
|
+
this.$editorOpen = signal(false);
|
|
626
|
+
this.$editorKind = signal('catalog');
|
|
627
|
+
/** True while editing a required item (Admin/Settings) — its Include-function field is suppressed. */
|
|
628
|
+
this.$editorRequired = signal(false);
|
|
629
|
+
/**
|
|
630
|
+
* Bumped whenever ngx-translate (re)loads, so the translated palette/section labels — resolved
|
|
631
|
+
* imperatively via `translateService.instant` inside computeds — recompute once translations arrive
|
|
632
|
+
* (a plain computed would otherwise keep the raw keys captured on first, pre-load evaluation).
|
|
633
|
+
*/
|
|
634
|
+
this._$translationTick = signal(0);
|
|
635
|
+
this.$paletteGroups = computed(() => {
|
|
636
|
+
this._$translationTick();
|
|
637
|
+
return this._buildPaletteGroups();
|
|
638
|
+
});
|
|
639
|
+
/**
|
|
640
|
+
* All structure drop-list ids (root + every container), so each list — including palette lists and
|
|
641
|
+
* the nested container lists — connects to every structure list **by id**. CDK resolves these ids
|
|
642
|
+
* globally, so connections work regardless of DOM/DI nesting (a `cdkDropListGroup` would not see a
|
|
643
|
+
* nested list whose template is declared outside the group element).
|
|
644
|
+
*/
|
|
645
|
+
this.$structureListIds = computed(() => {
|
|
646
|
+
// Container lists are listed BEFORE the root list so that, where a nested section's drop zone
|
|
647
|
+
// overlaps the root list's area, CDK resolves to the inner (section) list first. The result:
|
|
648
|
+
// dropping inside a section's box lands in that section, while the section header row and the
|
|
649
|
+
// top-level gaps (covered only by the root list) still drop at the top level.
|
|
650
|
+
const containerIds = [];
|
|
651
|
+
this._walk(this.$structure(), node => {
|
|
652
|
+
if (this.isContainer(node))
|
|
653
|
+
containerIds.push(this.containerListId(node));
|
|
654
|
+
});
|
|
655
|
+
return [...containerIds, 'structure-root'];
|
|
656
|
+
});
|
|
657
|
+
this.includeFunctionKeys = Object.keys(IncludeFunction).filter(key => isNaN(Number(key)));
|
|
658
|
+
this.editorForm = this.fb.group({
|
|
659
|
+
title: this.fb.control('', Validators.required),
|
|
660
|
+
link: this.fb.control(''),
|
|
661
|
+
icon: this.fb.control(null),
|
|
662
|
+
includeFunction: this.fb.control(null),
|
|
663
|
+
section: this.fb.control('root'),
|
|
664
|
+
});
|
|
665
|
+
/** Sections an item can be placed in via the editor: top level + each container present in the tree. */
|
|
666
|
+
this.$sectionOptions = computed(() => {
|
|
667
|
+
this._$translationTick();
|
|
668
|
+
const options = [
|
|
669
|
+
{
|
|
670
|
+
value: 'root',
|
|
671
|
+
label: this.translateService.instant('adminSettings.menuConfiguration.editor.sectionRoot'),
|
|
672
|
+
},
|
|
673
|
+
];
|
|
674
|
+
this.$structure().forEach(node => {
|
|
675
|
+
if (this.isContainer(node))
|
|
676
|
+
options.push({ value: this._sectionValue(node), label: this.displayTitle(node) });
|
|
677
|
+
});
|
|
678
|
+
return options;
|
|
679
|
+
});
|
|
680
|
+
/** Kinds that can be freely placed in any section (and so get the editor's Section selector). */
|
|
681
|
+
this.SECTION_CAPABLE_KINDS = [
|
|
682
|
+
'custom-link',
|
|
683
|
+
'section-header',
|
|
684
|
+
'plugin-page',
|
|
685
|
+
];
|
|
686
|
+
this.$editorShowSection = computed(() => this.SECTION_CAPABLE_KINDS.includes(this.$editorKind()));
|
|
687
|
+
/** Tracks the editor's currently selected section so the icon field can react to placement changes. */
|
|
688
|
+
this._$editorSection = toSignal(this.editorForm.controls.section.valueChanges, {
|
|
689
|
+
initialValue: this.editorForm.controls.section.value,
|
|
690
|
+
});
|
|
691
|
+
/**
|
|
692
|
+
* The icon only surfaces in the rendered menu for top-level entries, so the editor hides the icon
|
|
693
|
+
* field for section headers and for any item placed inside a section (a sub-menu item).
|
|
694
|
+
*/
|
|
695
|
+
this.$editorShowIcon = computed(() => this.$editorKind() !== 'section-header' && this._$editorSection() === 'root');
|
|
696
|
+
this._editingUid = null;
|
|
697
|
+
this._pendingPaletteItem = null;
|
|
698
|
+
this._uidCounter = 0;
|
|
699
|
+
// Drop predicates — placement constraints. Every predicate also defers to a deeper nested list under
|
|
700
|
+
// the pointer (see `_pointerOverDeeperList`), so the innermost list always wins: without this, the
|
|
701
|
+
// root list — which geometrically encloses every nested list — would steal freely-placeable ('any')
|
|
702
|
+
// items (custom links, section headers, plugin pages) out of a section while you reorder inside it,
|
|
703
|
+
// because root accepts them (catalog items are protected only by their placement constraint).
|
|
704
|
+
// Palette lists reject all drops (you drag *out* of them).
|
|
705
|
+
this.topEnterPredicate = (drag, drop) => !this._pointerOverDeeperList(drop) && ['top', 'any'].includes(this._placementOf(drag.data));
|
|
706
|
+
this.adminEnterPredicate = (drag, drop) => !this._pointerOverDeeperList(drop) && this._containerAccepts('admin', drag.data);
|
|
707
|
+
this.developmentEnterPredicate = (drag, drop) => !this._pointerOverDeeperList(drop) && this._containerAccepts('development', drag.data);
|
|
708
|
+
// A custom section only accepts freely-placeable ('any') items — never another section or a
|
|
709
|
+
// placement-constrained catalog page — so the menu never nests beyond the two levels it renders.
|
|
710
|
+
this.groupEnterPredicate = (drag, drop) => !this._pointerOverDeeperList(drop) && this._placementOf(drag.data) === 'any';
|
|
711
|
+
this.paletteEnterPredicate = () => false;
|
|
712
|
+
/** Last known pointer position during a drag, used to resolve nested drop-list ambiguity. */
|
|
713
|
+
this._pointer = { x: 0, y: 0 };
|
|
714
|
+
this._trackPointer = (event) => {
|
|
715
|
+
const point = 'touches' in event ? event.touches[0] : event;
|
|
716
|
+
if (point)
|
|
717
|
+
this._pointer = { x: point.clientX, y: point.clientY };
|
|
718
|
+
};
|
|
719
|
+
this.trackByUid = (_, node) => node._uid;
|
|
720
|
+
this.iconService.registerAll([Add16, Edit16, Locked16, TrashCan16]);
|
|
721
|
+
merge(this.translateService.onLangChange, this.translateService.onDefaultLangChange, this.translateService.onTranslationChange)
|
|
722
|
+
.pipe(takeUntilDestroyed())
|
|
723
|
+
.subscribe(() => this._$translationTick.update(tick => tick + 1));
|
|
724
|
+
}
|
|
725
|
+
ngOnInit() {
|
|
726
|
+
this.load();
|
|
727
|
+
}
|
|
728
|
+
ngOnDestroy() {
|
|
729
|
+
// A drag can still be in progress when the component is destroyed (route change mid-drag), in
|
|
730
|
+
// which case onDragEnded never fires — always detach the document-level pointer listeners.
|
|
731
|
+
this._removePointerListeners();
|
|
732
|
+
}
|
|
733
|
+
// ----- Loading & seeding -----
|
|
734
|
+
load() {
|
|
735
|
+
this.$loading.set(true);
|
|
736
|
+
forkJoin({
|
|
737
|
+
dto: this.adminSettingsService
|
|
738
|
+
.getMenuConfiguration()
|
|
739
|
+
.pipe(catchError(() => of({ configuration: {} }))),
|
|
740
|
+
pages: this.pluginPageService.getMenuPages().pipe(catchError(() => of([]))),
|
|
741
|
+
}).subscribe(({ dto, pages }) => {
|
|
742
|
+
this.$pluginPages.set(pages);
|
|
743
|
+
const items = hasSavedMenuConfiguration(dto)
|
|
744
|
+
? dto.configuration.items
|
|
745
|
+
: buildMenuConfigurationFromRuntimeMenu(this.configService.config?.menu?.menuItems ?? [])
|
|
746
|
+
.items;
|
|
747
|
+
this.$structure.set(this._assignUids(items));
|
|
748
|
+
this.$loading.set(false);
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
onReset() {
|
|
752
|
+
this.load();
|
|
753
|
+
}
|
|
754
|
+
// ----- Drag & drop -----
|
|
755
|
+
onDragStarted() {
|
|
756
|
+
this.$dragging.set(true);
|
|
757
|
+
document.addEventListener('pointermove', this._trackPointer, true);
|
|
758
|
+
document.addEventListener('touchmove', this._trackPointer, true);
|
|
759
|
+
}
|
|
760
|
+
onDragEnded() {
|
|
761
|
+
this.$dragging.set(false);
|
|
762
|
+
this._removePointerListeners();
|
|
763
|
+
}
|
|
764
|
+
_removePointerListeners() {
|
|
765
|
+
document.removeEventListener('pointermove', this._trackPointer, true);
|
|
766
|
+
document.removeEventListener('touchmove', this._trackPointer, true);
|
|
767
|
+
}
|
|
768
|
+
onDrop(event) {
|
|
769
|
+
const isFromPalette = event.previousContainer.id.startsWith('palette-');
|
|
770
|
+
if (event.previousContainer === event.container) {
|
|
771
|
+
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
|
|
772
|
+
}
|
|
773
|
+
else if (isFromPalette) {
|
|
774
|
+
const node = this._paletteItemToNode(event.item.data);
|
|
775
|
+
if (!node)
|
|
776
|
+
return;
|
|
777
|
+
event.container.data.splice(event.currentIndex, 0, node);
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
|
|
781
|
+
}
|
|
782
|
+
this._bump();
|
|
783
|
+
}
|
|
784
|
+
// ----- Palette actions -----
|
|
785
|
+
onAddPaletteItem(item) {
|
|
786
|
+
// Catalog items have a fixed placement — add them straight to the matching section.
|
|
787
|
+
if (item.paletteType === 'catalog') {
|
|
788
|
+
const node = this._paletteItemToNode(item);
|
|
789
|
+
if (!node)
|
|
790
|
+
return;
|
|
791
|
+
this._defaultTargetFor(item).push(node);
|
|
792
|
+
this._bump();
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
// Generic (custom link, section header, section/group) + plugin-page items open the editor so
|
|
796
|
+
// the admin can set the title and pick the section (top level, Admin, a custom section, …)
|
|
797
|
+
// before the item is committed to the tree.
|
|
798
|
+
this.openNewItemEditor(item);
|
|
799
|
+
}
|
|
800
|
+
// ----- Row actions -----
|
|
801
|
+
openEditor(node) {
|
|
802
|
+
this._editingUid = node._uid;
|
|
803
|
+
this._pendingPaletteItem = null;
|
|
804
|
+
this.$editorKind.set(node.kind);
|
|
805
|
+
this.$editorRequired.set(this.isRequired(node));
|
|
806
|
+
this.editorForm.reset({
|
|
807
|
+
title: this._editableTitle(node),
|
|
808
|
+
// Only a custom link has an editable URL; every other kind's control is disabled and
|
|
809
|
+
// unrendered, so it is seeded empty — matching openNewItemEditor.
|
|
810
|
+
link: node.kind === 'custom-link' ? node.link : '',
|
|
811
|
+
icon: this._mdiKeyFromIconClass(this._displayIconClass(node)),
|
|
812
|
+
// Empty string (not null) so the "Geen" option (value="") is selected on open when the item
|
|
813
|
+
// carries no include function — a null value would leave the native select blank. The stored
|
|
814
|
+
// value is the enum name (or a legacy numeric ordinal); the select works with names.
|
|
815
|
+
includeFunction: node.kind === 'catalog' && !this.isRequired(node)
|
|
816
|
+
? (serializeIncludeFunction(node.includeFunction) ?? '')
|
|
817
|
+
: '',
|
|
818
|
+
section: this._findSectionOf(node._uid),
|
|
819
|
+
});
|
|
820
|
+
this._syncLinkControl(node.kind);
|
|
821
|
+
this.$editorOpen.set(true);
|
|
822
|
+
}
|
|
823
|
+
openNewItemEditor(item) {
|
|
824
|
+
this._editingUid = null;
|
|
825
|
+
this._pendingPaletteItem = item;
|
|
826
|
+
this.$editorKind.set(item.paletteType);
|
|
827
|
+
this.$editorRequired.set(false);
|
|
828
|
+
const defaultTitle = item.paletteType === 'section-header'
|
|
829
|
+
? this.translateService.instant('adminSettings.menuConfiguration.defaults.sectionHeader')
|
|
830
|
+
: item.paletteType === 'custom-link'
|
|
831
|
+
? this.translateService.instant('adminSettings.menuConfiguration.defaults.customLink')
|
|
832
|
+
: item.paletteType === 'group'
|
|
833
|
+
? this.translateService.instant('adminSettings.menuConfiguration.defaults.group')
|
|
834
|
+
: item.label;
|
|
835
|
+
this.editorForm.reset({
|
|
836
|
+
title: defaultTitle,
|
|
837
|
+
link: item.paletteType === 'custom-link' ? '/' : '',
|
|
838
|
+
icon: item.icon ? this._mdiKeyFromIconClass(item.icon) : null,
|
|
839
|
+
includeFunction: '',
|
|
840
|
+
section: 'root',
|
|
841
|
+
});
|
|
842
|
+
this._syncLinkControl(item.paletteType);
|
|
843
|
+
this.$editorOpen.set(true);
|
|
844
|
+
}
|
|
845
|
+
onEditorSave() {
|
|
846
|
+
if (this.editorForm.invalid)
|
|
847
|
+
return;
|
|
848
|
+
const value = this.editorForm.getRawValue();
|
|
849
|
+
const node = this._editingUid !== null
|
|
850
|
+
? this._findByUid(this.$structure(), this._editingUid)
|
|
851
|
+
: this._pendingPaletteItem
|
|
852
|
+
? this._paletteItemToNode(this._pendingPaletteItem)
|
|
853
|
+
: null;
|
|
854
|
+
if (!node) {
|
|
855
|
+
this.closeEditor();
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
node.title = (value.title ?? '').trim();
|
|
859
|
+
if (node.kind === 'custom-link') {
|
|
860
|
+
node.link = (value.link ?? '').trim();
|
|
861
|
+
}
|
|
862
|
+
if (node.kind === 'catalog' || node.kind === 'custom-link' || node.kind === 'plugin-page') {
|
|
863
|
+
const iconClass = this._iconClassFromMdiKey(value.icon);
|
|
864
|
+
if (iconClass) {
|
|
865
|
+
node.icon = iconClass;
|
|
866
|
+
}
|
|
867
|
+
else if (this._editingUid !== null) {
|
|
868
|
+
delete node.icon;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (node.kind === 'catalog') {
|
|
872
|
+
// Required items must never carry an include function (it could hide them at runtime).
|
|
873
|
+
// Persisted as the enum member *name* so the stored config survives enum reorders.
|
|
874
|
+
node.includeFunction =
|
|
875
|
+
this.isRequired(node) || !value.includeFunction
|
|
876
|
+
? undefined
|
|
877
|
+
: serializeIncludeFunction(value.includeFunction);
|
|
878
|
+
if (node.includeFunction === undefined)
|
|
879
|
+
delete node.includeFunction;
|
|
880
|
+
}
|
|
881
|
+
this._placeNode(node, value.section ?? 'root');
|
|
882
|
+
this._bump();
|
|
883
|
+
this.closeEditor();
|
|
884
|
+
}
|
|
885
|
+
closeEditor() {
|
|
886
|
+
this.$editorOpen.set(false);
|
|
887
|
+
this._editingUid = null;
|
|
888
|
+
this._pendingPaletteItem = null;
|
|
889
|
+
}
|
|
890
|
+
/** Commits a (new or edited) node into the chosen section, moving it if its section changed. */
|
|
891
|
+
_placeNode(node, section) {
|
|
892
|
+
const sectionCapable = this.SECTION_CAPABLE_KINDS.includes(node.kind);
|
|
893
|
+
if (this._editingUid !== null) {
|
|
894
|
+
// Existing node: only move it when it is section-capable and the section actually changed.
|
|
895
|
+
if (sectionCapable && this._findSectionOf(node._uid) !== section) {
|
|
896
|
+
this._removeByUid(this.$structure(), node._uid);
|
|
897
|
+
this._targetForSection(section).push(node);
|
|
898
|
+
}
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
// New node: place into the chosen section (top level for non-section-capable kinds).
|
|
902
|
+
const target = sectionCapable ? this._targetForSection(section) : this.$structure();
|
|
903
|
+
target.push(node);
|
|
904
|
+
}
|
|
905
|
+
_syncLinkControl(kind) {
|
|
906
|
+
if (kind === 'custom-link') {
|
|
907
|
+
this.editorForm.controls.link.enable();
|
|
908
|
+
}
|
|
909
|
+
else {
|
|
910
|
+
this.editorForm.controls.link.disable();
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
onRemove(node) {
|
|
914
|
+
if (this.isRequired(node))
|
|
915
|
+
return;
|
|
916
|
+
this._removeByUid(this.$structure(), node._uid);
|
|
917
|
+
this._bump();
|
|
918
|
+
}
|
|
919
|
+
onSave() {
|
|
920
|
+
this.$saving.set(true);
|
|
921
|
+
this.$saved.set(false);
|
|
922
|
+
const configuration = {
|
|
923
|
+
version: MENU_CONFIGURATION_VERSION,
|
|
924
|
+
items: this._stripUids(this.$structure()),
|
|
925
|
+
};
|
|
926
|
+
this.adminSettingsService.updateMenuConfiguration({ configuration }).subscribe({
|
|
927
|
+
next: () => {
|
|
928
|
+
this.$saving.set(false);
|
|
929
|
+
this._$reloadModalOpen.set(true);
|
|
930
|
+
},
|
|
931
|
+
error: () => this.$saving.set(false),
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
/** Reload the app so the freshly saved menu takes effect. */
|
|
935
|
+
onReloadConfirm() {
|
|
936
|
+
window.location.reload();
|
|
937
|
+
}
|
|
938
|
+
/** Dismiss the reload modal, leaving a persistent inline reminder that a reload is still pending. */
|
|
939
|
+
onReloadDismiss() {
|
|
940
|
+
this._$reloadModalOpen.set(false);
|
|
941
|
+
this.$saved.set(true);
|
|
942
|
+
}
|
|
943
|
+
/** Dismiss the persistent "menu saved" reminder. */
|
|
944
|
+
onDismissSavedNotification() {
|
|
945
|
+
this.$saved.set(false);
|
|
946
|
+
}
|
|
947
|
+
// ----- Display helpers (used by the template) -----
|
|
948
|
+
isContainer(node) {
|
|
949
|
+
return (node.kind === 'group' ||
|
|
950
|
+
(node.kind === 'catalog' && (node.itemId === 'admin' || node.itemId === 'development')));
|
|
951
|
+
}
|
|
952
|
+
isRequired(node) {
|
|
953
|
+
return node.kind === 'catalog' && !!getMenuCatalogEntry(node.itemId)?.required;
|
|
954
|
+
}
|
|
955
|
+
hasRuntimeSubmenu(node) {
|
|
956
|
+
return node.kind === 'catalog' && (node.itemId === 'cases' || node.itemId === 'objects');
|
|
957
|
+
}
|
|
958
|
+
displayTitle(node) {
|
|
959
|
+
if (node.kind === 'catalog') {
|
|
960
|
+
return this.translateService.instant(node.title ?? getMenuCatalogEntry(node.itemId)?.defaultTitleKey ?? node.itemId);
|
|
961
|
+
}
|
|
962
|
+
return node.title;
|
|
963
|
+
}
|
|
964
|
+
childrenOf(node) {
|
|
965
|
+
return this._childArray(node) ?? [];
|
|
966
|
+
}
|
|
967
|
+
containerListId(node) {
|
|
968
|
+
return `structure-children-${node.kind === 'catalog' ? node.itemId : node._uid}`;
|
|
969
|
+
}
|
|
970
|
+
containerEnterPredicate(node) {
|
|
971
|
+
if (node.kind === 'group')
|
|
972
|
+
return this.groupEnterPredicate;
|
|
973
|
+
if (node.kind === 'catalog' && node.itemId === 'development')
|
|
974
|
+
return this.developmentEnterPredicate;
|
|
975
|
+
return this.adminEnterPredicate;
|
|
976
|
+
}
|
|
977
|
+
iconClassOf(node) {
|
|
978
|
+
return this._displayIconClass(node);
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Which plugin configuration a placed page belongs to. Every configuration of one plugin
|
|
982
|
+
* contributes a page with the same title, so the row is otherwise indistinguishable from its
|
|
983
|
+
* siblings. Empty for every other kind, and for a page whose configuration no longer exists.
|
|
984
|
+
*/
|
|
985
|
+
configurationTitleOf(node) {
|
|
986
|
+
if (node.kind !== 'plugin-page')
|
|
987
|
+
return '';
|
|
988
|
+
return (this.$pluginPages().find(page => page.configurationId === node.configurationId)
|
|
989
|
+
?.configurationTitle ?? '');
|
|
990
|
+
}
|
|
991
|
+
// ----- Private helpers -----
|
|
992
|
+
_displayIconClass(node) {
|
|
993
|
+
if (node.kind === 'catalog')
|
|
994
|
+
return node.icon ?? getMenuCatalogEntry(node.itemId)?.defaultIcon ?? null;
|
|
995
|
+
if (node.kind === 'custom-link' || node.kind === 'plugin-page' || node.kind === 'group') {
|
|
996
|
+
return node.icon ?? null;
|
|
997
|
+
}
|
|
998
|
+
return null;
|
|
999
|
+
}
|
|
1000
|
+
_editableTitle(node) {
|
|
1001
|
+
if (node.kind === 'catalog')
|
|
1002
|
+
return node.title ?? getMenuCatalogEntry(node.itemId)?.defaultTitleKey ?? '';
|
|
1003
|
+
return node.title;
|
|
1004
|
+
}
|
|
1005
|
+
_placementOf(data) {
|
|
1006
|
+
if (data && 'paletteType' in data) {
|
|
1007
|
+
if (data.paletteType === 'catalog' && data.itemId) {
|
|
1008
|
+
return getMenuCatalogEntry(data.itemId)?.placement ?? 'any';
|
|
1009
|
+
}
|
|
1010
|
+
// A section (group) is top-level only; everything else generic is freely placeable.
|
|
1011
|
+
return data.paletteType === 'group' ? 'top' : 'any';
|
|
1012
|
+
}
|
|
1013
|
+
if (data && 'kind' in data && data.kind === 'catalog') {
|
|
1014
|
+
return getMenuCatalogEntry(data.itemId)?.placement ?? 'any';
|
|
1015
|
+
}
|
|
1016
|
+
return data && 'kind' in data && data.kind === 'group' ? 'top' : 'any';
|
|
1017
|
+
}
|
|
1018
|
+
_containerAccepts(placement, data) {
|
|
1019
|
+
const itemPlacement = this._placementOf(data);
|
|
1020
|
+
return itemPlacement === 'any' || itemPlacement === placement;
|
|
1021
|
+
}
|
|
1022
|
+
_paletteItemToNode(item) {
|
|
1023
|
+
switch (item.paletteType) {
|
|
1024
|
+
case 'catalog':
|
|
1025
|
+
return item.itemId ? this._withUid({ kind: 'catalog', itemId: item.itemId }) : null;
|
|
1026
|
+
case 'group':
|
|
1027
|
+
return this._withUid({
|
|
1028
|
+
kind: 'group',
|
|
1029
|
+
title: this.translateService.instant('adminSettings.menuConfiguration.defaults.group'),
|
|
1030
|
+
children: [],
|
|
1031
|
+
});
|
|
1032
|
+
case 'section-header':
|
|
1033
|
+
return this._withUid({
|
|
1034
|
+
kind: 'section-header',
|
|
1035
|
+
title: this.translateService.instant('adminSettings.menuConfiguration.defaults.sectionHeader'),
|
|
1036
|
+
});
|
|
1037
|
+
case 'custom-link':
|
|
1038
|
+
return this._withUid({
|
|
1039
|
+
kind: 'custom-link',
|
|
1040
|
+
title: this.translateService.instant('adminSettings.menuConfiguration.defaults.customLink'),
|
|
1041
|
+
link: '/',
|
|
1042
|
+
});
|
|
1043
|
+
case 'plugin-page':
|
|
1044
|
+
return item.page
|
|
1045
|
+
? this._withUid({
|
|
1046
|
+
kind: 'plugin-page',
|
|
1047
|
+
configurationId: item.page.configurationId,
|
|
1048
|
+
bundleKey: item.page.bundleKey ?? undefined,
|
|
1049
|
+
title: item.label,
|
|
1050
|
+
icon: item.page.icon ?? undefined,
|
|
1051
|
+
})
|
|
1052
|
+
: null;
|
|
1053
|
+
default:
|
|
1054
|
+
return null;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
_defaultTargetFor(item) {
|
|
1058
|
+
// Drag is unconstrained for these items, but the Add button still drops a page into its natural
|
|
1059
|
+
// home section by default (its catalog category), falling back to the top level.
|
|
1060
|
+
if (item.paletteType === 'catalog' && item.itemId) {
|
|
1061
|
+
const category = getMenuCatalogEntry(item.itemId)?.category;
|
|
1062
|
+
if (category === 'admin')
|
|
1063
|
+
return this._targetForSection('admin');
|
|
1064
|
+
if (category === 'development')
|
|
1065
|
+
return this._targetForSection('development');
|
|
1066
|
+
}
|
|
1067
|
+
return this.$structure();
|
|
1068
|
+
}
|
|
1069
|
+
/** A container's stable section id: catalog `itemId` for Admin/Development, `_uid` for a custom section. */
|
|
1070
|
+
_sectionValue(node) {
|
|
1071
|
+
return node.kind === 'catalog' ? node.itemId : node._uid;
|
|
1072
|
+
}
|
|
1073
|
+
/** The array that backs a section id (`'root'`, a catalog `itemId`, or a group `_uid`), creating children if needed. */
|
|
1074
|
+
_targetForSection(section) {
|
|
1075
|
+
if (!section || section === 'root')
|
|
1076
|
+
return this.$structure();
|
|
1077
|
+
const container = this.$structure().find(node => this.isContainer(node) && this._sectionValue(node) === section);
|
|
1078
|
+
if (container && (container.kind === 'catalog' || container.kind === 'group')) {
|
|
1079
|
+
container.children = container.children ?? [];
|
|
1080
|
+
return container.children;
|
|
1081
|
+
}
|
|
1082
|
+
return this.$structure();
|
|
1083
|
+
}
|
|
1084
|
+
/** Which section a node currently lives in: `'root'` or the containing section's id. */
|
|
1085
|
+
_findSectionOf(uid) {
|
|
1086
|
+
if (this.$structure().some(node => node._uid === uid))
|
|
1087
|
+
return 'root';
|
|
1088
|
+
for (const node of this.$structure()) {
|
|
1089
|
+
const children = this._childArray(node);
|
|
1090
|
+
if (children && children.some(child => child._uid === uid)) {
|
|
1091
|
+
return this._sectionValue(node);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return 'root';
|
|
1095
|
+
}
|
|
1096
|
+
_buildPaletteGroups() {
|
|
1097
|
+
const placedCatalog = new Set();
|
|
1098
|
+
const placedPlugins = new Set();
|
|
1099
|
+
this._walk(this.$structure(), node => {
|
|
1100
|
+
if (node.kind === 'catalog')
|
|
1101
|
+
placedCatalog.add(node.itemId);
|
|
1102
|
+
if (node.kind === 'plugin-page')
|
|
1103
|
+
placedPlugins.add(this._pluginKey(node.configurationId, node.bundleKey));
|
|
1104
|
+
});
|
|
1105
|
+
const fromCatalog = (category) => MENU_ITEM_CATALOG.filter(entry => entry.category === category && !placedCatalog.has(entry.itemId)).map(entry => ({
|
|
1106
|
+
paletteType: 'catalog',
|
|
1107
|
+
itemId: entry.itemId,
|
|
1108
|
+
label: this.translateService.instant(entry.defaultTitleKey),
|
|
1109
|
+
icon: entry.defaultIcon,
|
|
1110
|
+
}));
|
|
1111
|
+
const pluginPages = this.$pluginPages()
|
|
1112
|
+
.filter(page => !placedPlugins.has(this._pluginKey(page.configurationId, page.bundleKey)))
|
|
1113
|
+
.map(page => ({
|
|
1114
|
+
paletteType: 'plugin-page',
|
|
1115
|
+
page,
|
|
1116
|
+
label: this._localizedPluginTitle(page),
|
|
1117
|
+
sublabel: page.configurationTitle,
|
|
1118
|
+
icon: page.icon ?? undefined,
|
|
1119
|
+
}));
|
|
1120
|
+
return [
|
|
1121
|
+
{
|
|
1122
|
+
categoryKey: 'generic',
|
|
1123
|
+
items: [
|
|
1124
|
+
{
|
|
1125
|
+
paletteType: 'group',
|
|
1126
|
+
label: this.translateService.instant('adminSettings.menuConfiguration.generic.group'),
|
|
1127
|
+
},
|
|
1128
|
+
{
|
|
1129
|
+
paletteType: 'section-header',
|
|
1130
|
+
label: this.translateService.instant('adminSettings.menuConfiguration.generic.sectionHeader'),
|
|
1131
|
+
},
|
|
1132
|
+
{
|
|
1133
|
+
paletteType: 'custom-link',
|
|
1134
|
+
label: this.translateService.instant('adminSettings.menuConfiguration.generic.customLink'),
|
|
1135
|
+
},
|
|
1136
|
+
],
|
|
1137
|
+
},
|
|
1138
|
+
{ categoryKey: 'main', items: fromCatalog('main') },
|
|
1139
|
+
{ categoryKey: 'admin', items: fromCatalog('admin') },
|
|
1140
|
+
{ categoryKey: 'development', items: fromCatalog('development') },
|
|
1141
|
+
{ categoryKey: 'pluginPages', items: pluginPages },
|
|
1142
|
+
];
|
|
1143
|
+
}
|
|
1144
|
+
_localizedPluginTitle(page) {
|
|
1145
|
+
const lang = this.translateService.currentLang ?? this.translateService.defaultLang ?? 'en';
|
|
1146
|
+
return page.titleTranslations?.[lang] ?? page.title ?? page.configurationTitle;
|
|
1147
|
+
}
|
|
1148
|
+
_pluginKey(configurationId, bundleKey) {
|
|
1149
|
+
return `${configurationId}:${bundleKey ?? ''}`;
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* The MDI icon selector works with the full MDI class token (e.g. `mdi-view-dashboard`) — its
|
|
1153
|
+
* preview binds the value straight onto an element class and `POPULAR_MDI_ICONS` is `mdi-*` keyed
|
|
1154
|
+
* — so we keep the `mdi-` prefix here (stripping it broke the preview and double-prefixed on save).
|
|
1155
|
+
*/
|
|
1156
|
+
_mdiKeyFromIconClass(iconClass) {
|
|
1157
|
+
if (!iconClass)
|
|
1158
|
+
return null;
|
|
1159
|
+
const match = iconClass.match(/(mdi-[a-z0-9-]+)/i);
|
|
1160
|
+
return match ? match[1] : null;
|
|
1161
|
+
}
|
|
1162
|
+
/** Builds the menu `iconClass` from the selector's MDI class token (`mdi-view-dashboard` → `icon mdi mdi-view-dashboard`). */
|
|
1163
|
+
_iconClassFromMdiKey(key) {
|
|
1164
|
+
return key ? `icon mdi ${key}` : undefined;
|
|
1165
|
+
}
|
|
1166
|
+
// ----- Tree utilities -----
|
|
1167
|
+
/** The editable children array of a branch node (catalog group or custom section), else null. */
|
|
1168
|
+
_childArray(node) {
|
|
1169
|
+
if ((node.kind === 'catalog' || node.kind === 'group') && Array.isArray(node.children)) {
|
|
1170
|
+
return node.children;
|
|
1171
|
+
}
|
|
1172
|
+
return null;
|
|
1173
|
+
}
|
|
1174
|
+
_withUid(node) {
|
|
1175
|
+
return { ...node, _uid: `node-${this._uidCounter++}` };
|
|
1176
|
+
}
|
|
1177
|
+
_assignUids(items) {
|
|
1178
|
+
return items.map(item => {
|
|
1179
|
+
const node = this._withUid(item);
|
|
1180
|
+
const children = this._childArray(node);
|
|
1181
|
+
if (children) {
|
|
1182
|
+
node.children = this._assignUids(children);
|
|
1183
|
+
}
|
|
1184
|
+
return node;
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
_walk(nodes, visit) {
|
|
1188
|
+
nodes.forEach(node => {
|
|
1189
|
+
visit(node);
|
|
1190
|
+
const children = this._childArray(node);
|
|
1191
|
+
if (children)
|
|
1192
|
+
this._walk(children, visit);
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
_findByUid(nodes, uid) {
|
|
1196
|
+
for (const node of nodes) {
|
|
1197
|
+
if (node._uid === uid)
|
|
1198
|
+
return node;
|
|
1199
|
+
const children = this._childArray(node);
|
|
1200
|
+
if (children) {
|
|
1201
|
+
const found = this._findByUid(children, uid);
|
|
1202
|
+
if (found)
|
|
1203
|
+
return found;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
return null;
|
|
1207
|
+
}
|
|
1208
|
+
_removeByUid(nodes, uid) {
|
|
1209
|
+
const index = nodes.findIndex(node => node._uid === uid);
|
|
1210
|
+
if (index >= 0) {
|
|
1211
|
+
nodes.splice(index, 1);
|
|
1212
|
+
return true;
|
|
1213
|
+
}
|
|
1214
|
+
return nodes.some(node => {
|
|
1215
|
+
const children = this._childArray(node);
|
|
1216
|
+
return !!children && this._removeByUid(children, uid);
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
/** Deep-clones array references so the OnPush drag-drop lists re-render after an in-place mutation. */
|
|
1220
|
+
_bump() {
|
|
1221
|
+
this.$saved.set(false);
|
|
1222
|
+
this.$structure.set(this._clone(this.$structure()));
|
|
1223
|
+
}
|
|
1224
|
+
_clone(nodes) {
|
|
1225
|
+
return nodes.map(node => {
|
|
1226
|
+
const copy = { ...node };
|
|
1227
|
+
const children = this._childArray(node);
|
|
1228
|
+
if (children)
|
|
1229
|
+
copy.children = this._clone(children);
|
|
1230
|
+
return copy;
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
/** Produces the persisted structure without the transient `_uid` fields. */
|
|
1234
|
+
_stripUids(nodes) {
|
|
1235
|
+
return nodes.map(node => {
|
|
1236
|
+
const { _uid, ...rest } = node;
|
|
1237
|
+
const clean = rest;
|
|
1238
|
+
if ((clean.kind === 'catalog' || clean.kind === 'group') && Array.isArray(clean.children)) {
|
|
1239
|
+
clean.children = this._stripUids(clean.children);
|
|
1240
|
+
}
|
|
1241
|
+
return clean;
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsMenuConfigurationComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2$1.AdminSettingsService }, { token: i3.ExternalPluginPageService }, { token: i2.ConfigService }, { token: i5.TranslateService }, { token: i4.IconService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1245
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsMenuConfigurationComponent, isStandalone: true, selector: "valtimo-admin-settings-menu-configuration", ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n@if ($loading()) {\n <div class=\"menu-configuration__status\">\n <cds-loading [isActive]=\"true\" [overlay]=\"false\" size=\"normal\"></cds-loading>\n </div>\n} @else {\n <div class=\"menu-configuration\">\n @if ($saved()) {\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'success',\n title: ('adminSettings.menuConfiguration.savedTitle' | translate),\n message: ('adminSettings.menuConfiguration.savedSubtitle' | translate),\n showClose: true,\n lowContrast: true,\n }\"\n (close)=\"onDismissSavedNotification()\"\n ></cds-inline-notification>\n }\n\n <div\n fitPage\n [disableOverflow]=\"true\"\n class=\"menu-configuration__panels\"\n [class.menu-configuration__panels--dragging]=\"$dragging()\"\n >\n <!-- Left: the editable menu structure -->\n <section cdkScrollable class=\"menu-configuration__panel\">\n <div class=\"menu-configuration__panel-header\">\n <h4 class=\"menu-configuration__panel-title\">\n {{ 'adminSettings.menuConfiguration.structureTitle' | translate }}\n </h4>\n\n <div class=\"menu-configuration__panel-actions\">\n <button\n cdsButton=\"tertiary\"\n size=\"sm\"\n [onBottom]=\"true\"\n [vTooltip]=\"'adminSettings.menuConfiguration.resetTooltip' | translate\"\n (click)=\"onReset()\"\n [attr.data-test-id]=\"testIds.resetButton\"\n >\n {{ 'adminSettings.menuConfiguration.reset' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n size=\"sm\"\n [disabled]=\"$saving()\"\n (click)=\"onSave()\"\n [attr.data-test-id]=\"testIds.saveButton\"\n >\n {{ 'adminSettings.menuConfiguration.save' | translate }}\n </button>\n </div>\n </div>\n\n <valtimo-drag-drop-list\n [attr.data-test-id]=\"testIds.structureList\"\n [connectedTo]=\"$structureListIds()\"\n [enterPredicate]=\"topEnterPredicate\"\n [handleAriaLabel]=\"'adminSettings.menuConfiguration.dragHandle' | translate\"\n [items]=\"$structure()\"\n [itemTemplate]=\"structureItemTpl\"\n [expansionTemplate]=\"structureExpansionTpl\"\n [emptyTemplate]=\"structureEmptyTpl\"\n [wholeRowDraggable]=\"true\"\n listId=\"structure-root\"\n (dragEndedEvent)=\"onDragEnded()\"\n (dragStartedEvent)=\"onDragStarted()\"\n (droppedEvent)=\"onDrop($event)\"\n ></valtimo-drag-drop-list>\n </section>\n\n <!-- Right: the available-items catalog -->\n <section cdkScrollable class=\"menu-configuration__panel\">\n <div class=\"menu-configuration__panel-header\">\n <h4 class=\"menu-configuration__panel-title\">\n {{ 'adminSettings.menuConfiguration.availableTitle' | translate }}\n </h4>\n </div>\n\n @for (group of $paletteGroups(); track group.categoryKey) {\n <div class=\"menu-configuration__palette-group\">\n <h5 class=\"menu-configuration__palette-group-title\">\n {{ 'adminSettings.menuConfiguration.categories.' + group.categoryKey | translate }}\n </h5>\n\n @if (!group.items.length) {\n <p class=\"menu-configuration__palette-empty\">\n {{ 'adminSettings.menuConfiguration.allPlaced' | translate }}\n </p>\n } @else {\n <valtimo-drag-drop-list\n [connectedTo]=\"$structureListIds()\"\n [enterPredicate]=\"paletteEnterPredicate\"\n [handleAriaLabel]=\"'adminSettings.menuConfiguration.dragHandle' | translate\"\n [items]=\"group.items\"\n [itemTemplate]=\"paletteItemTpl\"\n [listId]=\"'palette-' + group.categoryKey\"\n [sortingDisabled]=\"true\"\n [wholeRowDraggable]=\"true\"\n (dragEndedEvent)=\"onDragEnded()\"\n (dragStartedEvent)=\"onDragStarted()\"\n ></valtimo-drag-drop-list>\n }\n </div>\n }\n </section>\n </div>\n </div>\n}\n\n<!-- The header row of a menu-structure item (icon, title, actions). The sub-list, if any, is rendered\n by structureExpansionTpl below the row \u2014 never inside it. -->\n<ng-template #structureItemTpl let-node>\n <div class=\"menu-configuration__row\">\n <div class=\"menu-configuration__row-main\">\n @if (iconClassOf(node)) {\n <i class=\"menu-configuration__row-icon\" [ngClass]=\"iconClassOf(node)\"></i>\n }\n\n <span\n class=\"menu-configuration__row-title\"\n [class.menu-configuration__row-title--group]=\"isContainer(node)\"\n >{{ displayTitle(node) }}</span\n >\n\n @if (configurationTitleOf(node)) {\n <span class=\"menu-configuration__row-subtitle\">{{ configurationTitleOf(node) }}</span>\n }\n\n @if (isRequired(node)) {\n <cds-tag type=\"cool-gray\" size=\"sm\">\n <svg cdsIcon=\"locked\" size=\"16\"></svg>\n {{ 'adminSettings.menuConfiguration.required' | translate }}\n </cds-tag>\n }\n </div>\n\n <div class=\"menu-configuration__row-actions\">\n <button\n cdsButton=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n (click)=\"openEditor(node)\"\n [title]=\"'interface.edit' | translate\"\n >\n <svg cdsIcon=\"edit\" size=\"16\"></svg>\n </button>\n\n @if (!isRequired(node)) {\n <button\n cdsButton=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n (click)=\"onRemove(node)\"\n [title]=\"'interface.delete' | translate\"\n >\n <svg cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- The sub-list under a structure item, rendered below (and outside) the row (recursive). -->\n<ng-template #structureExpansionTpl let-node>\n @if (isContainer(node)) {\n <div class=\"menu-configuration__children\">\n <valtimo-drag-drop-list\n [connectedTo]=\"$structureListIds()\"\n [emptyTemplate]=\"sectionEmptyTpl\"\n [enterPredicate]=\"containerEnterPredicate(node)\"\n [handleAriaLabel]=\"'adminSettings.menuConfiguration.dragHandle' | translate\"\n [items]=\"childrenOf(node)\"\n [itemTemplate]=\"structureItemTpl\"\n [expansionTemplate]=\"structureExpansionTpl\"\n [listId]=\"containerListId(node)\"\n [wholeRowDraggable]=\"true\"\n (dragEndedEvent)=\"onDragEnded()\"\n (dragStartedEvent)=\"onDragStarted()\"\n (droppedEvent)=\"onDrop($event)\"\n ></valtimo-drag-drop-list>\n </div>\n }\n\n <!-- Dynamic-submenu items (Cases, Objects) show a dummy submenu explaining it grows at runtime. -->\n @if (hasRuntimeSubmenu(node)) {\n <div class=\"menu-configuration__children menu-configuration__children--runtime\">\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'info',\n title: ('adminSettings.menuConfiguration.runtimeSubmenu' | translate),\n message: ('adminSettings.menuConfiguration.runtimeSubmenuNote' | translate),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </div>\n }\n</ng-template>\n\n<!-- A row in the available-items palette -->\n<ng-template #paletteItemTpl let-item>\n <div\n class=\"menu-configuration__palette-item\"\n [title]=\"item.label + (item.sublabel ? ' \u2014 ' + item.sublabel : '')\"\n >\n @if (item.icon) {\n <i class=\"menu-configuration__row-icon\" [ngClass]=\"item.icon\"></i>\n }\n\n <span class=\"menu-configuration__palette-text\">\n <span class=\"menu-configuration__palette-label\">{{ item.label }}</span>\n @if (item.sublabel) {\n <span class=\"menu-configuration__palette-sublabel\">{{ item.sublabel }}</span>\n }\n </span>\n\n <button\n cdsButton=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n (click)=\"onAddPaletteItem(item)\"\n [title]=\"'adminSettings.menuConfiguration.add' | translate\"\n >\n <svg cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n </div>\n</ng-template>\n\n<ng-template #structureEmptyTpl>\n <p class=\"menu-configuration__structure-empty\">\n {{ 'adminSettings.menuConfiguration.emptyStructure' | translate }}\n </p>\n</ng-template>\n\n<ng-template #sectionEmptyTpl>\n <p class=\"menu-configuration__structure-empty\">\n {{ 'adminSettings.menuConfiguration.emptySection' | translate }}\n </p>\n</ng-template>\n\n<!-- Item editor -->\n<cds-modal [open]=\"$editorOpen()\" (overlaySelected)=\"closeEditor()\">\n <cds-modal-header (closeSelect)=\"closeEditor()\">\n <h3 cdsModalHeaderHeading>{{ 'adminSettings.menuConfiguration.editor.title' | translate }}</h3>\n </cds-modal-header>\n\n <section\n cdsModalContent\n [cdsLayer]=\"1\"\n [formGroup]=\"editorForm\"\n class=\"menu-configuration__editor\"\n >\n <cds-text-label [helperText]=\"'adminSettings.menuConfiguration.editor.titleHelper' | translate\">\n {{ 'interface.title' | translate }}\n <input cdsText formControlName=\"title\" [attr.data-test-id]=\"testIds.editorTitleInput\" />\n </cds-text-label>\n\n @if ($editorKind() === 'custom-link') {\n <cds-text-label>\n {{ 'adminSettings.menuConfiguration.editor.link' | translate }}\n <input cdsText formControlName=\"link\" [attr.data-test-id]=\"testIds.editorLinkInput\" />\n </cds-text-label>\n }\n\n <!-- Gated on $editorOpen() so the icon selector (and its Carbon combobox) is recreated fresh each\n time the editor opens \u2014 otherwise the reused combobox keeps the previous entry's filter state. -->\n @if ($editorOpen() && $editorShowIcon()) {\n <valtimo-mdi-icon-selector\n [appendInline]=\"false\"\n [fullWidth]=\"true\"\n formControlName=\"icon\"\n ></valtimo-mdi-icon-selector>\n }\n\n @if ($editorShowSection()) {\n <cds-select\n formControlName=\"section\"\n [label]=\"'adminSettings.menuConfiguration.editor.section' | translate\"\n >\n @for (option of $sectionOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </cds-select>\n }\n\n @if ($editorKind() === 'catalog' && !$editorRequired()) {\n <cds-select\n formControlName=\"includeFunction\"\n [label]=\"'adminSettings.menuConfiguration.editor.includeFunction' | translate\"\n >\n <option value=\"\">\n {{ 'adminSettings.menuConfiguration.editor.includeFunctionNone' | translate }}\n </option>\n @for (key of includeFunctionKeys; track key) {\n <option [value]=\"key\">{{ key }}</option>\n }\n </cds-select>\n }\n\n <p class=\"menu-configuration__editor-note\">\n {{ 'adminSettings.menuConfiguration.editor.pbacNote' | translate }}\n </p>\n </section>\n\n <cds-modal-footer>\n <button\n cdsButton=\"secondary\"\n (click)=\"closeEditor()\"\n [attr.data-test-id]=\"testIds.editorCancelButton\"\n >\n {{ 'interface.cancel' | translate }}\n </button>\n <button\n cdsButton=\"primary\"\n [disabled]=\"editorForm.invalid\"\n (click)=\"onEditorSave()\"\n [attr.data-test-id]=\"testIds.editorSaveButton\"\n >\n {{ 'interface.save' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n\n<!-- After a successful save, offer to reload so the new menu takes effect immediately. -->\n<valtimo-confirmation-modal\n cancelButtonTextTranslationKey=\"adminSettings.menuConfiguration.reloadModal.dismiss\"\n confirmButtonTextTranslationKey=\"adminSettings.menuConfiguration.reloadModal.confirm\"\n contentTranslationKey=\"adminSettings.menuConfiguration.reloadModal.content\"\n titleTranslationKey=\"adminSettings.menuConfiguration.reloadModal.title\"\n [showModalSubject$]=\"reloadModalOpen$\"\n (cancelEvent)=\"onReloadDismiss()\"\n (confirmEvent)=\"onReloadConfirm()\"\n></valtimo-confirmation-modal>\n", styles: [".menu-configuration{display:flex;flex-direction:column;gap:var(--cds-spacing-05)}.menu-configuration__status{display:flex;justify-content:center;padding:var(--cds-spacing-07)}.menu-configuration__panels{display:grid;grid-template-columns:1fr 1fr;gap:var(--cds-spacing-06);align-items:stretch;min-height:0}.menu-configuration__panels--dragging ::ng-deep .valtimo-drag-drop-list:not(.cdk-drop-list-receiving):not(.cdk-drop-list-dragging)>.valtimo-drag-drop-list__item>.valtimo-drag-drop-list__row,.menu-configuration__panels--dragging ::ng-deep .valtimo-drag-drop-list:not(.cdk-drop-list-receiving):not(.cdk-drop-list-dragging)>.valtimo-drag-drop-list__item>.valtimo-drag-drop-list__expansion>.menu-configuration__children--runtime{opacity:.4;transition:opacity .15s ease}.menu-configuration__panel{display:flex;flex-direction:column;gap:var(--cds-spacing-04);padding:0 var(--cds-spacing-05) var(--cds-spacing-05);border:1px solid var(--cds-border-subtle);height:100%;min-height:0;overflow-y:auto;background-color:var(--cds-layer-01)}.menu-configuration__panel-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:var(--cds-spacing-05);min-height:var(--cds-spacing-09);padding:var(--cds-spacing-05) 0 var(--cds-spacing-05);background-color:var(--cds-layer)}.menu-configuration__panel-title{color:var(--cds-text-primary);font-weight:600}.menu-configuration__panel-actions{display:flex;gap:var(--cds-spacing-03);flex-shrink:0}.menu-configuration__row{display:flex;align-items:center;justify-content:space-between;gap:var(--cds-spacing-03);width:100%;min-width:0}.menu-configuration__row-main{display:flex;align-items:center;gap:var(--cds-spacing-03);min-width:0}.menu-configuration__row-icon{color:var(--cds-icon-primary);flex-shrink:0}.menu-configuration__row-title{color:var(--cds-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__row-title--group{font-weight:600}.menu-configuration__row-subtitle{color:var(--cds-text-secondary);font-size:var(--cds-label-01-font-size);letter-spacing:var(--cds-label-01-letter-spacing);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__row-actions{display:flex;flex-shrink:0}.menu-configuration__children{margin-top:var(--cds-spacing-03);margin-left:var(--cds-spacing-06);padding-left:var(--cds-spacing-04);border-left:var(--cds-spacing-01) solid var(--cds-border-subtle)}.menu-configuration__children--runtime cds-inline-notification,.menu-configuration__children--runtime .cds--inline-notification{min-width:0;margin-block:0}.menu-configuration__structure-empty,.menu-configuration__palette-empty{color:var(--cds-text-helper);padding:var(--cds-spacing-04);text-align:center}.menu-configuration__palette-group{display:flex;flex-direction:column;gap:var(--cds-spacing-03)}.menu-configuration__palette-group-title{color:var(--cds-text-secondary);text-transform:uppercase;font-size:var(--cds-label-01-font-size);letter-spacing:var(--cds-label-01-letter-spacing);margin-top:var(--cds-spacing-03)}.menu-configuration__palette-item{display:flex;align-items:center;gap:var(--cds-spacing-03);width:100%;min-width:0}.menu-configuration__palette-text{display:flex;flex:1 1 auto;flex-direction:column;min-width:0}.menu-configuration__palette-label{color:var(--cds-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__palette-sublabel{color:var(--cds-text-secondary);font-size:var(--cds-label-01-font-size);letter-spacing:var(--cds-label-01-letter-spacing);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__editor{display:flex;flex-direction:column;gap:var(--cds-spacing-05)}.menu-configuration__editor-note{color:var(--cds-text-helper);font-style:italic}:host ::ng-deep cds-inline-notification{max-inline-size:unset;width:100%}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i8.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "component", type: DragDropListComponent, selector: "valtimo-drag-drop-list", inputs: ["items", "listId", "connectedTo", "disabled", "sortingDisabled", "showHandle", "wholeRowDraggable", "orientation", "handleAriaLabel", "itemTemplate", "expansionTemplate", "emptyTemplate", "enterPredicate", "dragDisabled"], outputs: ["droppedEvent", "dragStartedEvent", "dragEndedEvent"] }, { kind: "directive", type: FitPageDirective, selector: "[fitPage]", inputs: ["spaceAdjustment", "fitPageDisabled", "disableOverflow", "bottomMargin"] }, { kind: "component", type: MdiIconSelectorComponent, selector: "valtimo-mdi-icon-selector", inputs: ["labelTranslationKey", "tooltipTranslationKey", "placeholderTranslationKey", "appendInline", "dropUp", "fullWidth"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i2$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$1.TooltipDirective, selector: "[vTooltip]", inputs: ["vTooltip", "onBottom", "tooltipDisabled"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: InputModule }, { kind: "component", type: i4.TextInputLabelComponent, selector: "cds-text-label, ibm-text-label", inputs: ["labelInputID", "disabled", "skeleton", "labelTemplate", "textInputTemplate", "helperText", "invalidText", "invalid", "warn", "warnText", "ariaLabel", "fluid"] }, { kind: "directive", type: i4.TextInput, selector: "[cdsText], [ibmText]", inputs: ["theme", "size", "invalid", "warn", "skeleton"] }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i4.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: LoadingModule }, { kind: "component", type: i4.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i4.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i4.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i4.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i4.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i4.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "ngmodule", type: NotificationModule }, { kind: "component", type: i4.Notification, selector: "cds-notification, cds-inline-notification, ibm-notification, ibm-inline-notification", inputs: ["notificationObj"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i4.Select, selector: "cds-select, ibm-select", inputs: ["value", "display", "label", "helperText", "invalidText", "warn", "warnText", "id", "size", "disabled", "skeleton", "invalid", "readonly", "theme", "ariaLabel", "fluid"], outputs: ["valueChange"] }, { kind: "directive", type: i4.Option, selector: "option" }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i4.Tag, selector: "cds-tag, ibm-tag", inputs: ["type", "size", "class", "skeleton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1246
|
+
}
|
|
1247
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsMenuConfigurationComponent, decorators: [{
|
|
1248
|
+
type: Component,
|
|
1249
|
+
args: [{ standalone: true, selector: 'valtimo-admin-settings-menu-configuration', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
1250
|
+
CommonModule,
|
|
1251
|
+
ReactiveFormsModule,
|
|
1252
|
+
TranslateModule,
|
|
1253
|
+
ScrollingModule,
|
|
1254
|
+
DragDropListComponent,
|
|
1255
|
+
FitPageDirective,
|
|
1256
|
+
MdiIconSelectorComponent,
|
|
1257
|
+
ConfirmationModalModule,
|
|
1258
|
+
TooltipModule,
|
|
1259
|
+
ButtonModule,
|
|
1260
|
+
IconModule,
|
|
1261
|
+
InputModule,
|
|
1262
|
+
LayerModule,
|
|
1263
|
+
LoadingModule,
|
|
1264
|
+
ModalModule,
|
|
1265
|
+
NotificationModule,
|
|
1266
|
+
SelectModule,
|
|
1267
|
+
TagModule,
|
|
1268
|
+
], template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n@if ($loading()) {\n <div class=\"menu-configuration__status\">\n <cds-loading [isActive]=\"true\" [overlay]=\"false\" size=\"normal\"></cds-loading>\n </div>\n} @else {\n <div class=\"menu-configuration\">\n @if ($saved()) {\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'success',\n title: ('adminSettings.menuConfiguration.savedTitle' | translate),\n message: ('adminSettings.menuConfiguration.savedSubtitle' | translate),\n showClose: true,\n lowContrast: true,\n }\"\n (close)=\"onDismissSavedNotification()\"\n ></cds-inline-notification>\n }\n\n <div\n fitPage\n [disableOverflow]=\"true\"\n class=\"menu-configuration__panels\"\n [class.menu-configuration__panels--dragging]=\"$dragging()\"\n >\n <!-- Left: the editable menu structure -->\n <section cdkScrollable class=\"menu-configuration__panel\">\n <div class=\"menu-configuration__panel-header\">\n <h4 class=\"menu-configuration__panel-title\">\n {{ 'adminSettings.menuConfiguration.structureTitle' | translate }}\n </h4>\n\n <div class=\"menu-configuration__panel-actions\">\n <button\n cdsButton=\"tertiary\"\n size=\"sm\"\n [onBottom]=\"true\"\n [vTooltip]=\"'adminSettings.menuConfiguration.resetTooltip' | translate\"\n (click)=\"onReset()\"\n [attr.data-test-id]=\"testIds.resetButton\"\n >\n {{ 'adminSettings.menuConfiguration.reset' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n size=\"sm\"\n [disabled]=\"$saving()\"\n (click)=\"onSave()\"\n [attr.data-test-id]=\"testIds.saveButton\"\n >\n {{ 'adminSettings.menuConfiguration.save' | translate }}\n </button>\n </div>\n </div>\n\n <valtimo-drag-drop-list\n [attr.data-test-id]=\"testIds.structureList\"\n [connectedTo]=\"$structureListIds()\"\n [enterPredicate]=\"topEnterPredicate\"\n [handleAriaLabel]=\"'adminSettings.menuConfiguration.dragHandle' | translate\"\n [items]=\"$structure()\"\n [itemTemplate]=\"structureItemTpl\"\n [expansionTemplate]=\"structureExpansionTpl\"\n [emptyTemplate]=\"structureEmptyTpl\"\n [wholeRowDraggable]=\"true\"\n listId=\"structure-root\"\n (dragEndedEvent)=\"onDragEnded()\"\n (dragStartedEvent)=\"onDragStarted()\"\n (droppedEvent)=\"onDrop($event)\"\n ></valtimo-drag-drop-list>\n </section>\n\n <!-- Right: the available-items catalog -->\n <section cdkScrollable class=\"menu-configuration__panel\">\n <div class=\"menu-configuration__panel-header\">\n <h4 class=\"menu-configuration__panel-title\">\n {{ 'adminSettings.menuConfiguration.availableTitle' | translate }}\n </h4>\n </div>\n\n @for (group of $paletteGroups(); track group.categoryKey) {\n <div class=\"menu-configuration__palette-group\">\n <h5 class=\"menu-configuration__palette-group-title\">\n {{ 'adminSettings.menuConfiguration.categories.' + group.categoryKey | translate }}\n </h5>\n\n @if (!group.items.length) {\n <p class=\"menu-configuration__palette-empty\">\n {{ 'adminSettings.menuConfiguration.allPlaced' | translate }}\n </p>\n } @else {\n <valtimo-drag-drop-list\n [connectedTo]=\"$structureListIds()\"\n [enterPredicate]=\"paletteEnterPredicate\"\n [handleAriaLabel]=\"'adminSettings.menuConfiguration.dragHandle' | translate\"\n [items]=\"group.items\"\n [itemTemplate]=\"paletteItemTpl\"\n [listId]=\"'palette-' + group.categoryKey\"\n [sortingDisabled]=\"true\"\n [wholeRowDraggable]=\"true\"\n (dragEndedEvent)=\"onDragEnded()\"\n (dragStartedEvent)=\"onDragStarted()\"\n ></valtimo-drag-drop-list>\n }\n </div>\n }\n </section>\n </div>\n </div>\n}\n\n<!-- The header row of a menu-structure item (icon, title, actions). The sub-list, if any, is rendered\n by structureExpansionTpl below the row \u2014 never inside it. -->\n<ng-template #structureItemTpl let-node>\n <div class=\"menu-configuration__row\">\n <div class=\"menu-configuration__row-main\">\n @if (iconClassOf(node)) {\n <i class=\"menu-configuration__row-icon\" [ngClass]=\"iconClassOf(node)\"></i>\n }\n\n <span\n class=\"menu-configuration__row-title\"\n [class.menu-configuration__row-title--group]=\"isContainer(node)\"\n >{{ displayTitle(node) }}</span\n >\n\n @if (configurationTitleOf(node)) {\n <span class=\"menu-configuration__row-subtitle\">{{ configurationTitleOf(node) }}</span>\n }\n\n @if (isRequired(node)) {\n <cds-tag type=\"cool-gray\" size=\"sm\">\n <svg cdsIcon=\"locked\" size=\"16\"></svg>\n {{ 'adminSettings.menuConfiguration.required' | translate }}\n </cds-tag>\n }\n </div>\n\n <div class=\"menu-configuration__row-actions\">\n <button\n cdsButton=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n (click)=\"openEditor(node)\"\n [title]=\"'interface.edit' | translate\"\n >\n <svg cdsIcon=\"edit\" size=\"16\"></svg>\n </button>\n\n @if (!isRequired(node)) {\n <button\n cdsButton=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n (click)=\"onRemove(node)\"\n [title]=\"'interface.delete' | translate\"\n >\n <svg cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- The sub-list under a structure item, rendered below (and outside) the row (recursive). -->\n<ng-template #structureExpansionTpl let-node>\n @if (isContainer(node)) {\n <div class=\"menu-configuration__children\">\n <valtimo-drag-drop-list\n [connectedTo]=\"$structureListIds()\"\n [emptyTemplate]=\"sectionEmptyTpl\"\n [enterPredicate]=\"containerEnterPredicate(node)\"\n [handleAriaLabel]=\"'adminSettings.menuConfiguration.dragHandle' | translate\"\n [items]=\"childrenOf(node)\"\n [itemTemplate]=\"structureItemTpl\"\n [expansionTemplate]=\"structureExpansionTpl\"\n [listId]=\"containerListId(node)\"\n [wholeRowDraggable]=\"true\"\n (dragEndedEvent)=\"onDragEnded()\"\n (dragStartedEvent)=\"onDragStarted()\"\n (droppedEvent)=\"onDrop($event)\"\n ></valtimo-drag-drop-list>\n </div>\n }\n\n <!-- Dynamic-submenu items (Cases, Objects) show a dummy submenu explaining it grows at runtime. -->\n @if (hasRuntimeSubmenu(node)) {\n <div class=\"menu-configuration__children menu-configuration__children--runtime\">\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'info',\n title: ('adminSettings.menuConfiguration.runtimeSubmenu' | translate),\n message: ('adminSettings.menuConfiguration.runtimeSubmenuNote' | translate),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </div>\n }\n</ng-template>\n\n<!-- A row in the available-items palette -->\n<ng-template #paletteItemTpl let-item>\n <div\n class=\"menu-configuration__palette-item\"\n [title]=\"item.label + (item.sublabel ? ' \u2014 ' + item.sublabel : '')\"\n >\n @if (item.icon) {\n <i class=\"menu-configuration__row-icon\" [ngClass]=\"item.icon\"></i>\n }\n\n <span class=\"menu-configuration__palette-text\">\n <span class=\"menu-configuration__palette-label\">{{ item.label }}</span>\n @if (item.sublabel) {\n <span class=\"menu-configuration__palette-sublabel\">{{ item.sublabel }}</span>\n }\n </span>\n\n <button\n cdsButton=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n (click)=\"onAddPaletteItem(item)\"\n [title]=\"'adminSettings.menuConfiguration.add' | translate\"\n >\n <svg cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n </div>\n</ng-template>\n\n<ng-template #structureEmptyTpl>\n <p class=\"menu-configuration__structure-empty\">\n {{ 'adminSettings.menuConfiguration.emptyStructure' | translate }}\n </p>\n</ng-template>\n\n<ng-template #sectionEmptyTpl>\n <p class=\"menu-configuration__structure-empty\">\n {{ 'adminSettings.menuConfiguration.emptySection' | translate }}\n </p>\n</ng-template>\n\n<!-- Item editor -->\n<cds-modal [open]=\"$editorOpen()\" (overlaySelected)=\"closeEditor()\">\n <cds-modal-header (closeSelect)=\"closeEditor()\">\n <h3 cdsModalHeaderHeading>{{ 'adminSettings.menuConfiguration.editor.title' | translate }}</h3>\n </cds-modal-header>\n\n <section\n cdsModalContent\n [cdsLayer]=\"1\"\n [formGroup]=\"editorForm\"\n class=\"menu-configuration__editor\"\n >\n <cds-text-label [helperText]=\"'adminSettings.menuConfiguration.editor.titleHelper' | translate\">\n {{ 'interface.title' | translate }}\n <input cdsText formControlName=\"title\" [attr.data-test-id]=\"testIds.editorTitleInput\" />\n </cds-text-label>\n\n @if ($editorKind() === 'custom-link') {\n <cds-text-label>\n {{ 'adminSettings.menuConfiguration.editor.link' | translate }}\n <input cdsText formControlName=\"link\" [attr.data-test-id]=\"testIds.editorLinkInput\" />\n </cds-text-label>\n }\n\n <!-- Gated on $editorOpen() so the icon selector (and its Carbon combobox) is recreated fresh each\n time the editor opens \u2014 otherwise the reused combobox keeps the previous entry's filter state. -->\n @if ($editorOpen() && $editorShowIcon()) {\n <valtimo-mdi-icon-selector\n [appendInline]=\"false\"\n [fullWidth]=\"true\"\n formControlName=\"icon\"\n ></valtimo-mdi-icon-selector>\n }\n\n @if ($editorShowSection()) {\n <cds-select\n formControlName=\"section\"\n [label]=\"'adminSettings.menuConfiguration.editor.section' | translate\"\n >\n @for (option of $sectionOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </cds-select>\n }\n\n @if ($editorKind() === 'catalog' && !$editorRequired()) {\n <cds-select\n formControlName=\"includeFunction\"\n [label]=\"'adminSettings.menuConfiguration.editor.includeFunction' | translate\"\n >\n <option value=\"\">\n {{ 'adminSettings.menuConfiguration.editor.includeFunctionNone' | translate }}\n </option>\n @for (key of includeFunctionKeys; track key) {\n <option [value]=\"key\">{{ key }}</option>\n }\n </cds-select>\n }\n\n <p class=\"menu-configuration__editor-note\">\n {{ 'adminSettings.menuConfiguration.editor.pbacNote' | translate }}\n </p>\n </section>\n\n <cds-modal-footer>\n <button\n cdsButton=\"secondary\"\n (click)=\"closeEditor()\"\n [attr.data-test-id]=\"testIds.editorCancelButton\"\n >\n {{ 'interface.cancel' | translate }}\n </button>\n <button\n cdsButton=\"primary\"\n [disabled]=\"editorForm.invalid\"\n (click)=\"onEditorSave()\"\n [attr.data-test-id]=\"testIds.editorSaveButton\"\n >\n {{ 'interface.save' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n\n<!-- After a successful save, offer to reload so the new menu takes effect immediately. -->\n<valtimo-confirmation-modal\n cancelButtonTextTranslationKey=\"adminSettings.menuConfiguration.reloadModal.dismiss\"\n confirmButtonTextTranslationKey=\"adminSettings.menuConfiguration.reloadModal.confirm\"\n contentTranslationKey=\"adminSettings.menuConfiguration.reloadModal.content\"\n titleTranslationKey=\"adminSettings.menuConfiguration.reloadModal.title\"\n [showModalSubject$]=\"reloadModalOpen$\"\n (cancelEvent)=\"onReloadDismiss()\"\n (confirmEvent)=\"onReloadConfirm()\"\n></valtimo-confirmation-modal>\n", styles: [".menu-configuration{display:flex;flex-direction:column;gap:var(--cds-spacing-05)}.menu-configuration__status{display:flex;justify-content:center;padding:var(--cds-spacing-07)}.menu-configuration__panels{display:grid;grid-template-columns:1fr 1fr;gap:var(--cds-spacing-06);align-items:stretch;min-height:0}.menu-configuration__panels--dragging ::ng-deep .valtimo-drag-drop-list:not(.cdk-drop-list-receiving):not(.cdk-drop-list-dragging)>.valtimo-drag-drop-list__item>.valtimo-drag-drop-list__row,.menu-configuration__panels--dragging ::ng-deep .valtimo-drag-drop-list:not(.cdk-drop-list-receiving):not(.cdk-drop-list-dragging)>.valtimo-drag-drop-list__item>.valtimo-drag-drop-list__expansion>.menu-configuration__children--runtime{opacity:.4;transition:opacity .15s ease}.menu-configuration__panel{display:flex;flex-direction:column;gap:var(--cds-spacing-04);padding:0 var(--cds-spacing-05) var(--cds-spacing-05);border:1px solid var(--cds-border-subtle);height:100%;min-height:0;overflow-y:auto;background-color:var(--cds-layer-01)}.menu-configuration__panel-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:var(--cds-spacing-05);min-height:var(--cds-spacing-09);padding:var(--cds-spacing-05) 0 var(--cds-spacing-05);background-color:var(--cds-layer)}.menu-configuration__panel-title{color:var(--cds-text-primary);font-weight:600}.menu-configuration__panel-actions{display:flex;gap:var(--cds-spacing-03);flex-shrink:0}.menu-configuration__row{display:flex;align-items:center;justify-content:space-between;gap:var(--cds-spacing-03);width:100%;min-width:0}.menu-configuration__row-main{display:flex;align-items:center;gap:var(--cds-spacing-03);min-width:0}.menu-configuration__row-icon{color:var(--cds-icon-primary);flex-shrink:0}.menu-configuration__row-title{color:var(--cds-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__row-title--group{font-weight:600}.menu-configuration__row-subtitle{color:var(--cds-text-secondary);font-size:var(--cds-label-01-font-size);letter-spacing:var(--cds-label-01-letter-spacing);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__row-actions{display:flex;flex-shrink:0}.menu-configuration__children{margin-top:var(--cds-spacing-03);margin-left:var(--cds-spacing-06);padding-left:var(--cds-spacing-04);border-left:var(--cds-spacing-01) solid var(--cds-border-subtle)}.menu-configuration__children--runtime cds-inline-notification,.menu-configuration__children--runtime .cds--inline-notification{min-width:0;margin-block:0}.menu-configuration__structure-empty,.menu-configuration__palette-empty{color:var(--cds-text-helper);padding:var(--cds-spacing-04);text-align:center}.menu-configuration__palette-group{display:flex;flex-direction:column;gap:var(--cds-spacing-03)}.menu-configuration__palette-group-title{color:var(--cds-text-secondary);text-transform:uppercase;font-size:var(--cds-label-01-font-size);letter-spacing:var(--cds-label-01-letter-spacing);margin-top:var(--cds-spacing-03)}.menu-configuration__palette-item{display:flex;align-items:center;gap:var(--cds-spacing-03);width:100%;min-width:0}.menu-configuration__palette-text{display:flex;flex:1 1 auto;flex-direction:column;min-width:0}.menu-configuration__palette-label{color:var(--cds-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__palette-sublabel{color:var(--cds-text-secondary);font-size:var(--cds-label-01-font-size);letter-spacing:var(--cds-label-01-letter-spacing);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.menu-configuration__editor{display:flex;flex-direction:column;gap:var(--cds-spacing-05)}.menu-configuration__editor-note{color:var(--cds-text-helper);font-style:italic}:host ::ng-deep cds-inline-notification{max-inline-size:unset;width:100%}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
1269
|
+
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2$1.AdminSettingsService }, { type: i3.ExternalPluginPageService }, { type: i2.ConfigService }, { type: i5.TranslateService }, { type: i4.IconService }] });
|
|
1270
|
+
|
|
545
1271
|
/*
|
|
546
1272
|
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
547
1273
|
*
|
|
@@ -567,8 +1293,8 @@ class AdminSettingsComponent {
|
|
|
567
1293
|
switchTab(tabKey) {
|
|
568
1294
|
this._router.navigate(['..', tabKey], { relativeTo: this._route });
|
|
569
1295
|
}
|
|
570
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsComponent, deps: [{ token: i1$
|
|
571
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsComponent, isStandalone: true, selector: "valtimo-admin-settings", ngImport: i0, template: "<!--\n ~ /*\n ~ * Copyright 2015-2026 Ritense BV, the Netherlands.\n ~ *\n ~ * Licensed under EUPL, Version 1.2 (the \"License\");\n ~ * you may not use this file except in compliance with the License.\n ~ * You may obtain a copy of the License at\n ~ *\n ~ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~ *\n ~ * Unless required by applicable law or agreed to in writing, software\n ~ * distributed under the License is distributed on an \"AS IS\" basis,\n ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ * See the License for the specific language governing permissions and\n ~ * limitations under the License.\n ~ */\n -->\n\n@if (activeTabKey$ | async; as activeTabKey) {\n <cds-tabs type=\"line\">\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.APPEARANCE}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.appearance' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.APPEARANCE)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-appearance></valtimo-admin-settings-appearance>\n }\n </cds-tab>\n }\n\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.FEATURE_TOGGLES}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.featureToggles' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.FEATURE_TOGGLES)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-feature-toggles></valtimo-admin-settings-feature-toggles>\n }\n </cds-tab>\n }\n\n </cds-tabs>\n}\n", styles: [":host ::ng-deep .cds--tab-content{padding-left:0!important;padding-right:0!important;padding-bottom:0!important;outline:none!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i4.Tabs, selector: "cds-tabs, ibm-tabs", inputs: ["position", "cacheActive", "followFocus", "isNavigation", "ariaLabel", "ariaLabelledby", "type", "theme", "skeleton"] }, { kind: "component", type: i4.Tab, selector: "cds-tab, ibm-tab", inputs: ["heading", "title", "context", "active", "disabled", "tabIndex", "id", "cacheActive", "tabContent", "templateContext"], outputs: ["selected"] }, { kind: "component", type: AdminSettingsAppearanceComponent, selector: "valtimo-admin-settings-appearance" }, { kind: "component", type: AdminSettingsFeatureTogglesComponent, selector: "valtimo-admin-settings-feature-toggles" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1296
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsComponent, deps: [{ token: i1$2.ActivatedRoute }, { token: i1$2.Router }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1297
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsComponent, isStandalone: true, selector: "valtimo-admin-settings", ngImport: i0, template: "<!--\n ~ /*\n ~ * Copyright 2015-2026 Ritense BV, the Netherlands.\n ~ *\n ~ * Licensed under EUPL, Version 1.2 (the \"License\");\n ~ * you may not use this file except in compliance with the License.\n ~ * You may obtain a copy of the License at\n ~ *\n ~ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~ *\n ~ * Unless required by applicable law or agreed to in writing, software\n ~ * distributed under the License is distributed on an \"AS IS\" basis,\n ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ * See the License for the specific language governing permissions and\n ~ * limitations under the License.\n ~ */\n -->\n\n@if (activeTabKey$ | async; as activeTabKey) {\n <cds-tabs type=\"line\">\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.APPEARANCE}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.appearance' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.APPEARANCE)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-appearance></valtimo-admin-settings-appearance>\n }\n </cds-tab>\n }\n\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.MENU_CONFIGURATION}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.menuConfiguration' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.MENU_CONFIGURATION)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-menu-configuration></valtimo-admin-settings-menu-configuration>\n }\n </cds-tab>\n }\n\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.FEATURE_TOGGLES}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.featureToggles' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.FEATURE_TOGGLES)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-feature-toggles></valtimo-admin-settings-feature-toggles>\n }\n </cds-tab>\n }\n\n </cds-tabs>\n}\n", styles: [":host ::ng-deep .cds--tab-content{padding-left:0!important;padding-right:0!important;padding-bottom:0!important;outline:none!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i4.Tabs, selector: "cds-tabs, ibm-tabs", inputs: ["position", "cacheActive", "followFocus", "isNavigation", "ariaLabel", "ariaLabelledby", "type", "theme", "skeleton"] }, { kind: "component", type: i4.Tab, selector: "cds-tab, ibm-tab", inputs: ["heading", "title", "context", "active", "disabled", "tabIndex", "id", "cacheActive", "tabContent", "templateContext"], outputs: ["selected"] }, { kind: "component", type: AdminSettingsAppearanceComponent, selector: "valtimo-admin-settings-appearance" }, { kind: "component", type: AdminSettingsFeatureTogglesComponent, selector: "valtimo-admin-settings-feature-toggles" }, { kind: "component", type: AdminSettingsMenuConfigurationComponent, selector: "valtimo-admin-settings-menu-configuration" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
572
1298
|
}
|
|
573
1299
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsComponent, decorators: [{
|
|
574
1300
|
type: Component,
|
|
@@ -578,8 +1304,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
578
1304
|
TabsModule,
|
|
579
1305
|
AdminSettingsAppearanceComponent,
|
|
580
1306
|
AdminSettingsFeatureTogglesComponent,
|
|
581
|
-
|
|
582
|
-
|
|
1307
|
+
AdminSettingsMenuConfigurationComponent,
|
|
1308
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ /*\n ~ * Copyright 2015-2026 Ritense BV, the Netherlands.\n ~ *\n ~ * Licensed under EUPL, Version 1.2 (the \"License\");\n ~ * you may not use this file except in compliance with the License.\n ~ * You may obtain a copy of the License at\n ~ *\n ~ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~ *\n ~ * Unless required by applicable law or agreed to in writing, software\n ~ * distributed under the License is distributed on an \"AS IS\" basis,\n ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ * See the License for the specific language governing permissions and\n ~ * limitations under the License.\n ~ */\n -->\n\n@if (activeTabKey$ | async; as activeTabKey) {\n <cds-tabs type=\"line\">\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.APPEARANCE}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.appearance' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.APPEARANCE)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-appearance></valtimo-admin-settings-appearance>\n }\n </cds-tab>\n }\n\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.MENU_CONFIGURATION}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.menuConfiguration' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.MENU_CONFIGURATION)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-menu-configuration></valtimo-admin-settings-menu-configuration>\n }\n </cds-tab>\n }\n\n @if ({active: activeTabKey === ADMIN_SETTINGS_TABS.FEATURE_TOGGLES}; as obs) {\n <cds-tab\n [active]=\"obs.active\"\n [heading]=\"'adminSettings.tabs.featureToggles' | translate\"\n (selected)=\"switchTab(ADMIN_SETTINGS_TABS.FEATURE_TOGGLES)\"\n >\n @if (obs.active) {\n <valtimo-admin-settings-feature-toggles></valtimo-admin-settings-feature-toggles>\n }\n </cds-tab>\n }\n\n </cds-tabs>\n}\n", styles: [":host ::ng-deep .cds--tab-content{padding-left:0!important;padding-right:0!important;padding-bottom:0!important;outline:none!important}\n"] }]
|
|
1309
|
+
}], ctorParameters: () => [{ type: i1$2.ActivatedRoute }, { type: i1$2.Router }] });
|
|
583
1310
|
|
|
584
1311
|
/*
|
|
585
1312
|
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
@@ -656,8 +1383,8 @@ class StartReindexModalComponent {
|
|
|
656
1383
|
modifiedAfter: null,
|
|
657
1384
|
});
|
|
658
1385
|
}
|
|
659
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: StartReindexModalComponent, deps: [{ token:
|
|
660
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: StartReindexModalComponent, isStandalone: true, selector: "valtimo-start-reindex-modal", inputs: { open: "open", documentDefinitions: "documentDefinitions" }, outputs: { closeEvent: "closeEvent" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal valtimoCdsModal *ngIf=\"open\" [open]=\"open\" size=\"sm\" (close)=\"onCancel()\">\n <cds-modal-header [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>{{ 'adminSettings.opensearch.reindex.startModalTitle' | translate }}</h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"formGroup\" class=\"start-reindex-form\">\n <cds-checkbox formControlName=\"pruneOrphans\">\n <span class=\"label-with-tooltip\">\n {{ 'adminSettings.opensearch.reindex.pruneOrphans' | translate }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruneOrphans' | translate\"></v-tooltip-icon>\n </span>\n </cds-checkbox>\n\n <cds-dropdown\n [label]=\"'adminSettings.opensearch.reindex.documentDefinitionName' | translate\"\n [placeholder]=\"'adminSettings.opensearch.reindex.documentDefinitionPlaceholder' | translate\"\n formControlName=\"documentDefinitionName\"\n >\n <cds-dropdown-list [items]=\"documentDefinitions\"></cds-dropdown-list>\n </cds-dropdown>\n\n <cds-date-picker\n [label]=\"'adminSettings.opensearch.reindex.modifiedAfter' | translate\"\n placeholder=\"DD-MM-YYYY\"\n [dateFormat]=\"'d-m-Y'\"\n (valueChange)=\"onDateSelected($event)\"\n ></cds-date-picker>\n </section>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button cdsButton=\"primary\" (click)=\"onSubmit()\">\n {{ 'adminSettings.opensearch.reindex.startButton' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".start-reindex-form{display:flex;flex-direction:column;gap:1rem}.start-reindex-form .label-with-tooltip{display:inline-flex;align-items:center;gap:4px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type:
|
|
1386
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: StartReindexModalComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1387
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: StartReindexModalComponent, isStandalone: true, selector: "valtimo-start-reindex-modal", inputs: { open: "open", documentDefinitions: "documentDefinitions" }, outputs: { closeEvent: "closeEvent" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal valtimoCdsModal *ngIf=\"open\" [open]=\"open\" size=\"sm\" (close)=\"onCancel()\">\n <cds-modal-header [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>{{ 'adminSettings.opensearch.reindex.startModalTitle' | translate }}</h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"formGroup\" class=\"start-reindex-form\">\n <cds-checkbox formControlName=\"pruneOrphans\">\n <span class=\"label-with-tooltip\">\n {{ 'adminSettings.opensearch.reindex.pruneOrphans' | translate }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruneOrphans' | translate\"></v-tooltip-icon>\n </span>\n </cds-checkbox>\n\n <cds-dropdown\n [label]=\"'adminSettings.opensearch.reindex.documentDefinitionName' | translate\"\n [placeholder]=\"'adminSettings.opensearch.reindex.documentDefinitionPlaceholder' | translate\"\n formControlName=\"documentDefinitionName\"\n >\n <cds-dropdown-list [items]=\"documentDefinitions\"></cds-dropdown-list>\n </cds-dropdown>\n\n <cds-date-picker\n [label]=\"'adminSettings.opensearch.reindex.modifiedAfter' | translate\"\n placeholder=\"DD-MM-YYYY\"\n [dateFormat]=\"'d-m-Y'\"\n (valueChange)=\"onDateSelected($event)\"\n ></cds-date-picker>\n </section>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button cdsButton=\"primary\" (click)=\"onSubmit()\">\n {{ 'adminSettings.opensearch.reindex.startButton' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".start-reindex-form{display:flex;flex-direction:column;gap:1rem}.start-reindex-form .label-with-tooltip{display:inline-flex;align-items:center;gap:4px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i4.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i4.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i4.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i4.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i4.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "directive", type: ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4.Checkbox, selector: "cds-checkbox, ibm-checkbox", inputs: ["disabled", "skeleton", "hideLabel", "name", "id", "required", "value", "ariaLabel", "ariaLabelledby", "indeterminate", "checked"], outputs: ["click", "checkedChange", "indeterminateChange"] }, { kind: "ngmodule", type: DatePickerInputModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i4.DatePicker, selector: "cds-date-picker, ibm-date-picker", inputs: ["range", "dateFormat", "language", "label", "helperText", "rangeHelperText", "rangeLabel", "placeholder", "ariaLabel", "inputPattern", "id", "value", "theme", "disabled", "readonly", "invalid", "invalidText", "warn", "warnText", "size", "rangeInvalid", "rangeInvalidText", "rangeWarn", "rangeWarnText", "skeleton", "plugins", "flatpickrOptions"], outputs: ["valueChange", "onClose"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i4.Dropdown, selector: "cds-dropdown, ibm-dropdown", inputs: ["id", "label", "hideLabel", "helperText", "placeholder", "displayValue", "clearText", "size", "type", "theme", "disabled", "readonly", "skeleton", "inline", "disableArrowKeys", "invalid", "invalidText", "warn", "warnText", "appendInline", "scrollableContainer", "itemValueKey", "selectionFeedback", "menuButtonLabel", "selectedLabel", "dropUp", "fluid"], outputs: ["selected", "onClose", "close"] }, { kind: "component", type: i4.DropdownList, selector: "cds-dropdown-list, ibm-dropdown-list", inputs: ["ariaLabel", "items", "listTpl", "type", "showTitles"], outputs: ["select", "scroll", "blurIntent"] }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i4.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: TooltipIconModule }, { kind: "component", type: i2$1.TooltipIconComponent, selector: "v-tooltip-icon", inputs: ["tooltip", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
661
1388
|
}
|
|
662
1389
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: StartReindexModalComponent, decorators: [{
|
|
663
1390
|
type: Component,
|
|
@@ -675,7 +1402,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
675
1402
|
LayerModule,
|
|
676
1403
|
TooltipIconModule,
|
|
677
1404
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal valtimoCdsModal *ngIf=\"open\" [open]=\"open\" size=\"sm\" (close)=\"onCancel()\">\n <cds-modal-header [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>{{ 'adminSettings.opensearch.reindex.startModalTitle' | translate }}</h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"formGroup\" class=\"start-reindex-form\">\n <cds-checkbox formControlName=\"pruneOrphans\">\n <span class=\"label-with-tooltip\">\n {{ 'adminSettings.opensearch.reindex.pruneOrphans' | translate }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruneOrphans' | translate\"></v-tooltip-icon>\n </span>\n </cds-checkbox>\n\n <cds-dropdown\n [label]=\"'adminSettings.opensearch.reindex.documentDefinitionName' | translate\"\n [placeholder]=\"'adminSettings.opensearch.reindex.documentDefinitionPlaceholder' | translate\"\n formControlName=\"documentDefinitionName\"\n >\n <cds-dropdown-list [items]=\"documentDefinitions\"></cds-dropdown-list>\n </cds-dropdown>\n\n <cds-date-picker\n [label]=\"'adminSettings.opensearch.reindex.modifiedAfter' | translate\"\n placeholder=\"DD-MM-YYYY\"\n [dateFormat]=\"'d-m-Y'\"\n (valueChange)=\"onDateSelected($event)\"\n ></cds-date-picker>\n </section>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button cdsButton=\"primary\" (click)=\"onSubmit()\">\n {{ 'adminSettings.opensearch.reindex.startButton' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".start-reindex-form{display:flex;flex-direction:column;gap:1rem}.start-reindex-form .label-with-tooltip{display:inline-flex;align-items:center;gap:4px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
678
|
-
}], ctorParameters: () => [{ type:
|
|
1405
|
+
}], ctorParameters: () => [{ type: i1$1.FormBuilder }], propDecorators: { open: [{
|
|
679
1406
|
type: Input
|
|
680
1407
|
}], documentDefinitions: [{
|
|
681
1408
|
type: Input
|
|
@@ -820,8 +1547,8 @@ class AdminSettingsOpensearchComponent {
|
|
|
820
1547
|
this._destroy$.next();
|
|
821
1548
|
this._destroy$.complete();
|
|
822
1549
|
}
|
|
823
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsOpensearchComponent, deps: [{ token: AdminSettingsManagementApiService }, { token: i2$2.DocumentService }, { token:
|
|
824
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsOpensearchComponent, isStandalone: true, selector: "valtimo-admin-settings-opensearch", ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<div\n class=\"opensearch-reindex\"\n *ngIf=\"{\n items: tableItems$ | async,\n loading: loading$ | async,\n starting: startingReindex$ | async,\n documentDefinitions: documentDefinitions$ | async,\n showModal: showModal$ | async,\n hasRunning: hasRunningRun$ | async\n } as obs\"\n>\n <valtimo-carbon-list\n [header]=\"false\"\n [items]=\"obs.items || []\"\n [fields]=\"fields\"\n [loading]=\"obs.loading\"\n [pagination]=\"pagination\"\n [expandedRowTemplate]=\"expandedRowTemplate\"\n [expandedRowKey]=\"'runId'\"\n (paginationClicked)=\"onPageChange($event)\"\n (paginationSet)=\"onPageSizeChange($event)\"\n >\n <ng-container header>\n {{ 'adminSettings.opensearch.reindex.title' | translate }}\n </ng-container>\n\n <div carbonToolbarContent>\n <button\n cdsButton=\"primary\"\n [disabled]=\"obs.hasRunning || obs.starting\"\n (click)=\"openModal()\"\n >\n @if (obs.starting) {\n <cds-loading size=\"sm\"></cds-loading>\n }\n {{ 'adminSettings.opensearch.reindex.startButton' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n </div>\n\n <valtimo-no-results\n title=\"{{ 'adminSettings.opensearch.reindex.noResults.title' | translate }}\"\n description=\"{{ 'adminSettings.opensearch.reindex.noResults.description' | translate }}\"\n ></valtimo-no-results>\n </valtimo-carbon-list>\n\n <valtimo-start-reindex-modal\n [open]=\"obs.showModal\"\n [documentDefinitions]=\"obs.documentDefinitions\"\n (closeEvent)=\"onModalClose($event)\"\n ></valtimo-start-reindex-modal>\n</div>\n\n<ng-template #expandedRowTemplate let-data=\"data\">\n <div class=\"opensearch-reindex__expanded\">\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.started' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.startedOn | date:'medium' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.finished' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.finishedOn ? (data.finishedOn | date:'medium') : '-' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.documentDefinitionName' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.scope?.documentDefinitionName || '-' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.pruneOrphans' | translate }}</span>\n <span class=\"opensearch-reindex__value opensearch-reindex__value-with-tooltip\">\n {{ data.scope?.pruneOrphans ? ('interface.yes' | translate) : ('interface.no' | translate) }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruneOrphans' | translate\"></v-tooltip-icon>\n </span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.modifiedAfter' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.scope?.modifiedAfter ? (data.scope.modifiedAfter | date:'medium') : '-' }}</span>\n\n <div class=\"opensearch-reindex__results-column\">\n <div class=\"opensearch-reindex__progress\">\n <span class=\"opensearch-reindex__progress-label\">\n {{ 'adminSettings.opensearch.reindex.reindexing' | translate }}\n </span>\n <cds-progress-bar\n [value]=\"data.totalCount > 0 ? (data.processedCount / data.totalCount) * 100 : 0\"\n [status]=\"data.status === 'RUNNING' && !data.pruningPhase ? 'active' : (data.status === 'COMPLETED' ? 'finished' : (data.status === 'RUNNING' ? 'finished' : 'error'))\"\n ></cds-progress-bar>\n <div class=\"opensearch-reindex__progress-footer\">\n <span>{{ 'adminSettings.opensearch.reindex.processed' | translate:{current: data.processedCount, total: data.totalCount} }}</span>\n <span>{{ 'adminSettings.opensearch.reindex.skipped' | translate }}: {{ data.skippedCount || 0 }}</span>\n </div>\n </div>\n\n @if (data.pruningPhase || data.pruneTotalCount) {\n <div class=\"opensearch-reindex__progress\">\n <span class=\"opensearch-reindex__progress-label\">\n {{ 'adminSettings.opensearch.reindex.pruning' | translate }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruned' | translate\"></v-tooltip-icon>\n </span>\n <cds-progress-bar\n [value]=\"data.pruneTotalCount > 0 ? (data.pruneCheckedCount / data.pruneTotalCount) * 100 : 0\"\n [status]=\"data.pruningPhase ? 'active' : (data.status === 'COMPLETED' ? 'finished' : 'error')\"\n ></cds-progress-bar>\n <div class=\"opensearch-reindex__progress-footer\">\n <span>{{ 'adminSettings.opensearch.reindex.processed' | translate:{current: data.pruneCheckedCount, total: data.pruneTotalCount || 0} }}</span>\n <span>{{ 'adminSettings.opensearch.reindex.pruningProgress' | translate:{removed: data.prunedCount || 0} }}</span>\n </div>\n </div>\n }\n\n @if (data.status === 'FAILED') {\n <a class=\"opensearch-reindex__error-link\" (click)=\"navigateToLogs(data)\">\n {{ 'adminSettings.opensearch.reindex.viewErrorLogs' | translate }}\n <svg cdsIcon=\"launch\" size=\"16\"></svg>\n </a>\n }\n </div>\n </div>\n</ng-template>\n", styles: [".opensearch-reindex{width:100%;display:flex;flex-direction:column;gap:24px}.opensearch-reindex ::ng-deep .cds--data-table{table-layout:fixed}.opensearch-reindex ::ng-deep .cds--data-table th.cds--table-expand{width:3.5rem}.opensearch-reindex ::ng-deep .cds--data-table thead th:not(.cds--table-expand){width:25%}.opensearch-reindex ::ng-deep tr[data-child-row]>td{padding-inline:3.5rem 0}.opensearch-reindex__expanded{padding:8px 0 16px;display:grid;grid-template-columns:repeat(4,1fr);column-gap:0;row-gap:8px;align-items:start}.opensearch-reindex__label{grid-column:1;padding-inline:1rem;font-size:14px;font-weight:600;color:var(--cds-text-primary)}.opensearch-reindex__value{grid-column:2;padding-inline:1rem;font-size:14px;color:var(--cds-text-primary)}.opensearch-reindex__results-column{grid-column:3/span 2;grid-row:1/6;padding-inline:1rem;display:flex;flex-direction:column;gap:16px}.opensearch-reindex__value-with-tooltip{display:inline-flex;align-items:center;gap:4px}.opensearch-reindex__progress-label{display:inline-flex;align-items:center;gap:4px;margin-bottom:4px;font-size:14px;font-weight:600;color:var(--cds-text-secondary)}.opensearch-reindex__progress-footer{display:flex;justify-content:space-between;align-items:center;margin-top:4px;font-size:12px;color:var(--cds-text-secondary)}.opensearch-reindex__progress{padding:8px 0}.opensearch-reindex__progress ::ng-deep .cds--progress-bar__track{background-color:var(--cds-border-subtle)}.opensearch-reindex__error-link{display:inline-flex;align-items:center;gap:4px;color:var(--cds-link-primary);font-size:14px;cursor:pointer;text-decoration:none}.opensearch-reindex__error-link:hover{text-decoration:underline}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.DatePipe, name: "date" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: LoadingModule }, { kind: "component", type: i4.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i4.ProgressBar, selector: "cds-progress-bar, ibm-progress-bar", inputs: ["value", "id", "label", "helperText", "max", "type", "status", "size"] }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: CarbonListModule }, { kind: "component", type: i2$1.CarbonListComponent, selector: "valtimo-carbon-list", inputs: ["items", "fields", "tableTranslations", "paginatorConfig", "pagination", "loading", "skeletonRowCount", "actions", "actionItems", "showActionItems", "header", "hideColumnHeader", "initialSortState", "sortState", "isSearchable", "initialSearchValue", "searchDebounceMs", "invalidSearchFields", "searchFields", "enableSingleSelection", "lastColumnTemplate", "paginationIdentifier", "showSelectionColumn", "striped", "hideToolbar", "lockedTooltipTranslationKey", "movingRowsEnabled", "dragAndDrop", "dragAndDropDisabled", "expandedRowTemplate", "expandedRowKey", "trackByKey"], outputs: ["rowClicked", "paginationClicked", "paginationSet", "search", "sortChanged", "moveRow", "itemsReordered"] }, { kind: "component", type: i2$1.CarbonNoResultsComponent, selector: "valtimo-no-results", inputs: ["action", "description", "illustration", "title", "smallPadding", "collapseVertically", "alwaysRenderVertically"] }, { kind: "component", type: StartReindexModalComponent, selector: "valtimo-start-reindex-modal", inputs: ["open", "documentDefinitions"], outputs: ["closeEvent"] }, { kind: "ngmodule", type: TooltipIconModule }, { kind: "component", type: i2$1.TooltipIconComponent, selector: "v-tooltip-icon", inputs: ["tooltip", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1550
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsOpensearchComponent, deps: [{ token: AdminSettingsManagementApiService }, { token: i2$2.DocumentService }, { token: i5.TranslateService }, { token: i1$2.Router }, { token: i4.IconService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1551
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AdminSettingsOpensearchComponent, isStandalone: true, selector: "valtimo-admin-settings-opensearch", ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<div\n class=\"opensearch-reindex\"\n *ngIf=\"{\n items: tableItems$ | async,\n loading: loading$ | async,\n starting: startingReindex$ | async,\n documentDefinitions: documentDefinitions$ | async,\n showModal: showModal$ | async,\n hasRunning: hasRunningRun$ | async\n } as obs\"\n>\n <valtimo-carbon-list\n [header]=\"false\"\n [items]=\"obs.items || []\"\n [fields]=\"fields\"\n [loading]=\"obs.loading\"\n [pagination]=\"pagination\"\n [expandedRowTemplate]=\"expandedRowTemplate\"\n [expandedRowKey]=\"'runId'\"\n (paginationClicked)=\"onPageChange($event)\"\n (paginationSet)=\"onPageSizeChange($event)\"\n >\n <ng-container header>\n {{ 'adminSettings.opensearch.reindex.title' | translate }}\n </ng-container>\n\n <div carbonToolbarContent>\n <button\n cdsButton=\"primary\"\n [disabled]=\"obs.hasRunning || obs.starting\"\n (click)=\"openModal()\"\n >\n @if (obs.starting) {\n <cds-loading size=\"sm\"></cds-loading>\n }\n {{ 'adminSettings.opensearch.reindex.startButton' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n </div>\n\n <valtimo-no-results\n title=\"{{ 'adminSettings.opensearch.reindex.noResults.title' | translate }}\"\n description=\"{{ 'adminSettings.opensearch.reindex.noResults.description' | translate }}\"\n ></valtimo-no-results>\n </valtimo-carbon-list>\n\n <valtimo-start-reindex-modal\n [open]=\"obs.showModal\"\n [documentDefinitions]=\"obs.documentDefinitions\"\n (closeEvent)=\"onModalClose($event)\"\n ></valtimo-start-reindex-modal>\n</div>\n\n<ng-template #expandedRowTemplate let-data=\"data\">\n <div class=\"opensearch-reindex__expanded\">\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.started' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.startedOn | date:'medium' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.finished' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.finishedOn ? (data.finishedOn | date:'medium') : '-' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.documentDefinitionName' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.scope?.documentDefinitionName || '-' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.pruneOrphans' | translate }}</span>\n <span class=\"opensearch-reindex__value opensearch-reindex__value-with-tooltip\">\n {{ data.scope?.pruneOrphans ? ('interface.yes' | translate) : ('interface.no' | translate) }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruneOrphans' | translate\"></v-tooltip-icon>\n </span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.modifiedAfter' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.scope?.modifiedAfter ? (data.scope.modifiedAfter | date:'medium') : '-' }}</span>\n\n <div class=\"opensearch-reindex__results-column\">\n <div class=\"opensearch-reindex__progress\">\n <span class=\"opensearch-reindex__progress-label\">\n {{ 'adminSettings.opensearch.reindex.reindexing' | translate }}\n </span>\n <cds-progress-bar\n [value]=\"data.totalCount > 0 ? (data.processedCount / data.totalCount) * 100 : 0\"\n [status]=\"data.status === 'RUNNING' && !data.pruningPhase ? 'active' : (data.status === 'COMPLETED' ? 'finished' : (data.status === 'RUNNING' ? 'finished' : 'error'))\"\n ></cds-progress-bar>\n <div class=\"opensearch-reindex__progress-footer\">\n <span>{{ 'adminSettings.opensearch.reindex.processed' | translate:{current: data.processedCount, total: data.totalCount} }}</span>\n <span>{{ 'adminSettings.opensearch.reindex.skipped' | translate }}: {{ data.skippedCount || 0 }}</span>\n </div>\n </div>\n\n @if (data.pruningPhase || data.pruneTotalCount) {\n <div class=\"opensearch-reindex__progress\">\n <span class=\"opensearch-reindex__progress-label\">\n {{ 'adminSettings.opensearch.reindex.pruning' | translate }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruned' | translate\"></v-tooltip-icon>\n </span>\n <cds-progress-bar\n [value]=\"data.pruneTotalCount > 0 ? (data.pruneCheckedCount / data.pruneTotalCount) * 100 : 0\"\n [status]=\"data.pruningPhase ? 'active' : (data.status === 'COMPLETED' ? 'finished' : 'error')\"\n ></cds-progress-bar>\n <div class=\"opensearch-reindex__progress-footer\">\n <span>{{ 'adminSettings.opensearch.reindex.processed' | translate:{current: data.pruneCheckedCount, total: data.pruneTotalCount || 0} }}</span>\n <span>{{ 'adminSettings.opensearch.reindex.pruningProgress' | translate:{removed: data.prunedCount || 0} }}</span>\n </div>\n </div>\n }\n\n @if (data.status === 'FAILED') {\n <a class=\"opensearch-reindex__error-link\" (click)=\"navigateToLogs(data)\">\n {{ 'adminSettings.opensearch.reindex.viewErrorLogs' | translate }}\n <svg cdsIcon=\"launch\" size=\"16\"></svg>\n </a>\n }\n </div>\n </div>\n</ng-template>\n", styles: [".opensearch-reindex{width:100%;display:flex;flex-direction:column;gap:24px}.opensearch-reindex ::ng-deep .cds--data-table{table-layout:fixed}.opensearch-reindex ::ng-deep .cds--data-table th.cds--table-expand{width:3.5rem}.opensearch-reindex ::ng-deep .cds--data-table thead th:not(.cds--table-expand){width:25%}.opensearch-reindex ::ng-deep tr[data-child-row]>td{padding-inline:3.5rem 0}.opensearch-reindex__expanded{padding:8px 0 16px;display:grid;grid-template-columns:repeat(4,1fr);column-gap:0;row-gap:8px;align-items:start}.opensearch-reindex__label{grid-column:1;padding-inline:1rem;font-size:14px;font-weight:600;color:var(--cds-text-primary)}.opensearch-reindex__value{grid-column:2;padding-inline:1rem;font-size:14px;color:var(--cds-text-primary)}.opensearch-reindex__results-column{grid-column:3/span 2;grid-row:1/6;padding-inline:1rem;display:flex;flex-direction:column;gap:16px}.opensearch-reindex__value-with-tooltip{display:inline-flex;align-items:center;gap:4px}.opensearch-reindex__progress-label{display:inline-flex;align-items:center;gap:4px;margin-bottom:4px;font-size:14px;font-weight:600;color:var(--cds-text-secondary)}.opensearch-reindex__progress-footer{display:flex;justify-content:space-between;align-items:center;margin-top:4px;font-size:12px;color:var(--cds-text-secondary)}.opensearch-reindex__progress{padding:8px 0}.opensearch-reindex__progress ::ng-deep .cds--progress-bar__track{background-color:var(--cds-border-subtle)}.opensearch-reindex__error-link{display:inline-flex;align-items:center;gap:4px;color:var(--cds-link-primary);font-size:14px;cursor:pointer;text-decoration:none}.opensearch-reindex__error-link:hover{text-decoration:underline}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.DatePipe, name: "date" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: LoadingModule }, { kind: "component", type: i4.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i4.ProgressBar, selector: "cds-progress-bar, ibm-progress-bar", inputs: ["value", "id", "label", "helperText", "max", "type", "status", "size"] }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: CarbonListModule }, { kind: "component", type: i2$1.CarbonListComponent, selector: "valtimo-carbon-list", inputs: ["items", "fields", "tableTranslations", "paginatorConfig", "pagination", "loading", "skeletonRowCount", "actions", "actionItems", "showActionItems", "header", "hideColumnHeader", "initialSortState", "sortState", "isSearchable", "initialSearchValue", "searchDebounceMs", "invalidSearchFields", "searchFields", "enableSingleSelection", "lastColumnTemplate", "paginationIdentifier", "showSelectionColumn", "striped", "hideToolbar", "lockedTooltipTranslationKey", "movingRowsEnabled", "dragAndDrop", "dragAndDropDisabled", "expandedRowTemplate", "expandedRowKey", "trackByKey"], outputs: ["rowClicked", "paginationClicked", "paginationSet", "search", "sortChanged", "moveRow", "itemsReordered"] }, { kind: "component", type: i2$1.CarbonNoResultsComponent, selector: "valtimo-no-results", inputs: ["action", "description", "illustration", "title", "smallPadding", "collapseVertically", "alwaysRenderVertically"] }, { kind: "component", type: StartReindexModalComponent, selector: "valtimo-start-reindex-modal", inputs: ["open", "documentDefinitions"], outputs: ["closeEvent"] }, { kind: "ngmodule", type: TooltipIconModule }, { kind: "component", type: i2$1.TooltipIconComponent, selector: "v-tooltip-icon", inputs: ["tooltip", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
825
1552
|
}
|
|
826
1553
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsOpensearchComponent, decorators: [{
|
|
827
1554
|
type: Component,
|
|
@@ -838,7 +1565,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
838
1565
|
StartReindexModalComponent,
|
|
839
1566
|
TooltipIconModule,
|
|
840
1567
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<div\n class=\"opensearch-reindex\"\n *ngIf=\"{\n items: tableItems$ | async,\n loading: loading$ | async,\n starting: startingReindex$ | async,\n documentDefinitions: documentDefinitions$ | async,\n showModal: showModal$ | async,\n hasRunning: hasRunningRun$ | async\n } as obs\"\n>\n <valtimo-carbon-list\n [header]=\"false\"\n [items]=\"obs.items || []\"\n [fields]=\"fields\"\n [loading]=\"obs.loading\"\n [pagination]=\"pagination\"\n [expandedRowTemplate]=\"expandedRowTemplate\"\n [expandedRowKey]=\"'runId'\"\n (paginationClicked)=\"onPageChange($event)\"\n (paginationSet)=\"onPageSizeChange($event)\"\n >\n <ng-container header>\n {{ 'adminSettings.opensearch.reindex.title' | translate }}\n </ng-container>\n\n <div carbonToolbarContent>\n <button\n cdsButton=\"primary\"\n [disabled]=\"obs.hasRunning || obs.starting\"\n (click)=\"openModal()\"\n >\n @if (obs.starting) {\n <cds-loading size=\"sm\"></cds-loading>\n }\n {{ 'adminSettings.opensearch.reindex.startButton' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n </div>\n\n <valtimo-no-results\n title=\"{{ 'adminSettings.opensearch.reindex.noResults.title' | translate }}\"\n description=\"{{ 'adminSettings.opensearch.reindex.noResults.description' | translate }}\"\n ></valtimo-no-results>\n </valtimo-carbon-list>\n\n <valtimo-start-reindex-modal\n [open]=\"obs.showModal\"\n [documentDefinitions]=\"obs.documentDefinitions\"\n (closeEvent)=\"onModalClose($event)\"\n ></valtimo-start-reindex-modal>\n</div>\n\n<ng-template #expandedRowTemplate let-data=\"data\">\n <div class=\"opensearch-reindex__expanded\">\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.started' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.startedOn | date:'medium' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.finished' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.finishedOn ? (data.finishedOn | date:'medium') : '-' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.documentDefinitionName' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.scope?.documentDefinitionName || '-' }}</span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.pruneOrphans' | translate }}</span>\n <span class=\"opensearch-reindex__value opensearch-reindex__value-with-tooltip\">\n {{ data.scope?.pruneOrphans ? ('interface.yes' | translate) : ('interface.no' | translate) }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruneOrphans' | translate\"></v-tooltip-icon>\n </span>\n\n <span class=\"opensearch-reindex__label\">{{ 'adminSettings.opensearch.reindex.modifiedAfter' | translate }}</span>\n <span class=\"opensearch-reindex__value\">{{ data.scope?.modifiedAfter ? (data.scope.modifiedAfter | date:'medium') : '-' }}</span>\n\n <div class=\"opensearch-reindex__results-column\">\n <div class=\"opensearch-reindex__progress\">\n <span class=\"opensearch-reindex__progress-label\">\n {{ 'adminSettings.opensearch.reindex.reindexing' | translate }}\n </span>\n <cds-progress-bar\n [value]=\"data.totalCount > 0 ? (data.processedCount / data.totalCount) * 100 : 0\"\n [status]=\"data.status === 'RUNNING' && !data.pruningPhase ? 'active' : (data.status === 'COMPLETED' ? 'finished' : (data.status === 'RUNNING' ? 'finished' : 'error'))\"\n ></cds-progress-bar>\n <div class=\"opensearch-reindex__progress-footer\">\n <span>{{ 'adminSettings.opensearch.reindex.processed' | translate:{current: data.processedCount, total: data.totalCount} }}</span>\n <span>{{ 'adminSettings.opensearch.reindex.skipped' | translate }}: {{ data.skippedCount || 0 }}</span>\n </div>\n </div>\n\n @if (data.pruningPhase || data.pruneTotalCount) {\n <div class=\"opensearch-reindex__progress\">\n <span class=\"opensearch-reindex__progress-label\">\n {{ 'adminSettings.opensearch.reindex.pruning' | translate }}\n <v-tooltip-icon [tooltip]=\"'adminSettings.opensearch.reindex.tooltips.pruned' | translate\"></v-tooltip-icon>\n </span>\n <cds-progress-bar\n [value]=\"data.pruneTotalCount > 0 ? (data.pruneCheckedCount / data.pruneTotalCount) * 100 : 0\"\n [status]=\"data.pruningPhase ? 'active' : (data.status === 'COMPLETED' ? 'finished' : 'error')\"\n ></cds-progress-bar>\n <div class=\"opensearch-reindex__progress-footer\">\n <span>{{ 'adminSettings.opensearch.reindex.processed' | translate:{current: data.pruneCheckedCount, total: data.pruneTotalCount || 0} }}</span>\n <span>{{ 'adminSettings.opensearch.reindex.pruningProgress' | translate:{removed: data.prunedCount || 0} }}</span>\n </div>\n </div>\n }\n\n @if (data.status === 'FAILED') {\n <a class=\"opensearch-reindex__error-link\" (click)=\"navigateToLogs(data)\">\n {{ 'adminSettings.opensearch.reindex.viewErrorLogs' | translate }}\n <svg cdsIcon=\"launch\" size=\"16\"></svg>\n </a>\n }\n </div>\n </div>\n</ng-template>\n", styles: [".opensearch-reindex{width:100%;display:flex;flex-direction:column;gap:24px}.opensearch-reindex ::ng-deep .cds--data-table{table-layout:fixed}.opensearch-reindex ::ng-deep .cds--data-table th.cds--table-expand{width:3.5rem}.opensearch-reindex ::ng-deep .cds--data-table thead th:not(.cds--table-expand){width:25%}.opensearch-reindex ::ng-deep tr[data-child-row]>td{padding-inline:3.5rem 0}.opensearch-reindex__expanded{padding:8px 0 16px;display:grid;grid-template-columns:repeat(4,1fr);column-gap:0;row-gap:8px;align-items:start}.opensearch-reindex__label{grid-column:1;padding-inline:1rem;font-size:14px;font-weight:600;color:var(--cds-text-primary)}.opensearch-reindex__value{grid-column:2;padding-inline:1rem;font-size:14px;color:var(--cds-text-primary)}.opensearch-reindex__results-column{grid-column:3/span 2;grid-row:1/6;padding-inline:1rem;display:flex;flex-direction:column;gap:16px}.opensearch-reindex__value-with-tooltip{display:inline-flex;align-items:center;gap:4px}.opensearch-reindex__progress-label{display:inline-flex;align-items:center;gap:4px;margin-bottom:4px;font-size:14px;font-weight:600;color:var(--cds-text-secondary)}.opensearch-reindex__progress-footer{display:flex;justify-content:space-between;align-items:center;margin-top:4px;font-size:12px;color:var(--cds-text-secondary)}.opensearch-reindex__progress{padding:8px 0}.opensearch-reindex__progress ::ng-deep .cds--progress-bar__track{background-color:var(--cds-border-subtle)}.opensearch-reindex__error-link{display:inline-flex;align-items:center;gap:4px;color:var(--cds-link-primary);font-size:14px;cursor:pointer;text-decoration:none}.opensearch-reindex__error-link:hover{text-decoration:underline}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
841
|
-
}], ctorParameters: () => [{ type: AdminSettingsManagementApiService }, { type: i2$2.DocumentService }, { type:
|
|
1568
|
+
}], ctorParameters: () => [{ type: AdminSettingsManagementApiService }, { type: i2$2.DocumentService }, { type: i5.TranslateService }, { type: i1$2.Router }, { type: i4.IconService }] });
|
|
842
1569
|
|
|
843
1570
|
/*
|
|
844
1571
|
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
@@ -876,7 +1603,7 @@ const routes = [
|
|
|
876
1603
|
];
|
|
877
1604
|
class AdminSettingsRouting {
|
|
878
1605
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsRouting, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
879
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsRouting, imports: [CommonModule, i1$
|
|
1606
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsRouting, imports: [CommonModule, i1$2.RouterModule], exports: [RouterModule] }); }
|
|
880
1607
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsRouting, imports: [CommonModule, RouterModule.forChild(routes), RouterModule] }); }
|
|
881
1608
|
}
|
|
882
1609
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AdminSettingsRouting, decorators: [{
|
|
@@ -1013,9 +1740,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
1013
1740
|
* limitations under the License.
|
|
1014
1741
|
*/
|
|
1015
1742
|
|
|
1743
|
+
/*
|
|
1744
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
1745
|
+
*
|
|
1746
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
1747
|
+
* you may not use this file except in compliance with the License.
|
|
1748
|
+
* You may obtain a copy of the License at
|
|
1749
|
+
*
|
|
1750
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
1751
|
+
*
|
|
1752
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1753
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
1754
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1755
|
+
* See the License for the specific language governing permissions and
|
|
1756
|
+
* limitations under the License.
|
|
1757
|
+
*/
|
|
1758
|
+
|
|
1016
1759
|
/**
|
|
1017
1760
|
* Generated bundle index. Do not edit.
|
|
1018
1761
|
*/
|
|
1019
1762
|
|
|
1020
|
-
export { ACCENT_COLOR_DEFINITIONS, ADMIN_SETTINGS_TABS, AdminSettingsManagementApiService, AdminSettingsModule, FEATURE_TOGGLE_DEFINITIONS };
|
|
1763
|
+
export { ACCENT_COLOR_DEFINITIONS, ADMIN_SETTINGS_TABS, AdminSettingsManagementApiService, AdminSettingsModule, FEATURE_TOGGLE_DEFINITIONS, MENU_CONFIGURATION_TEST_IDS };
|
|
1021
1764
|
//# sourceMappingURL=valtimo-admin-settings.mjs.map
|