@sqlrooms/sql-editor 0.26.0-rc.4 → 0.26.0-rc.6
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/README.md +2 -2
- package/dist/SqlEditorSlice.d.ts +9 -5
- package/dist/SqlEditorSlice.d.ts.map +1 -1
- package/dist/SqlEditorSlice.js +29 -20
- package/dist/SqlEditorSlice.js.map +1 -1
- package/dist/components/QueryEditorPanel.js +2 -2
- package/dist/components/QueryEditorPanel.js.map +1 -1
- package/dist/components/QueryEditorPanelActions.d.ts.map +1 -1
- package/dist/components/QueryEditorPanelActions.js +1 -1
- package/dist/components/QueryEditorPanelActions.js.map +1 -1
- package/dist/components/QueryEditorPanelEditor.js +1 -1
- package/dist/components/QueryEditorPanelEditor.js.map +1 -1
- package/dist/components/QueryEditorPanelTabsList.js +2 -2
- package/dist/components/QueryEditorPanelTabsList.js.map +1 -1
- package/dist/components/QueryTabMenuItem.js +2 -2
- package/dist/components/QueryTabMenuItem.js.map +1 -1
- package/package.json +12 -13
package/README.md
CHANGED
|
@@ -418,10 +418,10 @@ The SQL editor can be configured through the Zustand store.
|
|
|
418
418
|
```tsx
|
|
419
419
|
const config = createDefaultSqlEditorConfig();
|
|
420
420
|
// Customize if needed
|
|
421
|
-
config.
|
|
421
|
+
sqlEditor.config.queries = [
|
|
422
422
|
{id: 'default', name: 'Untitled', query: 'SELECT * FROM users LIMIT 10;'},
|
|
423
423
|
];
|
|
424
|
-
config.
|
|
424
|
+
sqlEditor.config.selectedQueryId = 'default';
|
|
425
425
|
|
|
426
426
|
// Use in store creation
|
|
427
427
|
const {roomStore} = createRoomStore({
|
package/dist/SqlEditorSlice.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { BaseRoomConfig, RoomShellSliceState, StateCreator } from '@sqlrooms/room-shell';
|
|
1
|
+
import { RoomShellSliceState, StateCreator } from '@sqlrooms/room-shell';
|
|
3
2
|
import { SqlEditorSliceConfig } from '@sqlrooms/sql-editor-config';
|
|
4
3
|
import * as arrow from 'apache-arrow';
|
|
5
4
|
export type QueryResult = {
|
|
@@ -27,6 +26,7 @@ export declare function isQueryWithResult(queryResult: QueryResult | undefined):
|
|
|
27
26
|
};
|
|
28
27
|
export type SqlEditorSliceState = {
|
|
29
28
|
sqlEditor: {
|
|
29
|
+
config: SqlEditorSliceConfig;
|
|
30
30
|
queryResult?: QueryResult;
|
|
31
31
|
/** @deprecated */
|
|
32
32
|
selectedTable?: string;
|
|
@@ -37,6 +37,10 @@ export type SqlEditorSliceState = {
|
|
|
37
37
|
queryResultLimit: number;
|
|
38
38
|
/** Options for the result limit dropdown */
|
|
39
39
|
queryResultLimitOptions: number[];
|
|
40
|
+
/**
|
|
41
|
+
* Set the config for the sql editor slice.
|
|
42
|
+
*/
|
|
43
|
+
setConfig(config: SqlEditorSliceConfig): void;
|
|
40
44
|
/**
|
|
41
45
|
* Run the currently selected query.
|
|
42
46
|
*/
|
|
@@ -105,12 +109,12 @@ export type SqlEditorSliceState = {
|
|
|
105
109
|
setQueryResultLimit(limit: number): void;
|
|
106
110
|
};
|
|
107
111
|
};
|
|
108
|
-
export declare function createSqlEditorSlice
|
|
112
|
+
export declare function createSqlEditorSlice({ config, queryResultLimit, queryResultLimitOptions, }?: {
|
|
113
|
+
config?: SqlEditorSliceConfig;
|
|
109
114
|
queryResultLimit?: number;
|
|
110
115
|
queryResultLimitOptions?: number[];
|
|
111
116
|
}): StateCreator<SqlEditorSliceState>;
|
|
112
|
-
type
|
|
113
|
-
type RoomStateWithSqlEditor = RoomShellSliceState<RoomConfigWithSqlEditor> & SqlEditorSliceState;
|
|
117
|
+
type RoomStateWithSqlEditor = RoomShellSliceState & SqlEditorSliceState;
|
|
114
118
|
export declare function useStoreWithSqlEditor<T>(selector: (state: RoomStateWithSqlEditor) => T): T;
|
|
115
119
|
export {};
|
|
116
120
|
//# sourceMappingURL=SqlEditorSlice.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlEditorSlice.d.ts","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SqlEditorSlice.d.ts","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"AAOA,OAAO,EAGL,mBAAmB,EACnB,YAAY,EAEb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAKtC,MAAM,MAAM,WAAW,GACnB;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,eAAe,CAAA;CAAC,GAC1E;IAAC,MAAM,EAAE,SAAS,CAAA;CAAC,GACnB;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,GAChC;IACE,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;CAC5B,GACD;IACE,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEN,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,WAAW,GAAG,SAAS,GACnC,WAAW,IAAI,WAAW,GAAG;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;CACvC,CAOA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE;QACT,MAAM,EAAE,oBAAoB,CAAC;QAE7B,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,mBAAmB;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,6FAA6F;QAC7F,eAAe,EAAE,OAAO,CAAC;QACzB,kBAAkB;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QAErB,gBAAgB,EAAE,MAAM,CAAC;QACzB,4CAA4C;QAC5C,uBAAuB,EAAE,MAAM,EAAE,CAAC;QAElC;;WAEG;QACH,SAAS,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC;QAE9C;;WAEG;QACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAE/C;;WAEG;QACH,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QAEzC;;WAEG;QACH,iBAAiB,IAAI,IAAI,CAAC;QAE1B;;;WAGG;QACH,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAElE;;;WAGG;QACH,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG;YACrC,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QAEF;;;WAGG;QACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAEtC;;;;WAIG;QACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAEvD;;;WAGG;QACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACrC;;;WAGG;QACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAEpC;;;;WAIG;QACH,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAE1D;;;WAGG;QACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAE1C;;WAEG;QACH,eAAe,IAAI,MAAM,CAAC;QAE1B,kBAAkB;QAClB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;QAE7C,iBAAiB,IAAI,IAAI,CAAC;QAE1B,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1C,CAAC;CACH,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EACnC,MAAuC,EACvC,gBAAsB,EACtB,uBAA0C,GAC3C,GAAE;IACD,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAyVzC;AAED,KAAK,sBAAsB,GAAG,mBAAmB,GAAG,mBAAmB,CAAC;AAExE,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,CAAC,GAC7C,CAAC,CAIH"}
|
package/dist/SqlEditorSlice.js
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createId } from '@paralleldrive/cuid2';
|
|
2
|
+
import { getSqlErrorWithPointer, makeLimitQuery, splitSqlStatements, } from '@sqlrooms/duckdb';
|
|
2
3
|
import { createSlice, useBaseRoomShellStore, } from '@sqlrooms/room-shell';
|
|
4
|
+
import { createDefaultSqlEditorConfig, } from '@sqlrooms/sql-editor-config';
|
|
3
5
|
import { generateUniqueName } from '@sqlrooms/utils';
|
|
4
6
|
import { csvFormat } from 'd3-dsv';
|
|
5
7
|
import { saveAs } from 'file-saver';
|
|
6
8
|
import { produce } from 'immer';
|
|
7
|
-
import { createId } from '@paralleldrive/cuid2';
|
|
8
9
|
export function isQueryWithResult(queryResult) {
|
|
9
10
|
return (queryResult?.status === 'success' &&
|
|
10
11
|
(queryResult.type === 'pragma' ||
|
|
11
12
|
queryResult.type === 'explain' ||
|
|
12
13
|
queryResult.type === 'select'));
|
|
13
14
|
}
|
|
14
|
-
export function createSqlEditorSlice({ queryResultLimit = 100, queryResultLimitOptions = [100, 500, 1000], } = {}) {
|
|
15
|
+
export function createSqlEditorSlice({ config = createDefaultSqlEditorConfig(), queryResultLimit = 100, queryResultLimitOptions = [100, 500, 1000], } = {}) {
|
|
15
16
|
return createSlice((set, get) => {
|
|
16
17
|
return {
|
|
17
18
|
sqlEditor: {
|
|
19
|
+
config,
|
|
18
20
|
// Initialize runtime state
|
|
19
21
|
isTablesLoading: false,
|
|
20
22
|
queryResultLimit,
|
|
21
23
|
queryResultLimitOptions,
|
|
24
|
+
setConfig: (config) => {
|
|
25
|
+
set((state) => produce(state, (draft) => {
|
|
26
|
+
draft.sqlEditor.config = config;
|
|
27
|
+
}));
|
|
28
|
+
},
|
|
22
29
|
exportResultsToCsv: (results, filename) => {
|
|
23
30
|
if (!results)
|
|
24
31
|
return;
|
|
@@ -28,20 +35,20 @@ export function createSqlEditorSlice({ queryResultLimit = 100, queryResultLimitO
|
|
|
28
35
|
saveAs(blob, filename || `export-${createId().substring(0, 5)}.csv`);
|
|
29
36
|
},
|
|
30
37
|
createQueryTab: (initialQuery = '') => {
|
|
31
|
-
const sqlEditorConfig = get().config
|
|
38
|
+
const sqlEditorConfig = get().sqlEditor.config;
|
|
32
39
|
const newQuery = {
|
|
33
40
|
id: createId(),
|
|
34
41
|
name: generateUniqueName('Untitled', sqlEditorConfig.queries.map((q) => q.name)),
|
|
35
42
|
query: initialQuery,
|
|
36
43
|
};
|
|
37
44
|
set((state) => produce(state, (draft) => {
|
|
38
|
-
draft.config.
|
|
39
|
-
draft.config.
|
|
45
|
+
draft.sqlEditor.config.queries.push(newQuery);
|
|
46
|
+
draft.sqlEditor.config.selectedQueryId = newQuery.id;
|
|
40
47
|
}));
|
|
41
48
|
return newQuery;
|
|
42
49
|
},
|
|
43
50
|
deleteQueryTab: (queryId) => {
|
|
44
|
-
const sqlEditorConfig = get().config
|
|
51
|
+
const sqlEditorConfig = get().sqlEditor.config;
|
|
45
52
|
const queries = sqlEditorConfig.queries;
|
|
46
53
|
if (queries.length <= 1) {
|
|
47
54
|
// Don't delete the last query
|
|
@@ -53,7 +60,7 @@ export function createSqlEditorSlice({ queryResultLimit = 100, queryResultLimitO
|
|
|
53
60
|
const isSelected = sqlEditorConfig.selectedQueryId === queryId;
|
|
54
61
|
const filteredQueries = queries.filter((q) => q.id !== queryId);
|
|
55
62
|
set((state) => produce(state, (draft) => {
|
|
56
|
-
draft.config.
|
|
63
|
+
draft.sqlEditor.config.queries = filteredQueries;
|
|
57
64
|
// If we're deleting the selected tab, select the previous one or the first one
|
|
58
65
|
if (isSelected && filteredQueries.length > 0) {
|
|
59
66
|
const newSelectedIndex = Math.max(0, index - 1);
|
|
@@ -61,14 +68,14 @@ export function createSqlEditorSlice({ queryResultLimit = 100, queryResultLimitO
|
|
|
61
68
|
const newSelectedId = filteredQueries[newSelectedIndex]?.id ??
|
|
62
69
|
filteredQueries[0]?.id;
|
|
63
70
|
if (newSelectedId) {
|
|
64
|
-
draft.config.
|
|
71
|
+
draft.sqlEditor.config.selectedQueryId = newSelectedId;
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
}));
|
|
68
75
|
},
|
|
69
76
|
renameQueryTab: (queryId, newName) => {
|
|
70
77
|
set((state) => produce(state, (draft) => {
|
|
71
|
-
const query = draft.config.
|
|
78
|
+
const query = draft.sqlEditor.config.queries.find((q) => q.id === queryId);
|
|
72
79
|
if (query) {
|
|
73
80
|
query.name = newName || query.name;
|
|
74
81
|
}
|
|
@@ -76,22 +83,25 @@ export function createSqlEditorSlice({ queryResultLimit = 100, queryResultLimitO
|
|
|
76
83
|
},
|
|
77
84
|
closeQueryTab: (queryId) => {
|
|
78
85
|
set((state) => produce(state, (draft) => {
|
|
79
|
-
draft.config.
|
|
80
|
-
const openedTabs = draft.config.
|
|
81
|
-
if (draft.config.
|
|
82
|
-
|
|
86
|
+
draft.sqlEditor.config.closedTabIds.push(queryId);
|
|
87
|
+
const openedTabs = draft.sqlEditor.config.queries.filter((q) => !draft.sqlEditor.config.closedTabIds.includes(q.id));
|
|
88
|
+
if (draft.sqlEditor.config.selectedQueryId === queryId &&
|
|
89
|
+
openedTabs.length > 0 &&
|
|
90
|
+
openedTabs[0]) {
|
|
91
|
+
draft.sqlEditor.config.selectedQueryId = openedTabs[0].id;
|
|
83
92
|
}
|
|
84
93
|
}));
|
|
85
94
|
},
|
|
86
95
|
openQueryTab: (queryId) => {
|
|
87
96
|
set((state) => produce(state, (draft) => {
|
|
88
|
-
draft.
|
|
89
|
-
|
|
97
|
+
draft.sqlEditor.config.closedTabIds =
|
|
98
|
+
draft.sqlEditor.config.closedTabIds?.filter((id) => id !== queryId);
|
|
99
|
+
draft.sqlEditor.config.selectedQueryId = queryId;
|
|
90
100
|
}));
|
|
91
101
|
},
|
|
92
102
|
updateQueryText: (queryId, queryText) => {
|
|
93
103
|
set((state) => produce(state, (draft) => {
|
|
94
|
-
const query = draft.config.
|
|
104
|
+
const query = draft.sqlEditor.config.queries.find((q) => q.id === queryId);
|
|
95
105
|
if (query) {
|
|
96
106
|
query.query = queryText;
|
|
97
107
|
}
|
|
@@ -99,11 +109,11 @@ export function createSqlEditorSlice({ queryResultLimit = 100, queryResultLimitO
|
|
|
99
109
|
},
|
|
100
110
|
setSelectedQueryId: (queryId) => {
|
|
101
111
|
set((state) => produce(state, (draft) => {
|
|
102
|
-
draft.config.
|
|
112
|
+
draft.sqlEditor.config.selectedQueryId = queryId;
|
|
103
113
|
}));
|
|
104
114
|
},
|
|
105
115
|
getCurrentQuery: () => {
|
|
106
|
-
const sqlEditorConfig = get().config
|
|
116
|
+
const sqlEditorConfig = get().sqlEditor.config;
|
|
107
117
|
const selectedId = sqlEditorConfig.selectedQueryId;
|
|
108
118
|
const query = sqlEditorConfig.queries.find((q) => q.id === selectedId);
|
|
109
119
|
return query?.query || '';
|
|
@@ -159,7 +169,6 @@ export function createSqlEditorSlice({ queryResultLimit = 100, queryResultLimitO
|
|
|
159
169
|
isBeingAborted: false,
|
|
160
170
|
controller: queryController,
|
|
161
171
|
};
|
|
162
|
-
draft.config.sqlEditor.lastExecutedQuery = query;
|
|
163
172
|
}));
|
|
164
173
|
let queryResult;
|
|
165
174
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlEditorSlice.js","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n DuckDbSliceConfig,\n getSqlErrorWithPointer,\n splitSqlStatements,\n makeLimitQuery,\n} from '@sqlrooms/duckdb';\nimport {\n BaseRoomConfig,\n createSlice,\n RoomShellSliceState,\n StateCreator,\n useBaseRoomShellStore,\n} from '@sqlrooms/room-shell';\nimport {SqlEditorSliceConfig} from '@sqlrooms/sql-editor-config';\nimport {generateUniqueName, genRandomStr} from '@sqlrooms/utils';\nimport * as arrow from 'apache-arrow';\nimport {csvFormat} from 'd3-dsv';\nimport {saveAs} from 'file-saver';\nimport {produce} from 'immer';\nimport {createId} from '@paralleldrive/cuid2';\n\nexport type QueryResult =\n | {status: 'loading'; isBeingAborted?: boolean; controller: AbortController}\n | {status: 'aborted'}\n | {status: 'error'; error: string}\n | {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n result: arrow.Table | undefined;\n lastQueryStatement: string;\n }\n | {\n status: 'success';\n type: 'exec';\n lastQueryStatement: string;\n };\n\nexport function isQueryWithResult(\n queryResult: QueryResult | undefined,\n): queryResult is QueryResult & {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n} {\n return (\n queryResult?.status === 'success' &&\n (queryResult.type === 'pragma' ||\n queryResult.type === 'explain' ||\n queryResult.type === 'select')\n );\n}\n\nexport type SqlEditorSliceState = {\n sqlEditor: {\n // Runtime state\n queryResult?: QueryResult;\n /** @deprecated */\n selectedTable?: string;\n /** @deprecated Use `useStoreWithSqlEditor((s) => s.db.isRefreshingTableSchemas)` instead. */\n isTablesLoading: boolean;\n /** @deprecated */\n tablesError?: string;\n\n queryResultLimit: number;\n /** Options for the result limit dropdown */\n queryResultLimitOptions: number[];\n\n /**\n * Run the currently selected query.\n */\n parseAndRunQuery(query: string): Promise<void>;\n\n /**\n * Run the currently selected query.\n */\n parseAndRunCurrentQuery(): Promise<void>;\n\n /**\n * Abort the currently running query.\n */\n abortCurrentQuery(): void;\n\n /**\n * Export query results to CSV.\n * @deprecated Use `useExportToCsv` from `@sqlrooms/duckdb` instead.\n */\n exportResultsToCsv(results: arrow.Table, filename?: string): void;\n\n /**\n * Create a new query tab.\n * @param initialQuery - Optional initial query text.\n */\n createQueryTab(initialQuery?: string): {\n id: string;\n name: string;\n query: string;\n };\n\n /**\n * Delete a query tab.\n * @param queryId - The ID of the query to delete.\n */\n deleteQueryTab(queryId: string): void;\n\n /**\n * Rename a query tab.\n * @param queryId - The ID of the query to rename.\n * @param newName - The new name for the query.\n */\n renameQueryTab(queryId: string, newName: string): void;\n\n /**\n * Close a query tab.\n * @param queryId - The ID of the query to close.\n */\n closeQueryTab(queryId: string): void;\n /**\n * Open a closed tab id.\n * @param queryId - The ID of the query to remove.\n */\n openQueryTab(queryId: string): void;\n\n /**\n * Update the SQL text for a query.\n * @param queryId - The ID of the query to update.\n * @param queryText - The new SQL text.\n */\n updateQueryText(queryId: string, queryText: string): void;\n\n /**\n * Set the selected query tab.\n * @param queryId - The ID of the query to select.\n */\n setSelectedQueryId(queryId: string): void;\n\n /**\n * Get the currently selected query's SQL text.\n */\n getCurrentQuery(): string;\n\n /** @deprecated */\n selectTable(table: string | undefined): void;\n\n clearQueryResults(): void;\n\n setQueryResultLimit(limit: number): void;\n };\n};\n\nexport function createSqlEditorSlice<\n PC extends BaseRoomConfig & DuckDbSliceConfig & SqlEditorSliceConfig,\n>({\n queryResultLimit = 100,\n queryResultLimitOptions = [100, 500, 1000],\n}: {\n queryResultLimit?: number;\n queryResultLimitOptions?: number[];\n} = {}): StateCreator<SqlEditorSliceState> {\n return createSlice<PC, SqlEditorSliceState>((set, get) => {\n return {\n sqlEditor: {\n // Initialize runtime state\n isTablesLoading: false,\n queryResultLimit,\n queryResultLimitOptions,\n\n exportResultsToCsv: (results, filename) => {\n if (!results) return;\n const blob = new Blob([csvFormat(results.toArray())], {\n type: 'text/plain;charset=utf-8',\n });\n saveAs(blob, filename || `export-${createId().substring(0, 5)}.csv`);\n },\n\n createQueryTab: (initialQuery = '') => {\n const sqlEditorConfig = get().config.sqlEditor;\n const newQuery = {\n id: createId(),\n name: generateUniqueName(\n 'Untitled',\n sqlEditorConfig.queries.map((q) => q.name),\n ),\n query: initialQuery,\n };\n\n set((state) =>\n produce(state, (draft) => {\n draft.config.sqlEditor.queries.push(newQuery);\n draft.config.sqlEditor.selectedQueryId = newQuery.id;\n }),\n );\n\n return newQuery;\n },\n\n deleteQueryTab: (queryId) => {\n const sqlEditorConfig = get().config.sqlEditor;\n const queries = sqlEditorConfig.queries;\n\n if (queries.length <= 1) {\n // Don't delete the last query\n return;\n }\n\n const index = queries.findIndex((q) => q.id === queryId);\n if (index === -1) return;\n\n const isSelected = sqlEditorConfig.selectedQueryId === queryId;\n const filteredQueries = queries.filter((q) => q.id !== queryId);\n\n set((state) =>\n produce(state, (draft) => {\n draft.config.sqlEditor.queries = filteredQueries;\n\n // If we're deleting the selected tab, select the previous one or the first one\n if (isSelected && filteredQueries.length > 0) {\n const newSelectedIndex = Math.max(0, index - 1);\n // Safely access the ID with fallback to the first query if needed\n const newSelectedId =\n filteredQueries[newSelectedIndex]?.id ??\n filteredQueries[0]?.id;\n if (newSelectedId) {\n draft.config.sqlEditor.selectedQueryId = newSelectedId;\n }\n }\n }),\n );\n },\n\n renameQueryTab: (queryId, newName) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.config.sqlEditor.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.name = newName || query.name;\n }\n }),\n );\n },\n\n closeQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.config.sqlEditor.closedTabIds.push(queryId);\n const openedTabs = draft.config.sqlEditor.queries.filter((q) => !draft.config.sqlEditor.closedTabIds.includes(q.id));\n\n if (draft.config.sqlEditor.selectedQueryId === queryId && openedTabs.length > 0 && openedTabs[0]) {\n draft.config.sqlEditor.selectedQueryId = openedTabs[0].id;\n }\n }),\n );\n },\n\n openQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.config.sqlEditor.closedTabIds = draft.config.sqlEditor.closedTabIds?.filter((id) => id !== queryId);\n draft.config.sqlEditor.selectedQueryId = queryId;\n }),\n );\n },\n\n updateQueryText: (queryId, queryText) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.config.sqlEditor.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.query = queryText;\n }\n }),\n );\n },\n\n setSelectedQueryId: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.config.sqlEditor.selectedQueryId = queryId;\n }),\n );\n },\n\n getCurrentQuery: () => {\n const sqlEditorConfig = get().config.sqlEditor;\n const selectedId = sqlEditorConfig.selectedQueryId;\n const query = sqlEditorConfig.queries.find(\n (q) => q.id === selectedId,\n );\n return query?.query || '';\n },\n\n /** @deprecated */\n selectTable: (table) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = table;\n }),\n );\n },\n\n clearQueryResults: () => {\n // Update state without using Immer for the Table type\n set((state) => ({\n ...state,\n sqlEditor: {\n ...state.sqlEditor,\n queryResults: null,\n queryError: undefined,\n },\n }));\n },\n\n parseAndRunCurrentQuery: async (): Promise<void> =>\n get().sqlEditor.parseAndRunQuery(get().sqlEditor.getCurrentQuery()),\n\n abortCurrentQuery: () => {\n const currentResult = get().sqlEditor.queryResult;\n if (currentResult?.status === 'loading' && currentResult.controller) {\n currentResult.controller.abort();\n }\n\n set((state) =>\n produce(state, (draft) => {\n if (draft.sqlEditor.queryResult?.status === 'loading') {\n draft.sqlEditor.queryResult.isBeingAborted = true;\n }\n }),\n );\n },\n\n setQueryResultLimit: (limit) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.queryResultLimit = limit;\n }),\n );\n },\n\n parseAndRunQuery: async (query): Promise<void> => {\n if (get().sqlEditor.queryResult?.status === 'loading') {\n throw new Error('Query already running');\n }\n if (!query.trim()) {\n return;\n }\n\n // Create abort controller for this query execution\n const queryController = new AbortController();\n\n // First update loading state and clear results\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = undefined;\n draft.sqlEditor.queryResult = {\n status: 'loading',\n isBeingAborted: false,\n controller: queryController,\n };\n draft.config.sqlEditor.lastExecutedQuery = query;\n }),\n );\n\n let queryResult: QueryResult;\n try {\n const connector = await get().db.getConnector();\n const signal = queryController.signal;\n\n const statements = splitSqlStatements(query);\n const allButLastStatements = statements.slice(0, -1);\n const lastQueryStatement = statements[\n statements.length - 1\n ] as string;\n\n if (!statements?.length) {\n throw new Error('Empty query');\n }\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const parsedLastStatement =\n await get().db.sqlSelectToJson(lastQueryStatement);\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const isValidSelectQuery = !parsedLastStatement.error;\n\n if (isValidSelectQuery) {\n // Add limit to the last statement\n const queryWithLimit = [\n ...allButLastStatements,\n makeLimitQuery(lastQueryStatement, {\n sanitize: false, // should already be sanitized\n limit: get().sqlEditor.queryResultLimit,\n }),\n ].join(';\\n');\n const result = await connector.query(queryWithLimit, {signal});\n queryResult = {\n status: 'success',\n type: 'select',\n lastQueryStatement,\n result,\n };\n } else {\n // Run the complete query as it is\n if (\n parsedLastStatement.error &&\n parsedLastStatement.error_type !== 'not implemented'\n ) {\n throw (\n `${parsedLastStatement.error_type} ${parsedLastStatement.error_subtype}: ${parsedLastStatement.error_message}` +\n `\\n${getSqlErrorWithPointer(lastQueryStatement, Number(parsedLastStatement.position)).formatted}`\n );\n }\n\n const result = await connector.query(query, {signal});\n // EXPLAIN and PRAGMA are not detected as select queries\n // and we cannot wrap them in a SELECT * FROM,\n // but we can still execute them and return the result\n if (/^(EXPLAIN)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'explain',\n lastQueryStatement,\n result,\n };\n } else if (/^(PRAGMA)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'pragma',\n lastQueryStatement,\n result,\n };\n } else {\n queryResult = {\n status: 'success',\n type: 'exec',\n lastQueryStatement,\n };\n }\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n // Refresh table schemas if there are multiple statements or if the\n // last statement is not a select query\n if (statements.length > 1 || !isValidSelectQuery) {\n get().db.refreshTableSchemas();\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n } catch (e) {\n console.error(e);\n const errorMessage = e instanceof Error ? e.message : String(e);\n if (\n errorMessage === 'Query aborted' ||\n queryController.signal.aborted\n ) {\n queryResult = {status: 'aborted'};\n } else {\n queryResult = {\n status: 'error',\n error: errorMessage,\n };\n }\n }\n\n set((state) => ({\n ...state,\n sqlEditor: {...state.sqlEditor, queryResult},\n }));\n },\n },\n };\n });\n}\n\ntype RoomConfigWithSqlEditor = BaseRoomConfig & SqlEditorSliceConfig;\ntype RoomStateWithSqlEditor = RoomShellSliceState<RoomConfigWithSqlEditor> &\n SqlEditorSliceState;\n\nexport function useStoreWithSqlEditor<T>(\n selector: (state: RoomStateWithSqlEditor) => T,\n): T {\n return useBaseRoomShellStore<\n BaseRoomConfig & SqlEditorSliceConfig,\n RoomShellSliceState<RoomConfigWithSqlEditor>,\n T\n >((state) => selector(state as unknown as RoomStateWithSqlEditor));\n}"]}
|
|
1
|
+
{"version":3,"file":"SqlEditorSlice.js","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n DuckDbSliceState,\n getSqlErrorWithPointer,\n makeLimitQuery,\n splitSqlStatements,\n} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n RoomShellSliceState,\n StateCreator,\n useBaseRoomShellStore,\n} from '@sqlrooms/room-shell';\nimport {\n createDefaultSqlEditorConfig,\n SqlEditorSliceConfig,\n} from '@sqlrooms/sql-editor-config';\nimport {generateUniqueName} from '@sqlrooms/utils';\nimport * as arrow from 'apache-arrow';\nimport {csvFormat} from 'd3-dsv';\nimport {saveAs} from 'file-saver';\nimport {produce} from 'immer';\n\nexport type QueryResult =\n | {status: 'loading'; isBeingAborted?: boolean; controller: AbortController}\n | {status: 'aborted'}\n | {status: 'error'; error: string}\n | {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n result: arrow.Table | undefined;\n lastQueryStatement: string;\n }\n | {\n status: 'success';\n type: 'exec';\n lastQueryStatement: string;\n };\n\nexport function isQueryWithResult(\n queryResult: QueryResult | undefined,\n): queryResult is QueryResult & {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n} {\n return (\n queryResult?.status === 'success' &&\n (queryResult.type === 'pragma' ||\n queryResult.type === 'explain' ||\n queryResult.type === 'select')\n );\n}\n\nexport type SqlEditorSliceState = {\n sqlEditor: {\n config: SqlEditorSliceConfig;\n // Runtime state\n queryResult?: QueryResult;\n /** @deprecated */\n selectedTable?: string;\n /** @deprecated Use `useStoreWithSqlEditor((s) => s.db.isRefreshingTableSchemas)` instead. */\n isTablesLoading: boolean;\n /** @deprecated */\n tablesError?: string;\n\n queryResultLimit: number;\n /** Options for the result limit dropdown */\n queryResultLimitOptions: number[];\n\n /**\n * Set the config for the sql editor slice.\n */\n setConfig(config: SqlEditorSliceConfig): void;\n\n /**\n * Run the currently selected query.\n */\n parseAndRunQuery(query: string): Promise<void>;\n\n /**\n * Run the currently selected query.\n */\n parseAndRunCurrentQuery(): Promise<void>;\n\n /**\n * Abort the currently running query.\n */\n abortCurrentQuery(): void;\n\n /**\n * Export query results to CSV.\n * @deprecated Use `useExportToCsv` from `@sqlrooms/duckdb` instead.\n */\n exportResultsToCsv(results: arrow.Table, filename?: string): void;\n\n /**\n * Create a new query tab.\n * @param initialQuery - Optional initial query text.\n */\n createQueryTab(initialQuery?: string): {\n id: string;\n name: string;\n query: string;\n };\n\n /**\n * Delete a query tab.\n * @param queryId - The ID of the query to delete.\n */\n deleteQueryTab(queryId: string): void;\n\n /**\n * Rename a query tab.\n * @param queryId - The ID of the query to rename.\n * @param newName - The new name for the query.\n */\n renameQueryTab(queryId: string, newName: string): void;\n\n /**\n * Close a query tab.\n * @param queryId - The ID of the query to close.\n */\n closeQueryTab(queryId: string): void;\n /**\n * Open a closed tab id.\n * @param queryId - The ID of the query to remove.\n */\n openQueryTab(queryId: string): void;\n\n /**\n * Update the SQL text for a query.\n * @param queryId - The ID of the query to update.\n * @param queryText - The new SQL text.\n */\n updateQueryText(queryId: string, queryText: string): void;\n\n /**\n * Set the selected query tab.\n * @param queryId - The ID of the query to select.\n */\n setSelectedQueryId(queryId: string): void;\n\n /**\n * Get the currently selected query's SQL text.\n */\n getCurrentQuery(): string;\n\n /** @deprecated */\n selectTable(table: string | undefined): void;\n\n clearQueryResults(): void;\n\n setQueryResultLimit(limit: number): void;\n };\n};\n\nexport function createSqlEditorSlice({\n config = createDefaultSqlEditorConfig(),\n queryResultLimit = 100,\n queryResultLimitOptions = [100, 500, 1000],\n}: {\n config?: SqlEditorSliceConfig;\n queryResultLimit?: number;\n queryResultLimitOptions?: number[];\n} = {}): StateCreator<SqlEditorSliceState> {\n return createSlice<\n SqlEditorSliceState,\n BaseRoomStoreState & DuckDbSliceState & SqlEditorSliceState\n >((set, get) => {\n return {\n sqlEditor: {\n config,\n // Initialize runtime state\n isTablesLoading: false,\n queryResultLimit,\n queryResultLimitOptions,\n\n setConfig: (config) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config = config;\n }),\n );\n },\n\n exportResultsToCsv: (results, filename) => {\n if (!results) return;\n const blob = new Blob([csvFormat(results.toArray())], {\n type: 'text/plain;charset=utf-8',\n });\n saveAs(blob, filename || `export-${createId().substring(0, 5)}.csv`);\n },\n\n createQueryTab: (initialQuery = '') => {\n const sqlEditorConfig = get().sqlEditor.config;\n const newQuery = {\n id: createId(),\n name: generateUniqueName(\n 'Untitled',\n sqlEditorConfig.queries.map((q) => q.name),\n ),\n query: initialQuery,\n };\n\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.queries.push(newQuery);\n draft.sqlEditor.config.selectedQueryId = newQuery.id;\n }),\n );\n\n return newQuery;\n },\n\n deleteQueryTab: (queryId) => {\n const sqlEditorConfig = get().sqlEditor.config;\n const queries = sqlEditorConfig.queries;\n\n if (queries.length <= 1) {\n // Don't delete the last query\n return;\n }\n\n const index = queries.findIndex((q) => q.id === queryId);\n if (index === -1) return;\n\n const isSelected = sqlEditorConfig.selectedQueryId === queryId;\n const filteredQueries = queries.filter((q) => q.id !== queryId);\n\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.queries = filteredQueries;\n\n // If we're deleting the selected tab, select the previous one or the first one\n if (isSelected && filteredQueries.length > 0) {\n const newSelectedIndex = Math.max(0, index - 1);\n // Safely access the ID with fallback to the first query if needed\n const newSelectedId =\n filteredQueries[newSelectedIndex]?.id ??\n filteredQueries[0]?.id;\n if (newSelectedId) {\n draft.sqlEditor.config.selectedQueryId = newSelectedId;\n }\n }\n }),\n );\n },\n\n renameQueryTab: (queryId, newName) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.name = newName || query.name;\n }\n }),\n );\n },\n\n closeQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.closedTabIds.push(queryId);\n const openedTabs = draft.sqlEditor.config.queries.filter(\n (q) => !draft.sqlEditor.config.closedTabIds.includes(q.id),\n );\n\n if (\n draft.sqlEditor.config.selectedQueryId === queryId &&\n openedTabs.length > 0 &&\n openedTabs[0]\n ) {\n draft.sqlEditor.config.selectedQueryId = openedTabs[0].id;\n }\n }),\n );\n },\n\n openQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.closedTabIds =\n draft.sqlEditor.config.closedTabIds?.filter(\n (id) => id !== queryId,\n );\n draft.sqlEditor.config.selectedQueryId = queryId;\n }),\n );\n },\n\n updateQueryText: (queryId, queryText) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.query = queryText;\n }\n }),\n );\n },\n\n setSelectedQueryId: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.selectedQueryId = queryId;\n }),\n );\n },\n\n getCurrentQuery: () => {\n const sqlEditorConfig = get().sqlEditor.config;\n const selectedId = sqlEditorConfig.selectedQueryId;\n const query = sqlEditorConfig.queries.find(\n (q) => q.id === selectedId,\n );\n return query?.query || '';\n },\n\n /** @deprecated */\n selectTable: (table) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = table;\n }),\n );\n },\n\n clearQueryResults: () => {\n // Update state without using Immer for the Table type\n set((state) => ({\n ...state,\n sqlEditor: {\n ...state.sqlEditor,\n queryResults: null,\n queryError: undefined,\n },\n }));\n },\n\n parseAndRunCurrentQuery: async (): Promise<void> =>\n get().sqlEditor.parseAndRunQuery(get().sqlEditor.getCurrentQuery()),\n\n abortCurrentQuery: () => {\n const currentResult = get().sqlEditor.queryResult;\n if (currentResult?.status === 'loading' && currentResult.controller) {\n currentResult.controller.abort();\n }\n\n set((state) =>\n produce(state, (draft) => {\n if (draft.sqlEditor.queryResult?.status === 'loading') {\n draft.sqlEditor.queryResult.isBeingAborted = true;\n }\n }),\n );\n },\n\n setQueryResultLimit: (limit) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.queryResultLimit = limit;\n }),\n );\n },\n\n parseAndRunQuery: async (query): Promise<void> => {\n if (get().sqlEditor.queryResult?.status === 'loading') {\n throw new Error('Query already running');\n }\n if (!query.trim()) {\n return;\n }\n\n // Create abort controller for this query execution\n const queryController = new AbortController();\n\n // First update loading state and clear results\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = undefined;\n draft.sqlEditor.queryResult = {\n status: 'loading',\n isBeingAborted: false,\n controller: queryController,\n };\n }),\n );\n\n let queryResult: QueryResult;\n try {\n const connector = await get().db.getConnector();\n const signal = queryController.signal;\n\n const statements = splitSqlStatements(query);\n const allButLastStatements = statements.slice(0, -1);\n const lastQueryStatement = statements[\n statements.length - 1\n ] as string;\n\n if (!statements?.length) {\n throw new Error('Empty query');\n }\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const parsedLastStatement =\n await get().db.sqlSelectToJson(lastQueryStatement);\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const isValidSelectQuery = !parsedLastStatement.error;\n\n if (isValidSelectQuery) {\n // Add limit to the last statement\n const queryWithLimit = [\n ...allButLastStatements,\n makeLimitQuery(lastQueryStatement, {\n sanitize: false, // should already be sanitized\n limit: get().sqlEditor.queryResultLimit,\n }),\n ].join(';\\n');\n const result = await connector.query(queryWithLimit, {signal});\n queryResult = {\n status: 'success',\n type: 'select',\n lastQueryStatement,\n result,\n };\n } else {\n // Run the complete query as it is\n if (\n parsedLastStatement.error &&\n parsedLastStatement.error_type !== 'not implemented'\n ) {\n throw (\n `${parsedLastStatement.error_type} ${parsedLastStatement.error_subtype}: ${parsedLastStatement.error_message}` +\n `\\n${getSqlErrorWithPointer(lastQueryStatement, Number(parsedLastStatement.position)).formatted}`\n );\n }\n\n const result = await connector.query(query, {signal});\n // EXPLAIN and PRAGMA are not detected as select queries\n // and we cannot wrap them in a SELECT * FROM,\n // but we can still execute them and return the result\n if (/^(EXPLAIN)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'explain',\n lastQueryStatement,\n result,\n };\n } else if (/^(PRAGMA)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'pragma',\n lastQueryStatement,\n result,\n };\n } else {\n queryResult = {\n status: 'success',\n type: 'exec',\n lastQueryStatement,\n };\n }\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n // Refresh table schemas if there are multiple statements or if the\n // last statement is not a select query\n if (statements.length > 1 || !isValidSelectQuery) {\n get().db.refreshTableSchemas();\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n } catch (e) {\n console.error(e);\n const errorMessage = e instanceof Error ? e.message : String(e);\n if (\n errorMessage === 'Query aborted' ||\n queryController.signal.aborted\n ) {\n queryResult = {status: 'aborted'};\n } else {\n queryResult = {\n status: 'error',\n error: errorMessage,\n };\n }\n }\n\n set((state) => ({\n ...state,\n sqlEditor: {...state.sqlEditor, queryResult},\n }));\n },\n },\n } satisfies SqlEditorSliceState;\n });\n}\n\ntype RoomStateWithSqlEditor = RoomShellSliceState & SqlEditorSliceState;\n\nexport function useStoreWithSqlEditor<T>(\n selector: (state: RoomStateWithSqlEditor) => T,\n): T {\n return useBaseRoomShellStore<RoomShellSliceState, T>((state) =>\n selector(state as unknown as RoomStateWithSqlEditor),\n );\n}\n"]}
|
|
@@ -6,8 +6,8 @@ import { QueryEditorPanelEditor } from './QueryEditorPanelEditor';
|
|
|
6
6
|
import { QueryEditorPanelTabsList } from './QueryEditorPanelTabsList';
|
|
7
7
|
export const QueryEditorPanel = ({ className, }) => {
|
|
8
8
|
// Get state and actions from store in a single call
|
|
9
|
-
const selectedQueryId = useStoreWithSqlEditor((s) => s.config.
|
|
10
|
-
const queries = useStoreWithSqlEditor((s) => s.config.
|
|
9
|
+
const selectedQueryId = useStoreWithSqlEditor((s) => s.sqlEditor.config.selectedQueryId);
|
|
10
|
+
const queries = useStoreWithSqlEditor((s) => s.sqlEditor.config.queries);
|
|
11
11
|
const setSelectedQueryId = useStoreWithSqlEditor((s) => s.sqlEditor.setSelectedQueryId);
|
|
12
12
|
return (_jsxs(Tabs, { value: selectedQueryId, onValueChange: setSelectedQueryId, className: cn('flex h-full flex-col',
|
|
13
13
|
// this is for Monaco's completion menu to not being cut off
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryEditorPanel.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanel.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AACnD,OAAO,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAC,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAC,wBAAwB,EAAC,MAAM,4BAA4B,CAAC;AAOpE,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,SAAS,GACV,EAAE,EAAE;IACH,oDAAoD;IAEpD,MAAM,eAAe,GAAG,qBAAqB,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"QueryEditorPanel.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanel.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AACnD,OAAO,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAC,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAC,wBAAwB,EAAC,MAAM,4BAA4B,CAAC;AAOpE,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,SAAS,GACV,EAAE,EAAE;IACH,oDAAoD;IAEpD,MAAM,eAAe,GAAG,qBAAqB,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,eAAe,CAC1C,CAAC;IACF,MAAM,OAAO,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzE,MAAM,kBAAkB,GAAG,qBAAqB,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,kBAAkB,CACtC,CAAC;IAEF,OAAO,CACL,MAAC,IAAI,IACH,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,kBAAkB,EACjC,SAAS,EAAE,EAAE,CACX,sBAAsB;QACtB,4DAA4D;QAC5D,kBAAkB,EAClB,SAAS,CACV,aAED,eAAK,SAAS,EAAC,0DAA0D,aACvE,KAAC,wBAAwB,KAAG,EAC5B,cAAK,SAAS,EAAC,QAAQ,GAAG,EAC1B,KAAC,uBAAuB,KAAG,IACvB,EACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAClB,KAAC,WAAW,IAEV,KAAK,EAAE,CAAC,CAAC,EAAE,EACX,SAAS,EAAC,6DAA6D,YAEvE,cAAK,SAAS,EAAC,0CAA0C,YACtD,CAAC,CAAC,EAAE,KAAK,eAAe,IAAI,CAC3B,KAAC,sBAAsB,IAAC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAI,CAC1C,GACG,IARD,CAAC,CAAC,EAAE,CASG,CACf,CAAC,IACG,CACR,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import React from 'react';\nimport {cn, Tabs, TabsContent} from '@sqlrooms/ui';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport {QueryEditorPanelActions} from './QueryEditorPanelActions';\nimport {QueryEditorPanelEditor} from './QueryEditorPanelEditor';\nimport {QueryEditorPanelTabsList} from './QueryEditorPanelTabsList';\n\nexport interface QueryEditorPanelProps {\n /** Custom class name for styling */\n className?: string;\n}\n\nexport const QueryEditorPanel: React.FC<QueryEditorPanelProps> = ({\n className,\n}) => {\n // Get state and actions from store in a single call\n\n const selectedQueryId = useStoreWithSqlEditor(\n (s) => s.sqlEditor.config.selectedQueryId,\n );\n const queries = useStoreWithSqlEditor((s) => s.sqlEditor.config.queries);\n const setSelectedQueryId = useStoreWithSqlEditor(\n (s) => s.sqlEditor.setSelectedQueryId,\n );\n\n return (\n <Tabs\n value={selectedQueryId}\n onValueChange={setSelectedQueryId}\n className={cn(\n 'flex h-full flex-col',\n // this is for Monaco's completion menu to not being cut off\n 'overflow-visible',\n className,\n )}\n >\n <div className=\"border-border flex items-center gap-4 border-b px-2 pt-1\">\n <QueryEditorPanelTabsList />\n <div className=\"flex-1\" />\n <QueryEditorPanelActions />\n </div>\n {queries.map((q) => (\n <TabsContent\n key={q.id}\n value={q.id}\n className=\"relative h-full flex-grow flex-col data-[state=active]:flex\"\n >\n <div className=\"absolute inset-0 h-full w-full flex-grow\">\n {q.id === selectedQueryId && (\n <QueryEditorPanelEditor queryId={q.id} />\n )}\n </div>\n </TabsContent>\n ))}\n </Tabs>\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryEditorPanelActions.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanelActions.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,
|
|
1
|
+
{"version":3,"file":"QueryEditorPanelActions.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanelActions.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,CAgFlE,CAAC"}
|
|
@@ -44,7 +44,7 @@ export const QueryEditorPanelActions = ({ className, }) => {
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
const buttonContent = getButtonContent();
|
|
47
|
-
return (_jsxs(Tooltip, { delayDuration: 100, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs(Button, { className: cn('flex items-center justify-center gap-2
|
|
47
|
+
return (_jsxs(Tooltip, { delayDuration: 100, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs(Button, { className: cn('flex h-6 items-center justify-center gap-2 px-4', className), variant: "default", size: "xs", onClick: handleClick, disabled: buttonContent.disabled, children: [buttonContent?.icon, _jsx("span", { children: buttonContent.text }), buttonContent.rightIcon] }) }), _jsx(TooltipContent, { align: "end", children: isLoading
|
|
48
48
|
? 'Cancel the running query'
|
|
49
49
|
: `Run query (${isMac ? 'Cmd' : 'Ctrl'}+Enter)` })] }));
|
|
50
50
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryEditorPanelActions.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelActions.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAC,OAAO,EAAE,YAAY,EAAC,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AAExD,MAAM,CAAC,MAAM,uBAAuB,GAAmC,CAAC,EACtE,SAAS,GACV,EAAE,EAAE;IACH,MAAM,eAAe,GAAG,qBAAqB,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAC3C,CAAC;IACF,MAAM,iBAAiB,GAAG,qBAAqB,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,iBAAiB,CACrC,CAAC;IACF,MAAM,WAAW,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IAExB,MAAM,SAAS,GAAG,WAAW,EAAE,MAAM,KAAK,SAAS,CAAC;IACpD,MAAM,SAAS,GACb,WAAW,EAAE,MAAM,KAAK,SAAS,IAAI,WAAW,CAAC,cAAc,CAAC;IAElE,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,IAAI,SAAS,EAAE,CAAC;YACd,iBAAiB,EAAE,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,eAAe,EAAE,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,GAKvB,EAAE;QACF,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO;oBACL,IAAI,EAAE,KAAC,OAAO,IAAC,SAAS,EAAC,sBAAsB,GAAG;oBAClD,IAAI,EAAE,eAAe;oBACrB,QAAQ,EAAE,IAAI;iBACf,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO;oBACL,IAAI,EAAE,KAAC,OAAO,IAAC,SAAS,EAAC,sBAAsB,GAAG;oBAClD,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,KAAK;oBACf,SAAS,EAAE,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,GAAG;iBAChD,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IAEzC,OAAO,CACL,MAAC,OAAO,IAAC,aAAa,EAAE,GAAG,aACzB,KAAC,cAAc,IAAC,OAAO,kBACrB,MAAC,MAAM,IACL,SAAS,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"QueryEditorPanelActions.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelActions.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAC,OAAO,EAAE,YAAY,EAAC,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AAExD,MAAM,CAAC,MAAM,uBAAuB,GAAmC,CAAC,EACtE,SAAS,GACV,EAAE,EAAE;IACH,MAAM,eAAe,GAAG,qBAAqB,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAC3C,CAAC;IACF,MAAM,iBAAiB,GAAG,qBAAqB,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,iBAAiB,CACrC,CAAC;IACF,MAAM,WAAW,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IAExB,MAAM,SAAS,GAAG,WAAW,EAAE,MAAM,KAAK,SAAS,CAAC;IACpD,MAAM,SAAS,GACb,WAAW,EAAE,MAAM,KAAK,SAAS,IAAI,WAAW,CAAC,cAAc,CAAC;IAElE,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,IAAI,SAAS,EAAE,CAAC;YACd,iBAAiB,EAAE,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,eAAe,EAAE,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,GAKvB,EAAE;QACF,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO;oBACL,IAAI,EAAE,KAAC,OAAO,IAAC,SAAS,EAAC,sBAAsB,GAAG;oBAClD,IAAI,EAAE,eAAe;oBACrB,QAAQ,EAAE,IAAI;iBACf,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO;oBACL,IAAI,EAAE,KAAC,OAAO,IAAC,SAAS,EAAC,sBAAsB,GAAG;oBAClD,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,KAAK;oBACf,SAAS,EAAE,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,GAAG;iBAChD,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IAEzC,OAAO,CACL,MAAC,OAAO,IAAC,aAAa,EAAE,GAAG,aACzB,KAAC,cAAc,IAAC,OAAO,kBACrB,MAAC,MAAM,IACL,SAAS,EAAE,EAAE,CACX,iDAAiD,EACjD,SAAS,CACV,EACD,OAAO,EAAC,SAAS,EACjB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,aAAa,CAAC,QAAQ,aAE/B,aAAa,EAAE,IAAI,EACpB,yBAAO,aAAa,CAAC,IAAI,GAAQ,EAChC,aAAa,CAAC,SAAS,IACjB,GACM,EACjB,KAAC,cAAc,IAAC,KAAK,EAAC,KAAK,YACxB,SAAS;oBACR,CAAC,CAAC,0BAA0B;oBAC5B,CAAC,CAAC,cAAc,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,SAAS,GAClC,IACT,CACX,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {\n Button,\n cn,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@sqlrooms/ui';\nimport {isMacOS} from '@sqlrooms/utils';\nimport {Loader2, OctagonXIcon} from 'lucide-react';\nimport React from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\n\nexport const QueryEditorPanelActions: React.FC<{className?: string}> = ({\n className,\n}) => {\n const runCurrentQuery = useStoreWithSqlEditor(\n (s) => s.sqlEditor.parseAndRunCurrentQuery,\n );\n const abortCurrentQuery = useStoreWithSqlEditor(\n (s) => s.sqlEditor.abortCurrentQuery,\n );\n const queryResult = useStoreWithSqlEditor((s) => s.sqlEditor.queryResult);\n const isMac = isMacOS();\n\n const isLoading = queryResult?.status === 'loading';\n const isAborted =\n queryResult?.status === 'loading' && queryResult.isBeingAborted;\n\n const handleClick = () => {\n if (isLoading) {\n abortCurrentQuery();\n } else {\n runCurrentQuery();\n }\n };\n\n const getButtonContent = (): {\n icon?: React.ReactNode;\n text: string;\n disabled: boolean;\n rightIcon?: React.ReactNode;\n } => {\n if (isLoading) {\n if (isAborted) {\n return {\n icon: <Loader2 className=\"h-3 w-3 animate-spin\" />,\n text: 'Cancelling...',\n disabled: true,\n };\n } else {\n return {\n icon: <Loader2 className=\"h-3 w-3 animate-spin\" />,\n text: 'Cancel',\n disabled: false,\n rightIcon: <OctagonXIcon className=\"h-3 w-3\" />,\n };\n }\n } else {\n return {\n text: 'Run',\n disabled: false,\n };\n }\n };\n\n const buttonContent = getButtonContent();\n\n return (\n <Tooltip delayDuration={100}>\n <TooltipTrigger asChild>\n <Button\n className={cn(\n 'flex h-6 items-center justify-center gap-2 px-4',\n className,\n )}\n variant=\"default\"\n size=\"xs\"\n onClick={handleClick}\n disabled={buttonContent.disabled}\n >\n {buttonContent?.icon}\n <span>{buttonContent.text}</span>\n {buttonContent.rightIcon}\n </Button>\n </TooltipTrigger>\n <TooltipContent align=\"end\">\n {isLoading\n ? 'Cancel the running query'\n : `Run query (${isMac ? 'Cmd' : 'Ctrl'}+Enter)`}\n </TooltipContent>\n </Tooltip>\n );\n};\n"]}
|
|
@@ -15,7 +15,7 @@ export const QueryEditorPanelEditor = ({ className, queryId }) => {
|
|
|
15
15
|
const tableSchemas = useStoreWithSqlEditor((s) => s.db.tables);
|
|
16
16
|
const runQuery = useStoreWithSqlEditor((s) => s.sqlEditor.parseAndRunQuery);
|
|
17
17
|
const connector = useStoreWithSqlEditor((s) => s.db.connector);
|
|
18
|
-
const queryText = useStoreWithSqlEditor((s) => s.config.
|
|
18
|
+
const queryText = useStoreWithSqlEditor((s) => s.sqlEditor.config.queries.find((q) => q.id === queryId)?.query);
|
|
19
19
|
const updateQueryText = useStoreWithSqlEditor((s) => s.sqlEditor.updateQueryText);
|
|
20
20
|
// Editor instance ref for keyboard shortcuts
|
|
21
21
|
const editorRef = useRef({});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryEditorPanelEditor.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelEditor.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAEhC,OAAO,EAAC,WAAW,EAAE,MAAM,EAAC,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAC,eAAe,EAAC,MAAM,oBAAoB,CAAC;AAKnD,MAAM,cAAc,GAAuD;IACzE,oBAAoB,EAAE,KAAK;IAC3B,eAAe,EAAE,IAAI;IACrB,OAAO,EAAE,EAAC,OAAO,EAAE,KAAK,EAAC;IACzB,QAAQ,EAAE,IAAI;IACd,gBAAgB,EAAE,IAAI;IACtB,0BAA0B,EAAE,IAAI;CACjC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAG9B,CAAC,EAAC,SAAS,EAAE,OAAO,EAAC,EAAE,EAAE;IAC5B,MAAM,YAAY,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAE/D,MAAM,SAAS,GAAG,qBAAqB,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"QueryEditorPanelEditor.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import {cn} from '@sqlrooms/ui';\nimport type * as Monaco from 'monaco-editor';\nimport {useCallback, useRef} from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport {SqlMonacoEditor} from '../SqlMonacoEditor';\n\ntype EditorInstance = Monaco.editor.IStandaloneCodeEditor;\ntype MonacoInstance = typeof Monaco;\n\nconst MONACO_OPTIONS: Monaco.editor.IStandaloneEditorConstructionOptions = {\n scrollBeyondLastLine: false,\n automaticLayout: true,\n minimap: {enabled: false},\n wordWrap: 'on',\n quickSuggestions: true,\n suggestOnTriggerCharacters: true,\n};\n\nexport const QueryEditorPanelEditor: React.FC<{\n className?: string;\n queryId: string;\n}> = ({className, queryId}) => {\n const tableSchemas = useStoreWithSqlEditor((s) => s.db.tables);\n const runQuery = useStoreWithSqlEditor((s) => s.sqlEditor.parseAndRunQuery);\n const connector = useStoreWithSqlEditor((s) => s.db.connector);\n\n const queryText = useStoreWithSqlEditor(\n (s) => s.sqlEditor.config.queries.find((q) => q.id === queryId)?.query,\n );\n const updateQueryText = useStoreWithSqlEditor(\n (s) => s.sqlEditor.updateQueryText,\n );\n // Editor instance ref for keyboard shortcuts\n const editorRef = useRef<{\n [key: string]: EditorInstance;\n }>({});\n\n // Handle query text update\n const handleUpdateQuery = useCallback(\n (value: string | undefined) => {\n if (!value) return;\n updateQueryText(queryId, value);\n },\n [queryId, updateQueryText],\n );\n\n // Handle editor mount\n const handleEditorMount = useCallback(\n (editor: EditorInstance, monaco: MonacoInstance) => {\n editorRef.current[queryId] = editor;\n // Add keyboard shortcut for running query\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (model && selection && !selection.isEmpty()) {\n runQuery(model.getValueInRange(selection));\n } else {\n runQuery(editor.getValue());\n }\n });\n },\n [runQuery],\n );\n\n return (\n <SqlMonacoEditor\n connector={connector}\n value={queryText ?? ''}\n onChange={handleUpdateQuery}\n className={cn('h-full w-full flex-grow', className)}\n options={MONACO_OPTIONS}\n onMount={handleEditorMount}\n tableSchemas={tableSchemas}\n />\n );\n};\n"]}
|
|
@@ -7,8 +7,8 @@ import DeleteSqlQueryModal from './DeleteSqlQueryModal';
|
|
|
7
7
|
import { QueryTabMenuItem } from './QueryTabMenuItem';
|
|
8
8
|
import RenameSqlQueryModal from './RenameSqlQueryModal';
|
|
9
9
|
export const QueryEditorPanelTabsList = ({ className, }) => {
|
|
10
|
-
const queries = useStoreWithSqlEditor((s) => s.config.
|
|
11
|
-
const closedTabIds = useStoreWithSqlEditor((s) => s.config.
|
|
10
|
+
const queries = useStoreWithSqlEditor((s) => s.sqlEditor.config.queries);
|
|
11
|
+
const closedTabIds = useStoreWithSqlEditor((s) => s.sqlEditor.config.closedTabIds);
|
|
12
12
|
const openedTabs = queries.filter((q) => !closedTabIds.includes(q.id));
|
|
13
13
|
const closedTabs = queries.filter((q) => closedTabIds.includes(q.id));
|
|
14
14
|
const renameQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.renameQueryTab);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryEditorPanelTabsList.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Button,\n cn,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n EditableText,\n Input,\n TabsList,\n TabsTrigger,\n} from '@sqlrooms/ui';\nimport {ListCollapseIcon, PlusIcon, XIcon, SearchIcon} from 'lucide-react';\nimport React, {useCallback, useMemo, useRef, useState} from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport DeleteSqlQueryModal from './DeleteSqlQueryModal';\nimport {QueryTabMenuItem} from './QueryTabMenuItem';\nimport RenameSqlQueryModal from './RenameSqlQueryModal';\n\nexport const QueryEditorPanelTabsList: React.FC<{className?: string}> = ({\n className,\n}) => {\n const queries = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries);\n const closedTabIds = useStoreWithSqlEditor(\n (s) => s.config.sqlEditor.closedTabIds,\n );\n const openedTabs = queries.filter((q) => !closedTabIds.includes(q.id));\n const closedTabs = queries.filter((q) => closedTabIds.includes(q.id));\n\n const renameQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.renameQueryTab,\n );\n\n // Local state for modals and editing\n const [queryToDelete, setQueryToDelete] = useState<string | null>(null);\n const [editingQueryId, setEditingQueryId] = useState<string | null>(null);\n const [queryToRename, setQueryToRename] = useState<{\n id: string;\n name: string;\n } | null>(null);\n const [searchQuery, setSearchQuery] = useState('');\n\n // Ref for the scrollable container\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const closeQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.closeQueryTab);\n const openQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.openQueryTab);\n const createQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.createQueryTab,\n );\n const deleteQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.deleteQueryTab,\n );\n\n // Handle rename query\n const handleStartRename = useCallback(\n (queryId: string, currentName: string) => {\n setQueryToRename({id: queryId, name: currentName});\n },\n [],\n );\n\n const handleFinishRename = useCallback(\n (newName: string) => {\n if (queryToRename) {\n renameQueryTab(queryToRename.id, newName);\n }\n setQueryToRename(null);\n },\n [queryToRename, renameQueryTab],\n );\n // Handle rename query\n const handleRename = useCallback(\n (queryId: string, newName: string) => {\n if (newName.trim() !== '') {\n renameQueryTab(queryId, newName.trim());\n }\n setEditingQueryId(null);\n },\n [renameQueryTab],\n );\n\n // Handle double click to start editing\n const handleDoubleClick = useCallback((queryId: string) => {\n setEditingQueryId(queryId);\n }, []);\n\n // Handle delete query\n const handleDeleteQuery = useCallback(\n (queryId: string) => {\n // Find the query to check if it's empty\n const queryToDelete = queries.find((q) => q.id === queryId);\n\n // If query is empty (no content), delete immediately without confirmation\n if (queryToDelete && queryToDelete.query.trim() === '') {\n deleteQueryTab(queryId);\n } else {\n // Otherwise, show confirmation modal\n setQueryToDelete(queryId);\n }\n },\n [queries, deleteQueryTab],\n );\n\n // Handle new query creation\n const handleNewQuery = useCallback(() => {\n createQueryTab();\n // Auto-scroll to the right after a short delay to ensure the tab is rendered\n setTimeout(() => {\n if (scrollContainerRef.current) {\n scrollContainerRef.current.scrollTo({\n left: scrollContainerRef.current.scrollWidth,\n behavior: 'smooth',\n });\n }\n }, 0);\n }, [createQueryTab]);\n\n const handleConfirmDeleteQuery = useCallback(() => {\n if (queryToDelete) {\n deleteQueryTab(queryToDelete);\n setQueryToDelete(null);\n }\n }, [queryToDelete, deleteQueryTab]);\n\n const filteredClosedTabs = useMemo(() => {\n if (!searchQuery.trim()) return closedTabs;\n const lowerQuery = searchQuery.toLowerCase();\n return closedTabs.filter((tab) =>\n tab.name.toLowerCase().includes(lowerQuery),\n );\n }, [closedTabs, searchQuery]);\n\n const filteredOpenedTabs = useMemo(() => {\n if (!searchQuery.trim()) return openedTabs;\n const lowerQuery = searchQuery.toLowerCase();\n return openedTabs.filter((tab) =>\n tab.name.toLowerCase().includes(lowerQuery),\n );\n }, [openedTabs, searchQuery]);\n\n const renderTabGroup = useCallback(\n (tabs: typeof queries, emptyMessage: string) => {\n if (tabs.length === 0) {\n return (\n <DropdownMenuItem\n className=\"items-center justify-center text-xs\"\n disabled\n >\n {emptyMessage}\n </DropdownMenuItem>\n );\n }\n\n return tabs.map((tab) => (\n <QueryTabMenuItem\n key={tab.id}\n tab={tab}\n onRestore={() => openQueryTab(tab.id)}\n onRename={() => handleStartRename(tab.id, tab.name)}\n onDelete={() => handleDeleteQuery(tab.id)}\n />\n ));\n },\n [openQueryTab, handleStartRename, handleDeleteQuery],\n );\n\n return (\n <>\n <TabsList\n className={cn(\n 'flex min-w-0 justify-start gap-1 bg-transparent p-0 pt-1.5',\n className,\n )}\n >\n <div\n ref={scrollContainerRef}\n className=\"flex h-full min-w-0 items-center gap-1 overflow-x-auto overflow-y-hidden pr-1 [&::-webkit-scrollbar]:hidden\"\n >\n {openedTabs.map((q) => (\n <TabsTrigger\n key={q.id}\n value={q.id}\n className=\"data-[state=inactive]:hover:bg-primary/5 flex h-full min-w-[100px] max-w-[200px] flex-shrink-0 items-center justify-between gap-2 overflow-hidden rounded-b-none py-0 pl-4 pr-2 font-normal data-[state=active]:shadow-none\"\n >\n <div\n className=\"flex min-w-0 items-center\"\n onDoubleClick={() => handleDoubleClick(q.id)}\n >\n {editingQueryId !== q.id ? (\n <div className=\"truncate text-sm\">{q.name}</div>\n ) : (\n <EditableText\n value={q.name}\n onChange={(newName: string) => handleRename(q.id, newName)}\n className=\"h-6 min-w-0 flex-1 truncate text-sm shadow-none\"\n isEditing={editingQueryId === q.id}\n onEditingChange={(isEditing) => {\n if (!isEditing) {\n setEditingQueryId(null);\n }\n }}\n />\n )}\n </div>\n\n <Button\n size=\"xs\"\n variant=\"ghost\"\n className=\"hover:bg-primary/10 h-4 w-4 p-1\"\n onMouseDown={(e) => {\n e.stopPropagation();\n e.preventDefault();\n }}\n onClick={(e) => {\n e.stopPropagation();\n e.preventDefault();\n closeQueryTab(q.id);\n }}\n >\n <XIcon size={12} />\n </Button>\n </TabsTrigger>\n ))}\n </div>\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"ml-2 h-5 w-5 flex-shrink-0\"\n >\n <ListCollapseIcon className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n\n <DropdownMenuContent\n onCloseAutoFocus={(e) => e.preventDefault()}\n className=\"max-h-[400px] max-w-[240px] overflow-y-auto\"\n >\n <div className=\"flex items-center gap-1 px-2\">\n <SearchIcon className=\"text-muted-foreground\" size={14} />\n <Input\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={(e) => e.stopPropagation()}\n onKeyUp={(e) => e.stopPropagation()}\n className=\"border-none text-xs shadow-none focus-visible:ring-0\"\n placeholder=\"Search...\"\n />\n </div>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-muted-foreground text-xs font-normal\">\n Closed\n </DropdownMenuLabel>\n {renderTabGroup(filteredClosedTabs, 'No closed tabs')}\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-muted-foreground text-xs font-normal\">\n Opened\n </DropdownMenuLabel>\n {renderTabGroup(filteredOpenedTabs, 'No opened tabs')}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={handleNewQuery}\n className=\"h-5 w-5 flex-shrink-0\"\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n </TabsList>\n\n <DeleteSqlQueryModal\n isOpen={queryToDelete !== null}\n onClose={() => setQueryToDelete(null)}\n onConfirm={handleConfirmDeleteQuery}\n />\n <RenameSqlQueryModal\n isOpen={queryToRename !== null}\n onClose={() => setQueryToRename(null)}\n initialName={queryToRename?.name ?? ''}\n onRename={handleFinishRename}\n />\n </>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"QueryEditorPanelTabsList.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Button,\n cn,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n EditableText,\n Input,\n TabsList,\n TabsTrigger,\n} from '@sqlrooms/ui';\nimport {ListCollapseIcon, PlusIcon, XIcon, SearchIcon} from 'lucide-react';\nimport React, {useCallback, useMemo, useRef, useState} from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport DeleteSqlQueryModal from './DeleteSqlQueryModal';\nimport {QueryTabMenuItem} from './QueryTabMenuItem';\nimport RenameSqlQueryModal from './RenameSqlQueryModal';\n\nexport const QueryEditorPanelTabsList: React.FC<{className?: string}> = ({\n className,\n}) => {\n const queries = useStoreWithSqlEditor((s) => s.sqlEditor.config.queries);\n const closedTabIds = useStoreWithSqlEditor(\n (s) => s.sqlEditor.config.closedTabIds,\n );\n const openedTabs = queries.filter((q) => !closedTabIds.includes(q.id));\n const closedTabs = queries.filter((q) => closedTabIds.includes(q.id));\n\n const renameQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.renameQueryTab,\n );\n\n // Local state for modals and editing\n const [queryToDelete, setQueryToDelete] = useState<string | null>(null);\n const [editingQueryId, setEditingQueryId] = useState<string | null>(null);\n const [queryToRename, setQueryToRename] = useState<{\n id: string;\n name: string;\n } | null>(null);\n const [searchQuery, setSearchQuery] = useState('');\n\n // Ref for the scrollable container\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const closeQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.closeQueryTab);\n const openQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.openQueryTab);\n const createQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.createQueryTab,\n );\n const deleteQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.deleteQueryTab,\n );\n\n // Handle rename query\n const handleStartRename = useCallback(\n (queryId: string, currentName: string) => {\n setQueryToRename({id: queryId, name: currentName});\n },\n [],\n );\n\n const handleFinishRename = useCallback(\n (newName: string) => {\n if (queryToRename) {\n renameQueryTab(queryToRename.id, newName);\n }\n setQueryToRename(null);\n },\n [queryToRename, renameQueryTab],\n );\n // Handle rename query\n const handleRename = useCallback(\n (queryId: string, newName: string) => {\n if (newName.trim() !== '') {\n renameQueryTab(queryId, newName.trim());\n }\n setEditingQueryId(null);\n },\n [renameQueryTab],\n );\n\n // Handle double click to start editing\n const handleDoubleClick = useCallback((queryId: string) => {\n setEditingQueryId(queryId);\n }, []);\n\n // Handle delete query\n const handleDeleteQuery = useCallback(\n (queryId: string) => {\n // Find the query to check if it's empty\n const queryToDelete = queries.find((q) => q.id === queryId);\n\n // If query is empty (no content), delete immediately without confirmation\n if (queryToDelete && queryToDelete.query.trim() === '') {\n deleteQueryTab(queryId);\n } else {\n // Otherwise, show confirmation modal\n setQueryToDelete(queryId);\n }\n },\n [queries, deleteQueryTab],\n );\n\n // Handle new query creation\n const handleNewQuery = useCallback(() => {\n createQueryTab();\n // Auto-scroll to the right after a short delay to ensure the tab is rendered\n setTimeout(() => {\n if (scrollContainerRef.current) {\n scrollContainerRef.current.scrollTo({\n left: scrollContainerRef.current.scrollWidth,\n behavior: 'smooth',\n });\n }\n }, 0);\n }, [createQueryTab]);\n\n const handleConfirmDeleteQuery = useCallback(() => {\n if (queryToDelete) {\n deleteQueryTab(queryToDelete);\n setQueryToDelete(null);\n }\n }, [queryToDelete, deleteQueryTab]);\n\n const filteredClosedTabs = useMemo(() => {\n if (!searchQuery.trim()) return closedTabs;\n const lowerQuery = searchQuery.toLowerCase();\n return closedTabs.filter((tab) =>\n tab.name.toLowerCase().includes(lowerQuery),\n );\n }, [closedTabs, searchQuery]);\n\n const filteredOpenedTabs = useMemo(() => {\n if (!searchQuery.trim()) return openedTabs;\n const lowerQuery = searchQuery.toLowerCase();\n return openedTabs.filter((tab) =>\n tab.name.toLowerCase().includes(lowerQuery),\n );\n }, [openedTabs, searchQuery]);\n\n const renderTabGroup = useCallback(\n (tabs: typeof queries, emptyMessage: string) => {\n if (tabs.length === 0) {\n return (\n <DropdownMenuItem\n className=\"items-center justify-center text-xs\"\n disabled\n >\n {emptyMessage}\n </DropdownMenuItem>\n );\n }\n\n return tabs.map((tab) => (\n <QueryTabMenuItem\n key={tab.id}\n tab={tab}\n onRestore={() => openQueryTab(tab.id)}\n onRename={() => handleStartRename(tab.id, tab.name)}\n onDelete={() => handleDeleteQuery(tab.id)}\n />\n ));\n },\n [openQueryTab, handleStartRename, handleDeleteQuery],\n );\n\n return (\n <>\n <TabsList\n className={cn(\n 'flex min-w-0 justify-start gap-1 bg-transparent p-0 pt-1.5',\n className,\n )}\n >\n <div\n ref={scrollContainerRef}\n className=\"flex h-full min-w-0 items-center gap-1 overflow-x-auto overflow-y-hidden pr-1 [&::-webkit-scrollbar]:hidden\"\n >\n {openedTabs.map((q) => (\n <TabsTrigger\n key={q.id}\n value={q.id}\n className=\"data-[state=inactive]:hover:bg-primary/5 flex h-full min-w-[100px] max-w-[200px] flex-shrink-0 items-center justify-between gap-2 overflow-hidden rounded-b-none py-0 pl-4 pr-2 font-normal data-[state=active]:shadow-none\"\n >\n <div\n className=\"flex min-w-0 items-center\"\n onDoubleClick={() => handleDoubleClick(q.id)}\n >\n {editingQueryId !== q.id ? (\n <div className=\"truncate text-sm\">{q.name}</div>\n ) : (\n <EditableText\n value={q.name}\n onChange={(newName: string) => handleRename(q.id, newName)}\n className=\"h-6 min-w-0 flex-1 truncate text-sm shadow-none\"\n isEditing={editingQueryId === q.id}\n onEditingChange={(isEditing) => {\n if (!isEditing) {\n setEditingQueryId(null);\n }\n }}\n />\n )}\n </div>\n\n <Button\n size=\"xs\"\n variant=\"ghost\"\n className=\"hover:bg-primary/10 h-4 w-4 p-1\"\n onMouseDown={(e) => {\n e.stopPropagation();\n e.preventDefault();\n }}\n onClick={(e) => {\n e.stopPropagation();\n e.preventDefault();\n closeQueryTab(q.id);\n }}\n >\n <XIcon size={12} />\n </Button>\n </TabsTrigger>\n ))}\n </div>\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"ml-2 h-5 w-5 flex-shrink-0\"\n >\n <ListCollapseIcon className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n\n <DropdownMenuContent\n onCloseAutoFocus={(e) => e.preventDefault()}\n className=\"max-h-[400px] max-w-[240px] overflow-y-auto\"\n >\n <div className=\"flex items-center gap-1 px-2\">\n <SearchIcon className=\"text-muted-foreground\" size={14} />\n <Input\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={(e) => e.stopPropagation()}\n onKeyUp={(e) => e.stopPropagation()}\n className=\"border-none text-xs shadow-none focus-visible:ring-0\"\n placeholder=\"Search...\"\n />\n </div>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-muted-foreground text-xs font-normal\">\n Closed\n </DropdownMenuLabel>\n {renderTabGroup(filteredClosedTabs, 'No closed tabs')}\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-muted-foreground text-xs font-normal\">\n Opened\n </DropdownMenuLabel>\n {renderTabGroup(filteredOpenedTabs, 'No opened tabs')}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={handleNewQuery}\n className=\"h-5 w-5 flex-shrink-0\"\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n </TabsList>\n\n <DeleteSqlQueryModal\n isOpen={queryToDelete !== null}\n onClose={() => setQueryToDelete(null)}\n onConfirm={handleConfirmDeleteQuery}\n />\n <RenameSqlQueryModal\n isOpen={queryToRename !== null}\n onClose={() => setQueryToRename(null)}\n initialName={queryToRename?.name ?? ''}\n onRename={handleFinishRename}\n />\n </>\n );\n};\n"]}
|
|
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Button, DropdownMenuItem } from '@sqlrooms/ui';
|
|
3
3
|
import { PencilIcon, TrashIcon } from 'lucide-react';
|
|
4
4
|
export const QueryTabMenuItem = ({ tab, onRestore, onRename, onDelete, }) => {
|
|
5
|
-
return (_jsxs(DropdownMenuItem, { onClick: onRestore, className: "flex items-center justify-between truncate
|
|
5
|
+
return (_jsxs(DropdownMenuItem, { onClick: onRestore, className: "flex h-7 cursor-pointer items-center justify-between truncate", children: [_jsx("span", { className: "xs truncate pl-1", children: tab.name }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { size: "xs", variant: "ghost", className: "text-muted-foreground h-3 w-3", onClick: (e) => {
|
|
6
6
|
e.stopPropagation();
|
|
7
7
|
onRename();
|
|
8
|
-
}, children: _jsx(PencilIcon, { size: 12, className: "!size-3" }) }), _jsx(Button, { size: "xs", variant: "ghost", className: "
|
|
8
|
+
}, children: _jsx(PencilIcon, { size: 12, className: "!size-3" }) }), _jsx(Button, { size: "xs", variant: "ghost", className: "text-muted-foreground h-3 w-3", onClick: (e) => {
|
|
9
9
|
e.stopPropagation();
|
|
10
10
|
onDelete();
|
|
11
11
|
}, children: _jsx(TrashIcon, { size: 12, className: "!size-3" }) })] })] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryTabMenuItem.js","sourceRoot":"","sources":["../../src/components/QueryTabMenuItem.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,gBAAgB,EAAC,MAAM,cAAc,CAAC;AACtD,OAAO,EAAC,UAAU,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAanD,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,GAAG,EACH,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,CACL,MAAC,gBAAgB,IACf,OAAO,EAAE,SAAS,EAClB,SAAS,EAAC,+DAA+D,aAEzE,eAAM,SAAS,EAAC,kBAAkB,YAAE,GAAG,CAAC,IAAI,GAAQ,EACpD,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,OAAO,EACf,SAAS,EAAC,+BAA+B,EACzC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;4BACb,CAAC,CAAC,eAAe,EAAE,CAAC;4BACpB,QAAQ,EAAE,CAAC;wBACb,CAAC,YAED,KAAC,UAAU,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,SAAS,GAAG,GACrC,EACT,KAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,OAAO,EACf,SAAS,EAAC,+BAA+B,EACzC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;4BACb,CAAC,CAAC,eAAe,EAAE,CAAC;4BACpB,QAAQ,EAAE,CAAC;wBACb,CAAC,YAED,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,SAAS,GAAG,GACpC,IACL,IACW,CACpB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button, DropdownMenuItem} from '@sqlrooms/ui';\nimport {PencilIcon, TrashIcon} from 'lucide-react';\nimport React from 'react';\n\ninterface QueryTabMenuItemProps {\n tab: {\n id: string;\n name: string;\n };\n onRestore: () => void;\n onRename: () => void;\n onDelete: () => void;\n}\n\nexport const QueryTabMenuItem: React.FC<QueryTabMenuItemProps> = ({\n tab,\n onRestore,\n onRename,\n onDelete,\n}) => {\n return (\n <DropdownMenuItem\n onClick={onRestore}\n className=\"flex items-center justify-between truncate
|
|
1
|
+
{"version":3,"file":"QueryTabMenuItem.js","sourceRoot":"","sources":["../../src/components/QueryTabMenuItem.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,gBAAgB,EAAC,MAAM,cAAc,CAAC;AACtD,OAAO,EAAC,UAAU,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAanD,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,GAAG,EACH,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,CACL,MAAC,gBAAgB,IACf,OAAO,EAAE,SAAS,EAClB,SAAS,EAAC,+DAA+D,aAEzE,eAAM,SAAS,EAAC,kBAAkB,YAAE,GAAG,CAAC,IAAI,GAAQ,EACpD,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,OAAO,EACf,SAAS,EAAC,+BAA+B,EACzC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;4BACb,CAAC,CAAC,eAAe,EAAE,CAAC;4BACpB,QAAQ,EAAE,CAAC;wBACb,CAAC,YAED,KAAC,UAAU,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,SAAS,GAAG,GACrC,EACT,KAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,OAAO,EACf,SAAS,EAAC,+BAA+B,EACzC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;4BACb,CAAC,CAAC,eAAe,EAAE,CAAC;4BACpB,QAAQ,EAAE,CAAC;wBACb,CAAC,YAED,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,SAAS,GAAG,GACpC,IACL,IACW,CACpB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button, DropdownMenuItem} from '@sqlrooms/ui';\nimport {PencilIcon, TrashIcon} from 'lucide-react';\nimport React from 'react';\n\ninterface QueryTabMenuItemProps {\n tab: {\n id: string;\n name: string;\n };\n onRestore: () => void;\n onRename: () => void;\n onDelete: () => void;\n}\n\nexport const QueryTabMenuItem: React.FC<QueryTabMenuItemProps> = ({\n tab,\n onRestore,\n onRename,\n onDelete,\n}) => {\n return (\n <DropdownMenuItem\n onClick={onRestore}\n className=\"flex h-7 cursor-pointer items-center justify-between truncate\"\n >\n <span className=\"xs truncate pl-1\">{tab.name}</span>\n <div className=\"flex items-center gap-1\">\n <Button\n size=\"xs\"\n variant=\"ghost\"\n className=\"text-muted-foreground h-3 w-3\"\n onClick={(e) => {\n e.stopPropagation();\n onRename();\n }}\n >\n <PencilIcon size={12} className=\"!size-3\" />\n </Button>\n <Button\n size=\"xs\"\n variant=\"ghost\"\n className=\"text-muted-foreground h-3 w-3\"\n onClick={(e) => {\n e.stopPropagation();\n onDelete();\n }}\n >\n <TrashIcon size={12} className=\"!size-3\" />\n </Button>\n </div>\n </DropdownMenuItem>\n );\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/sql-editor",
|
|
3
|
-
"version": "0.26.0-rc.
|
|
4
|
-
"private": false,
|
|
3
|
+
"version": "0.26.0-rc.6",
|
|
5
4
|
"author": "Ilya Boyandin <ilya@boyandin.me>",
|
|
6
5
|
"license": "MIT",
|
|
7
6
|
"repository": {
|
|
@@ -29,16 +28,16 @@
|
|
|
29
28
|
"@hookform/resolvers": "^3.10.0",
|
|
30
29
|
"@monaco-editor/react": "^4.7.0",
|
|
31
30
|
"@paralleldrive/cuid2": "^2.2.2",
|
|
32
|
-
"@sqlrooms/data-table": "0.26.0-rc.
|
|
33
|
-
"@sqlrooms/duckdb": "0.26.0-rc.
|
|
34
|
-
"@sqlrooms/layout": "0.26.0-rc.
|
|
35
|
-
"@sqlrooms/monaco-editor": "0.26.0-rc.
|
|
36
|
-
"@sqlrooms/room-config": "0.26.0-rc.
|
|
37
|
-
"@sqlrooms/room-shell": "0.26.0-rc.
|
|
38
|
-
"@sqlrooms/schema-tree": "0.26.0-rc.
|
|
39
|
-
"@sqlrooms/sql-editor-config": "0.26.0-rc.
|
|
40
|
-
"@sqlrooms/ui": "0.26.0-rc.
|
|
41
|
-
"@sqlrooms/utils": "0.26.0-rc.
|
|
31
|
+
"@sqlrooms/data-table": "0.26.0-rc.6",
|
|
32
|
+
"@sqlrooms/duckdb": "0.26.0-rc.6",
|
|
33
|
+
"@sqlrooms/layout": "0.26.0-rc.6",
|
|
34
|
+
"@sqlrooms/monaco-editor": "0.26.0-rc.6",
|
|
35
|
+
"@sqlrooms/room-config": "0.26.0-rc.6",
|
|
36
|
+
"@sqlrooms/room-shell": "0.26.0-rc.6",
|
|
37
|
+
"@sqlrooms/schema-tree": "0.26.0-rc.6",
|
|
38
|
+
"@sqlrooms/sql-editor-config": "0.26.0-rc.6",
|
|
39
|
+
"@sqlrooms/ui": "0.26.0-rc.6",
|
|
40
|
+
"@sqlrooms/utils": "0.26.0-rc.6",
|
|
42
41
|
"@tanstack/react-table": "^8.21.3",
|
|
43
42
|
"d3-dsv": "^3.0.1",
|
|
44
43
|
"file-saver": "^2.0.5",
|
|
@@ -60,5 +59,5 @@
|
|
|
60
59
|
"@types/react": "^19.1.13",
|
|
61
60
|
"@types/react-dom": "^19.1.9"
|
|
62
61
|
},
|
|
63
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "f7b18280e7d81f653bb437cf81b1e23243809053"
|
|
64
63
|
}
|