@xpert-ai/plugin-live-dashboard 0.4.1 → 0.5.0
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/.xpertai-plugin/plugin.json +1 -1
- package/README.md +4 -0
- package/dist/lib/agent.schema.d.ts +179 -25
- package/dist/lib/agent.schema.js +10 -9
- package/dist/lib/archive.service.d.ts +145 -0
- package/dist/lib/archive.service.js +133 -0
- package/dist/lib/content.provider.d.ts +1 -1
- package/dist/lib/dashboard-archive.d.ts +70 -0
- package/dist/lib/dashboard-archive.js +118 -0
- package/dist/lib/dashboard-sources.d.ts +69 -0
- package/dist/lib/dashboard-sources.js +37 -0
- package/dist/lib/dashboard-view.schema.d.ts +422 -88
- package/dist/lib/dashboard.schema.d.ts +379 -58
- package/dist/lib/dashboard.schema.js +18 -1
- package/dist/lib/dashboard.service.d.ts +60 -14
- package/dist/lib/dashboard.service.js +8 -2
- package/dist/lib/document-package.d.ts +19 -4
- package/dist/lib/editing-patch.d.ts +3 -0
- package/dist/lib/editing-patch.js +2 -1
- package/dist/lib/editing-session.d.ts +4 -4
- package/dist/lib/editing.d.ts +202 -19
- package/dist/lib/editing.js +5 -2
- package/dist/lib/html-validation-feedback.d.ts +7 -0
- package/dist/lib/html-validation-feedback.js +19 -0
- package/dist/lib/html-validation.js +2 -1
- package/dist/lib/inspection-host.d.ts +7 -0
- package/dist/lib/inspection-host.js +48 -0
- package/dist/lib/inspection-runtime.d.ts +2 -0
- package/dist/lib/inspection-runtime.js +77 -0
- package/dist/lib/json-input.d.ts +4 -0
- package/dist/lib/json-input.js +21 -0
- package/dist/lib/middleware.js +3 -2
- package/dist/lib/plugin.js +2 -1
- package/dist/lib/presentation.provider.d.ts +24 -9
- package/dist/lib/presentation.provider.js +2 -1
- package/dist/lib/source-executions.d.ts +196 -0
- package/dist/lib/source-executions.js +25 -0
- package/dist/lib/source-validation.d.ts +2 -0
- package/dist/lib/source-validation.js +21 -0
- package/dist/lib/view.provider.d.ts +178 -8
- package/dist/lib/view.provider.js +30 -4
- package/dist/remote/app.css +1 -1
- package/dist/remote/app.js +100 -27
- package/dist/remote/build-manifest.json +37 -23
- package/docs/docs.json +3 -1
- package/docs/sources-inspect-portability-acceptance.mdx +67 -0
- package/docs/sources-inspect-portability.mdx +115 -0
- package/package.json +6 -5
- package/skills/live-dashboard/SKILL.md +5 -4
- package/skills/live-dashboard/references/source-inspection.md +17 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { DashboardProjectsService } from './projects.service';
|
|
2
|
-
import type { XpertExtensionViewManifest, XpertResolvedViewHostContext, XpertViewActionRequest, XpertViewQuery } from '@xpert-ai/contracts';
|
|
3
|
-
import { type IXpertViewExtensionProvider } from '@xpert-ai/plugin-sdk';
|
|
2
|
+
import type { XpertExtensionViewManifest, XpertResolvedViewHostContext, XpertViewActionRequest, XpertViewQuery, XpertViewFileAccessRequest } from '@xpert-ai/contracts';
|
|
3
|
+
import { type IXpertViewExtensionProvider, type XpertViewFileActionFile } from '@xpert-ai/plugin-sdk';
|
|
4
4
|
import { DashboardService } from './dashboard.service';
|
|
5
5
|
import { DashboardSharingService } from './sharing.service';
|
|
6
|
+
import { DashboardArchiveService } from './archive.service';
|
|
6
7
|
export declare const VIEW_KEY = "live-dashboard";
|
|
7
8
|
export declare const VIEW_PROVIDER = "live-dashboard";
|
|
8
9
|
export declare const FEATURE = "live_dashboard";
|
|
@@ -10,7 +11,8 @@ export declare class DashboardViewProvider implements IXpertViewExtensionProvide
|
|
|
10
11
|
private readonly service;
|
|
11
12
|
private readonly sharing;
|
|
12
13
|
private readonly projects;
|
|
13
|
-
|
|
14
|
+
private readonly archives;
|
|
15
|
+
constructor(service: DashboardService, sharing: DashboardSharingService, projects: DashboardProjectsService, archives: DashboardArchiveService);
|
|
14
16
|
supports(context: XpertResolvedViewHostContext): boolean;
|
|
15
17
|
getViewManifests(context: XpertResolvedViewHostContext, slot: string): XpertExtensionViewManifest[];
|
|
16
18
|
getRemoteComponentEntry(): Promise<{
|
|
@@ -57,9 +59,9 @@ export declare class DashboardViewProvider implements IXpertViewExtensionProvide
|
|
|
57
59
|
} | {
|
|
58
60
|
saved: {
|
|
59
61
|
manifest: {
|
|
60
|
-
schema: "xpert.live-dashboard";
|
|
61
|
-
id: string;
|
|
62
62
|
title: string;
|
|
63
|
+
id: string;
|
|
64
|
+
schema: "xpert.live-dashboard";
|
|
63
65
|
bindings: import("@xpert-ai/contracts").AnalyticsBinding[];
|
|
64
66
|
controls: {
|
|
65
67
|
type: "string" | "number" | "boolean" | "date";
|
|
@@ -69,20 +71,35 @@ export declare class DashboardViewProvider implements IXpertViewExtensionProvide
|
|
|
69
71
|
allowedValues?: (string | number | boolean | null)[] | undefined;
|
|
70
72
|
}[];
|
|
71
73
|
charts: {
|
|
74
|
+
title: string;
|
|
72
75
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
73
76
|
id: string;
|
|
74
|
-
title: string;
|
|
75
77
|
datasetId: string;
|
|
76
78
|
x: string;
|
|
77
79
|
y: string;
|
|
78
80
|
color?: string | undefined;
|
|
79
81
|
}[];
|
|
80
82
|
tables: {
|
|
81
|
-
id: string;
|
|
82
83
|
title: string;
|
|
84
|
+
id: string;
|
|
83
85
|
datasetId: string;
|
|
84
86
|
fields: string[];
|
|
85
87
|
}[];
|
|
88
|
+
sourceMetadata?: {
|
|
89
|
+
bindingId: string;
|
|
90
|
+
title: string;
|
|
91
|
+
description?: string | undefined;
|
|
92
|
+
}[] | undefined;
|
|
93
|
+
components?: {
|
|
94
|
+
title: string;
|
|
95
|
+
id: string;
|
|
96
|
+
elementId: string;
|
|
97
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
98
|
+
sources: {
|
|
99
|
+
bindingId: string;
|
|
100
|
+
fieldIds?: string[] | undefined;
|
|
101
|
+
}[];
|
|
102
|
+
}[] | undefined;
|
|
86
103
|
presentation?: {
|
|
87
104
|
type: "html";
|
|
88
105
|
html: string;
|
|
@@ -100,7 +117,7 @@ export declare class DashboardViewProvider implements IXpertViewExtensionProvide
|
|
|
100
117
|
artifactId: string;
|
|
101
118
|
versionId: string | null | undefined;
|
|
102
119
|
versionNumber: number | undefined;
|
|
103
|
-
};
|
|
120
|
+
} | undefined;
|
|
104
121
|
versions: {
|
|
105
122
|
current: boolean;
|
|
106
123
|
artifactId: string;
|
|
@@ -181,6 +198,16 @@ export declare class DashboardViewProvider implements IXpertViewExtensionProvide
|
|
|
181
198
|
};
|
|
182
199
|
}>;
|
|
183
200
|
executeViewAction(context: XpertResolvedViewHostContext, viewKey: string, action: string, request: XpertViewActionRequest): Promise<{
|
|
201
|
+
success: boolean;
|
|
202
|
+
data: import("@xpert-ai/contracts").AnalyticsDiscoveryResult;
|
|
203
|
+
refresh: boolean;
|
|
204
|
+
} | {
|
|
205
|
+
success: boolean;
|
|
206
|
+
data: {
|
|
207
|
+
discarded: boolean;
|
|
208
|
+
};
|
|
209
|
+
refresh: boolean;
|
|
210
|
+
} | {
|
|
184
211
|
success: boolean;
|
|
185
212
|
data: {
|
|
186
213
|
canEdit: boolean;
|
|
@@ -239,9 +266,152 @@ export declare class DashboardViewProvider implements IXpertViewExtensionProvide
|
|
|
239
266
|
artifactId: string;
|
|
240
267
|
};
|
|
241
268
|
refresh: boolean;
|
|
269
|
+
} | {
|
|
270
|
+
success: boolean;
|
|
271
|
+
data: {
|
|
272
|
+
payload?: {
|
|
273
|
+
ok: boolean;
|
|
274
|
+
widget_type: string;
|
|
275
|
+
surface: string;
|
|
276
|
+
sources: never[];
|
|
277
|
+
manifest: {
|
|
278
|
+
version: number;
|
|
279
|
+
surface: string;
|
|
280
|
+
title: string;
|
|
281
|
+
cards: never[];
|
|
282
|
+
filters: never[];
|
|
283
|
+
sources: never[];
|
|
284
|
+
charts: {
|
|
285
|
+
id: string;
|
|
286
|
+
title: string;
|
|
287
|
+
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
288
|
+
dataset: string;
|
|
289
|
+
encodings: {
|
|
290
|
+
color?: {
|
|
291
|
+
field: string;
|
|
292
|
+
} | undefined;
|
|
293
|
+
x: {
|
|
294
|
+
field: string;
|
|
295
|
+
};
|
|
296
|
+
y: {
|
|
297
|
+
field: string;
|
|
298
|
+
};
|
|
299
|
+
};
|
|
300
|
+
}[];
|
|
301
|
+
tables: {
|
|
302
|
+
id: string;
|
|
303
|
+
title: string;
|
|
304
|
+
dataset: string;
|
|
305
|
+
columns: {
|
|
306
|
+
field: string;
|
|
307
|
+
label: string;
|
|
308
|
+
}[];
|
|
309
|
+
}[];
|
|
310
|
+
blocks: ({
|
|
311
|
+
id: string;
|
|
312
|
+
type: string;
|
|
313
|
+
chartId: string;
|
|
314
|
+
} | {
|
|
315
|
+
id: string;
|
|
316
|
+
type: string;
|
|
317
|
+
tableId: string;
|
|
318
|
+
})[];
|
|
319
|
+
};
|
|
320
|
+
snapshot: {
|
|
321
|
+
version: number;
|
|
322
|
+
generatedAt: string;
|
|
323
|
+
status: string;
|
|
324
|
+
datasets: any;
|
|
325
|
+
};
|
|
326
|
+
} | undefined;
|
|
327
|
+
datasets: import("@xpert-ai/contracts").AnalyticalDataset[];
|
|
328
|
+
failures: {
|
|
329
|
+
bindingId: string;
|
|
330
|
+
datasetId: string;
|
|
331
|
+
reason: "unavailable";
|
|
332
|
+
}[];
|
|
333
|
+
};
|
|
334
|
+
refresh: boolean;
|
|
242
335
|
} | {
|
|
243
336
|
success: boolean;
|
|
244
337
|
data: import("@xpert-ai/contracts").AnalyticalDataset;
|
|
245
338
|
refresh: boolean;
|
|
246
339
|
}>;
|
|
340
|
+
executeViewFileAction(context: XpertResolvedViewHostContext, viewKey: string, action: string, _request: XpertViewActionRequest, file: XpertViewFileActionFile): Promise<{
|
|
341
|
+
success: boolean;
|
|
342
|
+
data: {
|
|
343
|
+
importId: `${string}-${string}-${string}-${string}-${string}`;
|
|
344
|
+
manifest: {
|
|
345
|
+
title: string;
|
|
346
|
+
id: string;
|
|
347
|
+
schema: "xpert.live-dashboard";
|
|
348
|
+
bindings: import("@xpert-ai/contracts").AnalyticsBinding[];
|
|
349
|
+
controls: {
|
|
350
|
+
type: "string" | "number" | "boolean" | "date";
|
|
351
|
+
controlId: string;
|
|
352
|
+
label: string;
|
|
353
|
+
defaultValue?: string | number | boolean | null | undefined;
|
|
354
|
+
allowedValues?: (string | number | boolean | null)[] | undefined;
|
|
355
|
+
}[];
|
|
356
|
+
charts: {
|
|
357
|
+
title: string;
|
|
358
|
+
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
359
|
+
id: string;
|
|
360
|
+
datasetId: string;
|
|
361
|
+
x: string;
|
|
362
|
+
y: string;
|
|
363
|
+
color?: string | undefined;
|
|
364
|
+
}[];
|
|
365
|
+
tables: {
|
|
366
|
+
title: string;
|
|
367
|
+
id: string;
|
|
368
|
+
datasetId: string;
|
|
369
|
+
fields: string[];
|
|
370
|
+
}[];
|
|
371
|
+
sourceMetadata?: {
|
|
372
|
+
bindingId: string;
|
|
373
|
+
title: string;
|
|
374
|
+
description?: string | undefined;
|
|
375
|
+
}[] | undefined;
|
|
376
|
+
components?: {
|
|
377
|
+
title: string;
|
|
378
|
+
id: string;
|
|
379
|
+
elementId: string;
|
|
380
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
381
|
+
sources: {
|
|
382
|
+
bindingId: string;
|
|
383
|
+
fieldIds?: string[] | undefined;
|
|
384
|
+
}[];
|
|
385
|
+
}[] | undefined;
|
|
386
|
+
presentation?: {
|
|
387
|
+
type: "html";
|
|
388
|
+
html: string;
|
|
389
|
+
dependencies?: import("@xpert-ai/plugin-sdk/artifact-document").ArtifactDocumentDependencyLock[] | undefined;
|
|
390
|
+
} | undefined;
|
|
391
|
+
};
|
|
392
|
+
requirements: {
|
|
393
|
+
schema: string;
|
|
394
|
+
version: number;
|
|
395
|
+
bindings: {
|
|
396
|
+
id: string;
|
|
397
|
+
providerId: string;
|
|
398
|
+
operation: string;
|
|
399
|
+
contractVersion: number;
|
|
400
|
+
source: import("@xpert-ai/contracts").AnalyticsSourceRef;
|
|
401
|
+
}[];
|
|
402
|
+
externalResources: string[];
|
|
403
|
+
dynamicResourcesMayExist: boolean;
|
|
404
|
+
includesQueryResults: boolean;
|
|
405
|
+
requiresAuthorizedHost: boolean;
|
|
406
|
+
};
|
|
407
|
+
sources: import("@xpert-ai/contracts").AnalyticsSourceSummary[];
|
|
408
|
+
};
|
|
409
|
+
refresh: boolean;
|
|
410
|
+
}>;
|
|
411
|
+
resolveViewFile(context: XpertResolvedViewHostContext, viewKey: string, request: XpertViewFileAccessRequest): Promise<{
|
|
412
|
+
reference: import("@xpert-ai/plugin-sdk").WorkspacePortableFileReference;
|
|
413
|
+
fileName: string;
|
|
414
|
+
mimeType: string;
|
|
415
|
+
size: number;
|
|
416
|
+
}>;
|
|
247
417
|
}
|
|
@@ -24,15 +24,18 @@ const dashboard_receipt_1 = require("./dashboard-receipt");
|
|
|
24
24
|
const dashboard_navigation_1 = require("./dashboard-navigation");
|
|
25
25
|
const project_1 = require("./project");
|
|
26
26
|
const dashboard_icon_1 = require("./dashboard-icon");
|
|
27
|
+
const dashboard_sources_1 = require("./dashboard-sources");
|
|
28
|
+
const archive_service_1 = require("./archive.service");
|
|
27
29
|
exports.VIEW_KEY = 'live-dashboard';
|
|
28
30
|
exports.VIEW_PROVIDER = 'live-dashboard';
|
|
29
31
|
exports.FEATURE = 'live_dashboard';
|
|
30
32
|
const text = (en_US, zh_Hans) => ({ en_US, zh_Hans });
|
|
31
33
|
let DashboardViewProvider = class DashboardViewProvider {
|
|
32
|
-
constructor(service, sharing, projects) {
|
|
34
|
+
constructor(service, sharing, projects, archives) {
|
|
33
35
|
this.service = service;
|
|
34
36
|
this.sharing = sharing;
|
|
35
37
|
this.projects = projects;
|
|
38
|
+
this.archives = archives;
|
|
36
39
|
}
|
|
37
40
|
supports(context) { return context.hostType === 'agent'; }
|
|
38
41
|
getViewManifests(context, slot) {
|
|
@@ -44,6 +47,7 @@ let DashboardViewProvider = class DashboardViewProvider {
|
|
|
44
47
|
workbench: { projectType: project_1.DASHBOARD_PROJECT_TYPE, fixed: true, openMode: 'on-demand', menu: { enabled: true, label: text('Live dashboards', '实时看板'), icon: dashboard_icon_1.dashboardIcon, order: 35 } },
|
|
45
48
|
view: { type: 'remote_component', runtime: 'react', protocolVersion: 1, component: { isolation: 'iframe', entry: exports.VIEW_KEY }, dataSource: { mode: 'platform' } },
|
|
46
49
|
dataSource: { mode: 'platform', querySchema: { supportsSelection: true, supportsParameters: true, supportsPagination: true, defaultPageSize: 50 }, cache: { enabled: false } },
|
|
50
|
+
fileAccess: { purposes: ['download'] },
|
|
47
51
|
clientCommands: [{ key: 'workbench.content.status' }, { key: 'workbench.content.resolve' }, { key: contracts_1.ASSISTANT_CONTEXT_SET_COMMAND, label: text('Select dashboard for Assistant', '设置助理当前看板') },
|
|
48
52
|
{ key: contracts_1.ASSISTANT_CHAT_SEND_MESSAGE_COMMAND, label: text('Create with Assistant', '交给助理制作') },
|
|
49
53
|
{ key: contracts_1.ARTIFACT_PRESENTATION_OPEN_COMMAND, label: text('Open shared page', '打开独立页面') },
|
|
@@ -51,6 +55,8 @@ let DashboardViewProvider = class DashboardViewProvider {
|
|
|
51
55
|
hostEvents: { subscriptions: [{ key: 'dashboard-created', event: 'assistant.tool.completed',
|
|
52
56
|
filter: { toolNames: dashboard_receipt_1.DASHBOARD_MUTATION_TOOLS }, action: { type: 'forward', debounceMs: 0 } }] },
|
|
53
57
|
actions: [
|
|
58
|
+
{ key: 'import-preview', label: text('Import dashboard file', '导入看板文件'), actionType: 'invoke', transport: 'file' },
|
|
59
|
+
...['import-commit', 'import-discard', 'import-browse'].map(key => ({ key, label: text('Import dashboard', '导入看板'), actionType: 'invoke' })),
|
|
54
60
|
...[
|
|
55
61
|
{ key: 'dashboards', label: text('Select dashboard', '选择看板') },
|
|
56
62
|
{ key: 'projects', label: text('Select project', '选择项目') },
|
|
@@ -80,15 +86,22 @@ let DashboardViewProvider = class DashboardViewProvider {
|
|
|
80
86
|
: undefined;
|
|
81
87
|
const versions = params.artifactId ? await this.service.history(context, params.artifactId) : undefined;
|
|
82
88
|
const unavailable = params.artifactId && mode === 'published' && !params.versionId && !versions?.some(version => version.current);
|
|
89
|
+
const saved = !unavailable && params.artifactId ? await this.service.openDocument(context, params.artifactId, params.versionId, params.draftRevision, mode) : undefined;
|
|
83
90
|
return { meta: { navigationTarget: (0, dashboard_navigation_1.dashboardNavigationTarget)(context), access, mode, currentProject,
|
|
84
91
|
dashboards: page.items, selectedDashboard, pagination: { page: page.page, pageSize: page.pageSize, hasMore: page.hasMore },
|
|
85
92
|
sources: access.canEdit ? await this.service.sources(context) : [],
|
|
86
93
|
...(unavailable ? { notice: 'not_published' } : params.artifactId ? {
|
|
87
|
-
saved:
|
|
94
|
+
saved: saved && { ...saved, manifest: access.canEdit ? saved.manifest : (0, dashboard_sources_1.publicDashboardManifest)(saved.manifest) }, versions
|
|
88
95
|
} : {}) } };
|
|
89
96
|
}
|
|
90
97
|
async executeViewAction(context, viewKey, action, request) {
|
|
91
98
|
assertView(viewKey);
|
|
99
|
+
if (action === 'import-commit')
|
|
100
|
+
return { success: true, data: await this.archives.commit(context, archive_service_1.importInputSchema.parse(request.input)), refresh: false };
|
|
101
|
+
if (action === 'import-browse')
|
|
102
|
+
return { success: true, data: await this.archives.browse(context, archive_service_1.importBrowseSchema.parse(request.input)), refresh: false };
|
|
103
|
+
if (action === 'import-discard')
|
|
104
|
+
return { success: true, data: await this.archives.discard(context, v3_1.z.object({ importId: v3_1.z.string().uuid() }).strict().parse(request.input).importId), refresh: false };
|
|
92
105
|
if (action === 'dashboards') {
|
|
93
106
|
const parsed = projects_schema_1.dashboardSearchSchema.safeParse(request.input);
|
|
94
107
|
if (!parsed.success)
|
|
@@ -128,7 +141,8 @@ let DashboardViewProvider = class DashboardViewProvider {
|
|
|
128
141
|
}
|
|
129
142
|
if (action === 'query') {
|
|
130
143
|
const input = dashboard_schema_1.querySchema.parse(request.input);
|
|
131
|
-
|
|
144
|
+
const result = await this.service.query(context, input.artifactId, input.versionId, input.controls, input.draftRevision);
|
|
145
|
+
return { success: true, data: { datasets: result.datasets, failures: result.failures, ...('payload' in result ? { payload: result.payload } : {}) }, refresh: false };
|
|
132
146
|
}
|
|
133
147
|
if (action === 'query-binding') {
|
|
134
148
|
const parsed = dashboard_schema_1.queryBindingSchema.safeParse(request.input);
|
|
@@ -139,11 +153,23 @@ let DashboardViewProvider = class DashboardViewProvider {
|
|
|
139
153
|
}
|
|
140
154
|
throw new common_1.BadRequestException('DASHBOARD_ACTION_UNSUPPORTED');
|
|
141
155
|
}
|
|
156
|
+
async executeViewFileAction(context, viewKey, action, _request, file) {
|
|
157
|
+
assertView(viewKey);
|
|
158
|
+
if (action !== 'import-preview')
|
|
159
|
+
throw new common_1.BadRequestException('DASHBOARD_ACTION_UNSUPPORTED');
|
|
160
|
+
return { success: true, data: await this.archives.prepare(context, file.buffer), refresh: false };
|
|
161
|
+
}
|
|
162
|
+
async resolveViewFile(context, viewKey, request) {
|
|
163
|
+
assertView(viewKey);
|
|
164
|
+
if (request.purpose !== 'download')
|
|
165
|
+
throw new common_1.ForbiddenException('DASHBOARD_ACTION_UNSUPPORTED');
|
|
166
|
+
return this.archives.exportFile(context, request.fileKey);
|
|
167
|
+
}
|
|
142
168
|
};
|
|
143
169
|
exports.DashboardViewProvider = DashboardViewProvider;
|
|
144
170
|
exports.DashboardViewProvider = DashboardViewProvider = __decorate([
|
|
145
171
|
(0, plugin_sdk_1.ViewExtensionProvider)(exports.VIEW_PROVIDER),
|
|
146
|
-
__metadata("design:paramtypes", [dashboard_service_1.DashboardService, sharing_service_1.DashboardSharingService, projects_service_1.DashboardProjectsService])
|
|
172
|
+
__metadata("design:paramtypes", [dashboard_service_1.DashboardService, sharing_service_1.DashboardSharingService, projects_service_1.DashboardProjectsService, archive_service_1.DashboardArchiveService])
|
|
147
173
|
], DashboardViewProvider);
|
|
148
174
|
function assertView(key) { if (key !== exports.VIEW_KEY)
|
|
149
175
|
throw new common_1.BadRequestException('DASHBOARD_VIEW_UNSUPPORTED'); }
|