Skip to content

Commit 430fec2

Browse files
committed
allow switching between integrations on SQL block
1 parent bc5b9ef commit 430fec2

File tree

2 files changed

+132
-12
lines changed

2 files changed

+132
-12
lines changed

src/notebooks/deepnote/sqlCellStatusBarProvider.ts

Lines changed: 124 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
NotebookCellStatusBarItemProvider,
77
NotebookEdit,
88
ProviderResult,
9+
QuickPickItem,
10+
QuickPickItemKind,
911
WorkspaceEdit,
1012
commands,
1113
l10n,
@@ -17,9 +19,9 @@ import { inject, injectable } from 'inversify';
1719

1820
import { IExtensionSyncActivationService } from '../../platform/activation/types';
1921
import { IDisposableRegistry } from '../../platform/common/types';
20-
import { Commands } from '../../platform/common/constants';
2122
import { IIntegrationStorage } from './integrations/types';
22-
import { DATAFRAME_SQL_INTEGRATION_ID } from '../../platform/notebooks/deepnote/integrationTypes';
23+
import { Commands } from '../../platform/common/constants';
24+
import { DATAFRAME_SQL_INTEGRATION_ID, IntegrationType } from '../../platform/notebooks/deepnote/integrationTypes';
2325

2426
/**
2527
* Provides status bar items for SQL cells showing the integration name and variable name
@@ -53,6 +55,13 @@ export class SqlCellStatusBarProvider implements NotebookCellStatusBarItemProvid
5355
})
5456
);
5557

58+
// Register command to switch SQL integration
59+
this.disposables.push(
60+
commands.registerCommand('deepnote.switchSqlIntegration', async (cell: NotebookCell) => {
61+
await this.switchIntegration(cell);
62+
})
63+
);
64+
5665
// Dispose our emitter with the extension
5766
this.disposables.push(this._onDidChangeCellStatusBarItems);
5867
}
@@ -113,7 +122,12 @@ export class SqlCellStatusBarProvider implements NotebookCellStatusBarItemProvid
113122
return {
114123
text: `$(database) ${l10n.t('DataFrame SQL (DuckDB)')}`,
115124
alignment: 1, // NotebookCellStatusBarAlignment.Left
116-
tooltip: l10n.t('Internal DuckDB integration for querying DataFrames')
125+
tooltip: l10n.t('Internal DuckDB integration for querying DataFrames\nClick to switch'),
126+
command: {
127+
title: l10n.t('Switch Integration'),
128+
command: 'deepnote.switchSqlIntegration',
129+
arguments: [cell]
130+
}
117131
};
118132
}
119133

@@ -126,15 +140,15 @@ export class SqlCellStatusBarProvider implements NotebookCellStatusBarItemProvid
126140
const config = await this.integrationStorage.getProjectIntegrationConfig(projectId, integrationId);
127141
const displayName = config?.name || l10n.t('Unknown integration (configure)');
128142

129-
// Create a status bar item that opens the integration management UI
143+
// Create a status bar item that opens the integration picker
130144
return {
131145
text: `$(database) ${displayName}`,
132146
alignment: 1, // NotebookCellStatusBarAlignment.Left
133-
tooltip: l10n.t('SQL Integration: {0}\nClick to configure', displayName),
147+
tooltip: l10n.t('SQL Integration: {0}\nClick to switch or configure', displayName),
134148
command: {
135-
title: l10n.t('Configure Integration'),
136-
command: Commands.ManageIntegrations,
137-
arguments: [integrationId]
149+
title: l10n.t('Switch Integration'),
150+
command: 'deepnote.switchSqlIntegration',
151+
arguments: [cell]
138152
}
139153
};
140154
}
@@ -201,4 +215,106 @@ export class SqlCellStatusBarProvider implements NotebookCellStatusBarItemProvid
201215
// Trigger status bar update
202216
this._onDidChangeCellStatusBarItems.fire();
203217
}
218+
219+
private async switchIntegration(cell: NotebookCell): Promise<void> {
220+
const currentIntegrationId = this.getIntegrationId(cell);
221+
222+
// Get all available integrations
223+
const allIntegrations = await this.integrationStorage.getAll();
224+
225+
// Build quick pick items
226+
const items: QuickPickItem[] = [];
227+
228+
// Check if current integration is unknown (not in the list)
229+
const isCurrentIntegrationUnknown =
230+
currentIntegrationId &&
231+
currentIntegrationId !== DATAFRAME_SQL_INTEGRATION_ID &&
232+
!allIntegrations.some((i) => i.id === currentIntegrationId);
233+
234+
// Add current unknown integration first if it exists
235+
if (isCurrentIntegrationUnknown && currentIntegrationId) {
236+
items.push({
237+
label: l10n.t('Unknown integration (configure)'),
238+
description: currentIntegrationId,
239+
detail: l10n.t('Currently selected'),
240+
id: currentIntegrationId
241+
} as QuickPickItem & { id: string });
242+
}
243+
244+
// Add all configured integrations
245+
for (const integration of allIntegrations) {
246+
const typeLabel = this.getIntegrationTypeLabel(integration.type);
247+
items.push({
248+
label: integration.name || integration.id,
249+
description: typeLabel,
250+
detail: integration.id === currentIntegrationId ? l10n.t('Currently selected') : undefined,
251+
// Store the integration ID in a custom property
252+
id: integration.id
253+
} as QuickPickItem & { id: string });
254+
}
255+
256+
// Add DuckDB integration
257+
items.push({
258+
label: l10n.t('DataFrame SQL (DuckDB)'),
259+
description: l10n.t('DuckDB'),
260+
detail: currentIntegrationId === DATAFRAME_SQL_INTEGRATION_ID ? l10n.t('Currently selected') : undefined,
261+
id: DATAFRAME_SQL_INTEGRATION_ID
262+
} as QuickPickItem & { id: string });
263+
264+
// Add separator
265+
items.push({
266+
label: '',
267+
kind: QuickPickItemKind.Separator
268+
});
269+
270+
// Add "Configure current integration" option
271+
if (currentIntegrationId && currentIntegrationId !== DATAFRAME_SQL_INTEGRATION_ID) {
272+
items.push({
273+
label: l10n.t('Configure current integration'),
274+
id: '__configure__'
275+
} as QuickPickItem & { id: string });
276+
}
277+
278+
const selected = await window.showQuickPick(items, {
279+
placeHolder: l10n.t('Select SQL integration'),
280+
matchOnDescription: true
281+
});
282+
283+
if (!selected) {
284+
return;
285+
}
286+
287+
const selectedId = (selected as QuickPickItem & { id: string }).id;
288+
289+
// Handle "Configure current integration" option
290+
if (selectedId === '__configure__' && currentIntegrationId) {
291+
await commands.executeCommand(Commands.ManageIntegrations, currentIntegrationId);
292+
return;
293+
}
294+
295+
// Update cell metadata with new integration ID
296+
const edit = new WorkspaceEdit();
297+
const updatedMetadata = {
298+
...cell.metadata,
299+
sql_integration_id: selectedId
300+
};
301+
302+
edit.set(cell.notebook.uri, [NotebookEdit.updateCellMetadata(cell.index, updatedMetadata)]);
303+
304+
await workspace.applyEdit(edit);
305+
306+
// Trigger status bar update
307+
this._onDidChangeCellStatusBarItems.fire();
308+
}
309+
310+
private getIntegrationTypeLabel(type: IntegrationType): string {
311+
switch (type) {
312+
case IntegrationType.Postgres:
313+
return l10n.t('PostgreSQL');
314+
case IntegrationType.BigQuery:
315+
return l10n.t('BigQuery');
316+
default:
317+
return type;
318+
}
319+
}
204320
}

src/notebooks/deepnote/sqlCellStatusBarProvider.unit.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,12 @@ suite('SqlCellStatusBarProvider', () => {
7272
const integrationItem = items[0];
7373
assert.strictEqual(integrationItem.text, '$(database) DataFrame SQL (DuckDB)');
7474
assert.strictEqual(integrationItem.alignment, 1);
75-
assert.strictEqual(integrationItem.tooltip, 'Internal DuckDB integration for querying DataFrames');
76-
assert.isUndefined(integrationItem.command);
75+
assert.strictEqual(
76+
integrationItem.tooltip,
77+
'Internal DuckDB integration for querying DataFrames\nClick to switch'
78+
);
79+
assert.isDefined(integrationItem.command);
80+
assert.strictEqual(integrationItem.command.command, 'deepnote.switchSqlIntegration');
7781

7882
// Check variable status bar item
7983
const variableItem = items[1];
@@ -118,8 +122,8 @@ suite('SqlCellStatusBarProvider', () => {
118122
assert.strictEqual(integrationItem.text, '$(database) My Postgres DB');
119123
assert.strictEqual(integrationItem.alignment, 1);
120124
assert.isDefined(integrationItem.command);
121-
assert.strictEqual(integrationItem.command.command, 'deepnote.manageIntegrations');
122-
assert.deepStrictEqual(integrationItem.command.arguments, [integrationId]);
125+
assert.strictEqual(integrationItem.command.command, 'deepnote.switchSqlIntegration');
126+
assert.deepStrictEqual(integrationItem.command.arguments, [cell]);
123127

124128
// Check variable status bar item
125129
const variableItem = items[1];

0 commit comments

Comments
 (0)