@memberjunction/ng-explorer-settings 6.2.0-edge.0 → 6.2.0-edge.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/account-info/account-info.component.d.ts +1 -1
- package/dist/lib/account-info/account-info.component.js +2 -2
- package/dist/lib/account-info/account-info.component.js.map +1 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +92 -10
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.js +222 -76
- package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
- package/dist/lib/application-management/application-management.component.d.ts +92 -10
- package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-management.component.js +229 -65
- package/dist/lib/application-management/application-management.component.js.map +1 -1
- package/dist/lib/application-settings/application-settings.component.d.ts +4 -4
- package/dist/lib/application-settings/application-settings.component.js +10 -10
- package/dist/lib/application-settings/application-settings.component.js.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts +88 -10
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.js +219 -63
- package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts +44 -6
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +117 -43
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts +25 -3
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.js +62 -18
- package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts +32 -4
- package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.js +84 -30
- package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
- package/dist/lib/role-management/role-management-agent-context.d.ts +12 -4
- package/dist/lib/role-management/role-management-agent-context.d.ts.map +1 -1
- package/dist/lib/role-management/role-management-agent-context.js +26 -10
- package/dist/lib/role-management/role-management-agent-context.js.map +1 -1
- package/dist/lib/role-management/role-management.component.d.ts +95 -11
- package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-management.component.js +259 -91
- package/dist/lib/role-management/role-management.component.js.map +1 -1
- package/dist/lib/settings/settings.component.d.ts +87 -11
- package/dist/lib/settings/settings.component.d.ts.map +1 -1
- package/dist/lib/settings/settings.component.js +211 -65
- package/dist/lib/settings/settings.component.js.map +1 -1
- package/dist/lib/shared/settings-card.component.d.ts +24 -4
- package/dist/lib/shared/settings-card.component.d.ts.map +1 -1
- package/dist/lib/shared/settings-card.component.js +46 -6
- package/dist/lib/shared/settings-card.component.js.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.d.ts +172 -18
- package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.js +320 -108
- package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
- package/dist/lib/user-app-config/user-app-config-content.component.js +3 -3
- package/dist/lib/user-app-config/user-app-config-content.component.js.map +1 -1
- package/dist/lib/user-app-config/user-app-config-reorder.d.ts +4 -0
- package/dist/lib/user-app-config/user-app-config-reorder.d.ts.map +1 -1
- package/dist/lib/user-app-config/user-app-config-reorder.js +11 -3
- package/dist/lib/user-app-config/user-app-config-reorder.js.map +1 -1
- package/dist/lib/user-management/transaction-group-refusals.d.ts +4 -2
- package/dist/lib/user-management/transaction-group-refusals.d.ts.map +1 -1
- package/dist/lib/user-management/transaction-group-refusals.js +7 -3
- package/dist/lib/user-management/transaction-group-refusals.js.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts +44 -6
- package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.js +121 -47
- package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
- package/dist/lib/user-management/user-management-agent-context.d.ts +10 -0
- package/dist/lib/user-management/user-management-agent-context.d.ts.map +1 -1
- package/dist/lib/user-management/user-management-agent-context.js +26 -6
- package/dist/lib/user-management/user-management-agent-context.js.map +1 -1
- package/dist/lib/user-management/user-management.component.d.ts +174 -16
- package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-management.component.js +480 -171
- package/dist/lib/user-management/user-management.component.js.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts +97 -15
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.js +280 -116
- package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
- package/package.json +20 -20
|
@@ -166,19 +166,51 @@ function RoleDialogComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
|
166
166
|
i0.ɵɵconditional(ctx_r1.isLoading ? 49 : 50);
|
|
167
167
|
} }
|
|
168
168
|
export class RoleDialogComponent extends BaseAngularComponent {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
Data = null;
|
|
170
|
+
/** @deprecated Use {@link Data}. */
|
|
171
|
+
set data(value) {
|
|
172
|
+
this.Data = value;
|
|
173
|
+
}
|
|
174
|
+
/** @deprecated Use {@link Data}. */
|
|
175
|
+
get data() {
|
|
176
|
+
return this.Data;
|
|
177
|
+
}
|
|
178
|
+
Visible = false;
|
|
179
|
+
/** @deprecated Use {@link Visible}. */
|
|
180
|
+
set visible(value) {
|
|
181
|
+
this.Visible = value;
|
|
182
|
+
}
|
|
183
|
+
/** @deprecated Use {@link Visible}. */
|
|
184
|
+
get visible() {
|
|
185
|
+
return this.Visible;
|
|
186
|
+
}
|
|
187
|
+
Result = new EventEmitter();
|
|
188
|
+
/**
|
|
189
|
+
* @deprecated Use {@link Result}.
|
|
190
|
+
*
|
|
191
|
+
* The same emitter under the old binding name, so a template still binding
|
|
192
|
+
* (result) keeps working. Must stay AFTER Result: class fields
|
|
193
|
+
* initialise in order, and the other way round this captures undefined.
|
|
194
|
+
*/
|
|
195
|
+
result = this.Result;
|
|
172
196
|
fb = inject(FormBuilder);
|
|
173
197
|
cdr = inject(ChangeDetectorRef);
|
|
174
198
|
ngZone = inject(NgZone);
|
|
175
199
|
get metadata() { return this.ProviderToUse; }
|
|
176
|
-
|
|
200
|
+
RoleForm;
|
|
201
|
+
/** @deprecated Use {@link RoleForm}. */
|
|
202
|
+
get roleForm() {
|
|
203
|
+
return this.RoleForm;
|
|
204
|
+
}
|
|
205
|
+
/** @deprecated Use {@link RoleForm}. */
|
|
206
|
+
set roleForm(value) {
|
|
207
|
+
this.RoleForm = value;
|
|
208
|
+
}
|
|
177
209
|
isLoading = false;
|
|
178
210
|
error = null;
|
|
179
211
|
constructor() {
|
|
180
212
|
super();
|
|
181
|
-
this.
|
|
213
|
+
this.RoleForm = this.fb.group({
|
|
182
214
|
name: ['', [Validators.required, Validators.maxLength(50)]],
|
|
183
215
|
description: [''],
|
|
184
216
|
directoryId: ['']
|
|
@@ -188,11 +220,11 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
188
220
|
// Initial setup
|
|
189
221
|
}
|
|
190
222
|
ngOnChanges(changes) {
|
|
191
|
-
if (changes['data'] && this.
|
|
223
|
+
if (changes['data'] && this.Data?.role && this.IsEditMode) {
|
|
192
224
|
this.loadRoleData();
|
|
193
225
|
}
|
|
194
226
|
// Reset form if switching to create mode or dialog becomes visible
|
|
195
|
-
if (changes['visible'] && this.
|
|
227
|
+
if (changes['visible'] && this.Visible && !this.IsEditMode) {
|
|
196
228
|
this.resetForm();
|
|
197
229
|
}
|
|
198
230
|
}
|
|
@@ -200,7 +232,7 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
200
232
|
// Cleanup if needed
|
|
201
233
|
}
|
|
202
234
|
resetForm() {
|
|
203
|
-
this.
|
|
235
|
+
this.RoleForm.reset({
|
|
204
236
|
name: '',
|
|
205
237
|
description: '',
|
|
206
238
|
directoryId: ''
|
|
@@ -208,48 +240,60 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
208
240
|
this.error = null;
|
|
209
241
|
}
|
|
210
242
|
onEscapeKey(event) {
|
|
211
|
-
if (this.
|
|
243
|
+
if (this.Visible) {
|
|
212
244
|
this.onCancel();
|
|
213
245
|
}
|
|
214
246
|
}
|
|
247
|
+
get WindowTitle() {
|
|
248
|
+
return this.IsEditMode ? 'Edit Role' : 'Create New Role';
|
|
249
|
+
}
|
|
250
|
+
/** @deprecated Use {@link WindowTitle}. */
|
|
215
251
|
get windowTitle() {
|
|
216
|
-
return this.
|
|
252
|
+
return this.WindowTitle;
|
|
217
253
|
}
|
|
254
|
+
get IsEditMode() {
|
|
255
|
+
return this.Data?.mode === 'edit';
|
|
256
|
+
}
|
|
257
|
+
/** @deprecated Use {@link IsEditMode}. */
|
|
218
258
|
get isEditMode() {
|
|
219
|
-
return this.
|
|
259
|
+
return this.IsEditMode;
|
|
220
260
|
}
|
|
221
|
-
get
|
|
222
|
-
if (!this.
|
|
261
|
+
get IsSystemRole() {
|
|
262
|
+
if (!this.Data?.role)
|
|
223
263
|
return false;
|
|
224
264
|
const systemRoleNames = ['Administrator', 'User', 'Guest', 'Developer'];
|
|
225
|
-
return systemRoleNames.includes(this.
|
|
265
|
+
return systemRoleNames.includes(this.Data.role.Name || '');
|
|
266
|
+
}
|
|
267
|
+
/** @deprecated Use {@link IsSystemRole}. */
|
|
268
|
+
get isSystemRole() {
|
|
269
|
+
return this.IsSystemRole;
|
|
226
270
|
}
|
|
227
271
|
loadRoleData() {
|
|
228
|
-
if (!this.
|
|
272
|
+
if (!this.Data?.role)
|
|
229
273
|
return;
|
|
230
|
-
const role = this.
|
|
231
|
-
this.
|
|
274
|
+
const role = this.Data.role;
|
|
275
|
+
this.RoleForm.patchValue({
|
|
232
276
|
name: role.Name,
|
|
233
277
|
description: role.Description,
|
|
234
278
|
directoryId: role.DirectoryID
|
|
235
279
|
});
|
|
236
280
|
// Disable name editing for system roles
|
|
237
|
-
if (this.
|
|
238
|
-
this.
|
|
281
|
+
if (this.IsSystemRole) {
|
|
282
|
+
this.RoleForm.get('name')?.disable();
|
|
239
283
|
}
|
|
240
284
|
}
|
|
241
|
-
async
|
|
242
|
-
if (this.
|
|
243
|
-
this.markFormGroupTouched(this.
|
|
285
|
+
async OnSubmit() {
|
|
286
|
+
if (this.RoleForm.invalid) {
|
|
287
|
+
this.markFormGroupTouched(this.RoleForm);
|
|
244
288
|
return;
|
|
245
289
|
}
|
|
246
290
|
this.isLoading = true;
|
|
247
291
|
this.error = null;
|
|
248
292
|
try {
|
|
249
293
|
let role;
|
|
250
|
-
if (this.
|
|
294
|
+
if (this.IsEditMode && this.Data?.role) {
|
|
251
295
|
// Edit existing role
|
|
252
|
-
role = this.
|
|
296
|
+
role = this.Data.role;
|
|
253
297
|
}
|
|
254
298
|
else {
|
|
255
299
|
// Create new role
|
|
@@ -257,9 +301,9 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
257
301
|
role.NewRecord();
|
|
258
302
|
}
|
|
259
303
|
// Update role properties
|
|
260
|
-
const formValue = this.
|
|
304
|
+
const formValue = this.RoleForm.value;
|
|
261
305
|
// Only update name if not a system role
|
|
262
|
-
if (!this.
|
|
306
|
+
if (!this.IsSystemRole) {
|
|
263
307
|
role.Name = formValue.name;
|
|
264
308
|
}
|
|
265
309
|
role.Description = formValue.description;
|
|
@@ -269,7 +313,7 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
269
313
|
if (!saveResult) {
|
|
270
314
|
throw new Error(role.LatestResult?.Message || 'Failed to save role');
|
|
271
315
|
}
|
|
272
|
-
this.
|
|
316
|
+
this.Result.emit({ action: 'save', role });
|
|
273
317
|
}
|
|
274
318
|
catch (error) {
|
|
275
319
|
console.error('Error saving role:', error);
|
|
@@ -285,8 +329,12 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
285
329
|
});
|
|
286
330
|
}
|
|
287
331
|
}
|
|
332
|
+
/** @deprecated Use {@link OnSubmit}. */
|
|
333
|
+
async onSubmit() {
|
|
334
|
+
return this.OnSubmit();
|
|
335
|
+
}
|
|
288
336
|
onCancel() {
|
|
289
|
-
this.
|
|
337
|
+
this.Result.emit({ action: 'cancel' });
|
|
290
338
|
}
|
|
291
339
|
markFormGroupTouched(formGroup) {
|
|
292
340
|
Object.keys(formGroup.controls).forEach(key => {
|
|
@@ -297,7 +345,7 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
297
345
|
static ɵfac = function RoleDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RoleDialogComponent)(); };
|
|
298
346
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RoleDialogComponent, selectors: [["mj-role-dialog"]], hostBindings: function RoleDialogComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
299
347
|
i0.ɵɵlistener("keydown.escape", function RoleDialogComponent_keydown_escape_HostBindingHandler($event) { return ctx.onEscapeKey($event); }, i0.ɵɵresolveDocument);
|
|
300
|
-
} }, inputs: { data: "data", visible: "visible" }, outputs: { result: "result" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [[1, "modal-backdrop"], [1, "modal-backdrop", 3, "click"], [1, "modal-dialog", 3, "click"], [1, "modal-header"], [1, "dialog-header"], [1, "dialog-title"], [1, "fa-solid", "fa-shield-halved"], [1, "dialog-subtitle"], ["type", "button", "aria-label", "Close dialog", 1, "modal-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "modal-body"], [3, "ngSubmit", "formGroup"], [1, "content-section"], [1, "form-section"], [1, "section-header"], [1, "section-title"], [1, "section-description"], [1, "form-grid"], [1, "form-field"], ["for", "name", 1, "field-label", "required"], ["id", "name", "type", "text", "formControlName", "name", "placeholder", "Sales Manager", 1, "field-input"], [1, "field-error"], ["for", "description", 1, "field-label"], ["id", "description", "formControlName", "description", "placeholder", "Describe the role's purpose and responsibilities...", "rows", "4", 1, "field-textarea"], [1, "field-hint"], [1, "fa-solid", "fa-cog"], ["Variant", "warning", "Title", "System Role", "Message", "This is a system-defined role. Some properties may be limited for editing to maintain system integrity."], ["Variant", "info", "Title", "Custom Role", "Message", "This is a custom role that can be fully configured and modified."], [1, "modal-footer"], ["type", "submit", 1, "btn", "btn-primary", 3, "disabled"], ["type", "button", 1, "btn", "btn-secondary", 3, "click"], ["Variant", "error", 3, "Message"], [1, "fa-solid", "fa-exclamation-circle"], ["for", "directoryId", 1, "field-label"], ["id", "directoryId", "type", "text", "formControlName", "directoryId", "placeholder", "External directory identifier", 1, "field-input"], [1, "fa-solid", "fa-key"], ["Variant", "info", "Title", "Permission Management"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-save"]], template: function RoleDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
348
|
+
} }, inputs: { Data: "Data", data: "data", Visible: "Visible", visible: "visible" }, outputs: { Result: "Result", result: "result" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [[1, "modal-backdrop"], [1, "modal-backdrop", 3, "click"], [1, "modal-dialog", 3, "click"], [1, "modal-header"], [1, "dialog-header"], [1, "dialog-title"], [1, "fa-solid", "fa-shield-halved"], [1, "dialog-subtitle"], ["type", "button", "aria-label", "Close dialog", 1, "modal-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "modal-body"], [3, "ngSubmit", "formGroup"], [1, "content-section"], [1, "form-section"], [1, "section-header"], [1, "section-title"], [1, "section-description"], [1, "form-grid"], [1, "form-field"], ["for", "name", 1, "field-label", "required"], ["id", "name", "type", "text", "formControlName", "name", "placeholder", "Sales Manager", 1, "field-input"], [1, "field-error"], ["for", "description", 1, "field-label"], ["id", "description", "formControlName", "description", "placeholder", "Describe the role's purpose and responsibilities...", "rows", "4", 1, "field-textarea"], [1, "field-hint"], [1, "fa-solid", "fa-cog"], ["Variant", "warning", "Title", "System Role", "Message", "This is a system-defined role. Some properties may be limited for editing to maintain system integrity."], ["Variant", "info", "Title", "Custom Role", "Message", "This is a custom role that can be fully configured and modified."], [1, "modal-footer"], ["type", "submit", 1, "btn", "btn-primary", 3, "disabled"], ["type", "button", 1, "btn", "btn-secondary", 3, "click"], ["Variant", "error", 3, "Message"], [1, "fa-solid", "fa-exclamation-circle"], ["for", "directoryId", 1, "field-label"], ["id", "directoryId", "type", "text", "formControlName", "directoryId", "placeholder", "External directory identifier", 1, "field-input"], [1, "fa-solid", "fa-key"], ["Variant", "info", "Title", "Permission Management"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-save"]], template: function RoleDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
301
349
|
i0.ɵɵconditionalCreate(0, RoleDialogComponent_Conditional_0_Template, 54, 12, "div", 0);
|
|
302
350
|
} if (rf & 2) {
|
|
303
351
|
i0.ɵɵconditional(ctx.visible ? 0 : -1);
|
|
@@ -306,10 +354,16 @@ export class RoleDialogComponent extends BaseAngularComponent {
|
|
|
306
354
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RoleDialogComponent, [{
|
|
307
355
|
type: Component,
|
|
308
356
|
args: [{ standalone: false, selector: 'mj-role-dialog', encapsulation: ViewEncapsulation.None, template: "<!-- MD3 Modal Dialog -->\n@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <!-- Modal Header with MJ Blue -->\n <div class=\"modal-header\">\n <div class=\"dialog-header\">\n <h2 class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n {{ isEditMode ? 'Edit Role' : 'Create New Role' }}\n </h2>\n <p class=\"dialog-subtitle\">\n {{ isEditMode ? 'Update role information and permissions' : 'Add a new role to the system' }}\n </p>\n </div>\n <button type=\"button\" class=\"modal-close\" (click)=\"onCancel()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"roleForm\" (ngSubmit)=\"onSubmit()\">\n @if (error) {\n <div class=\"content-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n <!-- Basic Information Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n Role Information\n </h3>\n <p class=\"section-description\">Define the role's basic properties and purpose</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"name\">Role Name</label>\n <input\n id=\"name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"Sales Manager\"\n [class.error]=\"roleForm.get('name')?.invalid && roleForm.get('name')?.touched\"\n />\n @if (roleForm.get('name')?.invalid && roleForm.get('name')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (roleForm.get('name')?.errors?.['required']) {\n Role name is required\n }\n @if (roleForm.get('name')?.errors?.['maxlength']) {\n Role name cannot exceed 50 characters\n }\n </div>\n }\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"description\">Description</label>\n <textarea\n id=\"description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the role's purpose and responsibilities...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this role is for and what permissions it should have.\n </div>\n </div>\n @if (isEditMode) {\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"directoryId\">Directory ID</label>\n <input\n id=\"directoryId\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"directoryId\"\n placeholder=\"External directory identifier\"\n />\n <div class=\"field-hint\">\n External directory identifier for syncing with Active Directory or other systems.\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Role Type Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-cog\"></i>\n Role Type\n </h3>\n <p class=\"section-description\">System or custom role classification</p>\n </div>\n <div class=\"form-grid\">\n @if (isSystemRole) {\n <mj-alert Variant=\"warning\" Title=\"System Role\" Message=\"This is a system-defined role. Some properties may be limited for editing to maintain system integrity.\" />\n } @else {\n <mj-alert Variant=\"info\" Title=\"Custom Role\" Message=\"This is a custom role that can be fully configured and modified.\" />\n }\n </div>\n </div>\n </div>\n <!-- Permissions Preview Section -->\n @if (isEditMode) {\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-key\"></i>\n Permissions\n </h3>\n <p class=\"section-description\">Manage role permissions and access rights</p>\n </div>\n <div class=\"form-grid\">\n <mj-alert Variant=\"info\" Title=\"Permission Management\">\n Role permissions can be managed in the <strong>Permissions</strong> tab of the settings dashboard. Use that interface to configure specific access rights for this role.\n </mj-alert>\n </div>\n </div>\n </div>\n }\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"roleForm.invalid || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n {{ isEditMode ? 'Update Role' : 'Create Role' }}\n }\n </button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n}\n", styles: ["/* ============================================\n Role Dialog Component\n Uses MJ Design Tokens (--mj-*)\n ============================================ */\n\n/* ============================================\n Modal Backdrop & Container\n ============================================ */\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1050;\n padding: 1rem;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.modal-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n width: 100%;\n max-width: 850px;\n max-height: calc(100vh - 2rem);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: slideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: scale(0.95) translateY(20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* ============================================\n Modal Header (MJ Blue)\n ============================================ */\n\n.modal-header {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n padding: 24px 32px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n border-radius: var(--mj-radius-2xl) var(--mj-radius-2xl) 0 0;\n flex-shrink: 0;\n}\n\n.dialog-header {\n flex: 1;\n min-width: 0;\n}\n\n.dialog-title {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 600;\n line-height: 1.3;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-title i {\n font-size: 1.25rem;\n opacity: 0.95;\n}\n\n.dialog-subtitle {\n margin: 0.5rem 0 0 0;\n font-size: 0.875rem;\n opacity: 0.9;\n font-weight: 400;\n line-height: 1.4;\n}\n\n.modal-close {\n background: transparent;\n border: none;\n color: var(--mj-brand-on-primary);\n cursor: pointer;\n padding: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n width: 40px;\n height: 40px;\n flex-shrink: 0;\n}\n\n.modal-close:hover {\n background: rgba(255, 255, 255, 0.1);\n}\n\n.modal-close:active {\n background: rgba(255, 255, 255, 0.2);\n transform: scale(0.95);\n}\n\n.modal-close i {\n font-size: 1.25rem;\n}\n\n/* ============================================\n Modal Body\n ============================================ */\n\n.modal-body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 0;\n background: var(--mj-bg-page);\n}\n\n.modal-body::-webkit-scrollbar {\n width: 8px;\n}\n\n.modal-body::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-sunken);\n}\n\n.modal-body::-webkit-scrollbar-thumb {\n background: var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n}\n\n.modal-body::-webkit-scrollbar-thumb:hover {\n background: var(--mj-color-neutral-400);\n}\n\n/* ============================================\n Form Structure\n ============================================ */\n\n.content-section {\n padding: 1.5rem 2rem;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.content-section:last-child {\n border-bottom: none;\n}\n\n.form-section {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.section-header {\n margin-bottom: 1rem;\n}\n\n.section-title {\n margin: 0 0 0.5rem 0;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.section-title i {\n font-size: 1.25rem;\n color: var(--mj-brand-primary);\n}\n\n.section-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n/* ============================================\n Form Grid Layout\n ============================================ */\n\n.form-grid {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n/* ============================================\n Form Fields\n ============================================ */\n\n.form-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.field-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.field-label.required::after {\n content: '*';\n color: var(--mj-status-error);\n margin-left: 0.25rem;\n}\n\n.field-input,\n.field-textarea {\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 0.875rem 1rem;\n font-size: 1rem;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: var(--mj-bg-page);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n width: 100%;\n box-sizing: border-box;\n}\n\n.field-input:hover:not(:disabled),\n.field-textarea:hover:not(:disabled) {\n border-color: var(--mj-color-neutral-400);\n}\n\n.field-input:focus,\n.field-textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-focus-ring);\n}\n\n.field-input:disabled,\n.field-textarea:disabled {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.field-input.error,\n.field-textarea.error {\n border-color: var(--mj-status-error);\n}\n\n.field-input.error:focus,\n.field-textarea.error:focus {\n --mj-ring-color: var(--mj-status-error);\n box-shadow: var(--mj-focus-ring);\n}\n\n.field-textarea {\n resize: vertical;\n min-height: 100px;\n line-height: 1.5;\n}\n\n.field-hint {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n margin-top: 0.25rem;\n}\n\n.field-error {\n font-size: 0.75rem;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-top: 0.25rem;\n}\n\n.field-error i {\n font-size: 0.875rem;\n}\n\n/* ============================================\n Modal Footer (Buttons)\n ============================================ */\n\n.modal-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 1rem;\n padding: 1.5rem 2rem;\n background: var(--mj-bg-surface-sunken);\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n/* ============================================\n Buttons\n ============================================ */\n\n.btn {\n padding: 0.75rem 1.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n border-radius: var(--mj-radius-full);\n border: none;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n font-family: inherit;\n text-transform: none;\n letter-spacing: 0.01em;\n}\n\n.btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.btn:active:not(:disabled) {\n transform: scale(0.98);\n}\n\n.btn i {\n font-size: 1rem;\n}\n\n.btn i.fa-spinner {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Primary Button (MJ Blue - Dark Button) */\n.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-primary:disabled {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n box-shadow: none;\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Secondary Button (Light Button) */\n.btn-secondary {\n background: var(--mj-bg-page);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-color-neutral-400);\n box-shadow: none;\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-secondary:disabled {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-default);\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* ============================================\n Responsive Design\n ============================================ */\n\n@media (max-width: 768px) {\n .modal-backdrop {\n padding: 0;\n }\n\n .modal-dialog {\n max-width: 100%;\n max-height: 100vh;\n border-radius: 0;\n animation: slideInMobile 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n @keyframes slideInMobile {\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .modal-header {\n padding: 20px 16px;\n border-radius: 0;\n }\n\n .dialog-title {\n font-size: 1.25rem;\n }\n\n .dialog-subtitle {\n font-size: 0.8125rem;\n }\n\n .content-section {\n padding: 1.25rem 1rem;\n }\n\n .section-title {\n font-size: 1.125rem;\n }\n\n .modal-footer {\n padding: 1rem;\n flex-direction: column;\n }\n\n .btn {\n width: 100%;\n justify-content: center;\n }\n}\n\n@media (max-width: 480px) {\n .modal-header {\n padding: 16px 12px;\n }\n\n .dialog-title {\n font-size: 1.125rem;\n gap: 0.5rem;\n }\n\n .dialog-title i {\n font-size: 1rem;\n }\n\n .dialog-subtitle {\n font-size: 0.75rem;\n margin-top: 0.25rem;\n }\n\n .content-section {\n padding: 1rem 0.75rem;\n }\n\n .section-title {\n font-size: 1rem;\n gap: 0.5rem;\n }\n\n .field-input,\n .field-textarea {\n padding: 0.75rem;\n font-size: 0.875rem;\n }\n\n .modal-footer {\n padding: 0.75rem;\n }\n\n .btn {\n padding: 0.625rem 1.25rem;\n font-size: 0.8125rem;\n }\n}\n\n/* ============================================\n Accessibility\n ============================================ */\n\n/* Focus Visible Styles */\n*:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Reduced Motion Support */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* High Contrast Mode Support */\n@media (prefers-contrast: high) {\n .modal-dialog {\n border: 2px solid var(--mj-border-default);\n }\n\n .btn {\n border: 2px solid currentColor;\n }\n\n .field-input,\n .field-textarea {\n border-width: 3px;\n }\n}\n\n/* ============================================\n Print Styles\n ============================================ */\n\n@media print {\n .modal-backdrop {\n display: none;\n }\n}\n"] }]
|
|
309
|
-
}], () => [], {
|
|
357
|
+
}], () => [], { Data: [{
|
|
358
|
+
type: Input
|
|
359
|
+
}], data: [{
|
|
360
|
+
type: Input
|
|
361
|
+
}], Visible: [{
|
|
310
362
|
type: Input
|
|
311
363
|
}], visible: [{
|
|
312
364
|
type: Input
|
|
365
|
+
}], Result: [{
|
|
366
|
+
type: Output
|
|
313
367
|
}], result: [{
|
|
314
368
|
type: Output
|
|
315
369
|
}], onEscapeKey: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/role-management/role-dialog/role-dialog.component.ts","../../../../src/lib/role-management/role-dialog/role-dialog.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAA+C,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAExL,OAAO,EAAoC,WAAW,EAAa,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAItG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;;;;ICiBzD,+BAA6B;IAC3B,+BAA8C;IAChD,iBAAM;;;IADsB,cAAiB;IAAjB,sCAAiB;;;IA4BjC,uCACF;;;IAEE,uDACF;;;IAPF,+BAAyB;IACvB,wBAA8C;IAC9C,wGAAkD;IAGlD,wGAAmD;IAGrD,iBAAM;;;;;IANJ,eAEC;IAFD,gJAEC;IACD,cAEC;IAFD,iJAEC;;;IAmBH,AADF,+BAAwB,gBACuB;IAAA,4BAAY;IAAA,iBAAQ;IACjE,4BAMI;IACJ,+BAAwB;IACtB,mGACF;IACF,AADE,iBAAM,EACF;;;IAiBN,+BAAoK;;;IAEpK,+BAA0H;;;IAU1H,AADF,AADF,AADF,+BAA6B,cACD,cACI,aACA;IACxB,wBAA+B;IAC/B,6BACF;IAAA,iBAAK;IACL,6BAA+B;IAAA,yDAAyC;IAC1E,AAD0E,iBAAI,EACxE;IAEJ,AADF,+BAAuB,mBACkC;IACrD,yDAAuC;IAAA,+BAAQ;IAAA,4BAAW;IAAA,iBAAS;IAAC,uHACtE;IAGN,AADE,AADE,AADE,iBAAW,EACP,EACF,EACF;;;IAUF,wBAA2C;IAC3C,2BACF;;;IACE,wBAAgC;IAChC,YACF;;;IADE,cACF;IADE,kFACF;;;;IA5IZ,8BAAiD;IAArB,oLAAS,iBAAU,KAAC;IAC9C,8BAA6D;IAAnC,iHAAS,wBAAwB,IAAC;IAItD,AADF,AADF,8BAA0B,aACG,YACA;IACvB,uBAAyC;IACzC,YACF;IAAA,iBAAK;IACL,4BAA2B;IACzB,YACF;IACF,AADE,iBAAI,EACA;IACN,iCAAyF;IAA/C,uLAAS,iBAAU,KAAC;IAC5D,wBAAiC;IAErC,AADE,iBAAS,EACL;IAGJ,AADF,gCAAwB,gBAC+B;IAAxB,4LAAY,iBAAU,KAAC;IAClD,sGAAa;IASP,AADF,AADF,AADF,gCAA6B,eACD,eACI,cACA;IACxB,wBAAyC;IACzC,mCACF;IAAA,iBAAK;IACL,8BAA+B;IAAA,+DAA8C;IAC/E,AAD+E,iBAAI,EAC7E;IAGF,AADF,AADF,gCAAuB,eACG,iBACyB;IAAA,0BAAS;IAAA,iBAAQ;IAChE,6BAOI;IACJ,sGAAsE;IAWxE,iBAAM;IAEJ,AADF,gCAAwB,iBACuB;IAAA,4BAAW;IAAA,iBAAQ;IAChE,gCAMY;IACZ,gCAAwB;IACtB,4GACF;IACF,AADE,iBAAM,EACF;IACN,sGAAkB;IAiBxB,AADE,AADE,iBAAM,EACF,EACF;IAKA,AADF,AADF,AADF,gCAA6B,eACD,eACI,cACA;IACxB,yBAA+B;IAC/B,4BACF;IAAA,iBAAK;IACL,8BAA+B;IAAA,qDAAoC;IACrE,AADqE,iBAAI,EACnE;IACN,gCAAuB;IAGnB,AAFF,2GAAoB,qFAEX;IAKf,AADE,AADE,iBAAM,EACF,EACF;IAEN,uGAAkB;IAoBhB,AADF,gCAA0B,kBAKrB;IAIC,AAHF,2FAAiB,qEAGR;IAIX,iBAAS;IACT,mCAAqE;IAArB,wLAAS,iBAAU,KAAC;IAClE,wBAAiC;IACjC,yBACF;IAKV,AADE,AADE,AADE,AADE,AADE,iBAAS,EACL,EACD,EACH,EACF,EACF;;;;;IA/II,eACF;IADE,oFACF;IAEE,eACF;IADE,+HACF;IAQI,eAAsB;IAAtB,2CAAsB;IAC1B,cAIC;IAJD,wCAIC;IAoBS,gBAA8E;IAA9E,iLAA8E;IAEhF,cAUC;IAVD,oLAUC;IAeH,eAcC;IAdD,6CAcC;IAeD,gBAIC;IAJD,+CAIC;IAKP,eAiBC;IAjBD,6CAiBC;IAMG,eAA0C;IAA1C,sEAA0C;IAE1C,cAMC;IAND,4CAMC;;ADtHf,MAAM,OAAO,mBAAoB,SAAQ,oBAAoB;IAClD,IAAI,GAA0B,IAAI,CAAC;IACnC,OAAO,GAAG,KAAK,CAAC;IACf,MAAM,GAAG,IAAI,YAAY,EAAoB,CAAC;IAEhD,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACzB,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAChC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAChC,IAAY,QAAQ,KAAK,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;IAC9C,QAAQ,CAAY;IACpB,SAAS,GAAG,KAAK,CAAC;IAClB,KAAK,GAAkB,IAAI,CAAC;IAEnC;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3D,WAAW,EAAE,CAAC,EAAE,CAAC;YACjB,WAAW,EAAE,CAAC,EAAE,CAAC;SAClB,CAAC,CAAC;IACL,CAAC;IAED,QAAQ;QACN,gBAAgB;IAClB,CAAC;IAED,WAAW,CAAC,OAAsB;QAChC,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;QAED,mEAAmE;QACnE,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED,WAAW;QACT,oBAAoB;IACtB,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAClB,IAAI,EAAE,EAAE;YACR,WAAW,EAAE,EAAE;YACf,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAGD,WAAW,CAAC,KAAY;QACtB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAW,WAAW;QACpB,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,iBAAiB,CAAC;IAC3D,CAAC;IAED,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IACpC,CAAC;IAED,IAAW,YAAY;QACrB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI;YAAE,OAAO,KAAK,CAAC;QACnC,MAAM,eAAe,GAAG,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QACxE,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAEO,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI;YAAE,OAAO;QAE7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;QAEH,wCAAwC;QACxC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;QACvC,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAElB,IAAI,CAAC;YACH,IAAI,IAAkB,CAAC;YAEvB,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;gBACvC,qBAAqB;gBACrB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACN,kBAAkB;gBAClB,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAe,WAAW,CAAC,CAAC;gBACtE,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,CAAC;YAED,yBAAyB;YACzB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAEtC,wCAAwC;YACxC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvB,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;YAC7B,CAAC;YAED,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;YACzC,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC,WAAW,IAAI,IAAI,CAAC;YAEjD,YAAY;YACZ,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,IAAI,qBAAqB,CAAC,CAAC;YACvE,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;gBACnB,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;gBACrF,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;gBACnB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzC,CAAC;IAEO,oBAAoB,CAAC,SAAoB;QAC/C,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;6GAtJU,mBAAmB;6DAAnB,mBAAmB;YAAnB,gHAAA,uBAAmB,0BAAA;;YCvBhC,uFAAe;;YAAf,sCAwJC;;;iFDjIY,mBAAmB;cAP/B,SAAS;6BACI,KAAK,YACP,gBAAgB,iBACX,iBAAiB,CAAC,IAAI;;kBAKpC,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kBA+CN,YAAY;mBAAC,yBAAyB,EAAE,CAAC,QAAQ,CAAC;;kFAlDxC,mBAAmB","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, inject, HostListener, ViewEncapsulation, ChangeDetectorRef, NgZone } from '@angular/core';\n\nimport { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';\nimport { Metadata } from '@memberjunction/core';\nimport { MJRoleEntity } from '@memberjunction/core-entities';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nexport interface RoleDialogData {\n role?: MJRoleEntity;\n mode: 'create' | 'edit';\n}\n\nexport interface RoleDialogResult {\n action: 'save' | 'cancel';\n role?: MJRoleEntity;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-role-dialog',\n encapsulation: ViewEncapsulation.None,\n templateUrl: './role-dialog.component.html',\n styleUrls: ['./role-dialog.component.css']\n})\nexport class RoleDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges {\n @Input() data: RoleDialogData | null = null;\n @Input() visible = false;\n @Output() result = new EventEmitter<RoleDialogResult>();\n\n private fb = inject(FormBuilder);\n private cdr = inject(ChangeDetectorRef);\n private ngZone = inject(NgZone);\n private get metadata() { return this.ProviderToUse; }\n public roleForm: FormGroup;\n public isLoading = false;\n public error: string | null = null;\n\n constructor() {\n super();\n this.roleForm = this.fb.group({\n name: ['', [Validators.required, Validators.maxLength(50)]],\n description: [''],\n directoryId: ['']\n });\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['data'] && this.data?.role && this.isEditMode) {\n this.loadRoleData();\n }\n \n // Reset form if switching to create mode or dialog becomes visible\n if (changes['visible'] && this.visible && !this.isEditMode) {\n this.resetForm();\n }\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n private resetForm(): void {\n this.roleForm.reset({\n name: '',\n description: '',\n directoryId: ''\n });\n this.error = null;\n }\n\n @HostListener('document:keydown.escape', ['$event'])\n onEscapeKey(event: Event): void {\n if (this.visible) {\n this.onCancel();\n }\n }\n\n public get windowTitle(): string {\n return this.isEditMode ? 'Edit Role' : 'Create New Role';\n }\n\n public get isEditMode(): boolean {\n return this.data?.mode === 'edit';\n }\n\n public get isSystemRole(): boolean {\n if (!this.data?.role) return false;\n const systemRoleNames = ['Administrator', 'User', 'Guest', 'Developer'];\n return systemRoleNames.includes(this.data.role.Name || '');\n }\n\n private loadRoleData(): void {\n if (!this.data?.role) return;\n\n const role = this.data.role;\n this.roleForm.patchValue({\n name: role.Name,\n description: role.Description,\n directoryId: role.DirectoryID\n });\n\n // Disable name editing for system roles\n if (this.isSystemRole) {\n this.roleForm.get('name')?.disable();\n }\n }\n\n public async onSubmit(): Promise<void> {\n if (this.roleForm.invalid) {\n this.markFormGroupTouched(this.roleForm);\n return;\n }\n\n this.isLoading = true;\n this.error = null;\n\n try {\n let role: MJRoleEntity;\n\n if (this.isEditMode && this.data?.role) {\n // Edit existing role\n role = this.data.role;\n } else {\n // Create new role\n role = await this.metadata.GetEntityObject<MJRoleEntity>('MJ: Roles');\n role.NewRecord();\n }\n\n // Update role properties\n const formValue = this.roleForm.value;\n \n // Only update name if not a system role\n if (!this.isSystemRole) {\n role.Name = formValue.name;\n }\n \n role.Description = formValue.description;\n role.DirectoryID = formValue.directoryId || null;\n\n // Save role\n const saveResult = await role.Save();\n if (!saveResult) {\n throw new Error(role.LatestResult?.Message || 'Failed to save role');\n }\n\n this.result.emit({ action: 'save', role });\n\n } catch (error: unknown) {\n console.error('Error saving role:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n public onCancel(): void {\n this.result.emit({ action: 'cancel' });\n }\n\n private markFormGroupTouched(formGroup: FormGroup): void {\n Object.keys(formGroup.controls).forEach(key => {\n const control = formGroup.get(key);\n control?.markAsTouched();\n });\n }\n}","<!-- MD3 Modal Dialog -->\n@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <!-- Modal Header with MJ Blue -->\n <div class=\"modal-header\">\n <div class=\"dialog-header\">\n <h2 class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n {{ isEditMode ? 'Edit Role' : 'Create New Role' }}\n </h2>\n <p class=\"dialog-subtitle\">\n {{ isEditMode ? 'Update role information and permissions' : 'Add a new role to the system' }}\n </p>\n </div>\n <button type=\"button\" class=\"modal-close\" (click)=\"onCancel()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"roleForm\" (ngSubmit)=\"onSubmit()\">\n @if (error) {\n <div class=\"content-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n <!-- Basic Information Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n Role Information\n </h3>\n <p class=\"section-description\">Define the role's basic properties and purpose</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"name\">Role Name</label>\n <input\n id=\"name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"Sales Manager\"\n [class.error]=\"roleForm.get('name')?.invalid && roleForm.get('name')?.touched\"\n />\n @if (roleForm.get('name')?.invalid && roleForm.get('name')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (roleForm.get('name')?.errors?.['required']) {\n Role name is required\n }\n @if (roleForm.get('name')?.errors?.['maxlength']) {\n Role name cannot exceed 50 characters\n }\n </div>\n }\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"description\">Description</label>\n <textarea\n id=\"description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the role's purpose and responsibilities...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this role is for and what permissions it should have.\n </div>\n </div>\n @if (isEditMode) {\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"directoryId\">Directory ID</label>\n <input\n id=\"directoryId\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"directoryId\"\n placeholder=\"External directory identifier\"\n />\n <div class=\"field-hint\">\n External directory identifier for syncing with Active Directory or other systems.\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Role Type Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-cog\"></i>\n Role Type\n </h3>\n <p class=\"section-description\">System or custom role classification</p>\n </div>\n <div class=\"form-grid\">\n @if (isSystemRole) {\n <mj-alert Variant=\"warning\" Title=\"System Role\" Message=\"This is a system-defined role. Some properties may be limited for editing to maintain system integrity.\" />\n } @else {\n <mj-alert Variant=\"info\" Title=\"Custom Role\" Message=\"This is a custom role that can be fully configured and modified.\" />\n }\n </div>\n </div>\n </div>\n <!-- Permissions Preview Section -->\n @if (isEditMode) {\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-key\"></i>\n Permissions\n </h3>\n <p class=\"section-description\">Manage role permissions and access rights</p>\n </div>\n <div class=\"form-grid\">\n <mj-alert Variant=\"info\" Title=\"Permission Management\">\n Role permissions can be managed in the <strong>Permissions</strong> tab of the settings dashboard. Use that interface to configure specific access rights for this role.\n </mj-alert>\n </div>\n </div>\n </div>\n }\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"roleForm.invalid || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n {{ isEditMode ? 'Update Role' : 'Create Role' }}\n }\n </button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"role-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/role-management/role-dialog/role-dialog.component.ts","../../../../src/lib/role-management/role-dialog/role-dialog.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, inject, HostListener, ViewEncapsulation, ChangeDetectorRef, NgZone } from '@angular/core';\n\nimport { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';\nimport { Metadata } from '@memberjunction/core';\nimport { MJRoleEntity } from '@memberjunction/core-entities';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nexport interface RoleDialogData {\n role?: MJRoleEntity;\n mode: 'create' | 'edit';\n}\n\nexport interface RoleDialogResult {\n action: 'save' | 'cancel';\n role?: MJRoleEntity;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-role-dialog',\n encapsulation: ViewEncapsulation.None,\n templateUrl: './role-dialog.component.html',\n styleUrls: ['./role-dialog.component.css']\n})\nexport class RoleDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges {\n @Input() Data: RoleDialogData | null = null;\n\n /** @deprecated Use {@link Data}. */\n @Input() set data(value: RoleDialogData | null) {\n this.Data = value;\n }\n /** @deprecated Use {@link Data}. */\n get data(): RoleDialogData | null {\n return this.Data;\n }\n @Input() Visible = false;\n\n /** @deprecated Use {@link Visible}. */\n @Input() set visible(value: RoleDialogComponent['Visible']) {\n this.Visible = value;\n }\n /** @deprecated Use {@link Visible}. */\n get visible(): RoleDialogComponent['Visible'] {\n return this.Visible;\n }\n @Output() Result = new EventEmitter<RoleDialogResult>();\n\n /**\n * @deprecated Use {@link Result}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (result) keeps working. Must stay AFTER Result: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() result = this.Result;\n\n private fb = inject(FormBuilder);\n private cdr = inject(ChangeDetectorRef);\n private ngZone = inject(NgZone);\n private get metadata() { return this.ProviderToUse; }\n public RoleForm: FormGroup;\n\n /** @deprecated Use {@link RoleForm}. */\n public get roleForm(): FormGroup {\n return this.RoleForm;\n }\n /** @deprecated Use {@link RoleForm}. */\n public set roleForm(value: FormGroup) {\n this.RoleForm = value;\n }\n public isLoading = false;\n public error: string | null = null;\n\n constructor() {\n super();\n this.RoleForm = this.fb.group({\n name: ['', [Validators.required, Validators.maxLength(50)]],\n description: [''],\n directoryId: ['']\n });\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['data'] && this.Data?.role && this.IsEditMode) {\n this.loadRoleData();\n }\n \n // Reset form if switching to create mode or dialog becomes visible\n if (changes['visible'] && this.Visible && !this.IsEditMode) {\n this.resetForm();\n }\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n private resetForm(): void {\n this.RoleForm.reset({\n name: '',\n description: '',\n directoryId: ''\n });\n this.error = null;\n }\n\n @HostListener('document:keydown.escape', ['$event'])\n onEscapeKey(event: Event): void {\n if (this.Visible) {\n this.onCancel();\n }\n }\n\n public get WindowTitle(): string {\n return this.IsEditMode ? 'Edit Role' : 'Create New Role';\n }\n\n /** @deprecated Use {@link WindowTitle}. */\n public get windowTitle(): string {\n return this.WindowTitle;\n }\n\n public get IsEditMode(): boolean {\n return this.Data?.mode === 'edit';\n }\n\n /** @deprecated Use {@link IsEditMode}. */\n public get isEditMode(): boolean {\n return this.IsEditMode;\n }\n\n public get IsSystemRole(): boolean {\n if (!this.Data?.role) return false;\n const systemRoleNames = ['Administrator', 'User', 'Guest', 'Developer'];\n return systemRoleNames.includes(this.Data.role.Name || '');\n }\n\n /** @deprecated Use {@link IsSystemRole}. */\n public get isSystemRole(): boolean {\n return this.IsSystemRole;\n }\n\n private loadRoleData(): void {\n if (!this.Data?.role) return;\n\n const role = this.Data.role;\n this.RoleForm.patchValue({\n name: role.Name,\n description: role.Description,\n directoryId: role.DirectoryID\n });\n\n // Disable name editing for system roles\n if (this.IsSystemRole) {\n this.RoleForm.get('name')?.disable();\n }\n }\n\n public async OnSubmit(): Promise<void> {\n if (this.RoleForm.invalid) {\n this.markFormGroupTouched(this.RoleForm);\n return;\n }\n\n this.isLoading = true;\n this.error = null;\n\n try {\n let role: MJRoleEntity;\n\n if (this.IsEditMode && this.Data?.role) {\n // Edit existing role\n role = this.Data.role;\n } else {\n // Create new role\n role = await this.metadata.GetEntityObject<MJRoleEntity>('MJ: Roles');\n role.NewRecord();\n }\n\n // Update role properties\n const formValue = this.RoleForm.value;\n \n // Only update name if not a system role\n if (!this.IsSystemRole) {\n role.Name = formValue.name;\n }\n \n role.Description = formValue.description;\n role.DirectoryID = formValue.directoryId || null;\n\n // Save role\n const saveResult = await role.Save();\n if (!saveResult) {\n throw new Error(role.LatestResult?.Message || 'Failed to save role');\n }\n\n this.Result.emit({ action: 'save', role });\n\n } catch (error: unknown) {\n console.error('Error saving role:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n /** @deprecated Use {@link OnSubmit}. */\n public async onSubmit(): Promise<void> {\n return this.OnSubmit();\n }\n\n public onCancel(): void {\n this.Result.emit({ action: 'cancel' });\n }\n\n private markFormGroupTouched(formGroup: FormGroup): void {\n Object.keys(formGroup.controls).forEach(key => {\n const control = formGroup.get(key);\n control?.markAsTouched();\n });\n }\n}","<!-- MD3 Modal Dialog -->\n@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <!-- Modal Header with MJ Blue -->\n <div class=\"modal-header\">\n <div class=\"dialog-header\">\n <h2 class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n {{ isEditMode ? 'Edit Role' : 'Create New Role' }}\n </h2>\n <p class=\"dialog-subtitle\">\n {{ isEditMode ? 'Update role information and permissions' : 'Add a new role to the system' }}\n </p>\n </div>\n <button type=\"button\" class=\"modal-close\" (click)=\"onCancel()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"roleForm\" (ngSubmit)=\"onSubmit()\">\n @if (error) {\n <div class=\"content-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n <!-- Basic Information Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n Role Information\n </h3>\n <p class=\"section-description\">Define the role's basic properties and purpose</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"name\">Role Name</label>\n <input\n id=\"name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"Sales Manager\"\n [class.error]=\"roleForm.get('name')?.invalid && roleForm.get('name')?.touched\"\n />\n @if (roleForm.get('name')?.invalid && roleForm.get('name')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (roleForm.get('name')?.errors?.['required']) {\n Role name is required\n }\n @if (roleForm.get('name')?.errors?.['maxlength']) {\n Role name cannot exceed 50 characters\n }\n </div>\n }\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"description\">Description</label>\n <textarea\n id=\"description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the role's purpose and responsibilities...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this role is for and what permissions it should have.\n </div>\n </div>\n @if (isEditMode) {\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"directoryId\">Directory ID</label>\n <input\n id=\"directoryId\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"directoryId\"\n placeholder=\"External directory identifier\"\n />\n <div class=\"field-hint\">\n External directory identifier for syncing with Active Directory or other systems.\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Role Type Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-cog\"></i>\n Role Type\n </h3>\n <p class=\"section-description\">System or custom role classification</p>\n </div>\n <div class=\"form-grid\">\n @if (isSystemRole) {\n <mj-alert Variant=\"warning\" Title=\"System Role\" Message=\"This is a system-defined role. Some properties may be limited for editing to maintain system integrity.\" />\n } @else {\n <mj-alert Variant=\"info\" Title=\"Custom Role\" Message=\"This is a custom role that can be fully configured and modified.\" />\n }\n </div>\n </div>\n </div>\n <!-- Permissions Preview Section -->\n @if (isEditMode) {\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-key\"></i>\n Permissions\n </h3>\n <p class=\"section-description\">Manage role permissions and access rights</p>\n </div>\n <div class=\"form-grid\">\n <mj-alert Variant=\"info\" Title=\"Permission Management\">\n Role permissions can be managed in the <strong>Permissions</strong> tab of the settings dashboard. Use that interface to configure specific access rights for this role.\n </mj-alert>\n </div>\n </div>\n </div>\n }\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"roleForm.invalid || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n {{ isEditMode ? 'Update Role' : 'Create Role' }}\n }\n </button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n}\n"]}
|
|
@@ -18,8 +18,12 @@ export type RoleTypeFilter = (typeof VALID_ROLE_TYPE_FILTERS)[number];
|
|
|
18
18
|
*/
|
|
19
19
|
export declare const ROLE_AGENT_CONTEXT_NAME_LIST_CAP = 25;
|
|
20
20
|
/** Type-guard for a role-type filter string. Keeps the FilterRolesByType tool tolerant. */
|
|
21
|
+
export declare function IsValidRoleTypeFilter(value: unknown): value is RoleTypeFilter;
|
|
22
|
+
/** @deprecated Use {@link IsValidRoleTypeFilter}. */
|
|
21
23
|
export declare function isValidRoleTypeFilter(value: unknown): value is RoleTypeFilter;
|
|
22
24
|
/** Cap a list of names to {@link ROLE_AGENT_CONTEXT_NAME_LIST_CAP}. Pure + deterministic. */
|
|
25
|
+
export declare function CapRoleNames(names: readonly string[]): string[];
|
|
26
|
+
/** @deprecated Use {@link CapRoleNames}. */
|
|
23
27
|
export declare function capRoleNames(names: readonly string[]): string[];
|
|
24
28
|
/** A minimal descriptor of a role (id + display name) supplied by the component. */
|
|
25
29
|
export interface RoleNameCandidate {
|
|
@@ -28,11 +32,11 @@ export interface RoleNameCandidate {
|
|
|
28
32
|
}
|
|
29
33
|
/** Outcome of a tolerant id→name→contains role resolution. */
|
|
30
34
|
export type RoleLookupResult = {
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
Ok: true;
|
|
36
|
+
Match: RoleNameCandidate;
|
|
33
37
|
} | {
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
Ok: false;
|
|
39
|
+
Error: string;
|
|
36
40
|
};
|
|
37
41
|
/**
|
|
38
42
|
* Resolve an agent-supplied role reference against the loaded roles, tolerantly:
|
|
@@ -43,6 +47,8 @@ export type RoleLookupResult = {
|
|
|
43
47
|
* Pure + deterministic. On a miss, returns a clear error listing a sample of available role
|
|
44
48
|
* names so the agent can correct itself.
|
|
45
49
|
*/
|
|
50
|
+
export declare function ResolveRoleByIDOrName(input: string, candidates: readonly RoleNameCandidate[]): RoleLookupResult;
|
|
51
|
+
/** @deprecated Use {@link ResolveRoleByIDOrName}. */
|
|
46
52
|
export declare function resolveRoleByIDOrName(input: string, candidates: readonly RoleNameCandidate[]): RoleLookupResult;
|
|
47
53
|
/**
|
|
48
54
|
* Read-only permission summary for the selected role, derived from the role's
|
|
@@ -92,5 +98,7 @@ export interface RoleManagementAgentContextInput {
|
|
|
92
98
|
* role-name list and emits a companion total-count when truncated; surfaces the read-only
|
|
93
99
|
* permission summary only when a role is selected and its permissions have been loaded.
|
|
94
100
|
*/
|
|
101
|
+
export declare function BuildRoleManagementAgentContext(input: RoleManagementAgentContextInput): Record<string, unknown>;
|
|
102
|
+
/** @deprecated Use {@link BuildRoleManagementAgentContext}. */
|
|
95
103
|
export declare function buildRoleManagementAgentContext(input: RoleManagementAgentContextInput): Record<string, unknown>;
|
|
96
104
|
//# sourceMappingURL=role-management-agent-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-management-agent-context.d.ts","sourceRoot":"","sources":["../../../src/lib/role-management/role-management-agent-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,sCAAuC,CAAC;AAC5E,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAEnD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAE7E;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE/D;AAED,oFAAoF;AACpF,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,8DAA8D;AAC9D,MAAM,MAAM,gBAAgB,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GACtC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,iBAAiB,EAAE,GAAG,gBAAgB,CAmB/G;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,+BAA+B;IAC5C,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,eAAe,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,UAAU,EAAE,cAAc,CAAC;IAC3B,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mGAAmG;IACnG,uBAAuB,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,+BAA+B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0B/G"}
|
|
1
|
+
{"version":3,"file":"role-management-agent-context.d.ts","sourceRoot":"","sources":["../../../src/lib/role-management/role-management-agent-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,sCAAuC,CAAC;AAC5E,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAEnD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAE7E;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAE7E;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE/D;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE/D;AAED,oFAAoF;AACpF,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,8DAA8D;AAC9D,MAAM,MAAM,gBAAgB,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GACtC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,iBAAiB,EAAE,GAAG,gBAAgB,CAmB/G;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,iBAAiB,EAAE,GAAG,gBAAgB,CAE/G;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,+BAA+B;IAC5C,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,eAAe,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,UAAU,EAAE,cAAc,CAAC;IAC3B,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mGAAmG;IACnG,uBAAuB,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,+BAA+B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0B/G;AAED,+DAA+D;AAC/D,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,+BAA+B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/G"}
|
|
@@ -17,13 +17,21 @@ export const VALID_ROLE_TYPE_FILTERS = ['all', 'system', 'custom'];
|
|
|
17
17
|
*/
|
|
18
18
|
export const ROLE_AGENT_CONTEXT_NAME_LIST_CAP = 25;
|
|
19
19
|
/** Type-guard for a role-type filter string. Keeps the FilterRolesByType tool tolerant. */
|
|
20
|
-
export function
|
|
20
|
+
export function IsValidRoleTypeFilter(value) {
|
|
21
21
|
return typeof value === 'string' && VALID_ROLE_TYPE_FILTERS.includes(value);
|
|
22
22
|
}
|
|
23
|
+
/** @deprecated Use {@link IsValidRoleTypeFilter}. */
|
|
24
|
+
export function isValidRoleTypeFilter(value) {
|
|
25
|
+
return IsValidRoleTypeFilter(value);
|
|
26
|
+
}
|
|
23
27
|
/** Cap a list of names to {@link ROLE_AGENT_CONTEXT_NAME_LIST_CAP}. Pure + deterministic. */
|
|
24
|
-
export function
|
|
28
|
+
export function CapRoleNames(names) {
|
|
25
29
|
return names.slice(0, ROLE_AGENT_CONTEXT_NAME_LIST_CAP);
|
|
26
30
|
}
|
|
31
|
+
/** @deprecated Use {@link CapRoleNames}. */
|
|
32
|
+
export function capRoleNames(names) {
|
|
33
|
+
return CapRoleNames(names);
|
|
34
|
+
}
|
|
27
35
|
/**
|
|
28
36
|
* Resolve an agent-supplied role reference against the loaded roles, tolerantly:
|
|
29
37
|
* 1. exact ID match (case-insensitive)
|
|
@@ -33,32 +41,36 @@ export function capRoleNames(names) {
|
|
|
33
41
|
* Pure + deterministic. On a miss, returns a clear error listing a sample of available role
|
|
34
42
|
* names so the agent can correct itself.
|
|
35
43
|
*/
|
|
36
|
-
export function
|
|
44
|
+
export function ResolveRoleByIDOrName(input, candidates) {
|
|
37
45
|
const needle = input.trim().toLowerCase();
|
|
38
46
|
if (!needle) {
|
|
39
|
-
return {
|
|
47
|
+
return { Ok: false, Error: 'Provide a role ID or name to select.' };
|
|
40
48
|
}
|
|
41
49
|
const byId = candidates.find(c => c.ID.toLowerCase() === needle);
|
|
42
50
|
if (byId) {
|
|
43
|
-
return {
|
|
51
|
+
return { Ok: true, Match: byId };
|
|
44
52
|
}
|
|
45
53
|
const exact = candidates.find(c => c.Name.toLowerCase() === needle);
|
|
46
54
|
if (exact) {
|
|
47
|
-
return {
|
|
55
|
+
return { Ok: true, Match: exact };
|
|
48
56
|
}
|
|
49
57
|
const contains = candidates.find(c => c.Name.toLowerCase().includes(needle));
|
|
50
58
|
if (contains) {
|
|
51
|
-
return {
|
|
59
|
+
return { Ok: true, Match: contains };
|
|
52
60
|
}
|
|
53
61
|
const sample = candidates.slice(0, 8).map(c => c.Name).join(', ');
|
|
54
|
-
return {
|
|
62
|
+
return { Ok: false, Error: `No role matches "${input}". Available roles: ${sample || '(none loaded)'}.` };
|
|
63
|
+
}
|
|
64
|
+
/** @deprecated Use {@link ResolveRoleByIDOrName}. */
|
|
65
|
+
export function resolveRoleByIDOrName(input, candidates) {
|
|
66
|
+
return ResolveRoleByIDOrName(input, candidates);
|
|
55
67
|
}
|
|
56
68
|
/**
|
|
57
69
|
* Build the agent-visible context object for Role Management. Pure (no `this`). Bounds the
|
|
58
70
|
* role-name list and emits a companion total-count when truncated; surfaces the read-only
|
|
59
71
|
* permission summary only when a role is selected and its permissions have been loaded.
|
|
60
72
|
*/
|
|
61
|
-
export function
|
|
73
|
+
export function BuildRoleManagementAgentContext(input) {
|
|
62
74
|
const context = {
|
|
63
75
|
TotalRoleCount: input.TotalRoleCount,
|
|
64
76
|
FilteredRoleCount: input.FilteredRoleCount,
|
|
@@ -70,7 +82,7 @@ export function buildRoleManagementAgentContext(input) {
|
|
|
70
82
|
SelectedRoleName: input.SelectedRoleName,
|
|
71
83
|
};
|
|
72
84
|
if (input.VisibleRoleNames.length > 0) {
|
|
73
|
-
context['VisibleRoleNames'] =
|
|
85
|
+
context['VisibleRoleNames'] = CapRoleNames(input.VisibleRoleNames);
|
|
74
86
|
if (input.VisibleRoleNames.length > ROLE_AGENT_CONTEXT_NAME_LIST_CAP) {
|
|
75
87
|
context['VisibleRoleCount'] = input.VisibleRoleNames.length;
|
|
76
88
|
}
|
|
@@ -82,4 +94,8 @@ export function buildRoleManagementAgentContext(input) {
|
|
|
82
94
|
}
|
|
83
95
|
return context;
|
|
84
96
|
}
|
|
97
|
+
/** @deprecated Use {@link BuildRoleManagementAgentContext}. */
|
|
98
|
+
export function buildRoleManagementAgentContext(input) {
|
|
99
|
+
return BuildRoleManagementAgentContext(input);
|
|
100
|
+
}
|
|
85
101
|
//# sourceMappingURL=role-management-agent-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-management-agent-context.js","sourceRoot":"","sources":["../../../src/lib/role-management/role-management-agent-context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Pure helpers for the Role Management admin surface's AI-agent integration.\n *\n * 🔒 READ-ONLY / GOVERNANCE SURFACE. These helpers shape a non-sensitive snapshot of the\n * role-management screen into the key-value `AgentContext` object and back agent-supplied\n * role references with tolerant id→name→contains resolution. They are intentionally free of\n * Angular / component dependencies so they can be unit-tested in isolation (mirrors the\n * Data Explorer agent-context pattern). Permission information is surfaced as a READ-ONLY\n * summary (counts only) — no grant/revoke surface, no secrets.\n */\n\n/** The three role-type filter values the surface supports. */\nexport const VALID_ROLE_TYPE_FILTERS = ['all', 'system', 'custom'] as const;\nexport type RoleTypeFilter = (typeof VALID_ROLE_TYPE_FILTERS)[number];\n\n/**\n * Upper bound on how many role names we publish in a name-list context field\n * (VisibleRoleNames). Keeps the streamed note bounded; a companion total-count field reports\n * the true number when the list is truncated.\n */\nexport const ROLE_AGENT_CONTEXT_NAME_LIST_CAP = 25;\n\n/** Type-guard for a role-type filter string. Keeps the FilterRolesByType tool tolerant. */\nexport function isValidRoleTypeFilter(value: unknown): value is RoleTypeFilter {\n return typeof value === 'string' && (VALID_ROLE_TYPE_FILTERS as readonly string[]).includes(value);\n}\n\n/** Cap a list of names to {@link ROLE_AGENT_CONTEXT_NAME_LIST_CAP}. Pure + deterministic. */\nexport function capRoleNames(names: readonly string[]): string[] {\n return names.slice(0, ROLE_AGENT_CONTEXT_NAME_LIST_CAP);\n}\n\n/** A minimal descriptor of a role (id + display name) supplied by the component. */\nexport interface RoleNameCandidate {\n ID: string;\n Name: string;\n}\n\n/** Outcome of a tolerant id→name→contains role resolution. */\nexport type RoleLookupResult =\n | { ok: true; match: RoleNameCandidate }\n | { ok: false; error: string };\n\n/**\n * Resolve an agent-supplied role reference against the loaded roles, tolerantly:\n * 1. exact ID match (case-insensitive)\n * 2. exact display-name match (case-insensitive)\n * 3. first case-insensitive *contains* match on name\n *\n * Pure + deterministic. On a miss, returns a clear error listing a sample of available role\n * names so the agent can correct itself.\n */\nexport function resolveRoleByIDOrName(input: string, candidates: readonly RoleNameCandidate[]): RoleLookupResult {\n const needle = input.trim().toLowerCase();\n if (!needle) {\n return { ok: false, error: 'Provide a role ID or name to select.' };\n }\n const byId = candidates.find(c => c.ID.toLowerCase() === needle);\n if (byId) {\n return { ok: true, match: byId };\n }\n const exact = candidates.find(c => c.Name.toLowerCase() === needle);\n if (exact) {\n return { ok: true, match: exact };\n }\n const contains = candidates.find(c => c.Name.toLowerCase().includes(needle));\n if (contains) {\n return { ok: true, match: contains };\n }\n const sample = candidates.slice(0, 8).map(c => c.Name).join(', ');\n return { ok: false, error: `No role matches \"${input}\". Available roles: ${sample || '(none loaded)'}.` };\n}\n\n/**\n * Read-only permission summary for the selected role, derived from the role's\n * entity-permission rows. Counts only — describes the breadth of access the role has been\n * granted without exposing any mutation surface.\n */\nexport interface RolePermissionSummary {\n /** Number of entities for which the role has at least one permission row. */\n EntityCount: number;\n /** Number of entities the role can read. */\n ReadCount: number;\n /** Number of entities the role can create. */\n CreateCount: number;\n /** Number of entities the role can update. */\n UpdateCount: number;\n /** Number of entities the role can delete. */\n DeleteCount: number;\n}\n\n/**\n * The plain, component-supplied snapshot used to build the role-management agent context.\n * NON-SENSITIVE by construction — counts, filter state, and on-screen display values only.\n */\nexport interface RoleManagementAgentContextInput {\n /** Total roles loaded (unfiltered). */\n TotalRoleCount: number;\n /** Roles currently visible after type/search filters. */\n FilteredRoleCount: number;\n /** Count of system roles (across the unfiltered set). */\n SystemRoleCount: number;\n /** Count of custom roles (across the unfiltered set). */\n CustomRoleCount: number;\n /** Active role-type filter. */\n TypeFilter: RoleTypeFilter;\n /** Current free-text search string. */\n SearchText: string;\n /** ID of the currently selected (expanded) role, or null. */\n SelectedRoleId: string | null;\n /** Display name of the currently selected role, or null. */\n SelectedRoleName: string | null;\n /** Display names of the currently visible (filtered) roles, in list order. */\n VisibleRoleNames: string[];\n /** Read-only permission summary for the selected role, or null when none selected / not loaded. */\n SelectedRolePermissions: RolePermissionSummary | null;\n}\n\n/**\n * Build the agent-visible context object for Role Management. Pure (no `this`). Bounds the\n * role-name list and emits a companion total-count when truncated; surfaces the read-only\n * permission summary only when a role is selected and its permissions have been loaded.\n */\nexport function buildRoleManagementAgentContext(input: RoleManagementAgentContextInput): Record<string, unknown> {\n const context: Record<string, unknown> = {\n TotalRoleCount: input.TotalRoleCount,\n FilteredRoleCount: input.FilteredRoleCount,\n SystemRoleCount: input.SystemRoleCount,\n CustomRoleCount: input.CustomRoleCount,\n TypeFilter: input.TypeFilter,\n SearchText: input.SearchText,\n SelectedRoleId: input.SelectedRoleId,\n SelectedRoleName: input.SelectedRoleName,\n };\n\n if (input.VisibleRoleNames.length > 0) {\n context['VisibleRoleNames'] = capRoleNames(input.VisibleRoleNames);\n if (input.VisibleRoleNames.length > ROLE_AGENT_CONTEXT_NAME_LIST_CAP) {\n context['VisibleRoleCount'] = input.VisibleRoleNames.length;\n }\n }\n\n // Read-only permission summary — surfaced ONLY when a role is selected AND its\n // permissions have been loaded (never fabricated zeros for an unselected role).\n if (input.SelectedRolePermissions) {\n context['SelectedRolePermissions'] = { ...input.SelectedRolePermissions };\n }\n\n return context;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"role-management-agent-context.js","sourceRoot":"","sources":["../../../src/lib/role-management/role-management-agent-context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Pure helpers for the Role Management admin surface's AI-agent integration.\n *\n * 🔒 READ-ONLY / GOVERNANCE SURFACE. These helpers shape a non-sensitive snapshot of the\n * role-management screen into the key-value `AgentContext` object and back agent-supplied\n * role references with tolerant id→name→contains resolution. They are intentionally free of\n * Angular / component dependencies so they can be unit-tested in isolation (mirrors the\n * Data Explorer agent-context pattern). Permission information is surfaced as a READ-ONLY\n * summary (counts only) — no grant/revoke surface, no secrets.\n */\n\n/** The three role-type filter values the surface supports. */\nexport const VALID_ROLE_TYPE_FILTERS = ['all', 'system', 'custom'] as const;\nexport type RoleTypeFilter = (typeof VALID_ROLE_TYPE_FILTERS)[number];\n\n/**\n * Upper bound on how many role names we publish in a name-list context field\n * (VisibleRoleNames). Keeps the streamed note bounded; a companion total-count field reports\n * the true number when the list is truncated.\n */\nexport const ROLE_AGENT_CONTEXT_NAME_LIST_CAP = 25;\n\n/** Type-guard for a role-type filter string. Keeps the FilterRolesByType tool tolerant. */\nexport function IsValidRoleTypeFilter(value: unknown): value is RoleTypeFilter {\n return typeof value === 'string' && (VALID_ROLE_TYPE_FILTERS as readonly string[]).includes(value);\n}\n\n/** @deprecated Use {@link IsValidRoleTypeFilter}. */\nexport function isValidRoleTypeFilter(value: unknown): value is RoleTypeFilter {\n return IsValidRoleTypeFilter(value);\n}\n\n/** Cap a list of names to {@link ROLE_AGENT_CONTEXT_NAME_LIST_CAP}. Pure + deterministic. */\nexport function CapRoleNames(names: readonly string[]): string[] {\n return names.slice(0, ROLE_AGENT_CONTEXT_NAME_LIST_CAP);\n}\n\n/** @deprecated Use {@link CapRoleNames}. */\nexport function capRoleNames(names: readonly string[]): string[] {\n return CapRoleNames(names);\n}\n\n/** A minimal descriptor of a role (id + display name) supplied by the component. */\nexport interface RoleNameCandidate {\n ID: string;\n Name: string;\n}\n\n/** Outcome of a tolerant id→name→contains role resolution. */\nexport type RoleLookupResult =\n | { Ok: true; Match: RoleNameCandidate }\n | { Ok: false; Error: string };\n\n/**\n * Resolve an agent-supplied role reference against the loaded roles, tolerantly:\n * 1. exact ID match (case-insensitive)\n * 2. exact display-name match (case-insensitive)\n * 3. first case-insensitive *contains* match on name\n *\n * Pure + deterministic. On a miss, returns a clear error listing a sample of available role\n * names so the agent can correct itself.\n */\nexport function ResolveRoleByIDOrName(input: string, candidates: readonly RoleNameCandidate[]): RoleLookupResult {\n const needle = input.trim().toLowerCase();\n if (!needle) {\n return { Ok: false, Error: 'Provide a role ID or name to select.' };\n }\n const byId = candidates.find(c => c.ID.toLowerCase() === needle);\n if (byId) {\n return { Ok: true, Match: byId };\n }\n const exact = candidates.find(c => c.Name.toLowerCase() === needle);\n if (exact) {\n return { Ok: true, Match: exact };\n }\n const contains = candidates.find(c => c.Name.toLowerCase().includes(needle));\n if (contains) {\n return { Ok: true, Match: contains };\n }\n const sample = candidates.slice(0, 8).map(c => c.Name).join(', ');\n return { Ok: false, Error: `No role matches \"${input}\". Available roles: ${sample || '(none loaded)'}.` };\n}\n\n/** @deprecated Use {@link ResolveRoleByIDOrName}. */\nexport function resolveRoleByIDOrName(input: string, candidates: readonly RoleNameCandidate[]): RoleLookupResult {\n return ResolveRoleByIDOrName(input, candidates);\n}\n\n/**\n * Read-only permission summary for the selected role, derived from the role's\n * entity-permission rows. Counts only — describes the breadth of access the role has been\n * granted without exposing any mutation surface.\n */\nexport interface RolePermissionSummary {\n /** Number of entities for which the role has at least one permission row. */\n EntityCount: number;\n /** Number of entities the role can read. */\n ReadCount: number;\n /** Number of entities the role can create. */\n CreateCount: number;\n /** Number of entities the role can update. */\n UpdateCount: number;\n /** Number of entities the role can delete. */\n DeleteCount: number;\n}\n\n/**\n * The plain, component-supplied snapshot used to build the role-management agent context.\n * NON-SENSITIVE by construction — counts, filter state, and on-screen display values only.\n */\nexport interface RoleManagementAgentContextInput {\n /** Total roles loaded (unfiltered). */\n TotalRoleCount: number;\n /** Roles currently visible after type/search filters. */\n FilteredRoleCount: number;\n /** Count of system roles (across the unfiltered set). */\n SystemRoleCount: number;\n /** Count of custom roles (across the unfiltered set). */\n CustomRoleCount: number;\n /** Active role-type filter. */\n TypeFilter: RoleTypeFilter;\n /** Current free-text search string. */\n SearchText: string;\n /** ID of the currently selected (expanded) role, or null. */\n SelectedRoleId: string | null;\n /** Display name of the currently selected role, or null. */\n SelectedRoleName: string | null;\n /** Display names of the currently visible (filtered) roles, in list order. */\n VisibleRoleNames: string[];\n /** Read-only permission summary for the selected role, or null when none selected / not loaded. */\n SelectedRolePermissions: RolePermissionSummary | null;\n}\n\n/**\n * Build the agent-visible context object for Role Management. Pure (no `this`). Bounds the\n * role-name list and emits a companion total-count when truncated; surfaces the read-only\n * permission summary only when a role is selected and its permissions have been loaded.\n */\nexport function BuildRoleManagementAgentContext(input: RoleManagementAgentContextInput): Record<string, unknown> {\n const context: Record<string, unknown> = {\n TotalRoleCount: input.TotalRoleCount,\n FilteredRoleCount: input.FilteredRoleCount,\n SystemRoleCount: input.SystemRoleCount,\n CustomRoleCount: input.CustomRoleCount,\n TypeFilter: input.TypeFilter,\n SearchText: input.SearchText,\n SelectedRoleId: input.SelectedRoleId,\n SelectedRoleName: input.SelectedRoleName,\n };\n\n if (input.VisibleRoleNames.length > 0) {\n context['VisibleRoleNames'] = CapRoleNames(input.VisibleRoleNames);\n if (input.VisibleRoleNames.length > ROLE_AGENT_CONTEXT_NAME_LIST_CAP) {\n context['VisibleRoleCount'] = input.VisibleRoleNames.length;\n }\n }\n\n // Read-only permission summary — surfaced ONLY when a role is selected AND its\n // permissions have been loaded (never fabricated zeros for an unselected role).\n if (input.SelectedRolePermissions) {\n context['SelectedRolePermissions'] = { ...input.SelectedRolePermissions };\n }\n\n return context;\n}\n\n/** @deprecated Use {@link BuildRoleManagementAgentContext}. */\nexport function buildRoleManagementAgentContext(input: RoleManagementAgentContextInput): Record<string, unknown> {\n return BuildRoleManagementAgentContext(input);\n}\n"]}
|