Alter table to be multi-select grid for dropping PG extensions (#16143)

* Check if no extensions currently present before adding

* Added multiselect option for dropping extensions

* Loc file changes
This commit is contained in:
nasc17
2021-07-14 15:51:42 -07:00
committed by GitHub
parent 1308878650
commit 5a428b83ae
2 changed files with 94 additions and 88 deletions

View File

@@ -43,7 +43,7 @@ export const saveText = localize('arc.save', "Save");
export const discardText = localize('arc.discard', "Discard"); export const discardText = localize('arc.discard', "Discard");
export const resetPassword = localize('arc.resetPassword', "Reset Password"); export const resetPassword = localize('arc.resetPassword', "Reset Password");
export const addExtensions = localize('arc.addExtensions', "Add extensions"); export const addExtensions = localize('arc.addExtensions', "Add extensions");
export const dropExtension = localize('arc.dropExtension', "Drop extension"); export const dropExtensions = localize('arc.dropExtensions', "Drop extensions");
export const openInAzurePortal = localize('arc.openInAzurePortal', "Open in Azure Portal"); export const openInAzurePortal = localize('arc.openInAzurePortal', "Open in Azure Portal");
export const resourceGroup = localize('arc.resourceGroup', "Resource Group"); export const resourceGroup = localize('arc.resourceGroup', "Resource Group");
export const region = localize('arc.region', "Region"); export const region = localize('arc.region', "Region");
@@ -223,7 +223,7 @@ export function extensionInstalled(name: string): string { return localize('arc.
export function updatingInstance(name: string): string { return localize('arc.updatingInstance', "Updating instance '{0}'...", name); } export function updatingInstance(name: string): string { return localize('arc.updatingInstance', "Updating instance '{0}'...", name); }
export function instanceDeleted(name: string): string { return localize('arc.instanceDeleted', "Instance '{0}' deleted", name); } export function instanceDeleted(name: string): string { return localize('arc.instanceDeleted', "Instance '{0}' deleted", name); }
export function instanceUpdated(name: string): string { return localize('arc.instanceUpdated', "Instance '{0}' updated", name); } export function instanceUpdated(name: string): string { return localize('arc.instanceUpdated', "Instance '{0}' updated", name); }
export function extensionDropped(name: string): string { return localize('arc.extensionDropped', "Extension '{0}' deleted", name); } export function extensionsDropped(name: string): string { return localize('arc.extensionsDropped', "Extensions '{0}' dropped", name); }
export function extensionsAdded(name: string): string { return localize('arc.extensionsAdded', "Extensions '{0}' added", name); } export function extensionsAdded(name: string): string { return localize('arc.extensionsAdded', "Extensions '{0}' added", name); }
export function copiedToClipboard(name: string): string { return localize('arc.copiedToClipboard', "{0} copied to clipboard", name); } export function copiedToClipboard(name: string): string { return localize('arc.copiedToClipboard', "{0} copied to clipboard", name); }
export function clickTheTroubleshootButton(resourceType: string): string { return localize('arc.clickTheTroubleshootButton', "Click the troubleshoot button to open the Azure Arc {0} troubleshooting notebook.", resourceType); } export function clickTheTroubleshootButton(resourceType: string): string { return localize('arc.clickTheTroubleshootButton', "Click the troubleshoot button to open the Azure Arc {0} troubleshooting notebook.", resourceType); }

View File

@@ -11,15 +11,15 @@ import { IconPathHelper, cssStyles } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage'; import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel'; import { PostgresModel } from '../../../models/postgresModel';
import { AddPGExtensionsDialog } from '../../dialogs/addPGExtensionsDialog'; import { AddPGExtensionsDialog } from '../../dialogs/addPGExtensionsDialog';
import { Deferred } from '../../../common/promise';
export class PostgresExtensionsPage extends DashboardPage { export class PostgresExtensionsPage extends DashboardPage {
private extensionNames: string[] = []; private extensionNames: string[] = [];
private droppedExtensions: string[] = [];
private extensionsTable!: azdata.DeclarativeTableComponent; private extensionsTable!: azdata.DeclarativeTableComponent;
private extensionsLoading!: azdata.LoadingComponent; private extensionsLoading!: azdata.LoadingComponent;
private addExtensionsButton!: azdata.ButtonComponent; private addExtensionsButton!: azdata.ButtonComponent;
private _dropExtPromise?: Deferred<void>; private dropExtensionsButton!: azdata.ButtonComponent;
private extensionsLink!: azdata.HyperlinkComponent; private extensionsLink!: azdata.HyperlinkComponent;
private readonly _azdataApi: azdataExt.IExtension; private readonly _azdataApi: azdataExt.IExtension;
@@ -79,23 +79,23 @@ export class PostgresExtensionsPage extends DashboardPage {
width: '100%', width: '100%',
columns: [ columns: [
{ {
displayName: loc.extensionName, displayName: '',
valueType: azdata.DeclarativeDataType.string, valueType: azdata.DeclarativeDataType.component,
width: '20px',
isReadOnly: true, isReadOnly: true,
width: '95%',
headerCssStyles: cssStyles.tableHeader, headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow rowCssStyles: cssStyles.tableRow
}, },
{ {
displayName: loc.dropText, displayName: loc.extensionName,
valueType: azdata.DeclarativeDataType.component, valueType: azdata.DeclarativeDataType.string,
isReadOnly: false, isReadOnly: true,
width: '10%', width: '100%',
headerCssStyles: cssStyles.tableHeader, headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow rowCssStyles: cssStyles.tableRow
} }
], ],
data: [] dataValues: []
}).component(); }).component();
this.extensionsLoading = this.modelView.modelBuilder.loadingComponent() this.extensionsLoading = this.modelView.modelBuilder.loadingComponent()
@@ -128,7 +128,8 @@ export class PostgresExtensionsPage extends DashboardPage {
if (extArg) { if (extArg) {
try { try {
this.addExtensionsButton.enabled = false; this.addExtensionsButton.enabled = false;
let extensionList = this.extensionNames.join() + ',' + extArg; this.dropExtensionsButton.enabled = false;
let extensionList = this.extensionNames.length ? this.extensionNames.join() + ',' + extArg : extArg;
await vscode.window.withProgress( await vscode.window.withProgress(
{ {
location: vscode.ProgressLocation.Notification, location: vscode.ProgressLocation.Notification,
@@ -152,7 +153,7 @@ export class PostgresExtensionsPage extends DashboardPage {
} }
); );
vscode.window.showInformationMessage(loc.extensionsAdded(extensionList)); vscode.window.showInformationMessage(loc.extensionsAdded(extArg));
} catch (error) { } catch (error) {
vscode.window.showErrorMessage(loc.updateExtensionsFailed(error)); vscode.window.showErrorMessage(loc.updateExtensionsFailed(error));
@@ -162,43 +163,20 @@ export class PostgresExtensionsPage extends DashboardPage {
} }
})); }));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([ // Drop extensions
{ component: this.addExtensionsButton } this.dropExtensionsButton = this.modelView.modelBuilder.button().withProps({
]).component(); label: loc.dropExtensions,
} ariaLabel: loc.addExtensions,
iconPath: IconPathHelper.add,
private refreshExtensionsTable(): void { enabled: false
let extensions = this._postgresModel.config!.spec.engine.extensions;
this.extensionsTable.data = extensions.map(e => {
this.extensionNames.push(e.name);
return [e.name, this.createDropButton(e.name)];
});
}
/**
* Creates drop button to add to each row of extensions table.
* Allows user to drop individual extension.
* @param name name of postgres extension the drop button will be tied to.
*/
public createDropButton(name: string): azdata.ButtonComponent {
// Can drop individual extensions
let button = this.modelView.modelBuilder.button().withProps({
iconPath: IconPathHelper.delete,
ariaLabel: loc.dropExtension,
title: loc.dropExtension,
width: '20px',
height: '20px',
enabled: true
}).component(); }).component();
this.disposables.push( this.disposables.push(
button.onDidClick(async () => { this.dropExtensionsButton.onDidClick(async () => {
try { try {
this.addExtensionsButton.enabled = false; this.addExtensionsButton.enabled = false;
button.enabled = false; this.dropExtensionsButton.enabled = false;
await this.dropExtension(name); await this.dropExtension();
try { try {
await this._postgresModel.refresh(); await this._postgresModel.refresh();
@@ -206,63 +184,91 @@ export class PostgresExtensionsPage extends DashboardPage {
vscode.window.showErrorMessage(loc.refreshFailed(error)); vscode.window.showErrorMessage(loc.refreshFailed(error));
} }
vscode.window.showInformationMessage(loc.extensionDropped(name)); vscode.window.showInformationMessage(loc.extensionsDropped(this.droppedExtensions.join()));
this.droppedExtensions = [];
} catch (error) { } catch (error) {
vscode.window.showErrorMessage(loc.updateExtensionsFailed(error)); vscode.window.showErrorMessage(loc.updateExtensionsFailed(error));
} finally { } finally {
this.addExtensionsButton.enabled = true; this.addExtensionsButton.enabled = true;
} }
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: this.addExtensionsButton },
{ component: this.dropExtensionsButton }
]).component();
}
private refreshExtensionsTable(): void {
let extensions = this._postgresModel.config!.spec.engine.extensions;
let extensionBasicData = extensions.map(e => {
this.extensionNames.push(e.name);
return [this.createDropCheckBox(e.name), e.name];
});
let extenesionFinalData: azdata.DeclarativeTableCellValue[][] = [];
extenesionFinalData = extensionBasicData.map(e => {
return e.map((value): azdata.DeclarativeTableCellValue => {
return { value: value };
});
});
this.extensionsTable.setDataValues(extenesionFinalData);
}
/**
* Creates checkboxes to select which extensions to drop.
* Allows user to drop multiple extension.
* @param name name of postgres extension the checkbox will be tied to.
*/
public createDropCheckBox(name: string): azdata.CheckBoxComponent {
// Can select extensions to drop
let checkBox = this.modelView.modelBuilder.checkBox().withProps({
ariaLabel: loc.dropExtensions,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
this.disposables.push(
checkBox.onChanged(() => {
if (checkBox.checked) {
this.droppedExtensions.push(name);
} else {
let index = this.droppedExtensions.indexOf(name, 0);
this.droppedExtensions.splice(index, 1);
}
this.dropExtensionsButton.enabled = this.droppedExtensions.length ? true : false;
}) })
); );
// Dropping the citus extension is not supported. return checkBox;
if (name === 'citus') {
button.enabled = false;
}
return button;
} }
/** /**
* Calls edit on postgres extensions with an updated extensions list. * Calls edit on postgres extensions with an updated extensions list.
* @param name name of postgres extension to not inlcude when editing list of extensions
*/ */
public async dropExtension(name: string): Promise<void> { public async dropExtension(): Promise<void> {
// Only allow one drop to be happening at a time this.droppedExtensions.forEach(d => {
if (this._dropExtPromise) { let index = this.droppedExtensions.indexOf(d, 0);
vscode.window.showErrorMessage(loc.dropMultipleExtensions); this.extensionNames.splice(index, 1);
return this._dropExtPromise.promise; });
}
this._dropExtPromise = new Deferred(); await vscode.window.withProgress(
try { {
await vscode.window.withProgress( location: vscode.ProgressLocation.Notification,
{ title: loc.updatingInstance(this._postgresModel.info.name),
location: vscode.ProgressLocation.Notification, cancellable: false
title: loc.updatingInstance(this._postgresModel.info.name), },
cancellable: false async (_progress, _token): Promise<void> => {
}, await this._azdataApi.azdata.arc.postgres.server.edit(
async (_progress, _token): Promise<void> => { this._postgresModel.info.name,
let index = this.extensionNames.indexOf(name, 0); {
this.extensionNames.splice(index, 1); extensions: this.extensionNames.join()
},
await this._azdataApi.azdata.arc.postgres.server.edit( this._postgresModel.controllerModel.azdataAdditionalEnvVars
this._postgresModel.info.name, );
{ }
extensions: this.extensionNames.join() );
},
this._postgresModel.controllerModel.azdataAdditionalEnvVars
);
}
);
this._dropExtPromise.resolve();
} catch (err) {
this._dropExtPromise.reject(err);
throw err;
} finally {
this._dropExtPromise = undefined;
}
} }
private handleConfigUpdated(): void { private handleConfigUpdated(): void {