@finos/legend-application 8.0.2 → 9.0.1
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/LegendApplicationComponentFrameworkProvider.d.ts +4 -2
- package/lib/components/LegendApplicationComponentFrameworkProvider.d.ts.map +1 -1
- package/lib/components/LegendApplicationComponentFrameworkProvider.js +7 -4
- package/lib/components/LegendApplicationComponentFrameworkProvider.js.map +1 -1
- package/lib/components/NotificationManager.js +1 -1
- package/lib/components/NotificationManager.js.map +1 -1
- package/lib/components/WebApplicationNavigatorProvider.d.ts.map +1 -1
- package/lib/components/WebApplicationNavigatorProvider.js +1 -1
- package/lib/components/WebApplicationNavigatorProvider.js.map +1 -1
- package/lib/components/{shared/execution-plan-viewer → execution-plan-viewer}/ExecutionPlanViewer.d.ts +1 -1
- package/lib/components/execution-plan-viewer/ExecutionPlanViewer.d.ts.map +1 -0
- package/lib/components/{shared/execution-plan-viewer → execution-plan-viewer}/ExecutionPlanViewer.js +3 -3
- package/lib/components/execution-plan-viewer/ExecutionPlanViewer.js.map +1 -0
- package/lib/components/{shared/execution-plan-viewer → execution-plan-viewer}/SQLExecutionNodeViewer.d.ts +1 -1
- package/lib/components/execution-plan-viewer/SQLExecutionNodeViewer.d.ts.map +1 -0
- package/lib/components/{shared/execution-plan-viewer → execution-plan-viewer}/SQLExecutionNodeViewer.js +2 -2
- package/lib/components/execution-plan-viewer/SQLExecutionNodeViewer.js.map +1 -0
- package/lib/components/shared/DocumentationLink.d.ts +5 -0
- package/lib/components/shared/DocumentationLink.d.ts.map +1 -1
- package/lib/components/shared/DocumentationLink.js +12 -2
- package/lib/components/shared/DocumentationLink.js.map +1 -1
- package/lib/components/shared/{PackageableElementOptionRenderer.d.ts → PackageableElementOptionLabel.d.ts} +1 -1
- package/lib/components/shared/PackageableElementOptionLabel.d.ts.map +1 -0
- package/lib/components/shared/{PackageableElementOptionRenderer.js → PackageableElementOptionLabel.js} +5 -5
- package/lib/components/shared/PackageableElementOptionLabel.js.map +1 -0
- package/lib/components/shared/TextInputEditor.d.ts.map +1 -1
- package/lib/components/shared/TextInputEditor.js +1 -2
- package/lib/components/shared/TextInputEditor.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +8 -9
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +8 -9
- package/lib/index.js.map +1 -1
- package/lib/stores/ApplicationStore.d.ts +2 -0
- package/lib/stores/ApplicationStore.d.ts.map +1 -1
- package/lib/stores/ApplicationStore.js +13 -10
- package/lib/stores/ApplicationStore.js.map +1 -1
- package/lib/stores/AssistantService.js +1 -1
- package/lib/stores/AssistantService.js.map +1 -1
- package/lib/stores/{shared/ExecutionPlanState.d.ts → ExecutionPlanState.d.ts} +1 -1
- package/lib/stores/ExecutionPlanState.d.ts.map +1 -0
- package/lib/stores/{shared/ExecutionPlanState.js → ExecutionPlanState.js} +0 -0
- package/lib/stores/ExecutionPlanState.js.map +1 -0
- package/lib/stores/LegendApplicationDocumentation.d.ts +2 -1
- package/lib/stores/LegendApplicationDocumentation.d.ts.map +1 -1
- package/lib/stores/LegendApplicationDocumentation.js +1 -0
- package/lib/stores/LegendApplicationDocumentation.js.map +1 -1
- package/lib/stores/WebApplicationNavigator.d.ts +62 -30
- package/lib/stores/WebApplicationNavigator.d.ts.map +1 -1
- package/lib/stores/WebApplicationNavigator.js +80 -15
- package/lib/stores/WebApplicationNavigator.js.map +1 -1
- package/lib/{components/ApplicationTestID.js → stores/WebApplicationRouter.d.ts} +4 -5
- package/lib/stores/WebApplicationRouter.d.ts.map +1 -0
- package/{src/components/ApplicationTestID.ts → lib/stores/WebApplicationRouter.js} +4 -4
- package/lib/stores/WebApplicationRouter.js.map +1 -0
- package/package.json +9 -11
- package/src/components/LegendApplicationComponentFrameworkProvider.tsx +18 -14
- package/src/components/NotificationManager.tsx +1 -1
- package/src/components/WebApplicationNavigatorProvider.tsx +1 -1
- package/src/components/{shared/execution-plan-viewer → execution-plan-viewer}/ExecutionPlanViewer.tsx +3 -3
- package/src/components/{shared/execution-plan-viewer → execution-plan-viewer}/SQLExecutionNodeViewer.tsx +3 -3
- package/src/components/shared/DocumentationLink.tsx +25 -1
- package/src/components/shared/{PackageableElementOptionRenderer.tsx → PackageableElementOptionLabel.tsx} +4 -4
- package/src/components/shared/TextInputEditor.tsx +1 -2
- package/src/index.ts +9 -9
- package/src/stores/ApplicationStore.ts +15 -12
- package/src/stores/AssistantService.ts +1 -1
- package/src/stores/{shared/ExecutionPlanState.ts → ExecutionPlanState.ts} +1 -1
- package/src/stores/LegendApplicationDocumentation.ts +1 -0
- package/src/stores/WebApplicationNavigator.ts +149 -39
- package/{lib/components/ApplicationTestID.d.ts → src/stores/WebApplicationRouter.ts} +12 -4
- package/tsconfig.json +7 -16
- package/lib/components/ApplicationTestID.d.ts.map +0 -1
- package/lib/components/ApplicationTestID.js.map +0 -1
- package/lib/components/shared/BasicValueSpecificationEditor.d.ts +0 -52
- package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +0 -1
- package/lib/components/shared/BasicValueSpecificationEditor.js +0 -323
- package/lib/components/shared/BasicValueSpecificationEditor.js.map +0 -1
- package/lib/components/shared/CustomDatePicker.d.ts +0 -38
- package/lib/components/shared/CustomDatePicker.d.ts.map +0 -1
- package/lib/components/shared/CustomDatePicker.js +0 -616
- package/lib/components/shared/CustomDatePicker.js.map +0 -1
- package/lib/components/shared/LambdaEditor.d.ts +0 -92
- package/lib/components/shared/LambdaEditor.d.ts.map +0 -1
- package/lib/components/shared/LambdaEditor.js +0 -434
- package/lib/components/shared/LambdaEditor.js.map +0 -1
- package/lib/components/shared/LambdaParameterValuesEditor.d.ts +0 -25
- package/lib/components/shared/LambdaParameterValuesEditor.d.ts.map +0 -1
- package/lib/components/shared/LambdaParameterValuesEditor.js +0 -52
- package/lib/components/shared/LambdaParameterValuesEditor.js.map +0 -1
- package/lib/components/shared/PackageableElementOptionRenderer.d.ts.map +0 -1
- package/lib/components/shared/PackageableElementOptionRenderer.js.map +0 -1
- package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.d.ts.map +0 -1
- package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.js.map +0 -1
- package/lib/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.d.ts.map +0 -1
- package/lib/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.js.map +0 -1
- package/lib/stores/CJS__Fuse.cjs +0 -35
- package/lib/stores/CJS__Fuse.cjs.map +0 -1
- package/lib/stores/CJS__Fuse.d.cts +0 -28
- package/lib/stores/CJS__Fuse.d.cts.map +0 -1
- package/lib/stores/shared/ExecutionPlanState.d.ts.map +0 -1
- package/lib/stores/shared/ExecutionPlanState.js.map +0 -1
- package/lib/stores/shared/LambdaEditorState.d.ts +0 -40
- package/lib/stores/shared/LambdaEditorState.d.ts.map +0 -1
- package/lib/stores/shared/LambdaEditorState.js +0 -81
- package/lib/stores/shared/LambdaEditorState.js.map +0 -1
- package/lib/stores/shared/LambdaParameterState.d.ts +0 -62
- package/lib/stores/shared/LambdaParameterState.d.ts.map +0 -1
- package/lib/stores/shared/LambdaParameterState.js +0 -160
- package/lib/stores/shared/LambdaParameterState.js.map +0 -1
- package/lib/stores/shared/ValueSpecificationModifierHelper.d.ts +0 -27
- package/lib/stores/shared/ValueSpecificationModifierHelper.d.ts.map +0 -1
- package/lib/stores/shared/ValueSpecificationModifierHelper.js +0 -49
- package/lib/stores/shared/ValueSpecificationModifierHelper.js.map +0 -1
- package/src/components/shared/BasicValueSpecificationEditor.tsx +0 -828
- package/src/components/shared/CustomDatePicker.tsx +0 -1292
- package/src/components/shared/LambdaEditor.tsx +0 -854
- package/src/components/shared/LambdaParameterValuesEditor.tsx +0 -118
- package/src/stores/CJS__Fuse.cts +0 -28
- package/src/stores/shared/LambdaEditorState.ts +0 -118
- package/src/stores/shared/LambdaParameterState.ts +0 -253
- package/src/stores/shared/ValueSpecificationModifierHelper.ts +0 -104
|
@@ -14,24 +14,28 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { LegendStyleProvider } from '@finos/legend-art';
|
|
17
|
+
import { Backdrop, LegendStyleProvider } from '@finos/legend-art';
|
|
18
|
+
import { observer } from 'mobx-react-lite';
|
|
18
19
|
import { DndProvider } from 'react-dnd';
|
|
19
20
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
20
21
|
import { ActionAlert } from './ActionAlert.js';
|
|
22
|
+
import { useApplicationStore } from './ApplicationStoreProvider.js';
|
|
21
23
|
import { BlockingAlert } from './BlockingAlert.js';
|
|
22
24
|
import { NotificationManager } from './NotificationManager.js';
|
|
23
25
|
|
|
24
|
-
export const LegendApplicationComponentFrameworkProvider
|
|
25
|
-
children: React.ReactNode
|
|
26
|
-
}
|
|
27
|
-
|
|
26
|
+
export const LegendApplicationComponentFrameworkProvider = observer(
|
|
27
|
+
(props: { children: React.ReactNode }) => {
|
|
28
|
+
const { children } = props;
|
|
29
|
+
const applicationStore = useApplicationStore();
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
return (
|
|
32
|
+
<LegendStyleProvider>
|
|
33
|
+
<BlockingAlert />
|
|
34
|
+
<ActionAlert />
|
|
35
|
+
<NotificationManager />
|
|
36
|
+
<Backdrop className="backdrop" open={applicationStore.showBackdrop} />
|
|
37
|
+
<DndProvider backend={HTML5Backend}>{children}</DndProvider>
|
|
38
|
+
</LegendStyleProvider>
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
);
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
import { guaranteeNonNullable } from '@finos/legend-shared';
|
|
18
18
|
import { useLocalObservable } from 'mobx-react-lite';
|
|
19
19
|
import { createContext, useContext } from 'react';
|
|
20
|
-
import { useHistory } from 'react-router';
|
|
21
20
|
import type { History } from 'history';
|
|
22
21
|
import { WebApplicationNavigator } from '../stores/WebApplicationNavigator.js';
|
|
22
|
+
import { useHistory } from 'react-router';
|
|
23
23
|
|
|
24
24
|
const WebApplicationNavigatorContext = createContext<
|
|
25
25
|
WebApplicationNavigator | undefined
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
ExecutionPlanViewTreeNodeData,
|
|
44
44
|
EXECUTION_PLAN_VIEW_MODE,
|
|
45
45
|
type ExecutionPlanState,
|
|
46
|
-
} from '
|
|
46
|
+
} from '../../stores/ExecutionPlanState.js';
|
|
47
47
|
import { observer } from 'mobx-react-lite';
|
|
48
48
|
import {
|
|
49
49
|
ExecutionPlan,
|
|
@@ -52,8 +52,8 @@ import {
|
|
|
52
52
|
RelationalTDSInstantiationExecutionNode,
|
|
53
53
|
type RawExecutionPlan,
|
|
54
54
|
} from '@finos/legend-graph';
|
|
55
|
-
import { EDITOR_LANGUAGE, TAB_SIZE } from '
|
|
56
|
-
import { TextInputEditor } from '../TextInputEditor.js';
|
|
55
|
+
import { EDITOR_LANGUAGE, TAB_SIZE } from '../../const.js';
|
|
56
|
+
import { TextInputEditor } from '../shared/TextInputEditor.js';
|
|
57
57
|
import { SQLExecutionNodeViewer } from './SQLExecutionNodeViewer.js';
|
|
58
58
|
|
|
59
59
|
/**
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
|
18
|
-
import type { ExecutionPlanState } from '
|
|
18
|
+
import type { ExecutionPlanState } from '../../stores/ExecutionPlanState.js';
|
|
19
19
|
import { format } from 'sql-formatter';
|
|
20
20
|
import type { SQLResultColumn } from '@finos/legend-graph';
|
|
21
|
-
import { TextInputEditor } from '../TextInputEditor.js';
|
|
22
|
-
import { EDITOR_LANGUAGE } from '
|
|
21
|
+
import { TextInputEditor } from '../shared/TextInputEditor.js';
|
|
22
|
+
import { EDITOR_LANGUAGE } from '../../const.js';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* TODO: Create a new `AbstractPlugin` for this, called `ExecutionPlanViewerPlugin`
|
|
@@ -33,7 +33,7 @@ export const DocumentationLink: React.FC<{
|
|
|
33
33
|
documentationKey,
|
|
34
34
|
);
|
|
35
35
|
} else if (documentationEntry.url) {
|
|
36
|
-
applicationStore.navigator.
|
|
36
|
+
applicationStore.navigator.visitAddress(documentationEntry.url);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
};
|
|
@@ -53,3 +53,27 @@ export const DocumentationLink: React.FC<{
|
|
|
53
53
|
/>
|
|
54
54
|
);
|
|
55
55
|
};
|
|
56
|
+
|
|
57
|
+
export const DocumentationPreview: React.FC<{
|
|
58
|
+
text?: string | undefined;
|
|
59
|
+
documentationKey: string;
|
|
60
|
+
className?: string | undefined;
|
|
61
|
+
}> = (props) => {
|
|
62
|
+
const { documentationKey, text, className } = props;
|
|
63
|
+
const applicationStore = useApplicationStore();
|
|
64
|
+
const documentationEntry =
|
|
65
|
+
applicationStore.documentationService.getDocEntry(documentationKey);
|
|
66
|
+
const textContent = text ?? documentationEntry?.text;
|
|
67
|
+
|
|
68
|
+
if (!documentationEntry || !textContent) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return (
|
|
72
|
+
<div className={clsx('documentation-preview', className)}>
|
|
73
|
+
<div className="documentation-preview__text">{textContent}</div>
|
|
74
|
+
<div className="documentation-preview__hint">
|
|
75
|
+
<DocumentationLink documentationKey={documentationKey} />
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
@@ -51,17 +51,17 @@ export const getPackageableElementOptionFormatter = (props: {
|
|
|
51
51
|
option: PackageableElementOption<PackageableElement>,
|
|
52
52
|
): React.ReactNode {
|
|
53
53
|
const className = props.darkMode
|
|
54
|
-
? 'packageable-element-
|
|
55
|
-
: 'packageable-element-
|
|
54
|
+
? 'packageable-element-option-label--dark'
|
|
55
|
+
: 'packageable-element-option-label';
|
|
56
56
|
const colorCode = getElementColorCode(option.value);
|
|
57
57
|
|
|
58
58
|
return (
|
|
59
59
|
<div className={className}>
|
|
60
60
|
<div
|
|
61
61
|
title={generateOptionTooltipText(option.value)}
|
|
62
|
-
className={`packageable-element-
|
|
62
|
+
className={`packageable-element-option-label__type ${
|
|
63
63
|
colorCode
|
|
64
|
-
? `packageable-element-
|
|
64
|
+
? `packageable-element-option-label__type--${colorCode}`
|
|
65
65
|
: ''
|
|
66
66
|
} `}
|
|
67
67
|
></div>
|
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
type IKeyboardEvent,
|
|
21
21
|
editor as monacoEditorAPI,
|
|
22
22
|
} from 'monaco-editor';
|
|
23
|
-
import { useResizeDetector } from 'react-resize-detector';
|
|
24
23
|
import {
|
|
25
24
|
disposeEditor,
|
|
26
25
|
disableEditorHotKeys,
|
|
@@ -28,6 +27,7 @@ import {
|
|
|
28
27
|
resetLineNumberGutterWidth,
|
|
29
28
|
getEditorValue,
|
|
30
29
|
normalizeLineEnding,
|
|
30
|
+
useResizeDetector,
|
|
31
31
|
} from '@finos/legend-art';
|
|
32
32
|
import { type EDITOR_LANGUAGE, EDITOR_THEME, TAB_SIZE } from '../../const.js';
|
|
33
33
|
import { useApplicationStore } from '../ApplicationStoreProvider.js';
|
|
@@ -78,7 +78,6 @@ export const TextInputEditor: React.FC<{
|
|
|
78
78
|
*/
|
|
79
79
|
const value = normalizeLineEnding(inputValue);
|
|
80
80
|
const textInputRef = useRef<HTMLDivElement>(null);
|
|
81
|
-
|
|
82
81
|
const { ref, width, height } = useResizeDetector<HTMLDivElement>();
|
|
83
82
|
|
|
84
83
|
useEffect(() => {
|
package/src/index.ts
CHANGED
|
@@ -41,21 +41,21 @@ export * from './stores/LegendApplicationPlugin.js';
|
|
|
41
41
|
|
|
42
42
|
export * from './components/shared/TextSearchAdvancedConfigMenu.js';
|
|
43
43
|
export * from './stores/shared/TextSearchAdvancedConfigState.js';
|
|
44
|
+
export * from './stores/LegendApplicationDocumentation.js';
|
|
44
45
|
|
|
45
46
|
export * from './stores/ApplicationStoreTestUtils.js';
|
|
47
|
+
export * from './stores/WebApplicationRouter.js';
|
|
46
48
|
|
|
47
49
|
// ------------------------------------------- Shared components -------------------------------------------
|
|
48
50
|
|
|
49
51
|
export * from './components/shared/DocumentationLink.js';
|
|
50
52
|
export * from './components/shared/TextInputEditor.js';
|
|
51
|
-
export * from './components/shared/
|
|
52
|
-
export * from './components/shared/BasicValueSpecificationEditor.js';
|
|
53
|
-
export * from './components/shared/LambdaParameterValuesEditor.js';
|
|
54
|
-
export * from './components/shared/PackageableElementOptionRenderer.js';
|
|
55
|
-
export * from './components/shared/execution-plan-viewer/ExecutionPlanViewer.js';
|
|
53
|
+
export * from './components/shared/PackageableElementOptionLabel.js';
|
|
56
54
|
|
|
57
|
-
export { LambdaEditorState } from './stores/shared/LambdaEditorState.js';
|
|
58
55
|
export * from './stores/shared/PackageableElementOption.js';
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @modularize
|
|
59
|
+
*/
|
|
60
|
+
export * from './components/execution-plan-viewer/ExecutionPlanViewer.js';
|
|
61
|
+
export * from './stores/ExecutionPlanState.js';
|
|
@@ -136,6 +136,9 @@ export class ApplicationStore<
|
|
|
136
136
|
telemetryService = new TelemetryService();
|
|
137
137
|
tracerService = new TracerService();
|
|
138
138
|
|
|
139
|
+
// misc
|
|
140
|
+
showBackdrop = false;
|
|
141
|
+
|
|
139
142
|
// theme
|
|
140
143
|
/**
|
|
141
144
|
* NOTE: this is the poor man way of doing theming
|
|
@@ -150,6 +153,8 @@ export class ApplicationStore<
|
|
|
150
153
|
blockingAlertInfo: observable,
|
|
151
154
|
actionAlertInfo: observable,
|
|
152
155
|
TEMPORARY__isLightThemeEnabled: observable,
|
|
156
|
+
showBackdrop: observable,
|
|
157
|
+
setShowBackdrop: action,
|
|
153
158
|
setBlockingAlert: action,
|
|
154
159
|
setActionAlertInfo: action,
|
|
155
160
|
setNotification: action,
|
|
@@ -185,6 +190,10 @@ export class ApplicationStore<
|
|
|
185
190
|
this.TEMPORARY__isLightThemeEnabled = val;
|
|
186
191
|
}
|
|
187
192
|
|
|
193
|
+
setShowBackdrop(val: boolean): void {
|
|
194
|
+
this.showBackdrop = val;
|
|
195
|
+
}
|
|
196
|
+
|
|
188
197
|
setBlockingAlert(alertInfo: BlockingAlertInfo | undefined): void {
|
|
189
198
|
this.blockingAlertInfo = alertInfo;
|
|
190
199
|
}
|
|
@@ -335,18 +344,12 @@ export class ApplicationStore<
|
|
|
335
344
|
};
|
|
336
345
|
|
|
337
346
|
async copyTextToClipboard(text: string): Promise<void> {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
await navigator.clipboard.writeText(text).catch((error) => {
|
|
345
|
-
this.notifyError(error);
|
|
346
|
-
});
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
this.notifyError('Browser does not support clipboard functionality');
|
|
347
|
+
// This is a much cleaner way which requires HTTPS
|
|
348
|
+
// See https://developers.google.com/web/updates/2018/03/clipboardapi
|
|
349
|
+
await navigator.clipboard.writeText(text).catch((error) => {
|
|
350
|
+
this.notifyError(error);
|
|
351
|
+
});
|
|
352
|
+
return;
|
|
350
353
|
}
|
|
351
354
|
|
|
352
355
|
notifyUnsupportedFeature(featureName: string): void {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { action, makeObservable, observable, computed } from 'mobx';
|
|
18
18
|
import type { DocumentationEntry } from './DocumentationService.js';
|
|
19
19
|
import type { GenericLegendApplicationStore } from './ApplicationStore.js';
|
|
20
|
-
import { Fuse } from '
|
|
20
|
+
import { Fuse } from '@finos/legend-art';
|
|
21
21
|
import {
|
|
22
22
|
type MarkdownText,
|
|
23
23
|
guaranteeNonEmptyString,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
ExecutionPlan,
|
|
22
22
|
ExecutionNode,
|
|
23
23
|
} from '@finos/legend-graph';
|
|
24
|
-
import type { GenericLegendApplicationStore } from '
|
|
24
|
+
import type { GenericLegendApplicationStore } from './ApplicationStore.js';
|
|
25
25
|
import type { TreeNodeData } from '@finos/legend-art';
|
|
26
26
|
|
|
27
27
|
export class ExecutionPlanViewTreeNodeData implements TreeNodeData {
|
|
@@ -16,4 +16,5 @@
|
|
|
16
16
|
|
|
17
17
|
export enum LEGEND_APPLICATION_DOCUMENTATION_KEY {
|
|
18
18
|
QUESTION_HOW_TO_USE_ADVANCED_SEARCH_SYNTAX = 'question.how-to-use-advanced-search-syntax',
|
|
19
|
+
QUESTION_WHEN_TO_CONFIGURE_PLATFORM_VERSIONS = 'question.when-to-configure-project-platform-dependencies-versions',
|
|
19
20
|
}
|
|
@@ -16,44 +16,102 @@
|
|
|
16
16
|
|
|
17
17
|
import type { History } from 'history';
|
|
18
18
|
import { guaranteeNonNullable } from '@finos/legend-shared';
|
|
19
|
+
import { action, computed, makeObservable, observable } from 'mobx';
|
|
20
|
+
|
|
21
|
+
type Location = string;
|
|
22
|
+
type Address = string;
|
|
19
23
|
|
|
20
24
|
/**
|
|
21
|
-
* This is an initial attempt to
|
|
22
|
-
* to other platforms. But regardless, this is more convenient for testing.
|
|
25
|
+
* This is an initial attempt to generalize the application navigation to other platforms
|
|
23
26
|
*
|
|
24
|
-
* NOTE: this
|
|
27
|
+
* NOTE: this might **NOT** be the right way to do this. Our intention here is to make
|
|
25
28
|
* app navigator something generic enough so we are somewhat platform-agnostic
|
|
26
29
|
* i.e. browser, electron, PC, UNIX, etc.
|
|
27
30
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* which is `ApplicationStore`. It means that we must dictate in the source
|
|
31
|
-
* code the platform the app depends on, clearly for web browser, `string` is the
|
|
32
|
-
* easy option, but if we do so, it defeats the purpose of this abstraction in the
|
|
33
|
-
* first place.
|
|
34
|
-
*
|
|
35
|
-
* As such, instead, we should design a more generic concept `Location` to pass around.
|
|
36
|
-
* We would need to flesh out the details, but this is the rough idea.
|
|
37
|
-
*
|
|
38
|
-
* Another thought is that we should also generalize Router so it handles more than just
|
|
31
|
+
* We should design a more advanced concept `Location` to pass around.
|
|
32
|
+
* Also, we should also generalize Router so it handles more than just
|
|
39
33
|
* URLs. If we make `router` and `navigator` work together, we can potentially generalize
|
|
40
34
|
* application navigation
|
|
41
35
|
*
|
|
42
36
|
* However, this depends on how and when we move to another platform, like `electron` for example
|
|
43
37
|
* See https://github.com/finos/legend-studio/issues/718
|
|
44
38
|
*/
|
|
45
|
-
interface ApplicationNavigator
|
|
39
|
+
interface ApplicationNavigator {
|
|
40
|
+
/**
|
|
41
|
+
* Navigate to the specified location
|
|
42
|
+
*/
|
|
43
|
+
goToLocation(location: Location): void;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Navigate to the specified location and reload the application
|
|
47
|
+
*/
|
|
48
|
+
reloadToLocation(
|
|
49
|
+
location: Location,
|
|
50
|
+
options?: { ignoreBlocking?: boolean | undefined },
|
|
51
|
+
): void;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Reload the application using the same address
|
|
55
|
+
*/
|
|
46
56
|
reload(): void;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Visit the specified address
|
|
60
|
+
*
|
|
61
|
+
* NOTE: unless specified, the visit will be done in a new window
|
|
62
|
+
*/
|
|
63
|
+
visitAddress(
|
|
64
|
+
address: Address,
|
|
65
|
+
options?: {
|
|
66
|
+
useSameWindow?: boolean | undefined;
|
|
67
|
+
},
|
|
68
|
+
): void;
|
|
69
|
+
|
|
70
|
+
getCurrentAddress(): Address;
|
|
71
|
+
getCurrentLocation(): Location;
|
|
72
|
+
generateAddress(location: Location): Address;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Disable platform native navigation feature
|
|
76
|
+
*
|
|
77
|
+
* e.g. in web browser, we will block back/forward buttons
|
|
78
|
+
*/
|
|
79
|
+
blockPlatformNavigation(blockCheckers: (() => boolean)[]): void;
|
|
80
|
+
unblockPlatformNavigation(): void;
|
|
81
|
+
get isPlatformNavigationBlocked(): boolean;
|
|
53
82
|
}
|
|
54
83
|
|
|
55
|
-
export class WebApplicationNavigator implements ApplicationNavigator
|
|
84
|
+
export class WebApplicationNavigator implements ApplicationNavigator {
|
|
56
85
|
private readonly historyAPI: History;
|
|
86
|
+
private _isPlatformNavigationBlocked = false;
|
|
87
|
+
private _forceBypassPlatformNavigationBlocking = false;
|
|
88
|
+
private _blockCheckers: (() => boolean)[] = [];
|
|
89
|
+
private _beforeUnloadListener = (event: BeforeUnloadEvent): void => {
|
|
90
|
+
if (this._forceBypassPlatformNavigationBlocking) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (this._blockCheckers.some((checker) => checker())) {
|
|
94
|
+
// NOTE: there is no way to customize the alert message for now since Chrome removed support for it due to security concerns
|
|
95
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload#Browser_compatibility
|
|
96
|
+
event.returnValue = '';
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
notifier?: ((message: string) => void) | undefined;
|
|
101
|
+
|
|
102
|
+
constructor(historyApiClient: History) {
|
|
103
|
+
makeObservable<WebApplicationNavigator, '_isPlatformNavigationBlocked'>(
|
|
104
|
+
this,
|
|
105
|
+
{
|
|
106
|
+
_isPlatformNavigationBlocked: observable,
|
|
107
|
+
isPlatformNavigationBlocked: computed,
|
|
108
|
+
blockPlatformNavigation: action,
|
|
109
|
+
unblockPlatformNavigation: action,
|
|
110
|
+
},
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
this.historyAPI = historyApiClient;
|
|
114
|
+
}
|
|
57
115
|
|
|
58
116
|
private get window(): Window {
|
|
59
117
|
return guaranteeNonNullable(
|
|
@@ -62,38 +120,90 @@ export class WebApplicationNavigator implements ApplicationNavigator<string> {
|
|
|
62
120
|
);
|
|
63
121
|
}
|
|
64
122
|
|
|
65
|
-
|
|
66
|
-
this.historyAPI
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
reload(): void {
|
|
70
|
-
this.window.location.reload();
|
|
123
|
+
goToLocation(location: Location): void {
|
|
124
|
+
this.historyAPI.push(location);
|
|
71
125
|
}
|
|
72
126
|
|
|
73
|
-
|
|
74
|
-
|
|
127
|
+
reloadToLocation(
|
|
128
|
+
location: Location,
|
|
129
|
+
options?: { ignoreBlocking?: boolean | undefined },
|
|
130
|
+
): void {
|
|
131
|
+
if (options?.ignoreBlocking) {
|
|
132
|
+
this._forceBypassPlatformNavigationBlocking = true;
|
|
133
|
+
}
|
|
134
|
+
// if (
|
|
135
|
+
// this._isPlatformNavigationBlocked &&
|
|
136
|
+
// !this._forceBypassPlatformNavigationBlocking
|
|
137
|
+
// ) {
|
|
138
|
+
// this.notifier
|
|
139
|
+
// return;
|
|
140
|
+
// }
|
|
141
|
+
this.window.location.href = this.generateAddress(location);
|
|
75
142
|
}
|
|
76
143
|
|
|
77
|
-
|
|
78
|
-
|
|
144
|
+
reload(options?: { ignoreBlocking?: boolean | undefined }): void {
|
|
145
|
+
if (options?.ignoreBlocking) {
|
|
146
|
+
this._forceBypassPlatformNavigationBlocking = true;
|
|
147
|
+
}
|
|
148
|
+
this.window.location.reload();
|
|
79
149
|
}
|
|
80
150
|
|
|
81
|
-
|
|
82
|
-
|
|
151
|
+
visitAddress(
|
|
152
|
+
address: Address,
|
|
153
|
+
options?: {
|
|
154
|
+
useSameWindow?: boolean | undefined;
|
|
155
|
+
},
|
|
156
|
+
): void {
|
|
157
|
+
if (options?.useSameWindow) {
|
|
158
|
+
this.window.location.href = address;
|
|
159
|
+
} else {
|
|
160
|
+
this.window.open(address, '_blank');
|
|
161
|
+
}
|
|
83
162
|
}
|
|
84
163
|
|
|
85
|
-
|
|
164
|
+
getCurrentAddress(): Address {
|
|
86
165
|
return this.window.location.href;
|
|
87
166
|
}
|
|
88
167
|
|
|
89
|
-
|
|
168
|
+
getCurrentLocation(): Location {
|
|
90
169
|
return this.historyAPI.location.pathname;
|
|
91
170
|
}
|
|
92
171
|
|
|
93
|
-
|
|
172
|
+
generateAddress(location: Location): string {
|
|
94
173
|
return (
|
|
95
|
-
window.location.origin +
|
|
96
|
-
this.historyAPI.createHref({ pathname:
|
|
174
|
+
this.window.location.origin +
|
|
175
|
+
this.historyAPI.createHref({ pathname: location })
|
|
97
176
|
);
|
|
98
177
|
}
|
|
178
|
+
|
|
179
|
+
blockPlatformNavigation(blockCheckers: (() => boolean)[]): void {
|
|
180
|
+
this._isPlatformNavigationBlocked = true;
|
|
181
|
+
|
|
182
|
+
// Here we attempt to cancel the effect of the back button
|
|
183
|
+
// See https://medium.com/codex/angular-guards-disabling-browsers-back-button-for-specific-url-fdf05d9fe155#4f13
|
|
184
|
+
// This makes the current location the last entry in the browser history and clears any forward history
|
|
185
|
+
this.window.history.pushState(null, '', this.getCurrentAddress());
|
|
186
|
+
// The popstate event is triggered every time the user clicks back/forward button, but the forward history
|
|
187
|
+
// has been cleared, and now if we go back, we call `history.forward()`, which go 1 page forward,
|
|
188
|
+
// but there's no page forward, so effectively, the user remains on the same page
|
|
189
|
+
this.window.onpopstate = () => {
|
|
190
|
+
window.history.forward();
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Block browser navigation: e.g. reload, setting `window.href` directly, etc.
|
|
194
|
+
this._blockCheckers = blockCheckers;
|
|
195
|
+
this.window.removeEventListener('beforeunload', this._beforeUnloadListener);
|
|
196
|
+
this.window.addEventListener('beforeunload', this._beforeUnloadListener);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
unblockPlatformNavigation(): void {
|
|
200
|
+
this._isPlatformNavigationBlocked = false;
|
|
201
|
+
this.window.onpopstate = null;
|
|
202
|
+
this._blockCheckers = [];
|
|
203
|
+
this.window.removeEventListener('beforeunload', this._beforeUnloadListener);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
get isPlatformNavigationBlocked(): boolean {
|
|
207
|
+
return this._isPlatformNavigationBlocked;
|
|
208
|
+
}
|
|
99
209
|
}
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
|
|
17
|
+
export { BrowserRouter } from 'react-router-dom';
|
|
18
|
+
export {
|
|
19
|
+
Router,
|
|
20
|
+
Route,
|
|
21
|
+
Switch,
|
|
22
|
+
Redirect,
|
|
23
|
+
useParams,
|
|
24
|
+
generatePath,
|
|
25
|
+
MemoryRouter,
|
|
26
|
+
} from 'react-router';
|
|
27
|
+
export { createMemoryHistory } from 'history';
|
package/tsconfig.json
CHANGED
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
"./src/const.ts",
|
|
32
32
|
"./src/index.ts",
|
|
33
33
|
"./src/application/LegendApplicationConfig.ts",
|
|
34
|
-
"./src/components/ApplicationTestID.ts",
|
|
35
34
|
"./src/stores/ApplicationEvent.ts",
|
|
36
35
|
"./src/stores/ApplicationNavigationContextService.ts",
|
|
37
36
|
"./src/stores/ApplicationStore.ts",
|
|
@@ -40,16 +39,14 @@
|
|
|
40
39
|
"./src/stores/AssistantService.ts",
|
|
41
40
|
"./src/stores/DocumentationService.ts",
|
|
42
41
|
"./src/stores/EventService.ts",
|
|
42
|
+
"./src/stores/ExecutionPlanState.ts",
|
|
43
43
|
"./src/stores/LegendApplicationDocumentation.ts",
|
|
44
44
|
"./src/stores/LegendApplicationPlugin.ts",
|
|
45
45
|
"./src/stores/PureLanguageSupport.ts",
|
|
46
46
|
"./src/stores/WebApplicationNavigator.ts",
|
|
47
|
-
"./src/stores/
|
|
48
|
-
"./src/stores/shared/LambdaEditorState.ts",
|
|
49
|
-
"./src/stores/shared/LambdaParameterState.ts",
|
|
47
|
+
"./src/stores/WebApplicationRouter.ts",
|
|
50
48
|
"./src/stores/shared/PackageableElementOption.ts",
|
|
51
49
|
"./src/stores/shared/TextSearchAdvancedConfigState.ts",
|
|
52
|
-
"./src/stores/shared/ValueSpecificationModifierHelper.ts",
|
|
53
50
|
"./src/application/LegendApplication.tsx",
|
|
54
51
|
"./src/application/LegendApplicationPluginManager.tsx",
|
|
55
52
|
"./src/components/ActionAlert.tsx",
|
|
@@ -62,23 +59,17 @@
|
|
|
62
59
|
"./src/components/VirtualAssistant.tsx",
|
|
63
60
|
"./src/components/WebApplicationNavigatorProvider.tsx",
|
|
64
61
|
"./src/components/WebApplicationNavigatorProviderTestUtils.tsx",
|
|
65
|
-
"./src/components/
|
|
66
|
-
"./src/components/
|
|
62
|
+
"./src/components/execution-plan-viewer/ExecutionPlanViewer.tsx",
|
|
63
|
+
"./src/components/execution-plan-viewer/SQLExecutionNodeViewer.tsx",
|
|
67
64
|
"./src/components/shared/DocumentationLink.tsx",
|
|
68
|
-
"./src/components/shared/
|
|
69
|
-
"./src/components/shared/LambdaParameterValuesEditor.tsx",
|
|
70
|
-
"./src/components/shared/PackageableElementOptionRenderer.tsx",
|
|
65
|
+
"./src/components/shared/PackageableElementOptionLabel.tsx",
|
|
71
66
|
"./src/components/shared/TextInputEditor.tsx",
|
|
72
|
-
"./src/components/shared/TextSearchAdvancedConfigMenu.tsx"
|
|
73
|
-
"./src/components/shared/execution-plan-viewer/ExecutionPlanViewer.tsx",
|
|
74
|
-
"./src/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.tsx",
|
|
75
|
-
"./src/stores/CJS__Fuse.cts"
|
|
67
|
+
"./src/components/shared/TextSearchAdvancedConfigMenu.tsx"
|
|
76
68
|
],
|
|
77
69
|
"include": [
|
|
78
70
|
"src/**/*.ts",
|
|
79
71
|
"src/**/*.tsx",
|
|
80
|
-
"src/**/*.json"
|
|
81
|
-
"src/**/*.cts"
|
|
72
|
+
"src/**/*.json"
|
|
82
73
|
],
|
|
83
74
|
"exclude": [
|
|
84
75
|
"src/**/__tests__/**/*.*",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationTestID.d.ts","sourceRoot":"","sources":["../../src/components/ApplicationTestID.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,oBAAY,mBAAmB;IAC7B,2BAA2B,iCAAiC;CAC7D"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationTestID.js","sourceRoot":"","sources":["../../src/components/ApplicationTestID.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,CAAN,IAAY,mBAEX;AAFD,WAAY,mBAAmB;IAC7B,mFAA4D,CAAA;AAC9D,CAAC,EAFW,mBAAmB,GAAnB,mBAAmB,KAAnB,mBAAmB,QAE9B"}
|