@finos/legend-extension-dsl-data-space 10.0.2 → 10.0.4

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 (67) hide show
  1. package/lib/components/DataSpaceDataAccess.d.ts.map +1 -1
  2. package/lib/components/DataSpaceDataAccess.js +11 -3
  3. package/lib/components/DataSpaceDataAccess.js.map +1 -1
  4. package/lib/components/DataSpaceDescription.d.ts +1 -1
  5. package/lib/components/DataSpaceDescription.d.ts.map +1 -1
  6. package/lib/components/DataSpaceDescription.js +8 -3
  7. package/lib/components/DataSpaceDescription.js.map +1 -1
  8. package/lib/components/DataSpaceDiagramViewer.d.ts +1 -1
  9. package/lib/components/DataSpaceDiagramViewer.d.ts.map +1 -1
  10. package/lib/components/DataSpaceDiagramViewer.js +22 -6
  11. package/lib/components/DataSpaceDiagramViewer.js.map +1 -1
  12. package/lib/components/DataSpaceModelsDocumentation.d.ts.map +1 -1
  13. package/lib/components/DataSpaceModelsDocumentation.js +11 -3
  14. package/lib/components/DataSpaceModelsDocumentation.js.map +1 -1
  15. package/lib/components/DataSpaceQuickStart.d.ts.map +1 -1
  16. package/lib/components/DataSpaceQuickStart.js +75 -61
  17. package/lib/components/DataSpaceQuickStart.js.map +1 -1
  18. package/lib/components/DataSpaceViewer.d.ts.map +1 -1
  19. package/lib/components/DataSpaceViewer.js +36 -14
  20. package/lib/components/DataSpaceViewer.js.map +1 -1
  21. package/lib/components/DataSpaceViewerActivityBar.d.ts.map +1 -1
  22. package/lib/components/DataSpaceViewerActivityBar.js +6 -7
  23. package/lib/components/DataSpaceViewerActivityBar.js.map +1 -1
  24. package/lib/components/DataSpaceWiki.d.ts.map +1 -1
  25. package/lib/components/DataSpaceWiki.js +11 -0
  26. package/lib/components/DataSpaceWiki.js.map +1 -1
  27. package/lib/graph-manager/action/analytics/DataSpaceAnalysis.d.ts +3 -1
  28. package/lib/graph-manager/action/analytics/DataSpaceAnalysis.d.ts.map +1 -1
  29. package/lib/graph-manager/action/analytics/DataSpaceAnalysis.js +3 -0
  30. package/lib/graph-manager/action/analytics/DataSpaceAnalysis.js.map +1 -1
  31. package/lib/graph-manager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.d.ts.map +1 -1
  32. package/lib/graph-manager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.js +7 -4
  33. package/lib/graph-manager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.js.map +1 -1
  34. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.d.ts +4 -5
  35. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.d.ts.map +1 -1
  36. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.js +64 -62
  37. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.js.map +1 -1
  38. package/lib/index.css +2 -2
  39. package/lib/index.css.map +1 -1
  40. package/lib/package.json +1 -1
  41. package/lib/stores/DSL_DataSpace_LegendApplicationPlugin_Extension.d.ts +1 -0
  42. package/lib/stores/DSL_DataSpace_LegendApplicationPlugin_Extension.d.ts.map +1 -1
  43. package/lib/stores/DataSpaceModelsDocumentationState.d.ts.map +1 -1
  44. package/lib/stores/DataSpaceModelsDocumentationState.js +1 -1
  45. package/lib/stores/DataSpaceModelsDocumentationState.js.map +1 -1
  46. package/lib/stores/DataSpaceViewerState.d.ts +38 -15
  47. package/lib/stores/DataSpaceViewerState.d.ts.map +1 -1
  48. package/lib/stores/DataSpaceViewerState.js +132 -62
  49. package/lib/stores/DataSpaceViewerState.js.map +1 -1
  50. package/lib/stores/query/DataSpaceQueryBuilderState.js +2 -2
  51. package/lib/stores/query/DataSpaceQueryBuilderState.js.map +1 -1
  52. package/package.json +13 -13
  53. package/src/components/DataSpaceDataAccess.tsx +27 -5
  54. package/src/components/DataSpaceDescription.tsx +22 -5
  55. package/src/components/DataSpaceDiagramViewer.tsx +49 -15
  56. package/src/components/DataSpaceModelsDocumentation.tsx +29 -5
  57. package/src/components/DataSpaceQuickStart.tsx +223 -211
  58. package/src/components/DataSpaceViewer.tsx +66 -12
  59. package/src/components/DataSpaceViewerActivityBar.tsx +6 -3
  60. package/src/components/DataSpaceWiki.tsx +14 -0
  61. package/src/graph-manager/action/analytics/DataSpaceAnalysis.ts +4 -0
  62. package/src/graph-manager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.ts +15 -3
  63. package/src/graph-manager/protocol/pure/v1/engine/analytics/V1_DataSpaceAnalysis.ts +112 -89
  64. package/src/stores/DSL_DataSpace_LegendApplicationPlugin_Extension.ts +5 -0
  65. package/src/stores/DataSpaceModelsDocumentationState.ts +1 -1
  66. package/src/stores/DataSpaceViewerState.ts +193 -73
  67. package/src/stores/query/DataSpaceQueryBuilderState.ts +2 -2
@@ -24,7 +24,12 @@ import {
24
24
  QuestionCircleIcon,
25
25
  clsx,
26
26
  } from '@finos/legend-art';
27
- import { type DataSpaceViewerState } from '../stores/DataSpaceViewerState.js';
27
+ import {
28
+ DATA_SPACE_VIEWER_ACTIVITY_MODE,
29
+ generateAnchorForActivity,
30
+ type DataSpaceViewerState,
31
+ generateAnchorForQuickStart,
32
+ } from '../stores/DataSpaceViewerState.js';
28
33
  import { useApplicationStore } from '@finos/legend-application';
29
34
  import {
30
35
  DataSpaceExecutableTDSResult,
@@ -33,7 +38,7 @@ import {
33
38
  } from '../graph-manager/action/analytics/DataSpaceAnalysis.js';
34
39
  import { DataSpaceMarkdownTextViewer } from './DataSpaceMarkdownTextViewer.js';
35
40
  import type { DSL_DataSpace_LegendApplicationPlugin_Extension } from '../stores/DSL_DataSpace_LegendApplicationPlugin_Extension.js';
36
- import { useState } from 'react';
41
+ import { useEffect, useRef, useState } from 'react';
37
42
  import { DataSpaceWikiPlaceholder } from './DataSpacePlaceholder.js';
38
43
  import {
39
44
  DataGrid,
@@ -50,8 +55,6 @@ enum TDS_EXECUTABLE_ACTION_TAB {
50
55
  QUERY_TEXT = 'QUERY_TEXT',
51
56
  }
52
57
 
53
- const MIN_NUMBER_OF_ROWS_FOR_AUTO_HEIGHT = 15;
54
-
55
58
  const TDSColumnDocumentationCellRenderer = (
56
59
  params: DataGridCellRendererParams<DataSpaceExecutableTDSResultColumn>,
57
60
  ): React.ReactNode => {
@@ -98,8 +101,6 @@ const DataSpaceExecutableTDSResultView = observer(
98
101
  const queryText = executableAnalysisResult.info?.query;
99
102
 
100
103
  const columnSpecifications = tdsResult.columns;
101
- const autoHeight =
102
- tdsResult.columns.length <= MIN_NUMBER_OF_ROWS_FOR_AUTO_HEIGHT;
103
104
  const extractTDSExecutableActionConfigurations =
104
105
  applicationStore.pluginManager
105
106
  .getApplicationPlugins()
@@ -108,6 +109,13 @@ const DataSpaceExecutableTDSResultView = observer(
108
109
  (
109
110
  plugin as DSL_DataSpace_LegendApplicationPlugin_Extension
110
111
  ).getExtraDataSpaceTDSExecutableActionConfigurations?.() ?? [],
112
+ )
113
+ .filter((configuration) =>
114
+ configuration.isSupported(
115
+ dataSpaceViewerState,
116
+ executableAnalysisResult,
117
+ tdsResult,
118
+ ),
111
119
  );
112
120
  const currentTabExtensionConfig =
113
121
  extractTDSExecutableActionConfigurations.find(
@@ -115,226 +123,196 @@ const DataSpaceExecutableTDSResultView = observer(
115
123
  );
116
124
 
117
125
  return (
118
- <div className="data-space__viewer__quickstart__item">
119
- <div className="data-space__viewer__quickstart__item__header">
120
- <div className="data-space__viewer__quickstart__item__header__title">
121
- {executableAnalysisResult.title}
122
- </div>
123
- <div className="data-space__viewer__quickstart__item__header__type">
124
- TDS
125
- </div>
126
- <div className="data-space__viewer__quickstart__item__header__anchor">
127
- <AnchorLinkIcon />
128
- </div>
129
- </div>
130
- {executableAnalysisResult.description !== undefined && (
131
- <div className="data-space__viewer__quickstart__item__description">
132
- <DataSpaceMarkdownTextViewer
133
- value={executableAnalysisResult.description}
134
- />
135
- </div>
136
- )}
137
- <div className="data-space__viewer__quickstart__item__content">
138
- <div className="data-space__viewer__quickstart__item__content__tab__header">
139
- <div className="data-space__viewer__quickstart__item__content__tabs">
126
+ <div className="data-space__viewer__quickstart__item__content">
127
+ <div className="data-space__viewer__quickstart__item__content__tab__header">
128
+ <div className="data-space__viewer__quickstart__item__content__tabs">
129
+ <button
130
+ className={clsx(
131
+ 'data-space__viewer__quickstart__item__content__tab',
132
+ {
133
+ 'data-space__viewer__quickstart__item__content__tab--active':
134
+ selectedTab === TDS_EXECUTABLE_ACTION_TAB.COLUMN_SPECS,
135
+ },
136
+ )}
137
+ tabIndex={-1}
138
+ onClick={() =>
139
+ setSelectedTab(TDS_EXECUTABLE_ACTION_TAB.COLUMN_SPECS)
140
+ }
141
+ >
142
+ <div className="data-space__viewer__quickstart__item__content__tab__label">
143
+ Column Specifications
144
+ </div>
145
+ </button>
146
+ <button
147
+ className={clsx(
148
+ 'data-space__viewer__quickstart__item__content__tab',
149
+ {
150
+ 'data-space__viewer__quickstart__item__content__tab--active':
151
+ selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY,
152
+ },
153
+ )}
154
+ tabIndex={-1}
155
+ onClick={() => setSelectedTab(TDS_EXECUTABLE_ACTION_TAB.QUERY)}
156
+ >
157
+ <div className="data-space__viewer__quickstart__item__content__tab__icon">
158
+ <LegendLogo className="data-space__viewer__quickstart__item__content__tab__icon--query" />
159
+ </div>
160
+ <div className="data-space__viewer__quickstart__item__content__tab__label">
161
+ Query
162
+ </div>
163
+ </button>
164
+ {extractTDSExecutableActionConfigurations.map((config) => (
140
165
  <button
166
+ key={config.key}
141
167
  className={clsx(
142
168
  'data-space__viewer__quickstart__item__content__tab',
143
169
  {
144
170
  'data-space__viewer__quickstart__item__content__tab--active':
145
- selectedTab === TDS_EXECUTABLE_ACTION_TAB.COLUMN_SPECS,
171
+ selectedTab === config.key,
146
172
  },
147
173
  )}
148
174
  tabIndex={-1}
149
- onClick={() =>
150
- setSelectedTab(TDS_EXECUTABLE_ACTION_TAB.COLUMN_SPECS)
151
- }
175
+ onClick={() => setSelectedTab(config.key)}
152
176
  >
177
+ {config.icon !== undefined && (
178
+ <div className="data-space__viewer__quickstart__item__content__tab__icon">
179
+ {config.icon}
180
+ </div>
181
+ )}
153
182
  <div className="data-space__viewer__quickstart__item__content__tab__label">
154
- Column Specifications
183
+ {config.title}
155
184
  </div>
156
185
  </button>
157
- <button
158
- className={clsx(
159
- 'data-space__viewer__quickstart__item__content__tab',
186
+ ))}
187
+ </div>
188
+ {queryText !== undefined && (
189
+ <button
190
+ className={clsx(
191
+ 'data-space__viewer__quickstart__item__content__tab',
192
+ {
193
+ 'data-space__viewer__quickstart__item__content__tab--active':
194
+ selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY_TEXT,
195
+ },
196
+ )}
197
+ tabIndex={-1}
198
+ onClick={() =>
199
+ setSelectedTab(TDS_EXECUTABLE_ACTION_TAB.QUERY_TEXT)
200
+ }
201
+ >
202
+ <div className="data-space__viewer__quickstart__item__content__tab__icon">
203
+ <CodeIcon className="data-space__viewer__quickstart__item__content__tab__icon--query" />
204
+ </div>
205
+ </button>
206
+ )}
207
+ </div>
208
+ <div className="data-space__viewer__quickstart__item__content__tab__content">
209
+ {selectedTab === TDS_EXECUTABLE_ACTION_TAB.COLUMN_SPECS && (
210
+ <div className="data-space__viewer__quickstart__tds__column-specs data-space__viewer__grid ag-theme-balham-dark">
211
+ <DataGrid
212
+ rowData={columnSpecifications}
213
+ gridOptions={{
214
+ suppressScrollOnNewData: true,
215
+ getRowId: (rowData) => rowData.data.uuid,
216
+ }}
217
+ suppressFieldDotNotation={true}
218
+ columnDefs={[
160
219
  {
161
- 'data-space__viewer__quickstart__item__content__tab--active':
162
- selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY,
220
+ minWidth: 50,
221
+ sortable: true,
222
+ resizable: true,
223
+ field: 'name',
224
+ headerValueGetter: () =>
225
+ `Column ${
226
+ columnSpecifications.length
227
+ ? ` (${columnSpecifications.length})`
228
+ : ''
229
+ }`,
230
+ flex: 1,
163
231
  },
164
- )}
165
- tabIndex={-1}
166
- onClick={() => setSelectedTab(TDS_EXECUTABLE_ACTION_TAB.QUERY)}
167
- >
168
- <div className="data-space__viewer__quickstart__item__content__tab__icon">
169
- <LegendLogo className="data-space__viewer__quickstart__item__content__tab__icon--query" />
170
- </div>
171
- <div className="data-space__viewer__quickstart__item__content__tab__label">
172
- Query
173
- </div>
174
- </button>
175
- {extractTDSExecutableActionConfigurations.map((config) => (
232
+ {
233
+ minWidth: 50,
234
+ sortable: false,
235
+ resizable: true,
236
+ cellRenderer: TDSColumnDocumentationCellRenderer,
237
+ headerName: 'Documentation',
238
+ flex: 1,
239
+ wrapText: true,
240
+ autoHeight: true,
241
+ },
242
+ {
243
+ minWidth: 50,
244
+ sortable: false,
245
+ resizable: false,
246
+ headerClass: 'data-space__viewer__grid__last-column-header',
247
+ cellRenderer: TDSColumnSampleValuesCellRenderer,
248
+ headerName: 'Sample Values',
249
+ flex: 1,
250
+ },
251
+ ]}
252
+ />
253
+ </div>
254
+ )}
255
+ {selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY && (
256
+ <div className="data-space__viewer__quickstart__tds__query">
257
+ <div className="data-space__viewer__quickstart__tds__query__actions">
258
+ <button
259
+ className="data-space__viewer__quickstart__tds__query__action btn--dark"
260
+ tabIndex={-1}
261
+ onClick={() => {
262
+ // TODO: wire this so we can go to the query for the service
263
+ }}
264
+ >
265
+ Open in Query
266
+ </button>
176
267
  <button
177
- key={config.key}
178
- className={clsx(
179
- 'data-space__viewer__quickstart__item__content__tab',
180
- {
181
- 'data-space__viewer__quickstart__item__content__tab--active':
182
- selectedTab === config.key,
183
- },
184
- )}
268
+ className="data-space__viewer__quickstart__tds__query__action btn--dark"
185
269
  tabIndex={-1}
186
- onClick={() => setSelectedTab(config.key)}
270
+ disabled={true}
187
271
  >
188
- {config.icon !== undefined && (
189
- <div className="data-space__viewer__quickstart__item__content__tab__icon">
190
- {config.icon}
191
- </div>
192
- )}
193
- <div className="data-space__viewer__quickstart__item__content__tab__label">
194
- {config.title}
195
- </div>
272
+ Open in Query with Test Data
196
273
  </button>
197
- ))}
274
+ </div>
198
275
  </div>
199
- {queryText !== undefined && (
200
- <button
201
- className={clsx(
202
- 'data-space__viewer__quickstart__item__content__tab',
203
- {
204
- 'data-space__viewer__quickstart__item__content__tab--active':
205
- selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY_TEXT,
206
- },
207
- )}
208
- tabIndex={-1}
209
- onClick={() =>
210
- setSelectedTab(TDS_EXECUTABLE_ACTION_TAB.QUERY_TEXT)
211
- }
212
- >
213
- <div className="data-space__viewer__quickstart__item__content__tab__icon">
214
- <CodeIcon className="data-space__viewer__quickstart__item__content__tab__icon--query" />
276
+ )}
277
+ {selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY_TEXT &&
278
+ queryText !== undefined && (
279
+ <div className="data-space__viewer__quickstart__tds__query-text">
280
+ <div className="data-space__viewer__quickstart__tds__query-text__content">
281
+ <CodeEditor
282
+ inputValue={queryText}
283
+ isReadOnly={true}
284
+ language={CODE_EDITOR_LANGUAGE.PURE}
285
+ showMiniMap={false}
286
+ hideGutter={true}
287
+ />
215
288
  </div>
216
- </button>
217
- )}
218
- </div>
219
- <div
220
- className={clsx(
221
- 'data-space__viewer__quickstart__item__content__tab__content',
222
- {
223
- 'data-space__viewer__quickstart__item__content__tab__content':
224
- autoHeight,
225
- },
226
- )}
227
- >
228
- {selectedTab === TDS_EXECUTABLE_ACTION_TAB.COLUMN_SPECS && (
229
- <div className="data-space__viewer__quickstart__tds__column-specs data-space__viewer__grid ag-theme-balham-dark">
230
- <DataGrid
231
- domLayout={autoHeight ? 'autoHeight' : 'normal'}
232
- rowData={columnSpecifications}
233
- gridOptions={{
234
- suppressScrollOnNewData: true,
235
- getRowId: (rowData) => rowData.data.uuid,
236
- }}
237
- suppressFieldDotNotation={true}
238
- columnDefs={[
239
- {
240
- minWidth: 50,
241
- sortable: true,
242
- resizable: true,
243
- field: 'name',
244
- headerValueGetter: () =>
245
- `Column ${
246
- columnSpecifications.length
247
- ? ` (${columnSpecifications.length})`
248
- : ''
249
- }`,
250
- flex: 1,
251
- },
252
- {
253
- minWidth: 50,
254
- sortable: false,
255
- resizable: true,
256
- cellRenderer: TDSColumnDocumentationCellRenderer,
257
- headerName: 'Documentation',
258
- flex: 1,
259
- wrapText: true,
260
- autoHeight: true,
261
- },
262
- {
263
- minWidth: 50,
264
- sortable: false,
265
- resizable: false,
266
- headerClass:
267
- 'data-space__viewer__grid__last-column-header',
268
- cellRenderer: TDSColumnSampleValuesCellRenderer,
269
- headerName: 'Sample Values',
270
- flex: 1,
271
- },
272
- ]}
273
- />
274
- </div>
275
- )}
276
- {selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY && (
277
- <div className="data-space__viewer__quickstart__tds__query">
278
- <div className="data-space__viewer__quickstart__tds__query__actions">
289
+ <div className="data-space__viewer__quickstart__tds__query-text__actions">
279
290
  <button
280
- className="data-space__viewer__quickstart__tds__query__action btn--dark"
291
+ className="data-space__viewer__quickstart__tds__query-text__action"
281
292
  tabIndex={-1}
293
+ title="Copy"
282
294
  onClick={() => {
283
- // TODO: wire this so we can go to the query for the service
295
+ applicationStore.clipboardService
296
+ .copyTextToClipboard(queryText)
297
+ .catch(applicationStore.alertUnhandledError);
284
298
  }}
285
299
  >
286
- Open in Query
300
+ <CopyIcon />
287
301
  </button>
288
302
  <button
289
- className="data-space__viewer__quickstart__tds__query__action btn--dark"
303
+ className="data-space__viewer__quickstart__tds__query-text__action"
290
304
  tabIndex={-1}
291
- disabled={true}
292
305
  >
293
- Open in Query with Test Data
306
+ <MoreVerticalIcon />
294
307
  </button>
295
308
  </div>
296
309
  </div>
297
310
  )}
298
- {selectedTab === TDS_EXECUTABLE_ACTION_TAB.QUERY_TEXT &&
299
- queryText !== undefined && (
300
- <div className="data-space__viewer__quickstart__tds__query-text">
301
- <div className="data-space__viewer__quickstart__tds__query-text__content">
302
- <CodeEditor
303
- inputValue={queryText}
304
- isReadOnly={true}
305
- language={CODE_EDITOR_LANGUAGE.PURE}
306
- showMiniMap={false}
307
- hideGutter={true}
308
- />
309
- </div>
310
- <div className="data-space__viewer__quickstart__tds__query-text__actions">
311
- <button
312
- className="data-space__viewer__quickstart__tds__query-text__action"
313
- tabIndex={-1}
314
- title="Copy"
315
- onClick={() => {
316
- applicationStore.clipboardService
317
- .copyTextToClipboard(queryText)
318
- .catch(applicationStore.alertUnhandledError);
319
- }}
320
- >
321
- <CopyIcon />
322
- </button>
323
- <button
324
- className="data-space__viewer__quickstart__tds__query-text__action"
325
- tabIndex={-1}
326
- >
327
- <MoreVerticalIcon />
328
- </button>
329
- </div>
330
- </div>
331
- )}
332
- {currentTabExtensionConfig?.renderer(
333
- dataSpaceViewerState,
334
- executableAnalysisResult,
335
- tdsResult,
336
- )}
337
- </div>
311
+ {currentTabExtensionConfig?.renderer(
312
+ dataSpaceViewerState,
313
+ executableAnalysisResult,
314
+ tdsResult,
315
+ )}
338
316
  </div>
339
317
  </div>
340
318
  );
@@ -347,30 +325,38 @@ const DataSpaceExecutableAnalysisResultView = observer(
347
325
  executableAnalysisResult: DataSpaceExecutableAnalysisResult;
348
326
  }) => {
349
327
  const { dataSpaceViewerState, executableAnalysisResult } = props;
328
+ const quickStartRef = useRef<HTMLDivElement>(null);
329
+ const anchor = generateAnchorForQuickStart(executableAnalysisResult);
330
+
331
+ useEffect(() => {
332
+ if (quickStartRef.current) {
333
+ dataSpaceViewerState.layoutState.setWikiPageAnchor(
334
+ anchor,
335
+ quickStartRef.current,
336
+ );
337
+ }
338
+ return () => dataSpaceViewerState.layoutState.unsetWikiPageAnchor(anchor);
339
+ }, [dataSpaceViewerState, anchor]);
350
340
 
351
- if (
352
- executableAnalysisResult.result instanceof DataSpaceExecutableTDSResult
353
- ) {
354
- return (
355
- <DataSpaceExecutableTDSResultView
356
- dataSpaceViewerState={dataSpaceViewerState}
357
- executableAnalysisResult={executableAnalysisResult}
358
- tdsResult={executableAnalysisResult.result}
359
- />
360
- );
361
- }
362
341
  return (
363
- <div className="data-space__viewer__quickstart__item">
342
+ <div ref={quickStartRef} className="data-space__viewer__quickstart__item">
364
343
  <div className="data-space__viewer__quickstart__item__header">
365
344
  <div className="data-space__viewer__quickstart__item__header__title">
366
345
  {executableAnalysisResult.title}
367
346
  </div>
368
347
  <div className="data-space__viewer__quickstart__item__header__type">
369
- UNKNOWN
348
+ {executableAnalysisResult.result instanceof
349
+ DataSpaceExecutableTDSResult
350
+ ? 'TDS'
351
+ : 'UNKNOWN'}
370
352
  </div>
371
- <div className="data-space__viewer__quickstart__item__header__anchor">
353
+ <button
354
+ className="data-space__viewer__quickstart__item__header__anchor"
355
+ tabIndex={-1}
356
+ onClick={() => dataSpaceViewerState.changeZone(anchor, true)}
357
+ >
372
358
  <AnchorLinkIcon />
373
- </div>
359
+ </button>
374
360
  </div>
375
361
  {executableAnalysisResult.description !== undefined && (
376
362
  <div className="data-space__viewer__quickstart__item__description">
@@ -379,6 +365,14 @@ const DataSpaceExecutableAnalysisResultView = observer(
379
365
  />
380
366
  </div>
381
367
  )}
368
+ {executableAnalysisResult.result instanceof
369
+ DataSpaceExecutableTDSResult && (
370
+ <DataSpaceExecutableTDSResultView
371
+ dataSpaceViewerState={dataSpaceViewerState}
372
+ executableAnalysisResult={executableAnalysisResult}
373
+ tdsResult={executableAnalysisResult.result}
374
+ />
375
+ )}
382
376
  </div>
383
377
  );
384
378
  },
@@ -390,6 +384,20 @@ export const DataSpaceQuickStart = observer(
390
384
  const applicationStore = useApplicationStore();
391
385
  const analysisResult = dataSpaceViewerState.dataSpaceAnalysisResult;
392
386
  const documentationUrl = analysisResult.supportInfo?.documentationUrl;
387
+ const sectionRef = useRef<HTMLDivElement>(null);
388
+ const anchor = generateAnchorForActivity(
389
+ DATA_SPACE_VIEWER_ACTIVITY_MODE.QUICK_START,
390
+ );
391
+
392
+ useEffect(() => {
393
+ if (sectionRef.current) {
394
+ dataSpaceViewerState.layoutState.setWikiPageAnchor(
395
+ anchor,
396
+ sectionRef.current,
397
+ );
398
+ }
399
+ return () => dataSpaceViewerState.layoutState.unsetWikiPageAnchor(anchor);
400
+ }, [dataSpaceViewerState, anchor]);
393
401
 
394
402
  const seeDocumentation = (): void => {
395
403
  if (documentationUrl) {
@@ -400,13 +408,17 @@ export const DataSpaceQuickStart = observer(
400
408
  };
401
409
 
402
410
  return (
403
- <div className="data-space__viewer__wiki__section">
411
+ <div ref={sectionRef} className="data-space__viewer__wiki__section">
404
412
  <div className="data-space__viewer__wiki__section__header">
405
413
  <div className="data-space__viewer__wiki__section__header__label">
406
414
  Quick Start
407
- <div className="data-space__viewer__wiki__section__header__anchor">
415
+ <button
416
+ className="data-space__viewer__wiki__section__header__anchor"
417
+ tabIndex={-1}
418
+ onClick={() => dataSpaceViewerState.changeZone(anchor, true)}
419
+ >
408
420
  <AnchorLinkIcon />
409
- </div>
421
+ </button>
410
422
  </div>
411
423
  {Boolean(documentationUrl) && (
412
424
  <button
@@ -15,17 +15,23 @@
15
15
  */
16
16
 
17
17
  import { observer } from 'mobx-react-lite';
18
- import { BlankPanelContent, VerifiedIcon, clsx } from '@finos/legend-art';
18
+ import {
19
+ BlankPanelContent,
20
+ CaretUpIcon,
21
+ VerifiedIcon,
22
+ clsx,
23
+ } from '@finos/legend-art';
19
24
  import {
20
25
  type DataSpaceViewerState,
21
26
  DATA_SPACE_VIEWER_ACTIVITY_MODE,
27
+ DATA_SPACE_WIKI_PAGE_SECTIONS,
22
28
  } from '../stores/DataSpaceViewerState.js';
23
29
  import { DataSpaceExecutionContextViewer } from './DataSpaceExecutionContextViewer.js';
24
30
  import { DataSpaceInfoPanel } from './DataSpaceInfoPanel.js';
25
31
  import { DataSpaceSupportPanel } from './DataSpaceSupportPanel.js';
26
32
  import { DataSpaceWiki } from './DataSpaceWiki.js';
27
33
  import { DataSpaceViewerActivityBar } from './DataSpaceViewerActivityBar.js';
28
- import { useRef, useState } from 'react';
34
+ import { useEffect, useRef, useState } from 'react';
29
35
 
30
36
  const DataSpaceHeader = observer(
31
37
  (props: {
@@ -33,10 +39,18 @@ const DataSpaceHeader = observer(
33
39
  showFullHeader: boolean;
34
40
  }) => {
35
41
  const { dataSpaceViewerState, showFullHeader } = props;
42
+ const headerRef = useRef<HTMLDivElement>(null);
36
43
  const analysisResult = dataSpaceViewerState.dataSpaceAnalysisResult;
37
44
 
45
+ useEffect(() => {
46
+ if (headerRef.current) {
47
+ dataSpaceViewerState.layoutState.header = headerRef.current;
48
+ }
49
+ }, [dataSpaceViewerState]);
50
+
38
51
  return (
39
52
  <div
53
+ ref={headerRef}
40
54
  className={clsx('data-space__viewer__header', {
41
55
  'data-space__viewer__header--floating': showFullHeader,
42
56
  })}
@@ -80,20 +94,44 @@ const DataSpacePlaceholderPanel: React.FC<{ message: string }> = (props) => {
80
94
  export const DataSpaceViewer = observer(
81
95
  (props: { dataSpaceViewerState: DataSpaceViewerState }) => {
82
96
  const { dataSpaceViewerState } = props;
83
- const bodyElement = useRef<HTMLDivElement>(null);
97
+ const frame = useRef<HTMLDivElement>(null);
84
98
  const [showFullHeader, setShowFullHeader] = useState(false);
99
+ const [scrollPercentage, setScrollPercentage] = useState(0);
85
100
 
86
101
  const onScroll: React.UIEventHandler<HTMLDivElement> = (event) => {
87
- setShowFullHeader(event.currentTarget.scrollTop > 0);
102
+ const scrollTop = event.currentTarget.scrollTop;
103
+ setShowFullHeader(scrollTop > 0);
104
+ dataSpaceViewerState.layoutState.setTopScrollerVisible(scrollTop > 0);
105
+ setScrollPercentage(
106
+ event.currentTarget.scrollHeight <= 0
107
+ ? 100
108
+ : Math.round(
109
+ ((event.currentTarget.scrollTop +
110
+ event.currentTarget.clientHeight) /
111
+ event.currentTarget.scrollHeight) *
112
+ 100,
113
+ ),
114
+ );
88
115
  };
89
116
 
90
- const isShowingWiki = [
91
- DATA_SPACE_VIEWER_ACTIVITY_MODE.DESCRIPTION,
92
- DATA_SPACE_VIEWER_ACTIVITY_MODE.DIAGRAM_VIEWER,
93
- DATA_SPACE_VIEWER_ACTIVITY_MODE.MODELS_DOCUMENTATION,
94
- DATA_SPACE_VIEWER_ACTIVITY_MODE.QUICK_START,
95
- DATA_SPACE_VIEWER_ACTIVITY_MODE.DATA_ACCESS,
96
- ].includes(dataSpaceViewerState.currentActivity);
117
+ const scrollToTop = (): void => {
118
+ if (dataSpaceViewerState.layoutState.frame) {
119
+ dataSpaceViewerState.layoutState.frame.scrollTo({
120
+ top: 0,
121
+ behavior: 'smooth',
122
+ });
123
+ }
124
+ };
125
+
126
+ const isShowingWiki = DATA_SPACE_WIKI_PAGE_SECTIONS.includes(
127
+ dataSpaceViewerState.currentActivity,
128
+ );
129
+
130
+ useEffect(() => {
131
+ if (frame.current) {
132
+ dataSpaceViewerState.layoutState.setFrame(frame.current);
133
+ }
134
+ }, [dataSpaceViewerState]);
97
135
 
98
136
  return (
99
137
  <div className="data-space__viewer">
@@ -101,7 +139,7 @@ export const DataSpaceViewer = observer(
101
139
  dataSpaceViewerState={dataSpaceViewerState}
102
140
  />
103
141
  <div
104
- ref={bodyElement}
142
+ ref={frame}
105
143
  className="data-space__viewer__body"
106
144
  onScroll={onScroll}
107
145
  >
@@ -109,6 +147,22 @@ export const DataSpaceViewer = observer(
109
147
  dataSpaceViewerState={dataSpaceViewerState}
110
148
  showFullHeader={showFullHeader}
111
149
  />
150
+ {dataSpaceViewerState.layoutState.isTopScrollerVisible && (
151
+ <div className="data-space__viewer__scroller">
152
+ <button
153
+ className="data-space__viewer__scroller__btn btn--dark"
154
+ tabIndex={-1}
155
+ title="Scroll to top"
156
+ disabled={!dataSpaceViewerState.layoutState.frame}
157
+ onClick={scrollToTop}
158
+ >
159
+ <CaretUpIcon />
160
+ </button>
161
+ <div className="data-space__viewer__scroller__percentage">
162
+ {scrollPercentage}%
163
+ </div>
164
+ </div>
165
+ )}
112
166
  <div
113
167
  className={clsx('data-space__viewer__frame', {
114
168
  'data-space__viewer__frame--boundless': isShowingWiki,