@finos/legend-application-studio 26.1.1 → 26.1.3
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__/LegendStudioApplicationNavigationContext.d.ts +2 -1
- package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioApplicationNavigationContext.js +1 -0
- package/lib/__lib__/LegendStudioApplicationNavigationContext.js.map +1 -1
- package/lib/__lib__/STO_Relational_LegendStudioCommand.d.ts +21 -0
- package/lib/__lib__/STO_Relational_LegendStudioCommand.d.ts.map +1 -0
- package/lib/__lib__/STO_Relational_LegendStudioCommand.js +28 -0
- package/lib/__lib__/STO_Relational_LegendStudioCommand.js.map +1 -0
- package/lib/application/LegendStudioApplicationConfig.d.ts +5 -0
- package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.js +6 -0
- package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
- package/lib/components/ElementIconUtils.d.ts +13 -2
- package/lib/components/ElementIconUtils.d.ts.map +1 -1
- package/lib/components/ElementIconUtils.js +15 -6
- package/lib/components/ElementIconUtils.js.map +1 -1
- package/lib/components/editor/Editor.d.ts.map +1 -1
- package/lib/components/editor/Editor.js +2 -1
- package/lib/components/editor/Editor.js.map +1 -1
- package/lib/components/editor/QuickInput.d.ts +19 -0
- package/lib/components/editor/QuickInput.d.ts.map +1 -0
- package/lib/components/editor/QuickInput.js +51 -0
- package/lib/components/editor/QuickInput.js.map +1 -0
- package/lib/components/editor/__test-utils__/EditorComponentTestUtils.d.ts.map +1 -1
- package/lib/components/editor/__test-utils__/EditorComponentTestUtils.js +5 -1
- package/lib/components/editor/__test-utils__/EditorComponentTestUtils.js.map +1 -1
- package/lib/components/editor/command-center/ProjectSearchCommand.js +3 -3
- package/lib/components/editor/command-center/ProjectSearchCommand.js.map +1 -1
- package/lib/components/editor/editor-group/EditorGroup.d.ts.map +1 -1
- package/lib/components/editor/editor-group/EditorGroup.js +11 -4
- package/lib/components/editor/editor-group/EditorGroup.js.map +1 -1
- package/lib/components/editor/editor-group/FunctionEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/FunctionEditor.js +30 -8
- package/lib/components/editor/editor-group/FunctionEditor.js.map +1 -1
- package/lib/components/editor/editor-group/GenerationSpecificationEditor.js +1 -1
- package/lib/components/editor/editor-group/GenerationSpecificationEditor.js.map +1 -1
- package/lib/components/editor/editor-group/GrammarTextEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/GrammarTextEditor.js +99 -100
- package/lib/components/editor/editor-group/GrammarTextEditor.js.map +1 -1
- package/lib/components/editor/editor-group/INTERNAL__UnknownFunctionActivatorEdtior.d.ts.map +1 -1
- package/lib/components/editor/editor-group/INTERNAL__UnknownFunctionActivatorEdtior.js +5 -5
- package/lib/components/editor/editor-group/INTERNAL__UnknownFunctionActivatorEdtior.js.map +1 -1
- package/lib/components/editor/editor-group/RuntimeEditor.js +1 -1
- package/lib/components/editor/editor-group/RuntimeEditor.js.map +1 -1
- package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.d.ts.map +1 -1
- package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.js +27 -19
- package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.js.map +1 -1
- package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.js +2 -2
- package/lib/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.js +5 -5
- package/lib/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.js.map +1 -1
- package/lib/components/editor/editor-group/element-generation-editor/FileGenerationEditor.js +2 -2
- package/lib/components/editor/editor-group/element-generation-editor/FileGenerationEditor.js.map +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.js +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.js.map +1 -1
- package/lib/components/editor/editor-group/mapping-editor/ClassMappingEditor.js +1 -1
- package/lib/components/editor/editor-group/mapping-editor/ClassMappingEditor.js.map +1 -1
- package/lib/components/editor/editor-group/mapping-editor/MappingExplorer.js +2 -2
- package/lib/components/editor/editor-group/mapping-editor/MappingExplorer.js.map +1 -1
- package/lib/components/editor/editor-group/mapping-editor/PropertyMappingsEditor.js +1 -1
- package/lib/components/editor/editor-group/mapping-editor/PropertyMappingsEditor.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js +4 -6
- package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.js +2 -2
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestableEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestableEditor.js +2 -2
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestableEditor.js.map +1 -1
- package/lib/components/editor/editor-group/uml-editor/AssociationEditor.js +2 -2
- package/lib/components/editor/editor-group/uml-editor/AssociationEditor.js.map +1 -1
- package/lib/components/editor/editor-group/uml-editor/ClassEditor.js +4 -4
- package/lib/components/editor/editor-group/uml-editor/ClassEditor.js.map +1 -1
- package/lib/components/editor/panel-group/PanelGroup.d.ts +2 -0
- package/lib/components/editor/panel-group/PanelGroup.d.ts.map +1 -1
- package/lib/components/editor/panel-group/PanelGroup.js +18 -3
- package/lib/components/editor/panel-group/PanelGroup.js.map +1 -1
- package/lib/components/editor/panel-group/SQLPlaygroundPanel.d.ts +26 -0
- package/lib/components/editor/panel-group/SQLPlaygroundPanel.d.ts.map +1 -0
- package/lib/components/editor/panel-group/SQLPlaygroundPanel.js +339 -0
- package/lib/components/editor/panel-group/SQLPlaygroundPanel.js.map +1 -0
- package/lib/components/editor/side-bar/Explorer.js +5 -6
- package/lib/components/editor/side-bar/Explorer.js.map +1 -1
- package/lib/components/editor/side-bar/testable/GlobalTestRunner.js +1 -1
- package/lib/components/editor/side-bar/testable/GlobalTestRunner.js.map +1 -1
- package/lib/components/extensions/Core_LegendStudioApplicationPlugin.d.ts.map +1 -1
- package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js +5 -1
- package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +2 -2
- package/lib/stores/editor/EditorConfig.d.ts +2 -1
- package/lib/stores/editor/EditorConfig.d.ts.map +1 -1
- package/lib/stores/editor/EditorConfig.js +1 -0
- package/lib/stores/editor/EditorConfig.js.map +1 -1
- package/lib/stores/editor/EditorStore.d.ts +8 -2
- package/lib/stores/editor/EditorStore.d.ts.map +1 -1
- package/lib/stores/editor/EditorStore.js +19 -4
- 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 +1 -0
- package/lib/stores/editor/GraphEditFormModeState.js.map +1 -1
- package/lib/stores/editor/QuickInputState.d.ts +28 -0
- package/lib/stores/editor/QuickInputState.d.ts.map +1 -0
- package/lib/stores/editor/QuickInputState.js +17 -0
- package/lib/stores/editor/QuickInputState.js.map +1 -0
- package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.d.ts +22 -2
- package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.js +181 -4
- package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/ProtocolValueBuilderState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/ProtocolValueBuilderState.js +6 -2
- package/lib/stores/editor/editor-state/element-editor-state/ProtocolValueBuilderState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts +19 -18
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js +167 -157
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingElementDecorator.d.ts +3 -3
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingElementDecorator.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingElementDecorator.js +2 -2
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingElementDecorator.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.d.ts +8 -9
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.js +9 -14
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts +4 -4
- 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 +7 -8
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.d.ts +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.js +3 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.js.map +1 -1
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts +82 -0
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts.map +1 -0
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js +328 -0
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js.map +1 -0
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.d.ts +1 -1
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.js +8 -2
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.js.map +1 -1
- package/package.json +12 -12
- package/src/__lib__/LegendStudioApplicationNavigationContext.ts +2 -0
- package/src/__lib__/STO_Relational_LegendStudioCommand.ts +30 -0
- package/src/application/LegendStudioApplicationConfig.ts +7 -0
- package/src/components/ElementIconUtils.tsx +23 -8
- package/src/components/editor/Editor.tsx +2 -0
- package/src/components/editor/QuickInput.tsx +91 -0
- package/src/components/editor/__test-utils__/EditorComponentTestUtils.tsx +5 -1
- package/src/components/editor/command-center/ProjectSearchCommand.tsx +4 -4
- package/src/components/editor/editor-group/EditorGroup.tsx +41 -1
- package/src/components/editor/editor-group/FunctionEditor.tsx +145 -5
- package/src/components/editor/editor-group/GenerationSpecificationEditor.tsx +1 -1
- package/src/components/editor/editor-group/GrammarTextEditor.tsx +134 -131
- package/src/components/editor/editor-group/INTERNAL__UnknownFunctionActivatorEdtior.tsx +26 -13
- package/src/components/editor/editor-group/RuntimeEditor.tsx +1 -1
- package/src/components/editor/editor-group/connection-editor/DatabaseBuilder.tsx +193 -150
- package/src/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.tsx +2 -2
- package/src/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.tsx +6 -5
- package/src/components/editor/editor-group/element-generation-editor/FileGenerationEditor.tsx +1 -1
- package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.tsx +1 -1
- package/src/components/editor/editor-group/mapping-editor/ClassMappingEditor.tsx +1 -1
- package/src/components/editor/editor-group/mapping-editor/MappingExplorer.tsx +2 -2
- package/src/components/editor/editor-group/mapping-editor/PropertyMappingsEditor.tsx +1 -1
- package/src/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.tsx +8 -10
- package/src/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.tsx +2 -2
- package/src/components/editor/editor-group/service-editor/testable/ServiceTestableEditor.tsx +9 -3
- package/src/components/editor/editor-group/uml-editor/AssociationEditor.tsx +2 -2
- package/src/components/editor/editor-group/uml-editor/ClassEditor.tsx +4 -4
- package/src/components/editor/panel-group/PanelGroup.tsx +35 -3
- package/src/components/editor/panel-group/SQLPlaygroundPanel.tsx +730 -0
- package/src/components/editor/side-bar/Explorer.tsx +5 -5
- package/src/components/editor/side-bar/testable/GlobalTestRunner.tsx +1 -1
- package/src/components/extensions/Core_LegendStudioApplicationPlugin.tsx +9 -3
- package/src/stores/editor/EditorConfig.ts +1 -0
- package/src/stores/editor/EditorStore.ts +23 -4
- package/src/stores/editor/GraphEditFormModeState.ts +1 -0
- package/src/stores/editor/QuickInputState.ts +24 -0
- package/src/stores/editor/editor-state/element-editor-state/FunctionEditorState.ts +317 -3
- package/src/stores/editor/editor-state/element-editor-state/ProtocolValueBuilderState.ts +11 -2
- package/src/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.ts +262 -249
- package/src/stores/editor/editor-state/element-editor-state/mapping/MappingElementDecorator.ts +5 -5
- package/src/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.ts +19 -23
- package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.ts +9 -9
- package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.ts +4 -2
- package/src/stores/editor/panel-group/SQLPlaygroundPanelState.ts +485 -0
- package/src/stores/graph-modifier/DSL_Service_GraphModifierHelper.ts +13 -1
- package/tsconfig.json +5 -0
@@ -0,0 +1,730 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2020-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 { observer } from 'mobx-react-lite';
|
18
|
+
import {
|
19
|
+
type TreeNodeContainerProps,
|
20
|
+
ResizablePanelGroup,
|
21
|
+
ResizablePanel,
|
22
|
+
ResizablePanelSplitter,
|
23
|
+
clsx,
|
24
|
+
TreeView,
|
25
|
+
PURE_DatabaseSchemaIcon,
|
26
|
+
PURE_DatabaseTableIcon,
|
27
|
+
ChevronDownIcon,
|
28
|
+
ChevronRightIcon,
|
29
|
+
KeyIcon,
|
30
|
+
CustomSelectorInput,
|
31
|
+
type SelectComponent,
|
32
|
+
createFilter,
|
33
|
+
PURE_ConnectionIcon,
|
34
|
+
BlankPanelPlaceholder,
|
35
|
+
PanelDropZone,
|
36
|
+
ResizablePanelSplitterLine,
|
37
|
+
PlayIcon,
|
38
|
+
PanelLoadingIndicator,
|
39
|
+
BlankPanelContent,
|
40
|
+
TrashIcon,
|
41
|
+
} from '@finos/legend-art';
|
42
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
43
|
+
import {
|
44
|
+
useApplicationStore,
|
45
|
+
useCommands,
|
46
|
+
useConditionedApplicationNavigationContext,
|
47
|
+
} from '@finos/legend-application';
|
48
|
+
import { flowResult } from 'mobx';
|
49
|
+
import {
|
50
|
+
CODE_EDITOR_LANGUAGE,
|
51
|
+
CODE_EDITOR_THEME,
|
52
|
+
getBaseCodeEditorOptions,
|
53
|
+
} from '@finos/legend-lego/code-editor';
|
54
|
+
import {
|
55
|
+
editor as monacoEditorAPI,
|
56
|
+
languages as monacoLanguagesAPI,
|
57
|
+
type IDisposable,
|
58
|
+
type IPosition,
|
59
|
+
} from 'monaco-editor';
|
60
|
+
import {
|
61
|
+
PackageableConnection,
|
62
|
+
RelationalDatabaseConnection,
|
63
|
+
guaranteeRelationalDatabaseConnection,
|
64
|
+
stringifyDataType,
|
65
|
+
} from '@finos/legend-graph';
|
66
|
+
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../__lib__/LegendStudioApplicationNavigationContext.js';
|
67
|
+
import {
|
68
|
+
DatabaseSchemaExplorerTreeColumnNodeData,
|
69
|
+
DatabaseSchemaExplorerTreeSchemaNodeData,
|
70
|
+
DatabaseSchemaExplorerTreeTableNodeData,
|
71
|
+
type DatabaseSchemaExplorerTreeData,
|
72
|
+
type DatabaseSchemaExplorerTreeNodeData,
|
73
|
+
type SQLPlaygroundPanelState,
|
74
|
+
} from '../../../stores/editor/panel-group/SQLPlaygroundPanelState.js';
|
75
|
+
import { renderColumnTypeIcon } from '../editor-group/connection-editor/DatabaseEditorHelper.js';
|
76
|
+
import { useEditorStore } from '../EditorStoreProvider.js';
|
77
|
+
import { PANEL_MODE } from '../../../stores/editor/EditorConfig.js';
|
78
|
+
import { useDrag, useDrop } from 'react-dnd';
|
79
|
+
import {
|
80
|
+
CORE_DND_TYPE,
|
81
|
+
type ElementDragSource,
|
82
|
+
} from '../../../stores/editor/utils/DnDUtils.js';
|
83
|
+
import { DataGrid } from '@finos/legend-lego/data-grid';
|
84
|
+
import {
|
85
|
+
getNonNullableEntry,
|
86
|
+
getNullableEntry,
|
87
|
+
getNullableLastEntry,
|
88
|
+
isNonNullable,
|
89
|
+
isString,
|
90
|
+
parseCSVString,
|
91
|
+
uniqBy,
|
92
|
+
} from '@finos/legend-shared';
|
93
|
+
|
94
|
+
const getDatabaseSchemaNodeIcon = (
|
95
|
+
node: DatabaseSchemaExplorerTreeNodeData,
|
96
|
+
): React.ReactNode => {
|
97
|
+
if (node instanceof DatabaseSchemaExplorerTreeSchemaNodeData) {
|
98
|
+
return (
|
99
|
+
<div className="sql-playground__database-schema-explorer-tree__icon--schema">
|
100
|
+
<PURE_DatabaseSchemaIcon />
|
101
|
+
</div>
|
102
|
+
);
|
103
|
+
} else if (node instanceof DatabaseSchemaExplorerTreeTableNodeData) {
|
104
|
+
return (
|
105
|
+
<div className="sql-playground__database-schema-explorer-tree__icon--table">
|
106
|
+
<PURE_DatabaseTableIcon />
|
107
|
+
</div>
|
108
|
+
);
|
109
|
+
} else if (node instanceof DatabaseSchemaExplorerTreeColumnNodeData) {
|
110
|
+
return renderColumnTypeIcon(node.column.type);
|
111
|
+
}
|
112
|
+
return null;
|
113
|
+
};
|
114
|
+
|
115
|
+
const DATABASE_NODE_DND_TYPE = 'DATABASE_NODE_DND_TYPE';
|
116
|
+
type DatabaseNodeDragType = { text: string };
|
117
|
+
|
118
|
+
const DatabaseSchemaExplorerTreeNodeContainer: React.FC<
|
119
|
+
TreeNodeContainerProps<
|
120
|
+
DatabaseSchemaExplorerTreeNodeData,
|
121
|
+
{
|
122
|
+
// empty
|
123
|
+
}
|
124
|
+
>
|
125
|
+
> = (props) => {
|
126
|
+
const { node, level, stepPaddingInRem, onNodeSelect } = props;
|
127
|
+
const isExpandable =
|
128
|
+
Boolean(!node.childrenIds || node.childrenIds.length) &&
|
129
|
+
!(node instanceof DatabaseSchemaExplorerTreeColumnNodeData);
|
130
|
+
const nodeExpandIcon = isExpandable ? (
|
131
|
+
node.isOpen ? (
|
132
|
+
<ChevronDownIcon />
|
133
|
+
) : (
|
134
|
+
<ChevronRightIcon />
|
135
|
+
)
|
136
|
+
) : (
|
137
|
+
<div />
|
138
|
+
);
|
139
|
+
const [, nodeDragRef] = useDrag<DatabaseNodeDragType>(
|
140
|
+
() => ({
|
141
|
+
type: DATABASE_NODE_DND_TYPE,
|
142
|
+
item: {
|
143
|
+
text:
|
144
|
+
node instanceof DatabaseSchemaExplorerTreeTableNodeData
|
145
|
+
? `${node.owner.name}.${node.label}`
|
146
|
+
: node.label,
|
147
|
+
},
|
148
|
+
}),
|
149
|
+
[node],
|
150
|
+
);
|
151
|
+
const nodeTypeIcon = getDatabaseSchemaNodeIcon(node);
|
152
|
+
const toggleExpandNode = (): void => onNodeSelect?.(node);
|
153
|
+
const isPrimaryKeyColumn =
|
154
|
+
node instanceof DatabaseSchemaExplorerTreeColumnNodeData &&
|
155
|
+
node.owner.primaryKey.includes(node.column);
|
156
|
+
|
157
|
+
return (
|
158
|
+
<div
|
159
|
+
className={clsx('tree-view__node__container')}
|
160
|
+
style={{
|
161
|
+
paddingLeft: `${level * (stepPaddingInRem ?? 1)}rem`,
|
162
|
+
display: 'flex',
|
163
|
+
}}
|
164
|
+
ref={nodeDragRef}
|
165
|
+
onClick={toggleExpandNode}
|
166
|
+
>
|
167
|
+
<div className="tree-view__node__icon sql-playground__database-schema-explorer-tree__node__icon__group">
|
168
|
+
<div className="sql-playground__database-schema-explorer-tree__expand-icon">
|
169
|
+
{nodeExpandIcon}
|
170
|
+
</div>
|
171
|
+
<div className="sql-playground__database-schema-explorer-tree__type-icon">
|
172
|
+
{nodeTypeIcon}
|
173
|
+
</div>
|
174
|
+
</div>
|
175
|
+
<div className="tree-view__node__label sql-playground__database-schema-explorer-tree__node__label">
|
176
|
+
{node.label}
|
177
|
+
{node instanceof DatabaseSchemaExplorerTreeColumnNodeData && (
|
178
|
+
<div className="sql-playground__database-schema-explorer-tree__node__type">
|
179
|
+
<div className="sql-playground__database-schema-explorer-tree__node__type__label">
|
180
|
+
{stringifyDataType(node.column.type)}
|
181
|
+
</div>
|
182
|
+
</div>
|
183
|
+
)}
|
184
|
+
{isPrimaryKeyColumn && (
|
185
|
+
<div
|
186
|
+
className="sql-playground__database-schema-explorer-tree__node__pk"
|
187
|
+
title="Primary Key"
|
188
|
+
>
|
189
|
+
<KeyIcon />
|
190
|
+
</div>
|
191
|
+
)}
|
192
|
+
</div>
|
193
|
+
</div>
|
194
|
+
);
|
195
|
+
};
|
196
|
+
|
197
|
+
export const DatabaseSchemaExplorer = observer(
|
198
|
+
(props: {
|
199
|
+
treeData: DatabaseSchemaExplorerTreeData;
|
200
|
+
playgroundState: SQLPlaygroundPanelState;
|
201
|
+
}) => {
|
202
|
+
const { treeData, playgroundState } = props;
|
203
|
+
const applicationStore = useApplicationStore();
|
204
|
+
|
205
|
+
const onNodeSelect = (node: DatabaseSchemaExplorerTreeNodeData): void => {
|
206
|
+
flowResult(playgroundState.onNodeSelect(node, treeData)).catch(
|
207
|
+
applicationStore.alertUnhandledError,
|
208
|
+
);
|
209
|
+
};
|
210
|
+
|
211
|
+
const getChildNodes = (
|
212
|
+
node: DatabaseSchemaExplorerTreeNodeData,
|
213
|
+
): DatabaseSchemaExplorerTreeNodeData[] =>
|
214
|
+
playgroundState
|
215
|
+
.getChildNodes(node, treeData)
|
216
|
+
?.sort((a, b) => a.label.localeCompare(b.label)) ?? [];
|
217
|
+
|
218
|
+
return (
|
219
|
+
<TreeView
|
220
|
+
className="sql-playground__database-schema-explorer-tree"
|
221
|
+
components={{
|
222
|
+
TreeNodeContainer: DatabaseSchemaExplorerTreeNodeContainer,
|
223
|
+
}}
|
224
|
+
innerProps={{}}
|
225
|
+
treeData={treeData}
|
226
|
+
onNodeSelect={onNodeSelect}
|
227
|
+
getChildNodes={getChildNodes}
|
228
|
+
/>
|
229
|
+
);
|
230
|
+
},
|
231
|
+
);
|
232
|
+
|
233
|
+
type RelationalDatabaseConnectionOption = {
|
234
|
+
label: React.ReactNode;
|
235
|
+
value: PackageableConnection;
|
236
|
+
};
|
237
|
+
const buildRelationalDatabaseConnectionOption = (
|
238
|
+
connection: PackageableConnection,
|
239
|
+
): RelationalDatabaseConnectionOption => {
|
240
|
+
const connectionValue = guaranteeRelationalDatabaseConnection(connection);
|
241
|
+
return {
|
242
|
+
value: connection,
|
243
|
+
label: (
|
244
|
+
<div className="sql-playground__config__connection-selector__option">
|
245
|
+
<div className="sql-playground__config__connection-selector__option__label">
|
246
|
+
{connection.name}
|
247
|
+
</div>
|
248
|
+
<div className="sql-playground__config__connection-selector__option__type">
|
249
|
+
{connectionValue.type}
|
250
|
+
</div>
|
251
|
+
</div>
|
252
|
+
),
|
253
|
+
};
|
254
|
+
};
|
255
|
+
|
256
|
+
// List of most popular SQL keywords
|
257
|
+
// See https://www.w3schools.com/sql/sql_ref_keywords.asp
|
258
|
+
const SQL_KEYWORDS = [
|
259
|
+
'AND',
|
260
|
+
'AS',
|
261
|
+
'ASC',
|
262
|
+
'BETWEEN',
|
263
|
+
'DESC',
|
264
|
+
'DISTINCT',
|
265
|
+
'EXEC',
|
266
|
+
'EXISTS',
|
267
|
+
'FROM',
|
268
|
+
'FULL OUTER JOIN',
|
269
|
+
'GROUP BY',
|
270
|
+
'HAVING',
|
271
|
+
'IN',
|
272
|
+
'INNER JOIN',
|
273
|
+
'IS NULL',
|
274
|
+
'IS NOT NULL',
|
275
|
+
'JOIN',
|
276
|
+
'LEFT JOIN',
|
277
|
+
'LIKE',
|
278
|
+
'LIMIT',
|
279
|
+
'NOT',
|
280
|
+
'NOT NULL',
|
281
|
+
'OR',
|
282
|
+
'ORDER BY',
|
283
|
+
'OUTER JOIN',
|
284
|
+
'RIGHT JOIN',
|
285
|
+
'SELECT',
|
286
|
+
'SELECT DISTINCT',
|
287
|
+
'SELECT INTO',
|
288
|
+
'SELECT TOP',
|
289
|
+
'TOP',
|
290
|
+
'UNION',
|
291
|
+
'UNION ALL',
|
292
|
+
'UNIQUE',
|
293
|
+
'WHERE',
|
294
|
+
];
|
295
|
+
|
296
|
+
const getKeywordSuggestions = async (
|
297
|
+
position: IPosition,
|
298
|
+
model: monacoEditorAPI.ITextModel,
|
299
|
+
): Promise<monacoLanguagesAPI.CompletionItem[]> =>
|
300
|
+
SQL_KEYWORDS.map(
|
301
|
+
(keyword) =>
|
302
|
+
({
|
303
|
+
label: keyword,
|
304
|
+
kind: monacoLanguagesAPI.CompletionItemKind.Keyword,
|
305
|
+
insertTextRules:
|
306
|
+
monacoLanguagesAPI.CompletionItemInsertTextRule.InsertAsSnippet,
|
307
|
+
insertText: `${keyword} `,
|
308
|
+
} as monacoLanguagesAPI.CompletionItem),
|
309
|
+
);
|
310
|
+
|
311
|
+
const getDatabaseSchemaEntities = async (
|
312
|
+
position: IPosition,
|
313
|
+
model: monacoEditorAPI.ITextModel,
|
314
|
+
playgroundState: SQLPlaygroundPanelState,
|
315
|
+
): Promise<monacoLanguagesAPI.CompletionItem[]> => {
|
316
|
+
if (playgroundState.treeData) {
|
317
|
+
return uniqBy(
|
318
|
+
Array.from(playgroundState.treeData.nodes.values()).map(
|
319
|
+
(value) =>
|
320
|
+
({
|
321
|
+
label: value.label,
|
322
|
+
kind: monacoLanguagesAPI.CompletionItemKind.Field,
|
323
|
+
insertTextRules:
|
324
|
+
monacoLanguagesAPI.CompletionItemInsertTextRule.InsertAsSnippet,
|
325
|
+
insertText: `${value.label} `,
|
326
|
+
} as monacoLanguagesAPI.CompletionItem),
|
327
|
+
),
|
328
|
+
(val) => val.label,
|
329
|
+
);
|
330
|
+
}
|
331
|
+
return [];
|
332
|
+
};
|
333
|
+
|
334
|
+
const PlaygroundSQLCodeEditor = observer(() => {
|
335
|
+
const editorStore = useEditorStore();
|
336
|
+
const playgroundState = editorStore.sqlPlaygroundState;
|
337
|
+
const applicationStore = useApplicationStore();
|
338
|
+
const codeEditorRef = useRef<HTMLDivElement>(null);
|
339
|
+
const [editor, setEditor] = useState<
|
340
|
+
monacoEditorAPI.IStandaloneCodeEditor | undefined
|
341
|
+
>();
|
342
|
+
const sqlIdentifierSuggestionProviderDisposer = useRef<
|
343
|
+
IDisposable | undefined
|
344
|
+
>(undefined);
|
345
|
+
|
346
|
+
const executeRawSQL = (): void => {
|
347
|
+
flowResult(playgroundState.executeRawSQL()).catch(
|
348
|
+
applicationStore.alertUnhandledError,
|
349
|
+
);
|
350
|
+
};
|
351
|
+
const reset = (): void => {
|
352
|
+
playgroundState.resetSQL();
|
353
|
+
};
|
354
|
+
|
355
|
+
useEffect(() => {
|
356
|
+
if (!editor && codeEditorRef.current) {
|
357
|
+
const element = codeEditorRef.current;
|
358
|
+
const newEditor = monacoEditorAPI.create(element, {
|
359
|
+
...getBaseCodeEditorOptions(),
|
360
|
+
theme: CODE_EDITOR_THEME.DEFAULT_DARK,
|
361
|
+
language: CODE_EDITOR_LANGUAGE.SQL,
|
362
|
+
padding: {
|
363
|
+
top: 10,
|
364
|
+
},
|
365
|
+
});
|
366
|
+
|
367
|
+
newEditor.onDidChangeModelContent(() => {
|
368
|
+
const currentVal = newEditor.getValue();
|
369
|
+
playgroundState.setSQLText(currentVal);
|
370
|
+
});
|
371
|
+
|
372
|
+
// Restore the editor model and view state
|
373
|
+
newEditor.setModel(playgroundState.sqlEditorTextModel);
|
374
|
+
if (playgroundState.sqlEditorViewState) {
|
375
|
+
newEditor.restoreViewState(playgroundState.sqlEditorViewState);
|
376
|
+
}
|
377
|
+
newEditor.focus(); // focus on the editor initially
|
378
|
+
playgroundState.setSQLEditor(newEditor);
|
379
|
+
setEditor(newEditor);
|
380
|
+
}
|
381
|
+
}, [playgroundState, applicationStore, editor]);
|
382
|
+
|
383
|
+
useCommands(playgroundState);
|
384
|
+
|
385
|
+
if (editor) {
|
386
|
+
sqlIdentifierSuggestionProviderDisposer.current?.dispose();
|
387
|
+
sqlIdentifierSuggestionProviderDisposer.current =
|
388
|
+
monacoLanguagesAPI.registerCompletionItemProvider(
|
389
|
+
CODE_EDITOR_LANGUAGE.SQL,
|
390
|
+
{
|
391
|
+
triggerCharacters: [],
|
392
|
+
provideCompletionItems: async (model, position, context) => {
|
393
|
+
let suggestions: monacoLanguagesAPI.CompletionItem[] = [];
|
394
|
+
if (
|
395
|
+
context.triggerKind ===
|
396
|
+
monacoLanguagesAPI.CompletionTriggerKind.Invoke
|
397
|
+
) {
|
398
|
+
// keywords
|
399
|
+
suggestions = suggestions.concat(
|
400
|
+
await getKeywordSuggestions(position, model),
|
401
|
+
);
|
402
|
+
|
403
|
+
// database schema entities
|
404
|
+
suggestions = suggestions.concat(
|
405
|
+
await getDatabaseSchemaEntities(
|
406
|
+
position,
|
407
|
+
model,
|
408
|
+
playgroundState,
|
409
|
+
),
|
410
|
+
);
|
411
|
+
}
|
412
|
+
|
413
|
+
return { suggestions };
|
414
|
+
},
|
415
|
+
},
|
416
|
+
);
|
417
|
+
}
|
418
|
+
|
419
|
+
// clean up
|
420
|
+
useEffect(
|
421
|
+
() => (): void => {
|
422
|
+
if (editor) {
|
423
|
+
// persist editor view state (cursor, scroll, etc.) to restore on re-open
|
424
|
+
playgroundState.setSQLEditorViewState(
|
425
|
+
editor.saveViewState() ?? undefined,
|
426
|
+
);
|
427
|
+
editor.dispose();
|
428
|
+
|
429
|
+
// Dispose the providers properly to avoid ending up with duplicated suggestions
|
430
|
+
sqlIdentifierSuggestionProviderDisposer.current?.dispose();
|
431
|
+
}
|
432
|
+
},
|
433
|
+
[playgroundState, editor],
|
434
|
+
);
|
435
|
+
|
436
|
+
const handleDatabaseNodeDrop = useCallback(
|
437
|
+
(item: DatabaseNodeDragType): void => {
|
438
|
+
if (isString(item.text)) {
|
439
|
+
if (playgroundState.sqlEditor) {
|
440
|
+
const currentValue = playgroundState.sqlEditorTextModel.getValue();
|
441
|
+
const lines = currentValue.split('\n');
|
442
|
+
const position = playgroundState.sqlEditor.getPosition() ?? {
|
443
|
+
lineNumber: lines.length,
|
444
|
+
column: getNullableLastEntry(lines)?.length ?? 0,
|
445
|
+
};
|
446
|
+
playgroundState.sqlEditor.executeEdits('', [
|
447
|
+
{
|
448
|
+
range: {
|
449
|
+
startLineNumber: position.lineNumber,
|
450
|
+
startColumn: position.column,
|
451
|
+
endLineNumber: position.lineNumber,
|
452
|
+
endColumn: position.column,
|
453
|
+
},
|
454
|
+
text: item.text,
|
455
|
+
forceMoveMarkers: true,
|
456
|
+
},
|
457
|
+
]);
|
458
|
+
playgroundState.setSQLText(
|
459
|
+
playgroundState.sqlEditorTextModel.getValue(),
|
460
|
+
);
|
461
|
+
}
|
462
|
+
}
|
463
|
+
},
|
464
|
+
[playgroundState],
|
465
|
+
);
|
466
|
+
const [{ isDatabaseNodeDragOver }, dropConnector] = useDrop<
|
467
|
+
DatabaseNodeDragType,
|
468
|
+
void,
|
469
|
+
{ isDatabaseNodeDragOver: boolean }
|
470
|
+
>(
|
471
|
+
() => ({
|
472
|
+
accept: DATABASE_NODE_DND_TYPE,
|
473
|
+
drop: (item): void => handleDatabaseNodeDrop(item),
|
474
|
+
collect: (monitor) => ({
|
475
|
+
isDatabaseNodeDragOver: monitor.isOver({ shallow: true }),
|
476
|
+
}),
|
477
|
+
}),
|
478
|
+
[handleDatabaseNodeDrop],
|
479
|
+
);
|
480
|
+
|
481
|
+
return (
|
482
|
+
<div className="sql-playground__code-editor">
|
483
|
+
<PanelLoadingIndicator isLoading={playgroundState.isExecutingRawSQL} />
|
484
|
+
<div className="sql-playground__code-editor__header">
|
485
|
+
<div className="sql-playground__code-editor__header__actions">
|
486
|
+
<button
|
487
|
+
className="sql-playground__code-editor__header__action"
|
488
|
+
tabIndex={-1}
|
489
|
+
onClick={executeRawSQL}
|
490
|
+
disabled={playgroundState.isExecutingRawSQL}
|
491
|
+
title="Execute (Ctrl + Enter)"
|
492
|
+
>
|
493
|
+
<PlayIcon />
|
494
|
+
</button>
|
495
|
+
<button
|
496
|
+
className="sql-playground__code-editor__header__action"
|
497
|
+
tabIndex={-1}
|
498
|
+
onClick={reset}
|
499
|
+
title="Reset"
|
500
|
+
>
|
501
|
+
<TrashIcon />
|
502
|
+
</button>
|
503
|
+
</div>
|
504
|
+
</div>
|
505
|
+
<PanelDropZone
|
506
|
+
className="sql-playground__code-editor__content"
|
507
|
+
isDragOver={isDatabaseNodeDragOver}
|
508
|
+
dropTargetConnector={dropConnector}
|
509
|
+
>
|
510
|
+
<div className="code-editor__container">
|
511
|
+
<div className="code-editor__body" ref={codeEditorRef} />
|
512
|
+
</div>
|
513
|
+
</PanelDropZone>
|
514
|
+
</div>
|
515
|
+
);
|
516
|
+
});
|
517
|
+
|
518
|
+
const parseExecutionResultData = (
|
519
|
+
data: string,
|
520
|
+
): { rowData: Record<string, string>[]; columns: string[] } | undefined => {
|
521
|
+
const lines = data.split('\n').filter((line) => line.trim().length);
|
522
|
+
if (lines.length) {
|
523
|
+
const columns = parseCSVString(getNonNullableEntry(lines, 0)) ?? [];
|
524
|
+
const rowData = lines
|
525
|
+
.slice(1)
|
526
|
+
.map((item) => {
|
527
|
+
const rowItems = parseCSVString(item);
|
528
|
+
if (!rowItems) {
|
529
|
+
return undefined;
|
530
|
+
}
|
531
|
+
const row: Record<string, string> = {};
|
532
|
+
columns.forEach((column, idx) => {
|
533
|
+
row[column] = getNullableEntry(rowItems, idx) ?? '';
|
534
|
+
});
|
535
|
+
return row;
|
536
|
+
})
|
537
|
+
.filter(isNonNullable);
|
538
|
+
return { rowData, columns };
|
539
|
+
}
|
540
|
+
return undefined;
|
541
|
+
};
|
542
|
+
|
543
|
+
const PlayGroundSQLExecutionResultGrid = observer(
|
544
|
+
(props: { result: string }) => {
|
545
|
+
const { result } = props;
|
546
|
+
const data = parseExecutionResultData(result);
|
547
|
+
|
548
|
+
if (!data) {
|
549
|
+
return (
|
550
|
+
<BlankPanelContent>{`Can't parse result, displaying raw form:\n${result}`}</BlankPanelContent>
|
551
|
+
);
|
552
|
+
}
|
553
|
+
return (
|
554
|
+
<div className="sql-playground__result__grid ag-theme-balham-dark">
|
555
|
+
<DataGrid
|
556
|
+
rowData={data.rowData}
|
557
|
+
overlayNoRowsTemplate={`<div class="sql-playground__result__grid--empty">No results</div>`}
|
558
|
+
alwaysShowVerticalScroll={true}
|
559
|
+
suppressFieldDotNotation={true}
|
560
|
+
columnDefs={data.columns.map((column) => ({
|
561
|
+
minWidth: 50,
|
562
|
+
sortable: true,
|
563
|
+
resizable: true,
|
564
|
+
headerName: column,
|
565
|
+
field: column,
|
566
|
+
flex: 1,
|
567
|
+
}))}
|
568
|
+
/>
|
569
|
+
</div>
|
570
|
+
);
|
571
|
+
},
|
572
|
+
);
|
573
|
+
|
574
|
+
type SQLPlaygroundPanelDropTarget = ElementDragSource;
|
575
|
+
|
576
|
+
export const SQLPlaygroundPanel = observer(() => {
|
577
|
+
const editorStore = useEditorStore();
|
578
|
+
const playgroundState = editorStore.sqlPlaygroundState;
|
579
|
+
const applicationStore = useApplicationStore();
|
580
|
+
|
581
|
+
// connection
|
582
|
+
const connectionSelectorRef = useRef<SelectComponent>(null);
|
583
|
+
const connectionFilterOption = createFilter({
|
584
|
+
ignoreCase: true,
|
585
|
+
ignoreAccents: false,
|
586
|
+
stringify: (option: RelationalDatabaseConnectionOption): string =>
|
587
|
+
option.value.path,
|
588
|
+
});
|
589
|
+
const connectionOptions = editorStore.graphManagerState.usableConnections
|
590
|
+
.filter(
|
591
|
+
(connection) =>
|
592
|
+
connection.connectionValue instanceof RelationalDatabaseConnection,
|
593
|
+
)
|
594
|
+
.map(buildRelationalDatabaseConnectionOption);
|
595
|
+
const selectedConnectionOption = playgroundState.connection
|
596
|
+
? buildRelationalDatabaseConnectionOption(playgroundState.connection)
|
597
|
+
: null;
|
598
|
+
const changeConnection = (val: RelationalDatabaseConnectionOption): void => {
|
599
|
+
if (val.value === playgroundState.connection) {
|
600
|
+
return;
|
601
|
+
}
|
602
|
+
playgroundState.setConnection(val.value);
|
603
|
+
};
|
604
|
+
const onPickConnection = (): void => {
|
605
|
+
editorStore.setQuickInputState({
|
606
|
+
title: 'Connection picker',
|
607
|
+
placeholder: 'Select a connection...',
|
608
|
+
options: connectionOptions,
|
609
|
+
getSearchValue: (option: RelationalDatabaseConnectionOption): string =>
|
610
|
+
option.value.path,
|
611
|
+
onSelect: changeConnection,
|
612
|
+
});
|
613
|
+
};
|
614
|
+
|
615
|
+
const handleConnectionDrop = useCallback(
|
616
|
+
(item: SQLPlaygroundPanelDropTarget): void => {
|
617
|
+
if (item.data.packageableElement instanceof PackageableConnection) {
|
618
|
+
if (
|
619
|
+
item.data.packageableElement.connectionValue instanceof
|
620
|
+
RelationalDatabaseConnection
|
621
|
+
) {
|
622
|
+
playgroundState.setConnection(item.data.packageableElement);
|
623
|
+
} else {
|
624
|
+
applicationStore.notificationService.notifyWarning(
|
625
|
+
`Can't use SQL playground with non-relational database connection`,
|
626
|
+
);
|
627
|
+
}
|
628
|
+
}
|
629
|
+
},
|
630
|
+
[playgroundState, applicationStore],
|
631
|
+
);
|
632
|
+
const [{ isConnectionDragOver }, dropConnector] = useDrop<
|
633
|
+
ElementDragSource,
|
634
|
+
void,
|
635
|
+
{ isConnectionDragOver: boolean }
|
636
|
+
>(
|
637
|
+
() => ({
|
638
|
+
accept: CORE_DND_TYPE.PROJECT_EXPLORER_CONNECTION,
|
639
|
+
drop: (item) => handleConnectionDrop(item),
|
640
|
+
collect: (monitor) => ({
|
641
|
+
isConnectionDragOver: monitor.isOver({ shallow: true }),
|
642
|
+
}),
|
643
|
+
}),
|
644
|
+
[handleConnectionDrop],
|
645
|
+
);
|
646
|
+
|
647
|
+
useEffect(() => {
|
648
|
+
flowResult(playgroundState.fetchDatabaseMetadata()).catch(
|
649
|
+
applicationStore.alertUnhandledError,
|
650
|
+
);
|
651
|
+
}, [playgroundState, applicationStore, playgroundState.connection]);
|
652
|
+
|
653
|
+
useConditionedApplicationNavigationContext(
|
654
|
+
LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SQL_PLAYGROUND,
|
655
|
+
editorStore.activePanelMode === PANEL_MODE.SQL_PLAYGROUND,
|
656
|
+
);
|
657
|
+
|
658
|
+
return (
|
659
|
+
<PanelDropZone
|
660
|
+
isDragOver={isConnectionDragOver}
|
661
|
+
dropTargetConnector={dropConnector}
|
662
|
+
>
|
663
|
+
<div className="sql-playground">
|
664
|
+
{playgroundState.connection && (
|
665
|
+
<ResizablePanelGroup orientation="vertical">
|
666
|
+
<ResizablePanel size={300}>
|
667
|
+
<div className="sql-playground__config">
|
668
|
+
<div className="sql-playground__config__connection-selector">
|
669
|
+
<div className="sql-playground__config__connection-selector__icon">
|
670
|
+
<PURE_ConnectionIcon />
|
671
|
+
</div>
|
672
|
+
<CustomSelectorInput
|
673
|
+
ref={connectionSelectorRef}
|
674
|
+
className="sql-playground__config__connection-selector__input"
|
675
|
+
options={connectionOptions}
|
676
|
+
onChange={changeConnection}
|
677
|
+
value={selectedConnectionOption}
|
678
|
+
darkMode={true}
|
679
|
+
placeholder="Choose a connection..."
|
680
|
+
filterOption={connectionFilterOption}
|
681
|
+
/>
|
682
|
+
</div>
|
683
|
+
<div className="sql-playground__config__schema-explorer">
|
684
|
+
{playgroundState.treeData && (
|
685
|
+
<DatabaseSchemaExplorer
|
686
|
+
treeData={playgroundState.treeData}
|
687
|
+
playgroundState={playgroundState}
|
688
|
+
/>
|
689
|
+
)}
|
690
|
+
</div>
|
691
|
+
</div>
|
692
|
+
</ResizablePanel>
|
693
|
+
<ResizablePanelSplitter />
|
694
|
+
<ResizablePanel>
|
695
|
+
<div className="panel sql-playground__sql-editor">
|
696
|
+
<ResizablePanelGroup orientation="horizontal">
|
697
|
+
<ResizablePanel>
|
698
|
+
<PlaygroundSQLCodeEditor />
|
699
|
+
</ResizablePanel>
|
700
|
+
<ResizablePanelSplitter>
|
701
|
+
<ResizablePanelSplitterLine color="var(--color-dark-grey-250)" />
|
702
|
+
</ResizablePanelSplitter>
|
703
|
+
<ResizablePanel size={300}>
|
704
|
+
{playgroundState.sqlExecutionResult !== undefined && (
|
705
|
+
<PlayGroundSQLExecutionResultGrid
|
706
|
+
result={playgroundState.sqlExecutionResult}
|
707
|
+
/>
|
708
|
+
)}
|
709
|
+
{playgroundState.sqlExecutionResult === undefined && (
|
710
|
+
<div />
|
711
|
+
)}
|
712
|
+
</ResizablePanel>
|
713
|
+
</ResizablePanelGroup>
|
714
|
+
</div>
|
715
|
+
</ResizablePanel>
|
716
|
+
</ResizablePanelGroup>
|
717
|
+
)}
|
718
|
+
{!playgroundState.connection && (
|
719
|
+
<BlankPanelPlaceholder
|
720
|
+
onClick={onPickConnection}
|
721
|
+
clickActionType="add"
|
722
|
+
text="Pick a connection to start"
|
723
|
+
tooltipText="Drop a connection to start..."
|
724
|
+
isDropZoneActive={isConnectionDragOver}
|
725
|
+
/>
|
726
|
+
)}
|
727
|
+
</div>
|
728
|
+
</PanelDropZone>
|
729
|
+
);
|
730
|
+
});
|