@finos/legend-extension-dsl-data-space 10.0.5 → 10.0.7

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.
Files changed (34) hide show
  1. package/lib/components/DataSpaceDescription.js +1 -1
  2. package/lib/components/DataSpaceDescription.js.map +1 -1
  3. package/lib/components/DataSpaceDiagramViewer.js +1 -1
  4. package/lib/components/DataSpaceDiagramViewer.js.map +1 -1
  5. package/lib/components/DataSpaceModelsDocumentation.js +1 -1
  6. package/lib/components/DataSpaceModelsDocumentation.js.map +1 -1
  7. package/lib/components/DataSpaceQuickStart.d.ts.map +1 -1
  8. package/lib/components/DataSpaceQuickStart.js +1 -1
  9. package/lib/components/DataSpaceQuickStart.js.map +1 -1
  10. package/lib/components/DataSpaceWiki.d.ts.map +1 -1
  11. package/lib/components/DataSpaceWiki.js +14 -5
  12. package/lib/components/DataSpaceWiki.js.map +1 -1
  13. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.d.ts +1 -1
  14. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.d.ts.map +1 -1
  15. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.js +2 -2
  16. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.js.map +1 -1
  17. package/lib/index.css +2 -2
  18. package/lib/index.css.map +1 -1
  19. package/lib/package.json +3 -3
  20. package/lib/stores/DataSpaceViewerState.d.ts +11 -6
  21. package/lib/stores/DataSpaceViewerState.d.ts.map +1 -1
  22. package/lib/stores/DataSpaceViewerState.js +96 -24
  23. package/lib/stores/DataSpaceViewerState.js.map +1 -1
  24. package/lib/stores/studio/DataSpacePreviewState.js +2 -2
  25. package/lib/stores/studio/DataSpacePreviewState.js.map +1 -1
  26. package/package.json +15 -15
  27. package/src/components/DataSpaceDescription.tsx +1 -1
  28. package/src/components/DataSpaceDiagramViewer.tsx +1 -1
  29. package/src/components/DataSpaceModelsDocumentation.tsx +1 -1
  30. package/src/components/DataSpaceQuickStart.tsx +14 -12
  31. package/src/components/DataSpaceWiki.tsx +16 -5
  32. package/src/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.ts +3 -2
  33. package/src/stores/DataSpaceViewerState.ts +135 -28
  34. package/src/stores/studio/DataSpacePreviewState.ts +2 -2
@@ -30,6 +30,7 @@ import type {
30
30
  PackageableRuntime,
31
31
  } from '@finos/legend-graph';
32
32
  import {
33
+ getNonNullableEnry,
33
34
  getNullableEntry,
34
35
  getNullableFirstEntry,
35
36
  guaranteeNonNullable,
@@ -75,6 +76,8 @@ const generateAnchorChunk = (text: string): string =>
75
76
  );
76
77
  export const generateAnchorForActivity = (activity: string): string =>
77
78
  generateAnchorChunk(activity);
79
+ export const extractActivityFromAnchor = (anchor: string): string =>
80
+ decodeURIComponent(anchor);
78
81
  export const generateAnchorForQuickStart = (
79
82
  quickStart: DataSpaceExecutableAnalysisResult,
80
83
  ): string =>
@@ -104,7 +107,6 @@ const DATA_SPACE_WIKI_PAGE_ANCHORS = DATA_SPACE_WIKI_PAGE_SECTIONS.map(
104
107
 
105
108
  type DataSpacePageNavigationCommand = {
106
109
  anchor: string;
107
- useSmoothScroll?: boolean;
108
110
  };
109
111
 
110
112
  class DataSpaceLayoutState {
@@ -117,25 +119,35 @@ class DataSpaceLayoutState {
117
119
  header?: HTMLElement | undefined;
118
120
  isTopScrollerVisible = false;
119
121
 
120
- wikiPageAnchorIndex = new Map<string, HTMLElement>();
121
- wikiNavigationCommand?: DataSpacePageNavigationCommand | undefined;
122
+ private wikiPageAnchorIndex = new Map<string, HTMLElement>();
123
+ wikiPageNavigationCommand?: DataSpacePageNavigationCommand | undefined;
124
+ private wikiPageVisibleAnchors: string[] = [];
125
+ private wikiPageScrollIntersectionObserver?: IntersectionObserver | undefined;
122
126
 
123
127
  constructor(dataSpaceViewerState: DataSpaceViewerState) {
124
- makeObservable(this, {
128
+ makeObservable<
129
+ DataSpaceLayoutState,
130
+ | 'wikiPageAnchorIndex'
131
+ | 'wikiPageVisibleAnchors'
132
+ | 'updatePageVisibleAnchors'
133
+ >(this, {
125
134
  currentNavigationZone: observable,
126
135
  isExpandedModeEnabled: observable,
127
136
  isTopScrollerVisible: observable,
128
137
  wikiPageAnchorIndex: observable,
138
+ wikiPageVisibleAnchors: observable,
129
139
  frame: observable.ref,
130
- wikiNavigationCommand: observable.ref,
131
- isAllWikiPageFullyRendered: computed,
140
+ wikiPageNavigationCommand: observable.ref,
141
+ isWikiPageFullyRendered: computed,
142
+ registerWikiPageScrollObserver: action,
132
143
  setCurrentNavigationZone: action,
133
144
  enableExpandedMode: action,
134
145
  setFrame: action,
135
146
  setTopScrollerVisible: action,
136
147
  setWikiPageAnchor: action,
137
148
  unsetWikiPageAnchor: action,
138
- setWikiAnchorToNavigate: action,
149
+ setWikiPageAnchorToNavigate: action,
150
+ updatePageVisibleAnchors: action,
139
151
  });
140
152
 
141
153
  this.dataSpaceViewerState = dataSpaceViewerState;
@@ -145,8 +157,9 @@ class DataSpaceLayoutState {
145
157
  this.currentNavigationZone = val;
146
158
  }
147
159
 
148
- get isAllWikiPageFullyRendered(): boolean {
160
+ get isWikiPageFullyRendered(): boolean {
149
161
  return (
162
+ Boolean(this.frame) &&
150
163
  DATA_SPACE_WIKI_PAGE_SECTIONS.includes(
151
164
  this.dataSpaceViewerState.currentActivity,
152
165
  ) &&
@@ -157,6 +170,98 @@ class DataSpaceLayoutState {
157
170
  );
158
171
  }
159
172
 
173
+ registerWikiPageScrollObserver(): void {
174
+ if (this.frame && this.isWikiPageFullyRendered) {
175
+ const wikiPageIntersectionObserver = new IntersectionObserver(
176
+ (entries, observer) => {
177
+ const anchorsWithVisibilityChanged = entries
178
+ .map((entry) => {
179
+ for (const [key, element] of this.wikiPageAnchorIndex.entries()) {
180
+ if (element === entry.target) {
181
+ return { key, isIntersecting: entry.isIntersecting };
182
+ }
183
+ }
184
+ return undefined;
185
+ })
186
+ .filter(isNonNullable);
187
+ anchorsWithVisibilityChanged.forEach((entry) => {
188
+ this.updatePageVisibleAnchors(entry.key, entry.isIntersecting);
189
+ });
190
+ // NOTE: sync scroll with menu/address is quite a delicate piece of work
191
+ // as it interferes with programatic scroll operations we do elsewhere.
192
+ // This is particularly bad when we do a programatic `smooth` scroll, which
193
+ // mimic user scrolling behavior and would tangle up with this observer
194
+ // Since currently, there's no good mechanism to detect scroll end event, and as such,
195
+ // there is no good way to temporarily disable this logic while doing the programmatic
196
+ // smooth scroll as such, we avoid supporting programatic smooth scrolling for now
197
+ // See https://github.com/w3c/csswg-drafts/issues/3744
198
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Document/scrollend_event
199
+ if (
200
+ // if current navigation zone is not set, do not update zone
201
+ this.currentNavigationZone === '' ||
202
+ // if there is no visible anchors, do not update zone
203
+ !this.wikiPageVisibleAnchors.length ||
204
+ // if some of the current visible anchors match or is parent section of the current
205
+ // navigation zone, do not update zone
206
+ this.wikiPageVisibleAnchors.some(
207
+ (visibleAnchor) =>
208
+ this.currentNavigationZone === visibleAnchor ||
209
+ this.currentNavigationZone.startsWith(
210
+ `${visibleAnchor}${NAVIGATION_ZONE_SEPARATOR}`,
211
+ ),
212
+ )
213
+ ) {
214
+ return;
215
+ }
216
+ const anchor = getNonNullableEnry(this.wikiPageVisibleAnchors, 0);
217
+ this.dataSpaceViewerState.syncZoneWithNavigation(anchor);
218
+ const anchorChunks = anchor.split(NAVIGATION_ZONE_SEPARATOR);
219
+ const activity = getNullableFirstEntry(anchorChunks);
220
+ if (activity) {
221
+ this.dataSpaceViewerState.setCurrentActivity(
222
+ extractActivityFromAnchor(
223
+ activity,
224
+ ) as DATA_SPACE_VIEWER_ACTIVITY_MODE,
225
+ );
226
+ }
227
+ },
228
+ {
229
+ root: this.frame,
230
+ threshold: 0.5,
231
+ },
232
+ );
233
+ Array.from(this.wikiPageAnchorIndex.values()).forEach((el) =>
234
+ wikiPageIntersectionObserver.observe(el),
235
+ );
236
+ this.wikiPageScrollIntersectionObserver = wikiPageIntersectionObserver;
237
+ }
238
+ }
239
+
240
+ unregisterWikiPageScrollObserver(): void {
241
+ this.wikiPageScrollIntersectionObserver?.disconnect();
242
+ this.wikiPageScrollIntersectionObserver = undefined;
243
+ this.wikiPageVisibleAnchors = [];
244
+ }
245
+
246
+ private updatePageVisibleAnchors(
247
+ changedAnchor: string,
248
+ isIntersecting: boolean,
249
+ ): void {
250
+ if (isIntersecting) {
251
+ const anchors = this.wikiPageVisibleAnchors.filter(
252
+ (anchor) => changedAnchor !== anchor,
253
+ );
254
+ // NOTE: the newly visible anchors should be the furthest one in
255
+ // the direction of scroll
256
+ anchors.push(changedAnchor);
257
+ this.wikiPageVisibleAnchors = anchors;
258
+ } else {
259
+ this.wikiPageVisibleAnchors = this.wikiPageVisibleAnchors.filter(
260
+ (anchor) => changedAnchor !== anchor,
261
+ );
262
+ }
263
+ }
264
+
160
265
  enableExpandedMode(val: boolean): void {
161
266
  this.isExpandedModeEnabled = val;
162
267
  }
@@ -180,32 +285,39 @@ class DataSpaceLayoutState {
180
285
  this.wikiPageAnchorIndex.delete(anchorKey);
181
286
  }
182
287
 
183
- setWikiAnchorToNavigate(
288
+ setWikiPageAnchorToNavigate(
184
289
  val: DataSpacePageNavigationCommand | undefined,
185
290
  ): void {
186
- this.wikiNavigationCommand = val;
291
+ this.wikiPageNavigationCommand = val;
187
292
  }
188
293
 
189
- navigateWikiAnchor(): void {
190
- if (this.wikiNavigationCommand && this.isAllWikiPageFullyRendered) {
191
- const anchor = this.wikiNavigationCommand.anchor;
294
+ navigateWikiPageAnchor(): void {
295
+ if (
296
+ this.frame &&
297
+ this.wikiPageNavigationCommand &&
298
+ this.isWikiPageFullyRendered
299
+ ) {
300
+ const anchor = this.wikiPageNavigationCommand.anchor;
192
301
  const matchingWikiPageSection = this.wikiPageAnchorIndex.get(anchor);
193
302
  const anchorChunks = anchor.split(NAVIGATION_ZONE_SEPARATOR);
194
303
  if (matchingWikiPageSection) {
195
- this.frame?.scrollTo({
196
- top:
197
- matchingWikiPageSection.offsetTop -
198
- (this.header?.getBoundingClientRect().height ?? 0),
199
- behavior: this.wikiNavigationCommand.useSmoothScroll
200
- ? 'smooth'
201
- : 'auto',
202
- });
304
+ this.frame.scrollTop =
305
+ matchingWikiPageSection.offsetTop -
306
+ (this.header?.getBoundingClientRect().height ?? 0);
203
307
  } else if (
204
308
  getNullableFirstEntry(anchorChunks) ===
205
309
  generateAnchorForActivity(
206
310
  DATA_SPACE_VIEWER_ACTIVITY_MODE.DIAGRAM_VIEWER,
207
311
  )
208
312
  ) {
313
+ this.frame.scrollTop =
314
+ guaranteeNonNullable(
315
+ this.wikiPageAnchorIndex.get(
316
+ generateAnchorForActivity(
317
+ DATA_SPACE_VIEWER_ACTIVITY_MODE.DIAGRAM_VIEWER,
318
+ ),
319
+ ),
320
+ ).offsetTop - (this.header?.getBoundingClientRect().height ?? 0);
209
321
  const matchingDiagram =
210
322
  this.dataSpaceViewerState.dataSpaceAnalysisResult.diagrams.find(
211
323
  (diagram) => generateAnchorForDiagram(diagram) === anchor,
@@ -215,7 +327,7 @@ class DataSpaceLayoutState {
215
327
  }
216
328
  }
217
329
 
218
- this.setWikiAnchorToNavigate(undefined);
330
+ this.setWikiPageAnchorToNavigate(undefined);
219
331
  }
220
332
  }
221
333
  }
@@ -426,13 +538,8 @@ export class DataSpaceViewerState {
426
538
  );
427
539
  if (activityChunk && matchingActivity) {
428
540
  if (DATA_SPACE_WIKI_PAGE_SECTIONS.includes(matchingActivity)) {
429
- this.layoutState.setWikiAnchorToNavigate({
541
+ this.layoutState.setWikiPageAnchorToNavigate({
430
542
  anchor: zone,
431
- // NOTE: if we are already on the wiki page, use smooth scroll to suggest the scrollability of the page
432
- // if we are navigating from a different section, go directly to the section within the page to avoid the wait
433
- useSmoothScroll: DATA_SPACE_WIKI_PAGE_SECTIONS.includes(
434
- this.currentActivity,
435
- ),
436
543
  });
437
544
  }
438
545
  this.setCurrentActivity(matchingActivity);
@@ -31,7 +31,7 @@ import type { DataSpace } from '../../graph/metamodel/pure/model/packageableElem
31
31
  import type { DataSpaceAnalysisResult } from '../../graph-manager/action/analytics/DataSpaceAnalysis.js';
32
32
  import { DSL_DataSpace_getGraphManagerExtension } from '../../graph-manager/protocol/pure/DSL_DataSpace_PureGraphManagerExtension.js';
33
33
  import { DataSpaceViewerState } from '../DataSpaceViewerState.js';
34
- import { LiveGraphData } from '@finos/legend-graph';
34
+ import { InMemoryGraphData } from '@finos/legend-graph';
35
35
 
36
36
  export class DataSpacePreviewState extends EditorExtensionState {
37
37
  readonly editorStore: EditorStore;
@@ -118,7 +118,7 @@ export class DataSpacePreviewState extends EditorExtensionState {
118
118
  analysisResult,
119
119
  {
120
120
  retriveGraphData: () =>
121
- new LiveGraphData(this.editorStore.graphManagerState.graph),
121
+ new InMemoryGraphData(this.editorStore.graphManagerState.graph),
122
122
  viewProject: () => {
123
123
  this.editorStore.applicationStore.notificationService.notifyWarning(
124
124
  'This feature is not supported in preview mode',