@malloy-publisher/sdk 0.0.119 → 0.0.120
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/dist/ServerProvider-49yj-aFb.cjs.js +1 -0
- package/dist/{ServerProvider-v0TajMUn.es.js → ServerProvider-BDgL8SVP.es.js} +355 -429
- package/dist/client/api.d.ts +285 -276
- package/dist/client/configuration.d.ts +1 -1
- package/dist/client/index.cjs.js +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.es.js +43 -46
- package/dist/components/ServerProvider.d.ts +1 -3
- package/dist/index.cjs.js +71 -71
- package/dist/index.es.js +17731 -17830
- package/package.json +1 -1
- package/src/components/Connections/common.ts +2 -0
- package/src/components/Model/Model.tsx +10 -10
- package/src/components/Model/ModelCell.tsx +10 -8
- package/src/components/Model/SourcesExplorer.tsx +7 -6
- package/src/components/Notebook/NotebookCell.tsx +4 -4
- package/src/components/Package/Package.tsx +7 -11
- package/src/components/Project/ConnectionExplorer.tsx +123 -160
- package/src/components/QueryResult/QueryResult.tsx +9 -7
- package/src/components/ServerProvider.tsx +0 -4
- package/src/hooks/useRawQueryData.ts +8 -6
- package/dist/ServerProvider-Bx3fsDOb.cjs.js +0 -1
- package/dist/components/Package/Schedules.d.ts +0 -5
- package/src/components/Package/Schedules.tsx +0 -114
package/package.json
CHANGED
|
@@ -188,6 +188,7 @@ export const connectionFieldsByType: Record<
|
|
|
188
188
|
type: "text",
|
|
189
189
|
},
|
|
190
190
|
],
|
|
191
|
+
duckdb: [],
|
|
191
192
|
};
|
|
192
193
|
|
|
193
194
|
export const attributesFieldName: Record<ConnectionTypeEnum, string> = {
|
|
@@ -196,4 +197,5 @@ export const attributesFieldName: Record<ConnectionTypeEnum, string> = {
|
|
|
196
197
|
snowflake: "snowflakeConnection",
|
|
197
198
|
trino: "trinoConnection",
|
|
198
199
|
mysql: "mysqlConnection",
|
|
200
|
+
duckdb: "duckdbConnection",
|
|
199
201
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "@malloydata/malloy-explorer/styles.css";
|
|
2
|
+
import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
|
|
3
|
+
import ZoomOutMapIcon from "@mui/icons-material/ZoomOutMap";
|
|
2
4
|
import {
|
|
3
5
|
Box,
|
|
4
6
|
IconButton,
|
|
@@ -7,17 +9,15 @@ import {
|
|
|
7
9
|
Tooltip,
|
|
8
10
|
Typography,
|
|
9
11
|
} from "@mui/material";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import "
|
|
13
|
-
import { QueryExplorerResult } from "./SourcesExplorer";
|
|
12
|
+
import React, { useState } from "react";
|
|
13
|
+
import { parseResourceUri } from "../../utils/formatting";
|
|
14
|
+
import { ApiErrorDisplay } from "../ApiErrorDisplay";
|
|
14
15
|
import { Loading } from "../Loading";
|
|
16
|
+
import { ModelCell } from "./ModelCell";
|
|
15
17
|
import { ModelExplorer } from "./ModelExplorer";
|
|
16
18
|
import { ModelExplorerDialog } from "./ModelExplorerDialog";
|
|
17
|
-
import {
|
|
19
|
+
import { QueryExplorerResult } from "./SourcesExplorer";
|
|
18
20
|
import { useModelData } from "./useModelData";
|
|
19
|
-
import React, { useState } from "react";
|
|
20
|
-
import { parseResourceUri } from "../../utils/formatting";
|
|
21
21
|
|
|
22
22
|
interface ModelProps {
|
|
23
23
|
onChange?: (query: QueryExplorerResult) => void;
|
|
@@ -103,8 +103,8 @@ export default function Model({ onChange, resourceUri }: ModelProps) {
|
|
|
103
103
|
>
|
|
104
104
|
Sources
|
|
105
105
|
</Typography>
|
|
106
|
-
<Tooltip title="Click to copy
|
|
107
|
-
<
|
|
106
|
+
<Tooltip title="Click to copy link">
|
|
107
|
+
<LinkOutlinedIcon
|
|
108
108
|
sx={{
|
|
109
109
|
fontSize: "24px",
|
|
110
110
|
color: "#666666",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Box, Typography, IconButton } from "@mui/material";
|
|
2
1
|
import SearchIcon from "@mui/icons-material/Search";
|
|
2
|
+
import { Box, IconButton, Typography } from "@mui/material";
|
|
3
3
|
import React, { useEffect } from "react";
|
|
4
4
|
import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
|
|
5
|
+
import { parseResourceUri } from "../../utils/formatting";
|
|
5
6
|
import { highlight } from "../highlighter";
|
|
6
7
|
import ResultContainer from "../RenderedResult/ResultContainer";
|
|
7
8
|
import ResultsDialog from "../ResultsDialog";
|
|
8
|
-
import { CleanMetricCard, CleanNotebookCell } from "../styles";
|
|
9
|
-
import { parseResourceUri } from "../../utils/formatting";
|
|
10
9
|
import { useServer } from "../ServerProvider";
|
|
10
|
+
import { CleanMetricCard, CleanNotebookCell } from "../styles";
|
|
11
11
|
|
|
12
12
|
interface ModelCellProps {
|
|
13
13
|
sourceName?: string;
|
|
@@ -37,14 +37,16 @@ export function ModelCell({
|
|
|
37
37
|
} = useQueryWithApiError({
|
|
38
38
|
queryKey: ["namedQueryResult", resourceUri, queryName],
|
|
39
39
|
queryFn: () =>
|
|
40
|
-
apiClients.
|
|
40
|
+
apiClients.models.executeQueryModel(
|
|
41
41
|
projectName,
|
|
42
42
|
packageName,
|
|
43
43
|
modelPath,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
{
|
|
45
|
+
query: undefined,
|
|
46
|
+
sourceName: undefined,
|
|
47
|
+
queryName: queryName,
|
|
48
|
+
versionId: versionId,
|
|
49
|
+
},
|
|
48
50
|
),
|
|
49
51
|
enabled: true, // Always execute
|
|
50
52
|
});
|
|
@@ -173,15 +173,16 @@ function SourceExplorerComponentInner({
|
|
|
173
173
|
...query,
|
|
174
174
|
query: malloy,
|
|
175
175
|
});
|
|
176
|
-
return apiClients.
|
|
176
|
+
return apiClients.models.executeQueryModel(
|
|
177
177
|
projectName,
|
|
178
178
|
packageName,
|
|
179
179
|
sourceAndPath.modelPath,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
{
|
|
181
|
+
query: malloy,
|
|
182
|
+
sourceName: undefined,
|
|
183
|
+
queryName: undefined,
|
|
184
|
+
versionId: versionId,
|
|
185
|
+
},
|
|
185
186
|
);
|
|
186
187
|
},
|
|
187
188
|
onSuccess: (data) => {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import CloseIcon from "@mui/icons-material/Close";
|
|
2
2
|
import CodeIcon from "@mui/icons-material/Code";
|
|
3
3
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
4
|
+
import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
|
|
4
5
|
import SearchIcon from "@mui/icons-material/Search";
|
|
5
|
-
import ShareIcon from "@mui/icons-material/Share";
|
|
6
6
|
import {
|
|
7
7
|
Box,
|
|
8
8
|
Dialog,
|
|
9
9
|
DialogContent,
|
|
10
10
|
DialogTitle,
|
|
11
11
|
IconButton,
|
|
12
|
+
Snackbar,
|
|
12
13
|
Stack,
|
|
13
14
|
Tooltip,
|
|
14
15
|
Typography,
|
|
15
|
-
Snackbar,
|
|
16
16
|
} from "@mui/material";
|
|
17
17
|
import Markdown from "markdown-to-jsx";
|
|
18
18
|
import React, { useEffect, useState } from "react";
|
|
@@ -176,8 +176,8 @@ export function NotebookCell({
|
|
|
176
176
|
justifyContent="space-between"
|
|
177
177
|
>
|
|
178
178
|
<Markdown>{cell.text}</Markdown>
|
|
179
|
-
<Tooltip title="Click to copy
|
|
180
|
-
<
|
|
179
|
+
<Tooltip title="Click to copy link">
|
|
180
|
+
<LinkOutlinedIcon
|
|
181
181
|
sx={{
|
|
182
182
|
fontSize: "24px",
|
|
183
183
|
color: "#666666",
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Box, Grid } from "@mui/material";
|
|
2
|
+
import { encodeResourceUri, parseResourceUri } from "../../utils/formatting";
|
|
2
3
|
import { Notebook } from "../Notebook";
|
|
3
|
-
import Config from "./Config";
|
|
4
|
-
import Connections from "./Connections";
|
|
5
|
-
import Databases from "./Databases";
|
|
6
|
-
import Models from "./Models";
|
|
7
|
-
import Notebooks from "./Notebooks";
|
|
8
|
-
import Schedules from "./Schedules";
|
|
9
4
|
import {
|
|
10
5
|
PackageCard,
|
|
11
6
|
PackageCardContent,
|
|
12
7
|
PackageSectionTitle,
|
|
13
8
|
} from "../styles";
|
|
14
|
-
import
|
|
9
|
+
import Config from "./Config";
|
|
10
|
+
import Connections from "./Connections";
|
|
11
|
+
import Databases from "./Databases";
|
|
12
|
+
import Models from "./Models";
|
|
13
|
+
import Notebooks from "./Notebooks";
|
|
15
14
|
|
|
16
15
|
const README_NOTEBOOK = "README.malloynb";
|
|
17
16
|
|
|
@@ -59,9 +58,6 @@ export default function Package({
|
|
|
59
58
|
<Grid size={{ xs: 12, md: 6 }}>
|
|
60
59
|
<Connections resourceUri={resourceUri} />
|
|
61
60
|
</Grid>
|
|
62
|
-
<Grid size={{ xs: 12, md: 12 }}>
|
|
63
|
-
<Schedules resourceUri={resourceUri} />
|
|
64
|
-
</Grid>
|
|
65
61
|
<Grid size={{ xs: 12, md: 12 }}>
|
|
66
62
|
<PackageCard>
|
|
67
63
|
<PackageCardContent>
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import {
|
|
3
2
|
Box,
|
|
3
|
+
Divider,
|
|
4
|
+
FormControlLabel,
|
|
5
|
+
Grid,
|
|
4
6
|
List,
|
|
5
7
|
ListItemButton,
|
|
6
8
|
ListItemText,
|
|
7
|
-
Typography,
|
|
8
|
-
Divider,
|
|
9
9
|
Paper,
|
|
10
|
-
Grid,
|
|
11
10
|
Switch,
|
|
12
|
-
FormControlLabel,
|
|
13
11
|
Table,
|
|
14
12
|
TableBody,
|
|
15
13
|
TableCell,
|
|
16
14
|
TableContainer,
|
|
17
15
|
TableHead,
|
|
18
16
|
TableRow,
|
|
19
|
-
|
|
17
|
+
Typography,
|
|
20
18
|
} from "@mui/material";
|
|
21
|
-
import
|
|
22
|
-
import { Loading } from "../Loading";
|
|
19
|
+
import React from "react";
|
|
23
20
|
import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
|
|
24
21
|
import { parseResourceUri } from "../../utils/formatting";
|
|
22
|
+
import { ApiErrorDisplay } from "../ApiErrorDisplay";
|
|
23
|
+
import { Loading } from "../Loading";
|
|
25
24
|
import { useServer } from "../ServerProvider";
|
|
26
25
|
|
|
27
26
|
interface ConnectionExplorerProps {
|
|
@@ -37,19 +36,30 @@ export default function ConnectionExplorer({
|
|
|
37
36
|
}: ConnectionExplorerProps) {
|
|
38
37
|
const { apiClients } = useServer();
|
|
39
38
|
const { projectName: projectName } = parseResourceUri(resourceUri);
|
|
40
|
-
const [selectedTable, setSelectedTable] = React.useState<
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const [selectedTable, setSelectedTable] = React.useState<
|
|
40
|
+
| { resource: string; columns: Array<{ name: string; type: string }> }
|
|
41
|
+
| undefined
|
|
42
|
+
>(undefined);
|
|
43
43
|
const [selectedSchema, setSelectedSchema] = React.useState<string | null>(
|
|
44
44
|
schema || null,
|
|
45
45
|
);
|
|
46
46
|
const [showHiddenSchemas, setShowHiddenSchemas] = React.useState(false);
|
|
47
|
-
const {
|
|
48
|
-
|
|
47
|
+
const {
|
|
48
|
+
data: schemasData,
|
|
49
|
+
isError: schemasError,
|
|
50
|
+
isLoading: schemasLoading,
|
|
51
|
+
error: schemasErrorObj,
|
|
52
|
+
} = useQueryWithApiError({
|
|
53
|
+
queryKey: ["schemas", projectName, connectionName],
|
|
49
54
|
queryFn: () =>
|
|
50
55
|
apiClients.connections.listSchemas(projectName, connectionName),
|
|
51
56
|
});
|
|
52
57
|
|
|
58
|
+
const availableSchemas =
|
|
59
|
+
schemasData?.data
|
|
60
|
+
?.map((schema: { name: string }) => schema.name)
|
|
61
|
+
.sort() || [];
|
|
62
|
+
|
|
53
63
|
return (
|
|
54
64
|
<Grid container spacing={1}>
|
|
55
65
|
{!schema && (
|
|
@@ -82,74 +92,39 @@ export default function ConnectionExplorer({
|
|
|
82
92
|
<Box
|
|
83
93
|
sx={{ mt: "2px", maxHeight: "600px", overflowY: "auto" }}
|
|
84
94
|
>
|
|
85
|
-
{
|
|
86
|
-
{
|
|
95
|
+
{schemasLoading && <Loading text="Loading schemas..." />}
|
|
96
|
+
{schemasError && (
|
|
87
97
|
<ApiErrorDisplay
|
|
88
|
-
error={
|
|
89
|
-
context={`${projectName} > ${connectionName}`}
|
|
98
|
+
error={schemasErrorObj}
|
|
99
|
+
context={`${projectName} > ${connectionName} > Schemas`}
|
|
90
100
|
/>
|
|
91
101
|
)}
|
|
92
|
-
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
? fullDescription.split(/\r?\n/)[0]
|
|
119
|
-
: undefined;
|
|
120
|
-
|
|
121
|
-
const item = (
|
|
122
|
-
<ListItemButton
|
|
123
|
-
key={schema.name}
|
|
124
|
-
selected={
|
|
125
|
-
selectedSchema === schema.name
|
|
126
|
-
}
|
|
127
|
-
onClick={() =>
|
|
128
|
-
setSelectedSchema(schema.name)
|
|
129
|
-
}
|
|
130
|
-
>
|
|
131
|
-
<ListItemText
|
|
132
|
-
primary={schema.name}
|
|
133
|
-
secondary={firstLine}
|
|
134
|
-
/>
|
|
135
|
-
</ListItemButton>
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
return hasDescription ? (
|
|
139
|
-
<Tooltip
|
|
140
|
-
key={schema.name}
|
|
141
|
-
title={fullDescription}
|
|
142
|
-
arrow
|
|
143
|
-
>
|
|
144
|
-
{item}
|
|
145
|
-
</Tooltip>
|
|
146
|
-
) : (
|
|
147
|
-
item
|
|
148
|
-
);
|
|
149
|
-
},
|
|
150
|
-
)}
|
|
151
|
-
</List>
|
|
152
|
-
)}
|
|
102
|
+
{!schemasLoading &&
|
|
103
|
+
!schemasError &&
|
|
104
|
+
availableSchemas.length === 0 && (
|
|
105
|
+
<Typography variant="body2">No Schemas</Typography>
|
|
106
|
+
)}
|
|
107
|
+
{!schemasLoading &&
|
|
108
|
+
!schemasError &&
|
|
109
|
+
availableSchemas.length > 0 && (
|
|
110
|
+
<List dense disablePadding>
|
|
111
|
+
{availableSchemas.map((schemaName: string) => {
|
|
112
|
+
const isSelected =
|
|
113
|
+
selectedSchema === schemaName;
|
|
114
|
+
return (
|
|
115
|
+
<ListItemButton
|
|
116
|
+
key={schemaName}
|
|
117
|
+
selected={isSelected}
|
|
118
|
+
onClick={() =>
|
|
119
|
+
setSelectedSchema(schemaName)
|
|
120
|
+
}
|
|
121
|
+
>
|
|
122
|
+
<ListItemText primary={schemaName} />
|
|
123
|
+
</ListItemButton>
|
|
124
|
+
);
|
|
125
|
+
})}
|
|
126
|
+
</List>
|
|
127
|
+
)}
|
|
153
128
|
</Box>
|
|
154
129
|
</Paper>
|
|
155
130
|
</Grid>
|
|
@@ -160,8 +135,8 @@ export default function ConnectionExplorer({
|
|
|
160
135
|
<TablesInSchema
|
|
161
136
|
connectionName={connectionName}
|
|
162
137
|
schemaName={selectedSchema}
|
|
163
|
-
onTableClick={(
|
|
164
|
-
setSelectedTable(
|
|
138
|
+
onTableClick={(table) => {
|
|
139
|
+
setSelectedTable(table);
|
|
165
140
|
}}
|
|
166
141
|
resourceUri={resourceUri}
|
|
167
142
|
/>
|
|
@@ -169,14 +144,9 @@ export default function ConnectionExplorer({
|
|
|
169
144
|
)}
|
|
170
145
|
</Grid>
|
|
171
146
|
<Grid size={{ xs: 12, md: schema ? 6 : 4 }}>
|
|
172
|
-
{selectedTable &&
|
|
147
|
+
{selectedTable && (
|
|
173
148
|
<Paper sx={{ p: 1, m: 0 }}>
|
|
174
|
-
<TableSchemaViewer
|
|
175
|
-
connectionName={connectionName}
|
|
176
|
-
schemaName={selectedSchema}
|
|
177
|
-
tableName={selectedTable}
|
|
178
|
-
resourceUri={resourceUri}
|
|
179
|
-
/>
|
|
149
|
+
<TableSchemaViewer table={selectedTable} />
|
|
180
150
|
</Paper>
|
|
181
151
|
)}
|
|
182
152
|
</Grid>
|
|
@@ -185,76 +155,42 @@ export default function ConnectionExplorer({
|
|
|
185
155
|
}
|
|
186
156
|
|
|
187
157
|
type TableSchemaViewerProps = {
|
|
188
|
-
|
|
189
|
-
schemaName: string;
|
|
190
|
-
tableName: string;
|
|
191
|
-
resourceUri: string;
|
|
158
|
+
table: { resource: string; columns: Array<{ name: string; type: string }> };
|
|
192
159
|
};
|
|
193
160
|
|
|
194
|
-
function TableSchemaViewer({
|
|
195
|
-
connectionName,
|
|
196
|
-
schemaName,
|
|
197
|
-
tableName,
|
|
198
|
-
resourceUri,
|
|
199
|
-
}: TableSchemaViewerProps) {
|
|
200
|
-
const { apiClients } = useServer();
|
|
201
|
-
const { projectName: projectName } = parseResourceUri(resourceUri);
|
|
202
|
-
const { data, isSuccess, isError, error, isLoading } = useQueryWithApiError({
|
|
203
|
-
queryKey: [
|
|
204
|
-
"tablePathSchema",
|
|
205
|
-
projectName,
|
|
206
|
-
connectionName,
|
|
207
|
-
schemaName,
|
|
208
|
-
tableName,
|
|
209
|
-
],
|
|
210
|
-
queryFn: () =>
|
|
211
|
-
apiClients.connections.getTablesource(
|
|
212
|
-
projectName,
|
|
213
|
-
connectionName,
|
|
214
|
-
tableName,
|
|
215
|
-
`${schemaName}.${tableName}`,
|
|
216
|
-
),
|
|
217
|
-
});
|
|
218
|
-
|
|
161
|
+
function TableSchemaViewer({ table }: TableSchemaViewerProps) {
|
|
219
162
|
return (
|
|
220
163
|
<>
|
|
221
164
|
<Typography variant="overline" fontWeight="bold">
|
|
222
|
-
Schema: {
|
|
165
|
+
Schema: {table.resource}
|
|
223
166
|
</Typography>
|
|
224
167
|
<Divider />
|
|
225
168
|
<Box sx={{ mt: "10px", maxHeight: "600px", overflowY: "auto" }}>
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
</TableRow>
|
|
252
|
-
),
|
|
253
|
-
)}
|
|
254
|
-
</TableBody>
|
|
255
|
-
</Table>
|
|
256
|
-
</TableContainer>
|
|
257
|
-
)}
|
|
169
|
+
<TableContainer>
|
|
170
|
+
<Table
|
|
171
|
+
size="small"
|
|
172
|
+
sx={{ "& .MuiTableCell-root": { padding: "10px" } }}
|
|
173
|
+
>
|
|
174
|
+
<TableHead>
|
|
175
|
+
<TableRow>
|
|
176
|
+
<TableCell>NAME</TableCell>
|
|
177
|
+
<TableCell>TYPE</TableCell>
|
|
178
|
+
</TableRow>
|
|
179
|
+
</TableHead>
|
|
180
|
+
<TableBody>
|
|
181
|
+
{table.columns
|
|
182
|
+
?.sort((a: { name: string }, b: { name: string }) =>
|
|
183
|
+
a.name.localeCompare(b.name),
|
|
184
|
+
)
|
|
185
|
+
?.map((column: { name: string; type: string }) => (
|
|
186
|
+
<TableRow key={column.name}>
|
|
187
|
+
<TableCell>{column.name}</TableCell>
|
|
188
|
+
<TableCell>{column.type}</TableCell>
|
|
189
|
+
</TableRow>
|
|
190
|
+
))}
|
|
191
|
+
</TableBody>
|
|
192
|
+
</Table>
|
|
193
|
+
</TableContainer>
|
|
258
194
|
</Box>
|
|
259
195
|
</>
|
|
260
196
|
);
|
|
@@ -263,7 +199,10 @@ function TableSchemaViewer({
|
|
|
263
199
|
interface TablesInSchemaProps {
|
|
264
200
|
connectionName: string;
|
|
265
201
|
schemaName: string;
|
|
266
|
-
onTableClick: (
|
|
202
|
+
onTableClick: (table: {
|
|
203
|
+
resource: string;
|
|
204
|
+
columns: Array<{ name: string; type: string }>;
|
|
205
|
+
}) => void;
|
|
267
206
|
resourceUri: string;
|
|
268
207
|
}
|
|
269
208
|
|
|
@@ -299,19 +238,43 @@ function TablesInSchema({
|
|
|
299
238
|
context={`${projectName} > ${connectionName} > ${schemaName}`}
|
|
300
239
|
/>
|
|
301
240
|
)}
|
|
302
|
-
{isSuccess && data
|
|
241
|
+
{isSuccess && data?.data?.length === 0 && (
|
|
303
242
|
<Typography variant="body2">No Tables</Typography>
|
|
304
243
|
)}
|
|
305
|
-
{isSuccess && data.data.length > 0 && (
|
|
244
|
+
{isSuccess && data?.data && data.data.length > 0 && (
|
|
306
245
|
<List dense disablePadding>
|
|
307
|
-
{data.data
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
246
|
+
{data.data
|
|
247
|
+
.sort(
|
|
248
|
+
(a: { resource: string }, b: { resource: string }) => {
|
|
249
|
+
// Extract table names for sorting
|
|
250
|
+
const tableNameA =
|
|
251
|
+
a.resource.split(".").pop() || a.resource;
|
|
252
|
+
const tableNameB =
|
|
253
|
+
b.resource.split(".").pop() || b.resource;
|
|
254
|
+
return tableNameA.localeCompare(tableNameB);
|
|
255
|
+
},
|
|
256
|
+
)
|
|
257
|
+
.map(
|
|
258
|
+
(table: {
|
|
259
|
+
resource: string;
|
|
260
|
+
columns: Array<{ name: string; type: string }>;
|
|
261
|
+
}) => {
|
|
262
|
+
// Extract table name from resource path (e.g., "schema.table_name" -> "table_name")
|
|
263
|
+
const tableName =
|
|
264
|
+
table.resource.split(".").pop() || table.resource;
|
|
265
|
+
return (
|
|
266
|
+
<ListItemButton
|
|
267
|
+
key={table.resource}
|
|
268
|
+
onClick={() => onTableClick(table)}
|
|
269
|
+
>
|
|
270
|
+
<ListItemText
|
|
271
|
+
primary={tableName}
|
|
272
|
+
secondary={`${table.columns.length} columns`}
|
|
273
|
+
/>
|
|
274
|
+
</ListItemButton>
|
|
275
|
+
);
|
|
276
|
+
},
|
|
277
|
+
)}
|
|
315
278
|
</List>
|
|
316
279
|
)}
|
|
317
280
|
</Box>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Suspense, lazy } from "react";
|
|
2
|
-
import { ApiErrorDisplay } from "../ApiErrorDisplay";
|
|
3
|
-
import { Loading } from "../Loading";
|
|
4
2
|
import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
|
|
5
3
|
import { parseResourceUri } from "../../utils/formatting";
|
|
4
|
+
import { ApiErrorDisplay } from "../ApiErrorDisplay";
|
|
5
|
+
import { Loading } from "../Loading";
|
|
6
6
|
import { useServer } from "../ServerProvider";
|
|
7
7
|
|
|
8
8
|
const RenderedResult = lazy(() => import("../RenderedResult/RenderedResult"));
|
|
@@ -77,14 +77,16 @@ export default function QueryResult({
|
|
|
77
77
|
const { data, isSuccess, isError, error } = useQueryWithApiError({
|
|
78
78
|
queryKey: [resourceUri, query, sourceName, queryName],
|
|
79
79
|
queryFn: () =>
|
|
80
|
-
apiClients.
|
|
80
|
+
apiClients.models.executeQueryModel(
|
|
81
81
|
projectName,
|
|
82
82
|
packageName,
|
|
83
83
|
modelPath,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
{
|
|
85
|
+
query: query,
|
|
86
|
+
sourceName: sourceName,
|
|
87
|
+
queryName: queryName,
|
|
88
|
+
versionId: versionId,
|
|
89
|
+
},
|
|
88
90
|
),
|
|
89
91
|
});
|
|
90
92
|
|
|
@@ -8,8 +8,6 @@ import {
|
|
|
8
8
|
NotebooksApi,
|
|
9
9
|
PackagesApi,
|
|
10
10
|
ProjectsApi,
|
|
11
|
-
QueryresultsApi,
|
|
12
|
-
SchedulesApi,
|
|
13
11
|
WatchModeApi,
|
|
14
12
|
} from "../client";
|
|
15
13
|
import { Configuration } from "../client/configuration";
|
|
@@ -65,14 +63,12 @@ const getApiClients = (
|
|
|
65
63
|
const config = new Configuration({ basePath });
|
|
66
64
|
|
|
67
65
|
return {
|
|
68
|
-
queryResults: new QueryresultsApi(config, basePath, axiosInstance),
|
|
69
66
|
models: new ModelsApi(config, basePath, axiosInstance),
|
|
70
67
|
projects: new ProjectsApi(config, basePath, axiosInstance),
|
|
71
68
|
packages: new PackagesApi(config, basePath, axiosInstance),
|
|
72
69
|
notebooks: new NotebooksApi(config, basePath, axiosInstance),
|
|
73
70
|
connections: new ConnectionsApi(config, basePath, axiosInstance),
|
|
74
71
|
databases: new DatabasesApi(config, basePath, axiosInstance),
|
|
75
|
-
schedules: new SchedulesApi(config, basePath, axiosInstance),
|
|
76
72
|
watchMode: new WatchModeApi(config, basePath, axiosInstance),
|
|
77
73
|
};
|
|
78
74
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { useServer } from "../components/ServerProvider";
|
|
1
2
|
import { parseResourceUri } from "../utils/formatting";
|
|
2
3
|
import { useQueryWithApiError } from "./useQueryWithApiError";
|
|
3
|
-
import { useServer } from "../components/ServerProvider";
|
|
4
4
|
|
|
5
5
|
interface UseRawQueryDataProps {
|
|
6
6
|
modelPath: string;
|
|
@@ -35,14 +35,16 @@ export function useRawQueryData({
|
|
|
35
35
|
queryName,
|
|
36
36
|
],
|
|
37
37
|
queryFn: () =>
|
|
38
|
-
apiClients.
|
|
38
|
+
apiClients.models.executeQueryModel(
|
|
39
39
|
projectName,
|
|
40
40
|
packageName,
|
|
41
41
|
modelPath,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
{
|
|
43
|
+
query: query,
|
|
44
|
+
sourceName: sourceName,
|
|
45
|
+
queryName: queryName,
|
|
46
|
+
versionId: versionId,
|
|
47
|
+
},
|
|
46
48
|
),
|
|
47
49
|
enabled,
|
|
48
50
|
});
|