@memberjunction/ng-user-routines 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.
|
@@ -536,7 +536,7 @@ export class MyRoutinesListComponent extends BaseAngularComponent {
|
|
|
536
536
|
i0.ɵɵconditional(!ctx.IsLoading && ctx.Routines.length > 0 && ctx.FilteredRoutines.length === 0 ? 2 : -1);
|
|
537
537
|
i0.ɵɵadvance();
|
|
538
538
|
i0.ɵɵconditional(!ctx.IsLoading && ctx.FilteredRoutines.length > 0 ? 3 : -1);
|
|
539
|
-
} }, dependencies: [i1.MJButtonDirective, i1.MJEmptyStateComponent, i2.LoadingComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n}\n\n.routines-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 48px 0;\n}\n\n.routines-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));\n gap: 16px;\n}\n\n.routine-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 10px);\n transition: box-shadow 0.15s ease, border-color 0.15s ease;\n}\n\n.routine-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.routine-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n}\n\n.routine-target-icon[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--mj-radius-md, 8px);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.routine-card-title[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.routine-name[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.routine-target-line[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.routine-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.routine-meta[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.routine-meta-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.routine-meta-row[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n width: 14px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.routine-type-badge[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.routine-cron[_ngcontent-%COMP%] {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.routine-tz[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.routine-meta-muted[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.routine-card-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: auto;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.routine-actions-spacer[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n}\n\n\n
|
|
539
|
+
} }, dependencies: [i1.MJButtonDirective, i1.MJEmptyStateComponent, i2.LoadingComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n}\n\n.routines-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 48px 0;\n}\n\n.routines-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));\n gap: 16px;\n}\n\n.routine-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 10px);\n transition: box-shadow 0.15s ease, border-color 0.15s ease;\n}\n\n.routine-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.routine-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n}\n\n.routine-target-icon[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--mj-radius-md, 8px);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.routine-card-title[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.routine-name[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.routine-target-line[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.routine-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.routine-meta[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.routine-meta-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.routine-meta-row[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n width: 14px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.routine-type-badge[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.routine-cron[_ngcontent-%COMP%] {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.routine-tz[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.routine-meta-muted[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.routine-card-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: auto;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.routine-actions-spacer[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n}\n\n\n.routine-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 11px;\n font-weight: 600;\n line-height: 1.5;\n white-space: nowrap;\n}\n\n.routine-chip--success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.routine-chip--warning[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n\n.routine-chip--error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.routine-chip--info[_ngcontent-%COMP%] {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n\n.routine-chip--muted[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-default);\n}"] });
|
|
540
540
|
}
|
|
541
541
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyRoutinesListComponent, [{
|
|
542
542
|
type: Component,
|
|
@@ -630,7 +630,7 @@ export class NewRoutineComponent extends BaseAngularComponent {
|
|
|
630
630
|
/** Handles agent selection from the category tree (leaf nodes only). */
|
|
631
631
|
/** The selected agent as a CompositeKey for the tree-dropdown's Value binding. */
|
|
632
632
|
get SelectedAgentKey() {
|
|
633
|
-
return this.TargetID ? CompositeKey.FromID(this.TargetID) : null;
|
|
633
|
+
return this.TargetID ? CompositeKey.FromID(this.TargetID) : null; // first-pk-ok: TargetID is an MJ: AI Agents record (agent tree leaf) — core entity keyed by ID
|
|
634
634
|
}
|
|
635
635
|
OnAgentNodeSelected(args) {
|
|
636
636
|
if (args.Node.Type === 'leaf') {
|
|
@@ -1050,7 +1050,7 @@ export class NewRoutineComponent extends BaseAngularComponent {
|
|
|
1050
1050
|
i0.ɵɵconditionalCreate(0, NewRoutineComponent_Conditional_0_Template, 2, 0, "div", 0)(1, NewRoutineComponent_Conditional_1_Template, 49, 22, "div", 1);
|
|
1051
1051
|
} if (rf & 2) {
|
|
1052
1052
|
i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
|
|
1053
|
-
} }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MJAlertComponent, i2.MJButtonDirective, i2.MJComboboxComponent, i2.MJDropdownComponent, i2.MJNumericInputComponent, i2.MJSwitchComponent, i3.LoadingComponent, i4.CodeEditorComponent, i5.TreeDropdownComponent, i6.MentionEditorComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.editor-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 48px 0;\n}\n\n.routine-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 4px 2px 0 2px;\n}\n\n.editor-errors[_ngcontent-%COMP%] {\n margin: 0;\n padding-left: 18px;\n}\n\n.editor-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-lg, 10px);\n}\n\n.editor-section-title[_ngcontent-%COMP%] {\n margin: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.editor-section-title[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.editor-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.editor-field--inline[_ngcontent-%COMP%] {\n flex-direction: row;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.editor-field-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.editor-field-row[_ngcontent-%COMP%] > .editor-field[_ngcontent-%COMP%] {\n flex: 1 1 220px;\n}\n\n.editor-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.editor-required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.editor-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.editor-hint-inline[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n
|
|
1053
|
+
} }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MJAlertComponent, i2.MJButtonDirective, i2.MJComboboxComponent, i2.MJDropdownComponent, i2.MJNumericInputComponent, i2.MJSwitchComponent, i3.LoadingComponent, i4.CodeEditorComponent, i5.TreeDropdownComponent, i6.MentionEditorComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.editor-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 48px 0;\n}\n\n.routine-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 4px 2px 0 2px;\n}\n\n.editor-errors[_ngcontent-%COMP%] {\n margin: 0;\n padding-left: 18px;\n}\n\n.editor-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-lg, 10px);\n}\n\n.editor-section-title[_ngcontent-%COMP%] {\n margin: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.editor-section-title[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.editor-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.editor-field--inline[_ngcontent-%COMP%] {\n flex-direction: row;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.editor-field-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.editor-field-row[_ngcontent-%COMP%] > .editor-field[_ngcontent-%COMP%] {\n flex: 1 1 220px;\n}\n\n.editor-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.editor-required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.editor-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.editor-hint-inline[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n.editor-segmented[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: 0;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n overflow: hidden;\n width: fit-content;\n}\n\n.editor-segmented--wrap[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n}\n\n.editor-segment[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n font-size: 13px;\n border: none;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: background 0.12s ease, color 0.12s ease;\n}\n\n.editor-segment[_ngcontent-%COMP%] + .editor-segment[_ngcontent-%COMP%] {\n border-left: 1px solid var(--mj-border-default);\n}\n\n.editor-segment[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.editor-segment--active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n\n.editor-schedule-detail[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 12px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.editor-schedule-preview[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.editor-schedule-preview[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.editor-time-input[_ngcontent-%COMP%] {\n width: 130px;\n}\n\n.editor-inline-dropdown[_ngcontent-%COMP%] {\n min-width: 140px;\n}\n\n.editor-mono[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, monospace);\n}\n\n\n.editor-code[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n overflow: hidden;\n min-height: 90px;\n}\n\n\n.editor-skills[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.editor-skill-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n font-size: 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full, 999px);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease;\n}\n\n.editor-skill-chip[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.editor-skill-chip--selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.editor-skill-check[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n.editor-switches[_ngcontent-%COMP%] {\n gap: 24px;\n}\n\n.editor-recipients-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.editor-recipient-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px;\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface);\n}\n\n.editor-recipient-order[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.editor-recipient-mode[_ngcontent-%COMP%] {\n flex: 0 0 150px;\n}\n\n.editor-recipient-target[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.editor-recipient-channel[_ngcontent-%COMP%] {\n flex: 0 0 120px;\n}\n\n\n.editor-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 0 4px 0;\n border-top: 1px solid var(--mj-border-default);\n position: sticky;\n bottom: 0;\n background: var(--mj-bg-surface);\n}\n\n\n.editor-selected-agent[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md, 8px);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 13px;\n font-weight: 600;\n width: fit-content;\n}\n\n.editor-selected-agent-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 400;\n color: var(--mj-text-muted);\n}\n\n.editor-agent-tree[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n max-height: 280px;\n overflow: auto;\n background: var(--mj-bg-surface);\n}\n\n\n.editor-advanced-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 10px 12px;\n border: 1px dashed var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n text-align: left;\n}\n\n.editor-advanced-toggle[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.editor-advanced-toggle[_ngcontent-%COMP%] .editor-hint-inline[_ngcontent-%COMP%] {\n font-weight: 400;\n font-size: 11px;\n color: var(--mj-text-muted);\n}"] });
|
|
1054
1054
|
}
|
|
1055
1055
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NewRoutineComponent, [{
|
|
1056
1056
|
type: Component,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new-routine.component.js","sourceRoot":"","sources":["../../src/lib/new-routine.component.ts","../../src/lib/new-routine.component.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { CompositeKey, IMetadataProvider, RunView } from '@memberjunction/core';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { MJUserRoutineEntity, MJUserRoutineRecipientEntity, UserRoutineEngine } from '@memberjunction/core-entities';\nimport {\n BuildCronExpression,\n CRON_DAY_NAMES,\n CronPresetKind,\n CronSchedule,\n DescribeCronExpression,\n IsPlausibleCronExpression,\n NormalizeUUID,\n ParseCronExpression,\n} from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { AfterNodeSelectEventArgs, TreeBranchConfig, TreeLeafConfig } from '@memberjunction/ng-trees';\nimport {\n FromDateTimeLocal,\n GetLocalTimezone,\n GetTimezoneOptions,\n IsPlausibleEmail,\n ParseSkillIDs,\n SerializeSkillIDs,\n ToDateTimeLocal,\n ValidateOptionalJson,\n} from './routine-ui-helpers';\nimport { LoadRoutineTargetCatalog, RoutineSkillOption, RoutineTargetCatalog } from './routine-target-catalog';\nimport { AfterRoutineCreatedEventArgs, BeforeRoutineCreatedEventArgs } from './user-routines-events';\n\n/** One editable recipient row (existing rows carry their entity for update/delete). */\ninterface RecipientRow {\n Entity: MJUserRoutineRecipientEntity | null;\n Mode: 'user' | 'email';\n UserID: string | null;\n Email: string;\n Channel: MJUserRoutineRecipientEntity['Channel'];\n}\n\n/** Minimal user shape for the recipient user picker. */\ninterface UserOption {\n ID: string;\n Name: string;\n Email: string | null;\n}\n\n/**\n * Create/edit form for a User Routine. Routines run an AI AGENT on a schedule\n * (TargetType is implicitly 'Agent') — the agent is chosen from a categorical tree\n * grouped by Agent Category, showing each agent's own IconClass, with Realtime-type\n * agents excluded (interactive-only). Also covers the initial message, optional JSON\n * payload, AI Skills pre-activation, cron presets + advanced escape hatch, IANA\n * timezone, activation window, notification settings, and the ordered recipients list.\n *\n * Reusable (Generic) component: no Router, no page chrome. The host mounts it\n * (slide-in / dialog / inline), passes `RoutineID` (null = create), and reacts to\n * `Saved` / `Cancelled` plus the cancelable `BeforeRoutineCreated` /\n * `AfterRoutineCreated` pair for new routines. All persistence flows through MJ\n * entity objects with explicit `Save()` boolean checks; failures surface\n * `LatestResult.CompleteMessage`. Cached routine/recipient data comes from\n * {@link UserRoutineEngine}.\n */\n@Component({\n standalone: false,\n selector: 'mj-new-routine',\n templateUrl: './new-routine.component.html',\n styleUrls: ['./new-routine.component.css'],\n})\nexport class NewRoutineComponent extends BaseAngularComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n private notifications = inject(MJNotificationService);\n\n // ---------------------------------------------------------------\n // Inputs / Outputs\n // ---------------------------------------------------------------\n private _routineID: string | null = null;\n /** ID of the routine to edit, or null to create a new one. */\n @Input()\n public set RoutineID(value: string | null) {\n if (value !== this._routineID) {\n this._routineID = value;\n if (this.initialized) {\n void this.reload();\n }\n }\n }\n public get RoutineID(): string | null {\n return this._routineID;\n }\n\n /** Emitted after a successful save (routine + recipients persisted) — create AND edit. */\n @Output() Saved = new EventEmitter<MJUserRoutineEntity>();\n /** Emitted when the user cancels without saving. */\n @Output() Cancelled = new EventEmitter<void>();\n /** Cancelable: fires before a NEW routine is saved for the first time. */\n @Output() BeforeRoutineCreated = new EventEmitter<BeforeRoutineCreatedEventArgs>();\n /** Informational: fires after a new routine (and its recipients) was persisted. */\n @Output() AfterRoutineCreated = new EventEmitter<AfterRoutineCreatedEventArgs>();\n\n // ---------------------------------------------------------------\n // Form state\n // ---------------------------------------------------------------\n public Name = '';\n public Description = '';\n /** The selected agent's ID (TargetType is implicitly 'Agent'). */\n public TargetID: string | null = null;\n public InitialMessage = '';\n public StartingPayloadText = '';\n public SelectedSkillIDs: string[] = [];\n public RoutineType: MJUserRoutineEntity['RoutineType'] = 'Scheduled';\n\n public ScheduleKind: CronPresetKind = 'daily';\n /** Minute past each hour for the hourly preset. */\n public ScheduleMinute = 0;\n /** \"HH:MM\" run time for daily/weekly/monthly presets. */\n public ScheduleTime = '09:00';\n public ScheduleDayOfWeek = 1;\n public ScheduleDayOfMonth = 1;\n public RawCron = '';\n\n public Timezone: string = GetLocalTimezone();\n public StartAtLocal = '';\n public EndAtLocal = '';\n\n public NotifyCondition: MJUserRoutineEntity['NotifyCondition'] = 'Always';\n public NotifyViaInApp = true;\n public NotifyViaEmail = false;\n public Recipients: RecipientRow[] = [];\n\n // ---------------------------------------------------------------\n // Options / status\n // ---------------------------------------------------------------\n /**\n * Progressive disclosure: the basic view (name / agent / message / frequency)\n * covers the 80% path; everything else lives behind this toggle. Auto-expands\n * when editing a routine that already uses advanced settings.\n */\n public ShowAdvanced = false;\n\n public Catalog: RoutineTargetCatalog | null = null;\n public UserOptions: UserOption[] = [];\n public TimezoneOptions: string[] = GetTimezoneOptions();\n public IsLoading = true;\n public IsSaving = false;\n public ValidationErrors: string[] = [];\n\n /** Tree config for the agent-category branches. */\n public AgentTreeBranchConfig: TreeBranchConfig = {\n EntityName: 'MJ: AI Agent Categories',\n DisplayField: 'Name',\n ParentIDField: 'ParentID',\n DefaultIcon: 'fa-solid fa-folder',\n OrderBy: 'Name ASC',\n };\n /** Tree config for the pickable agents (built at load time — excludes Realtime types). */\n public AgentTreeLeafConfig: TreeLeafConfig | undefined;\n /** Tree selection binding (single agent). */\n public SelectedAgentIDs: string[] = [];\n\n public readonly DayNames = CRON_DAY_NAMES;\n public readonly DayOfWeekOptions = CRON_DAY_NAMES.map((name, i) => ({ text: name, value: i }));\n public readonly DayOfMonthOptions = Array.from({ length: 31 }, (_, i) => ({ text: `${i + 1}`, value: i + 1 }));\n public readonly ScheduleKindOptions: Array<{ Value: CronPresetKind; Label: string }> = [\n { Value: 'hourly', Label: 'Hourly' },\n { Value: 'daily', Label: 'Daily' },\n { Value: 'weekly', Label: 'Weekly' },\n { Value: 'monthly', Label: 'Monthly' },\n { Value: 'advanced', Label: 'Advanced (cron)' },\n ];\n public readonly NotifyConditionOptions = [\n { text: 'Always — after every run', value: 'Always' },\n { text: 'On success only', value: 'OnSuccess' },\n { text: 'On failure only', value: 'OnFailure' },\n { text: 'On change — when the result differs from the prior run', value: 'OnChange' },\n ];\n public readonly ChannelOptions = [\n { text: 'In-app', value: 'InApp' },\n { text: 'Email', value: 'Email' },\n ];\n public readonly RecipientModeOptions = [\n { text: 'MJ user', value: 'user' },\n { text: 'External email', value: 'email' },\n ];\n\n private editingEntity: MJUserRoutineEntity | null = null;\n private deletedRecipients: MJUserRoutineRecipientEntity[] = [];\n private initialized = false;\n\n async ngOnInit(): Promise<void> {\n this.initialized = true;\n await this.reload();\n }\n\n /** True when editing an existing routine (vs. creating a new one). */\n public get IsEdit(): boolean {\n return this._routineID != null;\n }\n\n /** Active skills available for pre-activation. */\n public get SkillOptions(): RoutineSkillOption[] {\n return this.Catalog?.Skills ?? [];\n }\n\n /** Name of the currently selected agent (empty when none). */\n public get SelectedAgentName(): string {\n if (!this.TargetID) {\n return '';\n }\n return this.Catalog?.NameByID.get(NormalizeUUID(this.TargetID)) ?? '';\n }\n\n /** IconClass of the currently selected agent (robot fallback). */\n public get SelectedAgentIcon(): string {\n if (!this.TargetID) {\n return 'fa-solid fa-robot';\n }\n return this.Catalog?.IconByID.get(NormalizeUUID(this.TargetID)) ?? 'fa-solid fa-robot';\n }\n\n /** Live human-readable preview of the schedule being built. */\n public get SchedulePreview(): string {\n return DescribeCronExpression(this.buildCron());\n }\n\n /** Helper text under the RoutineType toggle. */\n public get RoutineTypeHelp(): string {\n return this.RoutineType === 'Scheduled'\n ? 'Runs on the schedule and notifies per the notification condition.'\n : 'Runs on the schedule and hashes each result — pair with the \"On change\" condition to be notified only when the result changes.';\n }\n\n /** Handles agent selection from the category tree (leaf nodes only). */\n /** The selected agent as a CompositeKey for the tree-dropdown's Value binding. */\n public get SelectedAgentKey(): CompositeKey | null {\n return this.TargetID ? CompositeKey.FromID(this.TargetID) : null;\n }\n\n public OnAgentNodeSelected(args: AfterNodeSelectEventArgs): void {\n if (args.Node.Type === 'leaf') {\n this.TargetID = args.Node.ID;\n this.SelectedAgentIDs = [args.Node.ID];\n this.cdr.markForCheck();\n }\n }\n\n public SetScheduleKind(kind: CronPresetKind): void {\n if (kind === this.ScheduleKind) {\n return;\n }\n if (kind === 'advanced' && !this.RawCron.trim()) {\n // Seed the advanced box from the current preset so nothing is lost\n this.RawCron = this.buildCron();\n }\n this.ScheduleKind = kind;\n this.cdr.markForCheck();\n }\n\n /** Toggles a skill in/out of the RequestedSkillIDs selection. */\n public ToggleSkill(skillID: string): void {\n const index = this.SelectedSkillIDs.indexOf(skillID);\n if (index >= 0) {\n this.SelectedSkillIDs = this.SelectedSkillIDs.filter((id) => id !== skillID);\n } else {\n this.SelectedSkillIDs = [...this.SelectedSkillIDs, skillID];\n }\n this.cdr.markForCheck();\n }\n\n public IsSkillSelected(skillID: string): boolean {\n return this.SelectedSkillIDs.includes(skillID);\n }\n\n // ---------------------------------------------------------------\n // Recipients\n // ---------------------------------------------------------------\n public AddRecipient(): void {\n this.Recipients = [\n ...this.Recipients,\n { Entity: null, Mode: 'user', UserID: null, Email: '', Channel: 'InApp' },\n ];\n void this.ensureUserOptions();\n }\n\n public RemoveRecipient(index: number): void {\n const row = this.Recipients[index];\n if (row?.Entity) {\n this.deletedRecipients.push(row.Entity);\n }\n this.Recipients = this.Recipients.filter((_, i) => i !== index);\n }\n\n /** Moves a recipient up/down — the saved Sequence is the row index. */\n public MoveRecipient(index: number, delta: -1 | 1): void {\n const target = index + delta;\n if (target < 0 || target >= this.Recipients.length) {\n return;\n }\n const next = [...this.Recipients];\n [next[index], next[target]] = [next[target], next[index]];\n this.Recipients = next;\n }\n\n /** When the row's mode flips, clear the other identity field. */\n public OnRecipientModeChange(row: RecipientRow): void {\n if (row.Mode === 'user') {\n row.Email = '';\n void this.ensureUserOptions();\n } else {\n row.UserID = null;\n }\n }\n\n // ---------------------------------------------------------------\n // Save / cancel\n // ---------------------------------------------------------------\n public Cancel(): void {\n this.Cancelled.emit();\n }\n\n public async Save(): Promise<void> {\n if (this.IsSaving) {\n return;\n }\n this.ValidationErrors = this.validate();\n if (this.ValidationErrors.length > 0) {\n this.cdr.markForCheck();\n return;\n }\n\n this.IsSaving = true;\n this.cdr.markForCheck();\n try {\n const p = this.ProviderToUse;\n const isNew = !this.IsEdit;\n const routine =\n this.editingEntity ??\n (await p.GetEntityObject<MJUserRoutineEntity>('MJ: User Routines', p.CurrentUser));\n if (isNew) {\n routine.UserID = p.CurrentUser.ID;\n }\n\n routine.Name = this.Name.trim();\n routine.Description = this.Description.trim() || null;\n routine.RoutineType = this.RoutineType;\n routine.TargetType = 'Agent';\n // Validated non-null in validate()\n routine.TargetID = this.TargetID as string;\n routine.InitialMessage = this.InitialMessage.trim() || null;\n routine.StartingPayload = this.StartingPayloadText.trim() || null;\n routine.RequestedSkillIDs = SerializeSkillIDs(this.SelectedSkillIDs);\n routine.CronExpression = this.buildCron();\n routine.Timezone = this.Timezone;\n routine.StartAt = FromDateTimeLocal(this.StartAtLocal);\n routine.EndAt = FromDateTimeLocal(this.EndAtLocal);\n routine.NotifyCondition = this.NotifyCondition;\n routine.NotifyViaInApp = this.NotifyViaInApp;\n routine.NotifyViaEmail = this.NotifyViaEmail;\n\n if (isNew) {\n const beforeArgs = new BeforeRoutineCreatedEventArgs(routine);\n this.BeforeRoutineCreated.emit(beforeArgs);\n if (beforeArgs.Cancel) {\n return;\n }\n }\n\n const saved = await routine.Save();\n if (!saved) {\n this.ValidationErrors = [\n `Save failed: ${routine.LatestResult?.CompleteMessage ?? 'unknown error'}`,\n ];\n return;\n }\n\n const recipientErrors = await this.saveRecipients(routine);\n if (recipientErrors.length > 0) {\n this.ValidationErrors = recipientErrors;\n return;\n }\n\n if (isNew) {\n // Re-scope the engine's dependent (recipients/runs) configs to include\n // the new routine — their client-side filter is a Config-time snapshot.\n await this.engine().Refresh(p.CurrentUser);\n this.AfterRoutineCreated.emit(new AfterRoutineCreatedEventArgs(routine));\n }\n\n this.notifications.CreateSimpleNotification(\n isNew ? `'${routine.Name}' created` : `'${routine.Name}' updated`,\n 'success',\n 3000\n );\n this.Saved.emit(routine);\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n // ---------------------------------------------------------------\n // Internals\n // ---------------------------------------------------------------\n private engine(): UserRoutineEngine {\n return UserRoutineEngine.GetProviderInstance<UserRoutineEngine>(this.ProviderToUse, UserRoutineEngine) as UserRoutineEngine;\n }\n\n /** True when the loaded routine differs from the basic-path defaults in any advanced field. */\n private usesAdvancedSettings(): boolean {\n return this.Description.trim().length > 0\n || this.RoutineType === 'Monitoring'\n || this.StartingPayloadText.trim().length > 0\n || this.SelectedSkillIDs.length > 0\n || this.Timezone !== GetLocalTimezone()\n || this.StartAtLocal.trim().length > 0\n || this.EndAtLocal.trim().length > 0\n || this.NotifyCondition !== 'Always'\n || !this.NotifyViaInApp\n || this.NotifyViaEmail\n || this.Recipients.length > 0;\n }\n\n private async reload(): Promise<void> {\n this.IsLoading = true;\n this.ValidationErrors = [];\n this.deletedRecipients = [];\n this.cdr.markForCheck();\n try {\n const p = this.ProviderToUse;\n const [catalog] = await Promise.all([\n LoadRoutineTargetCatalog(p),\n this.engine().Config(false, p.CurrentUser, p),\n ]);\n this.Catalog = catalog;\n this.buildAgentTreeConfig(p);\n if (this._routineID) {\n await this.loadExisting(this._routineID);\n this.ShowAdvanced = this.usesAdvancedSettings();\n } else {\n this.resetForNew();\n this.ShowAdvanced = false;\n }\n if (this.Recipients.some((r) => r.Mode === 'user')) {\n await this.ensureUserOptions();\n }\n } catch (e) {\n this.ValidationErrors = [\n `Failed to load the editor: ${e instanceof Error ? e.message : 'unknown error'}`,\n ];\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Builds the agent tree leaf config: Active, root-level agents only, EXCLUDING\n * agents whose type is the Realtime agent type. The exclusion is expressed as an\n * inline NOT IN list of type IDs resolved from metadata BY NAME (never hardcoded).\n */\n private buildAgentTreeConfig(provider: IMetadataProvider): void {\n const realtimeTypeIDs = this.resolveRealtimeTypeIDs(provider);\n const filters = [`Status='Active'`, `ParentID IS NULL`];\n if (realtimeTypeIDs.length > 0) {\n const inList = realtimeTypeIDs.map((id) => `'${id}'`).join(',');\n filters.push(`(TypeID IS NULL OR TypeID NOT IN (${inList}))`);\n }\n this.AgentTreeLeafConfig = {\n EntityName: 'MJ: AI Agents',\n ParentField: 'CategoryID',\n DisplayField: 'Name',\n IconField: 'IconClass',\n DefaultIcon: 'fa-solid fa-robot',\n ExtraFilter: filters.join(' AND '),\n OrderBy: 'Name ASC',\n };\n }\n\n /** Realtime agent-type IDs resolved from the cached AI metadata by type NAME. */\n private resolveRealtimeTypeIDs(provider: IMetadataProvider): string[] {\n // The catalog load above already Config'd AIEngineBase for this provider —\n // reuse its cached AgentTypes through the provider-scoped instance.\n const engine = AIEngineBase.GetProviderInstance<AIEngineBase>(provider, AIEngineBase) as AIEngineBase;\n return engine.AgentTypes\n .filter((t) => t.Name?.trim().toLowerCase() === 'realtime')\n .map((t) => t.ID);\n }\n\n private resetForNew(): void {\n this.editingEntity = null;\n this.Name = '';\n this.Description = '';\n this.TargetID = null;\n this.SelectedAgentIDs = [];\n this.InitialMessage = '';\n this.StartingPayloadText = '';\n this.SelectedSkillIDs = [];\n this.RoutineType = 'Scheduled';\n this.ScheduleKind = 'daily';\n this.ScheduleMinute = 0;\n this.ScheduleTime = '09:00';\n this.ScheduleDayOfWeek = 1;\n this.ScheduleDayOfMonth = 1;\n this.RawCron = '';\n this.Timezone = GetLocalTimezone();\n this.StartAtLocal = '';\n this.EndAtLocal = '';\n this.NotifyCondition = 'Always';\n this.NotifyViaInApp = true;\n this.NotifyViaEmail = false;\n this.Recipients = [];\n }\n\n private async loadExisting(routineID: string): Promise<void> {\n const p = this.ProviderToUse;\n // Prefer the engine's cached entity; fall back to a direct load (e.g., deep link\n // into a routine saved elsewhere before the cache refreshed).\n let routine = this.engine().GetRoutineByID(routineID) ?? null;\n if (!routine) {\n const loadedEntity = await p.GetEntityObject<MJUserRoutineEntity>('MJ: User Routines', p.CurrentUser);\n const loaded = await loadedEntity.Load(routineID);\n routine = loaded ? loadedEntity : null;\n }\n if (!routine) {\n this.ValidationErrors = [`Routine ${routineID} could not be loaded.`];\n this.resetForNew();\n return;\n }\n this.editingEntity = routine;\n this.Name = routine.Name;\n this.Description = routine.Description ?? '';\n this.TargetID = routine.TargetID;\n this.SelectedAgentIDs = routine.TargetID ? [routine.TargetID] : [];\n this.InitialMessage = routine.InitialMessage ?? '';\n this.StartingPayloadText = routine.StartingPayload ?? '';\n this.SelectedSkillIDs = ParseSkillIDs(routine.RequestedSkillIDs);\n this.RoutineType = routine.RoutineType;\n this.applyCron(ParseCronExpression(routine.CronExpression));\n this.Timezone = routine.Timezone;\n this.StartAtLocal = ToDateTimeLocal(routine.StartAt);\n this.EndAtLocal = ToDateTimeLocal(routine.EndAt);\n this.NotifyCondition = routine.NotifyCondition;\n this.NotifyViaInApp = routine.NotifyViaInApp;\n this.NotifyViaEmail = routine.NotifyViaEmail;\n this.loadRecipientRows(routineID);\n }\n\n private applyCron(schedule: CronSchedule): void {\n this.ScheduleKind = schedule.Kind;\n this.ScheduleMinute = schedule.Minute;\n this.ScheduleTime = `${schedule.Hour.toString().padStart(2, '0')}:${schedule.Minute.toString().padStart(2, '0')}`;\n this.ScheduleDayOfWeek = schedule.DayOfWeek;\n this.ScheduleDayOfMonth = schedule.DayOfMonth;\n this.RawCron = schedule.Raw;\n }\n\n private buildCron(): string {\n const { hour, minute } = this.parseScheduleTime();\n const schedule: CronSchedule = {\n Kind: this.ScheduleKind,\n Minute: this.ScheduleKind === 'hourly' ? this.clampMinute(this.ScheduleMinute) : minute,\n Hour: hour,\n DayOfWeek: this.ScheduleDayOfWeek,\n DayOfMonth: this.ScheduleDayOfMonth,\n Raw: this.RawCron,\n };\n return BuildCronExpression(schedule);\n }\n\n private parseScheduleTime(): { hour: number; minute: number } {\n const match = /^(\\d{1,2}):(\\d{2})$/.exec(this.ScheduleTime.trim());\n if (!match) {\n return { hour: 9, minute: 0 };\n }\n return {\n hour: Math.min(23, Math.max(0, parseInt(match[1], 10))),\n minute: this.clampMinute(parseInt(match[2], 10)),\n };\n }\n\n private clampMinute(minute: number): number {\n return Math.min(59, Math.max(0, Math.round(minute ?? 0)));\n }\n\n /** Builds the editable recipient rows from the engine's cached recipients. */\n private loadRecipientRows(routineID: string): void {\n this.Recipients = this.engine()\n .RecipientsForRoutine(routineID)\n .map((entity) => ({\n Entity: entity,\n Mode: entity.UserID ? ('user' as const) : ('email' as const),\n UserID: entity.UserID,\n Email: entity.Email ?? '',\n Channel: entity.Channel,\n }));\n }\n\n /** Lazily loads the user picker options the first time a user-mode row exists. */\n private async ensureUserOptions(): Promise<void> {\n if (this.UserOptions.length > 0) {\n return;\n }\n const p = this.ProviderToUse;\n const rv = RunView.FromMetadataProvider(p);\n const result = await rv.RunView<UserOption>(\n {\n EntityName: 'MJ: Users',\n Fields: ['ID', 'Name', 'Email'],\n ExtraFilter: `IsActive=1`,\n OrderBy: 'Name ASC',\n ResultType: 'simple',\n },\n p.CurrentUser\n );\n if (result.Success) {\n this.UserOptions = result.Results ?? [];\n this.cdr.markForCheck();\n }\n }\n\n private validate(): string[] {\n const errors: string[] = [];\n if (!this.Name.trim()) {\n errors.push('Name is required.');\n }\n if (!this.TargetID) {\n errors.push('Select the agent this routine should run.');\n }\n if (this.ScheduleKind === 'advanced' && !IsPlausibleCronExpression(this.RawCron)) {\n errors.push('The advanced cron expression must have 5 (or 6) space-separated fields.');\n }\n if (!this.Timezone?.trim()) {\n errors.push('Timezone is required.');\n }\n const payloadCheck = ValidateOptionalJson(this.StartingPayloadText);\n if (!payloadCheck.Valid) {\n errors.push(`Starting payload is not valid JSON: ${payloadCheck.Error}`);\n }\n const startAt = FromDateTimeLocal(this.StartAtLocal);\n const endAt = FromDateTimeLocal(this.EndAtLocal);\n if (startAt && endAt && endAt.getTime() <= startAt.getTime()) {\n errors.push('End of the activation window must be after its start.');\n }\n this.Recipients.forEach((row, i) => {\n if (row.Mode === 'user' && !row.UserID) {\n errors.push(`Recipient ${i + 1}: choose a user (or switch the row to an external email).`);\n }\n if (row.Mode === 'email' && !IsPlausibleEmail(row.Email)) {\n errors.push(`Recipient ${i + 1}: enter a valid email address.`);\n }\n });\n return errors;\n }\n\n /** Persists recipient rows in order (Sequence = index) and deletes removed rows. */\n private async saveRecipients(routine: MJUserRoutineEntity): Promise<string[]> {\n const p = this.ProviderToUse;\n const errors: string[] = [];\n\n for (const entity of this.deletedRecipients) {\n const deleted = await entity.Delete();\n if (!deleted) {\n errors.push(\n `Failed to remove a recipient: ${entity.LatestResult?.CompleteMessage ?? 'unknown error'}`\n );\n }\n }\n this.deletedRecipients = [];\n\n for (let i = 0; i < this.Recipients.length; i++) {\n const row = this.Recipients[i];\n const entity =\n row.Entity ??\n (await p.GetEntityObject<MJUserRoutineRecipientEntity>('MJ: User Routine Recipients', p.CurrentUser));\n entity.RoutineID = routine.ID;\n entity.UserID = row.Mode === 'user' ? row.UserID : null;\n entity.Email = row.Mode === 'email' ? row.Email.trim() : null;\n entity.Channel = row.Channel;\n entity.Sequence = i;\n const saved = await entity.Save();\n if (saved) {\n row.Entity = entity;\n } else {\n errors.push(\n `Failed to save recipient ${i + 1}: ${entity.LatestResult?.CompleteMessage ?? 'unknown error'}`\n );\n }\n }\n return errors;\n }\n}\n","@if (IsLoading) {\n <div class=\"editor-loading\">\n <mj-loading text=\"Loading editor...\" size=\"medium\"></mj-loading>\n </div>\n} @else {\n <div class=\"routine-editor\">\n\n @if (ValidationErrors.length > 0) {\n <mj-alert Variant=\"error\">\n <ul class=\"editor-errors\">\n @for (error of ValidationErrors; track error) {\n <li>{{ error }}</li>\n }\n </ul>\n </mj-alert>\n }\n\n <!-- ═══════════ BASICS (the 80% path: name, agent, message, schedule) ═══════════ -->\n <section class=\"editor-section\">\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-name\">Name <span class=\"editor-required\">*</span></label>\n <input id=\"routine-name\" class=\"mj-input\" type=\"text\" [(ngModel)]=\"Name\" placeholder=\"e.g. Morning membership digest\" />\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Which agent should this routine run? <span class=\"editor-required\">*</span></label>\n @if (AgentTreeLeafConfig) {\n <mj-tree-dropdown\n [BranchConfig]=\"AgentTreeBranchConfig\"\n [LeafConfig]=\"AgentTreeLeafConfig\"\n DefaultExpansion=\"all\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n [Value]=\"SelectedAgentKey\"\n [Clearable]=\"false\"\n Placeholder=\"Select an agent...\"\n (AfterNodeSelect)=\"OnAgentNodeSelected($event)\">\n </mj-tree-dropdown>\n }\n <div class=\"editor-hint\">Active agents only, grouped by category — realtime (voice) agents are interactive-only and can't be scheduled.</div>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-message\">Message sent on each run</label>\n <!-- Composer mention editor in DISCOVERY mode: trigger providers are ClassFactory-\n discovered (ng-conversations registers '@' agent / '#' record / '/' skill plugins\n when loaded). '@' agent mentions are excluded — the routine's agent is fixed by\n the picker above. With no providers registered this degrades gracefully to a\n plain text editor. -->\n <mj-mention-editor id=\"routine-message\"\n [(ngModel)]=\"InitialMessage\"\n placeholder=\"The message the routine sends to the agent each time it runs\"\n [ExcludedTriggerKeys]=\"['agent-mentions']\"\n [Provider]=\"Provider\"\n [enableAttachments]=\"false\"\n [autoFocus]=\"false\"\n [currentUser]=\"ProviderToUse.CurrentUser\"></mj-mention-editor>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Frequency</label>\n <div class=\"editor-segmented editor-segmented--wrap\" role=\"radiogroup\" aria-label=\"Schedule frequency\">\n @for (option of ScheduleKindOptions; track option.Value) {\n <button type=\"button\" class=\"editor-segment\"\n [class.editor-segment--active]=\"ScheduleKind === option.Value\"\n (click)=\"SetScheduleKind(option.Value)\">\n {{ option.Label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"editor-schedule-detail\">\n @switch (ScheduleKind) {\n @case ('hourly') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">At minute</label>\n <mj-numeric-input [(ngModel)]=\"ScheduleMinute\" [Min]=\"0\" [Max]=\"59\" [Step]=\"5\"></mj-numeric-input>\n <span class=\"editor-hint-inline\">past every hour</span>\n </div>\n }\n @case ('daily') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">At</label>\n <input class=\"mj-input editor-time-input\" type=\"time\" [(ngModel)]=\"ScheduleTime\" />\n <span class=\"editor-hint-inline\">every day</span>\n </div>\n }\n @case ('weekly') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">Every</label>\n <mj-dropdown class=\"editor-inline-dropdown\" [Data]=\"DayOfWeekOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"ScheduleDayOfWeek\"></mj-dropdown>\n <label class=\"editor-label\">at</label>\n <input class=\"mj-input editor-time-input\" type=\"time\" [(ngModel)]=\"ScheduleTime\" />\n </div>\n }\n @case ('monthly') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">On day</label>\n <mj-dropdown class=\"editor-inline-dropdown\" [Data]=\"DayOfMonthOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"ScheduleDayOfMonth\"></mj-dropdown>\n <label class=\"editor-label\">at</label>\n <input class=\"mj-input editor-time-input\" type=\"time\" [(ngModel)]=\"ScheduleTime\" />\n </div>\n }\n @case ('advanced') {\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-cron\">Cron expression</label>\n <input id=\"routine-cron\" class=\"mj-input editor-mono\" type=\"text\" [(ngModel)]=\"RawCron\"\n placeholder=\"minute hour day-of-month month day-of-week\" />\n </div>\n }\n }\n <div class=\"editor-schedule-preview\">\n <i class=\"fa-solid fa-calendar-check\"></i> {{ SchedulePreview || 'No schedule yet' }}\n </div>\n </div>\n </section>\n\n <!-- ═══════════ ADVANCED (progressive disclosure — collapsed by default) ═══════════ -->\n <button type=\"button\" class=\"editor-advanced-toggle\" (click)=\"ShowAdvanced = !ShowAdvanced\"\n [attr.aria-expanded]=\"ShowAdvanced\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!ShowAdvanced\" [class.fa-chevron-down]=\"ShowAdvanced\"></i>\n Advanced options\n <span class=\"editor-hint-inline\">description · monitoring · timezone · window · payload · skills · notifications</span>\n </button>\n\n @if (ShowAdvanced) {\n <section class=\"editor-section\">\n <h3 class=\"editor-section-title\"><i class=\"fa-solid fa-circle-info\"></i> Details</h3>\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-description\">Description</label>\n <textarea id=\"routine-description\" class=\"mj-textarea\" rows=\"2\" [(ngModel)]=\"Description\"\n placeholder=\"What does this routine do?\"></textarea>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Routine type</label>\n <div class=\"editor-segmented\" role=\"radiogroup\" aria-label=\"Routine type\">\n <button type=\"button\" class=\"editor-segment\"\n [class.editor-segment--active]=\"RoutineType === 'Scheduled'\"\n (click)=\"RoutineType = 'Scheduled'\">\n <i class=\"fa-solid fa-clock\"></i> Scheduled\n </button>\n <button type=\"button\" class=\"editor-segment\"\n [class.editor-segment--active]=\"RoutineType === 'Monitoring'\"\n (click)=\"RoutineType = 'Monitoring'\">\n <i class=\"fa-solid fa-eye\"></i> Monitoring\n </button>\n </div>\n <div class=\"editor-hint\">{{ RoutineTypeHelp }}</div>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Timezone</label>\n <mj-combobox\n [Data]=\"TimezoneOptions\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Select an IANA timezone...\"\n [(ngModel)]=\"Timezone\">\n </mj-combobox>\n </div>\n\n <div class=\"editor-field-row\">\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-startat\">Active from (optional)</label>\n <input id=\"routine-startat\" class=\"mj-input\" type=\"datetime-local\" [(ngModel)]=\"StartAtLocal\" />\n </div>\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-endat\">Active until (optional)</label>\n <input id=\"routine-endat\" class=\"mj-input\" type=\"datetime-local\" [(ngModel)]=\"EndAtLocal\" />\n </div>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Starting payload (JSON, optional)</label>\n <div class=\"editor-code\">\n <mj-code-editor [(ngModel)]=\"StartingPayloadText\" language=\"json\"\n placeholder='{ \"example\": true }'></mj-code-editor>\n </div>\n <div class=\"editor-hint\">Passed to the agent on each run. Leave blank for none.</div>\n </div>\n\n @if (SkillOptions.length > 0) {\n <div class=\"editor-field\">\n <label class=\"editor-label\">Pre-activate skills (optional)</label>\n <div class=\"editor-skills\">\n @for (skill of SkillOptions; track skill.ID) {\n <button type=\"button\" class=\"editor-skill-chip\"\n [class.editor-skill-chip--selected]=\"IsSkillSelected(skill.ID)\"\n [title]=\"skill.Description ?? skill.Name\"\n (click)=\"ToggleSkill(skill.ID)\">\n <i [class]=\"skill.IconClass || 'fa-solid fa-wand-magic-sparkles'\"></i>\n {{ skill.Name }}\n @if (IsSkillSelected(skill.ID)) {\n <i class=\"fa-solid fa-check editor-skill-check\"></i>\n }\n </button>\n }\n </div>\n <div class=\"editor-hint\">Selected skills start every run with their instructions and tools in effect (subject to the agent's skill gates).</div>\n </div>\n }\n </section>\n\n <section class=\"editor-section\">\n <h3 class=\"editor-section-title\"><i class=\"fa-solid fa-bell\"></i> Notifications</h3>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Notify me</label>\n <mj-dropdown [Data]=\"NotifyConditionOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"NotifyCondition\"></mj-dropdown>\n </div>\n\n <div class=\"editor-field editor-field--inline editor-switches\">\n <mj-switch [(ngModel)]=\"NotifyViaInApp\" OnLabel=\"In-app\" OffLabel=\"In-app\"></mj-switch>\n <mj-switch [(ngModel)]=\"NotifyViaEmail\" OnLabel=\"Email\" OffLabel=\"Email\"></mj-switch>\n </div>\n\n <div class=\"editor-field\">\n <div class=\"editor-recipients-header\">\n <label class=\"editor-label\">Additional recipients</label>\n <button mjButton variant=\"outline\" size=\"sm\" (click)=\"AddRecipient()\">\n <i class=\"fa-solid fa-plus\"></i> Add recipient\n </button>\n </div>\n @if (Recipients.length === 0) {\n <div class=\"editor-hint\">Only you (the owner) will be notified.</div>\n }\n @for (row of Recipients; track $index; let i = $index; let first = $first; let last = $last) {\n <div class=\"editor-recipient-row\">\n <div class=\"editor-recipient-order\">\n <button mjButton variant=\"icon\" size=\"sm\" title=\"Move up\" [disabled]=\"first\" (click)=\"MoveRecipient(i, -1)\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button mjButton variant=\"icon\" size=\"sm\" title=\"Move down\" [disabled]=\"last\" (click)=\"MoveRecipient(i, 1)\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n <mj-dropdown class=\"editor-recipient-mode\" [Data]=\"RecipientModeOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"row.Mode\" (ngModelChange)=\"OnRecipientModeChange(row)\"></mj-dropdown>\n @if (row.Mode === 'user') {\n <mj-combobox class=\"editor-recipient-target\" [Data]=\"UserOptions\" TextField=\"Name\" ValueField=\"ID\"\n [ValuePrimitive]=\"true\" Placeholder=\"Select a user...\" [(ngModel)]=\"row.UserID\"></mj-combobox>\n } @else {\n <input class=\"mj-input editor-recipient-target\" type=\"email\" placeholder=\"name@example.com\" [(ngModel)]=\"row.Email\" />\n }\n <mj-dropdown class=\"editor-recipient-channel\" [Data]=\"ChannelOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"row.Channel\"></mj-dropdown>\n <button mjButton variant=\"icon\" size=\"sm\" title=\"Remove recipient\" (click)=\"RemoveRecipient(i)\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </div>\n }\n </div>\n </section>\n }\n\n <!-- ======================= Footer (confirm LEFT, cancel RIGHT) ======================= -->\n <div class=\"editor-footer\">\n <button mjButton variant=\"primary\" size=\"md\" [disabled]=\"IsSaving\" (click)=\"Save()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n }\n {{ IsEdit ? 'Save Changes' : 'Create Routine' }}\n </button>\n <button mjButton variant=\"secondary\" size=\"md\" [disabled]=\"IsSaving\" (click)=\"Cancel()\">Cancel</button>\n </div>\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"new-routine.component.js","sourceRoot":"","sources":["../../src/lib/new-routine.component.ts","../../src/lib/new-routine.component.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { CompositeKey, IMetadataProvider, RunView } from '@memberjunction/core';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { MJUserRoutineEntity, MJUserRoutineRecipientEntity, UserRoutineEngine } from '@memberjunction/core-entities';\nimport {\n BuildCronExpression,\n CRON_DAY_NAMES,\n CronPresetKind,\n CronSchedule,\n DescribeCronExpression,\n IsPlausibleCronExpression,\n NormalizeUUID,\n ParseCronExpression,\n} from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { AfterNodeSelectEventArgs, TreeBranchConfig, TreeLeafConfig } from '@memberjunction/ng-trees';\nimport {\n FromDateTimeLocal,\n GetLocalTimezone,\n GetTimezoneOptions,\n IsPlausibleEmail,\n ParseSkillIDs,\n SerializeSkillIDs,\n ToDateTimeLocal,\n ValidateOptionalJson,\n} from './routine-ui-helpers';\nimport { LoadRoutineTargetCatalog, RoutineSkillOption, RoutineTargetCatalog } from './routine-target-catalog';\nimport { AfterRoutineCreatedEventArgs, BeforeRoutineCreatedEventArgs } from './user-routines-events';\n\n/** One editable recipient row (existing rows carry their entity for update/delete). */\ninterface RecipientRow {\n Entity: MJUserRoutineRecipientEntity | null;\n Mode: 'user' | 'email';\n UserID: string | null;\n Email: string;\n Channel: MJUserRoutineRecipientEntity['Channel'];\n}\n\n/** Minimal user shape for the recipient user picker. */\ninterface UserOption {\n ID: string;\n Name: string;\n Email: string | null;\n}\n\n/**\n * Create/edit form for a User Routine. Routines run an AI AGENT on a schedule\n * (TargetType is implicitly 'Agent') — the agent is chosen from a categorical tree\n * grouped by Agent Category, showing each agent's own IconClass, with Realtime-type\n * agents excluded (interactive-only). Also covers the initial message, optional JSON\n * payload, AI Skills pre-activation, cron presets + advanced escape hatch, IANA\n * timezone, activation window, notification settings, and the ordered recipients list.\n *\n * Reusable (Generic) component: no Router, no page chrome. The host mounts it\n * (slide-in / dialog / inline), passes `RoutineID` (null = create), and reacts to\n * `Saved` / `Cancelled` plus the cancelable `BeforeRoutineCreated` /\n * `AfterRoutineCreated` pair for new routines. All persistence flows through MJ\n * entity objects with explicit `Save()` boolean checks; failures surface\n * `LatestResult.CompleteMessage`. Cached routine/recipient data comes from\n * {@link UserRoutineEngine}.\n */\n@Component({\n standalone: false,\n selector: 'mj-new-routine',\n templateUrl: './new-routine.component.html',\n styleUrls: ['./new-routine.component.css'],\n})\nexport class NewRoutineComponent extends BaseAngularComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n private notifications = inject(MJNotificationService);\n\n // ---------------------------------------------------------------\n // Inputs / Outputs\n // ---------------------------------------------------------------\n private _routineID: string | null = null;\n /** ID of the routine to edit, or null to create a new one. */\n @Input()\n public set RoutineID(value: string | null) {\n if (value !== this._routineID) {\n this._routineID = value;\n if (this.initialized) {\n void this.reload();\n }\n }\n }\n public get RoutineID(): string | null {\n return this._routineID;\n }\n\n /** Emitted after a successful save (routine + recipients persisted) — create AND edit. */\n @Output() Saved = new EventEmitter<MJUserRoutineEntity>();\n /** Emitted when the user cancels without saving. */\n @Output() Cancelled = new EventEmitter<void>();\n /** Cancelable: fires before a NEW routine is saved for the first time. */\n @Output() BeforeRoutineCreated = new EventEmitter<BeforeRoutineCreatedEventArgs>();\n /** Informational: fires after a new routine (and its recipients) was persisted. */\n @Output() AfterRoutineCreated = new EventEmitter<AfterRoutineCreatedEventArgs>();\n\n // ---------------------------------------------------------------\n // Form state\n // ---------------------------------------------------------------\n public Name = '';\n public Description = '';\n /** The selected agent's ID (TargetType is implicitly 'Agent'). */\n public TargetID: string | null = null;\n public InitialMessage = '';\n public StartingPayloadText = '';\n public SelectedSkillIDs: string[] = [];\n public RoutineType: MJUserRoutineEntity['RoutineType'] = 'Scheduled';\n\n public ScheduleKind: CronPresetKind = 'daily';\n /** Minute past each hour for the hourly preset. */\n public ScheduleMinute = 0;\n /** \"HH:MM\" run time for daily/weekly/monthly presets. */\n public ScheduleTime = '09:00';\n public ScheduleDayOfWeek = 1;\n public ScheduleDayOfMonth = 1;\n public RawCron = '';\n\n public Timezone: string = GetLocalTimezone();\n public StartAtLocal = '';\n public EndAtLocal = '';\n\n public NotifyCondition: MJUserRoutineEntity['NotifyCondition'] = 'Always';\n public NotifyViaInApp = true;\n public NotifyViaEmail = false;\n public Recipients: RecipientRow[] = [];\n\n // ---------------------------------------------------------------\n // Options / status\n // ---------------------------------------------------------------\n /**\n * Progressive disclosure: the basic view (name / agent / message / frequency)\n * covers the 80% path; everything else lives behind this toggle. Auto-expands\n * when editing a routine that already uses advanced settings.\n */\n public ShowAdvanced = false;\n\n public Catalog: RoutineTargetCatalog | null = null;\n public UserOptions: UserOption[] = [];\n public TimezoneOptions: string[] = GetTimezoneOptions();\n public IsLoading = true;\n public IsSaving = false;\n public ValidationErrors: string[] = [];\n\n /** Tree config for the agent-category branches. */\n public AgentTreeBranchConfig: TreeBranchConfig = {\n EntityName: 'MJ: AI Agent Categories',\n DisplayField: 'Name',\n ParentIDField: 'ParentID',\n DefaultIcon: 'fa-solid fa-folder',\n OrderBy: 'Name ASC',\n };\n /** Tree config for the pickable agents (built at load time — excludes Realtime types). */\n public AgentTreeLeafConfig: TreeLeafConfig | undefined;\n /** Tree selection binding (single agent). */\n public SelectedAgentIDs: string[] = [];\n\n public readonly DayNames = CRON_DAY_NAMES;\n public readonly DayOfWeekOptions = CRON_DAY_NAMES.map((name, i) => ({ text: name, value: i }));\n public readonly DayOfMonthOptions = Array.from({ length: 31 }, (_, i) => ({ text: `${i + 1}`, value: i + 1 }));\n public readonly ScheduleKindOptions: Array<{ Value: CronPresetKind; Label: string }> = [\n { Value: 'hourly', Label: 'Hourly' },\n { Value: 'daily', Label: 'Daily' },\n { Value: 'weekly', Label: 'Weekly' },\n { Value: 'monthly', Label: 'Monthly' },\n { Value: 'advanced', Label: 'Advanced (cron)' },\n ];\n public readonly NotifyConditionOptions = [\n { text: 'Always — after every run', value: 'Always' },\n { text: 'On success only', value: 'OnSuccess' },\n { text: 'On failure only', value: 'OnFailure' },\n { text: 'On change — when the result differs from the prior run', value: 'OnChange' },\n ];\n public readonly ChannelOptions = [\n { text: 'In-app', value: 'InApp' },\n { text: 'Email', value: 'Email' },\n ];\n public readonly RecipientModeOptions = [\n { text: 'MJ user', value: 'user' },\n { text: 'External email', value: 'email' },\n ];\n\n private editingEntity: MJUserRoutineEntity | null = null;\n private deletedRecipients: MJUserRoutineRecipientEntity[] = [];\n private initialized = false;\n\n async ngOnInit(): Promise<void> {\n this.initialized = true;\n await this.reload();\n }\n\n /** True when editing an existing routine (vs. creating a new one). */\n public get IsEdit(): boolean {\n return this._routineID != null;\n }\n\n /** Active skills available for pre-activation. */\n public get SkillOptions(): RoutineSkillOption[] {\n return this.Catalog?.Skills ?? [];\n }\n\n /** Name of the currently selected agent (empty when none). */\n public get SelectedAgentName(): string {\n if (!this.TargetID) {\n return '';\n }\n return this.Catalog?.NameByID.get(NormalizeUUID(this.TargetID)) ?? '';\n }\n\n /** IconClass of the currently selected agent (robot fallback). */\n public get SelectedAgentIcon(): string {\n if (!this.TargetID) {\n return 'fa-solid fa-robot';\n }\n return this.Catalog?.IconByID.get(NormalizeUUID(this.TargetID)) ?? 'fa-solid fa-robot';\n }\n\n /** Live human-readable preview of the schedule being built. */\n public get SchedulePreview(): string {\n return DescribeCronExpression(this.buildCron());\n }\n\n /** Helper text under the RoutineType toggle. */\n public get RoutineTypeHelp(): string {\n return this.RoutineType === 'Scheduled'\n ? 'Runs on the schedule and notifies per the notification condition.'\n : 'Runs on the schedule and hashes each result — pair with the \"On change\" condition to be notified only when the result changes.';\n }\n\n /** Handles agent selection from the category tree (leaf nodes only). */\n /** The selected agent as a CompositeKey for the tree-dropdown's Value binding. */\n public get SelectedAgentKey(): CompositeKey | null {\n return this.TargetID ? CompositeKey.FromID(this.TargetID) : null; // first-pk-ok: TargetID is an MJ: AI Agents record (agent tree leaf) — core entity keyed by ID\n }\n\n public OnAgentNodeSelected(args: AfterNodeSelectEventArgs): void {\n if (args.Node.Type === 'leaf') {\n this.TargetID = args.Node.ID;\n this.SelectedAgentIDs = [args.Node.ID];\n this.cdr.markForCheck();\n }\n }\n\n public SetScheduleKind(kind: CronPresetKind): void {\n if (kind === this.ScheduleKind) {\n return;\n }\n if (kind === 'advanced' && !this.RawCron.trim()) {\n // Seed the advanced box from the current preset so nothing is lost\n this.RawCron = this.buildCron();\n }\n this.ScheduleKind = kind;\n this.cdr.markForCheck();\n }\n\n /** Toggles a skill in/out of the RequestedSkillIDs selection. */\n public ToggleSkill(skillID: string): void {\n const index = this.SelectedSkillIDs.indexOf(skillID);\n if (index >= 0) {\n this.SelectedSkillIDs = this.SelectedSkillIDs.filter((id) => id !== skillID);\n } else {\n this.SelectedSkillIDs = [...this.SelectedSkillIDs, skillID];\n }\n this.cdr.markForCheck();\n }\n\n public IsSkillSelected(skillID: string): boolean {\n return this.SelectedSkillIDs.includes(skillID);\n }\n\n // ---------------------------------------------------------------\n // Recipients\n // ---------------------------------------------------------------\n public AddRecipient(): void {\n this.Recipients = [\n ...this.Recipients,\n { Entity: null, Mode: 'user', UserID: null, Email: '', Channel: 'InApp' },\n ];\n void this.ensureUserOptions();\n }\n\n public RemoveRecipient(index: number): void {\n const row = this.Recipients[index];\n if (row?.Entity) {\n this.deletedRecipients.push(row.Entity);\n }\n this.Recipients = this.Recipients.filter((_, i) => i !== index);\n }\n\n /** Moves a recipient up/down — the saved Sequence is the row index. */\n public MoveRecipient(index: number, delta: -1 | 1): void {\n const target = index + delta;\n if (target < 0 || target >= this.Recipients.length) {\n return;\n }\n const next = [...this.Recipients];\n [next[index], next[target]] = [next[target], next[index]];\n this.Recipients = next;\n }\n\n /** When the row's mode flips, clear the other identity field. */\n public OnRecipientModeChange(row: RecipientRow): void {\n if (row.Mode === 'user') {\n row.Email = '';\n void this.ensureUserOptions();\n } else {\n row.UserID = null;\n }\n }\n\n // ---------------------------------------------------------------\n // Save / cancel\n // ---------------------------------------------------------------\n public Cancel(): void {\n this.Cancelled.emit();\n }\n\n public async Save(): Promise<void> {\n if (this.IsSaving) {\n return;\n }\n this.ValidationErrors = this.validate();\n if (this.ValidationErrors.length > 0) {\n this.cdr.markForCheck();\n return;\n }\n\n this.IsSaving = true;\n this.cdr.markForCheck();\n try {\n const p = this.ProviderToUse;\n const isNew = !this.IsEdit;\n const routine =\n this.editingEntity ??\n (await p.GetEntityObject<MJUserRoutineEntity>('MJ: User Routines', p.CurrentUser));\n if (isNew) {\n routine.UserID = p.CurrentUser.ID;\n }\n\n routine.Name = this.Name.trim();\n routine.Description = this.Description.trim() || null;\n routine.RoutineType = this.RoutineType;\n routine.TargetType = 'Agent';\n // Validated non-null in validate()\n routine.TargetID = this.TargetID as string;\n routine.InitialMessage = this.InitialMessage.trim() || null;\n routine.StartingPayload = this.StartingPayloadText.trim() || null;\n routine.RequestedSkillIDs = SerializeSkillIDs(this.SelectedSkillIDs);\n routine.CronExpression = this.buildCron();\n routine.Timezone = this.Timezone;\n routine.StartAt = FromDateTimeLocal(this.StartAtLocal);\n routine.EndAt = FromDateTimeLocal(this.EndAtLocal);\n routine.NotifyCondition = this.NotifyCondition;\n routine.NotifyViaInApp = this.NotifyViaInApp;\n routine.NotifyViaEmail = this.NotifyViaEmail;\n\n if (isNew) {\n const beforeArgs = new BeforeRoutineCreatedEventArgs(routine);\n this.BeforeRoutineCreated.emit(beforeArgs);\n if (beforeArgs.Cancel) {\n return;\n }\n }\n\n const saved = await routine.Save();\n if (!saved) {\n this.ValidationErrors = [\n `Save failed: ${routine.LatestResult?.CompleteMessage ?? 'unknown error'}`,\n ];\n return;\n }\n\n const recipientErrors = await this.saveRecipients(routine);\n if (recipientErrors.length > 0) {\n this.ValidationErrors = recipientErrors;\n return;\n }\n\n if (isNew) {\n // Re-scope the engine's dependent (recipients/runs) configs to include\n // the new routine — their client-side filter is a Config-time snapshot.\n await this.engine().Refresh(p.CurrentUser);\n this.AfterRoutineCreated.emit(new AfterRoutineCreatedEventArgs(routine));\n }\n\n this.notifications.CreateSimpleNotification(\n isNew ? `'${routine.Name}' created` : `'${routine.Name}' updated`,\n 'success',\n 3000\n );\n this.Saved.emit(routine);\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n // ---------------------------------------------------------------\n // Internals\n // ---------------------------------------------------------------\n private engine(): UserRoutineEngine {\n return UserRoutineEngine.GetProviderInstance<UserRoutineEngine>(this.ProviderToUse, UserRoutineEngine) as UserRoutineEngine;\n }\n\n /** True when the loaded routine differs from the basic-path defaults in any advanced field. */\n private usesAdvancedSettings(): boolean {\n return this.Description.trim().length > 0\n || this.RoutineType === 'Monitoring'\n || this.StartingPayloadText.trim().length > 0\n || this.SelectedSkillIDs.length > 0\n || this.Timezone !== GetLocalTimezone()\n || this.StartAtLocal.trim().length > 0\n || this.EndAtLocal.trim().length > 0\n || this.NotifyCondition !== 'Always'\n || !this.NotifyViaInApp\n || this.NotifyViaEmail\n || this.Recipients.length > 0;\n }\n\n private async reload(): Promise<void> {\n this.IsLoading = true;\n this.ValidationErrors = [];\n this.deletedRecipients = [];\n this.cdr.markForCheck();\n try {\n const p = this.ProviderToUse;\n const [catalog] = await Promise.all([\n LoadRoutineTargetCatalog(p),\n this.engine().Config(false, p.CurrentUser, p),\n ]);\n this.Catalog = catalog;\n this.buildAgentTreeConfig(p);\n if (this._routineID) {\n await this.loadExisting(this._routineID);\n this.ShowAdvanced = this.usesAdvancedSettings();\n } else {\n this.resetForNew();\n this.ShowAdvanced = false;\n }\n if (this.Recipients.some((r) => r.Mode === 'user')) {\n await this.ensureUserOptions();\n }\n } catch (e) {\n this.ValidationErrors = [\n `Failed to load the editor: ${e instanceof Error ? e.message : 'unknown error'}`,\n ];\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Builds the agent tree leaf config: Active, root-level agents only, EXCLUDING\n * agents whose type is the Realtime agent type. The exclusion is expressed as an\n * inline NOT IN list of type IDs resolved from metadata BY NAME (never hardcoded).\n */\n private buildAgentTreeConfig(provider: IMetadataProvider): void {\n const realtimeTypeIDs = this.resolveRealtimeTypeIDs(provider);\n const filters = [`Status='Active'`, `ParentID IS NULL`];\n if (realtimeTypeIDs.length > 0) {\n const inList = realtimeTypeIDs.map((id) => `'${id}'`).join(',');\n filters.push(`(TypeID IS NULL OR TypeID NOT IN (${inList}))`);\n }\n this.AgentTreeLeafConfig = {\n EntityName: 'MJ: AI Agents',\n ParentField: 'CategoryID',\n DisplayField: 'Name',\n IconField: 'IconClass',\n DefaultIcon: 'fa-solid fa-robot',\n ExtraFilter: filters.join(' AND '),\n OrderBy: 'Name ASC',\n };\n }\n\n /** Realtime agent-type IDs resolved from the cached AI metadata by type NAME. */\n private resolveRealtimeTypeIDs(provider: IMetadataProvider): string[] {\n // The catalog load above already Config'd AIEngineBase for this provider —\n // reuse its cached AgentTypes through the provider-scoped instance.\n const engine = AIEngineBase.GetProviderInstance<AIEngineBase>(provider, AIEngineBase) as AIEngineBase;\n return engine.AgentTypes\n .filter((t) => t.Name?.trim().toLowerCase() === 'realtime')\n .map((t) => t.ID);\n }\n\n private resetForNew(): void {\n this.editingEntity = null;\n this.Name = '';\n this.Description = '';\n this.TargetID = null;\n this.SelectedAgentIDs = [];\n this.InitialMessage = '';\n this.StartingPayloadText = '';\n this.SelectedSkillIDs = [];\n this.RoutineType = 'Scheduled';\n this.ScheduleKind = 'daily';\n this.ScheduleMinute = 0;\n this.ScheduleTime = '09:00';\n this.ScheduleDayOfWeek = 1;\n this.ScheduleDayOfMonth = 1;\n this.RawCron = '';\n this.Timezone = GetLocalTimezone();\n this.StartAtLocal = '';\n this.EndAtLocal = '';\n this.NotifyCondition = 'Always';\n this.NotifyViaInApp = true;\n this.NotifyViaEmail = false;\n this.Recipients = [];\n }\n\n private async loadExisting(routineID: string): Promise<void> {\n const p = this.ProviderToUse;\n // Prefer the engine's cached entity; fall back to a direct load (e.g., deep link\n // into a routine saved elsewhere before the cache refreshed).\n let routine = this.engine().GetRoutineByID(routineID) ?? null;\n if (!routine) {\n const loadedEntity = await p.GetEntityObject<MJUserRoutineEntity>('MJ: User Routines', p.CurrentUser);\n const loaded = await loadedEntity.Load(routineID);\n routine = loaded ? loadedEntity : null;\n }\n if (!routine) {\n this.ValidationErrors = [`Routine ${routineID} could not be loaded.`];\n this.resetForNew();\n return;\n }\n this.editingEntity = routine;\n this.Name = routine.Name;\n this.Description = routine.Description ?? '';\n this.TargetID = routine.TargetID;\n this.SelectedAgentIDs = routine.TargetID ? [routine.TargetID] : [];\n this.InitialMessage = routine.InitialMessage ?? '';\n this.StartingPayloadText = routine.StartingPayload ?? '';\n this.SelectedSkillIDs = ParseSkillIDs(routine.RequestedSkillIDs);\n this.RoutineType = routine.RoutineType;\n this.applyCron(ParseCronExpression(routine.CronExpression));\n this.Timezone = routine.Timezone;\n this.StartAtLocal = ToDateTimeLocal(routine.StartAt);\n this.EndAtLocal = ToDateTimeLocal(routine.EndAt);\n this.NotifyCondition = routine.NotifyCondition;\n this.NotifyViaInApp = routine.NotifyViaInApp;\n this.NotifyViaEmail = routine.NotifyViaEmail;\n this.loadRecipientRows(routineID);\n }\n\n private applyCron(schedule: CronSchedule): void {\n this.ScheduleKind = schedule.Kind;\n this.ScheduleMinute = schedule.Minute;\n this.ScheduleTime = `${schedule.Hour.toString().padStart(2, '0')}:${schedule.Minute.toString().padStart(2, '0')}`;\n this.ScheduleDayOfWeek = schedule.DayOfWeek;\n this.ScheduleDayOfMonth = schedule.DayOfMonth;\n this.RawCron = schedule.Raw;\n }\n\n private buildCron(): string {\n const { hour, minute } = this.parseScheduleTime();\n const schedule: CronSchedule = {\n Kind: this.ScheduleKind,\n Minute: this.ScheduleKind === 'hourly' ? this.clampMinute(this.ScheduleMinute) : minute,\n Hour: hour,\n DayOfWeek: this.ScheduleDayOfWeek,\n DayOfMonth: this.ScheduleDayOfMonth,\n Raw: this.RawCron,\n };\n return BuildCronExpression(schedule);\n }\n\n private parseScheduleTime(): { hour: number; minute: number } {\n const match = /^(\\d{1,2}):(\\d{2})$/.exec(this.ScheduleTime.trim());\n if (!match) {\n return { hour: 9, minute: 0 };\n }\n return {\n hour: Math.min(23, Math.max(0, parseInt(match[1], 10))),\n minute: this.clampMinute(parseInt(match[2], 10)),\n };\n }\n\n private clampMinute(minute: number): number {\n return Math.min(59, Math.max(0, Math.round(minute ?? 0)));\n }\n\n /** Builds the editable recipient rows from the engine's cached recipients. */\n private loadRecipientRows(routineID: string): void {\n this.Recipients = this.engine()\n .RecipientsForRoutine(routineID)\n .map((entity) => ({\n Entity: entity,\n Mode: entity.UserID ? ('user' as const) : ('email' as const),\n UserID: entity.UserID,\n Email: entity.Email ?? '',\n Channel: entity.Channel,\n }));\n }\n\n /** Lazily loads the user picker options the first time a user-mode row exists. */\n private async ensureUserOptions(): Promise<void> {\n if (this.UserOptions.length > 0) {\n return;\n }\n const p = this.ProviderToUse;\n const rv = RunView.FromMetadataProvider(p);\n const result = await rv.RunView<UserOption>(\n {\n EntityName: 'MJ: Users',\n Fields: ['ID', 'Name', 'Email'],\n ExtraFilter: `IsActive=1`,\n OrderBy: 'Name ASC',\n ResultType: 'simple',\n },\n p.CurrentUser\n );\n if (result.Success) {\n this.UserOptions = result.Results ?? [];\n this.cdr.markForCheck();\n }\n }\n\n private validate(): string[] {\n const errors: string[] = [];\n if (!this.Name.trim()) {\n errors.push('Name is required.');\n }\n if (!this.TargetID) {\n errors.push('Select the agent this routine should run.');\n }\n if (this.ScheduleKind === 'advanced' && !IsPlausibleCronExpression(this.RawCron)) {\n errors.push('The advanced cron expression must have 5 (or 6) space-separated fields.');\n }\n if (!this.Timezone?.trim()) {\n errors.push('Timezone is required.');\n }\n const payloadCheck = ValidateOptionalJson(this.StartingPayloadText);\n if (!payloadCheck.Valid) {\n errors.push(`Starting payload is not valid JSON: ${payloadCheck.Error}`);\n }\n const startAt = FromDateTimeLocal(this.StartAtLocal);\n const endAt = FromDateTimeLocal(this.EndAtLocal);\n if (startAt && endAt && endAt.getTime() <= startAt.getTime()) {\n errors.push('End of the activation window must be after its start.');\n }\n this.Recipients.forEach((row, i) => {\n if (row.Mode === 'user' && !row.UserID) {\n errors.push(`Recipient ${i + 1}: choose a user (or switch the row to an external email).`);\n }\n if (row.Mode === 'email' && !IsPlausibleEmail(row.Email)) {\n errors.push(`Recipient ${i + 1}: enter a valid email address.`);\n }\n });\n return errors;\n }\n\n /** Persists recipient rows in order (Sequence = index) and deletes removed rows. */\n private async saveRecipients(routine: MJUserRoutineEntity): Promise<string[]> {\n const p = this.ProviderToUse;\n const errors: string[] = [];\n\n for (const entity of this.deletedRecipients) {\n const deleted = await entity.Delete();\n if (!deleted) {\n errors.push(\n `Failed to remove a recipient: ${entity.LatestResult?.CompleteMessage ?? 'unknown error'}`\n );\n }\n }\n this.deletedRecipients = [];\n\n for (let i = 0; i < this.Recipients.length; i++) {\n const row = this.Recipients[i];\n const entity =\n row.Entity ??\n (await p.GetEntityObject<MJUserRoutineRecipientEntity>('MJ: User Routine Recipients', p.CurrentUser));\n entity.RoutineID = routine.ID;\n entity.UserID = row.Mode === 'user' ? row.UserID : null;\n entity.Email = row.Mode === 'email' ? row.Email.trim() : null;\n entity.Channel = row.Channel;\n entity.Sequence = i;\n const saved = await entity.Save();\n if (saved) {\n row.Entity = entity;\n } else {\n errors.push(\n `Failed to save recipient ${i + 1}: ${entity.LatestResult?.CompleteMessage ?? 'unknown error'}`\n );\n }\n }\n return errors;\n }\n}\n","@if (IsLoading) {\n <div class=\"editor-loading\">\n <mj-loading text=\"Loading editor...\" size=\"medium\"></mj-loading>\n </div>\n} @else {\n <div class=\"routine-editor\">\n\n @if (ValidationErrors.length > 0) {\n <mj-alert Variant=\"error\">\n <ul class=\"editor-errors\">\n @for (error of ValidationErrors; track error) {\n <li>{{ error }}</li>\n }\n </ul>\n </mj-alert>\n }\n\n <!-- ═══════════ BASICS (the 80% path: name, agent, message, schedule) ═══════════ -->\n <section class=\"editor-section\">\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-name\">Name <span class=\"editor-required\">*</span></label>\n <input id=\"routine-name\" class=\"mj-input\" type=\"text\" [(ngModel)]=\"Name\" placeholder=\"e.g. Morning membership digest\" />\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Which agent should this routine run? <span class=\"editor-required\">*</span></label>\n @if (AgentTreeLeafConfig) {\n <mj-tree-dropdown\n [BranchConfig]=\"AgentTreeBranchConfig\"\n [LeafConfig]=\"AgentTreeLeafConfig\"\n DefaultExpansion=\"all\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n [Value]=\"SelectedAgentKey\"\n [Clearable]=\"false\"\n Placeholder=\"Select an agent...\"\n (AfterNodeSelect)=\"OnAgentNodeSelected($event)\">\n </mj-tree-dropdown>\n }\n <div class=\"editor-hint\">Active agents only, grouped by category — realtime (voice) agents are interactive-only and can't be scheduled.</div>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-message\">Message sent on each run</label>\n <!-- Composer mention editor in DISCOVERY mode: trigger providers are ClassFactory-\n discovered (ng-conversations registers '@' agent / '#' record / '/' skill plugins\n when loaded). '@' agent mentions are excluded — the routine's agent is fixed by\n the picker above. With no providers registered this degrades gracefully to a\n plain text editor. -->\n <mj-mention-editor id=\"routine-message\"\n [(ngModel)]=\"InitialMessage\"\n placeholder=\"The message the routine sends to the agent each time it runs\"\n [ExcludedTriggerKeys]=\"['agent-mentions']\"\n [Provider]=\"Provider\"\n [enableAttachments]=\"false\"\n [autoFocus]=\"false\"\n [currentUser]=\"ProviderToUse.CurrentUser\"></mj-mention-editor>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Frequency</label>\n <div class=\"editor-segmented editor-segmented--wrap\" role=\"radiogroup\" aria-label=\"Schedule frequency\">\n @for (option of ScheduleKindOptions; track option.Value) {\n <button type=\"button\" class=\"editor-segment\"\n [class.editor-segment--active]=\"ScheduleKind === option.Value\"\n (click)=\"SetScheduleKind(option.Value)\">\n {{ option.Label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"editor-schedule-detail\">\n @switch (ScheduleKind) {\n @case ('hourly') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">At minute</label>\n <mj-numeric-input [(ngModel)]=\"ScheduleMinute\" [Min]=\"0\" [Max]=\"59\" [Step]=\"5\"></mj-numeric-input>\n <span class=\"editor-hint-inline\">past every hour</span>\n </div>\n }\n @case ('daily') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">At</label>\n <input class=\"mj-input editor-time-input\" type=\"time\" [(ngModel)]=\"ScheduleTime\" />\n <span class=\"editor-hint-inline\">every day</span>\n </div>\n }\n @case ('weekly') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">Every</label>\n <mj-dropdown class=\"editor-inline-dropdown\" [Data]=\"DayOfWeekOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"ScheduleDayOfWeek\"></mj-dropdown>\n <label class=\"editor-label\">at</label>\n <input class=\"mj-input editor-time-input\" type=\"time\" [(ngModel)]=\"ScheduleTime\" />\n </div>\n }\n @case ('monthly') {\n <div class=\"editor-field editor-field--inline\">\n <label class=\"editor-label\">On day</label>\n <mj-dropdown class=\"editor-inline-dropdown\" [Data]=\"DayOfMonthOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"ScheduleDayOfMonth\"></mj-dropdown>\n <label class=\"editor-label\">at</label>\n <input class=\"mj-input editor-time-input\" type=\"time\" [(ngModel)]=\"ScheduleTime\" />\n </div>\n }\n @case ('advanced') {\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-cron\">Cron expression</label>\n <input id=\"routine-cron\" class=\"mj-input editor-mono\" type=\"text\" [(ngModel)]=\"RawCron\"\n placeholder=\"minute hour day-of-month month day-of-week\" />\n </div>\n }\n }\n <div class=\"editor-schedule-preview\">\n <i class=\"fa-solid fa-calendar-check\"></i> {{ SchedulePreview || 'No schedule yet' }}\n </div>\n </div>\n </section>\n\n <!-- ═══════════ ADVANCED (progressive disclosure — collapsed by default) ═══════════ -->\n <button type=\"button\" class=\"editor-advanced-toggle\" (click)=\"ShowAdvanced = !ShowAdvanced\"\n [attr.aria-expanded]=\"ShowAdvanced\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!ShowAdvanced\" [class.fa-chevron-down]=\"ShowAdvanced\"></i>\n Advanced options\n <span class=\"editor-hint-inline\">description · monitoring · timezone · window · payload · skills · notifications</span>\n </button>\n\n @if (ShowAdvanced) {\n <section class=\"editor-section\">\n <h3 class=\"editor-section-title\"><i class=\"fa-solid fa-circle-info\"></i> Details</h3>\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-description\">Description</label>\n <textarea id=\"routine-description\" class=\"mj-textarea\" rows=\"2\" [(ngModel)]=\"Description\"\n placeholder=\"What does this routine do?\"></textarea>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Routine type</label>\n <div class=\"editor-segmented\" role=\"radiogroup\" aria-label=\"Routine type\">\n <button type=\"button\" class=\"editor-segment\"\n [class.editor-segment--active]=\"RoutineType === 'Scheduled'\"\n (click)=\"RoutineType = 'Scheduled'\">\n <i class=\"fa-solid fa-clock\"></i> Scheduled\n </button>\n <button type=\"button\" class=\"editor-segment\"\n [class.editor-segment--active]=\"RoutineType === 'Monitoring'\"\n (click)=\"RoutineType = 'Monitoring'\">\n <i class=\"fa-solid fa-eye\"></i> Monitoring\n </button>\n </div>\n <div class=\"editor-hint\">{{ RoutineTypeHelp }}</div>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Timezone</label>\n <mj-combobox\n [Data]=\"TimezoneOptions\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Select an IANA timezone...\"\n [(ngModel)]=\"Timezone\">\n </mj-combobox>\n </div>\n\n <div class=\"editor-field-row\">\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-startat\">Active from (optional)</label>\n <input id=\"routine-startat\" class=\"mj-input\" type=\"datetime-local\" [(ngModel)]=\"StartAtLocal\" />\n </div>\n <div class=\"editor-field\">\n <label class=\"editor-label\" for=\"routine-endat\">Active until (optional)</label>\n <input id=\"routine-endat\" class=\"mj-input\" type=\"datetime-local\" [(ngModel)]=\"EndAtLocal\" />\n </div>\n </div>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Starting payload (JSON, optional)</label>\n <div class=\"editor-code\">\n <mj-code-editor [(ngModel)]=\"StartingPayloadText\" language=\"json\"\n placeholder='{ \"example\": true }'></mj-code-editor>\n </div>\n <div class=\"editor-hint\">Passed to the agent on each run. Leave blank for none.</div>\n </div>\n\n @if (SkillOptions.length > 0) {\n <div class=\"editor-field\">\n <label class=\"editor-label\">Pre-activate skills (optional)</label>\n <div class=\"editor-skills\">\n @for (skill of SkillOptions; track skill.ID) {\n <button type=\"button\" class=\"editor-skill-chip\"\n [class.editor-skill-chip--selected]=\"IsSkillSelected(skill.ID)\"\n [title]=\"skill.Description ?? skill.Name\"\n (click)=\"ToggleSkill(skill.ID)\">\n <i [class]=\"skill.IconClass || 'fa-solid fa-wand-magic-sparkles'\"></i>\n {{ skill.Name }}\n @if (IsSkillSelected(skill.ID)) {\n <i class=\"fa-solid fa-check editor-skill-check\"></i>\n }\n </button>\n }\n </div>\n <div class=\"editor-hint\">Selected skills start every run with their instructions and tools in effect (subject to the agent's skill gates).</div>\n </div>\n }\n </section>\n\n <section class=\"editor-section\">\n <h3 class=\"editor-section-title\"><i class=\"fa-solid fa-bell\"></i> Notifications</h3>\n\n <div class=\"editor-field\">\n <label class=\"editor-label\">Notify me</label>\n <mj-dropdown [Data]=\"NotifyConditionOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"NotifyCondition\"></mj-dropdown>\n </div>\n\n <div class=\"editor-field editor-field--inline editor-switches\">\n <mj-switch [(ngModel)]=\"NotifyViaInApp\" OnLabel=\"In-app\" OffLabel=\"In-app\"></mj-switch>\n <mj-switch [(ngModel)]=\"NotifyViaEmail\" OnLabel=\"Email\" OffLabel=\"Email\"></mj-switch>\n </div>\n\n <div class=\"editor-field\">\n <div class=\"editor-recipients-header\">\n <label class=\"editor-label\">Additional recipients</label>\n <button mjButton variant=\"outline\" size=\"sm\" (click)=\"AddRecipient()\">\n <i class=\"fa-solid fa-plus\"></i> Add recipient\n </button>\n </div>\n @if (Recipients.length === 0) {\n <div class=\"editor-hint\">Only you (the owner) will be notified.</div>\n }\n @for (row of Recipients; track $index; let i = $index; let first = $first; let last = $last) {\n <div class=\"editor-recipient-row\">\n <div class=\"editor-recipient-order\">\n <button mjButton variant=\"icon\" size=\"sm\" title=\"Move up\" [disabled]=\"first\" (click)=\"MoveRecipient(i, -1)\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button mjButton variant=\"icon\" size=\"sm\" title=\"Move down\" [disabled]=\"last\" (click)=\"MoveRecipient(i, 1)\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n <mj-dropdown class=\"editor-recipient-mode\" [Data]=\"RecipientModeOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"row.Mode\" (ngModelChange)=\"OnRecipientModeChange(row)\"></mj-dropdown>\n @if (row.Mode === 'user') {\n <mj-combobox class=\"editor-recipient-target\" [Data]=\"UserOptions\" TextField=\"Name\" ValueField=\"ID\"\n [ValuePrimitive]=\"true\" Placeholder=\"Select a user...\" [(ngModel)]=\"row.UserID\"></mj-combobox>\n } @else {\n <input class=\"mj-input editor-recipient-target\" type=\"email\" placeholder=\"name@example.com\" [(ngModel)]=\"row.Email\" />\n }\n <mj-dropdown class=\"editor-recipient-channel\" [Data]=\"ChannelOptions\" TextField=\"text\" ValueField=\"value\"\n [ValuePrimitive]=\"true\" [(ngModel)]=\"row.Channel\"></mj-dropdown>\n <button mjButton variant=\"icon\" size=\"sm\" title=\"Remove recipient\" (click)=\"RemoveRecipient(i)\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </div>\n }\n </div>\n </section>\n }\n\n <!-- ======================= Footer (confirm LEFT, cancel RIGHT) ======================= -->\n <div class=\"editor-footer\">\n <button mjButton variant=\"primary\" size=\"md\" [disabled]=\"IsSaving\" (click)=\"Save()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n }\n {{ IsEdit ? 'Save Changes' : 'Create Routine' }}\n </button>\n <button mjButton variant=\"secondary\" size=\"md\" [disabled]=\"IsSaving\" (click)=\"Cancel()\">Cancel</button>\n </div>\n </div>\n}\n"]}
|
|
@@ -270,7 +270,7 @@ export class RoutineHistoryComponent extends BaseAngularComponent {
|
|
|
270
270
|
i0.ɵɵconditionalCreate(0, RoutineHistoryComponent_Conditional_0_Template, 2, 0, "div", 0)(1, RoutineHistoryComponent_Conditional_1_Template, 1, 1, "mj-alert", 1)(2, RoutineHistoryComponent_Conditional_2_Template, 1, 0, "mj-empty-state", 2)(3, RoutineHistoryComponent_Conditional_3_Template, 3, 0, "div", 3);
|
|
271
271
|
} if (rf & 2) {
|
|
272
272
|
i0.ɵɵconditional(ctx.IsLoading ? 0 : ctx.LoadError ? 1 : ctx.Runs.length === 0 ? 2 : 3);
|
|
273
|
-
} }, dependencies: [i1.MJAlertComponent, i1.MJButtonDirective, i1.MJEmptyStateComponent, i2.LoadingComponent, i3.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n}\n\n.history-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 48px 0;\n}\n\n.history-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.history-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 14px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.history-row-main[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.history-started[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.history-relative[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.history-duration[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.history-spacer[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n}\n\n.history-notified[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n font-size: 13px;\n}\n\n.history-summary[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.history-error[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-status-error-text);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: var(--mj-radius-sm, 6px);\n padding: 8px 10px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n\n
|
|
273
|
+
} }, dependencies: [i1.MJAlertComponent, i1.MJButtonDirective, i1.MJEmptyStateComponent, i2.LoadingComponent, i3.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n}\n\n.history-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 48px 0;\n}\n\n.history-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.history-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 14px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.history-row-main[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.history-started[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.history-relative[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.history-duration[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.history-spacer[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n}\n\n.history-notified[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n font-size: 13px;\n}\n\n.history-summary[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.history-error[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-status-error-text);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: var(--mj-radius-sm, 6px);\n padding: 8px 10px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n\n.history-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 11px;\n font-weight: 600;\n white-space: nowrap;\n}\n\n.history-chip--success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.history-chip--error[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.history-chip--info[_ngcontent-%COMP%] {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n\n.history-chip--muted[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n border: 1px solid var(--mj-border-default);\n}"] });
|
|
274
274
|
}
|
|
275
275
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RoutineHistoryComponent, [{
|
|
276
276
|
type: Component,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-user-routines",
|
|
3
|
-
"version": "6.1.0-edge.
|
|
3
|
+
"version": "6.1.0-edge.6",
|
|
4
4
|
"description": "MemberJunction: Reusable Angular components for User Routines — list, editor, and run history for cron-scheduled Agent / Action / Prompt routines",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -11,32 +11,32 @@
|
|
|
11
11
|
"author": "",
|
|
12
12
|
"license": "BUSL-1.1",
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@angular/compiler": "21.
|
|
15
|
-
"@angular/compiler-cli": "21.
|
|
14
|
+
"@angular/compiler": "21.2.22",
|
|
15
|
+
"@angular/compiler-cli": "21.2.22",
|
|
16
16
|
"vitest": "^4.0.18",
|
|
17
|
-
"@memberjunction/ng-test-utils": "6.1.0-edge.
|
|
17
|
+
"@memberjunction/ng-test-utils": "6.1.0-edge.6"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@angular/
|
|
21
|
-
"@angular/
|
|
22
|
-
"@angular/
|
|
20
|
+
"@angular/animations": "^21.2.22",
|
|
21
|
+
"@angular/common": "^21.2.22",
|
|
22
|
+
"@angular/core": "^21.2.22",
|
|
23
|
+
"@angular/forms": "^21.2.22",
|
|
24
|
+
"@angular/platform-browser": "^21.2.22"
|
|
23
25
|
},
|
|
24
26
|
"dependencies": {
|
|
25
|
-
"@
|
|
26
|
-
"@
|
|
27
|
-
"@memberjunction/
|
|
28
|
-
"@memberjunction/
|
|
29
|
-
"@memberjunction/
|
|
30
|
-
"@memberjunction/
|
|
31
|
-
"@memberjunction/
|
|
32
|
-
"@memberjunction/ng-
|
|
33
|
-
"@memberjunction/ng-
|
|
34
|
-
"@memberjunction/ng-
|
|
35
|
-
"@memberjunction/ng-
|
|
36
|
-
"@memberjunction/ng-
|
|
37
|
-
"@memberjunction/ng-
|
|
38
|
-
"@memberjunction/ng-trees": "6.1.0-edge.4",
|
|
39
|
-
"@memberjunction/ng-ui-components": "6.1.0-edge.4",
|
|
27
|
+
"@memberjunction/actions-base": "6.1.0-edge.6",
|
|
28
|
+
"@memberjunction/ai-engine-base": "6.1.0-edge.6",
|
|
29
|
+
"@memberjunction/core": "6.1.0-edge.6",
|
|
30
|
+
"@memberjunction/core-entities": "6.1.0-edge.6",
|
|
31
|
+
"@memberjunction/global": "6.1.0-edge.6",
|
|
32
|
+
"@memberjunction/ng-base-types": "6.1.0-edge.6",
|
|
33
|
+
"@memberjunction/ng-code-editor": "6.1.0-edge.6",
|
|
34
|
+
"@memberjunction/ng-composer": "6.1.0-edge.6",
|
|
35
|
+
"@memberjunction/ng-container-directives": "6.1.0-edge.6",
|
|
36
|
+
"@memberjunction/ng-notifications": "6.1.0-edge.6",
|
|
37
|
+
"@memberjunction/ng-shared-generic": "6.1.0-edge.6",
|
|
38
|
+
"@memberjunction/ng-trees": "6.1.0-edge.6",
|
|
39
|
+
"@memberjunction/ng-ui-components": "6.1.0-edge.6",
|
|
40
40
|
"rxjs": "^7.8.2",
|
|
41
41
|
"tslib": "^2.8.1"
|
|
42
42
|
},
|