@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.
Files changed (77) hide show
  1. package/dist/lib/account-info/account-info.component.d.ts +1 -1
  2. package/dist/lib/account-info/account-info.component.js +2 -2
  3. package/dist/lib/account-info/account-info.component.js.map +1 -1
  4. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +92 -10
  5. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
  6. package/dist/lib/application-management/application-dialog/application-dialog.component.js +222 -76
  7. package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
  8. package/dist/lib/application-management/application-management.component.d.ts +92 -10
  9. package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
  10. package/dist/lib/application-management/application-management.component.js +229 -65
  11. package/dist/lib/application-management/application-management.component.js.map +1 -1
  12. package/dist/lib/application-settings/application-settings.component.d.ts +4 -4
  13. package/dist/lib/application-settings/application-settings.component.js +10 -10
  14. package/dist/lib/application-settings/application-settings.component.js.map +1 -1
  15. package/dist/lib/entity-permissions/entity-permissions.component.d.ts +88 -10
  16. package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
  17. package/dist/lib/entity-permissions/entity-permissions.component.js +219 -63
  18. package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
  19. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts +44 -6
  20. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
  21. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +117 -43
  22. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
  23. package/dist/lib/notification-preferences/notification-preferences.component.d.ts +25 -3
  24. package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -1
  25. package/dist/lib/notification-preferences/notification-preferences.component.js +62 -18
  26. package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
  27. package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts +32 -4
  28. package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts.map +1 -1
  29. package/dist/lib/role-management/role-dialog/role-dialog.component.js +84 -30
  30. package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
  31. package/dist/lib/role-management/role-management-agent-context.d.ts +12 -4
  32. package/dist/lib/role-management/role-management-agent-context.d.ts.map +1 -1
  33. package/dist/lib/role-management/role-management-agent-context.js +26 -10
  34. package/dist/lib/role-management/role-management-agent-context.js.map +1 -1
  35. package/dist/lib/role-management/role-management.component.d.ts +95 -11
  36. package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
  37. package/dist/lib/role-management/role-management.component.js +259 -91
  38. package/dist/lib/role-management/role-management.component.js.map +1 -1
  39. package/dist/lib/settings/settings.component.d.ts +87 -11
  40. package/dist/lib/settings/settings.component.d.ts.map +1 -1
  41. package/dist/lib/settings/settings.component.js +211 -65
  42. package/dist/lib/settings/settings.component.js.map +1 -1
  43. package/dist/lib/shared/settings-card.component.d.ts +24 -4
  44. package/dist/lib/shared/settings-card.component.d.ts.map +1 -1
  45. package/dist/lib/shared/settings-card.component.js +46 -6
  46. package/dist/lib/shared/settings-card.component.js.map +1 -1
  47. package/dist/lib/sql-logging/sql-logging.component.d.ts +172 -18
  48. package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -1
  49. package/dist/lib/sql-logging/sql-logging.component.js +320 -108
  50. package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
  51. package/dist/lib/user-app-config/user-app-config-content.component.js +3 -3
  52. package/dist/lib/user-app-config/user-app-config-content.component.js.map +1 -1
  53. package/dist/lib/user-app-config/user-app-config-reorder.d.ts +4 -0
  54. package/dist/lib/user-app-config/user-app-config-reorder.d.ts.map +1 -1
  55. package/dist/lib/user-app-config/user-app-config-reorder.js +11 -3
  56. package/dist/lib/user-app-config/user-app-config-reorder.js.map +1 -1
  57. package/dist/lib/user-management/transaction-group-refusals.d.ts +4 -2
  58. package/dist/lib/user-management/transaction-group-refusals.d.ts.map +1 -1
  59. package/dist/lib/user-management/transaction-group-refusals.js +7 -3
  60. package/dist/lib/user-management/transaction-group-refusals.js.map +1 -1
  61. package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts +44 -6
  62. package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
  63. package/dist/lib/user-management/user-dialog/user-dialog.component.js +121 -47
  64. package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
  65. package/dist/lib/user-management/user-management-agent-context.d.ts +10 -0
  66. package/dist/lib/user-management/user-management-agent-context.d.ts.map +1 -1
  67. package/dist/lib/user-management/user-management-agent-context.js +26 -6
  68. package/dist/lib/user-management/user-management-agent-context.js.map +1 -1
  69. package/dist/lib/user-management/user-management.component.d.ts +174 -16
  70. package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
  71. package/dist/lib/user-management/user-management.component.js +480 -171
  72. package/dist/lib/user-management/user-management.component.js.map +1 -1
  73. package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts +97 -15
  74. package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts.map +1 -1
  75. package/dist/lib/user-profile-settings/user-profile-settings.component.js +280 -116
  76. package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
  77. package/package.json +20 -20
@@ -3,7 +3,7 @@ import { FormBuilder, Validators } from '@angular/forms';
3
3
  import { RunView } from '@memberjunction/core';
4
4
  import { UUIDsEqual } from '@memberjunction/global';
5
5
  import { BaseAngularComponent } from '@memberjunction/ng-base-types';
6
- import { serverRefusalReasons } from '../transaction-group-refusals';
6
+ import { ServerRefusalReasons } from '../transaction-group-refusals';
7
7
  import * as i0 from "@angular/core";
8
8
  import * as i1 from "@angular/forms";
9
9
  import * as i2 from "@memberjunction/ng-ui-components";
@@ -236,21 +236,69 @@ function UserDialogComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
236
236
  i0.ɵɵconditional(ctx_r1.isLoading ? 87 : 88);
237
237
  } }
238
238
  export class UserDialogComponent extends BaseAngularComponent {
239
- data = null;
240
- visible = false;
241
- result = new EventEmitter();
239
+ Data = null;
240
+ /** @deprecated Use {@link Data}. */
241
+ set data(value) {
242
+ this.Data = value;
243
+ }
244
+ /** @deprecated Use {@link Data}. */
245
+ get data() {
246
+ return this.Data;
247
+ }
248
+ Visible = false;
249
+ /** @deprecated Use {@link Visible}. */
250
+ set visible(value) {
251
+ this.Visible = value;
252
+ }
253
+ /** @deprecated Use {@link Visible}. */
254
+ get visible() {
255
+ return this.Visible;
256
+ }
257
+ Result = new EventEmitter();
258
+ /**
259
+ * @deprecated Use {@link Result}.
260
+ *
261
+ * The same emitter under the old binding name, so a template still binding
262
+ * (result) keeps working. Must stay AFTER Result: class fields
263
+ * initialise in order, and the other way round this captures undefined.
264
+ */
265
+ result = this.Result;
242
266
  fb = inject(FormBuilder);
243
267
  cdr = inject(ChangeDetectorRef);
244
268
  ngZone = inject(NgZone);
245
269
  get metadata() { return this.ProviderToUse; }
246
- userForm;
270
+ UserForm;
271
+ /** @deprecated Use {@link UserForm}. */
272
+ get userForm() {
273
+ return this.UserForm;
274
+ }
275
+ /** @deprecated Use {@link UserForm}. */
276
+ set userForm(value) {
277
+ this.UserForm = value;
278
+ }
247
279
  isLoading = false;
248
280
  error = null;
249
- selectedRoleIds = new Set();
250
- existingUserRoles = [];
281
+ SelectedRoleIds = new Set();
282
+ /** @deprecated Use {@link SelectedRoleIds}. */
283
+ get selectedRoleIds() {
284
+ return this.SelectedRoleIds;
285
+ }
286
+ /** @deprecated Use {@link SelectedRoleIds}. */
287
+ set selectedRoleIds(value) {
288
+ this.SelectedRoleIds = value;
289
+ }
290
+ ExistingUserRoles = [];
291
+ /** @deprecated Use {@link ExistingUserRoles}. */
292
+ get existingUserRoles() {
293
+ return this.ExistingUserRoles;
294
+ }
295
+ /** @deprecated Use {@link ExistingUserRoles}. */
296
+ set existingUserRoles(value) {
297
+ this.ExistingUserRoles = value;
298
+ }
251
299
  constructor() {
252
300
  super();
253
- this.userForm = this.fb.group({
301
+ this.UserForm = this.fb.group({
254
302
  name: ['', [Validators.required, Validators.email]],
255
303
  firstName: [''],
256
304
  lastName: [''],
@@ -266,9 +314,9 @@ export class UserDialogComponent extends BaseAngularComponent {
266
314
  ngOnChanges(changes) {
267
315
  // Always clear state when data changes to prevent persistence bugs
268
316
  if (changes['data']) {
269
- this.selectedRoleIds.clear();
270
- this.existingUserRoles = [];
271
- if (this.data?.user && this.isEditMode) {
317
+ this.SelectedRoleIds.clear();
318
+ this.ExistingUserRoles = [];
319
+ if (this.Data?.user && this.IsEditMode) {
272
320
  this.loadUserData();
273
321
  }
274
322
  else {
@@ -276,7 +324,7 @@ export class UserDialogComponent extends BaseAngularComponent {
276
324
  }
277
325
  }
278
326
  // Reset form when dialog becomes visible and not in edit mode
279
- if (changes['visible'] && this.visible && !this.isEditMode) {
327
+ if (changes['visible'] && this.Visible && !this.IsEditMode) {
280
328
  this.resetForm();
281
329
  }
282
330
  }
@@ -284,7 +332,7 @@ export class UserDialogComponent extends BaseAngularComponent {
284
332
  // Cleanup if needed
285
333
  }
286
334
  resetForm() {
287
- this.userForm.reset({
335
+ this.UserForm.reset({
288
336
  name: '',
289
337
  firstName: '',
290
338
  lastName: '',
@@ -293,25 +341,33 @@ export class UserDialogComponent extends BaseAngularComponent {
293
341
  type: 'User',
294
342
  isActive: true
295
343
  });
296
- this.selectedRoleIds.clear();
344
+ this.SelectedRoleIds.clear();
297
345
  this.error = null;
298
346
  }
299
347
  onEscapeKey(event) {
300
- if (this.visible) {
348
+ if (this.Visible) {
301
349
  this.onCancel();
302
350
  }
303
351
  }
352
+ get WindowTitle() {
353
+ return this.IsEditMode ? 'Edit User' : 'Create New User';
354
+ }
355
+ /** @deprecated Use {@link WindowTitle}. */
304
356
  get windowTitle() {
305
- return this.isEditMode ? 'Edit User' : 'Create New User';
357
+ return this.WindowTitle;
358
+ }
359
+ get IsEditMode() {
360
+ return this.Data?.mode === 'edit';
306
361
  }
362
+ /** @deprecated Use {@link IsEditMode}. */
307
363
  get isEditMode() {
308
- return this.data?.mode === 'edit';
364
+ return this.IsEditMode;
309
365
  }
310
366
  async loadUserData() {
311
- if (!this.data?.user)
367
+ if (!this.Data?.user)
312
368
  return;
313
- const user = this.data.user;
314
- this.userForm.patchValue({
369
+ const user = this.Data.user;
370
+ this.UserForm.patchValue({
315
371
  name: user.Name,
316
372
  firstName: user.FirstName,
317
373
  lastName: user.LastName,
@@ -332,10 +388,10 @@ export class UserDialogComponent extends BaseAngularComponent {
332
388
  ResultType: 'entity_object'
333
389
  });
334
390
  if (result.Success && result.Results) {
335
- this.existingUserRoles = result.Results;
391
+ this.ExistingUserRoles = result.Results;
336
392
  // Pre-select existing roles
337
- for (const userRole of this.existingUserRoles) {
338
- this.selectedRoleIds.add(userRole.RoleID);
393
+ for (const userRole of this.ExistingUserRoles) {
394
+ this.SelectedRoleIds.add(userRole.RoleID);
339
395
  }
340
396
  }
341
397
  }
@@ -343,36 +399,44 @@ export class UserDialogComponent extends BaseAngularComponent {
343
399
  console.warn('Failed to load existing user roles:', error);
344
400
  }
345
401
  }
346
- onRoleToggle(roleId, event) {
402
+ OnRoleToggle(roleId, event) {
347
403
  event.stopPropagation();
348
404
  const checkbox = event.target;
349
405
  if (checkbox.checked) {
350
- this.selectedRoleIds.add(roleId);
406
+ this.SelectedRoleIds.add(roleId);
351
407
  }
352
408
  else {
353
- this.selectedRoleIds.delete(roleId);
409
+ this.SelectedRoleIds.delete(roleId);
354
410
  }
355
411
  }
356
- toggleRole(roleId) {
357
- if (this.selectedRoleIds.has(roleId)) {
358
- this.selectedRoleIds.delete(roleId);
412
+ /** @deprecated Use {@link OnRoleToggle}. */
413
+ onRoleToggle(roleId, event) {
414
+ return this.OnRoleToggle(roleId, event);
415
+ }
416
+ ToggleRole(roleId) {
417
+ if (this.SelectedRoleIds.has(roleId)) {
418
+ this.SelectedRoleIds.delete(roleId);
359
419
  }
360
420
  else {
361
- this.selectedRoleIds.add(roleId);
421
+ this.SelectedRoleIds.add(roleId);
362
422
  }
363
423
  }
364
- async onSubmit() {
365
- if (this.userForm.invalid) {
366
- this.markFormGroupTouched(this.userForm);
424
+ /** @deprecated Use {@link ToggleRole}. */
425
+ toggleRole(roleId) {
426
+ return this.ToggleRole(roleId);
427
+ }
428
+ async OnSubmit() {
429
+ if (this.UserForm.invalid) {
430
+ this.markFormGroupTouched(this.UserForm);
367
431
  return;
368
432
  }
369
433
  this.isLoading = true;
370
434
  this.error = null;
371
435
  try {
372
436
  let user;
373
- if (this.isEditMode && this.data?.user) {
437
+ if (this.IsEditMode && this.Data?.user) {
374
438
  // Edit existing user
375
- user = this.data.user;
439
+ user = this.Data.user;
376
440
  }
377
441
  else {
378
442
  // Create new user
@@ -380,7 +444,7 @@ export class UserDialogComponent extends BaseAngularComponent {
380
444
  user.NewRecord();
381
445
  }
382
446
  // Update user properties
383
- const formValue = this.userForm.value;
447
+ const formValue = this.UserForm.value;
384
448
  user.Name = formValue.name;
385
449
  user.FirstName = formValue.firstName;
386
450
  user.LastName = formValue.lastName;
@@ -395,7 +459,7 @@ export class UserDialogComponent extends BaseAngularComponent {
395
459
  }
396
460
  // Handle role assignments
397
461
  await this.updateUserRoles(user.ID);
398
- this.result.emit({ action: 'save', user });
462
+ this.Result.emit({ action: 'save', user });
399
463
  }
400
464
  catch (error) {
401
465
  console.error('Error saving user:', error);
@@ -411,13 +475,17 @@ export class UserDialogComponent extends BaseAngularComponent {
411
475
  });
412
476
  }
413
477
  }
478
+ /** @deprecated Use {@link OnSubmit}. */
479
+ async onSubmit() {
480
+ return this.OnSubmit();
481
+ }
414
482
  async updateUserRoles(userId) {
415
483
  try {
416
484
  // Get current role IDs from existing UserRole entities
417
- const existingRoleIds = new Set(this.existingUserRoles.map(ur => ur.RoleID));
485
+ const existingRoleIds = new Set(this.ExistingUserRoles.map(ur => ur.RoleID));
418
486
  // Determine roles to add and remove
419
- const rolesToAdd = Array.from(this.selectedRoleIds).filter(roleId => !existingRoleIds.has(roleId));
420
- const rolesToRemove = this.existingUserRoles.filter(userRole => !this.selectedRoleIds.has(userRole.RoleID));
487
+ const rolesToAdd = Array.from(this.SelectedRoleIds).filter(roleId => !existingRoleIds.has(roleId));
488
+ const rolesToRemove = this.ExistingUserRoles.filter(userRole => !this.SelectedRoleIds.has(userRole.RoleID));
421
489
  if (rolesToAdd.length === 0 && rolesToRemove.length === 0) {
422
490
  return;
423
491
  }
@@ -439,7 +507,7 @@ export class UserDialogComponent extends BaseAngularComponent {
439
507
  refusals.push(`Remove ${this.describeRole(userRole.RoleID)}: ${userRole.LatestResult?.CompleteMessage ?? 'unknown error'}`);
440
508
  }
441
509
  else {
442
- enrolled.push({ label: `Remove ${this.describeRole(userRole.RoleID)}`, entity: userRole });
510
+ enrolled.push({ Label: `Remove ${this.describeRole(userRole.RoleID)}`, Entity: userRole });
443
511
  }
444
512
  }
445
513
  for (const roleId of rolesToAdd) {
@@ -452,7 +520,7 @@ export class UserDialogComponent extends BaseAngularComponent {
452
520
  refusals.push(`Add ${this.describeRole(roleId)}: ${userRole.LatestResult?.CompleteMessage ?? 'unknown error'}`);
453
521
  }
454
522
  else {
455
- enrolled.push({ label: `Add ${this.describeRole(roleId)}`, entity: userRole });
523
+ enrolled.push({ Label: `Add ${this.describeRole(roleId)}`, Entity: userRole });
456
524
  }
457
525
  }
458
526
  if (refusals.length > 0) {
@@ -463,7 +531,7 @@ export class UserDialogComponent extends BaseAngularComponent {
463
531
  if (!await tg.Submit()) {
464
532
  // Every row enrolled, so this is a SERVER-side refusal (or a rollback). Since #4309 the
465
533
  // server says which row and why, and that reason is now on each entity's LatestResult.
466
- const reasons = serverRefusalReasons(enrolled);
534
+ const reasons = ServerRefusalReasons(enrolled);
467
535
  throw new Error(reasons.length > 0
468
536
  ? `Failed to update user roles — all changes have been rolled back.\n${reasons.join('\n')}`
469
537
  : 'Failed to update user roles — all changes have been rolled back');
@@ -476,10 +544,10 @@ export class UserDialogComponent extends BaseAngularComponent {
476
544
  }
477
545
  /** Names a role for a refusal message; falls back to the ID when the catalog has no match. */
478
546
  describeRole(roleId) {
479
- return this.data?.availableRoles.find(r => UUIDsEqual(r.ID, roleId))?.Name ?? roleId;
547
+ return this.Data?.availableRoles.find(r => UUIDsEqual(r.ID, roleId))?.Name ?? roleId;
480
548
  }
481
549
  onCancel() {
482
- this.result.emit({ action: 'cancel' });
550
+ this.Result.emit({ action: 'cancel' });
483
551
  }
484
552
  markFormGroupTouched(formGroup) {
485
553
  Object.keys(formGroup.controls).forEach(key => {
@@ -490,7 +558,7 @@ export class UserDialogComponent extends BaseAngularComponent {
490
558
  static ɵfac = function UserDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserDialogComponent)(); };
491
559
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserDialogComponent, selectors: [["mj-user-dialog"]], hostBindings: function UserDialogComponent_HostBindings(rf, ctx) { if (rf & 1) {
492
560
  i0.ɵɵlistener("keydown.escape", function UserDialogComponent_keydown_escape_HostBindingHandler($event) { return ctx.onEscapeKey($event); }, i0.ɵɵresolveDocument);
493
- } }, 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-user"], [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, "fa-solid", "fa-id-card"], [1, "section-description"], [1, "form-grid"], [1, "form-field"], ["for", "name", 1, "field-label", "required"], ["id", "name", "type", "email", "formControlName", "name", "placeholder", "john@company.com", 1, "field-input"], [1, "field-error"], [1, "form-row"], ["for", "firstName", 1, "field-label"], ["id", "firstName", "type", "text", "formControlName", "firstName", "placeholder", "John", 1, "field-input"], ["for", "lastName", 1, "field-label"], ["id", "lastName", "type", "text", "formControlName", "lastName", "placeholder", "Doe", 1, "field-input"], ["for", "email", 1, "field-label", "required"], ["id", "email", "type", "email", "formControlName", "email", "placeholder", "john@company.com", 1, "field-input"], ["for", "title", 1, "field-label"], ["id", "title", "type", "text", "formControlName", "title", "placeholder", "Software Engineer", 1, "field-input"], [1, "fa-solid", "fa-cog"], ["for", "type", 1, "field-label"], ["id", "type", "formControlName", "type", 1, "field-select"], ["value", "User"], ["value", "Owner"], [1, "checkbox-field"], ["id", "isActive", "type", "checkbox", "formControlName", "isActive", 1, "checkbox-input"], ["for", "isActive", 1, "checkbox-label"], [1, "checkbox-indicator"], [2, "font-size", "12px", "color", "var(--md-on-surface-variant)", "margin-top", "2px"], [1, "fa-solid", "fa-user-tag"], [1, "roles-grid"], [1, "role-card", 3, "selected"], [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"], [1, "role-card", 3, "click"], [1, "role-content"], ["type", "checkbox", 1, "checkbox-input", 3, "change", "id", "checked"], [1, "checkbox-label", 3, "for"], [1, "role-info"], [1, "role-name"], [1, "role-description"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-save"]], template: function UserDialogComponent_Template(rf, ctx) { if (rf & 1) {
561
+ } }, 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-user"], [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, "fa-solid", "fa-id-card"], [1, "section-description"], [1, "form-grid"], [1, "form-field"], ["for", "name", 1, "field-label", "required"], ["id", "name", "type", "email", "formControlName", "name", "placeholder", "john@company.com", 1, "field-input"], [1, "field-error"], [1, "form-row"], ["for", "firstName", 1, "field-label"], ["id", "firstName", "type", "text", "formControlName", "firstName", "placeholder", "John", 1, "field-input"], ["for", "lastName", 1, "field-label"], ["id", "lastName", "type", "text", "formControlName", "lastName", "placeholder", "Doe", 1, "field-input"], ["for", "email", 1, "field-label", "required"], ["id", "email", "type", "email", "formControlName", "email", "placeholder", "john@company.com", 1, "field-input"], ["for", "title", 1, "field-label"], ["id", "title", "type", "text", "formControlName", "title", "placeholder", "Software Engineer", 1, "field-input"], [1, "fa-solid", "fa-cog"], ["for", "type", 1, "field-label"], ["id", "type", "formControlName", "type", 1, "field-select"], ["value", "User"], ["value", "Owner"], [1, "checkbox-field"], ["id", "isActive", "type", "checkbox", "formControlName", "isActive", 1, "checkbox-input"], ["for", "isActive", 1, "checkbox-label"], [1, "checkbox-indicator"], [2, "font-size", "12px", "color", "var(--md-on-surface-variant)", "margin-top", "2px"], [1, "fa-solid", "fa-user-tag"], [1, "roles-grid"], [1, "role-card", 3, "selected"], [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"], [1, "role-card", 3, "click"], [1, "role-content"], ["type", "checkbox", 1, "checkbox-input", 3, "change", "id", "checked"], [1, "checkbox-label", 3, "for"], [1, "role-info"], [1, "role-name"], [1, "role-description"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-save"]], template: function UserDialogComponent_Template(rf, ctx) { if (rf & 1) {
494
562
  i0.ɵɵconditionalCreate(0, UserDialogComponent_Conditional_0_Template, 92, 12, "div", 0);
495
563
  } if (rf & 2) {
496
564
  i0.ɵɵconditional(ctx.visible ? 0 : -1);
@@ -499,10 +567,16 @@ export class UserDialogComponent extends BaseAngularComponent {
499
567
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserDialogComponent, [{
500
568
  type: Component,
501
569
  args: [{ standalone: false, selector: 'mj-user-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-user\"></i>\n {{ isEditMode ? 'Edit User' : 'Create New User' }}\n </h2>\n <p class=\"dialog-subtitle\">\n {{ isEditMode ? 'Update user information and role assignments' : 'Add a new user 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]=\"userForm\" (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-id-card\"></i>\n Basic Information\n </h3>\n <p class=\"section-description\">Enter the user's personal and contact details</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"name\">Username/Email</label>\n <input\n id=\"name\"\n type=\"email\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"john@company.com\"\n [class.error]=\"userForm.get('name')?.invalid && userForm.get('name')?.touched\"\n />\n @if (userForm.get('name')?.invalid && userForm.get('name')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (userForm.get('name')?.errors?.['required']) {\n Username/Email is required\n }\n @if (userForm.get('name')?.errors?.['email']) {\n Please enter a valid email address\n }\n </div>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"firstName\">First Name</label>\n <input\n id=\"firstName\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"firstName\"\n placeholder=\"John\"\n />\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"lastName\">Last Name</label>\n <input\n id=\"lastName\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"lastName\"\n placeholder=\"Doe\"\n />\n </div>\n </div>\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"email\">Email Address</label>\n <input\n id=\"email\"\n type=\"email\"\n class=\"field-input\"\n formControlName=\"email\"\n placeholder=\"john@company.com\"\n [class.error]=\"userForm.get('email')?.invalid && userForm.get('email')?.touched\"\n />\n @if (userForm.get('email')?.invalid && userForm.get('email')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (userForm.get('email')?.errors?.['required']) {\n Email address is required\n }\n @if (userForm.get('email')?.errors?.['email']) {\n Please enter a valid email address\n }\n </div>\n }\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"title\">Job Title</label>\n <input\n id=\"title\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"title\"\n placeholder=\"Software Engineer\"\n />\n </div>\n </div>\n </div>\n </div>\n <!-- User Settings 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 User Settings\n </h3>\n <p class=\"section-description\">Configure user type and account status</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"type\">User Type</label>\n <select id=\"type\" class=\"field-select\" formControlName=\"type\">\n <option value=\"User\">Standard User</option>\n <option value=\"Owner\">System Owner</option>\n </select>\n </div>\n <div class=\"form-field\">\n <div class=\"checkbox-field\">\n <input\n id=\"isActive\"\n type=\"checkbox\"\n class=\"checkbox-input\"\n formControlName=\"isActive\"\n />\n <label class=\"checkbox-label\" for=\"isActive\">\n <div class=\"checkbox-indicator\"></div>\n <div>\n <strong>Active Account</strong>\n <div style=\"font-size: 12px; color: var(--md-on-surface-variant); margin-top: 2px;\">\n User can log in and access the system\n </div>\n </div>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Role Assignment 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-user-tag\"></i>\n Role Assignment\n </h3>\n <p class=\"section-description\">Select the roles to assign to this user</p>\n </div>\n <div class=\"roles-grid\">\n @for (role of data?.availableRoles; track role.ID) {\n <div class=\"role-card\"\n [class.selected]=\"selectedRoleIds.has(role.ID)\"\n (click)=\"toggleRole(role.ID)\">\n <div class=\"role-content\">\n <div class=\"checkbox-field\">\n <input\n type=\"checkbox\"\n class=\"checkbox-input\"\n [id]=\"'role-' + role.ID\"\n [checked]=\"selectedRoleIds.has(role.ID)\"\n (change)=\"onRoleToggle(role.ID, $event)\"\n />\n <label class=\"checkbox-label\" [for]=\"'role-' + role.ID\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n <div class=\"role-info\">\n <h4 class=\"role-name\">{{ role.Name }}</h4>\n @if (role.Description) {\n <p class=\"role-description\">{{ role.Description }}</p>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"userForm.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 User' : 'Create User' }}\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 User 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: 900px;\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.form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n}\n\n@media (max-width: 640px) {\n .form-row {\n grid-template-columns: 1fr;\n gap: 1.5rem;\n }\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-select {\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-select:hover:not(:disabled) {\n border-color: var(--mj-color-neutral-400);\n}\n\n.field-input:focus,\n.field-select: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-select: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-select.error {\n border-color: var(--mj-status-error);\n}\n\n.field-input.error:focus,\n.field-select.error:focus {\n --mj-ring-color: var(--mj-status-error);\n box-shadow: var(--mj-focus-ring);\n}\n\n.field-input::placeholder,\n.field-select::placeholder {\n color: var(--mj-text-secondary);\n}\n\n/* Select Dropdown Styling */\n.field-select {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2379747E' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e\");\n background-position: right 16px center;\n background-repeat: no-repeat;\n background-size: 16px;\n padding-right: calc(16px + 32px);\n appearance: none;\n cursor: pointer;\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 Checkboxes\n ============================================ */\n\n.checkbox-field {\n display: flex;\n align-items: flex-start;\n gap: 0.75rem;\n cursor: pointer;\n margin-bottom: 0;\n}\n\n.checkbox-input {\n position: absolute;\n opacity: 0;\n cursor: pointer;\n}\n\n.checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 0.75rem;\n cursor: pointer;\n font-size: 0.875rem;\n color: var(--mj-text-primary);\n line-height: 1.4;\n margin: 0;\n flex: 1;\n}\n\n.checkbox-indicator {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-color-neutral-400);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-page);\n flex-shrink: 0;\n position: relative;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n margin-top: 2px;\n}\n\n.checkbox-indicator::after {\n content: '';\n position: absolute;\n left: 6px;\n top: 2px;\n width: 4px;\n height: 8px;\n border: solid var(--mj-brand-on-primary);\n border-width: 0 2px 2px 0;\n opacity: 0;\n transform: rotate(45deg) scale(0.8);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.checkbox-input:checked + .checkbox-label .checkbox-indicator {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.checkbox-input:checked + .checkbox-label .checkbox-indicator::after {\n opacity: 1;\n transform: rotate(45deg) scale(1);\n}\n\n.checkbox-input:focus + .checkbox-label .checkbox-indicator {\n box-shadow: var(--mj-focus-ring);\n}\n\n.checkbox-label strong {\n display: block;\n font-weight: 600;\n margin-bottom: 0.125rem;\n}\n\n/* ============================================\n Role Cards\n ============================================ */\n\n.roles-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1rem;\n}\n\n@media (max-width: 640px) {\n .roles-grid {\n grid-template-columns: 1fr;\n }\n}\n\n.role-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n padding: 1.25rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.role-card:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-2px);\n}\n\n.role-card.selected {\n background: var(--mj-brand-accent-subtle);\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-md);\n}\n\n.role-content {\n display: flex;\n align-items: flex-start;\n gap: 1rem;\n}\n\n.role-info {\n flex: 1;\n min-width: 0;\n}\n\n.role-name {\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 0.25rem 0;\n line-height: 1.3;\n}\n\n.role-description {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n margin: 0;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\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 .roles-grid {\n grid-template-columns: 1fr;\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-select {\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-select {\n border-width: 3px;\n }\n\n .role-card {\n border-width: 2px;\n }\n}\n\n/* ============================================\n Print Styles\n ============================================ */\n\n@media print {\n .modal-backdrop {\n display: none;\n }\n}\n"] }]
502
- }], () => [], { data: [{
570
+ }], () => [], { Data: [{
571
+ type: Input
572
+ }], data: [{
573
+ type: Input
574
+ }], Visible: [{
503
575
  type: Input
504
576
  }], visible: [{
505
577
  type: Input
578
+ }], Result: [{
579
+ type: Output
506
580
  }], result: [{
507
581
  type: Output
508
582
  }], onEscapeKey: [{
@@ -1 +1 @@
1
- {"version":3,"file":"user-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/user-management/user-dialog/user-dialog.component.ts","../../../../src/lib/user-management/user-dialog/user-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, RunView } from '@memberjunction/core';\nimport { MJUserEntity, MJRoleEntity, MJUserRoleEntity } from '@memberjunction/core-entities';\n\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { EnrolledRow, serverRefusalReasons } from '../transaction-group-refusals';\nexport interface UserDialogData {\n user?: MJUserEntity;\n mode: 'create' | 'edit';\n availableRoles: MJRoleEntity[];\n}\n\nexport interface UserDialogResult {\n action: 'save' | 'cancel';\n user?: MJUserEntity;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-user-dialog',\n encapsulation: ViewEncapsulation.None,\n templateUrl: './user-dialog.component.html',\n styleUrls: ['./user-dialog.component.css']\n})\nexport class UserDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges {\n @Input() data: UserDialogData | null = null;\n @Input() visible = false;\n @Output() result = new EventEmitter<UserDialogResult>();\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 userForm: FormGroup;\n public isLoading = false;\n public error: string | null = null;\n public selectedRoleIds = new Set<string>();\n public existingUserRoles: MJUserRoleEntity[] = [];\n\n constructor() {\n super();\n this.userForm = this.fb.group({\n name: ['', [Validators.required, Validators.email]],\n firstName: [''],\n lastName: [''],\n email: ['', [Validators.required, Validators.email]],\n title: [''],\n type: ['User', Validators.required],\n isActive: [true]\n });\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n // Always clear state when data changes to prevent persistence bugs\n if (changes['data']) {\n this.selectedRoleIds.clear();\n this.existingUserRoles = [];\n \n if (this.data?.user && this.isEditMode) {\n this.loadUserData();\n } else {\n this.resetForm();\n }\n }\n \n // Reset form when dialog becomes visible and not in edit mode\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.userForm.reset({\n name: '',\n firstName: '',\n lastName: '',\n email: '',\n title: '',\n type: 'User',\n isActive: true\n });\n this.selectedRoleIds.clear();\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 User' : 'Create New User';\n }\n\n public get isEditMode(): boolean {\n return this.data?.mode === 'edit';\n }\n\n private async loadUserData(): Promise<void> {\n if (!this.data?.user) return;\n\n const user = this.data.user;\n this.userForm.patchValue({\n name: user.Name,\n firstName: user.FirstName,\n lastName: user.LastName,\n email: user.Email,\n title: user.Title,\n type: user.Type,\n isActive: user.IsActive\n });\n\n // Load existing user roles\n await this.loadExistingUserRoles(user.ID);\n }\n\n private async loadExistingUserRoles(userId: string): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJUserRoleEntity>({\n EntityName: 'MJ: User Roles',\n ExtraFilter: `UserID='${userId}'`,\n ResultType: 'entity_object'\n });\n\n if (result.Success && result.Results) {\n this.existingUserRoles = result.Results;\n // Pre-select existing roles\n for (const userRole of this.existingUserRoles) {\n this.selectedRoleIds.add(userRole.RoleID);\n }\n }\n } catch (error) {\n console.warn('Failed to load existing user roles:', error);\n }\n }\n\n public onRoleToggle(roleId: string, event: Event): void {\n event.stopPropagation();\n const checkbox = event.target as HTMLInputElement;\n if (checkbox.checked) {\n this.selectedRoleIds.add(roleId);\n } else {\n this.selectedRoleIds.delete(roleId);\n }\n }\n\n public toggleRole(roleId: string): void {\n if (this.selectedRoleIds.has(roleId)) {\n this.selectedRoleIds.delete(roleId);\n } else {\n this.selectedRoleIds.add(roleId);\n }\n }\n\n public async onSubmit(): Promise<void> {\n if (this.userForm.invalid) {\n this.markFormGroupTouched(this.userForm);\n return;\n }\n\n this.isLoading = true;\n this.error = null;\n\n try {\n let user: MJUserEntity;\n\n if (this.isEditMode && this.data?.user) {\n // Edit existing user\n user = this.data.user;\n } else {\n // Create new user\n user = await this.metadata.GetEntityObject<MJUserEntity>('MJ: Users');\n user.NewRecord();\n }\n\n // Update user properties\n const formValue = this.userForm.value;\n user.Name = formValue.name;\n user.FirstName = formValue.firstName;\n user.LastName = formValue.lastName;\n user.Email = formValue.email;\n user.Title = formValue.title;\n user.Type = formValue.type;\n user.IsActive = formValue.isActive;\n\n // Save user\n const saveResult = await user.Save();\n if (!saveResult) {\n throw new Error(user.LatestResult?.Message || 'Failed to save user');\n }\n\n // Handle role assignments\n await this.updateUserRoles(user.ID);\n\n this.result.emit({ action: 'save', user });\n\n } catch (error: unknown) {\n console.error('Error saving user:', 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 private async updateUserRoles(userId: string): Promise<void> {\n try {\n // Get current role IDs from existing UserRole entities\n const existingRoleIds = new Set(this.existingUserRoles.map(ur => ur.RoleID));\n\n // Determine roles to add and remove\n const rolesToAdd = Array.from(this.selectedRoleIds).filter(roleId => !existingRoleIds.has(roleId));\n const rolesToRemove = this.existingUserRoles.filter(userRole => !this.selectedRoleIds.has(userRole.RoleID));\n\n if (rolesToAdd.length === 0 && rolesToRemove.length === 0) {\n return;\n }\n\n // Batch all role deletes and adds into one transactional GraphQL call\n const tg = await this.metadata.CreateTransactionGroup();\n\n // Each Delete()/Save() only ENROLS the row in the group; the write is deferred to Submit().\n // A false return therefore means the row was refused CLIENT-side and never enrolled — so\n // submitting anyway writes a PARTIAL change, or an empty one whose Submit() returns true for\n // having nothing to do, and either way the dialog closes reporting success. Same rule and\n // same reason as `UserManagementComponent.executeBulkRoleAssign`, where the transaction-group\n // semantics — and why the server-side #4282 guard is NOT what this catches — are set out in full.\n const refusals: string[] = [];\n // Enrolled rows are kept so the SERVER's reason can be read back off them below; without\n // that, the reason #4309 puts on LatestResult has nobody left to read it.\n const enrolled: EnrolledRow[] = [];\n\n for (const userRole of rolesToRemove) {\n userRole.TransactionGroup = tg;\n if (!await userRole.Delete()) {\n refusals.push(`Remove ${this.describeRole(userRole.RoleID)}: ${userRole.LatestResult?.CompleteMessage ?? 'unknown error'}`);\n }\n else {\n enrolled.push({ label: `Remove ${this.describeRole(userRole.RoleID)}`, entity: userRole });\n }\n }\n\n for (const roleId of rolesToAdd) {\n const userRole = await this.metadata.GetEntityObject<MJUserRoleEntity>('MJ: User Roles');\n userRole.NewRecord();\n userRole.UserID = userId;\n userRole.RoleID = roleId;\n userRole.TransactionGroup = tg;\n if (!await userRole.Save()) {\n refusals.push(`Add ${this.describeRole(roleId)}: ${userRole.LatestResult?.CompleteMessage ?? 'unknown error'}`);\n }\n else {\n enrolled.push({ label: `Add ${this.describeRole(roleId)}`, entity: userRole });\n }\n }\n\n if (refusals.length > 0) {\n // Nothing was written: the refused rows never enrolled, and the rest are still only queued\n // because Submit() is not reached.\n throw new Error(`Failed to update user roles — no role changes were made.\\n${refusals.join('\\n')}`);\n }\n\n if (!await tg.Submit()) {\n // Every row enrolled, so this is a SERVER-side refusal (or a rollback). Since #4309 the\n // server says which row and why, and that reason is now on each entity's LatestResult.\n const reasons = serverRefusalReasons(enrolled);\n throw new Error(reasons.length > 0\n ? `Failed to update user roles — all changes have been rolled back.\\n${reasons.join('\\n')}`\n : 'Failed to update user roles — all changes have been rolled back');\n }\n } catch (error) {\n console.error('Error updating user roles:', error);\n throw error;\n }\n }\n\n /** Names a role for a refusal message; falls back to the ID when the catalog has no match. */\n private describeRole(roleId: string): string {\n return this.data?.availableRoles.find(r => UUIDsEqual(r.ID, roleId))?.Name ?? roleId;\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-user\"></i>\n {{ isEditMode ? 'Edit User' : 'Create New User' }}\n </h2>\n <p class=\"dialog-subtitle\">\n {{ isEditMode ? 'Update user information and role assignments' : 'Add a new user 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]=\"userForm\" (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-id-card\"></i>\n Basic Information\n </h3>\n <p class=\"section-description\">Enter the user's personal and contact details</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"name\">Username/Email</label>\n <input\n id=\"name\"\n type=\"email\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"john@company.com\"\n [class.error]=\"userForm.get('name')?.invalid && userForm.get('name')?.touched\"\n />\n @if (userForm.get('name')?.invalid && userForm.get('name')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (userForm.get('name')?.errors?.['required']) {\n Username/Email is required\n }\n @if (userForm.get('name')?.errors?.['email']) {\n Please enter a valid email address\n }\n </div>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"firstName\">First Name</label>\n <input\n id=\"firstName\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"firstName\"\n placeholder=\"John\"\n />\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"lastName\">Last Name</label>\n <input\n id=\"lastName\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"lastName\"\n placeholder=\"Doe\"\n />\n </div>\n </div>\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"email\">Email Address</label>\n <input\n id=\"email\"\n type=\"email\"\n class=\"field-input\"\n formControlName=\"email\"\n placeholder=\"john@company.com\"\n [class.error]=\"userForm.get('email')?.invalid && userForm.get('email')?.touched\"\n />\n @if (userForm.get('email')?.invalid && userForm.get('email')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (userForm.get('email')?.errors?.['required']) {\n Email address is required\n }\n @if (userForm.get('email')?.errors?.['email']) {\n Please enter a valid email address\n }\n </div>\n }\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"title\">Job Title</label>\n <input\n id=\"title\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"title\"\n placeholder=\"Software Engineer\"\n />\n </div>\n </div>\n </div>\n </div>\n <!-- User Settings 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 User Settings\n </h3>\n <p class=\"section-description\">Configure user type and account status</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"type\">User Type</label>\n <select id=\"type\" class=\"field-select\" formControlName=\"type\">\n <option value=\"User\">Standard User</option>\n <option value=\"Owner\">System Owner</option>\n </select>\n </div>\n <div class=\"form-field\">\n <div class=\"checkbox-field\">\n <input\n id=\"isActive\"\n type=\"checkbox\"\n class=\"checkbox-input\"\n formControlName=\"isActive\"\n />\n <label class=\"checkbox-label\" for=\"isActive\">\n <div class=\"checkbox-indicator\"></div>\n <div>\n <strong>Active Account</strong>\n <div style=\"font-size: 12px; color: var(--md-on-surface-variant); margin-top: 2px;\">\n User can log in and access the system\n </div>\n </div>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Role Assignment 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-user-tag\"></i>\n Role Assignment\n </h3>\n <p class=\"section-description\">Select the roles to assign to this user</p>\n </div>\n <div class=\"roles-grid\">\n @for (role of data?.availableRoles; track role.ID) {\n <div class=\"role-card\"\n [class.selected]=\"selectedRoleIds.has(role.ID)\"\n (click)=\"toggleRole(role.ID)\">\n <div class=\"role-content\">\n <div class=\"checkbox-field\">\n <input\n type=\"checkbox\"\n class=\"checkbox-input\"\n [id]=\"'role-' + role.ID\"\n [checked]=\"selectedRoleIds.has(role.ID)\"\n (change)=\"onRoleToggle(role.ID, $event)\"\n />\n <label class=\"checkbox-label\" [for]=\"'role-' + role.ID\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n <div class=\"role-info\">\n <h4 class=\"role-name\">{{ role.Name }}</h4>\n @if (role.Description) {\n <p class=\"role-description\">{{ role.Description }}</p>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"userForm.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 User' : 'Create User' }}\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":"user-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/user-management/user-dialog/user-dialog.component.ts","../../../../src/lib/user-management/user-dialog/user-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, RunView } from '@memberjunction/core';\nimport { MJUserEntity, MJRoleEntity, MJUserRoleEntity } from '@memberjunction/core-entities';\n\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { EnrolledRow, ServerRefusalReasons } from '../transaction-group-refusals';\nexport interface UserDialogData {\n user?: MJUserEntity;\n mode: 'create' | 'edit';\n availableRoles: MJRoleEntity[];\n}\n\nexport interface UserDialogResult {\n action: 'save' | 'cancel';\n user?: MJUserEntity;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-user-dialog',\n encapsulation: ViewEncapsulation.None,\n templateUrl: './user-dialog.component.html',\n styleUrls: ['./user-dialog.component.css']\n})\nexport class UserDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges {\n @Input() Data: UserDialogData | null = null;\n\n /** @deprecated Use {@link Data}. */\n @Input() set data(value: UserDialogData | null) {\n this.Data = value;\n }\n /** @deprecated Use {@link Data}. */\n get data(): UserDialogData | null {\n return this.Data;\n }\n @Input() Visible = false;\n\n /** @deprecated Use {@link Visible}. */\n @Input() set visible(value: UserDialogComponent['Visible']) {\n this.Visible = value;\n }\n /** @deprecated Use {@link Visible}. */\n get visible(): UserDialogComponent['Visible'] {\n return this.Visible;\n }\n @Output() Result = new EventEmitter<UserDialogResult>();\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 UserForm: FormGroup;\n\n /** @deprecated Use {@link UserForm}. */\n public get userForm(): FormGroup {\n return this.UserForm;\n }\n /** @deprecated Use {@link UserForm}. */\n public set userForm(value: FormGroup) {\n this.UserForm = value;\n }\n public isLoading = false;\n public error: string | null = null;\n public SelectedRoleIds = new Set<string>();\n\n /** @deprecated Use {@link SelectedRoleIds}. */\n public get selectedRoleIds() {\n return this.SelectedRoleIds;\n }\n /** @deprecated Use {@link SelectedRoleIds}. */\n public set selectedRoleIds(value) {\n this.SelectedRoleIds = value;\n }\n public ExistingUserRoles: MJUserRoleEntity[] = [];\n\n /** @deprecated Use {@link ExistingUserRoles}. */\n public get existingUserRoles(): MJUserRoleEntity[] {\n return this.ExistingUserRoles;\n }\n /** @deprecated Use {@link ExistingUserRoles}. */\n public set existingUserRoles(value: MJUserRoleEntity[]) {\n this.ExistingUserRoles = value;\n }\n\n constructor() {\n super();\n this.UserForm = this.fb.group({\n name: ['', [Validators.required, Validators.email]],\n firstName: [''],\n lastName: [''],\n email: ['', [Validators.required, Validators.email]],\n title: [''],\n type: ['User', Validators.required],\n isActive: [true]\n });\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n // Always clear state when data changes to prevent persistence bugs\n if (changes['data']) {\n this.SelectedRoleIds.clear();\n this.ExistingUserRoles = [];\n \n if (this.Data?.user && this.IsEditMode) {\n this.loadUserData();\n } else {\n this.resetForm();\n }\n }\n \n // Reset form when dialog becomes visible and not in edit mode\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.UserForm.reset({\n name: '',\n firstName: '',\n lastName: '',\n email: '',\n title: '',\n type: 'User',\n isActive: true\n });\n this.SelectedRoleIds.clear();\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 User' : 'Create New User';\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 private async loadUserData(): Promise<void> {\n if (!this.Data?.user) return;\n\n const user = this.Data.user;\n this.UserForm.patchValue({\n name: user.Name,\n firstName: user.FirstName,\n lastName: user.LastName,\n email: user.Email,\n title: user.Title,\n type: user.Type,\n isActive: user.IsActive\n });\n\n // Load existing user roles\n await this.loadExistingUserRoles(user.ID);\n }\n\n private async loadExistingUserRoles(userId: string): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJUserRoleEntity>({\n EntityName: 'MJ: User Roles',\n ExtraFilter: `UserID='${userId}'`,\n ResultType: 'entity_object'\n });\n\n if (result.Success && result.Results) {\n this.ExistingUserRoles = result.Results;\n // Pre-select existing roles\n for (const userRole of this.ExistingUserRoles) {\n this.SelectedRoleIds.add(userRole.RoleID);\n }\n }\n } catch (error) {\n console.warn('Failed to load existing user roles:', error);\n }\n }\n\n public OnRoleToggle(roleId: string, event: Event): void {\n event.stopPropagation();\n const checkbox = event.target as HTMLInputElement;\n if (checkbox.checked) {\n this.SelectedRoleIds.add(roleId);\n } else {\n this.SelectedRoleIds.delete(roleId);\n }\n }\n\n /** @deprecated Use {@link OnRoleToggle}. */\n public onRoleToggle(roleId: string, event: Event): void {\n return this.OnRoleToggle(roleId, event);\n }\n\n public ToggleRole(roleId: string): void {\n if (this.SelectedRoleIds.has(roleId)) {\n this.SelectedRoleIds.delete(roleId);\n } else {\n this.SelectedRoleIds.add(roleId);\n }\n }\n\n /** @deprecated Use {@link ToggleRole}. */\n public toggleRole(roleId: string): void {\n return this.ToggleRole(roleId);\n }\n\n public async OnSubmit(): Promise<void> {\n if (this.UserForm.invalid) {\n this.markFormGroupTouched(this.UserForm);\n return;\n }\n\n this.isLoading = true;\n this.error = null;\n\n try {\n let user: MJUserEntity;\n\n if (this.IsEditMode && this.Data?.user) {\n // Edit existing user\n user = this.Data.user;\n } else {\n // Create new user\n user = await this.metadata.GetEntityObject<MJUserEntity>('MJ: Users');\n user.NewRecord();\n }\n\n // Update user properties\n const formValue = this.UserForm.value;\n user.Name = formValue.name;\n user.FirstName = formValue.firstName;\n user.LastName = formValue.lastName;\n user.Email = formValue.email;\n user.Title = formValue.title;\n user.Type = formValue.type;\n user.IsActive = formValue.isActive;\n\n // Save user\n const saveResult = await user.Save();\n if (!saveResult) {\n throw new Error(user.LatestResult?.Message || 'Failed to save user');\n }\n\n // Handle role assignments\n await this.updateUserRoles(user.ID);\n\n this.Result.emit({ action: 'save', user });\n\n } catch (error: unknown) {\n console.error('Error saving user:', 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 private async updateUserRoles(userId: string): Promise<void> {\n try {\n // Get current role IDs from existing UserRole entities\n const existingRoleIds = new Set(this.ExistingUserRoles.map(ur => ur.RoleID));\n\n // Determine roles to add and remove\n const rolesToAdd = Array.from(this.SelectedRoleIds).filter(roleId => !existingRoleIds.has(roleId));\n const rolesToRemove = this.ExistingUserRoles.filter(userRole => !this.SelectedRoleIds.has(userRole.RoleID));\n\n if (rolesToAdd.length === 0 && rolesToRemove.length === 0) {\n return;\n }\n\n // Batch all role deletes and adds into one transactional GraphQL call\n const tg = await this.metadata.CreateTransactionGroup();\n\n // Each Delete()/Save() only ENROLS the row in the group; the write is deferred to Submit().\n // A false return therefore means the row was refused CLIENT-side and never enrolled — so\n // submitting anyway writes a PARTIAL change, or an empty one whose Submit() returns true for\n // having nothing to do, and either way the dialog closes reporting success. Same rule and\n // same reason as `UserManagementComponent.executeBulkRoleAssign`, where the transaction-group\n // semantics — and why the server-side #4282 guard is NOT what this catches — are set out in full.\n const refusals: string[] = [];\n // Enrolled rows are kept so the SERVER's reason can be read back off them below; without\n // that, the reason #4309 puts on LatestResult has nobody left to read it.\n const enrolled: EnrolledRow[] = [];\n\n for (const userRole of rolesToRemove) {\n userRole.TransactionGroup = tg;\n if (!await userRole.Delete()) {\n refusals.push(`Remove ${this.describeRole(userRole.RoleID)}: ${userRole.LatestResult?.CompleteMessage ?? 'unknown error'}`);\n }\n else {\n enrolled.push({ Label: `Remove ${this.describeRole(userRole.RoleID)}`, Entity: userRole });\n }\n }\n\n for (const roleId of rolesToAdd) {\n const userRole = await this.metadata.GetEntityObject<MJUserRoleEntity>('MJ: User Roles');\n userRole.NewRecord();\n userRole.UserID = userId;\n userRole.RoleID = roleId;\n userRole.TransactionGroup = tg;\n if (!await userRole.Save()) {\n refusals.push(`Add ${this.describeRole(roleId)}: ${userRole.LatestResult?.CompleteMessage ?? 'unknown error'}`);\n }\n else {\n enrolled.push({ Label: `Add ${this.describeRole(roleId)}`, Entity: userRole });\n }\n }\n\n if (refusals.length > 0) {\n // Nothing was written: the refused rows never enrolled, and the rest are still only queued\n // because Submit() is not reached.\n throw new Error(`Failed to update user roles — no role changes were made.\\n${refusals.join('\\n')}`);\n }\n\n if (!await tg.Submit()) {\n // Every row enrolled, so this is a SERVER-side refusal (or a rollback). Since #4309 the\n // server says which row and why, and that reason is now on each entity's LatestResult.\n const reasons = ServerRefusalReasons(enrolled);\n throw new Error(reasons.length > 0\n ? `Failed to update user roles — all changes have been rolled back.\\n${reasons.join('\\n')}`\n : 'Failed to update user roles — all changes have been rolled back');\n }\n } catch (error) {\n console.error('Error updating user roles:', error);\n throw error;\n }\n }\n\n /** Names a role for a refusal message; falls back to the ID when the catalog has no match. */\n private describeRole(roleId: string): string {\n return this.Data?.availableRoles.find(r => UUIDsEqual(r.ID, roleId))?.Name ?? roleId;\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-user\"></i>\n {{ isEditMode ? 'Edit User' : 'Create New User' }}\n </h2>\n <p class=\"dialog-subtitle\">\n {{ isEditMode ? 'Update user information and role assignments' : 'Add a new user 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]=\"userForm\" (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-id-card\"></i>\n Basic Information\n </h3>\n <p class=\"section-description\">Enter the user's personal and contact details</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"name\">Username/Email</label>\n <input\n id=\"name\"\n type=\"email\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"john@company.com\"\n [class.error]=\"userForm.get('name')?.invalid && userForm.get('name')?.touched\"\n />\n @if (userForm.get('name')?.invalid && userForm.get('name')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (userForm.get('name')?.errors?.['required']) {\n Username/Email is required\n }\n @if (userForm.get('name')?.errors?.['email']) {\n Please enter a valid email address\n }\n </div>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"firstName\">First Name</label>\n <input\n id=\"firstName\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"firstName\"\n placeholder=\"John\"\n />\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"lastName\">Last Name</label>\n <input\n id=\"lastName\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"lastName\"\n placeholder=\"Doe\"\n />\n </div>\n </div>\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"email\">Email Address</label>\n <input\n id=\"email\"\n type=\"email\"\n class=\"field-input\"\n formControlName=\"email\"\n placeholder=\"john@company.com\"\n [class.error]=\"userForm.get('email')?.invalid && userForm.get('email')?.touched\"\n />\n @if (userForm.get('email')?.invalid && userForm.get('email')?.touched) {\n <div class=\"field-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n @if (userForm.get('email')?.errors?.['required']) {\n Email address is required\n }\n @if (userForm.get('email')?.errors?.['email']) {\n Please enter a valid email address\n }\n </div>\n }\n </div>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"title\">Job Title</label>\n <input\n id=\"title\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"title\"\n placeholder=\"Software Engineer\"\n />\n </div>\n </div>\n </div>\n </div>\n <!-- User Settings 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 User Settings\n </h3>\n <p class=\"section-description\">Configure user type and account status</p>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"type\">User Type</label>\n <select id=\"type\" class=\"field-select\" formControlName=\"type\">\n <option value=\"User\">Standard User</option>\n <option value=\"Owner\">System Owner</option>\n </select>\n </div>\n <div class=\"form-field\">\n <div class=\"checkbox-field\">\n <input\n id=\"isActive\"\n type=\"checkbox\"\n class=\"checkbox-input\"\n formControlName=\"isActive\"\n />\n <label class=\"checkbox-label\" for=\"isActive\">\n <div class=\"checkbox-indicator\"></div>\n <div>\n <strong>Active Account</strong>\n <div style=\"font-size: 12px; color: var(--md-on-surface-variant); margin-top: 2px;\">\n User can log in and access the system\n </div>\n </div>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Role Assignment 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-user-tag\"></i>\n Role Assignment\n </h3>\n <p class=\"section-description\">Select the roles to assign to this user</p>\n </div>\n <div class=\"roles-grid\">\n @for (role of data?.availableRoles; track role.ID) {\n <div class=\"role-card\"\n [class.selected]=\"selectedRoleIds.has(role.ID)\"\n (click)=\"toggleRole(role.ID)\">\n <div class=\"role-content\">\n <div class=\"checkbox-field\">\n <input\n type=\"checkbox\"\n class=\"checkbox-input\"\n [id]=\"'role-' + role.ID\"\n [checked]=\"selectedRoleIds.has(role.ID)\"\n (change)=\"onRoleToggle(role.ID, $event)\"\n />\n <label class=\"checkbox-label\" [for]=\"'role-' + role.ID\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n <div class=\"role-info\">\n <h4 class=\"role-name\">{{ role.Name }}</h4>\n @if (role.Description) {\n <p class=\"role-description\">{{ role.Description }}</p>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"userForm.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 User' : 'Create User' }}\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"]}
@@ -20,8 +20,12 @@ export type UserStatusFilter = (typeof VALID_USER_STATUS_FILTERS)[number];
20
20
  */
21
21
  export declare const USER_AGENT_CONTEXT_NAME_LIST_CAP = 25;
22
22
  /** Type-guard for a user-status filter string. Keeps the SwitchUserStatusFilter tool tolerant. */
23
+ export declare function IsValidUserStatusFilter(value: unknown): value is UserStatusFilter;
24
+ /** @deprecated Use {@link IsValidUserStatusFilter}. */
23
25
  export declare function isValidUserStatusFilter(value: unknown): value is UserStatusFilter;
24
26
  /** Cap a list of names to {@link USER_AGENT_CONTEXT_NAME_LIST_CAP}. Pure + deterministic. */
27
+ export declare function CapUserNames(names: readonly string[]): string[];
28
+ /** @deprecated Use {@link CapUserNames}. */
25
29
  export declare function capUserNames(names: readonly string[]): string[];
26
30
  /**
27
31
  * A minimal, NON-SENSITIVE descriptor of a user, supplied by the component so the pure
@@ -57,12 +61,16 @@ export type NamedLookupResult<T> = {
57
61
  * Pure + deterministic over the supplied candidate list. On a miss, returns a clear error
58
62
  * listing a sample of available names so the agent can correct itself.
59
63
  */
64
+ export declare function ResolveUserByIDOrName(input: string, candidates: readonly UserNameCandidate[]): NamedLookupResult<UserNameCandidate>;
65
+ /** @deprecated Use {@link ResolveUserByIDOrName}. */
60
66
  export declare function resolveUserByIDOrName(input: string, candidates: readonly UserNameCandidate[]): NamedLookupResult<UserNameCandidate>;
61
67
  /**
62
68
  * Resolve an agent-supplied role reference (id or display name) against the loaded roles,
63
69
  * tolerantly: exact ID → exact name → first contains. Backs FilterUsersByRole so the agent
64
70
  * can say either the role name or the role id.
65
71
  */
72
+ export declare function ResolveRoleByIDOrName(input: string, candidates: readonly RoleNameCandidate[]): NamedLookupResult<RoleNameCandidate>;
73
+ /** @deprecated Use {@link ResolveRoleByIDOrName}. */
66
74
  export declare function resolveRoleByIDOrName(input: string, candidates: readonly RoleNameCandidate[]): NamedLookupResult<RoleNameCandidate>;
67
75
  /**
68
76
  * The plain, component-supplied snapshot used to build the user-management agent context.
@@ -103,5 +111,7 @@ export interface UserManagementAgentContextInput {
103
111
  * stays unit-testable and decoupled from change-detection timing. Bounds every name list and
104
112
  * emits a companion total-count when truncated.
105
113
  */
114
+ export declare function BuildUserManagementAgentContext(input: UserManagementAgentContextInput): Record<string, unknown>;
115
+ /** @deprecated Use {@link BuildUserManagementAgentContext}. */
106
116
  export declare function buildUserManagementAgentContext(input: UserManagementAgentContextInput): Record<string, unknown>;
107
117
  //# sourceMappingURL=user-management-agent-context.d.ts.map