@finos/legend-application-studio 28.21.42 → 28.21.44
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/lib/__lib__/LegendStudioEvent.d.ts +18 -4
- package/lib/__lib__/LegendStudioEvent.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioEvent.js +20 -5
- package/lib/__lib__/LegendStudioEvent.js.map +1 -1
- package/lib/__lib__/LegendStudioTelemetryHelper.d.ts +177 -31
- package/lib/__lib__/LegendStudioTelemetryHelper.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioTelemetryHelper.js +229 -72
- package/lib/__lib__/LegendStudioTelemetryHelper.js.map +1 -1
- package/lib/__lib__/LegendStudioUserDataHelper.d.ts +18 -1
- package/lib/__lib__/LegendStudioUserDataHelper.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioUserDataHelper.js +71 -0
- package/lib/__lib__/LegendStudioUserDataHelper.js.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.d.ts +12 -0
- package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.js +6 -0
- package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
- package/lib/components/LegendStudioWebApplication.d.ts.map +1 -1
- package/lib/components/LegendStudioWebApplication.js +5 -2
- package/lib/components/LegendStudioWebApplication.js.map +1 -1
- package/lib/components/ShowcaseManager.d.ts.map +1 -1
- package/lib/components/ShowcaseManager.js +6 -4
- package/lib/components/ShowcaseManager.js.map +1 -1
- package/lib/components/editor/ActivityBar.d.ts.map +1 -1
- package/lib/components/editor/ActivityBar.js +2 -1
- package/lib/components/editor/ActivityBar.js.map +1 -1
- package/lib/components/editor/editor-group/GrammarTextEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/GrammarTextEditor.js +7 -1
- package/lib/components/editor/editor-group/GrammarTextEditor.js.map +1 -1
- package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.d.ts +37 -0
- package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.d.ts.map +1 -0
- package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.js +126 -0
- package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.js.map +1 -0
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +22 -127
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.js +4 -4
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.js.map +1 -1
- package/lib/components/showcase/ShowcaseFeedback.d.ts +36 -0
- package/lib/components/showcase/ShowcaseFeedback.d.ts.map +1 -0
- package/lib/components/showcase/ShowcaseFeedback.js +70 -0
- package/lib/components/showcase/ShowcaseFeedback.js.map +1 -0
- package/lib/components/showcase/ShowcaseViewer.d.ts.map +1 -1
- package/lib/components/showcase/ShowcaseViewer.js +3 -1
- package/lib/components/showcase/ShowcaseViewer.js.map +1 -1
- package/lib/components/workspace-setup/WorkspaceSetup.d.ts.map +1 -1
- package/lib/components/workspace-setup/WorkspaceSetup.js +2 -1
- package/lib/components/workspace-setup/WorkspaceSetup.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/LegendStudioBaseStore.d.ts.map +1 -1
- package/lib/stores/LegendStudioBaseStore.js +1 -0
- package/lib/stores/LegendStudioBaseStore.js.map +1 -1
- package/lib/stores/ShowcaseManagerState.d.ts +5 -3
- package/lib/stores/ShowcaseManagerState.d.ts.map +1 -1
- package/lib/stores/ShowcaseManagerState.js +44 -11
- package/lib/stores/ShowcaseManagerState.js.map +1 -1
- package/lib/stores/editor/EditorGraphState.d.ts.map +1 -1
- package/lib/stores/editor/EditorGraphState.js +1 -1
- package/lib/stores/editor/EditorGraphState.js.map +1 -1
- package/lib/stores/editor/EditorStore.d.ts +2 -1
- package/lib/stores/editor/EditorStore.d.ts.map +1 -1
- package/lib/stores/editor/EditorStore.js +8 -2
- package/lib/stores/editor/EditorStore.js.map +1 -1
- package/lib/stores/editor/GraphEditFormModeState.d.ts.map +1 -1
- package/lib/stores/editor/GraphEditFormModeState.js +2 -2
- package/lib/stores/editor/GraphEditFormModeState.js.map +1 -1
- package/lib/stores/editor/GraphEditGrammarModeState.d.ts +19 -0
- package/lib/stores/editor/GraphEditGrammarModeState.d.ts.map +1 -1
- package/lib/stores/editor/GraphEditGrammarModeState.js +92 -4
- package/lib/stores/editor/GraphEditGrammarModeState.js.map +1 -1
- package/lib/stores/editor/GraphEditorMode.d.ts +1 -0
- package/lib/stores/editor/GraphEditorMode.d.ts.map +1 -1
- package/lib/stores/editor/GraphEditorMode.js.map +1 -1
- package/lib/stores/editor/StandardEditorMode.d.ts +16 -5
- package/lib/stores/editor/StandardEditorMode.d.ts.map +1 -1
- package/lib/stores/editor/StandardEditorMode.js +4 -2
- package/lib/stores/editor/StandardEditorMode.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +2 -14
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +5 -75
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts +0 -11
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js +2 -77
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js +4 -4
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js.map +1 -1
- package/lib/stores/editor/sidebar-state/LocalChangesState.d.ts +1 -0
- package/lib/stores/editor/sidebar-state/LocalChangesState.d.ts.map +1 -1
- package/lib/stores/editor/sidebar-state/LocalChangesState.js +27 -0
- package/lib/stores/editor/sidebar-state/LocalChangesState.js.map +1 -1
- package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.d.ts.map +1 -1
- package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.js +7 -0
- package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.js.map +1 -1
- package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.d.ts.map +1 -1
- package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js +7 -2
- package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js.map +1 -1
- package/lib/stores/lazy-text-editor/LazyTextEditorStore.d.ts +1 -0
- package/lib/stores/lazy-text-editor/LazyTextEditorStore.d.ts.map +1 -1
- package/lib/stores/lazy-text-editor/LazyTextEditorStore.js +3 -0
- package/lib/stores/lazy-text-editor/LazyTextEditorStore.js.map +1 -1
- package/lib/stores/project-reviewer/ProjectReviewerStore.d.ts.map +1 -1
- package/lib/stores/project-reviewer/ProjectReviewerStore.js +2 -0
- package/lib/stores/project-reviewer/ProjectReviewerStore.js.map +1 -1
- package/lib/stores/project-view/ProjectViewerEditorMode.d.ts +2 -2
- package/lib/stores/project-view/ProjectViewerEditorMode.d.ts.map +1 -1
- package/lib/stores/project-view/ProjectViewerEditorMode.js +12 -0
- package/lib/stores/project-view/ProjectViewerEditorMode.js.map +1 -1
- package/lib/stores/project-view/ProjectViewerStore.d.ts.map +1 -1
- package/lib/stores/project-view/ProjectViewerStore.js +3 -1
- package/lib/stores/project-view/ProjectViewerStore.js.map +1 -1
- package/lib/stores/showcase/ShowcaseViewerEditorMode.d.ts.map +1 -1
- package/lib/stores/showcase/ShowcaseViewerEditorMode.js.map +1 -1
- package/lib/stores/showcase/ShowcaseViewerStore.d.ts.map +1 -1
- package/lib/stores/showcase/ShowcaseViewerStore.js +7 -3
- package/lib/stores/showcase/ShowcaseViewerStore.js.map +1 -1
- package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts.map +1 -1
- package/lib/stores/workspace-setup/WorkspaceSetupStore.js +1 -0
- package/lib/stores/workspace-setup/WorkspaceSetupStore.js.map +1 -1
- package/package.json +16 -16
- package/src/__lib__/LegendStudioEvent.ts +22 -6
- package/src/__lib__/LegendStudioTelemetryHelper.ts +425 -104
- package/src/__lib__/LegendStudioUserDataHelper.ts +115 -0
- package/src/application/LegendStudioApplicationConfig.ts +19 -0
- package/src/components/LegendStudioWebApplication.tsx +18 -2
- package/src/components/ShowcaseManager.tsx +24 -4
- package/src/components/editor/ActivityBar.tsx +5 -1
- package/src/components/editor/editor-group/GrammarTextEditor.tsx +18 -1
- package/src/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.tsx +285 -0
- package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +38 -323
- package/src/components/editor/editor-group/service-editor/ServiceEditor.tsx +4 -0
- package/src/components/showcase/ShowcaseFeedback.tsx +136 -0
- package/src/components/showcase/ShowcaseViewer.tsx +10 -0
- package/src/components/workspace-setup/WorkspaceSetup.tsx +6 -1
- package/src/index.ts +2 -0
- package/src/stores/LegendStudioBaseStore.ts +1 -0
- package/src/stores/ShowcaseManagerState.ts +67 -8
- package/src/stores/editor/EditorGraphState.ts +1 -0
- package/src/stores/editor/EditorStore.ts +26 -4
- package/src/stores/editor/GraphEditFormModeState.ts +2 -0
- package/src/stores/editor/GraphEditGrammarModeState.ts +139 -1
- package/src/stores/editor/GraphEditorMode.ts +1 -0
- package/src/stores/editor/StandardEditorMode.ts +21 -7
- package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +3 -119
- package/src/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.ts +1 -136
- package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.ts +4 -0
- package/src/stores/editor/sidebar-state/LocalChangesState.ts +47 -0
- package/src/stores/editor/sidebar-state/WorkspaceUpdaterState.ts +18 -0
- package/src/stores/editor/sidebar-state/dev-metadata/DevMetadataState.ts +7 -0
- package/src/stores/lazy-text-editor/LazyTextEditorStore.ts +4 -0
- package/src/stores/project-reviewer/ProjectReviewerStore.ts +4 -0
- package/src/stores/project-view/ProjectViewerEditorMode.ts +17 -4
- package/src/stores/project-view/ProjectViewerStore.ts +5 -0
- package/src/stores/showcase/ShowcaseViewerEditorMode.ts +4 -5
- package/src/stores/showcase/ShowcaseViewerStore.ts +12 -2
- package/src/stores/workspace-setup/WorkspaceSetupStore.ts +2 -0
- package/tsconfig.json +2 -0
|
@@ -45,6 +45,11 @@ export enum LEGEND_STUDIO_USER_DATA_KEY {
|
|
|
45
45
|
// sandbox-tag project search on every mount. Revalidated against SDLC in
|
|
46
46
|
// the background; invalidated automatically on 404 or after the TTL.
|
|
47
47
|
WORKSPACE_SETUP_SANDBOX_INFO = 'studio-editor.workspace-setup.sandboxInfo',
|
|
48
|
+
// Per-browser cache of the user's showcase feedback votes (thumbs up /
|
|
49
|
+
// thumbs down). Purely a UX state store so the viewer can highlight the
|
|
50
|
+
// vote the user already cast; the source of truth for aggregate analysis
|
|
51
|
+
// is the `showcase.viewer.feedback.submit` telemetry event.
|
|
52
|
+
SHOWCASE_FEEDBACK_VOTES = 'studio-editor.showcase.feedback.votes',
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
// --- Workspace setup recents -------------------------------------------------
|
|
@@ -171,6 +176,86 @@ export class CachedSandboxInfo {
|
|
|
171
176
|
);
|
|
172
177
|
}
|
|
173
178
|
|
|
179
|
+
// --- Showcase feedback votes -------------------------------------------------
|
|
180
|
+
|
|
181
|
+
const SHOWCASE_FEEDBACK_VOTES_VERSION = 1;
|
|
182
|
+
// Cap the store so it can't grow without bound as users vote across many
|
|
183
|
+
// showcases. Older votes fall off first — this is purely a UX cache so
|
|
184
|
+
// losing very old entries just means the button state won't be pre-filled;
|
|
185
|
+
// the telemetry event is still the source of truth.
|
|
186
|
+
const MAX_SHOWCASE_FEEDBACK_VOTES = 200;
|
|
187
|
+
|
|
188
|
+
export class ShowcaseFeedbackVote {
|
|
189
|
+
showcasePath!: string;
|
|
190
|
+
vote!: 'up' | 'down';
|
|
191
|
+
votedAt!: number;
|
|
192
|
+
|
|
193
|
+
static readonly serialization = new SerializationFactory(
|
|
194
|
+
createModelSchema(ShowcaseFeedbackVote, {
|
|
195
|
+
showcasePath: primitive(),
|
|
196
|
+
// Stored as a plain string; validated on read.
|
|
197
|
+
vote: primitive(),
|
|
198
|
+
votedAt: primitive(),
|
|
199
|
+
}),
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export class ShowcaseFeedbackVotes {
|
|
204
|
+
version: number = SHOWCASE_FEEDBACK_VOTES_VERSION;
|
|
205
|
+
votes: ShowcaseFeedbackVote[] = [];
|
|
206
|
+
|
|
207
|
+
static readonly serialization = new SerializationFactory(
|
|
208
|
+
createModelSchema(ShowcaseFeedbackVotes, {
|
|
209
|
+
version: primitive(),
|
|
210
|
+
votes: list(usingModelSchema(ShowcaseFeedbackVote.serialization.schema)),
|
|
211
|
+
}),
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const isValidShowcaseVote = (v: unknown): v is 'up' | 'down' =>
|
|
216
|
+
v === 'up' || v === 'down';
|
|
217
|
+
|
|
218
|
+
const emptyShowcaseFeedbackVotes = (): ShowcaseFeedbackVotes =>
|
|
219
|
+
new ShowcaseFeedbackVotes();
|
|
220
|
+
|
|
221
|
+
const readShowcaseFeedbackVotes = (
|
|
222
|
+
service: UserDataService,
|
|
223
|
+
): ShowcaseFeedbackVotes => {
|
|
224
|
+
const raw = returnUndefOnError(() =>
|
|
225
|
+
service.getObjectValue(LEGEND_STUDIO_USER_DATA_KEY.SHOWCASE_FEEDBACK_VOTES),
|
|
226
|
+
);
|
|
227
|
+
if (!raw) {
|
|
228
|
+
return emptyShowcaseFeedbackVotes();
|
|
229
|
+
}
|
|
230
|
+
const parsed = returnUndefOnError(() =>
|
|
231
|
+
ShowcaseFeedbackVotes.serialization.fromJson(
|
|
232
|
+
raw as PlainObject<ShowcaseFeedbackVotes>,
|
|
233
|
+
),
|
|
234
|
+
);
|
|
235
|
+
if (!parsed) {
|
|
236
|
+
return emptyShowcaseFeedbackVotes();
|
|
237
|
+
}
|
|
238
|
+
// Reset the store on any future schema-version bump; old entries were
|
|
239
|
+
// written under a different shape and can't be trusted.
|
|
240
|
+
if (parsed.version !== SHOWCASE_FEEDBACK_VOTES_VERSION) {
|
|
241
|
+
return emptyShowcaseFeedbackVotes();
|
|
242
|
+
}
|
|
243
|
+
parsed.votes = parsed.votes
|
|
244
|
+
.filter((v) => isValidShowcaseVote(v.vote))
|
|
245
|
+
.slice(0, MAX_SHOWCASE_FEEDBACK_VOTES);
|
|
246
|
+
return parsed;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const writeShowcaseFeedbackVotes = (
|
|
250
|
+
service: UserDataService,
|
|
251
|
+
store: ShowcaseFeedbackVotes,
|
|
252
|
+
): void => {
|
|
253
|
+
service.persistValue(
|
|
254
|
+
LEGEND_STUDIO_USER_DATA_KEY.SHOWCASE_FEEDBACK_VOTES,
|
|
255
|
+
ShowcaseFeedbackVotes.serialization.toJson(store),
|
|
256
|
+
);
|
|
257
|
+
};
|
|
258
|
+
|
|
174
259
|
export class LegendStudioUserDataHelper {
|
|
175
260
|
static globalTestRunner_getShowDependencyPanel(
|
|
176
261
|
service: UserDataService,
|
|
@@ -378,4 +463,34 @@ export class LegendStudioUserDataHelper {
|
|
|
378
463
|
undefined,
|
|
379
464
|
);
|
|
380
465
|
}
|
|
466
|
+
|
|
467
|
+
// --- Showcase feedback votes -------------------------------------------
|
|
468
|
+
|
|
469
|
+
static showcaseFeedback_getVote(
|
|
470
|
+
service: UserDataService,
|
|
471
|
+
showcasePath: string,
|
|
472
|
+
): ShowcaseFeedbackVote | undefined {
|
|
473
|
+
return readShowcaseFeedbackVotes(service).votes.find(
|
|
474
|
+
(v) => v.showcasePath === showcasePath,
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
static showcaseFeedback_recordVote(
|
|
479
|
+
service: UserDataService,
|
|
480
|
+
entry: {
|
|
481
|
+
showcasePath: string;
|
|
482
|
+
vote: 'up' | 'down';
|
|
483
|
+
},
|
|
484
|
+
): void {
|
|
485
|
+
const store = readShowcaseFeedbackVotes(service);
|
|
486
|
+
const next = new ShowcaseFeedbackVote();
|
|
487
|
+
next.showcasePath = entry.showcasePath;
|
|
488
|
+
next.vote = entry.vote;
|
|
489
|
+
next.votedAt = Date.now();
|
|
490
|
+
store.votes = [
|
|
491
|
+
next,
|
|
492
|
+
...store.votes.filter((v) => v.showcasePath !== entry.showcasePath),
|
|
493
|
+
].slice(0, MAX_SHOWCASE_FEEDBACK_VOTES);
|
|
494
|
+
writeShowcaseFeedbackVotes(service, store);
|
|
495
|
+
}
|
|
381
496
|
}
|
|
@@ -208,11 +208,20 @@ export interface LegendStudioApplicationConfigurationData
|
|
|
208
208
|
* the SDLC server's OAuth client allow-list.
|
|
209
209
|
*/
|
|
210
210
|
enablePopupReAuth?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* When `true`, the SDLC server is authenticated exclusively via the
|
|
213
|
+
* session cookie, never via an `Authorization: Bearer` header.
|
|
214
|
+
*
|
|
215
|
+
* See `SDLCServerClientConfig.useCookieAuthOnly`.
|
|
216
|
+
*/
|
|
217
|
+
useCookieAuthOnly?: boolean;
|
|
211
218
|
};
|
|
212
219
|
depot: { url: string };
|
|
213
220
|
engine: {
|
|
214
221
|
url: string;
|
|
215
222
|
queryUrl?: string;
|
|
223
|
+
useCookieAuthOnly?: boolean;
|
|
224
|
+
queryClientName?: string;
|
|
216
225
|
};
|
|
217
226
|
query?: { url: string };
|
|
218
227
|
showcase?: { url: string };
|
|
@@ -225,11 +234,14 @@ export class LegendStudioApplicationConfig extends LegendApplicationConfig {
|
|
|
225
234
|
|
|
226
235
|
readonly engineServerUrl: string;
|
|
227
236
|
readonly engineQueryServerUrl?: string | undefined;
|
|
237
|
+
readonly engineQueryClientName?: string | undefined;
|
|
238
|
+
readonly engineUseCookieAuthOnly: boolean;
|
|
228
239
|
readonly depotServerUrl: string;
|
|
229
240
|
readonly sdlcServerUrl: string;
|
|
230
241
|
readonly sdlcServerBaseHeaders?: RequestHeaders | undefined;
|
|
231
242
|
readonly sdlcServerClient?: string | undefined;
|
|
232
243
|
readonly sdlcEnablePopupReAuth: boolean;
|
|
244
|
+
readonly sdlcUseCookieAuthOnly: boolean;
|
|
233
245
|
readonly queryApplicationUrl?: string | undefined;
|
|
234
246
|
readonly showcaseServerUrl?: string | undefined;
|
|
235
247
|
readonly pctReportUrl?: string | undefined;
|
|
@@ -256,6 +268,10 @@ export class LegendStudioApplicationConfig extends LegendApplicationConfig {
|
|
|
256
268
|
input.configData.engine.queryUrl,
|
|
257
269
|
);
|
|
258
270
|
}
|
|
271
|
+
this.engineQueryClientName = input.configData.engine.queryClientName;
|
|
272
|
+
this.engineUseCookieAuthOnly = Boolean(
|
|
273
|
+
input.configData.engine.useCookieAuthOnly,
|
|
274
|
+
);
|
|
259
275
|
|
|
260
276
|
// depot
|
|
261
277
|
assertNonNullable(
|
|
@@ -285,6 +301,9 @@ export class LegendStudioApplicationConfig extends LegendApplicationConfig {
|
|
|
285
301
|
this.sdlcEnablePopupReAuth = Boolean(
|
|
286
302
|
input.configData.sdlc.enablePopupReAuth,
|
|
287
303
|
);
|
|
304
|
+
this.sdlcUseCookieAuthOnly = Boolean(
|
|
305
|
+
input.configData.sdlc.useCookieAuthOnly,
|
|
306
|
+
);
|
|
288
307
|
|
|
289
308
|
// query
|
|
290
309
|
if (input.configData.query?.url) {
|
|
@@ -40,6 +40,8 @@ import {
|
|
|
40
40
|
import {
|
|
41
41
|
useApplicationStore,
|
|
42
42
|
LegendTokenSync,
|
|
43
|
+
ExtensionPageBoundary,
|
|
44
|
+
LegendApplicationTelemetryHelper,
|
|
43
45
|
} from '@finos/legend-application';
|
|
44
46
|
import {
|
|
45
47
|
BrowserEnvironmentProvider,
|
|
@@ -64,6 +66,13 @@ const NotFoundPage = observer(() => {
|
|
|
64
66
|
const currentPath =
|
|
65
67
|
applicationStore.navigationService.navigator.getCurrentLocation();
|
|
66
68
|
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
LegendApplicationTelemetryHelper.logEvent_RouteNotFound(
|
|
71
|
+
applicationStore.telemetryService,
|
|
72
|
+
{ path: currentPath },
|
|
73
|
+
);
|
|
74
|
+
}, [applicationStore, currentPath]);
|
|
75
|
+
|
|
67
76
|
const documentation = applicationStore.documentationService.getDocEntry(
|
|
68
77
|
LEGEND_STUDIO_DOCUMENTATION_KEY.NOT_FOUND_HELP,
|
|
69
78
|
);
|
|
@@ -280,9 +289,16 @@ export const LegendStudioWebApplicationRouter = observer(() => {
|
|
|
280
289
|
.map(generateExtensionUrlPattern)
|
|
281
290
|
.map((path) => (
|
|
282
291
|
<Route
|
|
283
|
-
key={entry.key}
|
|
292
|
+
key={`${entry.key}:${path}`}
|
|
284
293
|
path={path}
|
|
285
|
-
element={
|
|
294
|
+
element={
|
|
295
|
+
<ExtensionPageBoundary
|
|
296
|
+
entryKey={entry.key}
|
|
297
|
+
pattern={path}
|
|
298
|
+
>
|
|
299
|
+
{entry.renderer()}
|
|
300
|
+
</ExtensionPageBoundary>
|
|
301
|
+
}
|
|
286
302
|
/>
|
|
287
303
|
)),
|
|
288
304
|
)}
|
|
@@ -42,6 +42,11 @@ import {
|
|
|
42
42
|
type ShowcaseTextSearchMatchResult,
|
|
43
43
|
type ShowcasesExplorerTreeNodeData,
|
|
44
44
|
} from '../stores/ShowcaseManagerState.js';
|
|
45
|
+
import {
|
|
46
|
+
SHOWCASE_LAUNCH_ENTRY_POINT,
|
|
47
|
+
SHOWCASE_FEEDBACK_SURFACE,
|
|
48
|
+
} from '../__lib__/LegendStudioTelemetryHelper.js';
|
|
49
|
+
import { ShowcaseFeedback } from './showcase/ShowcaseFeedback.js';
|
|
45
50
|
import { debounce, isNonNullable } from '@finos/legend-shared';
|
|
46
51
|
import { flowResult } from 'mobx';
|
|
47
52
|
import type { Showcase } from '@finos/legend-server-showcase';
|
|
@@ -86,9 +91,13 @@ const ShowcasesExplorerTreeNodeContainer = observer(
|
|
|
86
91
|
if (!node.metadata) {
|
|
87
92
|
toggleExpandNode(node);
|
|
88
93
|
} else {
|
|
89
|
-
flowResult(
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
flowResult(
|
|
95
|
+
showcaseManagerState.openShowcase(
|
|
96
|
+
node.metadata,
|
|
97
|
+
undefined,
|
|
98
|
+
SHOWCASE_LAUNCH_ENTRY_POINT.EXPLORER,
|
|
99
|
+
),
|
|
100
|
+
).catch(applicationStore.alertUnhandledError);
|
|
92
101
|
}
|
|
93
102
|
};
|
|
94
103
|
|
|
@@ -254,7 +263,11 @@ const ShowcaseManagerCodeSearchResult = observer(
|
|
|
254
263
|
}\n\nClick to open showcase`}
|
|
255
264
|
onClick={() => {
|
|
256
265
|
flowResult(
|
|
257
|
-
showcaseManagerState.openShowcase(
|
|
266
|
+
showcaseManagerState.openShowcase(
|
|
267
|
+
result.showcase,
|
|
268
|
+
undefined,
|
|
269
|
+
SHOWCASE_LAUNCH_ENTRY_POINT.SEARCH_SHOWCASE_MATCH,
|
|
270
|
+
),
|
|
258
271
|
).catch(applicationStore.alertUnhandledError);
|
|
259
272
|
}}
|
|
260
273
|
>
|
|
@@ -275,6 +288,7 @@ const ShowcaseManagerCodeSearchResult = observer(
|
|
|
275
288
|
showcaseManagerState.openShowcase(
|
|
276
289
|
result.showcase,
|
|
277
290
|
entry.line,
|
|
291
|
+
SHOWCASE_LAUNCH_ENTRY_POINT.SEARCH_CODE_MATCH,
|
|
278
292
|
),
|
|
279
293
|
).catch(applicationStore.alertUnhandledError);
|
|
280
294
|
}}
|
|
@@ -635,6 +649,12 @@ const ShowcaseViewer = observer(
|
|
|
635
649
|
lineToScroll={showcaseManagerState.showcaseLineToScroll}
|
|
636
650
|
/>
|
|
637
651
|
</div>
|
|
652
|
+
<ShowcaseFeedback
|
|
653
|
+
className="showcase-manager__viewer__feedback"
|
|
654
|
+
showcasePath={showcase.path}
|
|
655
|
+
title={showcase.title}
|
|
656
|
+
surface={SHOWCASE_FEEDBACK_SURFACE.ASSISTANT_PANEL}
|
|
657
|
+
/>
|
|
638
658
|
</div>
|
|
639
659
|
</div>
|
|
640
660
|
);
|
|
@@ -81,6 +81,7 @@ import {
|
|
|
81
81
|
ShowcaseManagerState,
|
|
82
82
|
openShowcaseManager,
|
|
83
83
|
} from '../../stores/ShowcaseManagerState.js';
|
|
84
|
+
import { SHOWCASE_MANAGER_ENTRY_POINT } from '../../__lib__/LegendStudioTelemetryHelper.js';
|
|
84
85
|
import { toggleShowcasePanel } from './ShowcaseSideBar.js';
|
|
85
86
|
import { useAuth, type AuthContextProps } from 'react-oidc-context';
|
|
86
87
|
|
|
@@ -223,7 +224,10 @@ export const ActivityBarMenu: React.FC<{
|
|
|
223
224
|
onClick={() =>
|
|
224
225
|
openShowcasePanel
|
|
225
226
|
? openShowcasePanel()
|
|
226
|
-
: openShowcaseManager(
|
|
227
|
+
: openShowcaseManager(
|
|
228
|
+
applicationStore,
|
|
229
|
+
SHOWCASE_MANAGER_ENTRY_POINT.ACTIVITY_BAR,
|
|
230
|
+
)
|
|
227
231
|
}
|
|
228
232
|
>
|
|
229
233
|
See Showcases
|
|
@@ -132,6 +132,12 @@ import {
|
|
|
132
132
|
GraphEditGrammarModeState,
|
|
133
133
|
} from '../../../stores/editor/GraphEditGrammarModeState.js';
|
|
134
134
|
import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
|
|
135
|
+
import {
|
|
136
|
+
LegendStudioTelemetryHelper,
|
|
137
|
+
TEXT_MODE_ACTION,
|
|
138
|
+
TEXT_MODE_ACTION_STATUS,
|
|
139
|
+
TEXT_MODE_TOGGLE_SOURCE,
|
|
140
|
+
} from '../../../__lib__/LegendStudioTelemetryHelper.js';
|
|
135
141
|
import { FileSystem_FileViewer } from './ArtifactGenerationViewer.js';
|
|
136
142
|
import type { FileSystem_File } from '../../../stores/editor/utils/FileSystemTreeUtils.js';
|
|
137
143
|
|
|
@@ -141,7 +147,9 @@ export const GrammarTextEditorHeaderTabContextMenu = observer(
|
|
|
141
147
|
const editorStore = useEditorStore();
|
|
142
148
|
const applicationStore = useApplicationStore();
|
|
143
149
|
const leaveTextMode = applicationStore.guardUnhandledError(() =>
|
|
144
|
-
flowResult(
|
|
150
|
+
flowResult(
|
|
151
|
+
editorStore.toggleTextMode(TEXT_MODE_TOGGLE_SOURCE.CONTEXT_MENU),
|
|
152
|
+
),
|
|
145
153
|
);
|
|
146
154
|
|
|
147
155
|
return (
|
|
@@ -766,6 +774,14 @@ const goToElement = (
|
|
|
766
774
|
LEGEND_STUDIO_APP_EVENT.TEXT_MODE_ACTION_KEYBOARD_SHORTCUT_GO_TO_DEFINITION__LAUNCH,
|
|
767
775
|
),
|
|
768
776
|
);
|
|
777
|
+
LegendStudioTelemetryHelper.logEvent_TextModeAction(
|
|
778
|
+
grammarModeState.editorStore.applicationStore.telemetryService,
|
|
779
|
+
grammarModeState.editorStore.editorMode.getSourceInfo(),
|
|
780
|
+
{
|
|
781
|
+
action: TEXT_MODE_ACTION.GO_TO_DEFINITION,
|
|
782
|
+
status: TEXT_MODE_ACTION_STATUS.LAUNCH,
|
|
783
|
+
},
|
|
784
|
+
);
|
|
769
785
|
const elementPath = resolveElementPathFromCurrentPosition(
|
|
770
786
|
_editor,
|
|
771
787
|
grammarModeState,
|
|
@@ -882,6 +898,7 @@ export const GrammarTextEditor = observer(() => {
|
|
|
882
898
|
});
|
|
883
899
|
_editor.onDidChangeModelContent(() => {
|
|
884
900
|
grammarTextEditorState.setGraphGrammarText(getCodeEditorValue(_editor));
|
|
901
|
+
grammarModeState.notifyGrammarTextEdited();
|
|
885
902
|
clearMarkers();
|
|
886
903
|
// NOTE: we can technically can reset the current element label regex string here
|
|
887
904
|
// but if we do that on first load, the cursor will not jump to the current element
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-present, Goldman Sachs
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { observer } from 'mobx-react-lite';
|
|
18
|
+
import { useState, type CSSProperties } from 'react';
|
|
19
|
+
import {
|
|
20
|
+
Dialog,
|
|
21
|
+
LongArrowRightIcon,
|
|
22
|
+
Modal,
|
|
23
|
+
ModalBody,
|
|
24
|
+
ModalFooter,
|
|
25
|
+
ModalFooterButton,
|
|
26
|
+
ModalHeader,
|
|
27
|
+
PencilEditIcon,
|
|
28
|
+
PlusIcon,
|
|
29
|
+
Tooltip,
|
|
30
|
+
} from '@finos/legend-art';
|
|
31
|
+
import {
|
|
32
|
+
ActionAlertActionType,
|
|
33
|
+
ActionAlertType,
|
|
34
|
+
} from '@finos/legend-application';
|
|
35
|
+
import type { RelationElementState } from '../../../../stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js';
|
|
36
|
+
import { RelationElementEditor } from './RelationElementsDataEditor.js';
|
|
37
|
+
import { useEditorStore } from '../../EditorStoreProvider.js';
|
|
38
|
+
|
|
39
|
+
export interface RelationElementSampleValuesReadOnlySource {
|
|
40
|
+
label: string;
|
|
41
|
+
message?: string | undefined;
|
|
42
|
+
onNavigate: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const RelationElementSampleValuesEditor = observer(
|
|
46
|
+
(props: {
|
|
47
|
+
title: string;
|
|
48
|
+
relationElementState: RelationElementState | undefined;
|
|
49
|
+
isReadOnly: boolean;
|
|
50
|
+
isBusy?: boolean | undefined;
|
|
51
|
+
hideColumnDefinitions?: boolean | undefined;
|
|
52
|
+
deleteConfirmMessage: string;
|
|
53
|
+
onAdd: () => Promise<void> | void;
|
|
54
|
+
onDelete: () => void;
|
|
55
|
+
hasMismatch?: boolean | undefined;
|
|
56
|
+
mismatchMessage?: string | undefined;
|
|
57
|
+
readOnlySource?: RelationElementSampleValuesReadOnlySource | undefined;
|
|
58
|
+
}) => {
|
|
59
|
+
const {
|
|
60
|
+
title,
|
|
61
|
+
relationElementState,
|
|
62
|
+
isReadOnly,
|
|
63
|
+
isBusy,
|
|
64
|
+
hideColumnDefinitions,
|
|
65
|
+
deleteConfirmMessage,
|
|
66
|
+
onAdd,
|
|
67
|
+
onDelete,
|
|
68
|
+
hasMismatch,
|
|
69
|
+
mismatchMessage,
|
|
70
|
+
readOnlySource,
|
|
71
|
+
} = props;
|
|
72
|
+
const editorStore = useEditorStore();
|
|
73
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
74
|
+
const isEditMode = Boolean(relationElementState) || Boolean(readOnlySource);
|
|
75
|
+
|
|
76
|
+
const closeModal = (): void => setIsModalOpen(false);
|
|
77
|
+
|
|
78
|
+
const handleClick = (): void => {
|
|
79
|
+
if (isEditMode) {
|
|
80
|
+
setIsModalOpen(true);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
Promise.resolve(onAdd())
|
|
84
|
+
.then(() => setIsModalOpen(true))
|
|
85
|
+
.catch(editorStore.applicationStore.alertUnhandledError);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const handleDelete = (): void => {
|
|
89
|
+
editorStore.applicationStore.alertService.setActionAlertInfo({
|
|
90
|
+
message: deleteConfirmMessage,
|
|
91
|
+
type: ActionAlertType.CAUTION,
|
|
92
|
+
actions: [
|
|
93
|
+
{
|
|
94
|
+
label: 'Confirm',
|
|
95
|
+
type: ActionAlertActionType.PROCEED_WITH_CAUTION,
|
|
96
|
+
handler: (): void => {
|
|
97
|
+
onDelete();
|
|
98
|
+
closeModal();
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
label: 'Cancel',
|
|
103
|
+
type: ActionAlertActionType.PROCEED,
|
|
104
|
+
default: true,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const buttonStyle: CSSProperties = {
|
|
111
|
+
cursor: isReadOnly ? 'not-allowed' : 'pointer',
|
|
112
|
+
};
|
|
113
|
+
if (relationElementState && !readOnlySource) {
|
|
114
|
+
buttonStyle.border = hasMismatch
|
|
115
|
+
? '2px solid var(--color-red-300)'
|
|
116
|
+
: '1px solid var(--color-blue-200)';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<>
|
|
121
|
+
<button
|
|
122
|
+
className="access-point-editor__sample-values-btn"
|
|
123
|
+
onClick={handleClick}
|
|
124
|
+
disabled={isReadOnly || isBusy}
|
|
125
|
+
title={isEditMode ? 'Edit sample values' : 'Add sample values'}
|
|
126
|
+
style={buttonStyle}
|
|
127
|
+
>
|
|
128
|
+
{isEditMode ? <PencilEditIcon /> : <PlusIcon />}
|
|
129
|
+
<span>Sample Values</span>
|
|
130
|
+
</button>
|
|
131
|
+
{isModalOpen && (
|
|
132
|
+
<Dialog
|
|
133
|
+
open={isModalOpen}
|
|
134
|
+
onClose={closeModal}
|
|
135
|
+
classes={{
|
|
136
|
+
root: 'editor-modal__root-container',
|
|
137
|
+
container: 'editor-modal__container',
|
|
138
|
+
paper: 'editor-modal__content',
|
|
139
|
+
}}
|
|
140
|
+
>
|
|
141
|
+
<Modal
|
|
142
|
+
className="editor-modal"
|
|
143
|
+
darkMode={
|
|
144
|
+
!editorStore.applicationStore.layoutService
|
|
145
|
+
.TEMPORARY__isLightColorThemeEnabled
|
|
146
|
+
}
|
|
147
|
+
>
|
|
148
|
+
<ModalHeader title={title} />
|
|
149
|
+
<ModalBody>
|
|
150
|
+
<div
|
|
151
|
+
style={{
|
|
152
|
+
padding: 0,
|
|
153
|
+
height: '100%',
|
|
154
|
+
flex: 1,
|
|
155
|
+
overflowY: 'auto',
|
|
156
|
+
overflowX: 'hidden',
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
{readOnlySource ? (
|
|
160
|
+
<div
|
|
161
|
+
style={{
|
|
162
|
+
padding: '1.5rem',
|
|
163
|
+
display: 'flex',
|
|
164
|
+
alignItems: 'center',
|
|
165
|
+
justifyContent: 'center',
|
|
166
|
+
gap: '1rem',
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
<span
|
|
170
|
+
style={{
|
|
171
|
+
color: 'var(--color-light-grey-200)',
|
|
172
|
+
whiteSpace: 'nowrap',
|
|
173
|
+
fontSize: '1.3rem',
|
|
174
|
+
fontWeight: 600,
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
{readOnlySource.message ??
|
|
178
|
+
'Sample Values already in Data Element'}
|
|
179
|
+
</span>
|
|
180
|
+
<div
|
|
181
|
+
style={{
|
|
182
|
+
display: 'flex',
|
|
183
|
+
alignItems: 'center',
|
|
184
|
+
gap: '0.5rem',
|
|
185
|
+
padding: '0.5rem 1rem',
|
|
186
|
+
background: 'var(--color-dark-grey-100)',
|
|
187
|
+
border: '1px solid var(--color-dark-grey-300)',
|
|
188
|
+
borderRadius: '0.2rem',
|
|
189
|
+
}}
|
|
190
|
+
>
|
|
191
|
+
<span
|
|
192
|
+
style={{
|
|
193
|
+
fontSize: '1.3rem',
|
|
194
|
+
fontWeight: 600,
|
|
195
|
+
color: 'var(--color-light-grey-200)',
|
|
196
|
+
}}
|
|
197
|
+
>
|
|
198
|
+
{readOnlySource.label}
|
|
199
|
+
</span>
|
|
200
|
+
<button
|
|
201
|
+
className="btn--sm btn--dark"
|
|
202
|
+
onClick={readOnlySource.onNavigate}
|
|
203
|
+
tabIndex={-1}
|
|
204
|
+
title="Navigate to data element"
|
|
205
|
+
style={{
|
|
206
|
+
padding: '0.3rem 0.5rem',
|
|
207
|
+
display: 'flex',
|
|
208
|
+
alignItems: 'center',
|
|
209
|
+
}}
|
|
210
|
+
>
|
|
211
|
+
<LongArrowRightIcon />
|
|
212
|
+
</button>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
) : (
|
|
216
|
+
<>
|
|
217
|
+
<div
|
|
218
|
+
style={{
|
|
219
|
+
color: 'var(--color-orange-200)',
|
|
220
|
+
fontWeight: 'bold',
|
|
221
|
+
fontSize: '14px',
|
|
222
|
+
padding: '0.5rem',
|
|
223
|
+
marginBottom: '1rem',
|
|
224
|
+
textAlign: 'center',
|
|
225
|
+
backgroundColor: 'var(--color-orange-50)',
|
|
226
|
+
border: '2px solid var(--color-orange-200)',
|
|
227
|
+
borderRadius: '4px',
|
|
228
|
+
}}
|
|
229
|
+
>
|
|
230
|
+
DO NOT ADD SENSITIVE DATA
|
|
231
|
+
</div>
|
|
232
|
+
{relationElementState && (
|
|
233
|
+
<Tooltip
|
|
234
|
+
title={mismatchMessage ?? ''}
|
|
235
|
+
arrow={true}
|
|
236
|
+
placement="top"
|
|
237
|
+
disableHoverListener={!hasMismatch}
|
|
238
|
+
>
|
|
239
|
+
<div
|
|
240
|
+
style={{
|
|
241
|
+
border: hasMismatch
|
|
242
|
+
? '2px solid var(--color-red-300)'
|
|
243
|
+
: 'none',
|
|
244
|
+
borderRadius: '4px',
|
|
245
|
+
padding: hasMismatch ? '0.5rem' : '0',
|
|
246
|
+
}}
|
|
247
|
+
>
|
|
248
|
+
<RelationElementEditor
|
|
249
|
+
relationElementState={relationElementState}
|
|
250
|
+
isReadOnly={isReadOnly}
|
|
251
|
+
{...(hideColumnDefinitions !== undefined
|
|
252
|
+
? { hideColumnDefinitions }
|
|
253
|
+
: {})}
|
|
254
|
+
/>
|
|
255
|
+
</div>
|
|
256
|
+
</Tooltip>
|
|
257
|
+
)}
|
|
258
|
+
</>
|
|
259
|
+
)}
|
|
260
|
+
</div>
|
|
261
|
+
</ModalBody>
|
|
262
|
+
<ModalFooter>
|
|
263
|
+
{!readOnlySource && (
|
|
264
|
+
<ModalFooterButton
|
|
265
|
+
title="Delete sample values"
|
|
266
|
+
onClick={handleDelete}
|
|
267
|
+
text="Delete"
|
|
268
|
+
type="secondary"
|
|
269
|
+
disabled={isReadOnly}
|
|
270
|
+
/>
|
|
271
|
+
)}
|
|
272
|
+
<ModalFooterButton
|
|
273
|
+
title="Close sample values editor"
|
|
274
|
+
onClick={closeModal}
|
|
275
|
+
text="Close"
|
|
276
|
+
type="secondary"
|
|
277
|
+
/>
|
|
278
|
+
</ModalFooter>
|
|
279
|
+
</Modal>
|
|
280
|
+
</Dialog>
|
|
281
|
+
)}
|
|
282
|
+
</>
|
|
283
|
+
);
|
|
284
|
+
},
|
|
285
|
+
);
|