@sqlrooms/room-shell 0.17.0
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/LICENSE.md +9 -0
- package/README.md +722 -0
- package/dist/RoomBuilder.d.ts +3 -0
- package/dist/RoomBuilder.d.ts.map +1 -0
- package/dist/RoomBuilder.js +28 -0
- package/dist/RoomBuilder.js.map +1 -0
- package/dist/RoomShell.d.ts +38 -0
- package/dist/RoomShell.d.ts.map +1 -0
- package/dist/RoomShell.js +47 -0
- package/dist/RoomShell.js.map +1 -0
- package/dist/RoomShellSidebarButtons.d.ts +19 -0
- package/dist/RoomShellSidebarButtons.d.ts.map +1 -0
- package/dist/RoomShellSidebarButtons.js +31 -0
- package/dist/RoomShellSidebarButtons.js.map +1 -0
- package/dist/RoomShellStore.d.ts +91 -0
- package/dist/RoomShellStore.d.ts.map +1 -0
- package/dist/RoomShellStore.js +461 -0
- package/dist/RoomShellStore.js.map +1 -0
- package/dist/data-sources/FileDataSourceCard.d.ts +9 -0
- package/dist/data-sources/FileDataSourceCard.d.ts.map +1 -0
- package/dist/data-sources/FileDataSourceCard.js +29 -0
- package/dist/data-sources/FileDataSourceCard.js.map +1 -0
- package/dist/data-sources/FileDataSourcesPanel.d.ts +6 -0
- package/dist/data-sources/FileDataSourcesPanel.d.ts.map +1 -0
- package/dist/data-sources/FileDataSourcesPanel.js +10 -0
- package/dist/data-sources/FileDataSourcesPanel.js.map +1 -0
- package/dist/data-sources/TableCard.d.ts +20 -0
- package/dist/data-sources/TableCard.d.ts.map +1 -0
- package/dist/data-sources/TableCard.js +12 -0
- package/dist/data-sources/TableCard.js.map +1 -0
- package/dist/data-sources/TablesListPanel.d.ts +7 -0
- package/dist/data-sources/TablesListPanel.d.ts.map +1 -0
- package/dist/data-sources/TablesListPanel.js +26 -0
- package/dist/data-sources/TablesListPanel.js.map +1 -0
- package/dist/data-sources/index.d.ts +5 -0
- package/dist/data-sources/index.d.ts.map +1 -0
- package/dist/data-sources/index.js +5 -0
- package/dist/data-sources/index.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/panels/RoomHeaderButton.d.ts +9 -0
- package/dist/panels/RoomHeaderButton.d.ts.map +1 -0
- package/dist/panels/RoomHeaderButton.js +8 -0
- package/dist/panels/RoomHeaderButton.js.map +1 -0
- package/dist/panels/RoomPanel.d.ts +8 -0
- package/dist/panels/RoomPanel.d.ts.map +1 -0
- package/dist/panels/RoomPanel.js +8 -0
- package/dist/panels/RoomPanel.js.map +1 -0
- package/dist/panels/RoomPanelHeader.d.ts +8 -0
- package/dist/panels/RoomPanelHeader.d.ts.map +1 -0
- package/dist/panels/RoomPanelHeader.js +17 -0
- package/dist/panels/RoomPanelHeader.js.map +1 -0
- package/dist/panels/index.d.ts +4 -0
- package/dist/panels/index.d.ts.map +1 -0
- package/dist/panels/index.js +4 -0
- package/dist/panels/index.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
import { createDefaultDuckDbConfig, createDuckDbSlice, } from '@sqlrooms/duckdb';
|
|
2
|
+
import { makeMosaicStack, removeMosaicNodeByKey } from '@sqlrooms/layout';
|
|
3
|
+
import { RoomStateContext, createRoomSlice, } from '@sqlrooms/core';
|
|
4
|
+
import { DEFAULT_MOSAIC_LAYOUT, DataSourceTypes, MAIN_VIEW, isMosaicLayoutParent, } from '@sqlrooms/room-config';
|
|
5
|
+
import { ErrorBoundary } from '@sqlrooms/ui';
|
|
6
|
+
import { castDraft, produce } from 'immer';
|
|
7
|
+
import { useContext } from 'react';
|
|
8
|
+
import { useStore } from 'zustand';
|
|
9
|
+
import { DataSourceStatus, } from './types';
|
|
10
|
+
import { convertToUniqueColumnOrTableName, convertToValidColumnOrTableName, downloadFile, } from '@sqlrooms/utils';
|
|
11
|
+
export const INITIAL_BASE_ROOM_CONFIG = {
|
|
12
|
+
title: '',
|
|
13
|
+
description: '',
|
|
14
|
+
layout: DEFAULT_MOSAIC_LAYOUT,
|
|
15
|
+
dataSources: [],
|
|
16
|
+
...createDefaultDuckDbConfig(),
|
|
17
|
+
};
|
|
18
|
+
const DOWNLOAD_DATA_SOURCES_TASK = 'download-data-sources';
|
|
19
|
+
const INIT_DB_TASK = 'init-db';
|
|
20
|
+
const INIT_ROOM_TASK = 'init-room';
|
|
21
|
+
export function createRoomShellSlice(props) {
|
|
22
|
+
const slice = (set, get, store) => {
|
|
23
|
+
const { connector, config: configProps, room: roomStateProps, ...restState } = props;
|
|
24
|
+
const initialConfig = {
|
|
25
|
+
...INITIAL_BASE_ROOM_CONFIG,
|
|
26
|
+
...configProps,
|
|
27
|
+
};
|
|
28
|
+
const initialRoomState = {
|
|
29
|
+
initialized: false,
|
|
30
|
+
CustomErrorBoundary: ErrorBoundary,
|
|
31
|
+
roomFiles: [],
|
|
32
|
+
panels: {},
|
|
33
|
+
roomFilesProgress: {},
|
|
34
|
+
isDataAvailable: false,
|
|
35
|
+
dataSourceStates: {},
|
|
36
|
+
...roomStateProps,
|
|
37
|
+
};
|
|
38
|
+
const roomSliceState = createRoomSlice({
|
|
39
|
+
config: initialConfig,
|
|
40
|
+
room: initialRoomState,
|
|
41
|
+
})(set, get, store);
|
|
42
|
+
const roomState = {
|
|
43
|
+
...roomSliceState,
|
|
44
|
+
...createDuckDbSlice({ connector })(set, get, store),
|
|
45
|
+
room: {
|
|
46
|
+
...initialRoomState,
|
|
47
|
+
...roomSliceState.room,
|
|
48
|
+
async initialize() {
|
|
49
|
+
roomSliceState.room.initialize();
|
|
50
|
+
const { setTaskProgress } = get().room;
|
|
51
|
+
setTaskProgress(INIT_DB_TASK, {
|
|
52
|
+
message: 'Initializing database…',
|
|
53
|
+
progress: undefined,
|
|
54
|
+
});
|
|
55
|
+
await get().db.initialize();
|
|
56
|
+
setTaskProgress(INIT_DB_TASK, undefined);
|
|
57
|
+
setTaskProgress(INIT_ROOM_TASK, {
|
|
58
|
+
message: 'Loading data sources…',
|
|
59
|
+
progress: undefined,
|
|
60
|
+
});
|
|
61
|
+
await updateReadyDataSources();
|
|
62
|
+
await maybeDownloadDataSources();
|
|
63
|
+
setTaskProgress(INIT_ROOM_TASK, undefined);
|
|
64
|
+
set((state) => produce(state, (draft) => {
|
|
65
|
+
draft.room.initialized = true;
|
|
66
|
+
}));
|
|
67
|
+
},
|
|
68
|
+
setRoomConfig: (config) => set((state) => produce(state, (draft) => {
|
|
69
|
+
draft.config = castDraft(config);
|
|
70
|
+
})),
|
|
71
|
+
setLastSavedConfig: (config) => set((state) => produce(state, (draft) => {
|
|
72
|
+
draft.room.lastSavedConfig = castDraft(config);
|
|
73
|
+
})),
|
|
74
|
+
hasUnsavedChanges: () => {
|
|
75
|
+
const { lastSavedConfig } = get().room;
|
|
76
|
+
const { config } = get();
|
|
77
|
+
return config !== lastSavedConfig;
|
|
78
|
+
},
|
|
79
|
+
setRoomTitle: (title) => set((state) => produce(state, (draft) => {
|
|
80
|
+
draft.config.title = title;
|
|
81
|
+
})),
|
|
82
|
+
setDescription: (description) => set((state) => produce(state, (draft) => {
|
|
83
|
+
draft.config.description = description;
|
|
84
|
+
})),
|
|
85
|
+
setLayout: (layout) => set((state) => produce(state, (draft) => {
|
|
86
|
+
draft.config.layout = layout;
|
|
87
|
+
})),
|
|
88
|
+
togglePanel: (panel, show) => {
|
|
89
|
+
const { config } = get();
|
|
90
|
+
if (config.layout?.nodes === panel) {
|
|
91
|
+
// don't hide the view if it's the only one
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const result = removeMosaicNodeByKey(config.layout?.nodes, panel);
|
|
95
|
+
const isShown = result.success;
|
|
96
|
+
if (isShown) {
|
|
97
|
+
if (show || panel === MAIN_VIEW /*&& areViewsReadyToRender()*/) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
set((state) => produce(state, (draft) => {
|
|
101
|
+
const layout = draft.config.layout;
|
|
102
|
+
layout.nodes = result.nextTree;
|
|
103
|
+
if (layout.pinned?.includes(panel)) {
|
|
104
|
+
layout.pinned = layout.pinned.filter((p) => p !== panel);
|
|
105
|
+
}
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
if (show === false) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
set((state) => produce(state, (draft) => {
|
|
113
|
+
const layout = draft.config.layout;
|
|
114
|
+
const root = layout.nodes;
|
|
115
|
+
const placement = draft.room.panels[panel]?.placement;
|
|
116
|
+
const side = placement === 'sidebar' ? 'first' : 'second';
|
|
117
|
+
const toReplace = isMosaicLayoutParent(root)
|
|
118
|
+
? root[side]
|
|
119
|
+
: undefined;
|
|
120
|
+
if (toReplace &&
|
|
121
|
+
isMosaicLayoutParent(root) &&
|
|
122
|
+
!isMosaicLayoutParent(toReplace) &&
|
|
123
|
+
toReplace !== MAIN_VIEW &&
|
|
124
|
+
!layout.fixed?.includes(toReplace) &&
|
|
125
|
+
!layout.pinned?.includes(toReplace)) {
|
|
126
|
+
// replace first un-pinned leaf
|
|
127
|
+
root[side] = panel;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
const panelNode = { node: panel, weight: 1 };
|
|
131
|
+
const restNode = {
|
|
132
|
+
node: config.layout?.nodes,
|
|
133
|
+
weight: 3,
|
|
134
|
+
};
|
|
135
|
+
// add to to the left
|
|
136
|
+
layout.nodes = makeMosaicStack(placement === 'sidebar-bottom' ? 'column' : 'row', side === 'first'
|
|
137
|
+
? [panelNode, restNode]
|
|
138
|
+
: [restNode, panelNode]);
|
|
139
|
+
}
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
/**
|
|
144
|
+
* Toggle the pin state of a panel.
|
|
145
|
+
* @param panel - The panel to toggle the pin state of.
|
|
146
|
+
*/
|
|
147
|
+
togglePanelPin: (panel) => {
|
|
148
|
+
set((state) => produce(state, (draft) => {
|
|
149
|
+
const layout = draft.config.layout;
|
|
150
|
+
const pinned = layout.pinned ?? [];
|
|
151
|
+
if (pinned.includes(panel)) {
|
|
152
|
+
layout.pinned = pinned.filter((p) => p !== panel);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
layout.pinned = [...pinned, panel];
|
|
156
|
+
}
|
|
157
|
+
}));
|
|
158
|
+
},
|
|
159
|
+
addDataSource: async (dataSource, status = DataSourceStatus.PENDING) => {
|
|
160
|
+
set((state) => produce(state, (draft) => {
|
|
161
|
+
const dataSources = draft.config.dataSources;
|
|
162
|
+
const tableName = dataSource.tableName;
|
|
163
|
+
const index = dataSources.findIndex((d) => d.tableName === tableName);
|
|
164
|
+
if (index >= 0) {
|
|
165
|
+
dataSources[index] = dataSource;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
dataSources.push(dataSource);
|
|
169
|
+
}
|
|
170
|
+
draft.room.dataSourceStates[tableName] = { status };
|
|
171
|
+
}));
|
|
172
|
+
await maybeDownloadDataSources();
|
|
173
|
+
},
|
|
174
|
+
async addOrUpdateSqlQueryDataSource(tableName, query, oldTableName) {
|
|
175
|
+
const { schema } = get().db;
|
|
176
|
+
const { db } = get();
|
|
177
|
+
const newTableName = tableName !== oldTableName
|
|
178
|
+
? convertToUniqueColumnOrTableName(tableName, await db.getTables(schema))
|
|
179
|
+
: tableName;
|
|
180
|
+
const { rowCount } = await db.createTableFromQuery(newTableName, query);
|
|
181
|
+
get().db.setTableRowCount(newTableName, rowCount);
|
|
182
|
+
set((state) => produce(state, (draft) => {
|
|
183
|
+
const newDataSource = {
|
|
184
|
+
type: DataSourceTypes.enum.sql,
|
|
185
|
+
sqlQuery: query,
|
|
186
|
+
tableName: newTableName,
|
|
187
|
+
};
|
|
188
|
+
if (oldTableName) {
|
|
189
|
+
draft.config.dataSources = draft.config.dataSources.map((dataSource) => dataSource.tableName === oldTableName
|
|
190
|
+
? newDataSource
|
|
191
|
+
: dataSource);
|
|
192
|
+
delete draft.room.dataSourceStates[oldTableName];
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
draft.config.dataSources.push(newDataSource);
|
|
196
|
+
}
|
|
197
|
+
draft.room.dataSourceStates[newTableName] = {
|
|
198
|
+
status: DataSourceStatus.READY,
|
|
199
|
+
};
|
|
200
|
+
}));
|
|
201
|
+
await get().db.refreshTableSchemas();
|
|
202
|
+
},
|
|
203
|
+
removeSqlQueryDataSource: async (tableName) => {
|
|
204
|
+
const { db } = get();
|
|
205
|
+
await db.dropTable(tableName);
|
|
206
|
+
set((state) => produce(state, (draft) => {
|
|
207
|
+
draft.config.dataSources = draft.config.dataSources.filter((d) => d.tableName !== tableName);
|
|
208
|
+
delete draft.room.dataSourceStates[tableName];
|
|
209
|
+
}));
|
|
210
|
+
await get().db.refreshTableSchemas();
|
|
211
|
+
},
|
|
212
|
+
setRoomFiles: (roomFiles) => set((state) => produce(state, (draft) => {
|
|
213
|
+
draft.room.roomFiles = roomFiles;
|
|
214
|
+
})),
|
|
215
|
+
async addRoomFile(file, desiredTableName, loadOptions) {
|
|
216
|
+
const { db } = get();
|
|
217
|
+
const pathname = file instanceof File ? file.name : file;
|
|
218
|
+
const tableName = desiredTableName ?? convertToValidColumnOrTableName(pathname);
|
|
219
|
+
await db.connector.loadFile(file, tableName, loadOptions);
|
|
220
|
+
// This must come before addDataSource, as addDataSource can trigger
|
|
221
|
+
// download which also adds the file
|
|
222
|
+
set((state) => produce(state, (draft) => {
|
|
223
|
+
draft.room.roomFiles.push({
|
|
224
|
+
pathname,
|
|
225
|
+
duckdbFileName: pathname,
|
|
226
|
+
size: file instanceof File ? file.size : undefined,
|
|
227
|
+
file: file instanceof File ? file : undefined,
|
|
228
|
+
});
|
|
229
|
+
}));
|
|
230
|
+
await get().room.addDataSource({
|
|
231
|
+
type: DataSourceTypes.enum.file,
|
|
232
|
+
fileName: pathname,
|
|
233
|
+
tableName,
|
|
234
|
+
},
|
|
235
|
+
// duckdbFileName ? DataSourceStatus.READY : DataSourceStatus.PENDING,
|
|
236
|
+
DataSourceStatus.READY);
|
|
237
|
+
await get().db.refreshTableSchemas();
|
|
238
|
+
set((state) => produce(state, (draft) => {
|
|
239
|
+
if (Object.values(get().room.dataSourceStates).every((ds) => ds.status === DataSourceStatus.READY)) {
|
|
240
|
+
draft.room.isDataAvailable = true;
|
|
241
|
+
}
|
|
242
|
+
}));
|
|
243
|
+
return get().db.findTableByName(tableName);
|
|
244
|
+
},
|
|
245
|
+
removeRoomFile(pathname) {
|
|
246
|
+
set((state) => produce(state, (draft) => {
|
|
247
|
+
draft.room.roomFiles = draft.room.roomFiles.filter((f) => f.pathname !== pathname);
|
|
248
|
+
draft.config.dataSources = draft.config.dataSources.filter((d) => d.type !== DataSourceTypes.Enum.file ||
|
|
249
|
+
d.fileName !== pathname);
|
|
250
|
+
}));
|
|
251
|
+
},
|
|
252
|
+
setRoomFileProgress(pathname, fileState) {
|
|
253
|
+
set((state) => produce(state, (draft) => {
|
|
254
|
+
draft.room.roomFilesProgress[pathname] = fileState;
|
|
255
|
+
// Update the file size in the room config from the progress info
|
|
256
|
+
const fileInfo = draft.room.roomFiles.find((f) => f.pathname === pathname);
|
|
257
|
+
if (fileInfo && fileInfo.size === undefined) {
|
|
258
|
+
if (fileState.status !== 'error' && fileState.progress) {
|
|
259
|
+
fileInfo.size = fileState.progress.total;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}));
|
|
263
|
+
},
|
|
264
|
+
areDatasetsReady: () => {
|
|
265
|
+
const { dataSourceStates } = get().room;
|
|
266
|
+
const { config } = get();
|
|
267
|
+
const dataSources = config.dataSources;
|
|
268
|
+
return dataSources.every((ds) => dataSourceStates[ds.tableName]?.status === DataSourceStatus.READY);
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
...restState,
|
|
272
|
+
};
|
|
273
|
+
// If the tables have changed, update the data sources
|
|
274
|
+
store.subscribe((state, prevState) => {
|
|
275
|
+
if (state.db.tables !== prevState.db.tables) {
|
|
276
|
+
updateReadyDataSources();
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
async function updateReadyDataSources() {
|
|
280
|
+
const { tables } = get().db;
|
|
281
|
+
const { dataSourceStates } = get().room;
|
|
282
|
+
const { config } = get();
|
|
283
|
+
const { dataSources } = config;
|
|
284
|
+
set((state) => produce(state, (draft) => {
|
|
285
|
+
for (const ds of dataSources) {
|
|
286
|
+
const tableName = ds.tableName;
|
|
287
|
+
const table = tables.find((t) => t.tableName === tableName);
|
|
288
|
+
if (table) {
|
|
289
|
+
draft.room.dataSourceStates[tableName] = {
|
|
290
|
+
status: DataSourceStatus.READY,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
// Prev status could be ERROR or PENDING, don't change it then
|
|
295
|
+
if (!dataSourceStates[tableName]?.status) {
|
|
296
|
+
draft.room.dataSourceStates[tableName] = {
|
|
297
|
+
status: DataSourceStatus.PENDING,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
async function maybeDownloadDataSources() {
|
|
305
|
+
const { roomFilesProgress, dataSourceStates } = get().room;
|
|
306
|
+
const { dataSources } = get().config;
|
|
307
|
+
const pendingDataSources = dataSources.filter((ds) => !dataSourceStates[ds.tableName] ||
|
|
308
|
+
dataSourceStates[ds.tableName]?.status === DataSourceStatus.PENDING);
|
|
309
|
+
const filesToDownload = pendingDataSources.filter((ds) => {
|
|
310
|
+
switch (ds.type) {
|
|
311
|
+
case DataSourceTypes.Enum.file:
|
|
312
|
+
return !roomFilesProgress[ds.fileName];
|
|
313
|
+
case DataSourceTypes.Enum.url:
|
|
314
|
+
return !roomFilesProgress[ds.url];
|
|
315
|
+
default:
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
if (filesToDownload.length > 0) {
|
|
320
|
+
await downloadRoomFiles(filesToDownload);
|
|
321
|
+
}
|
|
322
|
+
const queriesToRun = pendingDataSources.filter((ds) => ds.type === DataSourceTypes.Enum.sql);
|
|
323
|
+
if (queriesToRun.length > 0) {
|
|
324
|
+
await runDataSourceQueries(queriesToRun);
|
|
325
|
+
}
|
|
326
|
+
if (get().config.dataSources.length > 0) {
|
|
327
|
+
set((state) => produce(state, (draft) => {
|
|
328
|
+
draft.room.isDataAvailable = true;
|
|
329
|
+
}));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async function downloadRoomFiles(filesToDownload) {
|
|
333
|
+
if (!filesToDownload.length)
|
|
334
|
+
return;
|
|
335
|
+
const { setTableRowCount } = get().db;
|
|
336
|
+
const { captureException, setTaskProgress, setRoomFileProgress } = get().room;
|
|
337
|
+
filesToDownload.forEach((ds) => {
|
|
338
|
+
const fileName = ds.type === DataSourceTypes.Enum.file ? ds.fileName : ds.url;
|
|
339
|
+
set((state) => produce(state, (draft) => {
|
|
340
|
+
const info = {
|
|
341
|
+
duckdbFileName: fileName,
|
|
342
|
+
pathname: fileName,
|
|
343
|
+
file: undefined,
|
|
344
|
+
size: undefined,
|
|
345
|
+
};
|
|
346
|
+
const index = draft.room.roomFiles.findIndex((f) => f.pathname === fileName);
|
|
347
|
+
if (index >= 0) {
|
|
348
|
+
draft.room.roomFiles[index] = info;
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
draft.room.roomFiles.push(info);
|
|
352
|
+
}
|
|
353
|
+
}));
|
|
354
|
+
setRoomFileProgress(fileName, { status: 'download' });
|
|
355
|
+
});
|
|
356
|
+
if (filesToDownload.length > 0) {
|
|
357
|
+
updateTotalFileDownloadProgress();
|
|
358
|
+
}
|
|
359
|
+
const loadedFiles = await Promise.all(filesToDownload.map(async (ds) => {
|
|
360
|
+
const fileName = ds.type === DataSourceTypes.Enum.file ? ds.fileName : ds.url;
|
|
361
|
+
try {
|
|
362
|
+
if (ds.type === DataSourceTypes.Enum.file) {
|
|
363
|
+
throw new Error('File data source is not supported');
|
|
364
|
+
}
|
|
365
|
+
const url = ds.url;
|
|
366
|
+
setRoomFileProgress(fileName, { status: 'download' });
|
|
367
|
+
const downloadedFile = await downloadFile(url, {
|
|
368
|
+
...(ds.type === DataSourceTypes.Enum.url && {
|
|
369
|
+
method: ds.httpMethod,
|
|
370
|
+
headers: ds.headers,
|
|
371
|
+
}),
|
|
372
|
+
onProgress: (progress) => {
|
|
373
|
+
setRoomFileProgress(fileName, {
|
|
374
|
+
status: 'download',
|
|
375
|
+
progress,
|
|
376
|
+
});
|
|
377
|
+
updateTotalFileDownloadProgress();
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
setRoomFileProgress(fileName, { status: 'done' });
|
|
381
|
+
updateTotalFileDownloadProgress();
|
|
382
|
+
const { db } = get();
|
|
383
|
+
await db.connector.loadFile(new File([downloadedFile], fileName), ds.tableName, ds.loadOptions);
|
|
384
|
+
setTableRowCount(ds.tableName, await db.getTableRowCount(ds.tableName));
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
captureException(err);
|
|
388
|
+
console.error(err);
|
|
389
|
+
setRoomFileProgress(fileName, {
|
|
390
|
+
status: 'error',
|
|
391
|
+
message: 'Download failed',
|
|
392
|
+
});
|
|
393
|
+
// TODO: Make sure the errors are shown
|
|
394
|
+
}
|
|
395
|
+
finally {
|
|
396
|
+
setTaskProgress(DOWNLOAD_DATA_SOURCES_TASK, undefined);
|
|
397
|
+
}
|
|
398
|
+
}));
|
|
399
|
+
if (loadedFiles.length) {
|
|
400
|
+
await get().db.refreshTableSchemas();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
async function runDataSourceQueries(queries) {
|
|
404
|
+
for (const ds of queries) {
|
|
405
|
+
try {
|
|
406
|
+
const { tableName, sqlQuery } = ds;
|
|
407
|
+
set((state) => produce(state, (draft) => {
|
|
408
|
+
draft.room.dataSourceStates[tableName] = {
|
|
409
|
+
status: DataSourceStatus.FETCHING,
|
|
410
|
+
};
|
|
411
|
+
}));
|
|
412
|
+
const { rowCount } = await get().db.createTableFromQuery(tableName, sqlQuery);
|
|
413
|
+
get().db.setTableRowCount(tableName, rowCount);
|
|
414
|
+
set((state) => produce(state, (draft) => {
|
|
415
|
+
draft.room.dataSourceStates[tableName] = {
|
|
416
|
+
status: DataSourceStatus.READY,
|
|
417
|
+
};
|
|
418
|
+
}));
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
set((state) => produce(state, (draft) => {
|
|
422
|
+
draft.room.dataSourceStates[ds.tableName] = {
|
|
423
|
+
status: DataSourceStatus.ERROR,
|
|
424
|
+
message: `${err}`,
|
|
425
|
+
};
|
|
426
|
+
}));
|
|
427
|
+
// TODO: Make sure the errors are shown
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
await get().db.refreshTableSchemas();
|
|
431
|
+
await updateReadyDataSources();
|
|
432
|
+
}
|
|
433
|
+
function updateTotalFileDownloadProgress() {
|
|
434
|
+
const { setTaskProgress, roomFilesProgress } = get().room;
|
|
435
|
+
let total = 0, loaded = 0;
|
|
436
|
+
for (const p of Object.values(roomFilesProgress)) {
|
|
437
|
+
if (p.status === 'download' || p.status === 'done') {
|
|
438
|
+
total += p.progress?.total || 0;
|
|
439
|
+
loaded += p.progress?.loaded || 0;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
setTaskProgress(DOWNLOAD_DATA_SOURCES_TASK, {
|
|
443
|
+
progress: total > 0 ? Math.round((loaded / total) * 100) : undefined,
|
|
444
|
+
message: 'Downloading data…',
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
return roomState;
|
|
448
|
+
};
|
|
449
|
+
return slice;
|
|
450
|
+
}
|
|
451
|
+
export function useBaseRoomShellStore(selector) {
|
|
452
|
+
const store = useContext(RoomStateContext);
|
|
453
|
+
if (!store) {
|
|
454
|
+
throw new Error('Missing RoomStateProvider in the tree');
|
|
455
|
+
}
|
|
456
|
+
return useStore(store, selector);
|
|
457
|
+
}
|
|
458
|
+
export function createSlice(sliceCreator) {
|
|
459
|
+
return (set, get, store) => sliceCreator(set, get, store);
|
|
460
|
+
}
|
|
461
|
+
//# sourceMappingURL=RoomShellStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoomShellStore.js","sourceRoot":"","sources":["../src/RoomShellStore.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DataTable,\n DuckDbConnector,\n DuckDbSliceConfig,\n DuckDbSliceState,\n LoadFileOptions,\n createDefaultDuckDbConfig,\n createDuckDbSlice,\n} from '@sqlrooms/duckdb';\nimport {makeMosaicStack, removeMosaicNodeByKey} from '@sqlrooms/layout';\nimport {\n RoomState,\n RoomStateActions,\n RoomStateContext,\n RoomStateProps,\n createRoomSlice,\n} from '@sqlrooms/core';\nimport {\n DEFAULT_MOSAIC_LAYOUT,\n DataSource,\n DataSourceTypes,\n FileDataSource,\n LayoutConfig,\n MAIN_VIEW,\n SqlQueryDataSource,\n UrlDataSource,\n isMosaicLayoutParent,\n} from '@sqlrooms/room-config';\nimport {ErrorBoundary} from '@sqlrooms/ui';\nimport {castDraft, produce} from 'immer';\nimport {ReactNode, useContext} from 'react';\nimport {StateCreator, StoreApi, useStore} from 'zustand';\nimport {BaseRoomConfig} from '@sqlrooms/room-config/src/BaseRoomConfig';\nimport {\n DataSourceState,\n DataSourceStatus,\n RoomFileInfo,\n RoomFileState,\n} from './types';\nimport {\n convertToUniqueColumnOrTableName,\n convertToValidColumnOrTableName,\n downloadFile,\n ProgressInfo,\n} from '@sqlrooms/utils';\n\nexport type RoomShellStore<PC extends BaseRoomConfig> = StoreApi<\n RoomShellSliceState<PC>\n>;\n\nexport type RoomPanelInfo = {\n title?: string;\n icon?: React.ComponentType<{className?: string}>;\n component: React.ComponentType;\n placement: 'sidebar' | 'sidebar-bottom' | 'main' | 'top-bar';\n};\n\nexport const INITIAL_BASE_ROOM_CONFIG: BaseRoomConfig & DuckDbSliceConfig = {\n title: '',\n description: '',\n layout: DEFAULT_MOSAIC_LAYOUT,\n dataSources: [],\n ...createDefaultDuckDbConfig(),\n};\n\nexport type RoomShellSliceStateProps<PC extends BaseRoomConfig> =\n RoomStateProps<PC> & {\n initialized: boolean;\n roomFiles: RoomFileInfo[];\n roomFilesProgress: {[pathname: string]: RoomFileState};\n isDataAvailable: boolean; // Whether the data has been loaded (on initialization)\n dataSourceStates: {[tableName: string]: DataSourceState}; // TODO\n\n panels: Record<string, RoomPanelInfo>;\n CustomErrorBoundary: React.ComponentType<{\n onRetry?: () => void;\n children?: ReactNode;\n }>;\n };\n\nexport type RoomShellSliceStateActions<PC extends BaseRoomConfig> =\n RoomStateActions<PC> & {\n /**\n * Initialize the room state.\n * @returns A promise that resolves when the room state has been initialized.\n */\n initialize: () => Promise<void>;\n\n /**\n * Set the layout of the room.\n * @param layout - The layout to set.\n */\n setLayout(layout: LayoutConfig): void;\n /**\n * Toggle a panel.\n * @param panel - The panel to toggle.\n * @param show - Whether to show the panel.\n */\n togglePanel: (panel: string, show?: boolean) => void;\n /**\n * Toggle the pin state of a panel.\n * @param panel - The panel to toggle the pin state of.\n */\n togglePanelPin: (panel: string) => void;\n\n setRoomTitle(title: string): void;\n setDescription(description: string): void;\n\n /**\n * Add or update a SQL query data source.\n * @param tableName - The name of the table to create or update.\n * @param query - The SQL query to execute.\n * @param oldTableName - The name of the table to replace (optional).\n */\n addOrUpdateSqlQueryDataSource(\n tableName: string,\n query: string,\n oldTableName?: string,\n ): Promise<void>;\n removeSqlQueryDataSource(tableName: string): Promise<void>;\n areDatasetsReady(): boolean;\n\n addRoomFile(\n file: File | string,\n tableName?: string,\n loadFileOptions?: LoadFileOptions,\n ): Promise<DataTable | undefined>;\n removeRoomFile(pathname: string): void;\n setRoomFiles(info: RoomFileInfo[]): void;\n setRoomFileProgress(pathname: string, fileState: RoomFileState): void;\n addDataSource: (\n dataSource: DataSource,\n status?: DataSourceStatus,\n ) => Promise<void>;\n };\n\nexport type RoomShellSliceState<PC extends BaseRoomConfig> = RoomState<PC> & {\n config: PC;\n room: RoomShellSliceStateProps<PC> & RoomShellSliceStateActions<PC>;\n} & DuckDbSliceState;\n\n/**\n * \tThis type takes a union type U (for example, A | B) and transforms it into an intersection type (A & B). This is useful because if you pass in, say, two slices of type { a: number } and { b: string }, the union of the slice types would be { a: number } | { b: string }, but you really want an object that has both properties—i.e. { a: number } & { b: string }.\n */\ntype InitialState<PC extends BaseRoomConfig> = {\n connector?: DuckDbConnector;\n config: Partial<PC>;\n room: Partial<Omit<RoomShellSliceStateProps<PC>, 'config' | 'panels'>> & {\n panels?: RoomShellSliceStateProps<PC>['panels'];\n };\n};\n\nconst DOWNLOAD_DATA_SOURCES_TASK = 'download-data-sources';\nconst INIT_DB_TASK = 'init-db';\nconst INIT_ROOM_TASK = 'init-room';\n\nexport function createRoomShellSlice<PC extends BaseRoomConfig>(\n props: InitialState<PC>,\n): StateCreator<RoomShellSliceState<PC>> {\n const slice: StateCreator<RoomShellSliceState<PC>> = (set, get, store) => {\n const {\n connector,\n config: configProps,\n room: roomStateProps,\n ...restState\n } = props;\n const initialConfig: PC = {\n ...INITIAL_BASE_ROOM_CONFIG,\n ...configProps,\n } as PC;\n const initialRoomState = {\n initialized: false,\n CustomErrorBoundary: ErrorBoundary,\n roomFiles: [],\n panels: {},\n roomFilesProgress: {},\n isDataAvailable: false,\n dataSourceStates: {},\n ...roomStateProps,\n };\n const roomSliceState = createRoomSlice({\n config: initialConfig,\n room: initialRoomState,\n })(set, get, store);\n\n const roomState: RoomShellSliceState<PC> = {\n ...roomSliceState,\n ...createDuckDbSlice({connector})(set, get, store),\n room: {\n ...initialRoomState,\n ...roomSliceState.room,\n async initialize() {\n roomSliceState.room.initialize();\n\n const {setTaskProgress} = get().room;\n setTaskProgress(INIT_DB_TASK, {\n message: 'Initializing database…',\n progress: undefined,\n });\n await get().db.initialize();\n setTaskProgress(INIT_DB_TASK, undefined);\n\n setTaskProgress(INIT_ROOM_TASK, {\n message: 'Loading data sources…',\n progress: undefined,\n });\n await updateReadyDataSources();\n await maybeDownloadDataSources();\n setTaskProgress(INIT_ROOM_TASK, undefined);\n\n set((state) =>\n produce(state, (draft) => {\n draft.room.initialized = true;\n }),\n );\n },\n\n setRoomConfig: (config) =>\n set((state) =>\n produce(state, (draft) => {\n draft.config = castDraft(config);\n }),\n ),\n setLastSavedConfig: (config) =>\n set((state) =>\n produce(state, (draft) => {\n draft.room.lastSavedConfig = castDraft(config);\n }),\n ),\n hasUnsavedChanges: () => {\n const {lastSavedConfig} = get().room;\n const {config} = get();\n return config !== lastSavedConfig;\n },\n\n setRoomTitle: (title) =>\n set((state) =>\n produce(state, (draft) => {\n draft.config.title = title;\n }),\n ),\n\n setDescription: (description) =>\n set((state) =>\n produce(state, (draft) => {\n draft.config.description = description;\n }),\n ),\n setLayout: (layout) =>\n set((state) =>\n produce(state, (draft) => {\n draft.config.layout = layout;\n }),\n ),\n\n togglePanel: (panel, show) => {\n const {config} = get();\n if (config.layout?.nodes === panel) {\n // don't hide the view if it's the only one\n return;\n }\n const result = removeMosaicNodeByKey(config.layout?.nodes, panel);\n const isShown = result.success;\n if (isShown) {\n if (show || panel === MAIN_VIEW /*&& areViewsReadyToRender()*/) {\n return;\n }\n set((state) =>\n produce(state, (draft) => {\n const layout = draft.config.layout;\n layout.nodes = result.nextTree;\n if (layout.pinned?.includes(panel)) {\n layout.pinned = layout.pinned.filter((p) => p !== panel);\n }\n }),\n );\n } else {\n if (show === false) {\n return;\n }\n set((state) =>\n produce(state, (draft) => {\n const layout = draft.config.layout;\n const root = layout.nodes;\n const placement = draft.room.panels[panel]?.placement;\n const side = placement === 'sidebar' ? 'first' : 'second';\n const toReplace = isMosaicLayoutParent(root)\n ? root[side]\n : undefined;\n if (\n toReplace &&\n isMosaicLayoutParent(root) &&\n !isMosaicLayoutParent(toReplace) &&\n toReplace !== MAIN_VIEW &&\n !layout.fixed?.includes(toReplace) &&\n !layout.pinned?.includes(toReplace)\n ) {\n // replace first un-pinned leaf\n root[side] = panel;\n } else {\n const panelNode = {node: panel, weight: 1};\n const restNode = {\n node: config.layout?.nodes,\n weight: 3,\n };\n // add to to the left\n layout.nodes = makeMosaicStack(\n placement === 'sidebar-bottom' ? 'column' : 'row',\n side === 'first'\n ? [panelNode, restNode]\n : [restNode, panelNode],\n );\n }\n }),\n );\n }\n },\n\n /**\n * Toggle the pin state of a panel.\n * @param panel - The panel to toggle the pin state of.\n */\n togglePanelPin: (panel: string) => {\n set((state) =>\n produce(state, (draft) => {\n const layout = draft.config.layout;\n const pinned = layout.pinned ?? [];\n if (pinned.includes(panel)) {\n layout.pinned = pinned.filter((p) => p !== panel);\n } else {\n layout.pinned = [...pinned, panel];\n }\n }),\n );\n },\n\n addDataSource: async (\n dataSource,\n status = DataSourceStatus.PENDING,\n ) => {\n set((state) =>\n produce(state, (draft) => {\n const dataSources = draft.config.dataSources;\n const tableName = dataSource.tableName;\n const index = dataSources.findIndex(\n (d) => d.tableName === tableName,\n );\n if (index >= 0) {\n dataSources[index] = dataSource;\n } else {\n dataSources.push(dataSource);\n }\n draft.room.dataSourceStates[tableName] = {status};\n }),\n );\n await maybeDownloadDataSources();\n },\n\n async addOrUpdateSqlQueryDataSource(tableName, query, oldTableName) {\n const {schema} = get().db;\n const {db} = get();\n const newTableName =\n tableName !== oldTableName\n ? convertToUniqueColumnOrTableName(\n tableName,\n await db.getTables(schema),\n )\n : tableName;\n const {rowCount} = await db.createTableFromQuery(newTableName, query);\n get().db.setTableRowCount(newTableName, rowCount);\n set((state) =>\n produce(state, (draft) => {\n const newDataSource = {\n type: DataSourceTypes.enum.sql,\n sqlQuery: query,\n tableName: newTableName,\n };\n if (oldTableName) {\n draft.config.dataSources = draft.config.dataSources.map(\n (dataSource) =>\n dataSource.tableName === oldTableName\n ? newDataSource\n : dataSource,\n );\n delete draft.room.dataSourceStates[oldTableName];\n } else {\n draft.config.dataSources.push(newDataSource);\n }\n draft.room.dataSourceStates[newTableName] = {\n status: DataSourceStatus.READY,\n };\n }),\n );\n await get().db.refreshTableSchemas();\n },\n\n removeSqlQueryDataSource: async (tableName) => {\n const {db} = get();\n await db.dropTable(tableName);\n set((state) =>\n produce(state, (draft) => {\n draft.config.dataSources = draft.config.dataSources.filter(\n (d) => d.tableName !== tableName,\n );\n delete draft.room.dataSourceStates[tableName];\n }),\n );\n await get().db.refreshTableSchemas();\n },\n\n setRoomFiles: (roomFiles) =>\n set((state) =>\n produce(state, (draft) => {\n draft.room.roomFiles = roomFiles;\n }),\n ),\n\n async addRoomFile(file, desiredTableName, loadOptions) {\n const {db} = get();\n\n const pathname = file instanceof File ? file.name : file;\n const tableName =\n desiredTableName ?? convertToValidColumnOrTableName(pathname);\n\n await db.connector.loadFile(file, tableName, loadOptions);\n\n // This must come before addDataSource, as addDataSource can trigger\n // download which also adds the file\n set((state) =>\n produce(state, (draft) => {\n draft.room.roomFiles.push({\n pathname,\n duckdbFileName: pathname,\n size: file instanceof File ? file.size : undefined,\n file: file instanceof File ? file : undefined,\n });\n }),\n );\n await get().room.addDataSource(\n {\n type: DataSourceTypes.enum.file,\n fileName: pathname,\n tableName,\n },\n // duckdbFileName ? DataSourceStatus.READY : DataSourceStatus.PENDING,\n DataSourceStatus.READY,\n );\n await get().db.refreshTableSchemas();\n set((state) =>\n produce(state, (draft) => {\n if (\n Object.values(get().room.dataSourceStates).every(\n (ds) => ds.status === DataSourceStatus.READY,\n )\n ) {\n draft.room.isDataAvailable = true;\n }\n }),\n );\n return get().db.findTableByName(tableName);\n },\n\n removeRoomFile(pathname) {\n set((state) =>\n produce(state, (draft) => {\n draft.room.roomFiles = draft.room.roomFiles.filter(\n (f) => f.pathname !== pathname,\n );\n draft.config.dataSources = draft.config.dataSources.filter(\n (d) =>\n d.type !== DataSourceTypes.Enum.file ||\n d.fileName !== pathname,\n );\n }),\n );\n },\n\n setRoomFileProgress(pathname, fileState) {\n set((state) =>\n produce(state, (draft) => {\n draft.room.roomFilesProgress[pathname] = fileState;\n // Update the file size in the room config from the progress info\n const fileInfo = draft.room.roomFiles.find(\n (f) => f.pathname === pathname,\n );\n if (fileInfo && fileInfo.size === undefined) {\n if (fileState.status !== 'error' && fileState.progress) {\n fileInfo.size = fileState.progress.total;\n }\n }\n }),\n );\n },\n\n areDatasetsReady: () => {\n const {dataSourceStates} = get().room;\n const {config} = get();\n const dataSources = config.dataSources;\n return dataSources.every(\n (ds) =>\n dataSourceStates[ds.tableName]?.status === DataSourceStatus.READY,\n );\n },\n },\n\n ...restState,\n };\n\n // If the tables have changed, update the data sources\n store.subscribe((state, prevState) => {\n if (state.db.tables !== prevState.db.tables) {\n updateReadyDataSources();\n }\n });\n\n async function updateReadyDataSources() {\n const {tables} = get().db;\n const {dataSourceStates} = get().room;\n const {config} = get();\n const {dataSources} = config;\n set((state) =>\n produce(state, (draft) => {\n for (const ds of dataSources) {\n const tableName = ds.tableName;\n const table = tables.find((t) => t.tableName === tableName);\n if (table) {\n draft.room.dataSourceStates[tableName] = {\n status: DataSourceStatus.READY,\n };\n } else {\n // Prev status could be ERROR or PENDING, don't change it then\n if (!dataSourceStates[tableName]?.status) {\n draft.room.dataSourceStates[tableName] = {\n status: DataSourceStatus.PENDING,\n };\n }\n }\n }\n }),\n );\n }\n\n async function maybeDownloadDataSources() {\n const {roomFilesProgress, dataSourceStates} = get().room;\n const {dataSources} = get().config;\n const pendingDataSources = dataSources.filter(\n (ds) =>\n !dataSourceStates[ds.tableName] ||\n dataSourceStates[ds.tableName]?.status === DataSourceStatus.PENDING,\n );\n\n const filesToDownload = pendingDataSources.filter((ds) => {\n switch (ds.type) {\n case DataSourceTypes.Enum.file:\n return !roomFilesProgress[ds.fileName];\n case DataSourceTypes.Enum.url:\n return !roomFilesProgress[ds.url];\n default:\n return false;\n }\n }) as (FileDataSource | UrlDataSource)[];\n\n if (filesToDownload.length > 0) {\n await downloadRoomFiles(filesToDownload);\n }\n\n const queriesToRun = pendingDataSources.filter(\n (ds) => ds.type === DataSourceTypes.Enum.sql,\n );\n\n if (queriesToRun.length > 0) {\n await runDataSourceQueries(queriesToRun);\n }\n\n if (get().config.dataSources.length > 0) {\n set((state) =>\n produce(state, (draft) => {\n draft.room.isDataAvailable = true;\n }),\n );\n }\n }\n\n async function downloadRoomFiles(\n filesToDownload: (FileDataSource | UrlDataSource)[],\n ) {\n if (!filesToDownload.length) return;\n const {setTableRowCount} = get().db;\n const {captureException, setTaskProgress, setRoomFileProgress} =\n get().room;\n filesToDownload.forEach((ds) => {\n const fileName =\n ds.type === DataSourceTypes.Enum.file ? ds.fileName : ds.url;\n set((state) =>\n produce(state, (draft) => {\n const info = {\n duckdbFileName: fileName,\n pathname: fileName,\n file: undefined,\n size: undefined,\n };\n const index = draft.room.roomFiles.findIndex(\n (f) => f.pathname === fileName,\n );\n if (index >= 0) {\n draft.room.roomFiles[index] = info;\n } else {\n draft.room.roomFiles.push(info);\n }\n }),\n );\n setRoomFileProgress(fileName, {status: 'download'});\n });\n if (filesToDownload.length > 0) {\n updateTotalFileDownloadProgress();\n }\n\n const loadedFiles = await Promise.all(\n filesToDownload.map(async (ds) => {\n const fileName =\n ds.type === DataSourceTypes.Enum.file ? ds.fileName : ds.url;\n try {\n if (ds.type === DataSourceTypes.Enum.file) {\n throw new Error('File data source is not supported');\n }\n const url = ds.url;\n setRoomFileProgress(fileName, {status: 'download'});\n const downloadedFile = await downloadFile(url, {\n ...(ds.type === DataSourceTypes.Enum.url && {\n method: ds.httpMethod,\n headers: ds.headers,\n }),\n onProgress: (progress: ProgressInfo) => {\n setRoomFileProgress(fileName, {\n status: 'download',\n progress,\n });\n updateTotalFileDownloadProgress();\n },\n });\n setRoomFileProgress(fileName, {status: 'done'});\n updateTotalFileDownloadProgress();\n const {db} = get();\n await db.connector.loadFile(\n new File([downloadedFile], fileName),\n ds.tableName,\n ds.loadOptions,\n );\n setTableRowCount(\n ds.tableName,\n await db.getTableRowCount(ds.tableName),\n );\n } catch (err) {\n captureException(err);\n console.error(err);\n setRoomFileProgress(fileName, {\n status: 'error',\n message: 'Download failed',\n });\n // TODO: Make sure the errors are shown\n } finally {\n setTaskProgress(DOWNLOAD_DATA_SOURCES_TASK, undefined);\n }\n }),\n );\n if (loadedFiles.length) {\n await get().db.refreshTableSchemas();\n }\n }\n\n async function runDataSourceQueries(queries: SqlQueryDataSource[]) {\n for (const ds of queries) {\n try {\n const {tableName, sqlQuery} = ds;\n set((state) =>\n produce(state, (draft) => {\n draft.room.dataSourceStates[tableName] = {\n status: DataSourceStatus.FETCHING,\n };\n }),\n );\n const {rowCount} = await get().db.createTableFromQuery(\n tableName,\n sqlQuery,\n );\n get().db.setTableRowCount(tableName, rowCount);\n set((state) =>\n produce(state, (draft) => {\n draft.room.dataSourceStates[tableName] = {\n status: DataSourceStatus.READY,\n };\n }),\n );\n } catch (err) {\n set((state) =>\n produce(state, (draft) => {\n draft.room.dataSourceStates[ds.tableName] = {\n status: DataSourceStatus.ERROR,\n message: `${err}`,\n };\n }),\n );\n // TODO: Make sure the errors are shown\n }\n }\n await get().db.refreshTableSchemas();\n await updateReadyDataSources();\n }\n\n function updateTotalFileDownloadProgress() {\n const {setTaskProgress, roomFilesProgress} = get().room;\n let total = 0,\n loaded = 0;\n for (const p of Object.values(roomFilesProgress)) {\n if (p.status === 'download' || p.status === 'done') {\n total += p.progress?.total || 0;\n loaded += p.progress?.loaded || 0;\n }\n }\n setTaskProgress(DOWNLOAD_DATA_SOURCES_TASK, {\n progress: total > 0 ? Math.round((loaded / total) * 100) : undefined,\n message: 'Downloading data…',\n });\n }\n\n return roomState;\n };\n\n return slice;\n}\n\nexport function useBaseRoomShellStore<\n PC extends BaseRoomConfig,\n PS extends RoomShellSliceState<PC>,\n T,\n>(selector: (state: RoomShellSliceState<PC>) => T): T {\n const store = useContext(RoomStateContext);\n if (!store) {\n throw new Error('Missing RoomStateProvider in the tree');\n }\n return useStore(store as unknown as StoreApi<PS>, selector);\n}\n\nexport function createSlice<PC extends BaseRoomConfig, S>(\n sliceCreator: (\n ...args: Parameters<StateCreator<S & RoomShellSliceState<PC>>>\n ) => S,\n): StateCreator<S> {\n return (set, get, store) =>\n sliceCreator(\n set,\n get as () => S & RoomShellSliceState<PC>,\n store as StoreApi<S & RoomShellSliceState<PC>>,\n );\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { RoomFileInfo, RoomFileState } from '../types';
|
|
3
|
+
declare const FileDataSourceCard: FC<{
|
|
4
|
+
isReadOnly?: boolean;
|
|
5
|
+
fileInfo: RoomFileInfo;
|
|
6
|
+
fileState?: RoomFileState;
|
|
7
|
+
}>;
|
|
8
|
+
export { FileDataSourceCard };
|
|
9
|
+
//# sourceMappingURL=FileDataSourceCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileDataSourceCard.d.ts","sourceRoot":"","sources":["../../src/data-sources/FileDataSourceCard.tsx"],"names":[],"mappings":"AAoBA,OAAO,EAAC,EAAE,EAAc,MAAM,OAAO,CAAC;AAEtC,OAAO,EAAC,YAAY,EAAE,aAAa,EAAC,MAAM,UAAU,CAAC;AACrD,QAAA,MAAM,kBAAkB,EAAE,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,CA2GA,CAAC;AAEF,OAAO,EAAC,kBAAkB,EAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Tooltip, TooltipContent, TooltipTrigger, } from '@sqlrooms/ui';
|
|
3
|
+
import { formatBytes, splitFilePath } from '@sqlrooms/utils';
|
|
4
|
+
import { CloudDownloadIcon, CloudIcon, CloudUploadIcon, EllipsisIcon, FileDownIcon, FileTextIcon, XIcon, } from 'lucide-react';
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
|
+
import { useBaseRoomShellStore } from '../RoomShellStore';
|
|
7
|
+
const FileDataSourceCard = (props) => {
|
|
8
|
+
const { isReadOnly, fileInfo, fileState } = props;
|
|
9
|
+
const { pathname, size } = fileInfo;
|
|
10
|
+
const { filename } = splitFilePath(pathname);
|
|
11
|
+
const removeRoomFile = useBaseRoomShellStore((state) => state.room.removeRoomFile);
|
|
12
|
+
const handleRemoveFromRoom = useCallback(() => {
|
|
13
|
+
removeRoomFile(fileInfo.pathname);
|
|
14
|
+
}, [fileInfo.pathname, removeRoomFile]);
|
|
15
|
+
return (_jsxs("div", { className: "flex flex-col gap-1 p-2", children: [_jsxs("div", { className: "flex cursor-pointer flex-row items-center gap-1", children: [_jsx("div", { className: "w-[15px] flex-none", children: _jsx(FileTextIcon, { className: "w-[15px]" }) }), _jsx("div", { className: "flex-1 overflow-hidden text-ellipsis whitespace-nowrap", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "break-words text-xs", children: filename }) }), _jsx(TooltipContent, { side: "bottom", children: _jsx("pre", { className: "w-[300px] text-wrap break-words text-xs", children: pathname }) })] }) }), _jsx("div", { className: "flex-none", children: !isReadOnly ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { size: "icon", variant: "ghost", className: "text-muted-foreground h-6 w-6", children: _jsx(EllipsisIcon, { className: "h-5 w-5" }) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsxs(DropdownMenuItem, { onClick: handleRemoveFromRoom, children: [_jsx(XIcon, { className: "mr-2 h-4 w-4" }), "Remove from room"] }), _jsxs(DropdownMenuItem, { disabled: true, children: [_jsx(FileDownIcon, { className: "mr-2 h-4 w-4" }), "Download file"] })] })] })) : null })] }), _jsxs("div", { className: "flex flex-row items-center gap-1", children: [fileState?.status === 'error' ? (_jsx("div", { className: "bg-destructive/15 text-destructive flex-1 rounded p-1 text-xs", children: fileState.message })) : fileState?.status === 'download' ||
|
|
16
|
+
fileState?.status === 'upload' ? (_jsx("div", { className: "bg-secondary h-1 w-full overflow-hidden rounded", children: _jsx("div", { className: "bg-primary h-full transition-all duration-300", style: {
|
|
17
|
+
width: `${(fileState.progress?.ratio ?? 0) * 100}%`,
|
|
18
|
+
} }) })) : null, _jsx("div", { className: "flex-none", children: size !== undefined ? (_jsx("span", { className: "text-muted-foreground min-w-[70px] text-right text-xs", children: formatBytes(size) })) : null }), _jsx("div", { className: "cursor-pointer", title: fileState?.status === 'done'
|
|
19
|
+
? 'File synced'
|
|
20
|
+
: fileState?.status === 'download'
|
|
21
|
+
? 'Downloading file…'
|
|
22
|
+
: fileState?.status === 'upload'
|
|
23
|
+
? 'Uploading file…'
|
|
24
|
+
: fileState?.status === 'error'
|
|
25
|
+
? `Failed to sync file: ${fileState.message}`
|
|
26
|
+
: 'File not synced', children: fileState?.status === 'done' ? (_jsx(CloudIcon, { className: "w-[15px] text-green-400" })) : fileState?.status === 'download' ? (_jsx(CloudDownloadIcon, { className: "w-[15px] text-orange-400" })) : fileState?.status === 'upload' ? (_jsx(CloudUploadIcon, { className: "w-[15px] text-orange-400" })) : fileState?.status === 'error' ? (_jsx(CloudIcon, { className: "text-destructive w-[15px]" })) : (_jsx(CloudIcon, { className: "w-[15px] text-orange-400" })) })] })] }));
|
|
27
|
+
};
|
|
28
|
+
export { FileDataSourceCard };
|
|
29
|
+
//# sourceMappingURL=FileDataSourceCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileDataSourceCard.js","sourceRoot":"","sources":["../../src/data-sources/FileDataSourceCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@sqlrooms/ui';\nimport {formatBytes, splitFilePath} from '@sqlrooms/utils';\nimport {\n CloudDownloadIcon,\n CloudIcon,\n CloudUploadIcon,\n EllipsisIcon,\n FileDownIcon,\n FileTextIcon,\n XIcon,\n} from 'lucide-react';\nimport {FC, useCallback} from 'react';\nimport {useBaseRoomShellStore} from '../RoomShellStore';\nimport {RoomFileInfo, RoomFileState} from '../types';\nconst FileDataSourceCard: FC<{\n isReadOnly?: boolean;\n fileInfo: RoomFileInfo;\n fileState?: RoomFileState;\n}> = (props) => {\n const {isReadOnly, fileInfo, fileState} = props;\n const {pathname, size} = fileInfo;\n const {filename} = splitFilePath(pathname);\n const removeRoomFile = useBaseRoomShellStore(\n (state) => state.room.removeRoomFile,\n );\n const handleRemoveFromRoom = useCallback(() => {\n removeRoomFile(fileInfo.pathname);\n }, [fileInfo.pathname, removeRoomFile]);\n\n return (\n <div className=\"flex flex-col gap-1 p-2\">\n <div className=\"flex cursor-pointer flex-row items-center gap-1\">\n <div className=\"w-[15px] flex-none\">\n <FileTextIcon className=\"w-[15px]\" />\n </div>\n <div className=\"flex-1 overflow-hidden text-ellipsis whitespace-nowrap\">\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"break-words text-xs\">{filename}</span>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <pre className=\"w-[300px] text-wrap break-words text-xs\">\n {pathname}\n </pre>\n </TooltipContent>\n </Tooltip>\n </div>\n <div className=\"flex-none\">\n {!isReadOnly ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"text-muted-foreground h-6 w-6\"\n >\n <EllipsisIcon className=\"h-5 w-5\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={handleRemoveFromRoom}>\n <XIcon className=\"mr-2 h-4 w-4\" />\n Remove from room\n </DropdownMenuItem>\n <DropdownMenuItem disabled>\n <FileDownIcon className=\"mr-2 h-4 w-4\" />\n Download file\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n </div>\n <div className=\"flex flex-row items-center gap-1\">\n {fileState?.status === 'error' ? (\n <div className=\"bg-destructive/15 text-destructive flex-1 rounded p-1 text-xs\">\n {fileState.message}\n </div>\n ) : fileState?.status === 'download' ||\n fileState?.status === 'upload' ? (\n <div className=\"bg-secondary h-1 w-full overflow-hidden rounded\">\n <div\n className=\"bg-primary h-full transition-all duration-300\"\n style={{\n width: `${(fileState.progress?.ratio ?? 0) * 100}%`,\n }}\n />\n </div>\n ) : null}\n <div className=\"flex-none\">\n {size !== undefined ? (\n <span className=\"text-muted-foreground min-w-[70px] text-right text-xs\">\n {formatBytes(size)}\n </span>\n ) : null}\n </div>\n <div\n className=\"cursor-pointer\"\n title={\n fileState?.status === 'done'\n ? 'File synced'\n : fileState?.status === 'download'\n ? 'Downloading file…'\n : fileState?.status === 'upload'\n ? 'Uploading file…'\n : fileState?.status === 'error'\n ? `Failed to sync file: ${fileState.message}`\n : 'File not synced'\n }\n >\n {fileState?.status === 'done' ? (\n <CloudIcon className=\"w-[15px] text-green-400\" />\n ) : fileState?.status === 'download' ? (\n <CloudDownloadIcon className=\"w-[15px] text-orange-400\" />\n ) : fileState?.status === 'upload' ? (\n <CloudUploadIcon className=\"w-[15px] text-orange-400\" />\n ) : fileState?.status === 'error' ? (\n <CloudIcon className=\"text-destructive w-[15px]\" />\n ) : (\n <CloudIcon className=\"w-[15px] text-orange-400\" />\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport {FileDataSourceCard};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileDataSourcesPanel.d.ts","sourceRoot":"","sources":["../../src/data-sources/FileDataSourcesPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAIzB,QAAA,MAAM,oBAAoB,EAAE,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAC,CAkBpD,CAAC;AAEF,OAAO,EAAC,oBAAoB,EAAC,CAAC"}
|