@memberjunction/ng-user-routines 0.0.0 → 5.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/my-routines-list.component.d.ts +119 -0
- package/dist/lib/my-routines-list.component.d.ts.map +1 -0
- package/dist/lib/my-routines-list.component.js +574 -0
- package/dist/lib/my-routines-list.component.js.map +1 -0
- package/dist/lib/new-routine.component.d.ts +182 -0
- package/dist/lib/new-routine.component.d.ts.map +1 -0
- package/dist/lib/new-routine.component.js +1070 -0
- package/dist/lib/new-routine.component.js.map +1 -0
- package/dist/lib/routine-history.component.d.ts +65 -0
- package/dist/lib/routine-history.component.d.ts.map +1 -0
- package/dist/lib/routine-history.component.js +290 -0
- package/dist/lib/routine-history.component.js.map +1 -0
- package/dist/lib/routine-target-catalog.d.ts +48 -0
- package/dist/lib/routine-target-catalog.d.ts.map +1 -0
- package/dist/lib/routine-target-catalog.js +59 -0
- package/dist/lib/routine-target-catalog.js.map +1 -0
- package/dist/lib/routine-ui-helpers.d.ts +49 -0
- package/dist/lib/routine-ui-helpers.d.ts.map +1 -0
- package/dist/lib/routine-ui-helpers.js +174 -0
- package/dist/lib/routine-ui-helpers.js.map +1 -0
- package/dist/lib/user-routines-command-center.component.d.ts +88 -0
- package/dist/lib/user-routines-command-center.component.d.ts.map +1 -0
- package/dist/lib/user-routines-command-center.component.js +372 -0
- package/dist/lib/user-routines-command-center.component.js.map +1 -0
- package/dist/lib/user-routines-events.d.ts +88 -0
- package/dist/lib/user-routines-events.d.ts.map +1 -0
- package/dist/lib/user-routines-events.js +97 -0
- package/dist/lib/user-routines-events.js.map +1 -0
- package/dist/lib/user-routines-slide-in.component.d.ts +57 -0
- package/dist/lib/user-routines-slide-in.component.d.ts.map +1 -0
- package/dist/lib/user-routines-slide-in.component.js +170 -0
- package/dist/lib/user-routines-slide-in.component.js.map +1 -0
- package/dist/lib/user-routines.module.d.ts +37 -0
- package/dist/lib/user-routines.module.d.ts.map +1 -0
- package/dist/lib/user-routines.module.js +113 -0
- package/dist/lib/user-routines.module.js.map +1 -0
- package/dist/public-api.d.ts +10 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +19 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +49 -7
- package/README.md +0 -45
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loads the pickable routine targets (Agents / Actions / Prompts) and the Active AI
|
|
3
|
+
* Skills from the already-cached metadata engines — provider-scoped, lazy Config, no
|
|
4
|
+
* bespoke RunView round-trips. Shared by the routines list (id → name resolution) and
|
|
5
|
+
* the editor (target / skill pickers).
|
|
6
|
+
*/
|
|
7
|
+
import { IMetadataProvider } from '@memberjunction/core';
|
|
8
|
+
/** A pickable target (agent, action, or prompt). */
|
|
9
|
+
export interface RoutineTargetOption {
|
|
10
|
+
ID: string;
|
|
11
|
+
Name: string;
|
|
12
|
+
Description: string | null;
|
|
13
|
+
}
|
|
14
|
+
/** A pickable AI Skill for RequestedSkillIDs. */
|
|
15
|
+
export interface RoutineSkillOption {
|
|
16
|
+
ID: string;
|
|
17
|
+
Name: string;
|
|
18
|
+
Description: string | null;
|
|
19
|
+
IconClass: string | null;
|
|
20
|
+
Color: string | null;
|
|
21
|
+
}
|
|
22
|
+
/** The full catalog of routine-pickable targets + skills, plus an id → name map. */
|
|
23
|
+
export interface RoutineTargetCatalog {
|
|
24
|
+
/** Active agents, EXCLUDING agents whose type is the Realtime agent type (interactive-only). */
|
|
25
|
+
Agents: RoutineTargetOption[];
|
|
26
|
+
/** Active actions. */
|
|
27
|
+
Actions: RoutineTargetOption[];
|
|
28
|
+
/** Active prompts. */
|
|
29
|
+
Prompts: RoutineTargetOption[];
|
|
30
|
+
/** Active AI Skills (for Agent targets' RequestedSkillIDs). */
|
|
31
|
+
Skills: RoutineSkillOption[];
|
|
32
|
+
/**
|
|
33
|
+
* Display name for ANY known target id (normalized), regardless of status — so
|
|
34
|
+
* routines pointing at since-deactivated targets still render a name.
|
|
35
|
+
*/
|
|
36
|
+
NameByID: Map<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Font Awesome icon class for ANY known agent id (normalized) that has an
|
|
39
|
+
* IconClass set. Consumers fall back to 'fa-solid fa-robot' when absent.
|
|
40
|
+
*/
|
|
41
|
+
IconByID: Map<string, string>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Builds the catalog from the provider-scoped AI + Action engines. Both engines cache
|
|
45
|
+
* after their first Config, so repeated calls are cheap.
|
|
46
|
+
*/
|
|
47
|
+
export declare function LoadRoutineTargetCatalog(provider: IMetadataProvider): Promise<RoutineTargetCatalog>;
|
|
48
|
+
//# sourceMappingURL=routine-target-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routine-target-catalog.d.ts","sourceRoot":"","sources":["../../src/lib/routine-target-catalog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAKzD,oDAAoD;AACpD,MAAM,WAAW,mBAAmB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,iDAAiD;AACjD,MAAM,WAAW,kBAAkB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACjC,gGAAgG;IAChG,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,sBAAsB;IACtB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,sBAAsB;IACtB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,+DAA+D;IAC/D,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B;;;OAGG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA2DzG"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AIEngineBase } from '@memberjunction/ai-engine-base';
|
|
2
|
+
import { ActionEngineBase } from '@memberjunction/actions-base';
|
|
3
|
+
import { NormalizeUUID } from '@memberjunction/global';
|
|
4
|
+
/**
|
|
5
|
+
* Builds the catalog from the provider-scoped AI + Action engines. Both engines cache
|
|
6
|
+
* after their first Config, so repeated calls are cheap.
|
|
7
|
+
*/
|
|
8
|
+
export async function LoadRoutineTargetCatalog(provider) {
|
|
9
|
+
const aiEngine = AIEngineBase.GetProviderInstance(provider, AIEngineBase);
|
|
10
|
+
const actionEngine = ActionEngineBase.GetProviderInstance(provider, ActionEngineBase);
|
|
11
|
+
await Promise.all([
|
|
12
|
+
aiEngine.Config(false, undefined, provider),
|
|
13
|
+
actionEngine.Config(false, undefined, provider),
|
|
14
|
+
]);
|
|
15
|
+
// Resolve the Realtime agent type by NAME from metadata — never by hardcoded ID.
|
|
16
|
+
const realtimeTypeIDs = new Set(aiEngine.AgentTypes
|
|
17
|
+
.filter((t) => t.Name?.trim().toLowerCase() === 'realtime')
|
|
18
|
+
.map((t) => NormalizeUUID(t.ID)));
|
|
19
|
+
const nameByID = new Map();
|
|
20
|
+
const iconByID = new Map();
|
|
21
|
+
const byName = (a, b) => a.Name.localeCompare(b.Name);
|
|
22
|
+
const agents = aiEngine.Agents
|
|
23
|
+
.filter((a) => {
|
|
24
|
+
nameByID.set(NormalizeUUID(a.ID), a.Name ?? '');
|
|
25
|
+
if (a.IconClass) {
|
|
26
|
+
iconByID.set(NormalizeUUID(a.ID), a.IconClass);
|
|
27
|
+
}
|
|
28
|
+
const isRealtime = a.TypeID != null && realtimeTypeIDs.has(NormalizeUUID(a.TypeID));
|
|
29
|
+
return a.Status === 'Active' && !isRealtime;
|
|
30
|
+
})
|
|
31
|
+
.map((a) => ({ ID: a.ID, Name: a.Name ?? '', Description: a.Description ?? null }))
|
|
32
|
+
.sort(byName);
|
|
33
|
+
const actions = actionEngine.Actions
|
|
34
|
+
.filter((a) => {
|
|
35
|
+
nameByID.set(NormalizeUUID(a.ID), a.Name ?? '');
|
|
36
|
+
return a.Status === 'Active';
|
|
37
|
+
})
|
|
38
|
+
.map((a) => ({ ID: a.ID, Name: a.Name ?? '', Description: a.Description ?? null }))
|
|
39
|
+
.sort(byName);
|
|
40
|
+
const prompts = aiEngine.Prompts
|
|
41
|
+
.filter((prompt) => {
|
|
42
|
+
nameByID.set(NormalizeUUID(prompt.ID), prompt.Name ?? '');
|
|
43
|
+
return prompt.Status === 'Active';
|
|
44
|
+
})
|
|
45
|
+
.map((prompt) => ({ ID: prompt.ID, Name: prompt.Name ?? '', Description: prompt.Description ?? null }))
|
|
46
|
+
.sort(byName);
|
|
47
|
+
const skills = aiEngine.Skills
|
|
48
|
+
.filter((s) => s.Status === 'Active')
|
|
49
|
+
.map((s) => ({
|
|
50
|
+
ID: s.ID,
|
|
51
|
+
Name: s.Name ?? '',
|
|
52
|
+
Description: s.Description ?? null,
|
|
53
|
+
IconClass: s.IconClass ?? null,
|
|
54
|
+
Color: s.Color ?? null,
|
|
55
|
+
}))
|
|
56
|
+
.sort(byName);
|
|
57
|
+
return { Agents: agents, Actions: actions, Prompts: prompts, Skills: skills, NameByID: nameByID, IconByID: iconByID };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=routine-target-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routine-target-catalog.js","sourceRoot":"","sources":["../../src/lib/routine-target-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Loads the pickable routine targets (Agents / Actions / Prompts) and the Active AI\n * Skills from the already-cached metadata engines — provider-scoped, lazy Config, no\n * bespoke RunView round-trips. Shared by the routines list (id → name resolution) and\n * the editor (target / skill pickers).\n */\nimport { IMetadataProvider } from '@memberjunction/core';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { ActionEngineBase } from '@memberjunction/actions-base';\nimport { NormalizeUUID } from '@memberjunction/global';\n\n/** A pickable target (agent, action, or prompt). */\nexport interface RoutineTargetOption {\n ID: string;\n Name: string;\n Description: string | null;\n}\n\n/** A pickable AI Skill for RequestedSkillIDs. */\nexport interface RoutineSkillOption {\n ID: string;\n Name: string;\n Description: string | null;\n IconClass: string | null;\n Color: string | null;\n}\n\n/** The full catalog of routine-pickable targets + skills, plus an id → name map. */\nexport interface RoutineTargetCatalog {\n /** Active agents, EXCLUDING agents whose type is the Realtime agent type (interactive-only). */\n Agents: RoutineTargetOption[];\n /** Active actions. */\n Actions: RoutineTargetOption[];\n /** Active prompts. */\n Prompts: RoutineTargetOption[];\n /** Active AI Skills (for Agent targets' RequestedSkillIDs). */\n Skills: RoutineSkillOption[];\n /**\n * Display name for ANY known target id (normalized), regardless of status — so\n * routines pointing at since-deactivated targets still render a name.\n */\n NameByID: Map<string, string>;\n /**\n * Font Awesome icon class for ANY known agent id (normalized) that has an\n * IconClass set. Consumers fall back to 'fa-solid fa-robot' when absent.\n */\n IconByID: Map<string, string>;\n}\n\n/**\n * Builds the catalog from the provider-scoped AI + Action engines. Both engines cache\n * after their first Config, so repeated calls are cheap.\n */\nexport async function LoadRoutineTargetCatalog(provider: IMetadataProvider): Promise<RoutineTargetCatalog> {\n const aiEngine = AIEngineBase.GetProviderInstance<AIEngineBase>(provider, AIEngineBase) as AIEngineBase;\n const actionEngine = ActionEngineBase.GetProviderInstance<ActionEngineBase>(provider, ActionEngineBase) as ActionEngineBase;\n await Promise.all([\n aiEngine.Config(false, undefined, provider),\n actionEngine.Config(false, undefined, provider),\n ]);\n\n // Resolve the Realtime agent type by NAME from metadata — never by hardcoded ID.\n const realtimeTypeIDs = new Set<string>(\n aiEngine.AgentTypes\n .filter((t) => t.Name?.trim().toLowerCase() === 'realtime')\n .map((t) => NormalizeUUID(t.ID))\n );\n\n const nameByID = new Map<string, string>();\n const iconByID = new Map<string, string>();\n const byName = (a: { Name: string }, b: { Name: string }) => a.Name.localeCompare(b.Name);\n\n const agents = aiEngine.Agents\n .filter((a) => {\n nameByID.set(NormalizeUUID(a.ID), a.Name ?? '');\n if (a.IconClass) {\n iconByID.set(NormalizeUUID(a.ID), a.IconClass);\n }\n const isRealtime = a.TypeID != null && realtimeTypeIDs.has(NormalizeUUID(a.TypeID));\n return a.Status === 'Active' && !isRealtime;\n })\n .map((a) => ({ ID: a.ID, Name: a.Name ?? '', Description: a.Description ?? null }))\n .sort(byName);\n\n const actions = actionEngine.Actions\n .filter((a) => {\n nameByID.set(NormalizeUUID(a.ID), a.Name ?? '');\n return a.Status === 'Active';\n })\n .map((a) => ({ ID: a.ID, Name: a.Name ?? '', Description: a.Description ?? null }))\n .sort(byName);\n\n const prompts = aiEngine.Prompts\n .filter((prompt) => {\n nameByID.set(NormalizeUUID(prompt.ID), prompt.Name ?? '');\n return prompt.Status === 'Active';\n })\n .map((prompt) => ({ ID: prompt.ID, Name: prompt.Name ?? '', Description: prompt.Description ?? null }))\n .sort(byName);\n\n const skills = aiEngine.Skills\n .filter((s) => s.Status === 'Active')\n .map((s) => ({\n ID: s.ID,\n Name: s.Name ?? '',\n Description: s.Description ?? null,\n IconClass: s.IconClass ?? null,\n Color: s.Color ?? null,\n }))\n .sort(byName);\n\n return { Agents: agents, Actions: actions, Prompts: prompts, Skills: skills, NameByID: nameByID, IconByID: iconByID };\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure display / serialization helpers shared by the User Routines components.
|
|
3
|
+
* No Angular or MJ runtime dependencies — unit-testable in isolation.
|
|
4
|
+
*/
|
|
5
|
+
import type { MJUserRoutineEntity } from '@memberjunction/core-entities';
|
|
6
|
+
/** Chip variants aligned with the shared status-token vocabulary. */
|
|
7
|
+
export type RoutineChipVariant = 'success' | 'warning' | 'error' | 'info' | 'muted';
|
|
8
|
+
/** Maps a routine lifecycle status to a chip variant. */
|
|
9
|
+
export declare function RoutineStatusVariant(status: MJUserRoutineEntity['Status']): RoutineChipVariant;
|
|
10
|
+
/** Maps a run outcome status to a chip variant. */
|
|
11
|
+
export declare function RunStatusVariant(status: string | null | undefined): RoutineChipVariant;
|
|
12
|
+
/** Font Awesome icon class for a routine target type. */
|
|
13
|
+
export declare function TargetTypeIcon(targetType: MJUserRoutineEntity['TargetType']): string;
|
|
14
|
+
/**
|
|
15
|
+
* Compact relative-time label ("3m ago", "in 2h", "just now"). Returns an empty
|
|
16
|
+
* string for null input. `now` is injectable for tests.
|
|
17
|
+
*/
|
|
18
|
+
export declare function FormatRelativeTime(date: Date | null | undefined, now?: Date): string;
|
|
19
|
+
/** Duration between two timestamps as "4s", "2m 10s", "1h 4m". Empty when incomplete. */
|
|
20
|
+
export declare function FormatDuration(start: Date | null | undefined, end: Date | null | undefined): string;
|
|
21
|
+
/**
|
|
22
|
+
* Parses the RequestedSkillIDs JSON column into a string array. Tolerant: bad JSON,
|
|
23
|
+
* non-array shapes, and non-string members all collapse to an empty/filtered array.
|
|
24
|
+
*/
|
|
25
|
+
export declare function ParseSkillIDs(raw: string | null | undefined): string[];
|
|
26
|
+
/** Serializes a skill ID array to the JSON column value (null when empty). */
|
|
27
|
+
export declare function SerializeSkillIDs(ids: readonly string[]): string | null;
|
|
28
|
+
/** Validates optional JSON text (StartingPayload). Blank is valid (stored as NULL). */
|
|
29
|
+
export declare function ValidateOptionalJson(text: string | null | undefined): {
|
|
30
|
+
Valid: boolean;
|
|
31
|
+
Error?: string;
|
|
32
|
+
};
|
|
33
|
+
/** Very light email shape check for external recipients (not RFC-complete on purpose). */
|
|
34
|
+
export declare function IsPlausibleEmail(email: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Converts a Date to the string an `<input type="datetime-local">` expects
|
|
37
|
+
* ("YYYY-MM-DDTHH:MM", local time). Empty string for null.
|
|
38
|
+
*/
|
|
39
|
+
export declare function ToDateTimeLocal(date: Date | null | undefined): string;
|
|
40
|
+
/** Parses a datetime-local string back to a Date (null for blank/invalid). */
|
|
41
|
+
export declare function FromDateTimeLocal(value: string | null | undefined): Date | null;
|
|
42
|
+
/**
|
|
43
|
+
* The browser's IANA timezone list via Intl (ES2022), with a small static fallback for
|
|
44
|
+
* older runtimes. The current zone is included by construction on modern browsers.
|
|
45
|
+
*/
|
|
46
|
+
export declare function GetTimezoneOptions(): string[];
|
|
47
|
+
/** The user's current IANA timezone (falls back to UTC). */
|
|
48
|
+
export declare function GetLocalTimezone(): string;
|
|
49
|
+
//# sourceMappingURL=routine-ui-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routine-ui-helpers.d.ts","sourceRoot":"","sources":["../../src/lib/routine-ui-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,qEAAqE;AACrE,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpF,yDAAyD;AACzD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GAAG,kBAAkB,CAO9F;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,CAQtF;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,GAAG,MAAM,CAOpF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,CA6BhG;AAED,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAmBnG;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAatE;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAGvE;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAWxG;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAUrE;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAO/E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAW7C;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/** Maps a routine lifecycle status to a chip variant. */
|
|
2
|
+
export function RoutineStatusVariant(status) {
|
|
3
|
+
switch (status) {
|
|
4
|
+
case 'Active': return 'success';
|
|
5
|
+
case 'Paused': return 'warning';
|
|
6
|
+
case 'Disabled': return 'muted';
|
|
7
|
+
default: return 'muted';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Maps a run outcome status to a chip variant. */
|
|
11
|
+
export function RunStatusVariant(status) {
|
|
12
|
+
switch (status) {
|
|
13
|
+
case 'Success': return 'success';
|
|
14
|
+
case 'Failed': return 'error';
|
|
15
|
+
case 'Running': return 'info';
|
|
16
|
+
case 'Skipped': return 'muted';
|
|
17
|
+
default: return 'muted';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Font Awesome icon class for a routine target type. */
|
|
21
|
+
export function TargetTypeIcon(targetType) {
|
|
22
|
+
switch (targetType) {
|
|
23
|
+
case 'Agent': return 'fa-solid fa-robot';
|
|
24
|
+
case 'Action': return 'fa-solid fa-bolt';
|
|
25
|
+
case 'Prompt': return 'fa-solid fa-comment-dots';
|
|
26
|
+
default: return 'fa-solid fa-circle-question';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Compact relative-time label ("3m ago", "in 2h", "just now"). Returns an empty
|
|
31
|
+
* string for null input. `now` is injectable for tests.
|
|
32
|
+
*/
|
|
33
|
+
export function FormatRelativeTime(date, now = new Date()) {
|
|
34
|
+
if (!date) {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
const target = date instanceof Date ? date : new Date(date);
|
|
38
|
+
if (isNaN(target.getTime())) {
|
|
39
|
+
return '';
|
|
40
|
+
}
|
|
41
|
+
const diffMs = target.getTime() - now.getTime();
|
|
42
|
+
const absMs = Math.abs(diffMs);
|
|
43
|
+
const future = diffMs > 0;
|
|
44
|
+
if (absMs < 60_000) {
|
|
45
|
+
return future ? 'in <1m' : 'just now';
|
|
46
|
+
}
|
|
47
|
+
const units = [
|
|
48
|
+
{ ms: 86_400_000 * 365, label: 'y' },
|
|
49
|
+
{ ms: 86_400_000 * 30, label: 'mo' },
|
|
50
|
+
{ ms: 86_400_000, label: 'd' },
|
|
51
|
+
{ ms: 3_600_000, label: 'h' },
|
|
52
|
+
{ ms: 60_000, label: 'm' },
|
|
53
|
+
];
|
|
54
|
+
for (const unit of units) {
|
|
55
|
+
if (absMs >= unit.ms) {
|
|
56
|
+
const count = Math.floor(absMs / unit.ms);
|
|
57
|
+
return future ? `in ${count}${unit.label}` : `${count}${unit.label} ago`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return future ? 'in <1m' : 'just now';
|
|
61
|
+
}
|
|
62
|
+
/** Duration between two timestamps as "4s", "2m 10s", "1h 4m". Empty when incomplete. */
|
|
63
|
+
export function FormatDuration(start, end) {
|
|
64
|
+
if (!start || !end) {
|
|
65
|
+
return '';
|
|
66
|
+
}
|
|
67
|
+
const startMs = new Date(start).getTime();
|
|
68
|
+
const endMs = new Date(end).getTime();
|
|
69
|
+
if (isNaN(startMs) || isNaN(endMs) || endMs < startMs) {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
const totalSeconds = Math.round((endMs - startMs) / 1000);
|
|
73
|
+
if (totalSeconds < 60) {
|
|
74
|
+
return `${totalSeconds}s`;
|
|
75
|
+
}
|
|
76
|
+
const totalMinutes = Math.floor(totalSeconds / 60);
|
|
77
|
+
if (totalMinutes < 60) {
|
|
78
|
+
return `${totalMinutes}m ${totalSeconds % 60}s`;
|
|
79
|
+
}
|
|
80
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
81
|
+
return `${hours}h ${totalMinutes % 60}m`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Parses the RequestedSkillIDs JSON column into a string array. Tolerant: bad JSON,
|
|
85
|
+
* non-array shapes, and non-string members all collapse to an empty/filtered array.
|
|
86
|
+
*/
|
|
87
|
+
export function ParseSkillIDs(raw) {
|
|
88
|
+
if (!raw || raw.trim().length === 0) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const parsed = JSON.parse(raw);
|
|
93
|
+
if (!Array.isArray(parsed)) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
return parsed.filter((item) => typeof item === 'string' && item.length > 0);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Serializes a skill ID array to the JSON column value (null when empty). */
|
|
103
|
+
export function SerializeSkillIDs(ids) {
|
|
104
|
+
const clean = ids.filter((id) => id && id.length > 0);
|
|
105
|
+
return clean.length > 0 ? JSON.stringify(clean) : null;
|
|
106
|
+
}
|
|
107
|
+
/** Validates optional JSON text (StartingPayload). Blank is valid (stored as NULL). */
|
|
108
|
+
export function ValidateOptionalJson(text) {
|
|
109
|
+
const trimmed = (text ?? '').trim();
|
|
110
|
+
if (trimmed.length === 0) {
|
|
111
|
+
return { Valid: true };
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
JSON.parse(trimmed);
|
|
115
|
+
return { Valid: true };
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
return { Valid: false, Error: e instanceof Error ? e.message : 'Invalid JSON' };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Very light email shape check for external recipients (not RFC-complete on purpose). */
|
|
122
|
+
export function IsPlausibleEmail(email) {
|
|
123
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Converts a Date to the string an `<input type="datetime-local">` expects
|
|
127
|
+
* ("YYYY-MM-DDTHH:MM", local time). Empty string for null.
|
|
128
|
+
*/
|
|
129
|
+
export function ToDateTimeLocal(date) {
|
|
130
|
+
if (!date) {
|
|
131
|
+
return '';
|
|
132
|
+
}
|
|
133
|
+
const d = date instanceof Date ? date : new Date(date);
|
|
134
|
+
if (isNaN(d.getTime())) {
|
|
135
|
+
return '';
|
|
136
|
+
}
|
|
137
|
+
const pad = (n) => n.toString().padStart(2, '0');
|
|
138
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
139
|
+
}
|
|
140
|
+
/** Parses a datetime-local string back to a Date (null for blank/invalid). */
|
|
141
|
+
export function FromDateTimeLocal(value) {
|
|
142
|
+
const trimmed = (value ?? '').trim();
|
|
143
|
+
if (!trimmed) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
const parsed = new Date(trimmed);
|
|
147
|
+
return isNaN(parsed.getTime()) ? null : parsed;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The browser's IANA timezone list via Intl (ES2022), with a small static fallback for
|
|
151
|
+
* older runtimes. The current zone is included by construction on modern browsers.
|
|
152
|
+
*/
|
|
153
|
+
export function GetTimezoneOptions() {
|
|
154
|
+
if (typeof Intl.supportedValuesOf === 'function') {
|
|
155
|
+
return Intl.supportedValuesOf('timeZone');
|
|
156
|
+
}
|
|
157
|
+
return [
|
|
158
|
+
'UTC',
|
|
159
|
+
'America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles',
|
|
160
|
+
'Europe/London', 'Europe/Paris', 'Europe/Berlin',
|
|
161
|
+
'Asia/Tokyo', 'Asia/Shanghai', 'Asia/Kolkata',
|
|
162
|
+
'Australia/Sydney'
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
/** The user's current IANA timezone (falls back to UTC). */
|
|
166
|
+
export function GetLocalTimezone() {
|
|
167
|
+
try {
|
|
168
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return 'UTC';
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=routine-ui-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routine-ui-helpers.js","sourceRoot":"","sources":["../../src/lib/routine-ui-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure display / serialization helpers shared by the User Routines components.\n * No Angular or MJ runtime dependencies — unit-testable in isolation.\n */\nimport type { MJUserRoutineEntity } from '@memberjunction/core-entities';\n\n/** Chip variants aligned with the shared status-token vocabulary. */\nexport type RoutineChipVariant = 'success' | 'warning' | 'error' | 'info' | 'muted';\n\n/** Maps a routine lifecycle status to a chip variant. */\nexport function RoutineStatusVariant(status: MJUserRoutineEntity['Status']): RoutineChipVariant {\n switch (status) {\n case 'Active': return 'success';\n case 'Paused': return 'warning';\n case 'Disabled': return 'muted';\n default: return 'muted';\n }\n}\n\n/** Maps a run outcome status to a chip variant. */\nexport function RunStatusVariant(status: string | null | undefined): RoutineChipVariant {\n switch (status) {\n case 'Success': return 'success';\n case 'Failed': return 'error';\n case 'Running': return 'info';\n case 'Skipped': return 'muted';\n default: return 'muted';\n }\n}\n\n/** Font Awesome icon class for a routine target type. */\nexport function TargetTypeIcon(targetType: MJUserRoutineEntity['TargetType']): string {\n switch (targetType) {\n case 'Agent': return 'fa-solid fa-robot';\n case 'Action': return 'fa-solid fa-bolt';\n case 'Prompt': return 'fa-solid fa-comment-dots';\n default: return 'fa-solid fa-circle-question';\n }\n}\n\n/**\n * Compact relative-time label (\"3m ago\", \"in 2h\", \"just now\"). Returns an empty\n * string for null input. `now` is injectable for tests.\n */\nexport function FormatRelativeTime(date: Date | null | undefined, now: Date = new Date()): string {\n if (!date) {\n return '';\n }\n const target = date instanceof Date ? date : new Date(date);\n if (isNaN(target.getTime())) {\n return '';\n }\n const diffMs = target.getTime() - now.getTime();\n const absMs = Math.abs(diffMs);\n const future = diffMs > 0;\n\n if (absMs < 60_000) {\n return future ? 'in <1m' : 'just now';\n }\n const units: Array<{ ms: number; label: string }> = [\n { ms: 86_400_000 * 365, label: 'y' },\n { ms: 86_400_000 * 30, label: 'mo' },\n { ms: 86_400_000, label: 'd' },\n { ms: 3_600_000, label: 'h' },\n { ms: 60_000, label: 'm' },\n ];\n for (const unit of units) {\n if (absMs >= unit.ms) {\n const count = Math.floor(absMs / unit.ms);\n return future ? `in ${count}${unit.label}` : `${count}${unit.label} ago`;\n }\n }\n return future ? 'in <1m' : 'just now';\n}\n\n/** Duration between two timestamps as \"4s\", \"2m 10s\", \"1h 4m\". Empty when incomplete. */\nexport function FormatDuration(start: Date | null | undefined, end: Date | null | undefined): string {\n if (!start || !end) {\n return '';\n }\n const startMs = new Date(start).getTime();\n const endMs = new Date(end).getTime();\n if (isNaN(startMs) || isNaN(endMs) || endMs < startMs) {\n return '';\n }\n const totalSeconds = Math.round((endMs - startMs) / 1000);\n if (totalSeconds < 60) {\n return `${totalSeconds}s`;\n }\n const totalMinutes = Math.floor(totalSeconds / 60);\n if (totalMinutes < 60) {\n return `${totalMinutes}m ${totalSeconds % 60}s`;\n }\n const hours = Math.floor(totalMinutes / 60);\n return `${hours}h ${totalMinutes % 60}m`;\n}\n\n/**\n * Parses the RequestedSkillIDs JSON column into a string array. Tolerant: bad JSON,\n * non-array shapes, and non-string members all collapse to an empty/filtered array.\n */\nexport function ParseSkillIDs(raw: string | null | undefined): string[] {\n if (!raw || raw.trim().length === 0) {\n return [];\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((item): item is string => typeof item === 'string' && item.length > 0);\n } catch {\n return [];\n }\n}\n\n/** Serializes a skill ID array to the JSON column value (null when empty). */\nexport function SerializeSkillIDs(ids: readonly string[]): string | null {\n const clean = ids.filter((id) => id && id.length > 0);\n return clean.length > 0 ? JSON.stringify(clean) : null;\n}\n\n/** Validates optional JSON text (StartingPayload). Blank is valid (stored as NULL). */\nexport function ValidateOptionalJson(text: string | null | undefined): { Valid: boolean; Error?: string } {\n const trimmed = (text ?? '').trim();\n if (trimmed.length === 0) {\n return { Valid: true };\n }\n try {\n JSON.parse(trimmed);\n return { Valid: true };\n } catch (e) {\n return { Valid: false, Error: e instanceof Error ? e.message : 'Invalid JSON' };\n }\n}\n\n/** Very light email shape check for external recipients (not RFC-complete on purpose). */\nexport function IsPlausibleEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email.trim());\n}\n\n/**\n * Converts a Date to the string an `<input type=\"datetime-local\">` expects\n * (\"YYYY-MM-DDTHH:MM\", local time). Empty string for null.\n */\nexport function ToDateTimeLocal(date: Date | null | undefined): string {\n if (!date) {\n return '';\n }\n const d = date instanceof Date ? date : new Date(date);\n if (isNaN(d.getTime())) {\n return '';\n }\n const pad = (n: number) => n.toString().padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/** Parses a datetime-local string back to a Date (null for blank/invalid). */\nexport function FromDateTimeLocal(value: string | null | undefined): Date | null {\n const trimmed = (value ?? '').trim();\n if (!trimmed) {\n return null;\n }\n const parsed = new Date(trimmed);\n return isNaN(parsed.getTime()) ? null : parsed;\n}\n\n/**\n * The browser's IANA timezone list via Intl (ES2022), with a small static fallback for\n * older runtimes. The current zone is included by construction on modern browsers.\n */\nexport function GetTimezoneOptions(): string[] {\n if (typeof Intl.supportedValuesOf === 'function') {\n return Intl.supportedValuesOf('timeZone');\n }\n return [\n 'UTC',\n 'America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles',\n 'Europe/London', 'Europe/Paris', 'Europe/Berlin',\n 'Asia/Tokyo', 'Asia/Shanghai', 'Asia/Kolkata',\n 'Australia/Sydney'\n ];\n}\n\n/** The user's current IANA timezone (falls back to UTC). */\nexport function GetLocalTimezone(): string {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n } catch {\n return 'UTC';\n }\n}\n"]}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
3
|
+
import { MJUserRoutineEntity } from '@memberjunction/core-entities';
|
|
4
|
+
import { RoutineCounts, RoutineStatusFilter } from './my-routines-list.component';
|
|
5
|
+
import { ConversationOpenedEventArgs, AfterRoutineCreatedEventArgs, AfterRoutineDeletedEventArgs, AfterRoutinePausedEventArgs, AfterRoutineRunNowEventArgs, BeforeRoutineCreatedEventArgs, BeforeRoutineDeletedEventArgs, BeforeRoutinePausedEventArgs, BeforeRoutineRunNowEventArgs, HistoryRecordOpenedEventArgs, RoutineSelectedEventArgs } from './user-routines-events';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
/** The command center's active internal view. */
|
|
8
|
+
export type UserRoutinesView = 'list' | 'editor' | 'history';
|
|
9
|
+
/**
|
|
10
|
+
* User Routines "command center" — the composite surface combining the routines list
|
|
11
|
+
* (default view), the create/edit form, and per-routine run history behind an internal
|
|
12
|
+
* tabbed navigation. This is the component hosts embed (Explorer full page, the
|
|
13
|
+
* slide-in, or any custom app); the individual pieces remain exported for bespoke
|
|
14
|
+
* layouts.
|
|
15
|
+
*
|
|
16
|
+
* All child events bubble here unchanged (including the cancelable Before/After
|
|
17
|
+
* pairs), so a consumer only ever wires this one component.
|
|
18
|
+
*/
|
|
19
|
+
export declare class UserRoutinesCommandCenterComponent extends BaseAngularComponent {
|
|
20
|
+
private cdr;
|
|
21
|
+
private list?;
|
|
22
|
+
private history?;
|
|
23
|
+
/** Render the built-in compact header (mark + tabs + list controls). Hosts with their own chrome set false. */
|
|
24
|
+
ShowHeader: boolean;
|
|
25
|
+
/** Show a close (X) affordance in the built-in header (used by the slide-in wrapper). */
|
|
26
|
+
ShowClose: boolean;
|
|
27
|
+
private _selectedRoutineID;
|
|
28
|
+
/**
|
|
29
|
+
* Deep-link style selection: setting a routine ID opens its history view
|
|
30
|
+
* (clearing it returns to the list). Used by Explorer's query-param round trip.
|
|
31
|
+
*/
|
|
32
|
+
set SelectedRoutineID(value: string | null);
|
|
33
|
+
get SelectedRoutineID(): string | null;
|
|
34
|
+
/** Search text applied to the list view (hosts with their own chrome bind this). */
|
|
35
|
+
SearchText: string;
|
|
36
|
+
/** Status filter applied to the list view. */
|
|
37
|
+
StatusFilter: RoutineStatusFilter;
|
|
38
|
+
BeforeRoutineCreated: EventEmitter<BeforeRoutineCreatedEventArgs>;
|
|
39
|
+
AfterRoutineCreated: EventEmitter<AfterRoutineCreatedEventArgs>;
|
|
40
|
+
BeforeRoutinePaused: EventEmitter<BeforeRoutinePausedEventArgs>;
|
|
41
|
+
AfterRoutinePaused: EventEmitter<AfterRoutinePausedEventArgs>;
|
|
42
|
+
BeforeRoutineRunNow: EventEmitter<BeforeRoutineRunNowEventArgs>;
|
|
43
|
+
AfterRoutineRunNow: EventEmitter<AfterRoutineRunNowEventArgs>;
|
|
44
|
+
BeforeRoutineDeleted: EventEmitter<BeforeRoutineDeletedEventArgs>;
|
|
45
|
+
AfterRoutineDeleted: EventEmitter<AfterRoutineDeletedEventArgs>;
|
|
46
|
+
RoutineSelected: EventEmitter<RoutineSelectedEventArgs>;
|
|
47
|
+
HistoryRecordOpened: EventEmitter<HistoryRecordOpenedEventArgs>;
|
|
48
|
+
/** Re-emitted from the list — the routine's dedicated conversation was requested. */
|
|
49
|
+
ConversationOpened: EventEmitter<ConversationOpenedEventArgs>;
|
|
50
|
+
/** Loaded/filtered counts changed in the list view. */
|
|
51
|
+
CountsChanged: EventEmitter<RoutineCounts>;
|
|
52
|
+
/** The active internal view changed ('list' | 'editor' | 'history'). */
|
|
53
|
+
ViewChanged: EventEmitter<UserRoutinesView>;
|
|
54
|
+
/** The user clicked the built-in close affordance (slide-in wrapper handles it). */
|
|
55
|
+
CloseRequested: EventEmitter<void>;
|
|
56
|
+
/**
|
|
57
|
+
* The selected routine (history view) changed — `null` when returning to the list.
|
|
58
|
+
* Hosts using query-param round trips two-way bind [(SelectedRoutineID)].
|
|
59
|
+
*/
|
|
60
|
+
SelectedRoutineIDChange: EventEmitter<string | null>;
|
|
61
|
+
ActiveView: UserRoutinesView;
|
|
62
|
+
/** Routine being edited (null = creating a new one). */
|
|
63
|
+
EditingRoutineID: string | null;
|
|
64
|
+
/** Routine whose history is open. */
|
|
65
|
+
HistoryRoutineID: string | null;
|
|
66
|
+
HistoryRoutineName: string | null;
|
|
67
|
+
TotalCount: number;
|
|
68
|
+
FilteredCount: number;
|
|
69
|
+
ShowList(): void;
|
|
70
|
+
ShowNewRoutine(): void;
|
|
71
|
+
ShowEditRoutine(routine: MJUserRoutineEntity | string): void;
|
|
72
|
+
ShowHistory(routine: MJUserRoutineEntity | string): void;
|
|
73
|
+
/** Force-refreshes the active view's data. */
|
|
74
|
+
Refresh(): Promise<void>;
|
|
75
|
+
OnCountsChanged(counts: RoutineCounts): void;
|
|
76
|
+
OnRoutineSelected(args: RoutineSelectedEventArgs): void;
|
|
77
|
+
OnHistoryRequested(routine: MJUserRoutineEntity): void;
|
|
78
|
+
OnEditRequested(routine: MJUserRoutineEntity): void;
|
|
79
|
+
OnEditorSaved(_routine: MJUserRoutineEntity): void;
|
|
80
|
+
OnEditorCancelled(): void;
|
|
81
|
+
OnSearchChange(value: string): void;
|
|
82
|
+
private setView;
|
|
83
|
+
private setSelectedRoutine;
|
|
84
|
+
private openHistoryById;
|
|
85
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UserRoutinesCommandCenterComponent, never>;
|
|
86
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UserRoutinesCommandCenterComponent, "mj-user-routines-command-center", never, { "ShowHeader": { "alias": "ShowHeader"; "required": false; }; "ShowClose": { "alias": "ShowClose"; "required": false; }; "SelectedRoutineID": { "alias": "SelectedRoutineID"; "required": false; }; "SearchText": { "alias": "SearchText"; "required": false; }; "StatusFilter": { "alias": "StatusFilter"; "required": false; }; }, { "BeforeRoutineCreated": "BeforeRoutineCreated"; "AfterRoutineCreated": "AfterRoutineCreated"; "BeforeRoutinePaused": "BeforeRoutinePaused"; "AfterRoutinePaused": "AfterRoutinePaused"; "BeforeRoutineRunNow": "BeforeRoutineRunNow"; "AfterRoutineRunNow": "AfterRoutineRunNow"; "BeforeRoutineDeleted": "BeforeRoutineDeleted"; "AfterRoutineDeleted": "AfterRoutineDeleted"; "RoutineSelected": "RoutineSelected"; "HistoryRecordOpened": "HistoryRecordOpened"; "ConversationOpened": "ConversationOpened"; "CountsChanged": "CountsChanged"; "ViewChanged": "ViewChanged"; "CloseRequested": "CloseRequested"; "SelectedRoutineIDChange": "SelectedRoutineIDChange"; }, never, never, false, never>;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=user-routines-command-center.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-routines-command-center.component.d.ts","sourceRoot":"","sources":["../../src/lib/user-routines-command-center.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,YAAY,EAAoC,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAqB,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAA2B,aAAa,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAE3G,OAAO,EAAE,2BAA2B,EAChC,4BAA4B,EAC5B,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,6BAA6B,EAC7B,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,wBAAwB,EAC3B,MAAM,wBAAwB,CAAC;;AAEhC,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;GASG;AACH,qBAMa,kCAAmC,SAAQ,oBAAoB;IACxE,OAAO,CAAC,GAAG,CAA6B;IAErB,OAAO,CAAC,IAAI,CAAC,CAA0B;IACpC,OAAO,CAAC,OAAO,CAAC,CAA0B;IAKhE,+GAA+G;IACtG,UAAU,UAAQ;IAC3B,yFAAyF;IAChF,SAAS,UAAS;IAE3B,OAAO,CAAC,kBAAkB,CAAuB;IACjD;;;OAGG;IACH,IACW,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAShD;IACD,IAAW,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAE5C;IAED,oFAAoF;IAC3E,UAAU,SAAM;IACzB,8CAA8C;IACrC,YAAY,EAAE,mBAAmB,CAAS;IAKzC,oBAAoB,8CAAqD;IACzE,mBAAmB,6CAAoD;IACvE,mBAAmB,6CAAoD;IACvE,kBAAkB,4CAAmD;IACrE,mBAAmB,6CAAoD;IACvE,kBAAkB,4CAAmD;IACrE,oBAAoB,8CAAqD;IACzE,mBAAmB,6CAAoD;IACvE,eAAe,yCAAgD;IAC/D,mBAAmB,6CAAoD;IACjF,qFAAqF;IAC3E,kBAAkB,4CAAmD;IAC/E,uDAAuD;IAC7C,aAAa,8BAAqC;IAC5D,wEAAwE;IAC9D,WAAW,iCAAwC;IAC7D,oFAAoF;IAC1E,cAAc,qBAA4B;IACpD;;;OAGG;IACO,uBAAuB,8BAAqC;IAK/D,UAAU,EAAE,gBAAgB,CAAU;IAC7C,wDAAwD;IACjD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9C,qCAAqC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACvC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACzC,UAAU,SAAK;IACf,aAAa,SAAK;IAKlB,QAAQ,IAAI,IAAI;IAKhB,cAAc,IAAI,IAAI;IAKtB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI;IAK5D,WAAW,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI;IAW/D,8CAA8C;IACjC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAO5C,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,IAAI;IAIvD,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAItD,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAInD,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI;IAIlD,iBAAiB,IAAI,IAAI;IAIzB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ1C,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,eAAe;yCAzKd,kCAAkC;2CAAlC,kCAAkC;CAiL9C"}
|