@finos/legend-extension-dsl-data-space 10.0.6 → 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.
- package/lib/components/DataSpaceDescription.js +1 -1
- package/lib/components/DataSpaceDescription.js.map +1 -1
- package/lib/components/DataSpaceDiagramViewer.js +1 -1
- package/lib/components/DataSpaceDiagramViewer.js.map +1 -1
- package/lib/components/DataSpaceModelsDocumentation.js +1 -1
- package/lib/components/DataSpaceModelsDocumentation.js.map +1 -1
- package/lib/components/DataSpaceQuickStart.d.ts.map +1 -1
- package/lib/components/DataSpaceQuickStart.js +1 -1
- package/lib/components/DataSpaceQuickStart.js.map +1 -1
- package/lib/components/DataSpaceWiki.d.ts.map +1 -1
- package/lib/components/DataSpaceWiki.js +14 -5
- package/lib/components/DataSpaceWiki.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +3 -3
- package/lib/stores/DataSpaceViewerState.d.ts +11 -6
- package/lib/stores/DataSpaceViewerState.d.ts.map +1 -1
- package/lib/stores/DataSpaceViewerState.js +96 -24
- package/lib/stores/DataSpaceViewerState.js.map +1 -1
- package/package.json +15 -15
- package/src/components/DataSpaceDescription.tsx +1 -1
- package/src/components/DataSpaceDiagramViewer.tsx +1 -1
- package/src/components/DataSpaceModelsDocumentation.tsx +1 -1
- package/src/components/DataSpaceQuickStart.tsx +14 -12
- package/src/components/DataSpaceWiki.tsx +16 -5
- package/src/stores/DataSpaceViewerState.ts +135 -28
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
288
|
+
setWikiPageAnchorToNavigate(
|
|
184
289
|
val: DataSpacePageNavigationCommand | undefined,
|
|
185
290
|
): void {
|
|
186
|
-
this.
|
|
291
|
+
this.wikiPageNavigationCommand = val;
|
|
187
292
|
}
|
|
188
293
|
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
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
|
|
196
|
-
|
|
197
|
-
|
|
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.
|
|
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.
|
|
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);
|