@memberjunction/ng-archive-manager 6.1.0-edge.4 → 6.1.0-edge.6

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.
@@ -623,7 +623,7 @@ export class ArchiveConfigAdminComponent extends BaseAngularComponent {
623
623
  const md = this.ProviderToUse;
624
624
  const entity = await md.GetEntityObject('MJ: Archive Configurations', md.CurrentUser);
625
625
  if (!this.SelectedConfig.ID.startsWith('new-')) {
626
- await entity.InnerLoad(CompositeKey.FromKeyValuePair('ID', this.SelectedConfig.ID));
626
+ await entity.InnerLoad(CompositeKey.FromID(this.SelectedConfig.ID));
627
627
  }
628
628
  else {
629
629
  entity.NewRecord();
@@ -661,7 +661,7 @@ export class ArchiveConfigAdminComponent extends BaseAngularComponent {
661
661
  const md = this.ProviderToUse;
662
662
  const entity = await md.GetEntityObject('MJ: Archive Configuration Entities', md.CurrentUser);
663
663
  if (!configEntity.IsNew) {
664
- await entity.InnerLoad(CompositeKey.FromKeyValuePair('ID', configEntity.ID));
664
+ await entity.InnerLoad(CompositeKey.FromID(configEntity.ID));
665
665
  }
666
666
  else {
667
667
  entity.NewRecord();
@@ -717,7 +717,7 @@ export class ArchiveConfigAdminComponent extends BaseAngularComponent {
717
717
  i0.ɵɵconditional(ctx.IsLoading ? 1 : -1);
718
718
  i0.ɵɵadvance();
719
719
  i0.ɵɵconditional(!ctx.IsLoading ? 2 : -1);
720
- } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.LoadingComponent, i3.MJEmptyStateComponent], styles: [".config-admin[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.config-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px;\n}\n\n\n\n.config-layout[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n\n\n.config-list-panel[_ngcontent-%COMP%] {\n width: 35%;\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.config-list-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n\n h2 {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.config-card-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n\n\n.config-card[_ngcontent-%COMP%] {\n padding: 12px 14px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n cursor: pointer;\n transition: border-color 0.15s ease, background 0.15s ease;\n\n &:hover {\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n\n &.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, var(--mj-bg-surface));\n }\n}\n\n.config-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n\n.config-card-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.config-status-badge[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.status-active[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.status-inactive[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.config-card-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 14px;\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n\n i {\n margin-right: 4px;\n }\n}\n\n.config-card-date[_ngcontent-%COMP%] {\n margin-top: 6px;\n font-size: 0.73rem;\n color: var(--mj-text-muted);\n\n i {\n margin-right: 4px;\n }\n}\n\n.config-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n text-align: center;\n\n i {\n font-size: 2rem;\n margin-bottom: 12px;\n }\n\n p {\n margin: 0;\n font-size: 0.85rem;\n }\n}\n\n\n\n.config-detail-panel[_ngcontent-%COMP%] {\n width: 65%;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n}\n\n.config-detail-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n color: var(--mj-text-muted);\n\n i {\n font-size: 1.5rem;\n margin-bottom: 8px;\n }\n\n p {\n margin: 0;\n font-size: 0.85rem;\n }\n}\n\n.config-detail-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.config-detail-content[_ngcontent-%COMP%] {\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n\n\n.detail-section[_ngcontent-%COMP%] {\n h3 {\n margin: 0 0 12px;\n font-size: 0.9rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n\n i {\n color: var(--mj-brand-primary);\n }\n }\n}\n\n.detail-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n\n h3 {\n margin-bottom: 0;\n padding-bottom: 0;\n border-bottom: none;\n }\n}\n\n.detail-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n margin-bottom: 10px;\n\n .detail-field {\n flex: 1;\n }\n}\n\n.detail-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-bottom: 10px;\n\n label {\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n }\n}\n\n.detail-input[_ngcontent-%COMP%] {\n padding: 7px 10px;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n transition: border-color 0.15s ease;\n\n &:focus {\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n}\n\n.detail-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n font-family: inherit;\n}\n\n.detail-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding-top: 2px;\n\n input[type=\"checkbox\"] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s ease;\n position: relative;\n\n &:checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n\n &::after {\n content: '';\n position: absolute;\n left: 4px;\n top: 1px;\n width: 6px;\n height: 10px;\n border: solid var(--mj-text-inverse, white);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n }\n}\n\n\n\n.entity-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n}\n\n.entity-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.82rem;\n\n th {\n padding: 8px 10px;\n text-align: left;\n font-weight: 600;\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: middle;\n }\n\n tr:last-child td {\n border-bottom: none;\n }\n}\n\n.entity-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 4px 6px;\n font-size: 0.82rem;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 3px;\n outline: none;\n\n &:focus {\n border-color: var(--mj-border-focus);\n }\n}\n\n.entity-input-sm[_ngcontent-%COMP%] {\n width: 70px;\n}\n\n\n\n.entity-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s ease;\n position: relative;\n\n &:checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n\n &::after {\n content: '';\n position: absolute;\n left: 4px;\n top: 1px;\n width: 6px;\n height: 10px;\n border: solid var(--mj-text-inverse, white);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n}\n\n.entity-empty[_ngcontent-%COMP%] {\n text-align: center;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n border: 1px dashed var(--mj-border-default);\n border-radius: 6px;\n\n p {\n margin: 0;\n }\n}\n\n\n\n.config-status[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n border-radius: 6px;\n font-size: 0.85rem;\n\n i {\n font-size: 1rem;\n }\n}\n\n.status-success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.status-error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n\n\n.detail-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n font-size: 0.85rem;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease, opacity 0.15s ease;\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n}\n\n.btn-sm[_ngcontent-%COMP%] {\n padding: 5px 10px;\n font-size: 0.78rem;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n\n &:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n\n &:active:not(:disabled) {\n background: var(--mj-brand-primary-active);\n }\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-border-default);\n\n &:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n }\n}\n\n.btn-outline[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n\n &:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n }\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px 6px;\n border-radius: 4px;\n transition: color 0.15s ease, background 0.15s ease;\n}\n\n.btn-icon-danger[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n\n &:hover {\n color: var(--mj-status-error);\n background: var(--mj-status-error-bg);\n }\n}"], changeDetection: 0 });
720
+ } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.LoadingComponent, i3.MJEmptyStateComponent], styles: [".config-admin[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n\n.config-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px;\n}\n\n\n.config-layout[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n\n.config-list-panel[_ngcontent-%COMP%] {\n width: 35%;\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.config-list-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n\n h2 {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.config-card-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n\n.config-card[_ngcontent-%COMP%] {\n padding: 12px 14px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n cursor: pointer;\n transition: border-color 0.15s ease, background 0.15s ease;\n\n &:hover {\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n\n &.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, var(--mj-bg-surface));\n }\n}\n\n.config-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n\n.config-card-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.config-status-badge[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.status-active[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.status-inactive[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.config-card-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 14px;\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n\n i {\n margin-right: 4px;\n }\n}\n\n.config-card-date[_ngcontent-%COMP%] {\n margin-top: 6px;\n font-size: 0.73rem;\n color: var(--mj-text-muted);\n\n i {\n margin-right: 4px;\n }\n}\n\n.config-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n text-align: center;\n\n i {\n font-size: 2rem;\n margin-bottom: 12px;\n }\n\n p {\n margin: 0;\n font-size: 0.85rem;\n }\n}\n\n\n.config-detail-panel[_ngcontent-%COMP%] {\n width: 65%;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n}\n\n.config-detail-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n color: var(--mj-text-muted);\n\n i {\n font-size: 1.5rem;\n margin-bottom: 8px;\n }\n\n p {\n margin: 0;\n font-size: 0.85rem;\n }\n}\n\n.config-detail-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.config-detail-content[_ngcontent-%COMP%] {\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n\n.detail-section[_ngcontent-%COMP%] {\n h3 {\n margin: 0 0 12px;\n font-size: 0.9rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n\n i {\n color: var(--mj-brand-primary);\n }\n }\n}\n\n.detail-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n\n h3 {\n margin-bottom: 0;\n padding-bottom: 0;\n border-bottom: none;\n }\n}\n\n.detail-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n margin-bottom: 10px;\n\n .detail-field {\n flex: 1;\n }\n}\n\n.detail-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-bottom: 10px;\n\n label {\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n }\n}\n\n.detail-input[_ngcontent-%COMP%] {\n padding: 7px 10px;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n transition: border-color 0.15s ease;\n\n &:focus {\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n}\n\n.detail-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n font-family: inherit;\n}\n\n.detail-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding-top: 2px;\n\n input[type=\"checkbox\"] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s ease;\n position: relative;\n\n &:checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n\n &::after {\n content: '';\n position: absolute;\n left: 4px;\n top: 1px;\n width: 6px;\n height: 10px;\n border: solid var(--mj-text-inverse, white);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n }\n}\n\n\n.entity-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n}\n\n.entity-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.82rem;\n\n th {\n padding: 8px 10px;\n text-align: left;\n font-weight: 600;\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: middle;\n }\n\n tr:last-child td {\n border-bottom: none;\n }\n}\n\n.entity-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 4px 6px;\n font-size: 0.82rem;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 3px;\n outline: none;\n\n &:focus {\n border-color: var(--mj-border-focus);\n }\n}\n\n.entity-input-sm[_ngcontent-%COMP%] {\n width: 70px;\n}\n\n\n.entity-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s ease;\n position: relative;\n\n &:checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n\n &::after {\n content: '';\n position: absolute;\n left: 4px;\n top: 1px;\n width: 6px;\n height: 10px;\n border: solid var(--mj-text-inverse, white);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n}\n\n.entity-empty[_ngcontent-%COMP%] {\n text-align: center;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n border: 1px dashed var(--mj-border-default);\n border-radius: 6px;\n\n p {\n margin: 0;\n }\n}\n\n\n.config-status[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n border-radius: 6px;\n font-size: 0.85rem;\n\n i {\n font-size: 1rem;\n }\n}\n\n.status-success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.status-error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n\n.detail-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n font-size: 0.85rem;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease, opacity 0.15s ease;\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n}\n\n.btn-sm[_ngcontent-%COMP%] {\n padding: 5px 10px;\n font-size: 0.78rem;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n\n &:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n\n &:active:not(:disabled) {\n background: var(--mj-brand-primary-active);\n }\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-border-default);\n\n &:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n }\n}\n\n.btn-outline[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n\n &:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n }\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px 6px;\n border-radius: 4px;\n transition: color 0.15s ease, background 0.15s ease;\n}\n\n.btn-icon-danger[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n\n &:hover {\n color: var(--mj-status-error);\n background: var(--mj-status-error-bg);\n }\n}"], changeDetection: 0 });
721
721
  }
722
722
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ArchiveConfigAdminComponent, [{
723
723
  type: Component,
@@ -1 +1 @@
1
- {"version":3,"file":"archive-config-admin.component.js","sourceRoot":"","sources":["../../../src/lib/archive-config/archive-config-admin.component.ts","../../../src/lib/archive-config/archive-config-admin.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n OnInit,\n OnDestroy,\n inject,\n} from '@angular/core';\nimport { CompositeKey, RunView } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport {\n MJArchiveConfigurationEntity,\n MJArchiveConfigurationEntityEntity,\n MJArchiveConfigurationEntityType,\n MJArchiveConfigurationEntityEntityType,\n} from '@memberjunction/core-entities';\n\ntype ArchiveStatus = MJArchiveConfigurationEntityType['Status'];\ntype ArchiveMode = MJArchiveConfigurationEntityType['DefaultMode'];\ntype EntityMode = MJArchiveConfigurationEntityEntityType['Mode'];\n\n/** Represents an archive configuration record */\nexport interface ArchiveConfig {\n ID: string;\n Name: string;\n Description: string;\n Status: ArchiveStatus;\n StorageAccountID: string;\n StorageAccountName: string;\n RootPath: string;\n DefaultRetentionDays: number;\n DefaultBatchSize: number;\n DefaultMode: ArchiveMode;\n ArchiveRelatedRecordChanges: boolean;\n IsDirty: boolean;\n}\n\n/** Represents an entity within a configuration */\nexport interface ArchiveConfigEntity {\n ID: string;\n ArchiveConfigurationID: string;\n EntityName: string;\n Mode: EntityMode;\n RetentionDays: number;\n BatchSize: number;\n DateField: string;\n IsActive: boolean;\n IsNew: boolean;\n IsDirty: boolean;\n}\n\n/** Storage account option for the dropdown */\nexport interface StorageAccountOption {\n ID: string;\n Name: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-archive-config-admin',\n templateUrl: './archive-config-admin.component.html',\n styleUrls: ['./archive-config-admin.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ArchiveConfigAdminComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n\n /** All configurations */\n Configs: ArchiveConfig[] = [];\n\n /** Currently selected configuration */\n SelectedConfig: ArchiveConfig | null = null;\n\n /** Entities for the selected configuration */\n ConfigEntities: ArchiveConfigEntity[] = [];\n\n /** Available storage accounts for dropdown */\n StorageAccounts: StorageAccountOption[] = [];\n\n /** Available archive modes */\n ArchiveModes: string[] = ['StripFields', 'SoftDelete', 'HardDelete', 'ArchiveOnly'];\n\n /** Whether the list is loading */\n IsLoading = true;\n\n /** Whether the detail panel is loading */\n IsDetailLoading = false;\n\n /** Whether a save operation is in progress */\n IsSaving = false;\n\n /** Status message for feedback */\n StatusMessage = '';\n\n /** Status type for styling */\n StatusType: 'success' | 'error' | '' = '';\n\n private destroyed = false;\n\n ngOnInit(): void {\n this.loadAllData();\n }\n\n ngOnDestroy(): void {\n this.destroyed = true;\n }\n\n /** Select a configuration and load its entities */\n async SelectConfig(config: ArchiveConfig): Promise<void> {\n this.SelectedConfig = { ...config };\n this.clearStatus();\n await this.loadConfigEntities(config.ID);\n }\n\n /** Check if a config is the currently selected one */\n IsSelectedConfig(config: ArchiveConfig): boolean {\n return UUIDsEqual(this.SelectedConfig?.ID, config.ID);\n }\n\n /** Add a new empty entity row */\n AddEntity(): void {\n if (!this.SelectedConfig) return;\n\n const newEntity: ArchiveConfigEntity = {\n ID: `new-${Date.now()}`,\n ArchiveConfigurationID: this.SelectedConfig.ID,\n EntityName: '',\n Mode: this.SelectedConfig.DefaultMode ?? 'StripFields',\n RetentionDays: this.SelectedConfig.DefaultRetentionDays || 365,\n BatchSize: this.SelectedConfig.DefaultBatchSize || 100,\n DateField: '__mj_CreatedAt',\n IsActive: true,\n IsNew: true,\n IsDirty: true,\n };\n this.ConfigEntities = [...this.ConfigEntities, newEntity];\n this.cdr.markForCheck();\n }\n\n /** Remove an entity row */\n RemoveEntity(entity: ArchiveConfigEntity): void {\n this.ConfigEntities = this.ConfigEntities.filter((e) => !UUIDsEqual(e.ID, entity.ID));\n this.cdr.markForCheck();\n }\n\n /** Mark an entity as dirty when edited */\n OnEntityChanged(entity: ArchiveConfigEntity): void {\n entity.IsDirty = true;\n this.cdr.markForCheck();\n }\n\n /** Mark the selected config as dirty */\n OnConfigFieldChanged(): void {\n if (this.SelectedConfig) {\n this.SelectedConfig.IsDirty = true;\n this.cdr.markForCheck();\n }\n }\n\n /** Save the selected configuration and its entities */\n async Save(): Promise<void> {\n if (!this.SelectedConfig) return;\n\n this.IsSaving = true;\n this.clearStatus();\n this.cdr.markForCheck();\n\n try {\n await this.saveConfiguration();\n await this.saveConfigEntities();\n this.setStatus('Configuration saved successfully.', 'success');\n await this.refreshConfigList();\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : 'Save failed. Please try again.';\n this.setStatus(message, 'error');\n } finally {\n this.IsSaving = false;\n this.markForCheckIfAlive();\n }\n }\n\n /** Cancel changes and reload the selected config */\n async Cancel(): Promise<void> {\n if (!this.SelectedConfig) return;\n\n const configId = this.SelectedConfig.ID;\n this.clearStatus();\n\n const original = this.Configs.find((c) => UUIDsEqual(c.ID, configId));\n if (original) {\n this.SelectedConfig = { ...original };\n await this.loadConfigEntities(configId);\n }\n }\n\n /** Add a new configuration */\n AddConfiguration(): void {\n const newConfig: ArchiveConfig = {\n ID: `new-${Date.now()}`,\n Name: 'New Configuration',\n Description: '',\n Status: 'Disabled',\n StorageAccountID: '',\n StorageAccountName: '',\n RootPath: '/archives',\n DefaultRetentionDays: 365,\n DefaultBatchSize: 100,\n DefaultMode: 'StripFields',\n ArchiveRelatedRecordChanges: false,\n IsDirty: true,\n };\n this.Configs = [newConfig, ...this.Configs];\n this.SelectConfig(newConfig);\n }\n\n /** Get a display label for the status */\n GetStatusLabel(status: string | undefined): string {\n switch (status) {\n case 'Idle': return 'Idle';\n case 'Running': return 'Running';\n case 'Error': return 'Error';\n default: return 'Disabled';\n }\n }\n\n /** Load all initial data using batched RunViews */\n private async loadAllData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [configResult, storageResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Archive Configurations',\n ExtraFilter: '',\n OrderBy: 'Name',\n ResultType: 'simple',\n },\n {\n EntityName: 'MJ: File Storage Accounts',\n ExtraFilter: '',\n OrderBy: 'Name',\n ResultType: 'simple',\n Fields: ['ID', 'Name'],\n },\n ]);\n\n this.Configs = this.mapConfigRecords(configResult);\n this.StorageAccounts = this.mapStorageAccounts(storageResult);\n\n if (this.Configs.length > 0) {\n await this.SelectConfig(this.Configs[0]);\n }\n } catch {\n this.setStatus('Failed to load configurations.', 'error');\n } finally {\n this.IsLoading = false;\n this.markForCheckIfAlive();\n }\n }\n\n /** Map raw config records to typed objects */\n private mapConfigRecords(result: { Success: boolean; Results: Record<string, unknown>[] }): ArchiveConfig[] {\n if (!result.Success) return [];\n return result.Results.map((r) => ({\n ID: String(r['ID'] ?? ''),\n Name: String(r['Name'] ?? ''),\n Description: String(r['Description'] ?? ''),\n Status: (r['Status'] as ArchiveStatus) ?? 'Disabled',\n StorageAccountID: String(r['StorageAccountID'] ?? ''),\n StorageAccountName: String(r['StorageAccount'] ?? ''),\n RootPath: String(r['RootPath'] ?? ''),\n DefaultRetentionDays: Number(r['DefaultRetentionDays'] ?? 365),\n DefaultBatchSize: Number(r['DefaultBatchSize'] ?? 100),\n DefaultMode: (r['DefaultMode'] as ArchiveMode) ?? 'StripFields',\n ArchiveRelatedRecordChanges: Boolean(r['ArchiveRelatedRecordChanges']),\n IsDirty: false,\n }));\n }\n\n /** Map raw storage account records */\n private mapStorageAccounts(result: { Success: boolean; Results: Record<string, unknown>[] }): StorageAccountOption[] {\n if (!result.Success) return [];\n return result.Results.map((r) => ({\n ID: String(r['ID'] ?? ''),\n Name: String(r['Name'] ?? ''),\n }));\n }\n\n /** Load entities for a specific configuration */\n private async loadConfigEntities(configId: string): Promise<void> {\n this.IsDetailLoading = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const escapedId = configId.replace(/'/g, \"''\");\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: 'MJ: Archive Configuration Entities',\n ExtraFilter: `ArchiveConfigurationID='${escapedId}'`,\n OrderBy: 'Entity',\n ResultType: 'simple',\n });\n\n this.ConfigEntities = this.mapEntityRecords(result);\n } catch {\n this.ConfigEntities = [];\n } finally {\n this.IsDetailLoading = false;\n this.markForCheckIfAlive();\n }\n }\n\n /** Map raw entity records to typed objects */\n private mapEntityRecords(result: { Success: boolean; Results: Record<string, unknown>[] }): ArchiveConfigEntity[] {\n if (!result.Success) return [];\n return result.Results.map((r) => ({\n ID: String(r['ID'] ?? ''),\n ArchiveConfigurationID: String(r['ArchiveConfigurationID'] ?? ''),\n EntityName: String(r['Entity'] ?? ''),\n Mode: (r['Mode'] as EntityMode) ?? 'StripFields',\n RetentionDays: Number(r['RetentionDays'] ?? 365),\n BatchSize: Number(r['BatchSize'] ?? 100),\n DateField: String(r['DateField'] ?? '__mj_CreatedAt'),\n IsActive: Boolean(r['IsActive']),\n IsNew: false,\n IsDirty: false,\n }));\n }\n\n /** Save the configuration record using strongly-typed entity */\n private async saveConfiguration(): Promise<void> {\n if (!this.SelectedConfig?.IsDirty) return;\n\n const md = this.ProviderToUse;\n const entity = await md.GetEntityObject<MJArchiveConfigurationEntity>('MJ: Archive Configurations', md.CurrentUser);\n\n if (!this.SelectedConfig.ID.startsWith('new-')) {\n await entity.InnerLoad(CompositeKey.FromKeyValuePair('ID', this.SelectedConfig.ID));\n } else {\n entity.NewRecord();\n }\n\n entity.Name = this.SelectedConfig.Name;\n entity.Description = this.SelectedConfig.Description;\n entity.Status = this.SelectedConfig.Status ?? 'Disabled';\n if (this.SelectedConfig.StorageAccountID) {\n entity.StorageAccountID = this.SelectedConfig.StorageAccountID;\n }\n entity.RootPath = this.SelectedConfig.RootPath;\n entity.DefaultRetentionDays = this.SelectedConfig.DefaultRetentionDays;\n entity.DefaultBatchSize = this.SelectedConfig.DefaultBatchSize;\n entity.DefaultMode = this.SelectedConfig.DefaultMode ?? 'StripFields';\n entity.ArchiveRelatedRecordChanges = this.SelectedConfig.ArchiveRelatedRecordChanges;\n\n const saved = await entity.Save();\n if (!saved) {\n throw new Error('Failed to save configuration.');\n }\n\n // Update the ID if this was a new record\n if (this.SelectedConfig.ID.startsWith('new-')) {\n this.SelectedConfig.ID = entity.ID;\n }\n this.SelectedConfig.IsDirty = false;\n }\n\n /** Save all dirty/new entity records */\n private async saveConfigEntities(): Promise<void> {\n const dirtyEntities = this.ConfigEntities.filter((e) => e.IsDirty);\n for (const configEntity of dirtyEntities) {\n await this.saveConfigEntity(configEntity);\n }\n }\n\n /** Save a single config entity record using strongly-typed entity */\n private async saveConfigEntity(configEntity: ArchiveConfigEntity): Promise<void> {\n const md = this.ProviderToUse;\n const entity = await md.GetEntityObject<MJArchiveConfigurationEntityEntity>('MJ: Archive Configuration Entities', md.CurrentUser);\n\n if (!configEntity.IsNew) {\n await entity.InnerLoad(CompositeKey.FromKeyValuePair('ID', configEntity.ID));\n } else {\n entity.NewRecord();\n }\n\n entity.ArchiveConfigurationID = configEntity.ArchiveConfigurationID;\n entity.Mode = configEntity.Mode ?? null;\n entity.RetentionDays = configEntity.RetentionDays;\n entity.BatchSize = configEntity.BatchSize;\n entity.DateField = configEntity.DateField;\n entity.IsActive = configEntity.IsActive;\n\n const saved = await entity.Save();\n if (!saved) {\n throw new Error(`Failed to save entity \"${configEntity.EntityName}\".`);\n }\n\n configEntity.IsDirty = false;\n configEntity.IsNew = false;\n }\n\n /** Refresh the config list after a save */\n private async refreshConfigList(): Promise<void> {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: 'MJ: Archive Configurations',\n ExtraFilter: '',\n OrderBy: 'Name',\n ResultType: 'simple',\n });\n this.Configs = this.mapConfigRecords(result);\n }\n\n /** Set a status message */\n private setStatus(message: string, type: 'success' | 'error'): void {\n this.StatusMessage = message;\n this.StatusType = type;\n }\n\n /** Clear status message */\n private clearStatus(): void {\n this.StatusMessage = '';\n this.StatusType = '';\n }\n\n /** Mark for check only if not destroyed */\n private markForCheckIfAlive(): void {\n if (!this.destroyed) {\n this.cdr.markForCheck();\n }\n }\n}\n","<div class=\"config-admin\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"config-loading\">\n <mj-loading text=\"Loading configurations...\"></mj-loading>\n </div>\n }\n\n @if (!IsLoading) {\n <div class=\"config-layout\">\n <!-- Left panel: Config list -->\n <div class=\"config-list-panel\">\n <div class=\"config-list-header\">\n <h2>Archive Configurations</h2>\n <button class=\"btn btn-primary btn-sm\" (click)=\"AddConfiguration()\">\n <i class=\"fa-solid fa-plus\"></i>\n Add Configuration\n </button>\n </div>\n\n <div class=\"config-card-list\">\n @for (config of Configs; track config.ID) {\n <div\n class=\"config-card\"\n [class.selected]=\"IsSelectedConfig(config)\"\n (click)=\"SelectConfig(config)\"\n (keydown.enter)=\"SelectConfig(config)\"\n tabindex=\"0\"\n role=\"button\">\n <div class=\"config-card-header\">\n <span class=\"config-card-name\">{{ config.Name }}</span>\n <span\n class=\"config-status-badge\"\n [class.status-active]=\"config.Status === 'Idle' || config.Status === 'Running'\"\n [class.status-inactive]=\"config.Status === 'Disabled' || config.Status === 'Error'\">\n {{ GetStatusLabel(config.Status) }}\n </span>\n </div>\n <div class=\"config-card-meta\">\n <span><i class=\"fa-solid fa-database\"></i> {{ config.StorageAccountName || 'No storage' }}</span>\n <span><i class=\"fa-solid fa-folder\"></i> {{ config.RootPath }}</span>\n </div>\n <div class=\"config-card-date\">\n <span class=\"config-status-mode\"><i class=\"fa-solid fa-sliders\"></i> {{ config.DefaultMode }}</span>\n </div>\n </div>\n }\n\n @if (Configs.length === 0) {\n <mj-empty-state class=\"config-empty\" Size=\"compact\"\n Icon=\"fa-solid fa-folder-open\"\n Title=\"No configurations found\"\n Message=\"Create one to get started.\" />\n }\n </div>\n </div>\n\n <!-- Right panel: Detail -->\n <div class=\"config-detail-panel\">\n @if (!SelectedConfig) {\n <mj-empty-state class=\"config-detail-placeholder\"\n Icon=\"fa-solid fa-hand-pointer\"\n Title=\"No configuration selected\"\n Message=\"Select a configuration to view details\" />\n }\n\n @if (SelectedConfig) {\n @if (IsDetailLoading) {\n <div class=\"config-detail-loading\">\n <mj-loading text=\"Loading details...\" size=\"small\"></mj-loading>\n </div>\n }\n\n @if (!IsDetailLoading) {\n <div class=\"config-detail-content\">\n <!-- Header section -->\n <div class=\"detail-section\">\n <div class=\"detail-field\">\n <label for=\"config-name\">Name</label>\n <input\n id=\"config-name\"\n type=\"text\"\n [(ngModel)]=\"SelectedConfig.Name\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n <div class=\"detail-field\">\n <label>Active</label>\n <div class=\"detail-checkbox\">\n <input\n type=\"checkbox\"\n [checked]=\"SelectedConfig.Status === 'Idle'\"\n (change)=\"SelectedConfig.Status = SelectedConfig.Status === 'Idle' ? 'Disabled' : 'Idle'; OnConfigFieldChanged()\" />\n </div>\n </div>\n <div class=\"detail-field\">\n <label for=\"config-desc\">Description</label>\n <textarea\n id=\"config-desc\"\n [(ngModel)]=\"SelectedConfig.Description\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input detail-textarea\"\n rows=\"2\"></textarea>\n </div>\n </div>\n\n <!-- Storage section -->\n <div class=\"detail-section\">\n <h3><i class=\"fa-solid fa-hard-drive\"></i> Storage</h3>\n <div class=\"detail-row\">\n <div class=\"detail-field\">\n <label for=\"config-storage\">Storage Account</label>\n <select\n id=\"config-storage\"\n [(ngModel)]=\"SelectedConfig.StorageAccountID\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\">\n <option value=\"\">-- Select --</option>\n @for (account of StorageAccounts; track account.ID) {\n <option [value]=\"account.ID\">{{ account.Name }}</option>\n }\n </select>\n </div>\n <div class=\"detail-field\">\n <label for=\"config-path\">Root Path</label>\n <input\n id=\"config-path\"\n type=\"text\"\n [(ngModel)]=\"SelectedConfig.RootPath\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n </div>\n </div>\n\n <!-- Defaults section -->\n <div class=\"detail-section\">\n <h3><i class=\"fa-solid fa-sliders\"></i> Defaults</h3>\n <div class=\"detail-row\">\n <div class=\"detail-field\">\n <label for=\"config-retention\">Retention Days</label>\n <input\n id=\"config-retention\"\n type=\"number\"\n [(ngModel)]=\"SelectedConfig.DefaultRetentionDays\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n <div class=\"detail-field\">\n <label for=\"config-batch\">Batch Size</label>\n <input\n id=\"config-batch\"\n type=\"number\"\n [(ngModel)]=\"SelectedConfig.DefaultBatchSize\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n </div>\n <div class=\"detail-row\">\n <div class=\"detail-field\">\n <label for=\"config-mode\">Archive Mode</label>\n <select\n id=\"config-mode\"\n [(ngModel)]=\"SelectedConfig.DefaultMode\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\">\n @for (mode of ArchiveModes; track mode) {\n <option [value]=\"mode\">{{ mode }}</option>\n }\n </select>\n </div>\n <div class=\"detail-field\">\n <label>Archive Record Changes</label>\n <div class=\"detail-checkbox\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"SelectedConfig.ArchiveRelatedRecordChanges\"\n (ngModelChange)=\"OnConfigFieldChanged()\" />\n </div>\n </div>\n </div>\n </div>\n\n <!-- Entities section -->\n <div class=\"detail-section\">\n <div class=\"detail-section-header\">\n <h3><i class=\"fa-solid fa-table\"></i> Entities</h3>\n <button class=\"btn btn-sm btn-outline\" (click)=\"AddEntity()\">\n <i class=\"fa-solid fa-plus\"></i> Add Entity\n </button>\n </div>\n\n @if (ConfigEntities.length > 0) {\n <div class=\"entity-table-wrapper\">\n <table class=\"entity-table\">\n <thead>\n <tr>\n <th>Entity</th>\n <th>Mode</th>\n <th>Retention</th>\n <th>Batch</th>\n <th>Date Field</th>\n <th>Active</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n @for (entity of ConfigEntities; track entity.ID) {\n <tr>\n <td>\n <input\n type=\"text\"\n [(ngModel)]=\"entity.EntityName\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input\"\n placeholder=\"Entity name\" />\n </td>\n <td>\n <select\n [(ngModel)]=\"entity.Mode\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input\">\n @for (mode of ArchiveModes; track mode) {\n <option [value]=\"mode\">{{ mode }}</option>\n }\n </select>\n </td>\n <td>\n <input\n type=\"number\"\n [(ngModel)]=\"entity.RetentionDays\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input entity-input-sm\" />\n </td>\n <td>\n <input\n type=\"number\"\n [(ngModel)]=\"entity.BatchSize\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input entity-input-sm\" />\n </td>\n <td>\n <input\n type=\"text\"\n [(ngModel)]=\"entity.DateField\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input\"\n placeholder=\"e.g. CreatedAt\" />\n </td>\n <td>\n <input\n type=\"checkbox\"\n [(ngModel)]=\"entity.IsActive\"\n (ngModelChange)=\"OnEntityChanged(entity)\" />\n </td>\n <td>\n <button\n class=\"btn-icon btn-icon-danger\"\n (click)=\"RemoveEntity(entity)\"\n title=\"Remove entity\"\n aria-label=\"Remove entity\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (ConfigEntities.length === 0) {\n <mj-empty-state class=\"entity-empty\" Size=\"compact\"\n Icon=\"\" Title=\"No entities configured. Click &quot;Add Entity&quot; to add one.\" />\n }\n </div>\n\n <!-- Status message -->\n @if (StatusMessage) {\n <div class=\"config-status\" [class.status-success]=\"StatusType === 'success'\" [class.status-error]=\"StatusType === 'error'\">\n @if (StatusType === 'success') {\n <i class=\"fa-solid fa-circle-check\"></i>\n }\n @if (StatusType === 'error') {\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n }\n {{ StatusMessage }}\n </div>\n }\n\n <!-- Action bar (Save on LEFT per MJ convention) -->\n <div class=\"detail-actions\">\n <button\n class=\"btn btn-primary\"\n [disabled]=\"IsSaving\"\n (click)=\"Save()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i> Save\n }\n </button>\n <button class=\"btn btn-secondary\" [disabled]=\"IsSaving\" (click)=\"Cancel()\">\n Cancel\n </button>\n </div>\n </div>\n }\n }\n </div>\n </div>\n }\n</div>\n"]}
1
+ {"version":3,"file":"archive-config-admin.component.js","sourceRoot":"","sources":["../../../src/lib/archive-config/archive-config-admin.component.ts","../../../src/lib/archive-config/archive-config-admin.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n OnInit,\n OnDestroy,\n inject,\n} from '@angular/core';\nimport { CompositeKey, RunView } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport {\n MJArchiveConfigurationEntity,\n MJArchiveConfigurationEntityEntity,\n MJArchiveConfigurationEntityType,\n MJArchiveConfigurationEntityEntityType,\n} from '@memberjunction/core-entities';\n\ntype ArchiveStatus = MJArchiveConfigurationEntityType['Status'];\ntype ArchiveMode = MJArchiveConfigurationEntityType['DefaultMode'];\ntype EntityMode = MJArchiveConfigurationEntityEntityType['Mode'];\n\n/** Represents an archive configuration record */\nexport interface ArchiveConfig {\n ID: string;\n Name: string;\n Description: string;\n Status: ArchiveStatus;\n StorageAccountID: string;\n StorageAccountName: string;\n RootPath: string;\n DefaultRetentionDays: number;\n DefaultBatchSize: number;\n DefaultMode: ArchiveMode;\n ArchiveRelatedRecordChanges: boolean;\n IsDirty: boolean;\n}\n\n/** Represents an entity within a configuration */\nexport interface ArchiveConfigEntity {\n ID: string;\n ArchiveConfigurationID: string;\n EntityName: string;\n Mode: EntityMode;\n RetentionDays: number;\n BatchSize: number;\n DateField: string;\n IsActive: boolean;\n IsNew: boolean;\n IsDirty: boolean;\n}\n\n/** Storage account option for the dropdown */\nexport interface StorageAccountOption {\n ID: string;\n Name: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-archive-config-admin',\n templateUrl: './archive-config-admin.component.html',\n styleUrls: ['./archive-config-admin.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ArchiveConfigAdminComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n\n /** All configurations */\n Configs: ArchiveConfig[] = [];\n\n /** Currently selected configuration */\n SelectedConfig: ArchiveConfig | null = null;\n\n /** Entities for the selected configuration */\n ConfigEntities: ArchiveConfigEntity[] = [];\n\n /** Available storage accounts for dropdown */\n StorageAccounts: StorageAccountOption[] = [];\n\n /** Available archive modes */\n ArchiveModes: string[] = ['StripFields', 'SoftDelete', 'HardDelete', 'ArchiveOnly'];\n\n /** Whether the list is loading */\n IsLoading = true;\n\n /** Whether the detail panel is loading */\n IsDetailLoading = false;\n\n /** Whether a save operation is in progress */\n IsSaving = false;\n\n /** Status message for feedback */\n StatusMessage = '';\n\n /** Status type for styling */\n StatusType: 'success' | 'error' | '' = '';\n\n private destroyed = false;\n\n ngOnInit(): void {\n this.loadAllData();\n }\n\n ngOnDestroy(): void {\n this.destroyed = true;\n }\n\n /** Select a configuration and load its entities */\n async SelectConfig(config: ArchiveConfig): Promise<void> {\n this.SelectedConfig = { ...config };\n this.clearStatus();\n await this.loadConfigEntities(config.ID);\n }\n\n /** Check if a config is the currently selected one */\n IsSelectedConfig(config: ArchiveConfig): boolean {\n return UUIDsEqual(this.SelectedConfig?.ID, config.ID);\n }\n\n /** Add a new empty entity row */\n AddEntity(): void {\n if (!this.SelectedConfig) return;\n\n const newEntity: ArchiveConfigEntity = {\n ID: `new-${Date.now()}`,\n ArchiveConfigurationID: this.SelectedConfig.ID,\n EntityName: '',\n Mode: this.SelectedConfig.DefaultMode ?? 'StripFields',\n RetentionDays: this.SelectedConfig.DefaultRetentionDays || 365,\n BatchSize: this.SelectedConfig.DefaultBatchSize || 100,\n DateField: '__mj_CreatedAt',\n IsActive: true,\n IsNew: true,\n IsDirty: true,\n };\n this.ConfigEntities = [...this.ConfigEntities, newEntity];\n this.cdr.markForCheck();\n }\n\n /** Remove an entity row */\n RemoveEntity(entity: ArchiveConfigEntity): void {\n this.ConfigEntities = this.ConfigEntities.filter((e) => !UUIDsEqual(e.ID, entity.ID));\n this.cdr.markForCheck();\n }\n\n /** Mark an entity as dirty when edited */\n OnEntityChanged(entity: ArchiveConfigEntity): void {\n entity.IsDirty = true;\n this.cdr.markForCheck();\n }\n\n /** Mark the selected config as dirty */\n OnConfigFieldChanged(): void {\n if (this.SelectedConfig) {\n this.SelectedConfig.IsDirty = true;\n this.cdr.markForCheck();\n }\n }\n\n /** Save the selected configuration and its entities */\n async Save(): Promise<void> {\n if (!this.SelectedConfig) return;\n\n this.IsSaving = true;\n this.clearStatus();\n this.cdr.markForCheck();\n\n try {\n await this.saveConfiguration();\n await this.saveConfigEntities();\n this.setStatus('Configuration saved successfully.', 'success');\n await this.refreshConfigList();\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : 'Save failed. Please try again.';\n this.setStatus(message, 'error');\n } finally {\n this.IsSaving = false;\n this.markForCheckIfAlive();\n }\n }\n\n /** Cancel changes and reload the selected config */\n async Cancel(): Promise<void> {\n if (!this.SelectedConfig) return;\n\n const configId = this.SelectedConfig.ID;\n this.clearStatus();\n\n const original = this.Configs.find((c) => UUIDsEqual(c.ID, configId));\n if (original) {\n this.SelectedConfig = { ...original };\n await this.loadConfigEntities(configId);\n }\n }\n\n /** Add a new configuration */\n AddConfiguration(): void {\n const newConfig: ArchiveConfig = {\n ID: `new-${Date.now()}`,\n Name: 'New Configuration',\n Description: '',\n Status: 'Disabled',\n StorageAccountID: '',\n StorageAccountName: '',\n RootPath: '/archives',\n DefaultRetentionDays: 365,\n DefaultBatchSize: 100,\n DefaultMode: 'StripFields',\n ArchiveRelatedRecordChanges: false,\n IsDirty: true,\n };\n this.Configs = [newConfig, ...this.Configs];\n this.SelectConfig(newConfig);\n }\n\n /** Get a display label for the status */\n GetStatusLabel(status: string | undefined): string {\n switch (status) {\n case 'Idle': return 'Idle';\n case 'Running': return 'Running';\n case 'Error': return 'Error';\n default: return 'Disabled';\n }\n }\n\n /** Load all initial data using batched RunViews */\n private async loadAllData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [configResult, storageResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Archive Configurations',\n ExtraFilter: '',\n OrderBy: 'Name',\n ResultType: 'simple',\n },\n {\n EntityName: 'MJ: File Storage Accounts',\n ExtraFilter: '',\n OrderBy: 'Name',\n ResultType: 'simple',\n Fields: ['ID', 'Name'],\n },\n ]);\n\n this.Configs = this.mapConfigRecords(configResult);\n this.StorageAccounts = this.mapStorageAccounts(storageResult);\n\n if (this.Configs.length > 0) {\n await this.SelectConfig(this.Configs[0]);\n }\n } catch {\n this.setStatus('Failed to load configurations.', 'error');\n } finally {\n this.IsLoading = false;\n this.markForCheckIfAlive();\n }\n }\n\n /** Map raw config records to typed objects */\n private mapConfigRecords(result: { Success: boolean; Results: Record<string, unknown>[] }): ArchiveConfig[] {\n if (!result.Success) return [];\n return result.Results.map((r) => ({\n ID: String(r['ID'] ?? ''),\n Name: String(r['Name'] ?? ''),\n Description: String(r['Description'] ?? ''),\n Status: (r['Status'] as ArchiveStatus) ?? 'Disabled',\n StorageAccountID: String(r['StorageAccountID'] ?? ''),\n StorageAccountName: String(r['StorageAccount'] ?? ''),\n RootPath: String(r['RootPath'] ?? ''),\n DefaultRetentionDays: Number(r['DefaultRetentionDays'] ?? 365),\n DefaultBatchSize: Number(r['DefaultBatchSize'] ?? 100),\n DefaultMode: (r['DefaultMode'] as ArchiveMode) ?? 'StripFields',\n ArchiveRelatedRecordChanges: Boolean(r['ArchiveRelatedRecordChanges']),\n IsDirty: false,\n }));\n }\n\n /** Map raw storage account records */\n private mapStorageAccounts(result: { Success: boolean; Results: Record<string, unknown>[] }): StorageAccountOption[] {\n if (!result.Success) return [];\n return result.Results.map((r) => ({\n ID: String(r['ID'] ?? ''),\n Name: String(r['Name'] ?? ''),\n }));\n }\n\n /** Load entities for a specific configuration */\n private async loadConfigEntities(configId: string): Promise<void> {\n this.IsDetailLoading = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const escapedId = configId.replace(/'/g, \"''\");\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: 'MJ: Archive Configuration Entities',\n ExtraFilter: `ArchiveConfigurationID='${escapedId}'`,\n OrderBy: 'Entity',\n ResultType: 'simple',\n });\n\n this.ConfigEntities = this.mapEntityRecords(result);\n } catch {\n this.ConfigEntities = [];\n } finally {\n this.IsDetailLoading = false;\n this.markForCheckIfAlive();\n }\n }\n\n /** Map raw entity records to typed objects */\n private mapEntityRecords(result: { Success: boolean; Results: Record<string, unknown>[] }): ArchiveConfigEntity[] {\n if (!result.Success) return [];\n return result.Results.map((r) => ({\n ID: String(r['ID'] ?? ''),\n ArchiveConfigurationID: String(r['ArchiveConfigurationID'] ?? ''),\n EntityName: String(r['Entity'] ?? ''),\n Mode: (r['Mode'] as EntityMode) ?? 'StripFields',\n RetentionDays: Number(r['RetentionDays'] ?? 365),\n BatchSize: Number(r['BatchSize'] ?? 100),\n DateField: String(r['DateField'] ?? '__mj_CreatedAt'),\n IsActive: Boolean(r['IsActive']),\n IsNew: false,\n IsDirty: false,\n }));\n }\n\n /** Save the configuration record using strongly-typed entity */\n private async saveConfiguration(): Promise<void> {\n if (!this.SelectedConfig?.IsDirty) return;\n\n const md = this.ProviderToUse;\n const entity = await md.GetEntityObject<MJArchiveConfigurationEntity>('MJ: Archive Configurations', md.CurrentUser);\n\n if (!this.SelectedConfig.ID.startsWith('new-')) {\n await entity.InnerLoad(CompositeKey.FromID(this.SelectedConfig.ID));\n } else {\n entity.NewRecord();\n }\n\n entity.Name = this.SelectedConfig.Name;\n entity.Description = this.SelectedConfig.Description;\n entity.Status = this.SelectedConfig.Status ?? 'Disabled';\n if (this.SelectedConfig.StorageAccountID) {\n entity.StorageAccountID = this.SelectedConfig.StorageAccountID;\n }\n entity.RootPath = this.SelectedConfig.RootPath;\n entity.DefaultRetentionDays = this.SelectedConfig.DefaultRetentionDays;\n entity.DefaultBatchSize = this.SelectedConfig.DefaultBatchSize;\n entity.DefaultMode = this.SelectedConfig.DefaultMode ?? 'StripFields';\n entity.ArchiveRelatedRecordChanges = this.SelectedConfig.ArchiveRelatedRecordChanges;\n\n const saved = await entity.Save();\n if (!saved) {\n throw new Error('Failed to save configuration.');\n }\n\n // Update the ID if this was a new record\n if (this.SelectedConfig.ID.startsWith('new-')) {\n this.SelectedConfig.ID = entity.ID;\n }\n this.SelectedConfig.IsDirty = false;\n }\n\n /** Save all dirty/new entity records */\n private async saveConfigEntities(): Promise<void> {\n const dirtyEntities = this.ConfigEntities.filter((e) => e.IsDirty);\n for (const configEntity of dirtyEntities) {\n await this.saveConfigEntity(configEntity);\n }\n }\n\n /** Save a single config entity record using strongly-typed entity */\n private async saveConfigEntity(configEntity: ArchiveConfigEntity): Promise<void> {\n const md = this.ProviderToUse;\n const entity = await md.GetEntityObject<MJArchiveConfigurationEntityEntity>('MJ: Archive Configuration Entities', md.CurrentUser);\n\n if (!configEntity.IsNew) {\n await entity.InnerLoad(CompositeKey.FromID(configEntity.ID));\n } else {\n entity.NewRecord();\n }\n\n entity.ArchiveConfigurationID = configEntity.ArchiveConfigurationID;\n entity.Mode = configEntity.Mode ?? null;\n entity.RetentionDays = configEntity.RetentionDays;\n entity.BatchSize = configEntity.BatchSize;\n entity.DateField = configEntity.DateField;\n entity.IsActive = configEntity.IsActive;\n\n const saved = await entity.Save();\n if (!saved) {\n throw new Error(`Failed to save entity \"${configEntity.EntityName}\".`);\n }\n\n configEntity.IsDirty = false;\n configEntity.IsNew = false;\n }\n\n /** Refresh the config list after a save */\n private async refreshConfigList(): Promise<void> {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: 'MJ: Archive Configurations',\n ExtraFilter: '',\n OrderBy: 'Name',\n ResultType: 'simple',\n });\n this.Configs = this.mapConfigRecords(result);\n }\n\n /** Set a status message */\n private setStatus(message: string, type: 'success' | 'error'): void {\n this.StatusMessage = message;\n this.StatusType = type;\n }\n\n /** Clear status message */\n private clearStatus(): void {\n this.StatusMessage = '';\n this.StatusType = '';\n }\n\n /** Mark for check only if not destroyed */\n private markForCheckIfAlive(): void {\n if (!this.destroyed) {\n this.cdr.markForCheck();\n }\n }\n}\n","<div class=\"config-admin\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"config-loading\">\n <mj-loading text=\"Loading configurations...\"></mj-loading>\n </div>\n }\n\n @if (!IsLoading) {\n <div class=\"config-layout\">\n <!-- Left panel: Config list -->\n <div class=\"config-list-panel\">\n <div class=\"config-list-header\">\n <h2>Archive Configurations</h2>\n <button class=\"btn btn-primary btn-sm\" (click)=\"AddConfiguration()\">\n <i class=\"fa-solid fa-plus\"></i>\n Add Configuration\n </button>\n </div>\n\n <div class=\"config-card-list\">\n @for (config of Configs; track config.ID) {\n <div\n class=\"config-card\"\n [class.selected]=\"IsSelectedConfig(config)\"\n (click)=\"SelectConfig(config)\"\n (keydown.enter)=\"SelectConfig(config)\"\n tabindex=\"0\"\n role=\"button\">\n <div class=\"config-card-header\">\n <span class=\"config-card-name\">{{ config.Name }}</span>\n <span\n class=\"config-status-badge\"\n [class.status-active]=\"config.Status === 'Idle' || config.Status === 'Running'\"\n [class.status-inactive]=\"config.Status === 'Disabled' || config.Status === 'Error'\">\n {{ GetStatusLabel(config.Status) }}\n </span>\n </div>\n <div class=\"config-card-meta\">\n <span><i class=\"fa-solid fa-database\"></i> {{ config.StorageAccountName || 'No storage' }}</span>\n <span><i class=\"fa-solid fa-folder\"></i> {{ config.RootPath }}</span>\n </div>\n <div class=\"config-card-date\">\n <span class=\"config-status-mode\"><i class=\"fa-solid fa-sliders\"></i> {{ config.DefaultMode }}</span>\n </div>\n </div>\n }\n\n @if (Configs.length === 0) {\n <mj-empty-state class=\"config-empty\" Size=\"compact\"\n Icon=\"fa-solid fa-folder-open\"\n Title=\"No configurations found\"\n Message=\"Create one to get started.\" />\n }\n </div>\n </div>\n\n <!-- Right panel: Detail -->\n <div class=\"config-detail-panel\">\n @if (!SelectedConfig) {\n <mj-empty-state class=\"config-detail-placeholder\"\n Icon=\"fa-solid fa-hand-pointer\"\n Title=\"No configuration selected\"\n Message=\"Select a configuration to view details\" />\n }\n\n @if (SelectedConfig) {\n @if (IsDetailLoading) {\n <div class=\"config-detail-loading\">\n <mj-loading text=\"Loading details...\" size=\"small\"></mj-loading>\n </div>\n }\n\n @if (!IsDetailLoading) {\n <div class=\"config-detail-content\">\n <!-- Header section -->\n <div class=\"detail-section\">\n <div class=\"detail-field\">\n <label for=\"config-name\">Name</label>\n <input\n id=\"config-name\"\n type=\"text\"\n [(ngModel)]=\"SelectedConfig.Name\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n <div class=\"detail-field\">\n <label>Active</label>\n <div class=\"detail-checkbox\">\n <input\n type=\"checkbox\"\n [checked]=\"SelectedConfig.Status === 'Idle'\"\n (change)=\"SelectedConfig.Status = SelectedConfig.Status === 'Idle' ? 'Disabled' : 'Idle'; OnConfigFieldChanged()\" />\n </div>\n </div>\n <div class=\"detail-field\">\n <label for=\"config-desc\">Description</label>\n <textarea\n id=\"config-desc\"\n [(ngModel)]=\"SelectedConfig.Description\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input detail-textarea\"\n rows=\"2\"></textarea>\n </div>\n </div>\n\n <!-- Storage section -->\n <div class=\"detail-section\">\n <h3><i class=\"fa-solid fa-hard-drive\"></i> Storage</h3>\n <div class=\"detail-row\">\n <div class=\"detail-field\">\n <label for=\"config-storage\">Storage Account</label>\n <select\n id=\"config-storage\"\n [(ngModel)]=\"SelectedConfig.StorageAccountID\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\">\n <option value=\"\">-- Select --</option>\n @for (account of StorageAccounts; track account.ID) {\n <option [value]=\"account.ID\">{{ account.Name }}</option>\n }\n </select>\n </div>\n <div class=\"detail-field\">\n <label for=\"config-path\">Root Path</label>\n <input\n id=\"config-path\"\n type=\"text\"\n [(ngModel)]=\"SelectedConfig.RootPath\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n </div>\n </div>\n\n <!-- Defaults section -->\n <div class=\"detail-section\">\n <h3><i class=\"fa-solid fa-sliders\"></i> Defaults</h3>\n <div class=\"detail-row\">\n <div class=\"detail-field\">\n <label for=\"config-retention\">Retention Days</label>\n <input\n id=\"config-retention\"\n type=\"number\"\n [(ngModel)]=\"SelectedConfig.DefaultRetentionDays\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n <div class=\"detail-field\">\n <label for=\"config-batch\">Batch Size</label>\n <input\n id=\"config-batch\"\n type=\"number\"\n [(ngModel)]=\"SelectedConfig.DefaultBatchSize\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\" />\n </div>\n </div>\n <div class=\"detail-row\">\n <div class=\"detail-field\">\n <label for=\"config-mode\">Archive Mode</label>\n <select\n id=\"config-mode\"\n [(ngModel)]=\"SelectedConfig.DefaultMode\"\n (ngModelChange)=\"OnConfigFieldChanged()\"\n class=\"detail-input\">\n @for (mode of ArchiveModes; track mode) {\n <option [value]=\"mode\">{{ mode }}</option>\n }\n </select>\n </div>\n <div class=\"detail-field\">\n <label>Archive Record Changes</label>\n <div class=\"detail-checkbox\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"SelectedConfig.ArchiveRelatedRecordChanges\"\n (ngModelChange)=\"OnConfigFieldChanged()\" />\n </div>\n </div>\n </div>\n </div>\n\n <!-- Entities section -->\n <div class=\"detail-section\">\n <div class=\"detail-section-header\">\n <h3><i class=\"fa-solid fa-table\"></i> Entities</h3>\n <button class=\"btn btn-sm btn-outline\" (click)=\"AddEntity()\">\n <i class=\"fa-solid fa-plus\"></i> Add Entity\n </button>\n </div>\n\n @if (ConfigEntities.length > 0) {\n <div class=\"entity-table-wrapper\">\n <table class=\"entity-table\">\n <thead>\n <tr>\n <th>Entity</th>\n <th>Mode</th>\n <th>Retention</th>\n <th>Batch</th>\n <th>Date Field</th>\n <th>Active</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n @for (entity of ConfigEntities; track entity.ID) {\n <tr>\n <td>\n <input\n type=\"text\"\n [(ngModel)]=\"entity.EntityName\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input\"\n placeholder=\"Entity name\" />\n </td>\n <td>\n <select\n [(ngModel)]=\"entity.Mode\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input\">\n @for (mode of ArchiveModes; track mode) {\n <option [value]=\"mode\">{{ mode }}</option>\n }\n </select>\n </td>\n <td>\n <input\n type=\"number\"\n [(ngModel)]=\"entity.RetentionDays\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input entity-input-sm\" />\n </td>\n <td>\n <input\n type=\"number\"\n [(ngModel)]=\"entity.BatchSize\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input entity-input-sm\" />\n </td>\n <td>\n <input\n type=\"text\"\n [(ngModel)]=\"entity.DateField\"\n (ngModelChange)=\"OnEntityChanged(entity)\"\n class=\"entity-input\"\n placeholder=\"e.g. CreatedAt\" />\n </td>\n <td>\n <input\n type=\"checkbox\"\n [(ngModel)]=\"entity.IsActive\"\n (ngModelChange)=\"OnEntityChanged(entity)\" />\n </td>\n <td>\n <button\n class=\"btn-icon btn-icon-danger\"\n (click)=\"RemoveEntity(entity)\"\n title=\"Remove entity\"\n aria-label=\"Remove entity\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (ConfigEntities.length === 0) {\n <mj-empty-state class=\"entity-empty\" Size=\"compact\"\n Icon=\"\" Title=\"No entities configured. Click &quot;Add Entity&quot; to add one.\" />\n }\n </div>\n\n <!-- Status message -->\n @if (StatusMessage) {\n <div class=\"config-status\" [class.status-success]=\"StatusType === 'success'\" [class.status-error]=\"StatusType === 'error'\">\n @if (StatusType === 'success') {\n <i class=\"fa-solid fa-circle-check\"></i>\n }\n @if (StatusType === 'error') {\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n }\n {{ StatusMessage }}\n </div>\n }\n\n <!-- Action bar (Save on LEFT per MJ convention) -->\n <div class=\"detail-actions\">\n <button\n class=\"btn btn-primary\"\n [disabled]=\"IsSaving\"\n (click)=\"Save()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i> Save\n }\n </button>\n <button class=\"btn btn-secondary\" [disabled]=\"IsSaving\" (click)=\"Cancel()\">\n Cancel\n </button>\n </div>\n </div>\n }\n }\n </div>\n </div>\n }\n</div>\n"]}
@@ -360,7 +360,7 @@ export class ArchiveRestoreDialogComponent extends BaseAngularComponent {
360
360
  i0.ɵɵconditionalCreate(0, ArchiveRestoreDialogComponent_Conditional_0_Template, 18, 6);
361
361
  } if (rf & 2) {
362
362
  i0.ɵɵconditional(ctx.Visible ? 0 : -1);
363
- } }, dependencies: [i1.LoadingComponent, i2.MJEmptyStateComponent], styles: ["\n\n.restore-overlay[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n}\n\n\n\n.restore-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 860px;\n max-width: 92vw;\n max-height: 80vh;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 8px 32px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n\n\n.restore-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n\n h2 {\n margin: 0;\n font-size: 1.1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n\n i {\n color: var(--mj-brand-primary);\n }\n }\n}\n\n.restore-close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n padding: 6px;\n border-radius: 4px;\n color: var(--mj-text-muted);\n font-size: 1.1rem;\n transition: color 0.15s ease, background 0.15s ease;\n\n &:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n }\n}\n\n\n\n.restore-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n}\n\n\n\n.restore-content[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n\n\n.restore-timeline-panel[_ngcontent-%COMP%] {\n width: 40%;\n border-right: 1px solid var(--mj-border-default);\n overflow-y: auto;\n padding: 16px;\n}\n\n.restore-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n text-align: center;\n\n i {\n font-size: 2rem;\n margin-bottom: 12px;\n }\n\n p {\n margin: 0;\n font-size: 0.9rem;\n }\n}\n\n\n\n.timeline[_ngcontent-%COMP%] {\n position: relative;\n padding-left: 20px;\n\n \n\n &::before {\n content: '';\n position: absolute;\n left: 8px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n }\n}\n\n.timeline-node[_ngcontent-%COMP%] {\n position: relative;\n padding: 10px 12px;\n margin-bottom: 4px;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease;\n\n &:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n\n &.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n\n .timeline-dot {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n }\n }\n}\n\n.timeline-dot[_ngcontent-%COMP%] {\n position: absolute;\n left: -16px;\n top: 16px;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-border-strong);\n transition: all 0.15s ease;\n}\n\n.timeline-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.timeline-date[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.timeline-meta[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n\n\n.restore-preview-panel[_ngcontent-%COMP%] {\n width: 60%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n\n h3 {\n margin: 0;\n font-size: 0.9rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.preview-date[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.preview-json[_ngcontent-%COMP%] {\n flex: 1;\n margin: 0;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n font-family: 'Courier New', Courier, monospace;\n font-size: 0.8rem;\n line-height: 1.5;\n overflow: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.preview-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n color: var(--mj-text-muted);\n\n i {\n font-size: 1.5rem;\n margin-bottom: 8px;\n }\n\n p {\n margin: 0;\n font-size: 0.85rem;\n }\n}\n\n\n\n.restore-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 0.85rem;\n\n i {\n font-size: 1rem;\n }\n}\n\n.restore-message-success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border-top: 1px solid var(--mj-status-success-border);\n}\n\n.restore-message-error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border-top: 1px solid var(--mj-status-error-border);\n}\n\n\n\n.restore-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n font-size: 0.85rem;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease, opacity 0.15s ease;\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n\n &:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n\n &:active:not(:disabled) {\n background: var(--mj-brand-primary-active);\n }\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-border-default);\n\n &:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n }\n}"], changeDetection: 0 });
363
+ } }, dependencies: [i1.LoadingComponent, i2.MJEmptyStateComponent], styles: ["\n.restore-overlay[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n}\n\n\n.restore-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 860px;\n max-width: 92vw;\n max-height: 80vh;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 8px 32px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n\n.restore-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n\n h2 {\n margin: 0;\n font-size: 1.1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n\n i {\n color: var(--mj-brand-primary);\n }\n }\n}\n\n.restore-close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n padding: 6px;\n border-radius: 4px;\n color: var(--mj-text-muted);\n font-size: 1.1rem;\n transition: color 0.15s ease, background 0.15s ease;\n\n &:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n }\n}\n\n\n.restore-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n}\n\n\n.restore-content[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n\n.restore-timeline-panel[_ngcontent-%COMP%] {\n width: 40%;\n border-right: 1px solid var(--mj-border-default);\n overflow-y: auto;\n padding: 16px;\n}\n\n.restore-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n text-align: center;\n\n i {\n font-size: 2rem;\n margin-bottom: 12px;\n }\n\n p {\n margin: 0;\n font-size: 0.9rem;\n }\n}\n\n\n.timeline[_ngcontent-%COMP%] {\n position: relative;\n padding-left: 20px;\n\n \n &::before {\n content: '';\n position: absolute;\n left: 8px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n }\n}\n\n.timeline-node[_ngcontent-%COMP%] {\n position: relative;\n padding: 10px 12px;\n margin-bottom: 4px;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease;\n\n &:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n\n &.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n\n .timeline-dot {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n }\n }\n}\n\n.timeline-dot[_ngcontent-%COMP%] {\n position: absolute;\n left: -16px;\n top: 16px;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-border-strong);\n transition: all 0.15s ease;\n}\n\n.timeline-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.timeline-date[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.timeline-meta[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n\n.restore-preview-panel[_ngcontent-%COMP%] {\n width: 60%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-subtle);\n\n h3 {\n margin: 0;\n font-size: 0.9rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.preview-date[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.preview-json[_ngcontent-%COMP%] {\n flex: 1;\n margin: 0;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n font-family: 'Courier New', Courier, monospace;\n font-size: 0.8rem;\n line-height: 1.5;\n overflow: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.preview-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n color: var(--mj-text-muted);\n\n i {\n font-size: 1.5rem;\n margin-bottom: 8px;\n }\n\n p {\n margin: 0;\n font-size: 0.85rem;\n }\n}\n\n\n.restore-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 0.85rem;\n\n i {\n font-size: 1rem;\n }\n}\n\n.restore-message-success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border-top: 1px solid var(--mj-status-success-border);\n}\n\n.restore-message-error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border-top: 1px solid var(--mj-status-error-border);\n}\n\n\n.restore-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n font-size: 0.85rem;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease, opacity 0.15s ease;\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n\n &:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n\n &:active:not(:disabled) {\n background: var(--mj-brand-primary-active);\n }\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-border-default);\n\n &:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n }\n}"], changeDetection: 0 });
364
364
  }
365
365
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ArchiveRestoreDialogComponent, [{
366
366
  type: Component,
@@ -501,7 +501,7 @@ export class ArchiveRunViewerComponent extends BaseAngularComponent {
501
501
  i0.ɵɵclassProp("open", ctx.DrawerOpen);
502
502
  i0.ɵɵadvance();
503
503
  i0.ɵɵconditional(ctx.SelectedRun ? 5 : -1);
504
- } }, dependencies: [i1.NgClass, i2.LoadingComponent, i3.MJEmptyStateComponent], styles: [".run-viewer[_ngcontent-%COMP%] {\n padding: 20px;\n position: relative;\n}\n\n\n\n.run-viewer-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px;\n}\n\n\n\n.metrics-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.metric-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px 20px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n &:hover {\n border-color: var(--mj-border-default);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-text-primary) 6%, transparent);\n }\n}\n\n.metric-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 42px;\n height: 42px;\n border-radius: 10px;\n font-size: 1.1rem;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.metric-icon-archive[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.metric-icon-storage[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.metric-icon-time[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.metric-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.metric-label[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n\n\n.run-list-title[_ngcontent-%COMP%] {\n margin: 0 0 14px;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.run-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 40px;\n color: var(--mj-text-muted);\n text-align: center;\n\n i {\n font-size: 2rem;\n margin-bottom: 12px;\n }\n\n p {\n margin: 0;\n font-size: 0.9rem;\n }\n}\n\n\n\n.run-card[_ngcontent-%COMP%] {\n padding: 14px 18px;\n margin-bottom: 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n cursor: pointer;\n transition: border-color 0.15s ease, background 0.15s ease;\n\n &:hover {\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n}\n\n.run-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n\n.run-card-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.run-card-date[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n\n i {\n margin-right: 4px;\n }\n}\n\n.run-card-stats[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 14px;\n}\n\n.run-stat[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n\n i {\n font-size: 0.72rem;\n }\n}\n\n.run-stat-error[_ngcontent-%COMP%] {\n color: var(--mj-status-error-text);\n}\n\n.run-stat-muted[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 10px;\n font-size: 0.72rem;\n font-weight: 600;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.status-badge-sm[_ngcontent-%COMP%] {\n padding: 1px 7px;\n font-size: 0.68rem;\n}\n\n.status-badge-success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.status-badge-error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n.status-badge-info[_ngcontent-%COMP%] {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n}\n\n.status-badge-default[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n\n\n.archive-drawer-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n}\n\n\n\n.archive-drawer[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n height: 100vh;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: -4px 0 24px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n z-index: 1000;\n transform: translateX(100%);\n transition: transform 0.3s ease;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n\n &.open {\n transform: translateX(0);\n }\n}\n\n\n\n.drawer-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n\n h3 {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.drawer-close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n padding: 6px;\n border-radius: 4px;\n color: var(--mj-text-muted);\n font-size: 1rem;\n transition: color 0.15s ease, background 0.15s ease;\n\n &:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n }\n}\n\n\n\n.drawer-summary[_ngcontent-%COMP%] {\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.drawer-summary-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 0;\n}\n\n.drawer-label[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.drawer-value[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n}\n\n\n\n.drawer-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.drawer-stat[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 14px 10px;\n border-right: 1px solid var(--mj-border-subtle);\n\n &:last-child {\n border-right: none;\n }\n}\n\n.drawer-stat-value[_ngcontent-%COMP%] {\n font-size: 1.2rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.drawer-stat-error[_ngcontent-%COMP%] .drawer-stat-value[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.drawer-stat-muted[_ngcontent-%COMP%] .drawer-stat-value[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.drawer-stat-label[_ngcontent-%COMP%] {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n\n\n.drawer-details[_ngcontent-%COMP%] {\n flex: 1;\n padding: 14px 18px;\n overflow-y: auto;\n\n h4 {\n margin: 0 0 12px;\n font-size: 0.88rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.drawer-details-empty[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n text-align: center;\n padding: 20px;\n}\n\n.drawer-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n}\n\n.drawer-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.78rem;\n\n th {\n padding: 7px 10px;\n text-align: left;\n font-weight: 600;\n font-size: 0.72rem;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n }\n\n tr:last-child td {\n border-bottom: none;\n }\n}\n\n.cell-entity[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.cell-id[_ngcontent-%COMP%] {\n max-width: 100px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: monospace;\n font-size: 0.72rem;\n color: var(--mj-text-secondary);\n}\n\n.cell-bytes[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n\n\n@media (max-width: 900px) {\n .metrics-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 600px) {\n .metrics-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}"], changeDetection: 0 });
504
+ } }, dependencies: [i1.NgClass, i2.LoadingComponent, i3.MJEmptyStateComponent], styles: [".run-viewer[_ngcontent-%COMP%] {\n padding: 20px;\n position: relative;\n}\n\n\n.run-viewer-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px;\n}\n\n\n.metrics-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.metric-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px 20px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 8px;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n\n &:hover {\n border-color: var(--mj-border-default);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-text-primary) 6%, transparent);\n }\n}\n\n.metric-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 42px;\n height: 42px;\n border-radius: 10px;\n font-size: 1.1rem;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.metric-icon-archive[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.metric-icon-storage[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.metric-icon-time[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.metric-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.metric-label[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n\n.run-list-title[_ngcontent-%COMP%] {\n margin: 0 0 14px;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.run-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 40px;\n color: var(--mj-text-muted);\n text-align: center;\n\n i {\n font-size: 2rem;\n margin-bottom: 12px;\n }\n\n p {\n margin: 0;\n font-size: 0.9rem;\n }\n}\n\n\n.run-card[_ngcontent-%COMP%] {\n padding: 14px 18px;\n margin-bottom: 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n cursor: pointer;\n transition: border-color 0.15s ease, background 0.15s ease;\n\n &:hover {\n border-color: var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n }\n\n &:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 2px;\n }\n}\n\n.run-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n}\n\n.run-card-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.run-card-date[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n\n i {\n margin-right: 4px;\n }\n}\n\n.run-card-stats[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 14px;\n}\n\n.run-stat[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n\n i {\n font-size: 0.72rem;\n }\n}\n\n.run-stat-error[_ngcontent-%COMP%] {\n color: var(--mj-status-error-text);\n}\n\n.run-stat-muted[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 10px;\n font-size: 0.72rem;\n font-weight: 600;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.status-badge-sm[_ngcontent-%COMP%] {\n padding: 1px 7px;\n font-size: 0.68rem;\n}\n\n.status-badge-success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.status-badge-error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n.status-badge-info[_ngcontent-%COMP%] {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n}\n\n.status-badge-default[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n\n.archive-drawer-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n}\n\n\n.archive-drawer[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n height: 100vh;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: -4px 0 24px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n z-index: 1000;\n transform: translateX(100%);\n transition: transform 0.3s ease;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n\n &.open {\n transform: translateX(0);\n }\n}\n\n\n.drawer-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n\n h3 {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.drawer-close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n padding: 6px;\n border-radius: 4px;\n color: var(--mj-text-muted);\n font-size: 1rem;\n transition: color 0.15s ease, background 0.15s ease;\n\n &:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n }\n}\n\n\n.drawer-summary[_ngcontent-%COMP%] {\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.drawer-summary-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 0;\n}\n\n.drawer-label[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.drawer-value[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n}\n\n\n.drawer-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.drawer-stat[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 14px 10px;\n border-right: 1px solid var(--mj-border-subtle);\n\n &:last-child {\n border-right: none;\n }\n}\n\n.drawer-stat-value[_ngcontent-%COMP%] {\n font-size: 1.2rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.drawer-stat-error[_ngcontent-%COMP%] .drawer-stat-value[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.drawer-stat-muted[_ngcontent-%COMP%] .drawer-stat-value[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.drawer-stat-label[_ngcontent-%COMP%] {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n\n.drawer-details[_ngcontent-%COMP%] {\n flex: 1;\n padding: 14px 18px;\n overflow-y: auto;\n\n h4 {\n margin: 0 0 12px;\n font-size: 0.88rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n}\n\n.drawer-details-empty[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n text-align: center;\n padding: 20px;\n}\n\n.drawer-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n}\n\n.drawer-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.78rem;\n\n th {\n padding: 7px 10px;\n text-align: left;\n font-weight: 600;\n font-size: 0.72rem;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n td {\n padding: 6px 10px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n }\n\n tr:last-child td {\n border-bottom: none;\n }\n}\n\n.cell-entity[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.cell-id[_ngcontent-%COMP%] {\n max-width: 100px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: monospace;\n font-size: 0.72rem;\n color: var(--mj-text-secondary);\n}\n\n.cell-bytes[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n\n@media (max-width: 900px) {\n .metrics-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 600px) {\n .metrics-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}"], changeDetection: 0 });
505
505
  }
506
506
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ArchiveRunViewerComponent, [{
507
507
  type: Component,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-archive-manager",
3
- "version": "6.1.0-edge.4",
3
+ "version": "6.1.0-edge.6",
4
4
  "description": "MemberJunction: Angular Archive Manager - UI components for managing entity field archiving, restoration, and configuration.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -15,24 +15,24 @@
15
15
  "author": "",
16
16
  "license": "BUSL-1.1",
17
17
  "devDependencies": {
18
- "@angular/compiler": "21.1.3",
19
- "@angular/compiler-cli": "21.1.3",
20
- "@memberjunction/ng-test-utils": "6.1.0-edge.4",
18
+ "@angular/compiler": "21.2.22",
19
+ "@angular/compiler-cli": "21.2.22",
20
+ "@memberjunction/ng-test-utils": "6.1.0-edge.6",
21
21
  "vitest": "^4.0.18"
22
22
  },
23
23
  "peerDependencies": {
24
- "@angular/common": "^21.1.3",
25
- "@angular/core": "^21.1.3",
26
- "@angular/forms": "^21.1.3",
24
+ "@angular/common": "^21.2.22",
25
+ "@angular/core": "^21.2.22",
26
+ "@angular/forms": "^21.2.22",
27
27
  "rxjs": "^7.8.2"
28
28
  },
29
29
  "dependencies": {
30
- "@memberjunction/ng-ui-components": "6.1.0-edge.4",
31
- "@memberjunction/core": "6.1.0-edge.4",
32
- "@memberjunction/ng-base-types": "6.1.0-edge.4",
33
- "@memberjunction/core-entities": "6.1.0-edge.4",
34
- "@memberjunction/global": "6.1.0-edge.4",
35
- "@memberjunction/ng-shared-generic": "6.1.0-edge.4",
30
+ "@memberjunction/ng-ui-components": "6.1.0-edge.6",
31
+ "@memberjunction/core": "6.1.0-edge.6",
32
+ "@memberjunction/ng-base-types": "6.1.0-edge.6",
33
+ "@memberjunction/core-entities": "6.1.0-edge.6",
34
+ "@memberjunction/global": "6.1.0-edge.6",
35
+ "@memberjunction/ng-shared-generic": "6.1.0-edge.6",
36
36
  "tslib": "^2.8.1"
37
37
  },
38
38
  "sideEffects": false,