@marimo-team/frontend 0.16.1 → 0.16.2
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/assets/{ConnectedDataExplorerComponent-2wVcyvDj.js → ConnectedDataExplorerComponent-B5cPvWoQ.js} +1 -1
- package/dist/assets/{ImageComparisonComponent-D2j6i0hv.js → ImageComparisonComponent-CqR26LSv.js} +1 -1
- package/dist/assets/{VegaLite-BckFaf2D.js → VegaLite-DvQDATwI.js} +1 -1
- package/dist/assets/_baseEach--KDTwKbG.js +1 -0
- package/dist/assets/_baseMap-Cu3o-eyO.js +1 -0
- package/dist/assets/{_baseUniq-BKktIGQ1.js → _baseUniq-y7ZXnMo1.js} +1 -1
- package/dist/assets/{_createAggregator-C5CVY-0t.js → _createAggregator-ZcHkHPNJ.js} +1 -1
- package/dist/assets/{agent-panel-RGLNjkYe.js → agent-panel-B91RoLct.js} +6 -6
- package/dist/assets/{any-language-editor-DjuXwGCA.js → any-language-editor-CxfHcm5h.js} +1 -1
- package/dist/assets/{architectureDiagram-W76B3OCA-Dyj4ds_R.js → architectureDiagram-W76B3OCA-BQsvK8uR.js} +1 -1
- package/dist/assets/{between-horizontal-start-Dt2aKpPf.js → between-horizontal-start-BmYToIaM.js} +1 -1
- package/dist/assets/{blockDiagram-QIGZ2CNN-o-i7DDvN.js → blockDiagram-QIGZ2CNN-r3HgCj4w.js} +1 -1
- package/dist/assets/{c4Diagram-FPNF74CW-DGHEwWrx.js → c4Diagram-FPNF74CW-BJbPNt41.js} +1 -1
- package/dist/assets/channel-DFaEx1fu.js +1 -0
- package/dist/assets/{chat-panel-9alr8FS4.js → chat-panel-IoPMv8e2.js} +3 -3
- package/dist/assets/{chunk-4BX2VUAB-BJecb-Ri.js → chunk-4BX2VUAB-Dv4MZ9Hj.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-CAATkc4w.js → chunk-55IACEB6-CM4AHquB.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DPuNbQ-f.js → chunk-FMBD7UC4-C_Zz0ENB.js} +1 -1
- package/dist/assets/{chunk-K7UQS3LO-C8TWVLiH.js → chunk-K7UQS3LO-DYSmiXYq.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-DiZZ09q4.js → chunk-QN33PNHL-QM4OPuQP.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BIUM7usu.js → chunk-QZHKN3VN-CfAsGyeB.js} +1 -1
- package/dist/assets/{chunk-TVAH2DTR-vGTArPBG.js → chunk-TVAH2DTR-6j_Cpjsi.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-D2KRqp_x.js → chunk-TZMSLE5B-BHslFJQE.js} +1 -1
- package/dist/assets/{circle-play-cjeNez0N.js → circle-play-CK3UZRYQ.js} +1 -1
- package/dist/assets/classDiagram-KNZD7YFC-BsZtvV5O.js +1 -0
- package/dist/assets/classDiagram-v2-RKCZMP56-BsZtvV5O.js +1 -0
- package/dist/assets/{clear-button-C97JtAez.js → clear-button-C4fDVSv8.js} +1 -1
- package/dist/assets/clone-YBEvPE-s.js +1 -0
- package/dist/assets/command-palette-D7hOfvf6.js +1 -0
- package/dist/assets/{common-Du9rSOwD.js → common-D-lbuUwz.js} +1 -1
- package/dist/assets/{compile-CZXqyOxa.js → compile-DVQe1Mzk.js} +1 -1
- package/dist/assets/{cose-bilkent-S5V4N54A-CqUN5Y9b.js → cose-bilkent-S5V4N54A-D-IS7WC8.js} +1 -1
- package/dist/assets/{dagre-5GWH7T2D-RJqTI9DM.js → dagre-5GWH7T2D-lYu-tEWT.js} +1 -1
- package/dist/assets/{data-grid-overlay-editor-DZN0q1LV.js → data-grid-overlay-editor-C5peOCit.js} +1 -1
- package/dist/assets/datasources-panel-D3NA20uZ.js +1 -0
- package/dist/assets/{dependency-graph-panel-CEog_O7V.js → dependency-graph-panel-BGVYOfkV.js} +1 -1
- package/dist/assets/{diagram-N5W7TBWH-D-l4zZ9d.js → diagram-N5W7TBWH-BnvIuYUp.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-CCOmBUt-.js → diagram-QEK2KX5R-DemedRK3.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-C_I_9jnZ.js → diagram-S2PKOQOG-iiY7AuyH.js} +1 -1
- package/dist/assets/{documentation-panel-C1BtMZ3M.js → documentation-panel-C3dSwOSQ.js} +1 -1
- package/dist/assets/{edit-page-B-oevUZ9.js → edit-page-C5TsEeSo.js} +17 -17
- package/dist/assets/{ellipsis-vertical-BEb-J8z6.js → ellipsis-vertical-CazJl8M7.js} +1 -1
- package/dist/assets/{empty-state-C99UyDE3.js → empty-state-DW308mFO.js} +1 -1
- package/dist/assets/{erDiagram-AWTI2OKA-BePOLi5M.js → erDiagram-AWTI2OKA-6wQ8Ugg0.js} +1 -1
- package/dist/assets/{error-panel-Bs34jXFh.js → error-panel-D1VnJ1yP.js} +1 -1
- package/dist/assets/{file-explorer-panel-Ck6UL861.js → file-explorer-panel-0oVd4t-D.js} +1 -1
- package/dist/assets/{flowDiagram-PVAE7QVJ-BgjFu5l7.js → flowDiagram-PVAE7QVJ-C55IUWjm.js} +1 -1
- package/dist/assets/{ganttDiagram-OWAHRB6G-YOPb3XSV.js → ganttDiagram-OWAHRB6G-DmqCM6ME.js} +1 -1
- package/dist/assets/{gitGraphDiagram-NY62KEGX-CGhqaDTy.js → gitGraphDiagram-NY62KEGX-DBvhAeM_.js} +1 -1
- package/dist/assets/{glide-data-editor-9QUH6iso.js → glide-data-editor-CHNuHidQ.js} +11 -11
- package/dist/assets/{graph-DQQFGrho.js → graph-CG6BgUWQ.js} +1 -1
- package/dist/assets/{home-page-DRKpPCrF.js → home-page-dgivXuSR.js} +3 -3
- package/dist/assets/{index-SGLNXrGP.js → index-BTGpssVX.js} +1 -1
- package/dist/assets/{index-Aeo6WiK7.js → index-BYVZlBF8.js} +1 -1
- package/dist/assets/{index-CUFv_thQ.js → index-BelfnXwL.js} +1 -1
- package/dist/assets/{index-DdnKZNxM.js → index-BneyUujp.js} +1 -1
- package/dist/assets/{index-BJNCMUmG.js → index-C02SqeRj.js} +1 -1
- package/dist/assets/{index-aE43R74q.js → index-C7dtgr9A.js} +1 -1
- package/dist/assets/{index-C2MD0vgD.js → index-CAQvMTzM.js} +1 -1
- package/dist/assets/index-CGDMlQfO.css +1 -0
- package/dist/assets/index-CelXfcd8.js +580 -0
- package/dist/assets/{index-C_tkBKNO.js → index-Csd6QrCV.js} +1 -1
- package/dist/assets/{index-BAbIIxHU.js → index-CtPksxf0.js} +1 -1
- package/dist/assets/{index-2252nrk6.js → index-Cxyk7pt-.js} +1 -1
- package/dist/assets/{index-BW3k9Gss.js → index-DAZ-9ri2.js} +1 -1
- package/dist/assets/{index-ClzeQrN7.js → index-DONRrmA2.js} +1 -1
- package/dist/assets/{index-B8jXZ12t.js → index-Db36XTG_.js} +1 -1
- package/dist/assets/{index-BprjMYH5.js → index-DdIhdEVw.js} +1 -1
- package/dist/assets/{index-CFKO7WXI.js → index-M_pBKDSe.js} +1 -1
- package/dist/assets/{index-CfaDbEdi.js → index-_luCZMLM.js} +1 -1
- package/dist/assets/{index-BjgnbONl.js → index-mkubqy9-.js} +1 -1
- package/dist/assets/{index-C1ez98sk.js → index-sbO9UaUU.js} +1 -1
- package/dist/assets/{index-G5QZppK2.js → index-z4krxQ4j.js} +1 -1
- package/dist/assets/infoDiagram-STP46IZ2-wTALjfPc.js +2 -0
- package/dist/assets/{isEmpty-D-4c7sMv.js → isEmpty-CqX_YTIf.js} +1 -1
- package/dist/assets/{journeyDiagram-BIP6EPQ6-C94u3Mv3.js → journeyDiagram-BIP6EPQ6-Y5w_Tqe_.js} +1 -1
- package/dist/assets/{kanban-definition-6OIFK2YF-BEXYFzz7.js → kanban-definition-6OIFK2YF-DbXs5Rxi.js} +1 -1
- package/dist/assets/{layout-Bz2BJ2ru.js → layout-BCNPDACj.js} +1 -1
- package/dist/assets/{linear-D8s7K76e.js → linear-uO6UVhXt.js} +1 -1
- package/dist/assets/{links-BpXlz1GG.js → links-Drv7cJgN.js} +3 -3
- package/dist/assets/{logs-panel-DC7wpmPz.js → logs-panel-BEQ1eRUp.js} +1 -1
- package/dist/assets/{markdown-renderer-DRdSWR9X.js → markdown-renderer-Dmzbb00W.js} +3 -3
- package/dist/assets/{mermaid-Y3x4hmD0.js → mermaid-qRc4MXIj.js} +1 -1
- package/dist/assets/{mermaid.core-DzthE35Y.js → mermaid.core-CvvJtCRj.js} +4 -4
- package/dist/assets/min-DYUOb1RR.js +1 -0
- package/dist/assets/{mindmap-definition-Q6HEUPPD-DktvuLe1.js → mindmap-definition-Q6HEUPPD-G5NognM-.js} +1 -1
- package/dist/assets/{number-overlay-editor-BEfwI1IT.js → number-overlay-editor-DPr5sHFu.js} +1 -1
- package/dist/assets/{outline-panel-CdsnAy2w.js → outline-panel-gxQXvVi4.js} +1 -1
- package/dist/assets/{packages-panel-DiTA-d_D.js → packages-panel-B1T0VPlg.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-DQDNQ-de.js → pieDiagram-ADFJNKIX-DK9SHkfc.js} +1 -1
- package/dist/assets/{quadrantDiagram-LMRXKWRM-0kgIXc2-.js → quadrantDiagram-LMRXKWRM-D1DdWF8C.js} +1 -1
- package/dist/assets/{react-plotly-DJqqfM7c.js → react-plotly-CTwajqCb.js} +1 -1
- package/dist/assets/{requirementDiagram-4UW4RH46-B5rb0ypd.js → requirementDiagram-4UW4RH46-DnjDAypr.js} +1 -1
- package/dist/assets/{run-page-CFmLrv1R.js → run-page-CQY9im22.js} +1 -1
- package/dist/assets/{sankeyDiagram-GR3RE2ED-Dom7IlnF.js → sankeyDiagram-GR3RE2ED-B67Va-ER.js} +1 -1
- package/dist/assets/{scratchpad-panel-CuHWpHO8.js → scratchpad-panel-DlDfcDtW.js} +1 -1
- package/dist/assets/{secrets-panel-CfHc5YD0.js → secrets-panel-BDGyuGZA.js} +1 -1
- package/dist/assets/{sequenceDiagram-C3RYC4MD-PNJWXQbw.js → sequenceDiagram-C3RYC4MD-DiWgZPtN.js} +1 -1
- package/dist/assets/{slides-component-CJgaTRZ0.js → slides-component-DhpPRtQp.js} +1 -1
- package/dist/assets/{snippets-panel-B2EC1txM.js → snippets-panel-CLkBXhJ2.js} +1 -1
- package/dist/assets/{sortBy-DZnlX29-.js → sortBy-D4OG7w4O.js} +1 -1
- package/dist/assets/{state-CWict9RU.js → state-Dz_3JyED.js} +1 -1
- package/dist/assets/{stateDiagram-KXAO66HF-BE58aJnr.js → stateDiagram-KXAO66HF-ByF2AULw.js} +1 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-CtBJqosP.js +1 -0
- package/dist/assets/{storage-DRaR04wR.js → storage-Dr0CC44z.js} +6 -6
- package/dist/assets/{terminal-BX3Su5q7.js → terminal-BtdissBf.js} +1 -1
- package/dist/assets/{time-hUzZfpNE.js → time-DKdOTnQg.js} +1 -1
- package/dist/assets/{timeline-definition-XQNQX7LJ-CqQP9t51.js → timeline-definition-XQNQX7LJ-DzER9bf6.js} +1 -1
- package/dist/assets/{tracing-B10Q1n-L.js → tracing-Dpx5M-u3.js} +2 -2
- package/dist/assets/{tracing-panel-Du8WCnno.js → tracing-panel-hCjBkSER.js} +2 -2
- package/dist/assets/{trash-B81GTiv6.js → trash-C6Ko-g5q.js} +1 -1
- package/dist/assets/{tree-6vW2ogkh.js → tree-BHN2gcCF.js} +6 -6
- package/dist/assets/{treemap-75Q7IDZK-CdwDwwsz.js → treemap-75Q7IDZK-DR79Mhzt.js} +1 -1
- package/dist/assets/{variable-panel-D5qgJI7k.js → variable-panel-PFBCFz36.js} +1 -1
- package/dist/assets/{vega-component-DJaJWMJM.js → vega-component-Db6-uY4C.js} +1 -1
- package/dist/assets/{xychartDiagram-6GGTOJPD-WFtXqaM9.js → xychartDiagram-6GGTOJPD-DWzBP3tZ.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +3 -3
- package/src/__mocks__/requests.ts +1 -0
- package/src/components/data-table/__tests__/columns.test.tsx +38 -0
- package/src/components/data-table/cell-hover-template/feature.ts +1 -1
- package/src/components/data-table/cell-hover-template/types.ts +1 -1
- package/src/components/data-table/columns.tsx +21 -2
- package/src/components/data-table/renderers.tsx +16 -8
- package/src/components/data-table/schemas.ts +16 -0
- package/src/components/editor/Cell.tsx +2 -0
- package/src/components/editor/errors/sql-validation-errors.tsx +34 -0
- package/src/components/editor/output/ConsoleOutput.tsx +13 -1
- package/src/components/editor/output/MarimoErrorOutput.tsx +60 -1
- package/src/core/ai/context/providers/cell-output.ts +1 -18
- package/src/core/codemirror/language/__tests__/extension.test.ts +24 -0
- package/src/core/codemirror/language/__tests__/sql-validation.test.ts +133 -0
- package/src/core/codemirror/language/languages/sql/sql-mode.ts +20 -0
- package/src/core/codemirror/language/languages/sql/sql.ts +90 -3
- package/src/core/codemirror/language/languages/sql/validation-errors.ts +79 -0
- package/src/core/codemirror/language/panel/panel.tsx +8 -2
- package/src/core/codemirror/language/panel/sql.tsx +81 -4
- package/src/core/config/feature-flag.tsx +3 -1
- package/src/core/datasets/request-registry.ts +17 -1
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/islands/main.ts +1 -0
- package/src/core/kernel/messages.ts +1 -0
- package/src/core/network/requests-network.ts +7 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.ts +1 -0
- package/src/core/network/types.ts +2 -0
- package/src/core/wasm/bridge.ts +5 -0
- package/src/core/websocket/useMarimoWebSocket.tsx +4 -0
- package/src/plugins/core/registerReactComponent.tsx +23 -19
- package/src/plugins/impl/DataTablePlugin.tsx +11 -4
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +17 -5
- package/src/stories/dataframe.stories.tsx +2 -0
- package/src/utils/__tests__/dom.test.ts +167 -0
- package/src/utils/dom.ts +55 -0
- package/dist/assets/_baseEach-CvTX9w0Y.js +0 -1
- package/dist/assets/_baseMap-CtlwA90f.js +0 -1
- package/dist/assets/channel-Co6iMgWq.js +0 -1
- package/dist/assets/classDiagram-KNZD7YFC-BbJ0rY3y.js +0 -1
- package/dist/assets/classDiagram-v2-RKCZMP56-BbJ0rY3y.js +0 -1
- package/dist/assets/clone-BMP0PsTa.js +0 -1
- package/dist/assets/command-palette-B93Pjcky.js +0 -1
- package/dist/assets/datasources-panel-v7H3cR0p.js +0 -1
- package/dist/assets/index-C7CoaNFb.js +0 -578
- package/dist/assets/index-DadI618h.css +0 -1
- package/dist/assets/infoDiagram-STP46IZ2-CJLOpSAf.js +0 -2
- package/dist/assets/min-BBO3-1Hg.js +0 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-CdThjimL.js +0 -1
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
+
import type { SelectTriggerProps } from "@radix-ui/react-select";
|
|
3
4
|
import { useAtomValue } from "jotai";
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
AlertCircle,
|
|
7
|
+
CircleHelpIcon,
|
|
8
|
+
DatabaseBackup,
|
|
9
|
+
SearchCheck,
|
|
10
|
+
} from "lucide-react";
|
|
5
11
|
import { transformDisplayName } from "@/components/databases/display";
|
|
6
12
|
import { DatabaseLogo } from "@/components/databases/icon";
|
|
13
|
+
import { Button } from "@/components/ui/button";
|
|
7
14
|
import {
|
|
8
15
|
Select,
|
|
9
16
|
SelectContent,
|
|
@@ -14,6 +21,7 @@ import {
|
|
|
14
21
|
SelectTrigger,
|
|
15
22
|
SelectValue,
|
|
16
23
|
} from "@/components/ui/select";
|
|
24
|
+
import { Tooltip } from "@/components/ui/tooltip";
|
|
17
25
|
import {
|
|
18
26
|
dataConnectionsMapAtom,
|
|
19
27
|
setLatestEngineSelected,
|
|
@@ -24,6 +32,7 @@ import {
|
|
|
24
32
|
} from "@/core/datasets/engines";
|
|
25
33
|
import type { DataSourceConnection } from "@/core/kernel/messages";
|
|
26
34
|
import { useNonce } from "@/hooks/useNonce";
|
|
35
|
+
import { type SQLMode, useSQLMode } from "../languages/sql/sql-mode";
|
|
27
36
|
|
|
28
37
|
interface SelectProps {
|
|
29
38
|
selectedEngine: ConnectionName;
|
|
@@ -77,7 +86,7 @@ export const SQLEngineSelect: React.FC<SelectProps> = ({
|
|
|
77
86
|
<SelectItem key={connection.name} value={connection.name}>
|
|
78
87
|
<div className="flex items-center gap-1">
|
|
79
88
|
<DatabaseLogo className="h-3 w-3" name={connection.dialect} />
|
|
80
|
-
<span className="truncate">
|
|
89
|
+
<span className="truncate ml-0.5">
|
|
81
90
|
{transformDisplayName(connection.display_name)}
|
|
82
91
|
</span>
|
|
83
92
|
</div>
|
|
@@ -88,9 +97,9 @@ export const SQLEngineSelect: React.FC<SelectProps> = ({
|
|
|
88
97
|
return (
|
|
89
98
|
<div className="flex flex-row gap-1 items-center">
|
|
90
99
|
<Select value={selectedEngine} onValueChange={handleSelectEngine}>
|
|
91
|
-
<
|
|
100
|
+
<SQLSelectTrigger>
|
|
92
101
|
<SelectValue placeholder="Select an engine" />
|
|
93
|
-
</
|
|
102
|
+
</SQLSelectTrigger>
|
|
94
103
|
<SelectContent>
|
|
95
104
|
<SelectGroup>
|
|
96
105
|
<SelectLabel>Database connections</SelectLabel>
|
|
@@ -130,3 +139,71 @@ export const SQLEngineSelect: React.FC<SelectProps> = ({
|
|
|
130
139
|
const HELP_KEY = "__help__";
|
|
131
140
|
const HELP_URL =
|
|
132
141
|
"http://docs.marimo.io/guides/working_with_data/sql/#connecting-to-a-custom-database";
|
|
142
|
+
|
|
143
|
+
export const SQLModeSelect: React.FC = () => {
|
|
144
|
+
const { sqlMode, setSQLMode } = useSQLMode();
|
|
145
|
+
|
|
146
|
+
const handleToggleMode = () => {
|
|
147
|
+
setSQLMode(sqlMode === "validate" ? "default" : "validate");
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const getModeIcon = (mode: SQLMode) => {
|
|
151
|
+
return mode === "validate" ? (
|
|
152
|
+
<SearchCheck className="h-3 w-3" />
|
|
153
|
+
) : (
|
|
154
|
+
<DatabaseBackup className="h-3 w-3" />
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const getTooltipContent = (mode: SQLMode) => {
|
|
159
|
+
return mode === "validate" ? (
|
|
160
|
+
<div className="text-xs">
|
|
161
|
+
<div className="font-semibold mb-1 flex flex-row items-center gap-1">
|
|
162
|
+
<SearchCheck className="h-3 w-3" />
|
|
163
|
+
Validate Mode
|
|
164
|
+
</div>
|
|
165
|
+
<p>Queries are validated as you write them</p>
|
|
166
|
+
</div>
|
|
167
|
+
) : (
|
|
168
|
+
<div className="text-xs">
|
|
169
|
+
<div className="font-semibold mb-1 flex flex-row items-center gap-1">
|
|
170
|
+
<DatabaseBackup className="h-3 w-3" />
|
|
171
|
+
Default Mode
|
|
172
|
+
</div>
|
|
173
|
+
<p>Standard editing</p>
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<div className="flex flex-row gap-1 items-center">
|
|
180
|
+
<Tooltip delayDuration={300} content={getTooltipContent(sqlMode)}>
|
|
181
|
+
<Button
|
|
182
|
+
variant="ghost"
|
|
183
|
+
size="sm"
|
|
184
|
+
onClick={handleToggleMode}
|
|
185
|
+
className="h-5 px-1.5 text-xs border-border shadow-none hover:bg-accent"
|
|
186
|
+
>
|
|
187
|
+
{getModeIcon(sqlMode)}
|
|
188
|
+
<span className="ml-1">
|
|
189
|
+
{sqlMode === "validate" ? "Validate" : "Default"}
|
|
190
|
+
</span>
|
|
191
|
+
</Button>
|
|
192
|
+
</Tooltip>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const SQLSelectTrigger: React.FC<SelectTriggerProps> = ({
|
|
198
|
+
children,
|
|
199
|
+
...props
|
|
200
|
+
}) => {
|
|
201
|
+
return (
|
|
202
|
+
<SelectTrigger
|
|
203
|
+
className="text-xs border-border shadow-none! ring-0! h-5 px-1.5 hover:bg-accent transition-colors"
|
|
204
|
+
{...props}
|
|
205
|
+
>
|
|
206
|
+
{children}
|
|
207
|
+
</SelectTrigger>
|
|
208
|
+
);
|
|
209
|
+
};
|
|
@@ -14,6 +14,7 @@ export interface ExperimentalFeatures {
|
|
|
14
14
|
mcp_docs: boolean;
|
|
15
15
|
sql_linter: boolean;
|
|
16
16
|
external_agents: boolean;
|
|
17
|
+
sql_mode: boolean;
|
|
17
18
|
// Add new feature flags here
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -26,13 +27,14 @@ const defaultValues: ExperimentalFeatures = {
|
|
|
26
27
|
mcp_docs: false,
|
|
27
28
|
sql_linter: false,
|
|
28
29
|
external_agents: import.meta.env.DEV,
|
|
30
|
+
sql_mode: false,
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
export function getFeatureFlag<T extends keyof ExperimentalFeatures>(
|
|
32
34
|
feature: T,
|
|
33
35
|
): ExperimentalFeatures[T] {
|
|
34
36
|
return (
|
|
35
|
-
(getResolvedMarimoConfig()
|
|
37
|
+
(getResolvedMarimoConfig()?.experimental?.[
|
|
36
38
|
feature
|
|
37
39
|
] as ExperimentalFeatures[T]) ?? defaultValues[feature]
|
|
38
40
|
);
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
SQLTableListPreview,
|
|
4
|
+
SQLTablePreview,
|
|
5
|
+
ValidateSQLResult,
|
|
6
|
+
} from "../kernel/messages";
|
|
3
7
|
import { DeferredRequestRegistry } from "../network/DeferredRequestRegistry";
|
|
4
8
|
import { getRequestClient } from "../network/requests";
|
|
5
9
|
import type {
|
|
6
10
|
PreviewSQLTableListRequest,
|
|
7
11
|
PreviewSQLTableRequest,
|
|
12
|
+
ValidateSQLRequest,
|
|
8
13
|
} from "../network/types";
|
|
9
14
|
|
|
10
15
|
// We make a request to the backend to preview the table, passing in Engine, DB, Schema, and Table
|
|
@@ -32,3 +37,14 @@ export const PreviewSQLTableList = new DeferredRequestRegistry<
|
|
|
32
37
|
...req,
|
|
33
38
|
});
|
|
34
39
|
});
|
|
40
|
+
|
|
41
|
+
export const ValidateSQL = new DeferredRequestRegistry<
|
|
42
|
+
Omit<ValidateSQLRequest, "requestId">,
|
|
43
|
+
ValidateSQLResult
|
|
44
|
+
>("validate-sql", async (requestId, req) => {
|
|
45
|
+
const client = getRequestClient();
|
|
46
|
+
await client.validateSQL({
|
|
47
|
+
requestId: requestId,
|
|
48
|
+
...req,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -153,6 +153,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
|
153
153
|
previewSQLTable = throwNotImplemented;
|
|
154
154
|
previewSQLTableList = throwNotImplemented;
|
|
155
155
|
previewDataSourceConnection = throwNotImplemented;
|
|
156
|
+
validateSQL = throwNotImplemented;
|
|
156
157
|
openFile = throwNotImplemented;
|
|
157
158
|
sendListFiles = throwNotImplemented;
|
|
158
159
|
sendSearchFiles = throwNotImplemented;
|
package/src/core/islands/main.ts
CHANGED
|
@@ -38,6 +38,7 @@ export type DataColumnPreview = OperationMessageData<"data-column-preview">;
|
|
|
38
38
|
export type SQLTablePreview = OperationMessageData<"sql-table-preview">;
|
|
39
39
|
export type SQLTableListPreview =
|
|
40
40
|
OperationMessageData<"sql-table-list-preview">;
|
|
41
|
+
export type ValidateSQLResult = OperationMessageData<"validate-sql-result">;
|
|
41
42
|
export type SecretKeysResult = OperationMessageData<"secret-keys-result">;
|
|
42
43
|
export type StartupLogs = OperationMessageData<"startup-logs">;
|
|
43
44
|
export type CellMessage = OperationMessageData<"cell-op">;
|
|
@@ -207,6 +207,13 @@ export function createNetworkRequests(): EditRequests & RunRequests {
|
|
|
207
207
|
})
|
|
208
208
|
.then(handleResponseReturnNull);
|
|
209
209
|
},
|
|
210
|
+
validateSQL: (request) => {
|
|
211
|
+
return getClient()
|
|
212
|
+
.POST("/api/sql/validate", {
|
|
213
|
+
body: request,
|
|
214
|
+
})
|
|
215
|
+
.then(handleResponseReturnNull);
|
|
216
|
+
},
|
|
210
217
|
openFile: async (request) => {
|
|
211
218
|
await waitForConnectionOpen();
|
|
212
219
|
await getClient()
|
|
@@ -57,6 +57,7 @@ export function createStaticRequests(): EditRequests & RunRequests {
|
|
|
57
57
|
previewSQLTable: throwNotInEditMode,
|
|
58
58
|
previewSQLTableList: throwNotInEditMode,
|
|
59
59
|
previewDataSourceConnection: throwNotInEditMode,
|
|
60
|
+
validateSQL: throwNotInEditMode,
|
|
60
61
|
openFile: throwNotInEditMode,
|
|
61
62
|
getUsageStats: throwNotInEditMode,
|
|
62
63
|
sendListFiles: throwNotInEditMode,
|
|
@@ -35,6 +35,7 @@ export function createErrorToastingRequests(
|
|
|
35
35
|
previewSQLTable: "Failed to fetch SQL table",
|
|
36
36
|
previewSQLTableList: "Failed to fetch SQL table list",
|
|
37
37
|
previewDataSourceConnection: "Failed to preview data source connection",
|
|
38
|
+
validateSQL: "Failed to validate SQL",
|
|
38
39
|
openFile: "Failed to open file",
|
|
39
40
|
getUsageStats: "", // No toast
|
|
40
41
|
sendListFiles: "Failed to list files",
|
|
@@ -62,6 +62,7 @@ export type PreviewSQLTableRequest = schemas["PreviewSQLTableRequest"];
|
|
|
62
62
|
export type PreviewSQLTableListRequest = schemas["PreviewSQLTableListRequest"];
|
|
63
63
|
export type PreviewDataSourceConnectionRequest =
|
|
64
64
|
schemas["PreviewDataSourceConnectionRequest"];
|
|
65
|
+
export type ValidateSQLRequest = schemas["ValidateSQLRequest"];
|
|
65
66
|
export type PdbRequest = schemas["PdbRequest"];
|
|
66
67
|
export type ReadCodeResponse = schemas["ReadCodeResponse"];
|
|
67
68
|
export type RecentFilesResponse = schemas["RecentFilesResponse"];
|
|
@@ -140,6 +141,7 @@ export interface EditRequests {
|
|
|
140
141
|
previewDataSourceConnection: (
|
|
141
142
|
request: PreviewDataSourceConnectionRequest,
|
|
142
143
|
) => Promise<null>;
|
|
144
|
+
validateSQL: (request: ValidateSQLRequest) => Promise<null>;
|
|
143
145
|
openFile: (request: { path: string }) => Promise<null>;
|
|
144
146
|
getUsageStats: () => Promise<UsageResponse>;
|
|
145
147
|
// Debugger
|
package/src/core/wasm/bridge.ts
CHANGED
|
@@ -496,6 +496,11 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
496
496
|
return null;
|
|
497
497
|
};
|
|
498
498
|
|
|
499
|
+
validateSQL: EditRequests["validateSQL"] = async (request) => {
|
|
500
|
+
await this.putControlRequest(request);
|
|
501
|
+
return null;
|
|
502
|
+
};
|
|
503
|
+
|
|
499
504
|
sendModelValue: RunRequests["sendModelValue"] = async (request) => {
|
|
500
505
|
await this.putControlRequest(request);
|
|
501
506
|
return null;
|
|
@@ -32,6 +32,7 @@ import type { ConnectionName } from "../datasets/engines";
|
|
|
32
32
|
import {
|
|
33
33
|
PreviewSQLTable,
|
|
34
34
|
PreviewSQLTableList,
|
|
35
|
+
ValidateSQL,
|
|
35
36
|
} from "../datasets/request-registry";
|
|
36
37
|
import { useDatasetsActions } from "../datasets/state";
|
|
37
38
|
import { UI_ELEMENT_REGISTRY } from "../dom/uiregistry";
|
|
@@ -238,6 +239,9 @@ export function useMarimoWebSocket(opts: {
|
|
|
238
239
|
case "sql-table-list-preview":
|
|
239
240
|
PreviewSQLTableList.resolve(msg.data.request_id as RequestId, msg.data);
|
|
240
241
|
return;
|
|
242
|
+
case "validate-sql-result":
|
|
243
|
+
ValidateSQL.resolve(msg.data.request_id as RequestId, msg.data);
|
|
244
|
+
return;
|
|
241
245
|
case "secret-keys-result":
|
|
242
246
|
SECRETS_REGISTRY.resolve(msg.data.request_id as RequestId, msg.data);
|
|
243
247
|
return;
|
|
@@ -24,7 +24,7 @@ import ReactDOM, { type Root } from "react-dom/client";
|
|
|
24
24
|
import useEvent from "react-use-event-hook";
|
|
25
25
|
import type { ZodSchema } from "zod";
|
|
26
26
|
import { notebookAtom } from "@/core/cells/cells.ts";
|
|
27
|
-
import {
|
|
27
|
+
import { HTMLCellId } from "@/core/cells/ids.ts";
|
|
28
28
|
import { isUninstantiated } from "@/core/cells/utils";
|
|
29
29
|
import { createInputEvent, MarimoValueUpdateEvent } from "@/core/dom/events";
|
|
30
30
|
import { getUIElementObjectId } from "@/core/dom/ui-element";
|
|
@@ -182,24 +182,28 @@ function PluginSlotInternal<T>(
|
|
|
182
182
|
const objectId = getUIElementObjectId(hostElement);
|
|
183
183
|
invariant(objectId, "Object ID should exist");
|
|
184
184
|
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
185
|
+
const htmlId = HTMLCellId.findElementThroughShadowDOMs(hostElement)?.id;
|
|
186
|
+
const cellId = htmlId ? HTMLCellId.parse(htmlId) : null;
|
|
187
|
+
if (cellId) {
|
|
188
|
+
// If the cell is not initialized, throw an error
|
|
189
|
+
const notebookState = store.get(notebookAtom);
|
|
190
|
+
const cellRuntime = notebookState.cellRuntime[cellId];
|
|
191
|
+
const cellData = notebookState.cellData[cellId];
|
|
192
|
+
|
|
193
|
+
const cellNotInitialized = isUninstantiated({
|
|
194
|
+
executionTime:
|
|
195
|
+
cellRuntime.runElapsedTimeMs ?? cellData.lastExecutionTime,
|
|
196
|
+
status: cellRuntime.status,
|
|
197
|
+
errored: cellRuntime.errored,
|
|
198
|
+
interrupted: cellRuntime.interrupted,
|
|
199
|
+
stopped: cellRuntime.stopped,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
if (cellNotInitialized) {
|
|
203
|
+
throw new CellNotInitializedError();
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
Logger.warn(`Cell ID ${cellId} cannot be found`);
|
|
203
207
|
}
|
|
204
208
|
|
|
205
209
|
const response = await FUNCTIONS_REGISTRY.request({
|
|
@@ -36,6 +36,10 @@ import {
|
|
|
36
36
|
import { usePanelOwnership } from "@/components/data-table/hooks/use-panel-ownership";
|
|
37
37
|
import { LoadingTable } from "@/components/data-table/loading-table";
|
|
38
38
|
import { RowViewerPanel } from "@/components/data-table/row-viewer-panel/row-viewer";
|
|
39
|
+
import {
|
|
40
|
+
type DownloadAsArgs,
|
|
41
|
+
DownloadAsSchema,
|
|
42
|
+
} from "@/components/data-table/schemas";
|
|
39
43
|
import {
|
|
40
44
|
type BinValues,
|
|
41
45
|
type ColumnHeaderStats,
|
|
@@ -182,6 +186,7 @@ interface Data<T> {
|
|
|
182
186
|
freezeColumnsRight?: string[];
|
|
183
187
|
textJustifyColumns?: Record<string, "left" | "center" | "right">;
|
|
184
188
|
wrappedColumns?: string[];
|
|
189
|
+
headerTooltip?: Record<string, string>;
|
|
185
190
|
totalColumns: number;
|
|
186
191
|
maxColumns: number | "all";
|
|
187
192
|
hasStableRowId: boolean;
|
|
@@ -190,7 +195,7 @@ interface Data<T> {
|
|
|
190
195
|
|
|
191
196
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
192
197
|
type DataTableFunctions = {
|
|
193
|
-
download_as:
|
|
198
|
+
download_as: DownloadAsArgs;
|
|
194
199
|
get_column_summaries: <T>(
|
|
195
200
|
opts: ColumnSummariesArgs,
|
|
196
201
|
) => Promise<ColumnSummaries<T>>;
|
|
@@ -249,6 +254,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
249
254
|
.record(z.enum(["left", "center", "right"]))
|
|
250
255
|
.optional(),
|
|
251
256
|
wrappedColumns: z.array(z.string()).optional(),
|
|
257
|
+
headerTooltip: z.record(z.string()).optional(),
|
|
252
258
|
fieldTypes: columnToFieldTypesSchema.nullish(),
|
|
253
259
|
totalColumns: z.number(),
|
|
254
260
|
maxColumns: z.union([z.number(), z.literal("all")]).default("all"),
|
|
@@ -263,9 +269,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
263
269
|
}),
|
|
264
270
|
)
|
|
265
271
|
.withFunctions<DataTableFunctions>({
|
|
266
|
-
download_as:
|
|
267
|
-
.input(z.object({ format: z.enum(["csv", "json", "parquet"]) }))
|
|
268
|
-
.output(z.string()),
|
|
272
|
+
download_as: DownloadAsSchema,
|
|
269
273
|
get_column_summaries: rpc
|
|
270
274
|
.input(z.object({ precompute: z.boolean() }))
|
|
271
275
|
.output(
|
|
@@ -706,6 +710,7 @@ const DataTableComponent = ({
|
|
|
706
710
|
freezeColumnsRight,
|
|
707
711
|
textJustifyColumns,
|
|
708
712
|
wrappedColumns,
|
|
713
|
+
headerTooltip,
|
|
709
714
|
totalColumns,
|
|
710
715
|
get_row_ids,
|
|
711
716
|
cellStyles,
|
|
@@ -779,6 +784,7 @@ const DataTableComponent = ({
|
|
|
779
784
|
fieldTypes: memoizedClampedFieldTypes,
|
|
780
785
|
textJustifyColumns: memoizedTextJustifyColumns,
|
|
781
786
|
wrappedColumns: memoizedWrappedColumns,
|
|
787
|
+
headerTooltip: headerTooltip,
|
|
782
788
|
// Only show data types if they are explicitly set
|
|
783
789
|
showDataTypes: showDataTypes,
|
|
784
790
|
calculateTopKRows: calculate_top_k_rows,
|
|
@@ -791,6 +797,7 @@ const DataTableComponent = ({
|
|
|
791
797
|
memoizedClampedFieldTypes,
|
|
792
798
|
memoizedTextJustifyColumns,
|
|
793
799
|
memoizedWrappedColumns,
|
|
800
|
+
headerTooltip,
|
|
794
801
|
calculate_top_k_rows,
|
|
795
802
|
],
|
|
796
803
|
);
|
|
@@ -4,6 +4,10 @@ import { isEqual } from "lodash-es";
|
|
|
4
4
|
import { Code2Icon, DatabaseIcon, FunctionSquareIcon } from "lucide-react";
|
|
5
5
|
import { type JSX, memo, useEffect, useRef, useState } from "react";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
import {
|
|
8
|
+
type DownloadAsArgs,
|
|
9
|
+
DownloadAsSchema,
|
|
10
|
+
} from "@/components/data-table/schemas";
|
|
7
11
|
import type { FieldTypesWithExternalType } from "@/components/data-table/types";
|
|
8
12
|
import { ReadonlyCode } from "@/components/editor/code/readonly-python-code";
|
|
9
13
|
import { Spinner } from "@/components/icons/spinner";
|
|
@@ -38,6 +42,7 @@ interface Data {
|
|
|
38
42
|
label?: string | null;
|
|
39
43
|
columns: ColumnDataTypes;
|
|
40
44
|
pageSize: number;
|
|
45
|
+
showDownload: boolean;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
@@ -67,6 +72,7 @@ type PluginFunctions = {
|
|
|
67
72
|
data: TableData<T>;
|
|
68
73
|
total_rows: number;
|
|
69
74
|
}>;
|
|
75
|
+
download_as: DownloadAsArgs;
|
|
70
76
|
};
|
|
71
77
|
|
|
72
78
|
// Value is selection, but it is not currently exposed to the user
|
|
@@ -77,13 +83,14 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
77
83
|
z.object({
|
|
78
84
|
label: z.string().nullish(),
|
|
79
85
|
pageSize: z.number().default(5),
|
|
86
|
+
showDownload: z.boolean().default(true),
|
|
80
87
|
columns: z
|
|
81
88
|
.array(z.tuple([z.string().or(z.number()), z.string(), z.string()]))
|
|
82
89
|
.transform((value) => {
|
|
83
90
|
const map = new Map<ColumnId, string>();
|
|
84
|
-
value.forEach(([key, dataType]) =>
|
|
85
|
-
map.set(key as ColumnId, dataType as DataType)
|
|
86
|
-
);
|
|
91
|
+
value.forEach(([key, dataType]) => {
|
|
92
|
+
map.set(key as ColumnId, dataType as DataType);
|
|
93
|
+
});
|
|
87
94
|
return map;
|
|
88
95
|
}),
|
|
89
96
|
}),
|
|
@@ -124,6 +131,7 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
124
131
|
total_rows: z.number(),
|
|
125
132
|
}),
|
|
126
133
|
),
|
|
134
|
+
download_as: DownloadAsSchema,
|
|
127
135
|
})
|
|
128
136
|
.renderer((props) => (
|
|
129
137
|
<TableProviders>
|
|
@@ -141,6 +149,8 @@ interface DataTableProps extends Data, PluginFunctions {
|
|
|
141
149
|
value: S;
|
|
142
150
|
setValue: (value: S) => void;
|
|
143
151
|
host: HTMLElement;
|
|
152
|
+
showDownload: boolean;
|
|
153
|
+
download_as: DownloadAsArgs;
|
|
144
154
|
}
|
|
145
155
|
|
|
146
156
|
const EMPTY: Transformations = {
|
|
@@ -151,11 +161,13 @@ export const DataFrameComponent = memo(
|
|
|
151
161
|
({
|
|
152
162
|
columns,
|
|
153
163
|
pageSize,
|
|
164
|
+
showDownload,
|
|
154
165
|
value,
|
|
155
166
|
setValue,
|
|
156
167
|
get_dataframe,
|
|
157
168
|
get_column_values,
|
|
158
169
|
search,
|
|
170
|
+
download_as,
|
|
159
171
|
host,
|
|
160
172
|
}: DataTableProps): JSX.Element => {
|
|
161
173
|
const { data, error, isPending } = useAsyncData(
|
|
@@ -270,8 +282,8 @@ export const DataFrameComponent = memo(
|
|
|
270
282
|
pagination={true}
|
|
271
283
|
fieldTypes={field_types}
|
|
272
284
|
rowHeaders={row_headers || Arrays.EMPTY}
|
|
273
|
-
showDownload={
|
|
274
|
-
download_as={
|
|
285
|
+
showDownload={showDownload}
|
|
286
|
+
download_as={download_as}
|
|
275
287
|
enableSearch={false}
|
|
276
288
|
showFilters={false}
|
|
277
289
|
search={search}
|