@memberjunction/ng-explorer-core 6.2.0-edge.3 → 6.2.0-edge.4
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/README.md +10 -0
- package/dist/app-routing.module.d.ts.map +1 -1
- package/dist/app-routing.module.js +5 -0
- package/dist/app-routing.module.js.map +1 -1
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +3 -2
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/guards/moved-nav-item-redirect.d.ts +15 -0
- package/dist/lib/guards/moved-nav-item-redirect.d.ts.map +1 -0
- package/dist/lib/guards/moved-nav-item-redirect.js +37 -0
- package/dist/lib/guards/moved-nav-item-redirect.js.map +1 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.d.ts +34 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.d.ts.map +1 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.js +70 -0
- package/dist/lib/omnibar/omnibar-dashboard-matches.js.map +1 -0
- package/dist/lib/omnibar/omnibar-palette.component.d.ts +27 -2
- package/dist/lib/omnibar/omnibar-palette.component.d.ts.map +1 -1
- package/dist/lib/omnibar/omnibar-palette.component.js +126 -65
- package/dist/lib/omnibar/omnibar-palette.component.js.map +1 -1
- package/dist/lib/omnibar/omnibar-provider.d.ts +4 -0
- package/dist/lib/omnibar/omnibar-provider.d.ts.map +1 -1
- package/dist/lib/omnibar/omnibar-provider.js.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts +2 -2
- package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-record.provider.js +3 -7
- package/dist/lib/omnibar/providers/omnibar-record.provider.js.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts +15 -2
- package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts.map +1 -1
- package/dist/lib/omnibar/providers/omnibar-search.provider.js +59 -7
- package/dist/lib/omnibar/providers/omnibar-search.provider.js.map +1 -1
- package/dist/lib/profile/forking-setting.d.ts +8 -0
- package/dist/lib/profile/forking-setting.d.ts.map +1 -0
- package/dist/lib/profile/forking-setting.js +18 -0
- package/dist/lib/profile/forking-setting.js.map +1 -0
- package/dist/lib/profile/profile-dialog.component.d.ts +8 -0
- package/dist/lib/profile/profile-dialog.component.d.ts.map +1 -1
- package/dist/lib/profile/profile-dialog.component.js +182 -92
- package/dist/lib/profile/profile-dialog.component.js.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +16 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.js +27 -4
- package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +7 -18
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +20 -41
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-search-routing.d.ts +10 -3
- package/dist/lib/resource-wrappers/chat-search-routing.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-search-routing.js +11 -4
- package/dist/lib/resource-wrappers/chat-search-routing.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.d.ts +29 -0
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.js +141 -0
- package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.d.ts +28 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.js +150 -0
- package/dist/lib/resource-wrappers/dashboard-part-config.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +361 -56
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +1312 -361
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-source-search.d.ts +86 -0
- package/dist/lib/resource-wrappers/dashboard-source-search.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-source-search.js +136 -0
- package/dist/lib/resource-wrappers/dashboard-source-search.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.d.ts +30 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.js +55 -0
- package/dist/lib/resource-wrappers/dashboard-studio-pane.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.d.ts +135 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.js +856 -0
- package/dist/lib/resource-wrappers/dashboard-studio-tools.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.d.ts +87 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.js +125 -0
- package/dist/lib/resource-wrappers/dashboard-tab-agent.js.map +1 -0
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts +28 -7
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js +174 -112
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +5 -4
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +7 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +20 -2
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/dashboard-tab-for-url.d.ts +35 -0
- package/dist/lib/shell/dashboard-tab-for-url.d.ts.map +1 -0
- package/dist/lib/shell/dashboard-tab-for-url.js +39 -0
- package/dist/lib/shell/dashboard-tab-for-url.js.map +1 -0
- package/dist/lib/shell/shell.component.d.ts +31 -2
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +109 -35
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +2 -1
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +6 -2
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/template-user/template-user-banner.component.d.ts +20 -0
- package/dist/lib/template-user/template-user-banner.component.d.ts.map +1 -0
- package/dist/lib/template-user/template-user-banner.component.js +67 -0
- package/dist/lib/template-user/template-user-banner.component.js.map +1 -0
- package/dist/module.d.ts +61 -59
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +58 -53
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-source-search.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/dashboard-source-search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElE,uEAAuE;AACvE,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAA4C,CAAC;AAE3F;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,0HAShC,CAAC;AAEX,2GAA2G;AAC3G,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,0DAA0D;IAC1D,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,+HAA+H;IAC/H,aAAa,EAAE,OAAO,CAAC;IACvB,yHAAyH;IACzH,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,qGAAqG;AACrG,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAC;IAC1J,+DAA+D;IAC/D,SAAS,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/G,oCAAoC;IACpC,WAAW,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACxG,sCAAsC;IACtC,YAAY,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC7G;AAOD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,CAU1I;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAM/B"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Source search for the dashboard studio tools: finds the artifacts, user views, queries and
|
|
3
|
+
* entities that match the agent's query, ranks them, and gives each match a panel config for AddPanel.
|
|
4
|
+
* Pure: the tab passes in the lists through {@link SourceSearchDeps}, already limited to what the user may use.
|
|
5
|
+
*/
|
|
6
|
+
/** Every {@link SourceKind}, in the order search results list them. */
|
|
7
|
+
export const SOURCE_KINDS = ['artifact', 'view', 'query', 'entity'];
|
|
8
|
+
/**
|
|
9
|
+
* The artifact types that suit an Artifact panel, by their names in the `MJ: Artifact Types` metadata:
|
|
10
|
+
* interactive components and reports, data (with Data Snapshot and Search Result Set, which use the same
|
|
11
|
+
* viewer), HTML, SVG and Markdown.
|
|
12
|
+
*/
|
|
13
|
+
export const DASHBOARD_ARTIFACT_TYPE_NAMES = [
|
|
14
|
+
'Component',
|
|
15
|
+
'Report',
|
|
16
|
+
'Data',
|
|
17
|
+
'Data Snapshot',
|
|
18
|
+
'Search Result Set',
|
|
19
|
+
'HTML',
|
|
20
|
+
'SVG Image',
|
|
21
|
+
'Markdown Document',
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* The items that match the query, best first, at most `limit` of them: exact name, then name start, then
|
|
25
|
+
* name contains, then description contains, ignoring case and the query's outer spaces. Items in one tier
|
|
26
|
+
* keep the order they were given in. An empty query gives the first `limit` items by name. The input
|
|
27
|
+
* array is not changed.
|
|
28
|
+
*/
|
|
29
|
+
export function RankByQuery(items, query, limit) {
|
|
30
|
+
const count = Math.max(0, limit);
|
|
31
|
+
const text = query.trim().toLowerCase();
|
|
32
|
+
if (!text)
|
|
33
|
+
return [...items].sort((a, b) => a.name.localeCompare(b.name)).slice(0, count);
|
|
34
|
+
return items
|
|
35
|
+
.map((item, index) => ({ item, index, tier: matchTier(item, text) }))
|
|
36
|
+
.filter(ranked => ranked.tier >= 0)
|
|
37
|
+
.sort((a, b) => a.tier - b.tier || a.index - b.index)
|
|
38
|
+
.slice(0, count)
|
|
39
|
+
.map(ranked => ranked.item);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Searches the sources of the requested kinds and gives up to `limit` results of each kind, ranked with
|
|
43
|
+
* {@link RankByQuery}, in {@link SOURCE_KINDS} order. It reads only the lists of the kinds it searches,
|
|
44
|
+
* and gives the artifact list the query without its outer spaces.
|
|
45
|
+
*/
|
|
46
|
+
export async function SearchDashboardSources(deps, query, kinds, limit) {
|
|
47
|
+
const results = [];
|
|
48
|
+
for (const kind of SOURCE_KINDS) {
|
|
49
|
+
if (kinds.includes(kind))
|
|
50
|
+
results.push(...RankByQuery(await listSources(deps, kind, query.trim()), query, limit));
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
/** How well an item matches a lowercase query: 0 exact name, 1 name start, 2 name contains, 3 description contains, -1 no match. */
|
|
55
|
+
function matchTier(item, text) {
|
|
56
|
+
const name = item.name.trim().toLowerCase();
|
|
57
|
+
if (name === text)
|
|
58
|
+
return 0;
|
|
59
|
+
if (name.startsWith(text))
|
|
60
|
+
return 1;
|
|
61
|
+
if (name.includes(text))
|
|
62
|
+
return 2;
|
|
63
|
+
return (item.description ?? '').toLowerCase().includes(text) ? 3 : -1;
|
|
64
|
+
}
|
|
65
|
+
/** The sources of one kind, as search results in the order the list gives them. The artifact list gets `query`. */
|
|
66
|
+
async function listSources(deps, kind, query) {
|
|
67
|
+
switch (kind) {
|
|
68
|
+
case 'artifact':
|
|
69
|
+
return (await deps.ListArtifacts(query)).map(artifactResult);
|
|
70
|
+
case 'view':
|
|
71
|
+
return deps.ListViews().map(viewResult);
|
|
72
|
+
case 'query':
|
|
73
|
+
return deps.ListQueries().map(queryResult);
|
|
74
|
+
case 'entity':
|
|
75
|
+
return deps.ListEntities().map(entityResult);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* An artifact as a search result. The config names the latest version when the list gives it; without a
|
|
80
|
+
* version number the panel shows the artifact's latest version.
|
|
81
|
+
*/
|
|
82
|
+
function artifactResult(artifact) {
|
|
83
|
+
const version = artifact.LatestVersion;
|
|
84
|
+
const versionKey = typeof version === 'number' && Number.isInteger(version) && version > 0 ? { versionNumber: version } : {};
|
|
85
|
+
return {
|
|
86
|
+
kind: 'artifact',
|
|
87
|
+
id: artifact.ID,
|
|
88
|
+
name: artifact.Name,
|
|
89
|
+
description: artifact.Description,
|
|
90
|
+
type: artifact.Type,
|
|
91
|
+
fitsDashboard: suitsPanel(artifact.Type),
|
|
92
|
+
suggestedConfig: { type: 'Artifact', artifactId: artifact.ID, ...versionKey },
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** A user view as a search result: a View panel of the view. */
|
|
96
|
+
function viewResult(view) {
|
|
97
|
+
return {
|
|
98
|
+
kind: 'view',
|
|
99
|
+
id: view.ID,
|
|
100
|
+
name: view.Name,
|
|
101
|
+
description: view.Description,
|
|
102
|
+
type: view.Entity,
|
|
103
|
+
fitsDashboard: true,
|
|
104
|
+
suggestedConfig: { type: 'View', viewId: view.ID, entityName: view.Entity },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** A query as a search result: a Query panel of the query. */
|
|
108
|
+
function queryResult(query) {
|
|
109
|
+
return {
|
|
110
|
+
kind: 'query',
|
|
111
|
+
id: query.ID,
|
|
112
|
+
name: query.Name,
|
|
113
|
+
description: query.Description,
|
|
114
|
+
type: query.Category,
|
|
115
|
+
fitsDashboard: true,
|
|
116
|
+
suggestedConfig: { type: 'Query', queryId: query.ID },
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** An entity as a search result: a View panel of all its records. */
|
|
120
|
+
function entityResult(entity) {
|
|
121
|
+
return {
|
|
122
|
+
kind: 'entity',
|
|
123
|
+
id: entity.ID,
|
|
124
|
+
name: entity.DisplayName || entity.Name,
|
|
125
|
+
description: entity.Description,
|
|
126
|
+
type: 'entity',
|
|
127
|
+
fitsDashboard: true,
|
|
128
|
+
suggestedConfig: { type: 'View', entityName: entity.Name },
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** True when the artifact type is one of DASHBOARD_ARTIFACT_TYPE_NAMES, ignoring case and outer spaces. */
|
|
132
|
+
function suitsPanel(type) {
|
|
133
|
+
const name = type?.trim().toLowerCase();
|
|
134
|
+
return DASHBOARD_ARTIFACT_TYPE_NAMES.some(known => known.toLowerCase() === name);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=dashboard-source-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-source-search.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/dashboard-source-search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,uEAAuE;AACvE,MAAM,CAAC,MAAM,YAAY,GAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAE3F;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,WAAW;IACX,QAAQ;IACR,MAAM;IACN,eAAe;IACf,mBAAmB;IACnB,MAAM;IACN,WAAW;IACX,mBAAmB;CACX,CAAC;AAyCX;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAyD,KAAmB,EAAE,KAAa,EAAE,KAAa;IACnI,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC1F,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;SACpE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;SAClC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SACpD,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAsB,EACtB,KAAa,EACb,KAA4B,EAC5B,KAAa;IAEb,MAAM,OAAO,GAAyB,EAAE,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACpH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,oIAAoI;AACpI,SAAS,SAAS,CAAC,IAAkD,EAAE,IAAY;IACjF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IAC5B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,mHAAmH;AACnH,KAAK,UAAU,WAAW,CAAC,IAAsB,EAAE,IAAgB,EAAE,KAAa;IAChF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC/D,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC1C,KAAK,OAAO;YACV,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC7C,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,QAAwB;IAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7H,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,aAAa,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxC,eAAe,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,UAAU,EAAE;KAC9E,CAAC;AACJ,CAAC;AAED,gEAAgE;AAChE,SAAS,UAAU,CAAC,IAAgB;IAClC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE;KAC5E,CAAC;AACJ,CAAC;AAED,8DAA8D;AAC9D,SAAS,WAAW,CAAC,KAAkB;IACrC,OAAO;QACL,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI,EAAE,KAAK,CAAC,QAAQ;QACpB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE;KACtD,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,SAAS,YAAY,CAAC,MAAoB;IACxC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI;QACvC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,IAAI,EAAE,QAAQ;QACd,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE;KAC3D,CAAC;AACJ,CAAC;AAED,2GAA2G;AAC3G,SAAS,UAAU,CAAC,IAAmB;IACrC,MAAM,IAAI,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,OAAO,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,CAAC;AACnF,CAAC","sourcesContent":["/**\n * @fileoverview Source search for the dashboard studio tools: finds the artifacts, user views, queries and\n * entities that match the agent's query, ranks them, and gives each match a panel config for AddPanel.\n * Pure: the tab passes in the lists through {@link SourceSearchDeps}, already limited to what the user may use.\n */\n\n/** The kinds of source a dashboard panel can show. */\nexport type SourceKind = 'artifact' | 'view' | 'query' | 'entity';\n\n/** Every {@link SourceKind}, in the order search results list them. */\nexport const SOURCE_KINDS: readonly SourceKind[] = ['artifact', 'view', 'query', 'entity'];\n\n/**\n * The artifact types that suit an Artifact panel, by their names in the `MJ: Artifact Types` metadata:\n * interactive components and reports, data (with Data Snapshot and Search Result Set, which use the same\n * viewer), HTML, SVG and Markdown.\n */\nexport const DASHBOARD_ARTIFACT_TYPE_NAMES = [\n 'Component',\n 'Report',\n 'Data',\n 'Data Snapshot',\n 'Search Result Set',\n 'HTML',\n 'SVG Image',\n 'Markdown Document',\n] as const;\n\n/** One source the agent can show in a dashboard panel. The keys are the SearchSources tool result keys. */\nexport interface SourceSearchResult {\n /** What the source is. */\n kind: SourceKind; // case-violation-ok-legacy-back-compat: SearchSources result keys the spec fixes, camelCase like every studio tool result\n /** The ID of the artifact, user view, query or entity. */\n id: string | null; // case-violation-ok-legacy-back-compat: SearchSources result keys the spec fixes, camelCase like every studio tool result\n /** The source's name. For an entity, its display name when it has one. */\n name: string; // case-violation-ok-legacy-back-compat: SearchSources result keys the spec fixes, camelCase like every studio tool result\n /** The source's description. */\n description: string | null; // case-violation-ok-legacy-back-compat: SearchSources result keys the spec fixes, camelCase like every studio tool result\n /** The artifact type, the view's entity, the query's category, or \"entity\". */\n type: string | null; // case-violation-ok-legacy-back-compat: SearchSources result keys the spec fixes, camelCase like every studio tool result\n /** False for an artifact whose type does not suit a panel (see DASHBOARD_ARTIFACT_TYPE_NAMES). True for every other source. */\n fitsDashboard: boolean; // case-violation-ok-legacy-back-compat: SearchSources result keys the spec fixes, camelCase like every studio tool result\n /** A panel config for AddPanel: `type` is the part type (Artifact, View or Query), and the other keys are its config. */\n suggestedConfig: Record<string, unknown>; // case-violation-ok-legacy-back-compat: SearchSources result keys the spec fixes, camelCase like every studio tool result\n}\n\n/** The lists the search reads. The tab builds them from the engines with the user's access rules. */\nexport interface SourceSearchDeps {\n /**\n * The artifacts the user can read. `query` is the search text without its outer spaces, or '' to list\n * every artifact; the list can leave out the artifacts whose name and description do not contain it.\n * `LatestVersion` is null when the list does not give it.\n */\n ListArtifacts(query: string): Promise<Array<{ ID: string; Name: string; Description: string | null; Type: string | null; LatestVersion: number | null }>>;\n /** The user's own views and the views shared with the user. */\n ListViews(): Array<{ ID: string; Name: string; Description: string | null; Entity: string; EntityID: string }>;\n /** The queries the user can run. */\n ListQueries(): Array<{ ID: string; Name: string; Description: string | null; Category: string | null }>;\n /** The entities the user can read. */\n ListEntities(): Array<{ ID: string; Name: string; DisplayName: string | null; Description: string | null }>;\n}\n\ntype ArtifactSource = Awaited<ReturnType<SourceSearchDeps['ListArtifacts']>>[number];\ntype ViewSource = ReturnType<SourceSearchDeps['ListViews']>[number];\ntype QuerySource = ReturnType<SourceSearchDeps['ListQueries']>[number];\ntype EntitySource = ReturnType<SourceSearchDeps['ListEntities']>[number];\n\n/**\n * The items that match the query, best first, at most `limit` of them: exact name, then name start, then\n * name contains, then description contains, ignoring case and the query's outer spaces. Items in one tier\n * keep the order they were given in. An empty query gives the first `limit` items by name. The input\n * array is not changed.\n */\nexport function RankByQuery<T extends { name: string; description: string | null }>(items: readonly T[], query: string, limit: number): T[] {\n const count = Math.max(0, limit);\n const text = query.trim().toLowerCase();\n if (!text) return [...items].sort((a, b) => a.name.localeCompare(b.name)).slice(0, count);\n return items\n .map((item, index) => ({ item, index, tier: matchTier(item, text) }))\n .filter(ranked => ranked.tier >= 0)\n .sort((a, b) => a.tier - b.tier || a.index - b.index)\n .slice(0, count)\n .map(ranked => ranked.item);\n}\n\n/**\n * Searches the sources of the requested kinds and gives up to `limit` results of each kind, ranked with\n * {@link RankByQuery}, in {@link SOURCE_KINDS} order. It reads only the lists of the kinds it searches,\n * and gives the artifact list the query without its outer spaces.\n */\nexport async function SearchDashboardSources(\n deps: SourceSearchDeps,\n query: string,\n kinds: readonly SourceKind[],\n limit: number,\n): Promise<SourceSearchResult[]> {\n const results: SourceSearchResult[] = [];\n for (const kind of SOURCE_KINDS) {\n if (kinds.includes(kind)) results.push(...RankByQuery(await listSources(deps, kind, query.trim()), query, limit));\n }\n return results;\n}\n\n/** How well an item matches a lowercase query: 0 exact name, 1 name start, 2 name contains, 3 description contains, -1 no match. */\nfunction matchTier(item: { name: string; description: string | null }, text: string): number {\n const name = item.name.trim().toLowerCase();\n if (name === text) return 0;\n if (name.startsWith(text)) return 1;\n if (name.includes(text)) return 2;\n return (item.description ?? '').toLowerCase().includes(text) ? 3 : -1;\n}\n\n/** The sources of one kind, as search results in the order the list gives them. The artifact list gets `query`. */\nasync function listSources(deps: SourceSearchDeps, kind: SourceKind, query: string): Promise<SourceSearchResult[]> {\n switch (kind) {\n case 'artifact':\n return (await deps.ListArtifacts(query)).map(artifactResult);\n case 'view':\n return deps.ListViews().map(viewResult);\n case 'query':\n return deps.ListQueries().map(queryResult);\n case 'entity':\n return deps.ListEntities().map(entityResult);\n }\n}\n\n/**\n * An artifact as a search result. The config names the latest version when the list gives it; without a\n * version number the panel shows the artifact's latest version.\n */\nfunction artifactResult(artifact: ArtifactSource): SourceSearchResult {\n const version = artifact.LatestVersion;\n const versionKey = typeof version === 'number' && Number.isInteger(version) && version > 0 ? { versionNumber: version } : {};\n return {\n kind: 'artifact',\n id: artifact.ID,\n name: artifact.Name,\n description: artifact.Description,\n type: artifact.Type,\n fitsDashboard: suitsPanel(artifact.Type),\n suggestedConfig: { type: 'Artifact', artifactId: artifact.ID, ...versionKey },\n };\n}\n\n/** A user view as a search result: a View panel of the view. */\nfunction viewResult(view: ViewSource): SourceSearchResult {\n return {\n kind: 'view',\n id: view.ID,\n name: view.Name,\n description: view.Description,\n type: view.Entity,\n fitsDashboard: true,\n suggestedConfig: { type: 'View', viewId: view.ID, entityName: view.Entity },\n };\n}\n\n/** A query as a search result: a Query panel of the query. */\nfunction queryResult(query: QuerySource): SourceSearchResult {\n return {\n kind: 'query',\n id: query.ID,\n name: query.Name,\n description: query.Description,\n type: query.Category,\n fitsDashboard: true,\n suggestedConfig: { type: 'Query', queryId: query.ID },\n };\n}\n\n/** An entity as a search result: a View panel of all its records. */\nfunction entityResult(entity: EntitySource): SourceSearchResult {\n return {\n kind: 'entity',\n id: entity.ID,\n name: entity.DisplayName || entity.Name,\n description: entity.Description,\n type: 'entity',\n fitsDashboard: true,\n suggestedConfig: { type: 'View', entityName: entity.Name },\n };\n}\n\n/** True when the artifact type is one of DASHBOARD_ARTIFACT_TYPE_NAMES, ignoring case and outer spaces. */\nfunction suitsPanel(type: string | null): boolean {\n const name = type?.trim().toLowerCase();\n return DASHBOARD_ARTIFACT_TYPE_NAMES.some(known => known.toLowerCase() === name);\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The width of the AI pane in the dashboard tab: the user setting that stores it, and the reads that turn
|
|
3
|
+
* the setting and angular-split's sizes into widths the tab can use.
|
|
4
|
+
*/
|
|
5
|
+
/** The UserInfoEngine setting that stores the AI pane width. */
|
|
6
|
+
export declare const STUDIO_PANE_SETTING_KEY = "mj.dashboards.studio.layout";
|
|
7
|
+
/** The smallest width of the AI pane, in percent of the tab's width. */
|
|
8
|
+
export declare const STUDIO_PANE_COPILOT_MIN_PCT = 20;
|
|
9
|
+
/** The largest width of the AI pane, in percent of the tab's width. */
|
|
10
|
+
export declare const STUDIO_PANE_COPILOT_MAX_PCT = 60;
|
|
11
|
+
/** The widths of the dashboard and the AI pane, in percent of the tab's width. They add up to 100. */
|
|
12
|
+
export interface StudioPanePrefs {
|
|
13
|
+
/** The dashboard's width. */
|
|
14
|
+
MainSizePct: number;
|
|
15
|
+
/** The AI pane's width, a whole number from STUDIO_PANE_COPILOT_MIN_PCT to STUDIO_PANE_COPILOT_MAX_PCT. */
|
|
16
|
+
CopilotSizePct: number;
|
|
17
|
+
}
|
|
18
|
+
/** The widths the AI pane opens with when no width is saved. */
|
|
19
|
+
export declare const STUDIO_PANE_DEFAULTS: Readonly<StudioPanePrefs>;
|
|
20
|
+
/**
|
|
21
|
+
* The widths in the saved setting, or the defaults when the setting is missing or holds no number for the
|
|
22
|
+
* AI pane. The AI pane width is rounded and kept in its bounds; the dashboard gets the rest.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ParseStudioPanePrefs(raw: string | null | undefined): StudioPanePrefs;
|
|
25
|
+
/**
|
|
26
|
+
* The widths from the sizes of an angular-split dragEnd event, read as the AI pane width ParseStudioPanePrefs
|
|
27
|
+
* would give, or null unless the event holds exactly two finite numbers.
|
|
28
|
+
*/
|
|
29
|
+
export declare function PrefsFromSplitSizes(sizes: readonly (number | '*')[]): StudioPanePrefs | null;
|
|
30
|
+
//# sourceMappingURL=dashboard-studio-pane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-studio-pane.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/dashboard-studio-pane.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,gEAAgE;AAChE,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AAErE,wEAAwE;AACxE,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C,uEAAuE;AACvE,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C,sGAAsG;AACtG,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,2GAA2G;IAC3G,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,eAAe,CAA2C,CAAC;AAEvG;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,CAGpF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,eAAe,GAAG,IAAI,CAK5F"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The width of the AI pane in the dashboard tab: the user setting that stores it, and the reads that turn
|
|
3
|
+
* the setting and angular-split's sizes into widths the tab can use.
|
|
4
|
+
*/
|
|
5
|
+
/** The UserInfoEngine setting that stores the AI pane width. */
|
|
6
|
+
export const STUDIO_PANE_SETTING_KEY = 'mj.dashboards.studio.layout';
|
|
7
|
+
/** The smallest width of the AI pane, in percent of the tab's width. */
|
|
8
|
+
export const STUDIO_PANE_COPILOT_MIN_PCT = 20;
|
|
9
|
+
/** The largest width of the AI pane, in percent of the tab's width. */
|
|
10
|
+
export const STUDIO_PANE_COPILOT_MAX_PCT = 60;
|
|
11
|
+
/** The widths the AI pane opens with when no width is saved. */
|
|
12
|
+
export const STUDIO_PANE_DEFAULTS = { MainSizePct: 68, CopilotSizePct: 32 };
|
|
13
|
+
/**
|
|
14
|
+
* The widths in the saved setting, or the defaults when the setting is missing or holds no number for the
|
|
15
|
+
* AI pane. The AI pane width is rounded and kept in its bounds; the dashboard gets the rest.
|
|
16
|
+
*/
|
|
17
|
+
export function ParseStudioPanePrefs(raw) {
|
|
18
|
+
const copilotSize = savedCopilotSize(raw);
|
|
19
|
+
return copilotSize === null ? { ...STUDIO_PANE_DEFAULTS } : prefsForCopilotSize(copilotSize);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The widths from the sizes of an angular-split dragEnd event, read as the AI pane width ParseStudioPanePrefs
|
|
23
|
+
* would give, or null unless the event holds exactly two finite numbers.
|
|
24
|
+
*/
|
|
25
|
+
export function PrefsFromSplitSizes(sizes) {
|
|
26
|
+
if (sizes.length !== 2)
|
|
27
|
+
return null;
|
|
28
|
+
const [mainSize, copilotSize] = sizes;
|
|
29
|
+
if (!isFiniteNumber(mainSize) || !isFiniteNumber(copilotSize))
|
|
30
|
+
return null;
|
|
31
|
+
return prefsForCopilotSize(copilotSize);
|
|
32
|
+
}
|
|
33
|
+
/** The AI pane width in the saved setting, or null when the setting is not JSON with a finite CopilotSizePct. */
|
|
34
|
+
function savedCopilotSize(raw) {
|
|
35
|
+
if (!raw)
|
|
36
|
+
return null;
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(raw);
|
|
39
|
+
if (typeof parsed !== 'object' || parsed === null || !('CopilotSizePct' in parsed))
|
|
40
|
+
return null;
|
|
41
|
+
return isFiniteNumber(parsed.CopilotSizePct) ? parsed.CopilotSizePct : null;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** The widths for an AI pane width, rounded and kept in its bounds, with the rest for the dashboard. */
|
|
48
|
+
function prefsForCopilotSize(copilotSize) {
|
|
49
|
+
const copilot = Math.max(STUDIO_PANE_COPILOT_MIN_PCT, Math.min(STUDIO_PANE_COPILOT_MAX_PCT, Math.round(copilotSize)));
|
|
50
|
+
return { MainSizePct: 100 - copilot, CopilotSizePct: copilot };
|
|
51
|
+
}
|
|
52
|
+
function isFiniteNumber(value) {
|
|
53
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=dashboard-studio-pane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-studio-pane.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/dashboard-studio-pane.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,gEAAgE;AAChE,MAAM,CAAC,MAAM,uBAAuB,GAAG,6BAA6B,CAAC;AAErE,wEAAwE;AACxE,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,uEAAuE;AACvE,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAU9C,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAA8B,EAAE,WAAW,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;AAEvG;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAA8B;IACjE,MAAM,WAAW,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,oBAAoB,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;AAC/F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAgC;IAClE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC;IACtC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,OAAO,mBAAmB,CAAC,WAAW,CAAC,CAAC;AAC1C,CAAC;AAED,iHAAiH;AACjH,SAAS,gBAAgB,CAAC,GAA8B;IACtD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,gBAAgB,IAAI,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QAChG,OAAO,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,wGAAwG;AACxG,SAAS,mBAAmB,CAAC,WAAmB;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACtH,OAAO,EAAE,WAAW,EAAE,GAAG,GAAG,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;AACjE,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["/**\n * The width of the AI pane in the dashboard tab: the user setting that stores it, and the reads that turn\n * the setting and angular-split's sizes into widths the tab can use.\n */\n\n/** The UserInfoEngine setting that stores the AI pane width. */\nexport const STUDIO_PANE_SETTING_KEY = 'mj.dashboards.studio.layout';\n\n/** The smallest width of the AI pane, in percent of the tab's width. */\nexport const STUDIO_PANE_COPILOT_MIN_PCT = 20;\n\n/** The largest width of the AI pane, in percent of the tab's width. */\nexport const STUDIO_PANE_COPILOT_MAX_PCT = 60;\n\n/** The widths of the dashboard and the AI pane, in percent of the tab's width. They add up to 100. */\nexport interface StudioPanePrefs {\n /** The dashboard's width. */\n MainSizePct: number;\n /** The AI pane's width, a whole number from STUDIO_PANE_COPILOT_MIN_PCT to STUDIO_PANE_COPILOT_MAX_PCT. */\n CopilotSizePct: number;\n}\n\n/** The widths the AI pane opens with when no width is saved. */\nexport const STUDIO_PANE_DEFAULTS: Readonly<StudioPanePrefs> = { MainSizePct: 68, CopilotSizePct: 32 };\n\n/**\n * The widths in the saved setting, or the defaults when the setting is missing or holds no number for the\n * AI pane. The AI pane width is rounded and kept in its bounds; the dashboard gets the rest.\n */\nexport function ParseStudioPanePrefs(raw: string | null | undefined): StudioPanePrefs {\n const copilotSize = savedCopilotSize(raw);\n return copilotSize === null ? { ...STUDIO_PANE_DEFAULTS } : prefsForCopilotSize(copilotSize);\n}\n\n/**\n * The widths from the sizes of an angular-split dragEnd event, read as the AI pane width ParseStudioPanePrefs\n * would give, or null unless the event holds exactly two finite numbers.\n */\nexport function PrefsFromSplitSizes(sizes: readonly (number | '*')[]): StudioPanePrefs | null {\n if (sizes.length !== 2) return null;\n const [mainSize, copilotSize] = sizes;\n if (!isFiniteNumber(mainSize) || !isFiniteNumber(copilotSize)) return null;\n return prefsForCopilotSize(copilotSize);\n}\n\n/** The AI pane width in the saved setting, or null when the setting is not JSON with a finite CopilotSizePct. */\nfunction savedCopilotSize(raw: string | null | undefined): number | null {\n if (!raw) return null;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== 'object' || parsed === null || !('CopilotSizePct' in parsed)) return null;\n return isFiniteNumber(parsed.CopilotSizePct) ? parsed.CopilotSizePct : null;\n } catch {\n return null;\n }\n}\n\n/** The widths for an AI pane width, rounded and kept in its bounds, with the rest for the dashboard. */\nfunction prefsForCopilotSize(copilotSize: number): StudioPanePrefs {\n const copilot = Math.max(STUDIO_PANE_COPILOT_MIN_PCT, Math.min(STUDIO_PANE_COPILOT_MAX_PCT, Math.round(copilotSize)));\n return { MainSizePct: 100 - copilot, CopilotSizePct: copilot };\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n"]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Client tools that let an agent read and change the Config dashboard open in a
|
|
3
|
+
* dashboard tab: its state and a screenshot of it, its panels and layout, the sources a panel can show,
|
|
4
|
+
* and requests to the user to save it or pin it to Home. Pure functions over {@link DashboardStudioHost}:
|
|
5
|
+
* the tab supplies the state, applies the edits, searches the sources and asks the user.
|
|
6
|
+
*
|
|
7
|
+
* 🔒 BOUNDARY: the edit tools change the open dashboard in memory only and never save it. The Request*
|
|
8
|
+
* tools never save or pin: they ask the user in a confirm dialog, and the tab does what the user confirms.
|
|
9
|
+
* The edit and Request* tools act only when their `dashboardId` is the open dashboard's id. Tool handlers
|
|
10
|
+
* never throw: a bad parameter, a refused edit or a failed host call returns `{ Success: false, ErrorMessage }`.
|
|
11
|
+
*/
|
|
12
|
+
import type { ResolvedLayoutConfig } from 'golden-layout';
|
|
13
|
+
import type { MJDashboardPartTypeEntity } from '@memberjunction/core-entities';
|
|
14
|
+
import { type DashboardConfig, type PanelConfig, type PanelPosition } from '@memberjunction/ng-dashboard-viewer';
|
|
15
|
+
import type { ElementCapture } from '@memberjunction/ng-shared';
|
|
16
|
+
import { type DashboardTabAgentTool } from './dashboard-tab-agent';
|
|
17
|
+
import { type SourceKind, type SourceSearchResult } from './dashboard-source-search';
|
|
18
|
+
/**
|
|
19
|
+
* The reads and edits the studio tools make on the dashboard tab, and the requests they put to the user.
|
|
20
|
+
* The tab implements it.
|
|
21
|
+
*
|
|
22
|
+
* How the tools use it, and what they need from it:
|
|
23
|
+
* - The tools make at most one edit call at a time, unless an edit call does not settle within
|
|
24
|
+
* DASHBOARD_STUDIO_EDIT_TIMEOUT_MS; then the next edit starts while the late call may still run and
|
|
25
|
+
* overwrite it. The edit tools from one BuildDashboardStudioTools call share a queue: each reads the
|
|
26
|
+
* dashboard, checks its call and awaits its one edit call (AddPanel, RemovePanel, UpdatePanelConfig or
|
|
27
|
+
* ApplyLayout) only after the previous edit tool has finished. The next edit is checked against
|
|
28
|
+
* GetConfig(), so an edit call resolves only once GetConfig() shows its change.
|
|
29
|
+
* - An edit call must settle within DASHBOARD_STUDIO_EDIT_TIMEOUT_MS (30 seconds). When it does not, the tool
|
|
30
|
+
* tells the agent that the edit did not finish in time, and the next edit starts.
|
|
31
|
+
* - The tools that do not edit (the reads, the screenshot, the requests and the search) start after the
|
|
32
|
+
* edits queued before them have finished or timed out.
|
|
33
|
+
* - An edit that cannot be applied rejects with an Error that says why; it never drops a change
|
|
34
|
+
* silently. The tools return the rejection to the agent as a failed result with that message.
|
|
35
|
+
* - The tools never save or pin. Confirm asks the user, and the tab does what the user confirms.
|
|
36
|
+
*/
|
|
37
|
+
export interface DashboardStudioHost {
|
|
38
|
+
/** The Config dashboard open in the tab, or null when none is loaded. */
|
|
39
|
+
Dashboard(): {
|
|
40
|
+
ID: string;
|
|
41
|
+
Name: string;
|
|
42
|
+
Description: string | null;
|
|
43
|
+
} | null;
|
|
44
|
+
/** The dashboard configuration as the tab shows it now, with every panel in its layout. Null before it loads. */
|
|
45
|
+
GetConfig(): DashboardConfig | null;
|
|
46
|
+
/** The part types the dashboard can show. */
|
|
47
|
+
GetPartTypes(): readonly Pick<MJDashboardPartTypeEntity, 'ID' | 'Name' | 'Icon'>[];
|
|
48
|
+
/** True while the tab is in edit mode. */
|
|
49
|
+
IsEditing(): boolean;
|
|
50
|
+
/** True when the user may edit the dashboard. */
|
|
51
|
+
CanEdit(): boolean;
|
|
52
|
+
/** True when the dashboard has changes that are not saved. */
|
|
53
|
+
HasUnsavedChanges(): boolean;
|
|
54
|
+
/** True while a Save runs. */
|
|
55
|
+
IsSaving(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Puts the tab in edit mode when the user can edit. Returns whether the tab is editing afterwards.
|
|
58
|
+
* Entering edit mode can reload the saved dashboard when it was saved elsewhere since it loaded.
|
|
59
|
+
*/
|
|
60
|
+
EnterEditMode(): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Adds a panel and resolves with its id, or null when the dashboard did not add it. With a position,
|
|
63
|
+
* the panel goes there; without one, it joins the first tab stack.
|
|
64
|
+
*/
|
|
65
|
+
AddPanel(partTypeId: string, config: PanelConfig, title: string, icon: string | undefined, position: PanelPosition | undefined): Promise<string | null>;
|
|
66
|
+
/** Removes a panel. */
|
|
67
|
+
RemovePanel(panelId: string): Promise<void>;
|
|
68
|
+
/** Gives a panel a new config, and a new title and icon when they are given. */
|
|
69
|
+
UpdatePanelConfig(panelId: string, config: PanelConfig, title?: string, icon?: string): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Shows a layout built with the layout editor functions and marks the dashboard changed. Resolves only
|
|
72
|
+
* after GetConfig() returns the new layout; rejects when the rebuild fails.
|
|
73
|
+
*/
|
|
74
|
+
ApplyLayout(layout: ResolvedLayoutConfig): Promise<void>;
|
|
75
|
+
/** The panel's address in the layout, for example `row/0 › column/1 › tab 0`, or null when it is not in the layout. */
|
|
76
|
+
GetPanelPath(panelId: string): string | null;
|
|
77
|
+
/**
|
|
78
|
+
* A JPEG of the dashboard as the tab shows it, at most `maxWidth` pixels wide. Rejects with an Error that
|
|
79
|
+
* says why when the capture fails or takes too long.
|
|
80
|
+
*/
|
|
81
|
+
CaptureScreenshot(maxWidth: number): Promise<ElementCapture>;
|
|
82
|
+
/**
|
|
83
|
+
* The box of each panel the tab shows, in CSS pixels relative to the top left corner of the element that
|
|
84
|
+
* CaptureScreenshot captures. A panel that is not shown, such as one in a hidden tab, is left out.
|
|
85
|
+
*/
|
|
86
|
+
PanelBounds(): Array<{
|
|
87
|
+
panelId: string;
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
width: number;
|
|
91
|
+
height: number;
|
|
92
|
+
}>;
|
|
93
|
+
/** True while a voice session runs. */
|
|
94
|
+
IsVoiceSessionActive(): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Sends an image to the running voice session as a video frame. `base64` has no data URL prefix. Returns
|
|
97
|
+
* true when the voice session took the frame, and false when it did not.
|
|
98
|
+
*/
|
|
99
|
+
SendVoiceFrame(base64: string, mimeType: string): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Opens a confirm dialog and resolves with the user's answer. `kind` picks the text, and `detail` gives the
|
|
102
|
+
* name and description a save would apply. When the user confirms, the tab does what was asked as the
|
|
103
|
+
* user's own action and then resolves true. Rejects with an Error that says why when it cannot ask, for
|
|
104
|
+
* example while another request waits for an answer, or when the confirmed action fails.
|
|
105
|
+
*/
|
|
106
|
+
Confirm(kind: 'save' | 'pin', detail: {
|
|
107
|
+
name?: string;
|
|
108
|
+
description?: string;
|
|
109
|
+
}): Promise<boolean>;
|
|
110
|
+
/**
|
|
111
|
+
* The sources the user may show in a panel that match `query`: up to `limit` of each kind in `kinds`, in
|
|
112
|
+
* SOURCE_KINDS order, best match first. The user's access rules apply: artifacts the user can read, the
|
|
113
|
+
* user's own and shared views, queries the user can run, and entities the user can read. Rejects with an
|
|
114
|
+
* Error that says why when a list cannot be read.
|
|
115
|
+
*/
|
|
116
|
+
SearchSources(query: string, kinds: readonly SourceKind[], limit: number): Promise<SourceSearchResult[]>;
|
|
117
|
+
}
|
|
118
|
+
/** How long, in milliseconds, the edit queue waits for one edit before it reports that the edit did not finish and starts the next edit. */
|
|
119
|
+
export declare const DASHBOARD_STUDIO_EDIT_TIMEOUT_MS = 30000;
|
|
120
|
+
/** What a panel shows, read from its config: the kind of source, and its id or name when the config has them. */
|
|
121
|
+
export declare function DescribePanelSource(config: PanelConfig): {
|
|
122
|
+
kind: string;
|
|
123
|
+
id: string | null;
|
|
124
|
+
name: string | null;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* The studio tools: GetDashboardState reads the open dashboard; AddPanel, RemovePanel, MovePanel,
|
|
128
|
+
* ResizePanel and UpdatePanelSettings change its panels and layout in memory; GetDashboardScreenshot
|
|
129
|
+
* captures it; RequestSaveDashboard and RequestPinToHome ask the user to save it or pin it to Home; and
|
|
130
|
+
* SearchSources finds the sources a panel can show. The tools of one call share a queue: it runs their
|
|
131
|
+
* edits one at a time, and the other tools start after the edits queued before them. So a tab registers
|
|
132
|
+
* one set of tools and keeps it.
|
|
133
|
+
*/
|
|
134
|
+
export declare function BuildDashboardStudioTools(host: DashboardStudioHost): DashboardTabAgentTool[];
|
|
135
|
+
//# sourceMappingURL=dashboard-studio-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-studio-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/dashboard-studio-tools.ts"],"names":[],"mappings":"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"}
|