@finos/legend-application-studio 28.21.43 → 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 +10 -0
- package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.js +4 -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/dataProduct/DataProductEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +6 -16
- 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/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 +7 -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 +1 -11
- 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 +2 -64
- 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 +1 -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 +2 -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 +6 -3
- package/lib/stores/showcase/ShowcaseViewerStore.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 +14 -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/dataProduct/DataProductEditor.tsx +4 -54
- 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/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 +24 -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 +0 -106
- 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 +2 -0
- package/src/stores/project-view/ProjectViewerEditorMode.ts +17 -4
- package/src/stores/project-view/ProjectViewerStore.ts +3 -0
- package/src/stores/showcase/ShowcaseViewerEditorMode.ts +4 -5
- package/src/stores/showcase/ShowcaseViewerStore.ts +10 -2
- package/tsconfig.json +1 -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,12 +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;
|
|
216
223
|
useCookieAuthOnly?: boolean;
|
|
224
|
+
queryClientName?: string;
|
|
217
225
|
};
|
|
218
226
|
query?: { url: string };
|
|
219
227
|
showcase?: { url: string };
|
|
@@ -226,12 +234,14 @@ export class LegendStudioApplicationConfig extends LegendApplicationConfig {
|
|
|
226
234
|
|
|
227
235
|
readonly engineServerUrl: string;
|
|
228
236
|
readonly engineQueryServerUrl?: string | undefined;
|
|
237
|
+
readonly engineQueryClientName?: string | undefined;
|
|
229
238
|
readonly engineUseCookieAuthOnly: boolean;
|
|
230
239
|
readonly depotServerUrl: string;
|
|
231
240
|
readonly sdlcServerUrl: string;
|
|
232
241
|
readonly sdlcServerBaseHeaders?: RequestHeaders | undefined;
|
|
233
242
|
readonly sdlcServerClient?: string | undefined;
|
|
234
243
|
readonly sdlcEnablePopupReAuth: boolean;
|
|
244
|
+
readonly sdlcUseCookieAuthOnly: boolean;
|
|
235
245
|
readonly queryApplicationUrl?: string | undefined;
|
|
236
246
|
readonly showcaseServerUrl?: string | undefined;
|
|
237
247
|
readonly pctReportUrl?: string | undefined;
|
|
@@ -258,6 +268,7 @@ export class LegendStudioApplicationConfig extends LegendApplicationConfig {
|
|
|
258
268
|
input.configData.engine.queryUrl,
|
|
259
269
|
);
|
|
260
270
|
}
|
|
271
|
+
this.engineQueryClientName = input.configData.engine.queryClientName;
|
|
261
272
|
this.engineUseCookieAuthOnly = Boolean(
|
|
262
273
|
input.configData.engine.useCookieAuthOnly,
|
|
263
274
|
);
|
|
@@ -290,6 +301,9 @@ export class LegendStudioApplicationConfig extends LegendApplicationConfig {
|
|
|
290
301
|
this.sdlcEnablePopupReAuth = Boolean(
|
|
291
302
|
input.configData.sdlc.enablePopupReAuth,
|
|
292
303
|
);
|
|
304
|
+
this.sdlcUseCookieAuthOnly = Boolean(
|
|
305
|
+
input.configData.sdlc.useCookieAuthOnly,
|
|
306
|
+
);
|
|
293
307
|
|
|
294
308
|
// query
|
|
295
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
|
|
@@ -53,7 +53,6 @@ import {
|
|
|
53
53
|
ModalFooter,
|
|
54
54
|
ModalFooterButton,
|
|
55
55
|
ModalHeader,
|
|
56
|
-
ModalTitle,
|
|
57
56
|
PanelContent,
|
|
58
57
|
PanelDnDEntry,
|
|
59
58
|
PanelEntryDragHandle,
|
|
@@ -1054,56 +1053,6 @@ export const LakehouseDataProductAccessPointEditor = observer(
|
|
|
1054
1053
|
},
|
|
1055
1054
|
);
|
|
1056
1055
|
|
|
1057
|
-
const DataProductDeploymentResponseModal = observer(
|
|
1058
|
-
(props: { state: DataProductEditorState }) => {
|
|
1059
|
-
const { state } = props;
|
|
1060
|
-
const applicationStore = state.editorStore.applicationStore;
|
|
1061
|
-
const closeModal = (): void => state.setDeployResponse(undefined);
|
|
1062
|
-
return (
|
|
1063
|
-
<Dialog
|
|
1064
|
-
open={Boolean(state.deployResponse)}
|
|
1065
|
-
classes={{
|
|
1066
|
-
root: 'editor-modal__root-container',
|
|
1067
|
-
container: 'editor-modal__container',
|
|
1068
|
-
paper: 'editor-modal__content',
|
|
1069
|
-
}}
|
|
1070
|
-
onClose={closeModal}
|
|
1071
|
-
>
|
|
1072
|
-
<Modal
|
|
1073
|
-
darkMode={
|
|
1074
|
-
!applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
|
|
1075
|
-
}
|
|
1076
|
-
className="editor-modal"
|
|
1077
|
-
>
|
|
1078
|
-
<ModalHeader>
|
|
1079
|
-
<ModalTitle title="Data Product Deployment Response" />
|
|
1080
|
-
</ModalHeader>
|
|
1081
|
-
<ModalBody>
|
|
1082
|
-
<PanelContent>
|
|
1083
|
-
<CodeEditor
|
|
1084
|
-
inputValue={JSON.stringify(
|
|
1085
|
-
state.deployResponse?.content ?? {},
|
|
1086
|
-
null,
|
|
1087
|
-
2,
|
|
1088
|
-
)}
|
|
1089
|
-
isReadOnly={true}
|
|
1090
|
-
language={CODE_EDITOR_LANGUAGE.JSON}
|
|
1091
|
-
/>
|
|
1092
|
-
</PanelContent>
|
|
1093
|
-
</ModalBody>
|
|
1094
|
-
<ModalFooter>
|
|
1095
|
-
<ModalFooterButton
|
|
1096
|
-
onClick={closeModal}
|
|
1097
|
-
text="Close"
|
|
1098
|
-
type="secondary"
|
|
1099
|
-
/>
|
|
1100
|
-
</ModalFooter>
|
|
1101
|
-
</Modal>
|
|
1102
|
-
</Dialog>
|
|
1103
|
-
);
|
|
1104
|
-
},
|
|
1105
|
-
);
|
|
1106
|
-
|
|
1107
1056
|
const AccessPointGroupPublicToggle = observer(
|
|
1108
1057
|
(props: { groupState: AccessPointGroupState }) => {
|
|
1109
1058
|
const { groupState } = props;
|
|
@@ -1345,6 +1294,7 @@ const AccessPointGroupEditor = observer(
|
|
|
1345
1294
|
LegendStudioTelemetryHelper.logEvent_DataProductLegendAISuggestLaunched(
|
|
1346
1295
|
editorStore.applicationStore.telemetryService,
|
|
1347
1296
|
productEditorState.product.path,
|
|
1297
|
+
editorStore.editorMode.getSourceInfo(),
|
|
1348
1298
|
);
|
|
1349
1299
|
setIsSuggestingWithAI(true);
|
|
1350
1300
|
setAISuggestion(undefined);
|
|
@@ -1367,6 +1317,7 @@ const AccessPointGroupEditor = observer(
|
|
|
1367
1317
|
editorStore.applicationStore.telemetryService,
|
|
1368
1318
|
productEditorState.product.path,
|
|
1369
1319
|
error.message,
|
|
1320
|
+
editorStore.editorMode.getSourceInfo(),
|
|
1370
1321
|
);
|
|
1371
1322
|
if (
|
|
1372
1323
|
error instanceof NetworkClientError &&
|
|
@@ -1395,6 +1346,7 @@ const AccessPointGroupEditor = observer(
|
|
|
1395
1346
|
LegendStudioTelemetryHelper.logEvent_DataProductLegendAISuggestApplied(
|
|
1396
1347
|
editorStore.applicationStore.telemetryService,
|
|
1397
1348
|
productEditorState.product.path,
|
|
1349
|
+
editorStore.editorMode.getSourceInfo(),
|
|
1398
1350
|
);
|
|
1399
1351
|
// Find matching group in the response
|
|
1400
1352
|
const gIdx =
|
|
@@ -1437,6 +1389,7 @@ const AccessPointGroupEditor = observer(
|
|
|
1437
1389
|
LegendStudioTelemetryHelper.logEvent_DataProductLegendAISuggestDiscarded(
|
|
1438
1390
|
editorStore.applicationStore.telemetryService,
|
|
1439
1391
|
productEditorState.product.path,
|
|
1392
|
+
editorStore.editorMode.getSourceInfo(),
|
|
1440
1393
|
);
|
|
1441
1394
|
setAISuggestion(undefined);
|
|
1442
1395
|
};
|
|
@@ -1963,9 +1916,6 @@ const AccessPointGroupTab = observer(
|
|
|
1963
1916
|
/>
|
|
1964
1917
|
)}
|
|
1965
1918
|
</PanelContent>
|
|
1966
|
-
{dataProductEditorState.deployResponse && (
|
|
1967
|
-
<DataProductDeploymentResponseModal state={dataProductEditorState} />
|
|
1968
|
-
)}
|
|
1969
1919
|
</div>
|
|
1970
1920
|
);
|
|
1971
1921
|
},
|
|
@@ -274,6 +274,7 @@ const ServiceGeneralEditor = observer(() => {
|
|
|
274
274
|
LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestLaunched(
|
|
275
275
|
applicationStore.telemetryService,
|
|
276
276
|
service.path,
|
|
277
|
+
editorStore.editorMode.getSourceInfo(),
|
|
277
278
|
);
|
|
278
279
|
setIsSuggestingWithAI(true);
|
|
279
280
|
setAIDocSuggestion(undefined);
|
|
@@ -290,6 +291,7 @@ const ServiceGeneralEditor = observer(() => {
|
|
|
290
291
|
applicationStore.telemetryService,
|
|
291
292
|
service.path,
|
|
292
293
|
error.message,
|
|
294
|
+
editorStore.editorMode.getSourceInfo(),
|
|
293
295
|
);
|
|
294
296
|
if (
|
|
295
297
|
error instanceof NetworkClientError &&
|
|
@@ -315,6 +317,7 @@ const ServiceGeneralEditor = observer(() => {
|
|
|
315
317
|
LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestApplied(
|
|
316
318
|
applicationStore.telemetryService,
|
|
317
319
|
service.path,
|
|
320
|
+
editorStore.editorMode.getSourceInfo(),
|
|
318
321
|
);
|
|
319
322
|
service_setDocumentation(service, aiDocSuggestion);
|
|
320
323
|
setAIDocSuggestion(undefined);
|
|
@@ -323,6 +326,7 @@ const ServiceGeneralEditor = observer(() => {
|
|
|
323
326
|
LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestDiscarded(
|
|
324
327
|
applicationStore.telemetryService,
|
|
325
328
|
service.path,
|
|
329
|
+
editorStore.editorMode.getSourceInfo(),
|
|
326
330
|
);
|
|
327
331
|
setAIDocSuggestion(undefined);
|
|
328
332
|
};
|
|
@@ -0,0 +1,136 @@
|
|
|
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 { useEffect, useRef, useState } from 'react';
|
|
18
|
+
import { clsx, ThumbsUpIcon, ThumbsDownIcon } from '@finos/legend-art';
|
|
19
|
+
import { useApplicationStore } from '@finos/legend-application';
|
|
20
|
+
import { LegendStudioUserDataHelper } from '../../__lib__/LegendStudioUserDataHelper.js';
|
|
21
|
+
import {
|
|
22
|
+
LegendStudioTelemetryHelper,
|
|
23
|
+
SHOWCASE_FEEDBACK_VOTE,
|
|
24
|
+
type SHOWCASE_FEEDBACK_SURFACE,
|
|
25
|
+
} from '../../__lib__/LegendStudioTelemetryHelper.js';
|
|
26
|
+
|
|
27
|
+
const THANKS_DISPLAY_DURATION_MS = 2500;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* "Was this showcase helpful?" widget.
|
|
31
|
+
*
|
|
32
|
+
* v1 storage strategy: telemetry is the source of truth for aggregate
|
|
33
|
+
* analysis (`showcase.viewer.feedback.submit`). The user's vote per
|
|
34
|
+
* showcase is cached in browser `UserDataService` (localStorage) purely
|
|
35
|
+
* so we can suppress re-prompting on revisit — there is no backend today.
|
|
36
|
+
*
|
|
37
|
+
* UX: once a user votes, the buttons are replaced with a brief
|
|
38
|
+
* "Thanks for the feedback!" message and then the whole widget unmounts.
|
|
39
|
+
* On subsequent visits to the same showcase, the widget renders nothing.
|
|
40
|
+
*/
|
|
41
|
+
export const ShowcaseFeedback = (props: {
|
|
42
|
+
showcasePath: string;
|
|
43
|
+
title?: string | undefined;
|
|
44
|
+
surface: SHOWCASE_FEEDBACK_SURFACE;
|
|
45
|
+
/** Optional CSS class hook so the two mount points can size / align. */
|
|
46
|
+
className?: string | undefined;
|
|
47
|
+
}) => {
|
|
48
|
+
const { showcasePath, title, surface, className } = props;
|
|
49
|
+
const applicationStore = useApplicationStore();
|
|
50
|
+
const alreadyVoted = Boolean(
|
|
51
|
+
LegendStudioUserDataHelper.showcaseFeedback_getVote(
|
|
52
|
+
applicationStore.userDataService,
|
|
53
|
+
showcasePath,
|
|
54
|
+
),
|
|
55
|
+
);
|
|
56
|
+
const [phase, setPhase] = useState<'prompt' | 'thanks' | 'done'>(
|
|
57
|
+
alreadyVoted ? 'done' : 'prompt',
|
|
58
|
+
);
|
|
59
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(
|
|
60
|
+
undefined,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
useEffect(
|
|
64
|
+
() => (): void => {
|
|
65
|
+
if (timeoutRef.current !== undefined) {
|
|
66
|
+
clearTimeout(timeoutRef.current);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
[],
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const submit = (vote: SHOWCASE_FEEDBACK_VOTE): void => {
|
|
73
|
+
LegendStudioUserDataHelper.showcaseFeedback_recordVote(
|
|
74
|
+
applicationStore.userDataService,
|
|
75
|
+
{
|
|
76
|
+
showcasePath,
|
|
77
|
+
vote: vote === SHOWCASE_FEEDBACK_VOTE.UP ? 'up' : 'down',
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
LegendStudioTelemetryHelper.logEvent_ShowcaseFeedbackSubmit(
|
|
81
|
+
applicationStore.telemetryService,
|
|
82
|
+
{
|
|
83
|
+
showcasePath,
|
|
84
|
+
title,
|
|
85
|
+
vote,
|
|
86
|
+
surface,
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
setPhase('thanks');
|
|
90
|
+
timeoutRef.current = setTimeout(() => {
|
|
91
|
+
setPhase('done');
|
|
92
|
+
}, THANKS_DISPLAY_DURATION_MS);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
if (phase === 'done') {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (phase === 'thanks') {
|
|
100
|
+
return (
|
|
101
|
+
<div
|
|
102
|
+
className={clsx('showcase-feedback', className)}
|
|
103
|
+
role="status"
|
|
104
|
+
aria-live="polite"
|
|
105
|
+
>
|
|
106
|
+
<div className="showcase-feedback__prompt">
|
|
107
|
+
Thanks for the feedback!
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<div className={clsx('showcase-feedback', className)}>
|
|
115
|
+
<div className="showcase-feedback__prompt">Was this helpful?</div>
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
className="showcase-feedback__btn"
|
|
119
|
+
tabIndex={-1}
|
|
120
|
+
title="Thumbs up"
|
|
121
|
+
onClick={() => submit(SHOWCASE_FEEDBACK_VOTE.UP)}
|
|
122
|
+
>
|
|
123
|
+
<ThumbsUpIcon />
|
|
124
|
+
</button>
|
|
125
|
+
<button
|
|
126
|
+
type="button"
|
|
127
|
+
className="showcase-feedback__btn"
|
|
128
|
+
tabIndex={-1}
|
|
129
|
+
title="Thumbs down"
|
|
130
|
+
onClick={() => submit(SHOWCASE_FEEDBACK_VOTE.DOWN)}
|
|
131
|
+
>
|
|
132
|
+
<ThumbsDownIcon />
|
|
133
|
+
</button>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
};
|
|
@@ -62,6 +62,8 @@ import { LEGEND_STUDIO_TEST_ID } from '../../__lib__/LegendStudioTesting.js';
|
|
|
62
62
|
import { Explorer } from '../editor/side-bar/Explorer.js';
|
|
63
63
|
import { PanelGroup } from '../editor/panel-group/PanelGroup.js';
|
|
64
64
|
import { QueryDataCubeViewer } from '@finos/legend-query-builder';
|
|
65
|
+
import { ShowcaseFeedback } from './ShowcaseFeedback.js';
|
|
66
|
+
import { SHOWCASE_FEEDBACK_SURFACE } from '../../__lib__/LegendStudioTelemetryHelper.js';
|
|
65
67
|
|
|
66
68
|
const ShowcaseViewerStatusBar = observer(() => {
|
|
67
69
|
const editorStore = useEditorStore();
|
|
@@ -109,6 +111,14 @@ const ShowcaseViewerStatusBar = observer(() => {
|
|
|
109
111
|
</div>
|
|
110
112
|
</div>
|
|
111
113
|
)}
|
|
114
|
+
{showcase && (
|
|
115
|
+
<ShowcaseFeedback
|
|
116
|
+
className="showcase-feedback--status-bar"
|
|
117
|
+
showcasePath={showcaseStore.showcase.path}
|
|
118
|
+
title={showcase.title}
|
|
119
|
+
surface={SHOWCASE_FEEDBACK_SURFACE.DEEP_LINK_VIEWER}
|
|
120
|
+
/>
|
|
121
|
+
)}
|
|
112
122
|
</div>
|
|
113
123
|
<div className="editor__status-bar__right">
|
|
114
124
|
<button
|
|
@@ -80,6 +80,7 @@ import {
|
|
|
80
80
|
import { Project } from '@finos/legend-server-sdlc';
|
|
81
81
|
import { WorkspaceSetupStore } from '../../stores/workspace-setup/WorkspaceSetupStore.js';
|
|
82
82
|
import { openShowcaseManager } from '../../stores/ShowcaseManagerState.js';
|
|
83
|
+
import { SHOWCASE_MANAGER_ENTRY_POINT } from '../../__lib__/LegendStudioTelemetryHelper.js';
|
|
83
84
|
|
|
84
85
|
const WorkspaceSetupStoreContext = createContext<
|
|
85
86
|
WorkspaceSetupStore | undefined
|
|
@@ -151,7 +152,11 @@ export const ShowcaseCard: React.FC<{ hideDocumentation?: boolean }> = (
|
|
|
151
152
|
<OpenIcon />
|
|
152
153
|
</div>
|
|
153
154
|
),
|
|
154
|
-
action: () =>
|
|
155
|
+
action: () =>
|
|
156
|
+
openShowcaseManager(
|
|
157
|
+
applicationStore,
|
|
158
|
+
SHOWCASE_MANAGER_ENTRY_POINT.WORKSPACE_SETUP,
|
|
159
|
+
),
|
|
155
160
|
},
|
|
156
161
|
]}
|
|
157
162
|
isStable={true}
|
|
@@ -159,6 +159,7 @@ export class LegendStudioBaseStore {
|
|
|
159
159
|
serverUrl: this.applicationStore.config.sdlcServerUrl,
|
|
160
160
|
baseHeaders: this.applicationStore.config.sdlcServerBaseHeaders,
|
|
161
161
|
client: this.applicationStore.config.sdlcServerClient,
|
|
162
|
+
useCookieAuthOnly: this.applicationStore.config.sdlcUseCookieAuthOnly,
|
|
162
163
|
// On a mid-session 401, auto-launch the popup re-auth flow. The
|
|
163
164
|
// handler enforces a one-attempt-per-episode guard to prevent endless
|
|
164
165
|
// retry loops; when it gives up, the StatusBar manual button remains
|