@valtimo/access-control-management 13.42.0 → 13.44.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.
@@ -138,6 +138,11 @@ var AccessControlEditorTab;
138
138
  */
139
139
  const ACCESS_CONTROL_EDITOR_TEST_IDS = {
140
140
  addPermissionButton: 'accessControlEditorAddPermission',
141
+ // Accordion sections of a permission card; only one is expanded at a time, so the
142
+ // controls inside a collapsed section are present but not visible.
143
+ sectionResourceActions: 'accessControlEditorSectionResourceActions',
144
+ sectionConditions: 'accessControlEditorSectionConditions',
145
+ sectionContext: 'accessControlEditorSectionContext',
141
146
  permissionListItem: 'accessControlEditorPermissionListItem',
142
147
  permissionCard: 'accessControlEditorPermissionCard',
143
148
  removePermissionButton: 'accessControlEditorRemovePermission',
@@ -155,6 +160,40 @@ const ACCESS_CONTROL_EDITOR_TEST_IDS = {
155
160
  conditionClazzInput: 'accessControlEditorConditionClazz',
156
161
  };
157
162
 
163
+ /*
164
+ * Copyright 2015-2026 Ritense BV, the Netherlands.
165
+ *
166
+ * Licensed under EUPL, Version 1.2 (the "License");
167
+ * you may not use this file except in compliance with the License.
168
+ * You may obtain a copy of the License at
169
+ *
170
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
171
+ *
172
+ * Unless required by applicable law or agreed to in writing, software
173
+ * distributed under the License is distributed on an "AS IS" basis,
174
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
175
+ * See the License for the specific language governing permissions and
176
+ * limitations under the License.
177
+ */
178
+ const ACCESS_CONTROL_ROLES_TEST_IDS = {
179
+ // Roles overview — toolbar batch actions (only rendered once a row is selected)
180
+ exportButton: 'accessControlRolesExport',
181
+ // Role detail — page-header overflow menu
182
+ moreMenuEditMetadata: 'accessControlRoleEditMetadata',
183
+ moreMenuExport: 'accessControlRoleExport',
184
+ // Role metadata modal (shared by add and edit)
185
+ metadataKeyInput: 'accessControlRoleMetadataKey',
186
+ metadataKeyModeSwitch: 'accessControlRoleMetadataKeyModeSwitch',
187
+ metadataConfirmButton: 'accessControlRoleMetadataConfirm',
188
+ metadataCancelButton: 'accessControlRoleMetadataCancel',
189
+ // Role detail — page header
190
+ saveButton: 'accessControlRoleSave',
191
+ // Export role modal
192
+ exportModalSingleFile: 'accessControlRoleExportSingleFile',
193
+ exportModalSeparateFiles: 'accessControlRoleExportSeparateFiles',
194
+ exportModalConfirmButton: 'accessControlRoleExportConfirm',
195
+ };
196
+
158
197
  /*
159
198
  * Copyright 2015-2026 Ritense BV, the Netherlands.
160
199
  *
@@ -998,6 +1037,7 @@ class RoleMetadataModalComponent {
998
1037
  // only lists these; a custom key is entered via manual mode.
999
1038
  this.$roleKeyItems = signal([]);
1000
1039
  this.$loadingRoles = signal(false);
1040
+ this.testIds = ACCESS_CONTROL_ROLES_TEST_IDS;
1001
1041
  // Whether the key is typed manually rather than picked from the dropdown.
1002
1042
  this.$keyManual = signal(false);
1003
1043
  this.form = this.fb.group({
@@ -1059,11 +1099,11 @@ class RoleMetadataModalComponent {
1059
1099
  }, CARBON_CONSTANTS.modalAnimationMs);
1060
1100
  }
1061
1101
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: RoleMetadataModalComponent, deps: [{ token: i1.FormBuilder }, { token: AccessControlService }], target: i0.ɵɵFactoryTarget.Component }); }
1062
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: RoleMetadataModalComponent, isStandalone: false, selector: "valtimo-role-metadata-modal", inputs: { type: "type", open: "open", defaultKeyValue: "defaultKeyValue", usedKeys: "usedKeys" }, outputs: { closeEvent: "closeEvent" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{\n isAdd: type === 'add',\n } as vars\"\n [open]=\"open\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n valtimoCdsModal\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{\n vars.isAdd\n ? ('accessControl.roles.add' | translate)\n : ('accessControl.roles.editRole' | translate)\n }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <form [formGroup]=\"form\">\n <div class=\"role-metadata-modal__field cds--form-item\">\n <label class=\"cds--label\">\n {{ 'accessControl.roles.name' | translate }} ({{ 'interface.required' | translate }})\n </label>\n\n @if ($keyManual()) {\n <input\n formControlName=\"key\"\n cdsText\n placeholder=\"{{ 'accessControl.roles.name' | translate }}\"\n [attr.modal-primary-focus]=\"true\"\n [invalid]=\"key.dirty && key.invalid\"\n />\n } @else {\n <v-select\n formControlName=\"key\"\n [appendInline]=\"false\"\n [clearable]=\"false\"\n [defaultSelectionId]=\"key.value || ''\"\n [dropUp]=\"false\"\n [invalid]=\"key.dirty && key.invalid\"\n [items]=\"$roleKeyItems()\"\n [loading]=\"$loadingRoles()\"\n [placeholder]=\"'accessControl.roles.selectRole' | translate\"\n ></v-select>\n }\n\n <button\n class=\"role-metadata-modal__mode-switch\"\n cdsButton=\"ghost\"\n size=\"sm\"\n type=\"button\"\n (click)=\"onKeyManualToggle(!$keyManual())\"\n >\n {{\n ($keyManual()\n ? 'accessControl.roles.chooseFromList'\n : 'accessControl.roles.enterManually'\n ) | translate\n }}\n </button>\n </div>\n </form>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button [disabled]=\"this.form.invalid\" (click)=\"onConfirm()\" cdsButton=\"primary\">\n {{ vars.isAdd ? ('interface.create' | translate) : ('interface.save' | translate) }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".role-metadata-modal__field{display:flex;flex-direction:column;gap:.5rem}.role-metadata-modal__field v-select{display:block;width:100%}.role-metadata-modal__field input{width:100%}.role-metadata-modal__mode-switch{align-self:flex-start}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i2$1.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i2$1.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i2$1.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i2$1.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i2$1.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i3$1.ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }, { kind: "directive", type: i2$1.TextInput, selector: "[cdsText], [ibmText]", inputs: ["theme", "size", "invalid", "warn", "skeleton"] }, { kind: "component", type: i3$1.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "directive", type: i2$1.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1102
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: RoleMetadataModalComponent, isStandalone: false, selector: "valtimo-role-metadata-modal", inputs: { type: "type", open: "open", defaultKeyValue: "defaultKeyValue", usedKeys: "usedKeys" }, outputs: { closeEvent: "closeEvent" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{\n isAdd: type === 'add',\n } as vars\"\n [open]=\"open\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n valtimoCdsModal\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{\n vars.isAdd\n ? ('accessControl.roles.add' | translate)\n : ('accessControl.roles.editRole' | translate)\n }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <form [formGroup]=\"form\">\n <div class=\"role-metadata-modal__field cds--form-item\">\n <label class=\"cds--label\">\n {{ 'accessControl.roles.name' | translate }} ({{ 'interface.required' | translate }})\n </label>\n\n @if ($keyManual()) {\n <input\n formControlName=\"key\"\n cdsText\n [attr.data-test-id]=\"testIds.metadataKeyInput\"\n placeholder=\"{{ 'accessControl.roles.name' | translate }}\"\n [attr.modal-primary-focus]=\"true\"\n [invalid]=\"key.dirty && key.invalid\"\n />\n } @else {\n <v-select\n formControlName=\"key\"\n [appendInline]=\"false\"\n [clearable]=\"false\"\n [defaultSelectionId]=\"key.value || ''\"\n [dropUp]=\"false\"\n [invalid]=\"key.dirty && key.invalid\"\n [items]=\"$roleKeyItems()\"\n [loading]=\"$loadingRoles()\"\n [placeholder]=\"'accessControl.roles.selectRole' | translate\"\n ></v-select>\n }\n\n <button\n class=\"role-metadata-modal__mode-switch\"\n cdsButton=\"ghost\"\n [attr.data-test-id]=\"testIds.metadataKeyModeSwitch\"\n size=\"sm\"\n type=\"button\"\n (click)=\"onKeyManualToggle(!$keyManual())\"\n >\n {{\n ($keyManual()\n ? 'accessControl.roles.chooseFromList'\n : 'accessControl.roles.enterManually'\n ) | translate\n }}\n </button>\n </div>\n </form>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.metadataCancelButton\"\n (click)=\"onCancel()\"\n >\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n [disabled]=\"this.form.invalid\"\n [attr.data-test-id]=\"testIds.metadataConfirmButton\"\n (click)=\"onConfirm()\"\n cdsButton=\"primary\"\n >\n {{ vars.isAdd ? ('interface.create' | translate) : ('interface.save' | translate) }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".role-metadata-modal__field{display:flex;flex-direction:column;gap:.5rem}.role-metadata-modal__field v-select{display:block;width:100%}.role-metadata-modal__field input{width:100%}.role-metadata-modal__mode-switch{align-self:flex-start}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i2$1.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i2$1.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i2$1.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i2$1.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i2$1.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i3$1.ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }, { kind: "directive", type: i2$1.TextInput, selector: "[cdsText], [ibmText]", inputs: ["theme", "size", "invalid", "warn", "skeleton"] }, { kind: "component", type: i3$1.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "directive", type: i2$1.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1063
1103
  }
1064
1104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: RoleMetadataModalComponent, decorators: [{
1065
1105
  type: Component,
1066
- args: [{ standalone: false, selector: 'valtimo-role-metadata-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{\n isAdd: type === 'add',\n } as vars\"\n [open]=\"open\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n valtimoCdsModal\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{\n vars.isAdd\n ? ('accessControl.roles.add' | translate)\n : ('accessControl.roles.editRole' | translate)\n }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <form [formGroup]=\"form\">\n <div class=\"role-metadata-modal__field cds--form-item\">\n <label class=\"cds--label\">\n {{ 'accessControl.roles.name' | translate }} ({{ 'interface.required' | translate }})\n </label>\n\n @if ($keyManual()) {\n <input\n formControlName=\"key\"\n cdsText\n placeholder=\"{{ 'accessControl.roles.name' | translate }}\"\n [attr.modal-primary-focus]=\"true\"\n [invalid]=\"key.dirty && key.invalid\"\n />\n } @else {\n <v-select\n formControlName=\"key\"\n [appendInline]=\"false\"\n [clearable]=\"false\"\n [defaultSelectionId]=\"key.value || ''\"\n [dropUp]=\"false\"\n [invalid]=\"key.dirty && key.invalid\"\n [items]=\"$roleKeyItems()\"\n [loading]=\"$loadingRoles()\"\n [placeholder]=\"'accessControl.roles.selectRole' | translate\"\n ></v-select>\n }\n\n <button\n class=\"role-metadata-modal__mode-switch\"\n cdsButton=\"ghost\"\n size=\"sm\"\n type=\"button\"\n (click)=\"onKeyManualToggle(!$keyManual())\"\n >\n {{\n ($keyManual()\n ? 'accessControl.roles.chooseFromList'\n : 'accessControl.roles.enterManually'\n ) | translate\n }}\n </button>\n </div>\n </form>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button [disabled]=\"this.form.invalid\" (click)=\"onConfirm()\" cdsButton=\"primary\">\n {{ vars.isAdd ? ('interface.create' | translate) : ('interface.save' | translate) }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".role-metadata-modal__field{display:flex;flex-direction:column;gap:.5rem}.role-metadata-modal__field v-select{display:block;width:100%}.role-metadata-modal__field input{width:100%}.role-metadata-modal__mode-switch{align-self:flex-start}\n"] }]
1106
+ args: [{ standalone: false, selector: 'valtimo-role-metadata-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{\n isAdd: type === 'add',\n } as vars\"\n [open]=\"open\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n valtimoCdsModal\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{\n vars.isAdd\n ? ('accessControl.roles.add' | translate)\n : ('accessControl.roles.editRole' | translate)\n }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <form [formGroup]=\"form\">\n <div class=\"role-metadata-modal__field cds--form-item\">\n <label class=\"cds--label\">\n {{ 'accessControl.roles.name' | translate }} ({{ 'interface.required' | translate }})\n </label>\n\n @if ($keyManual()) {\n <input\n formControlName=\"key\"\n cdsText\n [attr.data-test-id]=\"testIds.metadataKeyInput\"\n placeholder=\"{{ 'accessControl.roles.name' | translate }}\"\n [attr.modal-primary-focus]=\"true\"\n [invalid]=\"key.dirty && key.invalid\"\n />\n } @else {\n <v-select\n formControlName=\"key\"\n [appendInline]=\"false\"\n [clearable]=\"false\"\n [defaultSelectionId]=\"key.value || ''\"\n [dropUp]=\"false\"\n [invalid]=\"key.dirty && key.invalid\"\n [items]=\"$roleKeyItems()\"\n [loading]=\"$loadingRoles()\"\n [placeholder]=\"'accessControl.roles.selectRole' | translate\"\n ></v-select>\n }\n\n <button\n class=\"role-metadata-modal__mode-switch\"\n cdsButton=\"ghost\"\n [attr.data-test-id]=\"testIds.metadataKeyModeSwitch\"\n size=\"sm\"\n type=\"button\"\n (click)=\"onKeyManualToggle(!$keyManual())\"\n >\n {{\n ($keyManual()\n ? 'accessControl.roles.chooseFromList'\n : 'accessControl.roles.enterManually'\n ) | translate\n }}\n </button>\n </div>\n </form>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.metadataCancelButton\"\n (click)=\"onCancel()\"\n >\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n [disabled]=\"this.form.invalid\"\n [attr.data-test-id]=\"testIds.metadataConfirmButton\"\n (click)=\"onConfirm()\"\n cdsButton=\"primary\"\n >\n {{ vars.isAdd ? ('interface.create' | translate) : ('interface.save' | translate) }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".role-metadata-modal__field{display:flex;flex-direction:column;gap:.5rem}.role-metadata-modal__field v-select{display:block;width:100%}.role-metadata-modal__field input{width:100%}.role-metadata-modal__mode-switch{align-self:flex-start}\n"] }]
1067
1107
  }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: AccessControlService }], propDecorators: { type: [{
1068
1108
  type: Input
1069
1109
  }], open: [{
@@ -1133,6 +1173,7 @@ class ExportRoleModalComponent {
1133
1173
  this.exportEvent = new EventEmitter();
1134
1174
  this.closeEvent = new EventEmitter();
1135
1175
  this.selectedType$ = new BehaviorSubject(null);
1176
+ this.testIds = ACCESS_CONTROL_ROLES_TEST_IDS;
1136
1177
  }
1137
1178
  ngOnInit() {
1138
1179
  this.openResetSubscription();
@@ -1164,11 +1205,11 @@ class ExportRoleModalComponent {
1164
1205
  });
1165
1206
  }
1166
1207
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ExportRoleModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1167
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: ExportRoleModalComponent, isStandalone: false, selector: "valtimo-export-role-modal", inputs: { open: "open", exportRowKeys: "exportRowKeys", reset$: "reset$", disabled: "disabled" }, outputs: { exportEvent: "exportEvent", closeEvent: "closeEvent" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{title: ('interface.export' | translate), selectedType: selectedType$ | async} as vars\"\n valtimoCdsModal\n [open]=\"open\"\n size=\"sm\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{ vars.title }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <div class=\"export-buttons\">\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"selectType('unified')\">\n {{ 'accessControl.roles.singleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"document\" size=\"16\"></svg>\n </button>\n\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"selectType('separate')\">\n {{ 'accessControl.roles.multipleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"copy--file\" size=\"16\"></svg>\n </button>\n </div>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n [disabled]=\"!vars.selectedType || disabled\"\n cdsButton=\"primary\"\n (click)=\"onConfirm(vars.selectedType)\"\n >\n {{ vars.title }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".export-buttons{display:grid;width:100%;grid-template-columns:1fr 1fr;column-gap:16px}.export-buttons button{width:100%}\n/*!\n * Copyright 2015-2025 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: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "component", type: i2$1.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i2$1.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i2$1.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i2$1.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i2$1.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "directive", type: i3$1.ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "directive", type: i2$1.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1208
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: ExportRoleModalComponent, isStandalone: false, selector: "valtimo-export-role-modal", inputs: { open: "open", exportRowKeys: "exportRowKeys", reset$: "reset$", disabled: "disabled" }, outputs: { exportEvent: "exportEvent", closeEvent: "closeEvent" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{title: ('interface.export' | translate), selectedType: selectedType$ | async} as vars\"\n valtimoCdsModal\n [open]=\"open\"\n size=\"sm\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{ vars.title }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <div class=\"export-buttons\">\n <button\n [disabled]=\"disabled\"\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.exportModalSingleFile\"\n (click)=\"selectType('unified')\"\n >\n {{ 'accessControl.roles.singleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"document\" size=\"16\"></svg>\n </button>\n\n <button\n [disabled]=\"disabled\"\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.exportModalSeparateFiles\"\n (click)=\"selectType('separate')\"\n >\n {{ 'accessControl.roles.multipleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"copy--file\" size=\"16\"></svg>\n </button>\n </div>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n [disabled]=\"!vars.selectedType || disabled\"\n cdsButton=\"primary\"\n [attr.data-test-id]=\"testIds.exportModalConfirmButton\"\n (click)=\"onConfirm(vars.selectedType)\"\n >\n {{ vars.title }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".export-buttons{display:grid;width:100%;grid-template-columns:1fr 1fr;column-gap:16px}.export-buttons button{width:100%}\n/*!\n * Copyright 2015-2025 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: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "component", type: i2$1.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i2$1.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i2$1.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i2$1.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i2$1.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "directive", type: i3$1.ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "directive", type: i2$1.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1168
1209
  }
1169
1210
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ExportRoleModalComponent, decorators: [{
1170
1211
  type: Component,
1171
- args: [{ standalone: false, selector: 'valtimo-export-role-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{title: ('interface.export' | translate), selectedType: selectedType$ | async} as vars\"\n valtimoCdsModal\n [open]=\"open\"\n size=\"sm\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{ vars.title }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <div class=\"export-buttons\">\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"selectType('unified')\">\n {{ 'accessControl.roles.singleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"document\" size=\"16\"></svg>\n </button>\n\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"selectType('separate')\">\n {{ 'accessControl.roles.multipleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"copy--file\" size=\"16\"></svg>\n </button>\n </div>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n [disabled]=\"!vars.selectedType || disabled\"\n cdsButton=\"primary\"\n (click)=\"onConfirm(vars.selectedType)\"\n >\n {{ vars.title }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".export-buttons{display:grid;width:100%;grid-template-columns:1fr 1fr;column-gap:16px}.export-buttons button{width:100%}\n/*!\n * Copyright 2015-2025 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"] }]
1212
+ args: [{ standalone: false, selector: 'valtimo-export-role-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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\n *ngIf=\"{title: ('interface.export' | translate), selectedType: selectedType$ | async} as vars\"\n valtimoCdsModal\n [open]=\"open\"\n size=\"sm\"\n showFooter=\"true\"\n [title]=\"vars.title\"\n (close)=\"onCancel()\"\n>\n <cds-modal-header [cdsLayer]=\"1\" [showCloseButton]=\"true\" (closeSelect)=\"onCancel()\">\n <h3 cdsModalHeaderHeading>\n {{ vars.title }}\n </h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\">\n <div class=\"export-buttons\">\n <button\n [disabled]=\"disabled\"\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.exportModalSingleFile\"\n (click)=\"selectType('unified')\"\n >\n {{ 'accessControl.roles.singleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"document\" size=\"16\"></svg>\n </button>\n\n <button\n [disabled]=\"disabled\"\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.exportModalSeparateFiles\"\n (click)=\"selectType('separate')\"\n >\n {{ 'accessControl.roles.multipleExport' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"copy--file\" size=\"16\"></svg>\n </button>\n </div>\n </section>\n\n <cds-modal-footer [cdsLayer]=\"1\">\n <button [disabled]=\"disabled\" cdsButton=\"secondary\" (click)=\"onCancel()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n [disabled]=\"!vars.selectedType || disabled\"\n cdsButton=\"primary\"\n [attr.data-test-id]=\"testIds.exportModalConfirmButton\"\n (click)=\"onConfirm(vars.selectedType)\"\n >\n {{ vars.title }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [".export-buttons{display:grid;width:100%;grid-template-columns:1fr 1fr;column-gap:16px}.export-buttons button{width:100%}\n/*!\n * Copyright 2015-2025 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"] }]
1172
1213
  }], propDecorators: { open: [{
1173
1214
  type: Input
1174
1215
  }], exportRowKeys: [{
@@ -1221,6 +1262,7 @@ class AccessControlOverviewComponent {
1221
1262
  this.selectedRowKeys$ = new BehaviorSubject([]);
1222
1263
  this.resetExportType$ = new Subject();
1223
1264
  this.exportDisabled$ = new BehaviorSubject(false);
1265
+ this.testIds = ACCESS_CONTROL_ROLES_TEST_IDS;
1224
1266
  }
1225
1267
  ngOnInit() {
1226
1268
  this.accessControlService.loadRoles();
@@ -1278,11 +1320,11 @@ class AccessControlOverviewComponent {
1278
1320
  this.selectedRowKeys$.next(this.carbonList.selectedItems.map((role) => role.roleKey));
1279
1321
  }
1280
1322
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AccessControlOverviewComponent, deps: [{ token: AccessControlService }, { token: AccessControlExportService }, { token: i1$3.Router }], target: i0.ɵɵFactoryTarget.Component }); }
1281
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: AccessControlOverviewComponent, isStandalone: false, selector: "ng-component", viewQueries: [{ propertyName: "carbonList", first: true, predicate: CarbonListComponent, descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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<valtimo-carbon-list\n [header]=\"false\"\n [items]=\"roles$ | async\"\n [fields]=\"fields\"\n [loading]=\"loading$ | async\"\n [showSelectionColumn]=\"true\"\n (rowClicked)=\"onRowClick($event)\"\n>\n <ng-container header> {{ 'accessControl.roles.title' | translate }} </ng-container>\n\n <div carbonToolbarContent>\n <ng-container [ngTemplateOutlet]=\"addRoleButton\"></ng-container>\n </div>\n\n <ng-container carbonToolbarActions>\n <button cdsButton=\"primary\" (click)=\"showDeleteModal()\">\n {{ 'interface.delete' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n\n <button cdsButton=\"primary\" (click)=\"showExportModal()\">\n {{ 'interface.export' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"download\" size=\"16\"></svg>\n </button>\n </ng-container>\n\n <valtimo-no-results\n [action]=\"addRoleButton\"\n description=\"{{ 'accessControl.roles.noResults.description' | translate }}\"\n title=\"{{ 'accessControl.roles.noResults.title' | translate }}\"\n ></valtimo-no-results>\n</valtimo-carbon-list>\n\n<valtimo-role-metadata-modal\n [open]=\"showAddModal$ | async\"\n [usedKeys]=\"existingRoleKeys$ | async\"\n (closeEvent)=\"onAdd($event)\"\n></valtimo-role-metadata-modal>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-export-role-modal\n [disabled]=\"exportDisabled$ | async\"\n [exportRowKeys]=\"obs.selectedRowKeys\"\n [open]=\"showExportModal$ | async\"\n [reset$]=\"resetExportType$\"\n (exportEvent)=\"onExport($event)\"\n (closeEvent)=\"closeExportModal()\"\n >\n </valtimo-export-role-modal>\n</ng-container>\n\n<ng-template #addRoleButton>\n <button cdsButton=\"primary\" (click)=\"openAddModal()\">\n {{ 'accessControl.roles.add' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: i3$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: i3$1.CarbonNoResultsComponent, selector: "valtimo-no-results", inputs: ["action", "description", "illustration", "title", "smallPadding", "collapseVertically", "alwaysRenderVertically"] }, { kind: "component", type: RoleMetadataModalComponent, selector: "valtimo-role-metadata-modal", inputs: ["type", "open", "defaultKeyValue", "usedKeys"], outputs: ["closeEvent"] }, { kind: "component", type: DeleteRoleModalComponent, selector: "valtimo-delete-role-modal", inputs: ["deleteRowKeys", "showDeleteModal$"], outputs: ["deleteEvent"] }, { kind: "component", type: ExportRoleModalComponent, selector: "valtimo-export-role-modal", inputs: ["open", "exportRowKeys", "reset$", "disabled"], outputs: ["exportEvent", "closeEvent"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1323
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: AccessControlOverviewComponent, isStandalone: false, selector: "ng-component", viewQueries: [{ propertyName: "carbonList", first: true, predicate: CarbonListComponent, descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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<valtimo-carbon-list\n [header]=\"false\"\n [items]=\"roles$ | async\"\n [fields]=\"fields\"\n [loading]=\"loading$ | async\"\n [showSelectionColumn]=\"true\"\n (rowClicked)=\"onRowClick($event)\"\n>\n <ng-container header> {{ 'accessControl.roles.title' | translate }} </ng-container>\n\n <div carbonToolbarContent>\n <ng-container [ngTemplateOutlet]=\"addRoleButton\"></ng-container>\n </div>\n\n <ng-container carbonToolbarActions>\n <button cdsButton=\"primary\" (click)=\"showDeleteModal()\">\n {{ 'interface.delete' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"primary\"\n [attr.data-test-id]=\"testIds.exportButton\"\n (click)=\"showExportModal()\"\n >\n {{ 'interface.export' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"download\" size=\"16\"></svg>\n </button>\n </ng-container>\n\n <valtimo-no-results\n [action]=\"addRoleButton\"\n description=\"{{ 'accessControl.roles.noResults.description' | translate }}\"\n title=\"{{ 'accessControl.roles.noResults.title' | translate }}\"\n ></valtimo-no-results>\n</valtimo-carbon-list>\n\n<valtimo-role-metadata-modal\n [open]=\"showAddModal$ | async\"\n [usedKeys]=\"existingRoleKeys$ | async\"\n (closeEvent)=\"onAdd($event)\"\n></valtimo-role-metadata-modal>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-export-role-modal\n [disabled]=\"exportDisabled$ | async\"\n [exportRowKeys]=\"obs.selectedRowKeys\"\n [open]=\"showExportModal$ | async\"\n [reset$]=\"resetExportType$\"\n (exportEvent)=\"onExport($event)\"\n (closeEvent)=\"closeExportModal()\"\n >\n </valtimo-export-role-modal>\n</ng-container>\n\n<ng-template #addRoleButton>\n <button cdsButton=\"primary\" (click)=\"openAddModal()\">\n {{ 'accessControl.roles.add' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: i3$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: i3$1.CarbonNoResultsComponent, selector: "valtimo-no-results", inputs: ["action", "description", "illustration", "title", "smallPadding", "collapseVertically", "alwaysRenderVertically"] }, { kind: "component", type: RoleMetadataModalComponent, selector: "valtimo-role-metadata-modal", inputs: ["type", "open", "defaultKeyValue", "usedKeys"], outputs: ["closeEvent"] }, { kind: "component", type: DeleteRoleModalComponent, selector: "valtimo-delete-role-modal", inputs: ["deleteRowKeys", "showDeleteModal$"], outputs: ["deleteEvent"] }, { kind: "component", type: ExportRoleModalComponent, selector: "valtimo-export-role-modal", inputs: ["open", "exportRowKeys", "reset$", "disabled"], outputs: ["exportEvent", "closeEvent"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1282
1324
  }
1283
1325
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AccessControlOverviewComponent, decorators: [{
1284
1326
  type: Component,
1285
- args: [{ standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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<valtimo-carbon-list\n [header]=\"false\"\n [items]=\"roles$ | async\"\n [fields]=\"fields\"\n [loading]=\"loading$ | async\"\n [showSelectionColumn]=\"true\"\n (rowClicked)=\"onRowClick($event)\"\n>\n <ng-container header> {{ 'accessControl.roles.title' | translate }} </ng-container>\n\n <div carbonToolbarContent>\n <ng-container [ngTemplateOutlet]=\"addRoleButton\"></ng-container>\n </div>\n\n <ng-container carbonToolbarActions>\n <button cdsButton=\"primary\" (click)=\"showDeleteModal()\">\n {{ 'interface.delete' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n\n <button cdsButton=\"primary\" (click)=\"showExportModal()\">\n {{ 'interface.export' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"download\" size=\"16\"></svg>\n </button>\n </ng-container>\n\n <valtimo-no-results\n [action]=\"addRoleButton\"\n description=\"{{ 'accessControl.roles.noResults.description' | translate }}\"\n title=\"{{ 'accessControl.roles.noResults.title' | translate }}\"\n ></valtimo-no-results>\n</valtimo-carbon-list>\n\n<valtimo-role-metadata-modal\n [open]=\"showAddModal$ | async\"\n [usedKeys]=\"existingRoleKeys$ | async\"\n (closeEvent)=\"onAdd($event)\"\n></valtimo-role-metadata-modal>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-export-role-modal\n [disabled]=\"exportDisabled$ | async\"\n [exportRowKeys]=\"obs.selectedRowKeys\"\n [open]=\"showExportModal$ | async\"\n [reset$]=\"resetExportType$\"\n (exportEvent)=\"onExport($event)\"\n (closeEvent)=\"closeExportModal()\"\n >\n </valtimo-export-role-modal>\n</ng-container>\n\n<ng-template #addRoleButton>\n <button cdsButton=\"primary\" (click)=\"openAddModal()\">\n {{ 'accessControl.roles.add' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n</ng-template>\n" }]
1327
+ args: [{ standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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<valtimo-carbon-list\n [header]=\"false\"\n [items]=\"roles$ | async\"\n [fields]=\"fields\"\n [loading]=\"loading$ | async\"\n [showSelectionColumn]=\"true\"\n (rowClicked)=\"onRowClick($event)\"\n>\n <ng-container header> {{ 'accessControl.roles.title' | translate }} </ng-container>\n\n <div carbonToolbarContent>\n <ng-container [ngTemplateOutlet]=\"addRoleButton\"></ng-container>\n </div>\n\n <ng-container carbonToolbarActions>\n <button cdsButton=\"primary\" (click)=\"showDeleteModal()\">\n {{ 'interface.delete' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"primary\"\n [attr.data-test-id]=\"testIds.exportButton\"\n (click)=\"showExportModal()\"\n >\n {{ 'interface.export' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"download\" size=\"16\"></svg>\n </button>\n </ng-container>\n\n <valtimo-no-results\n [action]=\"addRoleButton\"\n description=\"{{ 'accessControl.roles.noResults.description' | translate }}\"\n title=\"{{ 'accessControl.roles.noResults.title' | translate }}\"\n ></valtimo-no-results>\n</valtimo-carbon-list>\n\n<valtimo-role-metadata-modal\n [open]=\"showAddModal$ | async\"\n [usedKeys]=\"existingRoleKeys$ | async\"\n (closeEvent)=\"onAdd($event)\"\n></valtimo-role-metadata-modal>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-export-role-modal\n [disabled]=\"exportDisabled$ | async\"\n [exportRowKeys]=\"obs.selectedRowKeys\"\n [open]=\"showExportModal$ | async\"\n [reset$]=\"resetExportType$\"\n (exportEvent)=\"onExport($event)\"\n (closeEvent)=\"closeExportModal()\"\n >\n </valtimo-export-role-modal>\n</ng-container>\n\n<ng-template #addRoleButton>\n <button cdsButton=\"primary\" (click)=\"openAddModal()\">\n {{ 'accessControl.roles.add' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n</ng-template>\n" }]
1286
1328
  }], ctorParameters: () => [{ type: AccessControlService }, { type: AccessControlExportService }, { type: i1$3.Router }], propDecorators: { carbonList: [{
1287
1329
  type: ViewChild,
1288
1330
  args: [CarbonListComponent]
@@ -1732,11 +1774,11 @@ class PermissionFormComponent {
1732
1774
  this.contextResourceTypeItems = this.formEditorService.containerTargetItems(this.resourceTypeValue, this.hasContextResource ? this.contextResourceTypeValue : null);
1733
1775
  }
1734
1776
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PermissionFormComponent, deps: [{ token: AccessControlFormEditorService }, { token: i2$1.IconService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
1735
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: PermissionFormComponent, isStandalone: false, selector: "valtimo-permission-form", inputs: { group: "group", index: "index", disabled: "disabled", roleKey: "roleKey" }, outputs: { removeEvent: "removeEvent" }, 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=\"permission-form\"\n [attr.data-test-id]=\"testIds.permissionCard\"\n [cdsLayer]=\"0\"\n [formGroup]=\"group\"\n>\n @if ($loading()) {\n <div class=\"permission-form__loading\">\n <cds-loading [isActive]=\"true\" [overlay]=\"false\" size=\"sm\"></cds-loading>\n </div>\n }\n\n <div class=\"permission-form__body\" [class.permission-form__body--hidden]=\"$loading()\">\n <!-- Header block: the permission preview followed by an editor-level note, separated from the\n editable sections below by a subtle divider. -->\n <div class=\"permission-form__header\">\n <!-- A larger preview of the permission (the same information shown in the sidebar list), so\n the rule being edited is recognisable at the top of the panel. The full resource type is\n shown here (the sidebar only shows the short name). -->\n <div class=\"permission-form__preview\">\n <div class=\"permission-form__preview-heading\">\n <h4 class=\"permission-form__preview-title\">\n @if (resourceTypeValue) {\n {{ resourceShortName }}\n } @else {\n {{ 'accessControl.editor.newPermission' | translate }}\n }\n </h4>\n\n @if (resourceTypeValue) {\n <span class=\"permission-form__preview-subtitle\">{{ resourceTypeValue }}</span>\n }\n </div>\n\n @if (conditionsArray.length || hasContext) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.includes' | translate\n }}</span>\n\n @if (conditionsArray.length) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasConditions' | translate\n }}</cds-tag>\n }\n @if (hasContext) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasContext' | translate\n }}</cds-tag>\n }\n </div>\n }\n\n @if (selectedActions.length) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.actions' | translate\n }}</span>\n\n @for (action of selectedActions; track action) {\n <cds-tag size=\"sm\" [type]=\"action | actionTagType\">{{\n action | actionLabel\n }}</cds-tag>\n }\n </div>\n }\n </div>\n\n <!-- Editor-level note: applies to the role selected on this page, and only system-supported\n options can be selected. -->\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {\n $implicit: resourceShortName\n ? ('accessControl.editor.permissionsHint'\n | translate: {resource: resourceShortName, role: roleKey})\n : ('accessControl.editor.permissionsHintNew' | translate: {role: roleKey}),\n }\n \"\n ></ng-container>\n </div>\n\n <cds-accordion class=\"permission-form__accordion\">\n <cds-accordion-item\n [expanded]=\"$openSection() === 'resourceActions'\"\n [title]=\"'accessControl.editor.resourceAndActions' | translate\"\n (selected)=\"onSectionToggle('resourceActions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.resourceActionsHint' | translate}\n \"\n ></ng-container>\n\n <div class=\"permission-form__row\">\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"resourceType\"\n [cdsLayer]=\"1\"\n [dataTestId]=\"testIds.resourceTypeSelect\"\n [defaultSelectionId]=\"resourceTypeValue\"\n [dropUp]=\"false\"\n [invalid]=\"group.get('resourceType')!.invalid && group.get('resourceType')!.touched\"\n [items]=\"resourceTypeItems\"\n [placeholder]=\"'accessControl.editor.resourceTypePlaceholder' | translate\"\n [required]=\"true\"\n [tooltip]=\"'accessControl.editor.tooltips.resourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.resourceType\"\n ></v-select>\n\n <div class=\"permission-form__actions-field\">\n <label class=\"cds--label label-with-tooltip\">\n {{ 'accessControl.editor.actions' | translate }} ({{\n 'interface.required' | translate\n }})\n <v-tooltip-icon\n [tooltip]=\"'accessControl.editor.tooltips.actions' | translate\"\n ></v-tooltip-icon>\n </label>\n\n @if (actionItems.length) {\n <div\n class=\"permission-form__actions-grid\"\n [attr.data-test-id]=\"testIds.actionsSelect\"\n [class.permission-form__actions-grid--invalid]=\"\n actionsControl.invalid && actionsControl.touched\n \"\n >\n @for (item of actionItems; track item.id) {\n <div class=\"permission-form__action\">\n <cds-checkbox\n [checked]=\"selectedActions.includes(item.id)\"\n [disabled]=\"disabled\"\n (checkedChange)=\"onActionToggle(item.id, $event)\"\n >\n {{ item.id | actionLabel }}\n </cds-checkbox>\n\n @if (item.id | actionDescription; as description) {\n <v-tooltip-icon [tooltip]=\"description\"></v-tooltip-icon>\n }\n </div>\n }\n </div>\n } @else {\n <p class=\"permission-form__hint\">\n {{ 'accessControl.editor.noActions' | translate }}\n </p>\n }\n </div>\n </div>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [class.permission-form__section-configured]=\"conditionsArray.length > 0\"\n [expanded]=\"$openSection() === 'conditions'\"\n [title]=\"'accessControl.editor.conditions' | translate\"\n (selected)=\"onSectionToggle('conditions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.conditionsHint' | translate}\n \"\n ></ng-container>\n\n <valtimo-condition-tree\n [conditions]=\"conditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"resourceTypeValue\"\n ></valtimo-condition-tree>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [class.permission-form__section-configured]=\"hasContext\"\n [expanded]=\"$openSection() === 'context'\"\n [title]=\"'accessControl.editor.contextSection' | translate\"\n (selected)=\"onSectionToggle('context', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.contextHint' | translate}\n \"\n ></ng-container>\n\n <cds-content-switcher\n class=\"permission-form__context-switcher\"\n [attr.data-test-id]=\"testIds.contextToggle\"\n [class.permission-form__context-switcher--disabled]=\"disabled\"\n size=\"sm\"\n >\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'none'\"\n (selected)=\"onContextModeChange('none')\"\n >\n {{ 'accessControl.editor.contextModeNone' | translate }}\n </button>\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'noContext'\"\n (selected)=\"onContextModeChange('noContext')\"\n >\n {{ 'accessControl.editor.contextModeNoContext' | translate }}\n </button>\n @if (hasContextTargets) {\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'specific'\"\n (selected)=\"onContextModeChange('specific')\"\n >\n {{ 'accessControl.editor.contextModeSpecific' | translate }}\n </button>\n }\n </cds-content-switcher>\n\n @switch (contextMode) {\n @case ('noContext') {\n <cds-inline-notification\n class=\"permission-form__notification\"\n [notificationObj]=\"{\n type: 'info',\n message: 'accessControl.editor.noContextHint' | translate,\n lowContrast: true,\n showClose: false,\n }\"\n ></cds-inline-notification>\n }\n @case ('specific') {\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"contextResourceType\"\n [cdsLayer]=\"1\"\n [clearable]=\"false\"\n [dataTestId]=\"testIds.contextResourceTypeSelect\"\n [defaultSelectionId]=\"contextResourceTypeValue || ''\"\n [dropUp]=\"false\"\n [items]=\"contextResourceTypeItems\"\n [placeholder]=\"'accessControl.editor.contextResourceTypePlaceholder' | translate\"\n [tooltip]=\"'accessControl.editor.tooltips.contextResourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.contextResourceType\"\n ></v-select>\n\n <valtimo-condition-tree\n [conditions]=\"contextConditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"contextResourceTypeValue\"\n ></valtimo-condition-tree>\n }\n }\n </div>\n </cds-accordion-item>\n </cds-accordion>\n\n <div class=\"permission-form__footer\">\n <button\n cdsButton=\"danger--ghost\"\n size=\"sm\"\n [attr.data-test-id]=\"testIds.removePermissionButton\"\n [disabled]=\"disabled\"\n (click)=\"openRemoveModal()\"\n >\n {{ 'accessControl.editor.removePermission' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"accessControl.editor.removePermission\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"accessControl.editor.removePermissionModal.content\"\n titleTranslationKey=\"accessControl.editor.removePermissionModal.title\"\n [showModalSubject$]=\"showRemoveModal$\"\n (confirmEvent)=\"onRemove()\"\n ></valtimo-confirmation-modal>\n\n <!-- Lightweight inline hint: a blue information icon with italic secondary text. The message is\n passed in via context so the icon and styling are defined in a single place. -->\n <ng-template #infoNote let-message>\n <p class=\"permission-form__info-note\">\n <svg class=\"permission-form__info-icon\" cdsIcon=\"information\" size=\"16\"></svg>\n\n <span>{{ message }}</span>\n </p>\n </ng-template>\n</div>\n", styles: [".permission-form{display:flex;flex-direction:column}.permission-form v-select{display:block;width:100%}.permission-form__loading{align-items:center;display:flex;justify-content:center;padding:1.5rem 0}.permission-form__body{display:flex;flex-direction:column;gap:1rem}.permission-form__body--hidden{display:none}.permission-form__accordion{width:100%}.permission-form__header{border-bottom:1px solid var(--cds-border-subtle, #e0e0e0);display:flex;flex-direction:column;gap:1rem;padding-bottom:1.5rem}.permission-form__preview{display:flex;flex-direction:column;gap:.5rem}.permission-form__preview-heading{display:flex;flex-direction:column;gap:.125rem}.permission-form__preview-title{font-size:1.25rem;font-weight:400;line-height:1.4;margin:0;overflow-wrap:anywhere}.permission-form__preview-subtitle{color:var(--cds-text-secondary, #525252);font-size:.75rem;font-weight:400;line-height:1.34;overflow-wrap:anywhere}.permission-form__preview-row{align-items:center;display:flex;flex-wrap:wrap;gap:.25rem}.permission-form__preview-row ::ng-deep .cds--tag{margin:0;max-width:none}.permission-form__preview-label{color:var(--cds-text-secondary, #525252);font-size:.875rem;font-weight:600;padding-right:.5rem}.permission-form__row{display:flex;flex-direction:column;gap:1rem}.permission-form__context-switcher{display:block;width:100%}.permission-form__context-switcher--disabled{opacity:.5;pointer-events:none}.permission-form__actions-field{display:flex;flex-direction:column;gap:.5rem}.permission-form__actions-grid{display:grid;gap:.25rem 1rem;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr))}.permission-form__actions-grid--invalid{border-left:2px solid var(--cds-support-error, #da1e28);margin-left:-.75rem;padding-left:calc(.75rem - 2px)}.permission-form__action{align-items:center;display:flex;gap:.25rem}.permission-form .label-with-tooltip{align-items:center;display:inline-flex;gap:.25rem}.permission-form__section{display:flex;flex-direction:column;gap:.75rem}.permission-form__hint{color:var(--cds-text-secondary, #525252);font-size:.875rem;margin:0}.permission-form__info-note{align-items:flex-start;color:var(--cds-text-secondary, #525252);display:flex;font-size:.875rem;gap:.375rem;line-height:1.34;margin-bottom:8px}.permission-form__info-icon{color:var(--cds-support-info, #0043ce);flex-shrink:0;margin-top:.0625rem}.permission-form__footer{display:flex;justify-content:flex-end;padding-top:.25rem}:host ::ng-deep .permission-form__accordion .cds--accordion__item:first-of-type{border-top:0}:host ::ng-deep .permission-form__accordion .cds--accordion__content{padding:1rem 1rem 1.5rem}:host ::ng-deep .permission-form__accordion .permission-form__section-configured .cds--accordion__title:after{background:var(--cds-support-info, #0043ce);border-radius:50%;content:\"\";display:inline-block;height:.5rem;margin-left:.5rem;vertical-align:middle;width:.5rem}:host ::ng-deep .permission-form__notification.cds--inline-notification{inline-size:100%;margin-block-end:0;max-inline-size:100%;min-inline-size: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"], dependencies: [{ kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: i3$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: i2$1.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "component", type: i2$1.Notification, selector: "cds-notification, cds-inline-notification, ibm-notification, ibm-inline-notification", inputs: ["notificationObj"] }, { kind: "component", type: i3$1.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "component", type: i3$1.TooltipIconComponent, selector: "v-tooltip-icon", inputs: ["tooltip", "disabled"] }, { kind: "component", type: i2$1.ContentSwitcher, selector: "cds-content-switcher, ibm-content-switcher", inputs: ["ariaLabel", "size"], outputs: ["selected"] }, { kind: "directive", type: i2$1.ContentSwitcherOption, selector: "[cdsContentOption], [ibmContentOption]", inputs: ["active", "name"], outputs: ["selected", "onClick", "onFocus"] }, { kind: "component", type: i2$1.Accordion, selector: "cds-accordion, ibm-accordion", inputs: ["align", "size", "skeleton"] }, { kind: "component", type: i2$1.AccordionItem, selector: "cds-accordion-item, ibm-accordion-item", inputs: ["title", "context", "id", "skeleton", "expanded", "disabled"], outputs: ["selected"] }, { kind: "component", type: i2$1.Checkbox, selector: "cds-checkbox, ibm-checkbox", inputs: ["disabled", "skeleton", "hideLabel", "name", "id", "required", "value", "ariaLabel", "ariaLabelledby", "indeterminate", "checked"], outputs: ["click", "checkedChange", "indeterminateChange"] }, { kind: "directive", type: i2$1.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "component", type: i2$1.Tag, selector: "cds-tag, ibm-tag", inputs: ["type", "size", "class", "skeleton"] }, { kind: "component", type: ConditionTreeComponent, selector: "valtimo-condition-tree", inputs: ["conditions", "resourceType", "disabled", "depth"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }, { kind: "pipe", type: ActionLabelPipe, name: "actionLabel" }, { kind: "pipe", type: ActionDescriptionPipe, name: "actionDescription" }, { kind: "pipe", type: ActionTagTypePipe, name: "actionTagType" }] }); }
1777
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: PermissionFormComponent, isStandalone: false, selector: "valtimo-permission-form", inputs: { group: "group", index: "index", disabled: "disabled", roleKey: "roleKey" }, outputs: { removeEvent: "removeEvent" }, 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=\"permission-form\"\n [attr.data-test-id]=\"testIds.permissionCard\"\n [cdsLayer]=\"0\"\n [formGroup]=\"group\"\n>\n @if ($loading()) {\n <div class=\"permission-form__loading\">\n <cds-loading [isActive]=\"true\" [overlay]=\"false\" size=\"sm\"></cds-loading>\n </div>\n }\n\n <div class=\"permission-form__body\" [class.permission-form__body--hidden]=\"$loading()\">\n <!-- Header block: the permission preview followed by an editor-level note, separated from the\n editable sections below by a subtle divider. -->\n <div class=\"permission-form__header\">\n <!-- A larger preview of the permission (the same information shown in the sidebar list), so\n the rule being edited is recognisable at the top of the panel. The full resource type is\n shown here (the sidebar only shows the short name). -->\n <div class=\"permission-form__preview\">\n <div class=\"permission-form__preview-heading\">\n <h4 class=\"permission-form__preview-title\">\n @if (resourceTypeValue) {\n {{ resourceShortName }}\n } @else {\n {{ 'accessControl.editor.newPermission' | translate }}\n }\n </h4>\n\n @if (resourceTypeValue) {\n <span class=\"permission-form__preview-subtitle\">{{ resourceTypeValue }}</span>\n }\n </div>\n\n @if (conditionsArray.length || hasContext) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.includes' | translate\n }}</span>\n\n @if (conditionsArray.length) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasConditions' | translate\n }}</cds-tag>\n }\n @if (hasContext) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasContext' | translate\n }}</cds-tag>\n }\n </div>\n }\n\n @if (selectedActions.length) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.actions' | translate\n }}</span>\n\n @for (action of selectedActions; track action) {\n <cds-tag size=\"sm\" [type]=\"action | actionTagType\">{{\n action | actionLabel\n }}</cds-tag>\n }\n </div>\n }\n </div>\n\n <!-- Editor-level note: applies to the role selected on this page, and only system-supported\n options can be selected. -->\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {\n $implicit: resourceShortName\n ? ('accessControl.editor.permissionsHint'\n | translate: {resource: resourceShortName, role: roleKey})\n : ('accessControl.editor.permissionsHintNew' | translate: {role: roleKey}),\n }\n \"\n ></ng-container>\n </div>\n\n <cds-accordion class=\"permission-form__accordion\">\n <cds-accordion-item\n [attr.data-test-id]=\"testIds.sectionResourceActions\"\n [expanded]=\"$openSection() === 'resourceActions'\"\n [title]=\"'accessControl.editor.resourceAndActions' | translate\"\n (selected)=\"onSectionToggle('resourceActions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.resourceActionsHint' | translate}\n \"\n ></ng-container>\n\n <div class=\"permission-form__row\">\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"resourceType\"\n [cdsLayer]=\"1\"\n [dataTestId]=\"testIds.resourceTypeSelect\"\n [defaultSelectionId]=\"resourceTypeValue\"\n [dropUp]=\"false\"\n [invalid]=\"group.get('resourceType')!.invalid && group.get('resourceType')!.touched\"\n [items]=\"resourceTypeItems\"\n [placeholder]=\"'accessControl.editor.resourceTypePlaceholder' | translate\"\n [required]=\"true\"\n [tooltip]=\"'accessControl.editor.tooltips.resourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.resourceType\"\n ></v-select>\n\n <div class=\"permission-form__actions-field\">\n <label class=\"cds--label label-with-tooltip\">\n {{ 'accessControl.editor.actions' | translate }} ({{\n 'interface.required' | translate\n }})\n <v-tooltip-icon\n [tooltip]=\"'accessControl.editor.tooltips.actions' | translate\"\n ></v-tooltip-icon>\n </label>\n\n @if (actionItems.length) {\n <div\n class=\"permission-form__actions-grid\"\n [attr.data-test-id]=\"testIds.actionsSelect\"\n [class.permission-form__actions-grid--invalid]=\"\n actionsControl.invalid && actionsControl.touched\n \"\n >\n @for (item of actionItems; track item.id) {\n <div class=\"permission-form__action\">\n <cds-checkbox\n [checked]=\"selectedActions.includes(item.id)\"\n [disabled]=\"disabled\"\n (checkedChange)=\"onActionToggle(item.id, $event)\"\n >\n {{ item.id | actionLabel }}\n </cds-checkbox>\n\n @if (item.id | actionDescription; as description) {\n <v-tooltip-icon [tooltip]=\"description\"></v-tooltip-icon>\n }\n </div>\n }\n </div>\n } @else {\n <p class=\"permission-form__hint\">\n {{ 'accessControl.editor.noActions' | translate }}\n </p>\n }\n </div>\n </div>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [attr.data-test-id]=\"testIds.sectionConditions\"\n [class.permission-form__section-configured]=\"conditionsArray.length > 0\"\n [expanded]=\"$openSection() === 'conditions'\"\n [title]=\"'accessControl.editor.conditions' | translate\"\n (selected)=\"onSectionToggle('conditions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.conditionsHint' | translate}\n \"\n ></ng-container>\n\n <valtimo-condition-tree\n [conditions]=\"conditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"resourceTypeValue\"\n ></valtimo-condition-tree>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [attr.data-test-id]=\"testIds.sectionContext\"\n [class.permission-form__section-configured]=\"hasContext\"\n [expanded]=\"$openSection() === 'context'\"\n [title]=\"'accessControl.editor.contextSection' | translate\"\n (selected)=\"onSectionToggle('context', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.contextHint' | translate}\n \"\n ></ng-container>\n\n <cds-content-switcher\n class=\"permission-form__context-switcher\"\n [attr.data-test-id]=\"testIds.contextToggle\"\n [class.permission-form__context-switcher--disabled]=\"disabled\"\n size=\"sm\"\n >\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'none'\"\n (selected)=\"onContextModeChange('none')\"\n >\n {{ 'accessControl.editor.contextModeNone' | translate }}\n </button>\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'noContext'\"\n (selected)=\"onContextModeChange('noContext')\"\n >\n {{ 'accessControl.editor.contextModeNoContext' | translate }}\n </button>\n @if (hasContextTargets) {\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'specific'\"\n (selected)=\"onContextModeChange('specific')\"\n >\n {{ 'accessControl.editor.contextModeSpecific' | translate }}\n </button>\n }\n </cds-content-switcher>\n\n @switch (contextMode) {\n @case ('noContext') {\n <cds-inline-notification\n class=\"permission-form__notification\"\n [notificationObj]=\"{\n type: 'info',\n message: 'accessControl.editor.noContextHint' | translate,\n lowContrast: true,\n showClose: false,\n }\"\n ></cds-inline-notification>\n }\n @case ('specific') {\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"contextResourceType\"\n [cdsLayer]=\"1\"\n [clearable]=\"false\"\n [dataTestId]=\"testIds.contextResourceTypeSelect\"\n [defaultSelectionId]=\"contextResourceTypeValue || ''\"\n [dropUp]=\"false\"\n [items]=\"contextResourceTypeItems\"\n [placeholder]=\"'accessControl.editor.contextResourceTypePlaceholder' | translate\"\n [tooltip]=\"'accessControl.editor.tooltips.contextResourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.contextResourceType\"\n ></v-select>\n\n <valtimo-condition-tree\n [conditions]=\"contextConditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"contextResourceTypeValue\"\n ></valtimo-condition-tree>\n }\n }\n </div>\n </cds-accordion-item>\n </cds-accordion>\n\n <div class=\"permission-form__footer\">\n <button\n cdsButton=\"danger--ghost\"\n size=\"sm\"\n [attr.data-test-id]=\"testIds.removePermissionButton\"\n [disabled]=\"disabled\"\n (click)=\"openRemoveModal()\"\n >\n {{ 'accessControl.editor.removePermission' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"accessControl.editor.removePermission\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"accessControl.editor.removePermissionModal.content\"\n titleTranslationKey=\"accessControl.editor.removePermissionModal.title\"\n [showModalSubject$]=\"showRemoveModal$\"\n (confirmEvent)=\"onRemove()\"\n ></valtimo-confirmation-modal>\n\n <!-- Lightweight inline hint: a blue information icon with italic secondary text. The message is\n passed in via context so the icon and styling are defined in a single place. -->\n <ng-template #infoNote let-message>\n <p class=\"permission-form__info-note\">\n <svg class=\"permission-form__info-icon\" cdsIcon=\"information\" size=\"16\"></svg>\n\n <span>{{ message }}</span>\n </p>\n </ng-template>\n</div>\n", styles: [".permission-form{display:flex;flex-direction:column}.permission-form v-select{display:block;width:100%}.permission-form__loading{align-items:center;display:flex;justify-content:center;padding:1.5rem 0}.permission-form__body{display:flex;flex-direction:column;gap:1rem}.permission-form__body--hidden{display:none}.permission-form__accordion{width:100%}.permission-form__header{border-bottom:1px solid var(--cds-border-subtle, #e0e0e0);display:flex;flex-direction:column;gap:1rem;padding-bottom:1.5rem}.permission-form__preview{display:flex;flex-direction:column;gap:.5rem}.permission-form__preview-heading{display:flex;flex-direction:column;gap:.125rem}.permission-form__preview-title{font-size:1.25rem;font-weight:400;line-height:1.4;margin:0;overflow-wrap:anywhere}.permission-form__preview-subtitle{color:var(--cds-text-secondary, #525252);font-size:.75rem;font-weight:400;line-height:1.34;overflow-wrap:anywhere}.permission-form__preview-row{align-items:center;display:flex;flex-wrap:wrap;gap:.25rem}.permission-form__preview-row ::ng-deep .cds--tag{margin:0;max-width:none}.permission-form__preview-label{color:var(--cds-text-secondary, #525252);font-size:.875rem;font-weight:600;padding-right:.5rem}.permission-form__row{display:flex;flex-direction:column;gap:1rem}.permission-form__context-switcher{display:block;width:100%}.permission-form__context-switcher--disabled{opacity:.5;pointer-events:none}.permission-form__actions-field{display:flex;flex-direction:column;gap:.5rem}.permission-form__actions-grid{display:grid;gap:.25rem 1rem;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr))}.permission-form__actions-grid--invalid{border-left:2px solid var(--cds-support-error, #da1e28);margin-left:-.75rem;padding-left:calc(.75rem - 2px)}.permission-form__action{align-items:center;display:flex;gap:.25rem}.permission-form .label-with-tooltip{align-items:center;display:inline-flex;gap:.25rem}.permission-form__section{display:flex;flex-direction:column;gap:.75rem}.permission-form__hint{color:var(--cds-text-secondary, #525252);font-size:.875rem;margin:0}.permission-form__info-note{align-items:flex-start;color:var(--cds-text-secondary, #525252);display:flex;font-size:.875rem;gap:.375rem;line-height:1.34;margin-bottom:8px}.permission-form__info-icon{color:var(--cds-support-info, #0043ce);flex-shrink:0;margin-top:.0625rem}.permission-form__footer{display:flex;justify-content:flex-end;padding-top:.25rem}:host ::ng-deep .permission-form__accordion .cds--accordion__item:first-of-type{border-top:0}:host ::ng-deep .permission-form__accordion .cds--accordion__content{padding:1rem 1rem 1.5rem}:host ::ng-deep .permission-form__accordion .permission-form__section-configured .cds--accordion__title:after{background:var(--cds-support-info, #0043ce);border-radius:50%;content:\"\";display:inline-block;height:.5rem;margin-left:.5rem;vertical-align:middle;width:.5rem}:host ::ng-deep .permission-form__notification.cds--inline-notification{inline-size:100%;margin-block-end:0;max-inline-size:100%;min-inline-size: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"], dependencies: [{ kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: i3$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: i2$1.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "component", type: i2$1.Notification, selector: "cds-notification, cds-inline-notification, ibm-notification, ibm-inline-notification", inputs: ["notificationObj"] }, { kind: "component", type: i3$1.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "component", type: i3$1.TooltipIconComponent, selector: "v-tooltip-icon", inputs: ["tooltip", "disabled"] }, { kind: "component", type: i2$1.ContentSwitcher, selector: "cds-content-switcher, ibm-content-switcher", inputs: ["ariaLabel", "size"], outputs: ["selected"] }, { kind: "directive", type: i2$1.ContentSwitcherOption, selector: "[cdsContentOption], [ibmContentOption]", inputs: ["active", "name"], outputs: ["selected", "onClick", "onFocus"] }, { kind: "component", type: i2$1.Accordion, selector: "cds-accordion, ibm-accordion", inputs: ["align", "size", "skeleton"] }, { kind: "component", type: i2$1.AccordionItem, selector: "cds-accordion-item, ibm-accordion-item", inputs: ["title", "context", "id", "skeleton", "expanded", "disabled"], outputs: ["selected"] }, { kind: "component", type: i2$1.Checkbox, selector: "cds-checkbox, ibm-checkbox", inputs: ["disabled", "skeleton", "hideLabel", "name", "id", "required", "value", "ariaLabel", "ariaLabelledby", "indeterminate", "checked"], outputs: ["click", "checkedChange", "indeterminateChange"] }, { kind: "directive", type: i2$1.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "component", type: i2$1.Tag, selector: "cds-tag, ibm-tag", inputs: ["type", "size", "class", "skeleton"] }, { kind: "component", type: ConditionTreeComponent, selector: "valtimo-condition-tree", inputs: ["conditions", "resourceType", "disabled", "depth"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }, { kind: "pipe", type: ActionLabelPipe, name: "actionLabel" }, { kind: "pipe", type: ActionDescriptionPipe, name: "actionDescription" }, { kind: "pipe", type: ActionTagTypePipe, name: "actionTagType" }] }); }
1736
1778
  }
1737
1779
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PermissionFormComponent, decorators: [{
1738
1780
  type: Component,
1739
- args: [{ standalone: false, selector: 'valtimo-permission-form', 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=\"permission-form\"\n [attr.data-test-id]=\"testIds.permissionCard\"\n [cdsLayer]=\"0\"\n [formGroup]=\"group\"\n>\n @if ($loading()) {\n <div class=\"permission-form__loading\">\n <cds-loading [isActive]=\"true\" [overlay]=\"false\" size=\"sm\"></cds-loading>\n </div>\n }\n\n <div class=\"permission-form__body\" [class.permission-form__body--hidden]=\"$loading()\">\n <!-- Header block: the permission preview followed by an editor-level note, separated from the\n editable sections below by a subtle divider. -->\n <div class=\"permission-form__header\">\n <!-- A larger preview of the permission (the same information shown in the sidebar list), so\n the rule being edited is recognisable at the top of the panel. The full resource type is\n shown here (the sidebar only shows the short name). -->\n <div class=\"permission-form__preview\">\n <div class=\"permission-form__preview-heading\">\n <h4 class=\"permission-form__preview-title\">\n @if (resourceTypeValue) {\n {{ resourceShortName }}\n } @else {\n {{ 'accessControl.editor.newPermission' | translate }}\n }\n </h4>\n\n @if (resourceTypeValue) {\n <span class=\"permission-form__preview-subtitle\">{{ resourceTypeValue }}</span>\n }\n </div>\n\n @if (conditionsArray.length || hasContext) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.includes' | translate\n }}</span>\n\n @if (conditionsArray.length) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasConditions' | translate\n }}</cds-tag>\n }\n @if (hasContext) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasContext' | translate\n }}</cds-tag>\n }\n </div>\n }\n\n @if (selectedActions.length) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.actions' | translate\n }}</span>\n\n @for (action of selectedActions; track action) {\n <cds-tag size=\"sm\" [type]=\"action | actionTagType\">{{\n action | actionLabel\n }}</cds-tag>\n }\n </div>\n }\n </div>\n\n <!-- Editor-level note: applies to the role selected on this page, and only system-supported\n options can be selected. -->\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {\n $implicit: resourceShortName\n ? ('accessControl.editor.permissionsHint'\n | translate: {resource: resourceShortName, role: roleKey})\n : ('accessControl.editor.permissionsHintNew' | translate: {role: roleKey}),\n }\n \"\n ></ng-container>\n </div>\n\n <cds-accordion class=\"permission-form__accordion\">\n <cds-accordion-item\n [expanded]=\"$openSection() === 'resourceActions'\"\n [title]=\"'accessControl.editor.resourceAndActions' | translate\"\n (selected)=\"onSectionToggle('resourceActions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.resourceActionsHint' | translate}\n \"\n ></ng-container>\n\n <div class=\"permission-form__row\">\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"resourceType\"\n [cdsLayer]=\"1\"\n [dataTestId]=\"testIds.resourceTypeSelect\"\n [defaultSelectionId]=\"resourceTypeValue\"\n [dropUp]=\"false\"\n [invalid]=\"group.get('resourceType')!.invalid && group.get('resourceType')!.touched\"\n [items]=\"resourceTypeItems\"\n [placeholder]=\"'accessControl.editor.resourceTypePlaceholder' | translate\"\n [required]=\"true\"\n [tooltip]=\"'accessControl.editor.tooltips.resourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.resourceType\"\n ></v-select>\n\n <div class=\"permission-form__actions-field\">\n <label class=\"cds--label label-with-tooltip\">\n {{ 'accessControl.editor.actions' | translate }} ({{\n 'interface.required' | translate\n }})\n <v-tooltip-icon\n [tooltip]=\"'accessControl.editor.tooltips.actions' | translate\"\n ></v-tooltip-icon>\n </label>\n\n @if (actionItems.length) {\n <div\n class=\"permission-form__actions-grid\"\n [attr.data-test-id]=\"testIds.actionsSelect\"\n [class.permission-form__actions-grid--invalid]=\"\n actionsControl.invalid && actionsControl.touched\n \"\n >\n @for (item of actionItems; track item.id) {\n <div class=\"permission-form__action\">\n <cds-checkbox\n [checked]=\"selectedActions.includes(item.id)\"\n [disabled]=\"disabled\"\n (checkedChange)=\"onActionToggle(item.id, $event)\"\n >\n {{ item.id | actionLabel }}\n </cds-checkbox>\n\n @if (item.id | actionDescription; as description) {\n <v-tooltip-icon [tooltip]=\"description\"></v-tooltip-icon>\n }\n </div>\n }\n </div>\n } @else {\n <p class=\"permission-form__hint\">\n {{ 'accessControl.editor.noActions' | translate }}\n </p>\n }\n </div>\n </div>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [class.permission-form__section-configured]=\"conditionsArray.length > 0\"\n [expanded]=\"$openSection() === 'conditions'\"\n [title]=\"'accessControl.editor.conditions' | translate\"\n (selected)=\"onSectionToggle('conditions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.conditionsHint' | translate}\n \"\n ></ng-container>\n\n <valtimo-condition-tree\n [conditions]=\"conditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"resourceTypeValue\"\n ></valtimo-condition-tree>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [class.permission-form__section-configured]=\"hasContext\"\n [expanded]=\"$openSection() === 'context'\"\n [title]=\"'accessControl.editor.contextSection' | translate\"\n (selected)=\"onSectionToggle('context', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.contextHint' | translate}\n \"\n ></ng-container>\n\n <cds-content-switcher\n class=\"permission-form__context-switcher\"\n [attr.data-test-id]=\"testIds.contextToggle\"\n [class.permission-form__context-switcher--disabled]=\"disabled\"\n size=\"sm\"\n >\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'none'\"\n (selected)=\"onContextModeChange('none')\"\n >\n {{ 'accessControl.editor.contextModeNone' | translate }}\n </button>\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'noContext'\"\n (selected)=\"onContextModeChange('noContext')\"\n >\n {{ 'accessControl.editor.contextModeNoContext' | translate }}\n </button>\n @if (hasContextTargets) {\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'specific'\"\n (selected)=\"onContextModeChange('specific')\"\n >\n {{ 'accessControl.editor.contextModeSpecific' | translate }}\n </button>\n }\n </cds-content-switcher>\n\n @switch (contextMode) {\n @case ('noContext') {\n <cds-inline-notification\n class=\"permission-form__notification\"\n [notificationObj]=\"{\n type: 'info',\n message: 'accessControl.editor.noContextHint' | translate,\n lowContrast: true,\n showClose: false,\n }\"\n ></cds-inline-notification>\n }\n @case ('specific') {\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"contextResourceType\"\n [cdsLayer]=\"1\"\n [clearable]=\"false\"\n [dataTestId]=\"testIds.contextResourceTypeSelect\"\n [defaultSelectionId]=\"contextResourceTypeValue || ''\"\n [dropUp]=\"false\"\n [items]=\"contextResourceTypeItems\"\n [placeholder]=\"'accessControl.editor.contextResourceTypePlaceholder' | translate\"\n [tooltip]=\"'accessControl.editor.tooltips.contextResourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.contextResourceType\"\n ></v-select>\n\n <valtimo-condition-tree\n [conditions]=\"contextConditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"contextResourceTypeValue\"\n ></valtimo-condition-tree>\n }\n }\n </div>\n </cds-accordion-item>\n </cds-accordion>\n\n <div class=\"permission-form__footer\">\n <button\n cdsButton=\"danger--ghost\"\n size=\"sm\"\n [attr.data-test-id]=\"testIds.removePermissionButton\"\n [disabled]=\"disabled\"\n (click)=\"openRemoveModal()\"\n >\n {{ 'accessControl.editor.removePermission' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"accessControl.editor.removePermission\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"accessControl.editor.removePermissionModal.content\"\n titleTranslationKey=\"accessControl.editor.removePermissionModal.title\"\n [showModalSubject$]=\"showRemoveModal$\"\n (confirmEvent)=\"onRemove()\"\n ></valtimo-confirmation-modal>\n\n <!-- Lightweight inline hint: a blue information icon with italic secondary text. The message is\n passed in via context so the icon and styling are defined in a single place. -->\n <ng-template #infoNote let-message>\n <p class=\"permission-form__info-note\">\n <svg class=\"permission-form__info-icon\" cdsIcon=\"information\" size=\"16\"></svg>\n\n <span>{{ message }}</span>\n </p>\n </ng-template>\n</div>\n", styles: [".permission-form{display:flex;flex-direction:column}.permission-form v-select{display:block;width:100%}.permission-form__loading{align-items:center;display:flex;justify-content:center;padding:1.5rem 0}.permission-form__body{display:flex;flex-direction:column;gap:1rem}.permission-form__body--hidden{display:none}.permission-form__accordion{width:100%}.permission-form__header{border-bottom:1px solid var(--cds-border-subtle, #e0e0e0);display:flex;flex-direction:column;gap:1rem;padding-bottom:1.5rem}.permission-form__preview{display:flex;flex-direction:column;gap:.5rem}.permission-form__preview-heading{display:flex;flex-direction:column;gap:.125rem}.permission-form__preview-title{font-size:1.25rem;font-weight:400;line-height:1.4;margin:0;overflow-wrap:anywhere}.permission-form__preview-subtitle{color:var(--cds-text-secondary, #525252);font-size:.75rem;font-weight:400;line-height:1.34;overflow-wrap:anywhere}.permission-form__preview-row{align-items:center;display:flex;flex-wrap:wrap;gap:.25rem}.permission-form__preview-row ::ng-deep .cds--tag{margin:0;max-width:none}.permission-form__preview-label{color:var(--cds-text-secondary, #525252);font-size:.875rem;font-weight:600;padding-right:.5rem}.permission-form__row{display:flex;flex-direction:column;gap:1rem}.permission-form__context-switcher{display:block;width:100%}.permission-form__context-switcher--disabled{opacity:.5;pointer-events:none}.permission-form__actions-field{display:flex;flex-direction:column;gap:.5rem}.permission-form__actions-grid{display:grid;gap:.25rem 1rem;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr))}.permission-form__actions-grid--invalid{border-left:2px solid var(--cds-support-error, #da1e28);margin-left:-.75rem;padding-left:calc(.75rem - 2px)}.permission-form__action{align-items:center;display:flex;gap:.25rem}.permission-form .label-with-tooltip{align-items:center;display:inline-flex;gap:.25rem}.permission-form__section{display:flex;flex-direction:column;gap:.75rem}.permission-form__hint{color:var(--cds-text-secondary, #525252);font-size:.875rem;margin:0}.permission-form__info-note{align-items:flex-start;color:var(--cds-text-secondary, #525252);display:flex;font-size:.875rem;gap:.375rem;line-height:1.34;margin-bottom:8px}.permission-form__info-icon{color:var(--cds-support-info, #0043ce);flex-shrink:0;margin-top:.0625rem}.permission-form__footer{display:flex;justify-content:flex-end;padding-top:.25rem}:host ::ng-deep .permission-form__accordion .cds--accordion__item:first-of-type{border-top:0}:host ::ng-deep .permission-form__accordion .cds--accordion__content{padding:1rem 1rem 1.5rem}:host ::ng-deep .permission-form__accordion .permission-form__section-configured .cds--accordion__title:after{background:var(--cds-support-info, #0043ce);border-radius:50%;content:\"\";display:inline-block;height:.5rem;margin-left:.5rem;vertical-align:middle;width:.5rem}:host ::ng-deep .permission-form__notification.cds--inline-notification{inline-size:100%;margin-block-end:0;max-inline-size:100%;min-inline-size: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"] }]
1781
+ args: [{ standalone: false, selector: 'valtimo-permission-form', 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=\"permission-form\"\n [attr.data-test-id]=\"testIds.permissionCard\"\n [cdsLayer]=\"0\"\n [formGroup]=\"group\"\n>\n @if ($loading()) {\n <div class=\"permission-form__loading\">\n <cds-loading [isActive]=\"true\" [overlay]=\"false\" size=\"sm\"></cds-loading>\n </div>\n }\n\n <div class=\"permission-form__body\" [class.permission-form__body--hidden]=\"$loading()\">\n <!-- Header block: the permission preview followed by an editor-level note, separated from the\n editable sections below by a subtle divider. -->\n <div class=\"permission-form__header\">\n <!-- A larger preview of the permission (the same information shown in the sidebar list), so\n the rule being edited is recognisable at the top of the panel. The full resource type is\n shown here (the sidebar only shows the short name). -->\n <div class=\"permission-form__preview\">\n <div class=\"permission-form__preview-heading\">\n <h4 class=\"permission-form__preview-title\">\n @if (resourceTypeValue) {\n {{ resourceShortName }}\n } @else {\n {{ 'accessControl.editor.newPermission' | translate }}\n }\n </h4>\n\n @if (resourceTypeValue) {\n <span class=\"permission-form__preview-subtitle\">{{ resourceTypeValue }}</span>\n }\n </div>\n\n @if (conditionsArray.length || hasContext) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.includes' | translate\n }}</span>\n\n @if (conditionsArray.length) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasConditions' | translate\n }}</cds-tag>\n }\n @if (hasContext) {\n <cds-tag size=\"sm\" type=\"high-contrast\">{{\n 'accessControl.editor.hasContext' | translate\n }}</cds-tag>\n }\n </div>\n }\n\n @if (selectedActions.length) {\n <div class=\"permission-form__preview-row\">\n <span class=\"permission-form__preview-label\">{{\n 'accessControl.editor.preview.actions' | translate\n }}</span>\n\n @for (action of selectedActions; track action) {\n <cds-tag size=\"sm\" [type]=\"action | actionTagType\">{{\n action | actionLabel\n }}</cds-tag>\n }\n </div>\n }\n </div>\n\n <!-- Editor-level note: applies to the role selected on this page, and only system-supported\n options can be selected. -->\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {\n $implicit: resourceShortName\n ? ('accessControl.editor.permissionsHint'\n | translate: {resource: resourceShortName, role: roleKey})\n : ('accessControl.editor.permissionsHintNew' | translate: {role: roleKey}),\n }\n \"\n ></ng-container>\n </div>\n\n <cds-accordion class=\"permission-form__accordion\">\n <cds-accordion-item\n [attr.data-test-id]=\"testIds.sectionResourceActions\"\n [expanded]=\"$openSection() === 'resourceActions'\"\n [title]=\"'accessControl.editor.resourceAndActions' | translate\"\n (selected)=\"onSectionToggle('resourceActions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.resourceActionsHint' | translate}\n \"\n ></ng-container>\n\n <div class=\"permission-form__row\">\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"resourceType\"\n [cdsLayer]=\"1\"\n [dataTestId]=\"testIds.resourceTypeSelect\"\n [defaultSelectionId]=\"resourceTypeValue\"\n [dropUp]=\"false\"\n [invalid]=\"group.get('resourceType')!.invalid && group.get('resourceType')!.touched\"\n [items]=\"resourceTypeItems\"\n [placeholder]=\"'accessControl.editor.resourceTypePlaceholder' | translate\"\n [required]=\"true\"\n [tooltip]=\"'accessControl.editor.tooltips.resourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.resourceType\"\n ></v-select>\n\n <div class=\"permission-form__actions-field\">\n <label class=\"cds--label label-with-tooltip\">\n {{ 'accessControl.editor.actions' | translate }} ({{\n 'interface.required' | translate\n }})\n <v-tooltip-icon\n [tooltip]=\"'accessControl.editor.tooltips.actions' | translate\"\n ></v-tooltip-icon>\n </label>\n\n @if (actionItems.length) {\n <div\n class=\"permission-form__actions-grid\"\n [attr.data-test-id]=\"testIds.actionsSelect\"\n [class.permission-form__actions-grid--invalid]=\"\n actionsControl.invalid && actionsControl.touched\n \"\n >\n @for (item of actionItems; track item.id) {\n <div class=\"permission-form__action\">\n <cds-checkbox\n [checked]=\"selectedActions.includes(item.id)\"\n [disabled]=\"disabled\"\n (checkedChange)=\"onActionToggle(item.id, $event)\"\n >\n {{ item.id | actionLabel }}\n </cds-checkbox>\n\n @if (item.id | actionDescription; as description) {\n <v-tooltip-icon [tooltip]=\"description\"></v-tooltip-icon>\n }\n </div>\n }\n </div>\n } @else {\n <p class=\"permission-form__hint\">\n {{ 'accessControl.editor.noActions' | translate }}\n </p>\n }\n </div>\n </div>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [attr.data-test-id]=\"testIds.sectionConditions\"\n [class.permission-form__section-configured]=\"conditionsArray.length > 0\"\n [expanded]=\"$openSection() === 'conditions'\"\n [title]=\"'accessControl.editor.conditions' | translate\"\n (selected)=\"onSectionToggle('conditions', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.conditionsHint' | translate}\n \"\n ></ng-container>\n\n <valtimo-condition-tree\n [conditions]=\"conditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"resourceTypeValue\"\n ></valtimo-condition-tree>\n </div>\n </cds-accordion-item>\n\n <cds-accordion-item\n [attr.data-test-id]=\"testIds.sectionContext\"\n [class.permission-form__section-configured]=\"hasContext\"\n [expanded]=\"$openSection() === 'context'\"\n [title]=\"'accessControl.editor.contextSection' | translate\"\n (selected)=\"onSectionToggle('context', $event)\"\n >\n <div class=\"permission-form__section\">\n <ng-container\n *ngTemplateOutlet=\"\n infoNote;\n context: {$implicit: 'accessControl.editor.contextHint' | translate}\n \"\n ></ng-container>\n\n <cds-content-switcher\n class=\"permission-form__context-switcher\"\n [attr.data-test-id]=\"testIds.contextToggle\"\n [class.permission-form__context-switcher--disabled]=\"disabled\"\n size=\"sm\"\n >\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'none'\"\n (selected)=\"onContextModeChange('none')\"\n >\n {{ 'accessControl.editor.contextModeNone' | translate }}\n </button>\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'noContext'\"\n (selected)=\"onContextModeChange('noContext')\"\n >\n {{ 'accessControl.editor.contextModeNoContext' | translate }}\n </button>\n @if (hasContextTargets) {\n <button\n cdsContentOption\n type=\"button\"\n [active]=\"contextMode === 'specific'\"\n (selected)=\"onContextModeChange('specific')\"\n >\n {{ 'accessControl.editor.contextModeSpecific' | translate }}\n </button>\n }\n </cds-content-switcher>\n\n @switch (contextMode) {\n @case ('noContext') {\n <cds-inline-notification\n class=\"permission-form__notification\"\n [notificationObj]=\"{\n type: 'info',\n message: 'accessControl.editor.noContextHint' | translate,\n lowContrast: true,\n showClose: false,\n }\"\n ></cds-inline-notification>\n }\n @case ('specific') {\n <v-select\n class=\"permission-form__resource-type\"\n formControlName=\"contextResourceType\"\n [cdsLayer]=\"1\"\n [clearable]=\"false\"\n [dataTestId]=\"testIds.contextResourceTypeSelect\"\n [defaultSelectionId]=\"contextResourceTypeValue || ''\"\n [dropUp]=\"false\"\n [items]=\"contextResourceTypeItems\"\n [placeholder]=\"'accessControl.editor.contextResourceTypePlaceholder' | translate\"\n [tooltip]=\"'accessControl.editor.tooltips.contextResourceType' | translate\"\n titleTranslationKey=\"accessControl.editor.contextResourceType\"\n ></v-select>\n\n <valtimo-condition-tree\n [conditions]=\"contextConditionsArray\"\n [disabled]=\"disabled\"\n [resourceType]=\"contextResourceTypeValue\"\n ></valtimo-condition-tree>\n }\n }\n </div>\n </cds-accordion-item>\n </cds-accordion>\n\n <div class=\"permission-form__footer\">\n <button\n cdsButton=\"danger--ghost\"\n size=\"sm\"\n [attr.data-test-id]=\"testIds.removePermissionButton\"\n [disabled]=\"disabled\"\n (click)=\"openRemoveModal()\"\n >\n {{ 'accessControl.editor.removePermission' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"trash-can\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"accessControl.editor.removePermission\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"accessControl.editor.removePermissionModal.content\"\n titleTranslationKey=\"accessControl.editor.removePermissionModal.title\"\n [showModalSubject$]=\"showRemoveModal$\"\n (confirmEvent)=\"onRemove()\"\n ></valtimo-confirmation-modal>\n\n <!-- Lightweight inline hint: a blue information icon with italic secondary text. The message is\n passed in via context so the icon and styling are defined in a single place. -->\n <ng-template #infoNote let-message>\n <p class=\"permission-form__info-note\">\n <svg class=\"permission-form__info-icon\" cdsIcon=\"information\" size=\"16\"></svg>\n\n <span>{{ message }}</span>\n </p>\n </ng-template>\n</div>\n", styles: [".permission-form{display:flex;flex-direction:column}.permission-form v-select{display:block;width:100%}.permission-form__loading{align-items:center;display:flex;justify-content:center;padding:1.5rem 0}.permission-form__body{display:flex;flex-direction:column;gap:1rem}.permission-form__body--hidden{display:none}.permission-form__accordion{width:100%}.permission-form__header{border-bottom:1px solid var(--cds-border-subtle, #e0e0e0);display:flex;flex-direction:column;gap:1rem;padding-bottom:1.5rem}.permission-form__preview{display:flex;flex-direction:column;gap:.5rem}.permission-form__preview-heading{display:flex;flex-direction:column;gap:.125rem}.permission-form__preview-title{font-size:1.25rem;font-weight:400;line-height:1.4;margin:0;overflow-wrap:anywhere}.permission-form__preview-subtitle{color:var(--cds-text-secondary, #525252);font-size:.75rem;font-weight:400;line-height:1.34;overflow-wrap:anywhere}.permission-form__preview-row{align-items:center;display:flex;flex-wrap:wrap;gap:.25rem}.permission-form__preview-row ::ng-deep .cds--tag{margin:0;max-width:none}.permission-form__preview-label{color:var(--cds-text-secondary, #525252);font-size:.875rem;font-weight:600;padding-right:.5rem}.permission-form__row{display:flex;flex-direction:column;gap:1rem}.permission-form__context-switcher{display:block;width:100%}.permission-form__context-switcher--disabled{opacity:.5;pointer-events:none}.permission-form__actions-field{display:flex;flex-direction:column;gap:.5rem}.permission-form__actions-grid{display:grid;gap:.25rem 1rem;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr))}.permission-form__actions-grid--invalid{border-left:2px solid var(--cds-support-error, #da1e28);margin-left:-.75rem;padding-left:calc(.75rem - 2px)}.permission-form__action{align-items:center;display:flex;gap:.25rem}.permission-form .label-with-tooltip{align-items:center;display:inline-flex;gap:.25rem}.permission-form__section{display:flex;flex-direction:column;gap:.75rem}.permission-form__hint{color:var(--cds-text-secondary, #525252);font-size:.875rem;margin:0}.permission-form__info-note{align-items:flex-start;color:var(--cds-text-secondary, #525252);display:flex;font-size:.875rem;gap:.375rem;line-height:1.34;margin-bottom:8px}.permission-form__info-icon{color:var(--cds-support-info, #0043ce);flex-shrink:0;margin-top:.0625rem}.permission-form__footer{display:flex;justify-content:flex-end;padding-top:.25rem}:host ::ng-deep .permission-form__accordion .cds--accordion__item:first-of-type{border-top:0}:host ::ng-deep .permission-form__accordion .cds--accordion__content{padding:1rem 1rem 1.5rem}:host ::ng-deep .permission-form__accordion .permission-form__section-configured .cds--accordion__title:after{background:var(--cds-support-info, #0043ce);border-radius:50%;content:\"\";display:inline-block;height:.5rem;margin-left:.5rem;vertical-align:middle;width:.5rem}:host ::ng-deep .permission-form__notification.cds--inline-notification{inline-size:100%;margin-block-end:0;max-inline-size:100%;min-inline-size: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"] }]
1740
1782
  }], ctorParameters: () => [{ type: AccessControlFormEditorService }, { type: i2$1.IconService }, { type: i0.ChangeDetectorRef }], propDecorators: { group: [{
1741
1783
  type: Input
1742
1784
  }], index: [{
@@ -2372,6 +2414,7 @@ class AccessControlEditorComponent extends PendingChangesComponent {
2372
2414
  this.moreDisabled$ = new BehaviorSubject(true);
2373
2415
  this.showDeleteModal$ = new BehaviorSubject(false);
2374
2416
  this.showEditModal$ = new BehaviorSubject(false);
2417
+ this.testIds = ACCESS_CONTROL_ROLES_TEST_IDS;
2375
2418
  this.selectedRowKeys$ = new BehaviorSubject(null);
2376
2419
  this.compactMode$ = this.pageHeaderService.compactMode$;
2377
2420
  this.$activeTab = signal(AccessControlEditorTab.EDITOR);
@@ -2583,11 +2626,11 @@ class AccessControlEditorComponent extends PendingChangesComponent {
2583
2626
  });
2584
2627
  }
2585
2628
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AccessControlEditorComponent, deps: [{ token: AccessControlService }, { token: i1$3.ActivatedRoute }, { token: i3$1.PageTitleService }, { token: i1$3.Router }, { token: i1$1.GlobalNotificationService }, { token: i1$2.TranslateService }, { token: AccessControlExportService }, { token: i3$1.PageHeaderService }], target: i0.ɵɵFactoryTarget.Component }); }
2586
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AccessControlEditorComponent, isStandalone: false, selector: "ng-component", viewQueries: [{ propertyName: "_formEditorTab", first: true, predicate: AccessControlFormEditorTabComponent, descendants: true }, { propertyName: "_tabs", predicate: Tab, descendants: true }], usesInheritance: true, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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<ng-container *ngIf=\"model$ | async as model; else loading\">\n <!-- The headers only switch the active tab; the tab content is rendered below (gated by the\n active-tab signal) instead of inside the Carbon tab panes. Carbon removes a pane's content\n as soon as another header is clicked, which would destroy the editor's unsaved form before\n the leave-page confirmation is resolved. -->\n <cds-tabs type=\"contained\">\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.EDITOR\"\n [heading]=\"'accessControl.roles.tabs.editor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.EDITOR)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.SUMMARY\"\n [heading]=\"'accessControl.roles.tabs.summary' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.SUMMARY)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.JSON_EDITOR\"\n [heading]=\"'accessControl.roles.tabs.jsonEditor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.JSON_EDITOR)\"\n ></cds-tab>\n </cds-tabs>\n\n <!-- White surface for the tab content. The Carbon tab pane used to provide this; since the\n content is now rendered outside the panes, the wrapper supplies the layer background. -->\n <div class=\"access-control-editor__content\">\n @if ($activeTab() === AccessControlEditorTab.EDITOR) {\n <valtimo-access-control-form-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n [roleKey]=\"roleKey$ | async\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-form-editor-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.SUMMARY) {\n <valtimo-access-control-overview-tab\n [permissions]=\"permissions$ | async\"\n [roleKey]=\"roleKey$ | async\"\n ></valtimo-access-control-overview-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.JSON_EDITOR) {\n <valtimo-access-control-json-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-json-editor-tab>\n }\n </div>\n</ng-container>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n model: model$ | async,\n moreDisabled: moreDisabled$ | async,\n compactMode: compactMode$ | async,\n } as obs\"\n class=\"buttons-container\"\n >\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option [disabled]=\"obs.moreDisabled\" (selected)=\"showEditModal()\">{{\n 'accessControl.roles.editMetadata' | translate\n }}</v-overflow-menu-option>\n\n <v-overflow-menu-option [disabled]=\"obs.moreDisabled\" (selected)=\"exportPermissions()\">{{\n 'interface.export' | translate\n }}</v-overflow-menu-option>\n\n <v-overflow-menu-option\n [disabled]=\"obs.moreDisabled\"\n type=\"danger\"\n (selected)=\"showDeleteModal()\"\n >{{ 'interface.delete' | translate }}</v-overflow-menu-option\n >\n </v-overflow-menu>\n\n <button\n [disabled]=\"saveDisabled$ | async\"\n cdsButton=\"primary\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"updatePermissions()\"\n >\n {{ 'interface.save' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"save\" size=\"16\"></svg>\n </button>\n </div>\n </ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-role-metadata-modal\n [defaultKeyValue]=\"obs.selectedRowKeys[0]\"\n [open]=\"showEditModal$ | async\"\n type=\"edit\"\n (closeEvent)=\"onEdit(obs.selectedRowKeys[0], $event)\"\n ></valtimo-role-metadata-modal>\n</ng-container>\n\n<ng-template #loading>\n <div class=\"loading-container\">\n <cds-loading></cds-loading>\n </div>\n</ng-template>\n", styles: [".loading-container{display:flex;width:100%;justify-content:center}.overflow-button{margin-right:16px}.buttons-container{display:flex;flex-direction:row;align-items:center}.buttons-container button{height:min-content}:host ::ng-deep .cds--tab-content{background-color:var(--cds-layer);outline:none!important;padding:0}.access-control-editor__content{background-color:var(--cds-layer)}\n/*!\n * Copyright 2015-2025 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: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "directive", type: i3$1.RenderInPageHeaderDirective, selector: "[renderInPageHeader]", inputs: ["fullWidth"] }, { kind: "component", type: i2$1.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "component", type: i3$1.OverflowMenuComponent, selector: "v-overflow-menu", inputs: ["open", "placement", "menuWidth", "offsetX", "offsetY", "closeOnSelect", "useHostAsReference", "portalToBody"], outputs: ["openChange"] }, { kind: "component", type: i3$1.OverflowMenuOptionComponent, selector: "v-overflow-menu-option", inputs: ["disabled", "type", "testId", "optionId"], outputs: ["selected"] }, { kind: "component", type: i3$1.OverflowMenuTriggerComponent, selector: "v-overflow-menu-trigger", inputs: ["compact"] }, { kind: "component", type: i2$1.Tabs, selector: "cds-tabs, ibm-tabs", inputs: ["position", "cacheActive", "followFocus", "isNavigation", "ariaLabel", "ariaLabelledby", "type", "theme", "skeleton"] }, { kind: "component", type: i2$1.Tab, selector: "cds-tab, ibm-tab", inputs: ["heading", "title", "context", "active", "disabled", "tabIndex", "id", "cacheActive", "tabContent", "templateContext"], outputs: ["selected"] }, { kind: "component", type: AccessControlJsonEditorTabComponent, selector: "valtimo-access-control-json-editor-tab", inputs: ["disabled", "model"], outputs: ["validEvent", "valueChangeEvent"] }, { kind: "component", type: AccessControlOverviewTabComponent, selector: "valtimo-access-control-overview-tab", inputs: ["roleKey", "permissions"] }, { kind: "component", type: RoleMetadataModalComponent, selector: "valtimo-role-metadata-modal", inputs: ["type", "open", "defaultKeyValue", "usedKeys"], outputs: ["closeEvent"] }, { kind: "component", type: AccessControlFormEditorTabComponent, selector: "valtimo-access-control-form-editor-tab", inputs: ["model", "disabled", "roleKey"], outputs: ["validEvent", "valueChangeEvent"] }, { kind: "component", type: DeleteRoleModalComponent, selector: "valtimo-delete-role-modal", inputs: ["deleteRowKeys", "showDeleteModal$"], outputs: ["deleteEvent"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2629
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AccessControlEditorComponent, isStandalone: false, selector: "ng-component", viewQueries: [{ propertyName: "_formEditorTab", first: true, predicate: AccessControlFormEditorTabComponent, descendants: true }, { propertyName: "_tabs", predicate: Tab, descendants: true }], usesInheritance: true, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 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<ng-container *ngIf=\"model$ | async as model; else loading\">\n <!-- The headers only switch the active tab; the tab content is rendered below (gated by the\n active-tab signal) instead of inside the Carbon tab panes. Carbon removes a pane's content\n as soon as another header is clicked, which would destroy the editor's unsaved form before\n the leave-page confirmation is resolved. -->\n <cds-tabs type=\"contained\">\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.EDITOR\"\n [heading]=\"'accessControl.roles.tabs.editor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.EDITOR)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.SUMMARY\"\n [heading]=\"'accessControl.roles.tabs.summary' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.SUMMARY)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.JSON_EDITOR\"\n [heading]=\"'accessControl.roles.tabs.jsonEditor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.JSON_EDITOR)\"\n ></cds-tab>\n </cds-tabs>\n\n <!-- White surface for the tab content. The Carbon tab pane used to provide this; since the\n content is now rendered outside the panes, the wrapper supplies the layer background. -->\n <div class=\"access-control-editor__content\">\n @if ($activeTab() === AccessControlEditorTab.EDITOR) {\n <valtimo-access-control-form-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n [roleKey]=\"roleKey$ | async\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-form-editor-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.SUMMARY) {\n <valtimo-access-control-overview-tab\n [permissions]=\"permissions$ | async\"\n [roleKey]=\"roleKey$ | async\"\n ></valtimo-access-control-overview-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.JSON_EDITOR) {\n <valtimo-access-control-json-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-json-editor-tab>\n }\n </div>\n</ng-container>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n model: model$ | async,\n moreDisabled: moreDisabled$ | async,\n compactMode: compactMode$ | async,\n } as obs\"\n class=\"buttons-container\"\n >\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option\n [testId]=\"testIds.moreMenuEditMetadata\"\n [disabled]=\"obs.moreDisabled\"\n (selected)=\"showEditModal()\"\n >{{ 'accessControl.roles.editMetadata' | translate }}</v-overflow-menu-option\n >\n\n <v-overflow-menu-option\n [testId]=\"testIds.moreMenuExport\"\n [disabled]=\"obs.moreDisabled\"\n (selected)=\"exportPermissions()\"\n >{{ 'interface.export' | translate }}</v-overflow-menu-option\n >\n\n <v-overflow-menu-option\n [disabled]=\"obs.moreDisabled\"\n type=\"danger\"\n (selected)=\"showDeleteModal()\"\n >{{ 'interface.delete' | translate }}</v-overflow-menu-option\n >\n </v-overflow-menu>\n\n <button\n [disabled]=\"saveDisabled$ | async\"\n cdsButton=\"primary\"\n [attr.data-test-id]=\"testIds.saveButton\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"updatePermissions()\"\n >\n {{ 'interface.save' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"save\" size=\"16\"></svg>\n </button>\n </div>\n </ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-role-metadata-modal\n [defaultKeyValue]=\"obs.selectedRowKeys[0]\"\n [open]=\"showEditModal$ | async\"\n type=\"edit\"\n (closeEvent)=\"onEdit(obs.selectedRowKeys[0], $event)\"\n ></valtimo-role-metadata-modal>\n</ng-container>\n\n<ng-template #loading>\n <div class=\"loading-container\">\n <cds-loading></cds-loading>\n </div>\n</ng-template>\n", styles: [".loading-container{display:flex;width:100%;justify-content:center}.overflow-button{margin-right:16px}.buttons-container{display:flex;flex-direction:row;align-items:center}.buttons-container button{height:min-content}:host ::ng-deep .cds--tab-content{background-color:var(--cds-layer);outline:none!important;padding:0}.access-control-editor__content{background-color:var(--cds-layer)}\n/*!\n * Copyright 2015-2025 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: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i2$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "directive", type: i3$1.RenderInPageHeaderDirective, selector: "[renderInPageHeader]", inputs: ["fullWidth"] }, { kind: "component", type: i2$1.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "component", type: i3$1.OverflowMenuComponent, selector: "v-overflow-menu", inputs: ["open", "placement", "menuWidth", "offsetX", "offsetY", "closeOnSelect", "useHostAsReference", "portalToBody"], outputs: ["openChange"] }, { kind: "component", type: i3$1.OverflowMenuOptionComponent, selector: "v-overflow-menu-option", inputs: ["disabled", "type", "testId", "optionId"], outputs: ["selected"] }, { kind: "component", type: i3$1.OverflowMenuTriggerComponent, selector: "v-overflow-menu-trigger", inputs: ["compact", "label"] }, { kind: "component", type: i2$1.Tabs, selector: "cds-tabs, ibm-tabs", inputs: ["position", "cacheActive", "followFocus", "isNavigation", "ariaLabel", "ariaLabelledby", "type", "theme", "skeleton"] }, { kind: "component", type: i2$1.Tab, selector: "cds-tab, ibm-tab", inputs: ["heading", "title", "context", "active", "disabled", "tabIndex", "id", "cacheActive", "tabContent", "templateContext"], outputs: ["selected"] }, { kind: "component", type: AccessControlJsonEditorTabComponent, selector: "valtimo-access-control-json-editor-tab", inputs: ["disabled", "model"], outputs: ["validEvent", "valueChangeEvent"] }, { kind: "component", type: AccessControlOverviewTabComponent, selector: "valtimo-access-control-overview-tab", inputs: ["roleKey", "permissions"] }, { kind: "component", type: RoleMetadataModalComponent, selector: "valtimo-role-metadata-modal", inputs: ["type", "open", "defaultKeyValue", "usedKeys"], outputs: ["closeEvent"] }, { kind: "component", type: AccessControlFormEditorTabComponent, selector: "valtimo-access-control-form-editor-tab", inputs: ["model", "disabled", "roleKey"], outputs: ["validEvent", "valueChangeEvent"] }, { kind: "component", type: DeleteRoleModalComponent, selector: "valtimo-delete-role-modal", inputs: ["deleteRowKeys", "showDeleteModal$"], outputs: ["deleteEvent"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2587
2630
  }
2588
2631
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AccessControlEditorComponent, decorators: [{
2589
2632
  type: Component,
2590
- args: [{ standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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<ng-container *ngIf=\"model$ | async as model; else loading\">\n <!-- The headers only switch the active tab; the tab content is rendered below (gated by the\n active-tab signal) instead of inside the Carbon tab panes. Carbon removes a pane's content\n as soon as another header is clicked, which would destroy the editor's unsaved form before\n the leave-page confirmation is resolved. -->\n <cds-tabs type=\"contained\">\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.EDITOR\"\n [heading]=\"'accessControl.roles.tabs.editor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.EDITOR)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.SUMMARY\"\n [heading]=\"'accessControl.roles.tabs.summary' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.SUMMARY)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.JSON_EDITOR\"\n [heading]=\"'accessControl.roles.tabs.jsonEditor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.JSON_EDITOR)\"\n ></cds-tab>\n </cds-tabs>\n\n <!-- White surface for the tab content. The Carbon tab pane used to provide this; since the\n content is now rendered outside the panes, the wrapper supplies the layer background. -->\n <div class=\"access-control-editor__content\">\n @if ($activeTab() === AccessControlEditorTab.EDITOR) {\n <valtimo-access-control-form-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n [roleKey]=\"roleKey$ | async\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-form-editor-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.SUMMARY) {\n <valtimo-access-control-overview-tab\n [permissions]=\"permissions$ | async\"\n [roleKey]=\"roleKey$ | async\"\n ></valtimo-access-control-overview-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.JSON_EDITOR) {\n <valtimo-access-control-json-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-json-editor-tab>\n }\n </div>\n</ng-container>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n model: model$ | async,\n moreDisabled: moreDisabled$ | async,\n compactMode: compactMode$ | async,\n } as obs\"\n class=\"buttons-container\"\n >\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option [disabled]=\"obs.moreDisabled\" (selected)=\"showEditModal()\">{{\n 'accessControl.roles.editMetadata' | translate\n }}</v-overflow-menu-option>\n\n <v-overflow-menu-option [disabled]=\"obs.moreDisabled\" (selected)=\"exportPermissions()\">{{\n 'interface.export' | translate\n }}</v-overflow-menu-option>\n\n <v-overflow-menu-option\n [disabled]=\"obs.moreDisabled\"\n type=\"danger\"\n (selected)=\"showDeleteModal()\"\n >{{ 'interface.delete' | translate }}</v-overflow-menu-option\n >\n </v-overflow-menu>\n\n <button\n [disabled]=\"saveDisabled$ | async\"\n cdsButton=\"primary\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"updatePermissions()\"\n >\n {{ 'interface.save' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"save\" size=\"16\"></svg>\n </button>\n </div>\n </ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-role-metadata-modal\n [defaultKeyValue]=\"obs.selectedRowKeys[0]\"\n [open]=\"showEditModal$ | async\"\n type=\"edit\"\n (closeEvent)=\"onEdit(obs.selectedRowKeys[0], $event)\"\n ></valtimo-role-metadata-modal>\n</ng-container>\n\n<ng-template #loading>\n <div class=\"loading-container\">\n <cds-loading></cds-loading>\n </div>\n</ng-template>\n", styles: [".loading-container{display:flex;width:100%;justify-content:center}.overflow-button{margin-right:16px}.buttons-container{display:flex;flex-direction:row;align-items:center}.buttons-container button{height:min-content}:host ::ng-deep .cds--tab-content{background-color:var(--cds-layer);outline:none!important;padding:0}.access-control-editor__content{background-color:var(--cds-layer)}\n/*!\n * Copyright 2015-2025 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"] }]
2633
+ args: [{ standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n ~ Copyright 2015-2025 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<ng-container *ngIf=\"model$ | async as model; else loading\">\n <!-- The headers only switch the active tab; the tab content is rendered below (gated by the\n active-tab signal) instead of inside the Carbon tab panes. Carbon removes a pane's content\n as soon as another header is clicked, which would destroy the editor's unsaved form before\n the leave-page confirmation is resolved. -->\n <cds-tabs type=\"contained\">\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.EDITOR\"\n [heading]=\"'accessControl.roles.tabs.editor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.EDITOR)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.SUMMARY\"\n [heading]=\"'accessControl.roles.tabs.summary' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.SUMMARY)\"\n ></cds-tab>\n\n <cds-tab\n [active]=\"$activeTab() === AccessControlEditorTab.JSON_EDITOR\"\n [heading]=\"'accessControl.roles.tabs.jsonEditor' | translate\"\n (selected)=\"setActiveTab(AccessControlEditorTab.JSON_EDITOR)\"\n ></cds-tab>\n </cds-tabs>\n\n <!-- White surface for the tab content. The Carbon tab pane used to provide this; since the\n content is now rendered outside the panes, the wrapper supplies the layer background. -->\n <div class=\"access-control-editor__content\">\n @if ($activeTab() === AccessControlEditorTab.EDITOR) {\n <valtimo-access-control-form-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n [roleKey]=\"roleKey$ | async\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-form-editor-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.SUMMARY) {\n <valtimo-access-control-overview-tab\n [permissions]=\"permissions$ | async\"\n [roleKey]=\"roleKey$ | async\"\n ></valtimo-access-control-overview-tab>\n }\n\n @if ($activeTab() === AccessControlEditorTab.JSON_EDITOR) {\n <valtimo-access-control-json-editor-tab\n [disabled]=\"editorDisabled$ | async\"\n [model]=\"model\"\n (validEvent)=\"onValid($event)\"\n (valueChangeEvent)=\"onValueChange($event)\"\n ></valtimo-access-control-json-editor-tab>\n }\n </div>\n</ng-container>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n model: model$ | async,\n moreDisabled: moreDisabled$ | async,\n compactMode: compactMode$ | async,\n } as obs\"\n class=\"buttons-container\"\n >\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option\n [testId]=\"testIds.moreMenuEditMetadata\"\n [disabled]=\"obs.moreDisabled\"\n (selected)=\"showEditModal()\"\n >{{ 'accessControl.roles.editMetadata' | translate }}</v-overflow-menu-option\n >\n\n <v-overflow-menu-option\n [testId]=\"testIds.moreMenuExport\"\n [disabled]=\"obs.moreDisabled\"\n (selected)=\"exportPermissions()\"\n >{{ 'interface.export' | translate }}</v-overflow-menu-option\n >\n\n <v-overflow-menu-option\n [disabled]=\"obs.moreDisabled\"\n type=\"danger\"\n (selected)=\"showDeleteModal()\"\n >{{ 'interface.delete' | translate }}</v-overflow-menu-option\n >\n </v-overflow-menu>\n\n <button\n [disabled]=\"saveDisabled$ | async\"\n cdsButton=\"primary\"\n [attr.data-test-id]=\"testIds.saveButton\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"updatePermissions()\"\n >\n {{ 'interface.save' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"save\" size=\"16\"></svg>\n </button>\n </div>\n </ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"{selectedRowKeys: selectedRowKeys$ | async} as obs\">\n <valtimo-delete-role-modal\n [deleteRowKeys]=\"obs.selectedRowKeys\"\n [showDeleteModal$]=\"showDeleteModal$\"\n (deleteEvent)=\"onDelete($event)\"\n >\n </valtimo-delete-role-modal>\n\n <valtimo-role-metadata-modal\n [defaultKeyValue]=\"obs.selectedRowKeys[0]\"\n [open]=\"showEditModal$ | async\"\n type=\"edit\"\n (closeEvent)=\"onEdit(obs.selectedRowKeys[0], $event)\"\n ></valtimo-role-metadata-modal>\n</ng-container>\n\n<ng-template #loading>\n <div class=\"loading-container\">\n <cds-loading></cds-loading>\n </div>\n</ng-template>\n", styles: [".loading-container{display:flex;width:100%;justify-content:center}.overflow-button{margin-right:16px}.buttons-container{display:flex;flex-direction:row;align-items:center}.buttons-container button{height:min-content}:host ::ng-deep .cds--tab-content{background-color:var(--cds-layer);outline:none!important;padding:0}.access-control-editor__content{background-color:var(--cds-layer)}\n/*!\n * Copyright 2015-2025 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"] }]
2591
2634
  }], ctorParameters: () => [{ type: AccessControlService }, { type: i1$3.ActivatedRoute }, { type: i3$1.PageTitleService }, { type: i1$3.Router }, { type: i1$1.GlobalNotificationService }, { type: i1$2.TranslateService }, { type: AccessControlExportService }, { type: i3$1.PageHeaderService }], propDecorators: { _tabs: [{
2592
2635
  type: ViewChildren,
2593
2636
  args: [Tab]