mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-23 17:23:02 -05:00
View extensions of Postgres server group (#15887)
* Init * Fix view * Change strings * Change strings edit/view * Only view extensions * Added loading text * Add table label, remove try catch block, prfixes * String add * Take out podstatus model, add correct link
This commit is contained in:
18
extensions/arc/images/extensions.svg
Normal file
18
extensions/arc/images/extensions.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
|
||||
<defs>
|
||||
<linearGradient id="a7ee2b34-5d31-4c40-9ffe-8433e6b85e09" x1="8.144" y1="13.837" x2="8.144" y2="6.11" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#32bedd" />
|
||||
<stop offset="0.175" stop-color="#32caea" />
|
||||
<stop offset="0.41" stop-color="#32d2f2" />
|
||||
<stop offset="0.775" stop-color="#32d4f5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<title>MsPortalFx.base.images-21</title>
|
||||
<g id="b60cdf7c-998d-4b07-83eb-3c17ec41d74f">
|
||||
<g>
|
||||
<rect x="4.281" y="6.11" width="7.726" height="7.726" rx="0.303" fill="url(#a7ee2b34-5d31-4c40-9ffe-8433e6b85e09)" />
|
||||
<path d="M16.894.66h-7.3a.3.3,0,0,0-.3.3V2.287a.3.3,0,0,0,.3.3h5.371a.605.605,0,0,1,.605.606V8.651a.3.3,0,0,0,.3.3H17.2a.3.3,0,0,0,.3-.3V1.266A.606.606,0,0,0,16.894.66Z" fill="#773adc" />
|
||||
<path d="M14.333,10.223v4.806a.552.552,0,0,1-.552.552H2.81a.552.552,0,0,1-.552-.552V4.672A.552.552,0,0,1,2.81,4.12h5.5a.3.3,0,0,0,.3-.3V2.665a.3.3,0,0,0-.3-.3H1.052A.552.552,0,0,0,.5,2.914V16.788a.552.552,0,0,0,.552.552H15.539a.553.553,0,0,0,.553-.552V10.223a.3.3,0,0,0-.3-.3H14.636A.3.3,0,0,0,14.333,10.223Z" fill="#b3b3b3" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -28,6 +28,7 @@ export class IconPathHelper {
|
||||
public static collapseUp: IconPath;
|
||||
public static collapseDown: IconPath;
|
||||
public static postgres: IconPath;
|
||||
public static extensions: IconPath;
|
||||
public static computeStorage: IconPath;
|
||||
public static connection: IconPath;
|
||||
public static backup: IconPath;
|
||||
@@ -74,6 +75,10 @@ export class IconPathHelper {
|
||||
light: IconPathHelper.context.asAbsolutePath('images/postgres.svg'),
|
||||
dark: IconPathHelper.context.asAbsolutePath('images/postgres.svg')
|
||||
};
|
||||
IconPathHelper.extensions = {
|
||||
light: IconPathHelper.context.asAbsolutePath('images/extensions.svg'),
|
||||
dark: IconPathHelper.context.asAbsolutePath('images/extensions.svg')
|
||||
};
|
||||
IconPathHelper.computeStorage = {
|
||||
light: context.asAbsolutePath('images/billing.svg'),
|
||||
dark: context.asAbsolutePath('images/billing.svg')
|
||||
|
||||
@@ -18,6 +18,7 @@ export const miaaType = localize('arc.miaaType', "SQL managed instance - Azure A
|
||||
|
||||
export const overview = localize('arc.overview', "Overview");
|
||||
export const connectionStrings = localize('arc.connectionStrings', "Connection Strings");
|
||||
export const preLoadedExtensions = localize('arc.preloaded Extensions', "Preloaded Extensions");
|
||||
export const networking = localize('arc.networking', "Networking");
|
||||
export const properties = localize('arc.properties', "Properties");
|
||||
export const settings = localize('arc.settings', "Settings");
|
||||
@@ -39,6 +40,7 @@ export const deleteText = localize('arc.delete', "Delete");
|
||||
export const saveText = localize('arc.save', "Save");
|
||||
export const discardText = localize('arc.discard', "Discard");
|
||||
export const resetPassword = localize('arc.resetPassword', "Reset Password");
|
||||
export const addExtensions = localize('arc.addExtensions', "Add extensions");
|
||||
export const openInAzurePortal = localize('arc.openInAzurePortal', "Open in Azure Portal");
|
||||
export const resourceGroup = localize('arc.resourceGroup', "Resource Group");
|
||||
export const region = localize('arc.region', "Region");
|
||||
@@ -52,6 +54,13 @@ export const type = localize('arc.type', "Type");
|
||||
export const status = localize('arc.status', "Status");
|
||||
export const miaaAdmin = localize('arc.miaaAdmin', "Managed instance admin");
|
||||
export const controllerEndpoint = localize('arc.controllerEndpoint', "Controller endpoint");
|
||||
export const extensionName = localize('arc.extensionName', "Extension name");
|
||||
export const extensionsDescription = localize('arc.extensionsDescription', "PostgreSQL provides the ability to extend the functionality of your database by using extensions. Extensions allow for bundling multiple related SQL objects together in a single package that can be loaded or removed from your database with a single command. After being loaded in the database, extensions can function like built-in features.");
|
||||
export const extensionsFunction = localize('arc.extensionsFunction', "Some extensions must be loaded into PostgreSQL at startup time before they can be used. These preloaded extensions can be viewed below.");
|
||||
export const extensionsLearnMore = localize('arc.extensionsLearnMore', "Learn more about PostgreSQL extensions.");
|
||||
export const extensionsTableLoading = localize('arc.extensionsTableLoading', "Table of preloaded extensions are loading.");
|
||||
export const extensionsTableLabel = localize('arc.extensionsTableLabel', "Table of preloaded extensions.");
|
||||
export const extensionsTableLoadingComplete = localize('arc.extensionsTableLoadingComplete', "Preloaded extensions can now be viewed.");
|
||||
export const dataController = localize('arc.dataController', "Data controller");
|
||||
export const kibanaDashboard = localize('arc.kibanaDashboard', "Kibana Dashboard");
|
||||
export const grafanaDashboard = localize('arc.grafanaDashboard', "Grafana Dashboard");
|
||||
|
||||
@@ -18,6 +18,7 @@ import { PostgresWorkerNodeParametersPage } from './postgresWorkerNodeParameters
|
||||
import { PostgresPropertiesPage } from './postgresPropertiesPage';
|
||||
import { PostgresResourceHealthPage } from './postgresResourceHealthPage';
|
||||
import { PostgresCoordinatorNodeParametersPage } from './postgresCoordinatorNodeParametersPage';
|
||||
import { PostgresExtensionsPage } from './postgresExtensionsPage';
|
||||
|
||||
export class PostgresDashboard extends Dashboard {
|
||||
constructor(private _context: vscode.ExtensionContext, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
|
||||
@@ -34,6 +35,7 @@ export class PostgresDashboard extends Dashboard {
|
||||
|
||||
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
|
||||
const overviewPage = new PostgresOverviewPage(modelView, this.dashboard, this._controllerModel, this._postgresModel);
|
||||
const extensionsPage = new PostgresExtensionsPage(modelView, this.dashboard, this._postgresModel);
|
||||
const connectionStringsPage = new PostgresConnectionStringsPage(modelView, this.dashboard, this._postgresModel);
|
||||
const computeAndStoragePage = new PostgresComputeAndStoragePage(modelView, this.dashboard, this._postgresModel);
|
||||
const propertiesPage = new PostgresPropertiesPage(modelView, this.dashboard, this._controllerModel, this._postgresModel);
|
||||
@@ -49,6 +51,7 @@ export class PostgresDashboard extends Dashboard {
|
||||
title: loc.settings,
|
||||
tabs: [
|
||||
propertiesPage.tab,
|
||||
extensionsPage.tab,
|
||||
connectionStringsPage.tab,
|
||||
computeAndStoragePage.tab,
|
||||
coordinatorNodeParametersPage.tab,
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as azdata from 'azdata';
|
||||
import * as azdataExt from 'azdata-ext';
|
||||
import * as loc from '../../../localizedConstants';
|
||||
import { IconPathHelper, cssStyles } from '../../../constants';
|
||||
import { DashboardPage } from '../../components/dashboardPage';
|
||||
import { PostgresModel } from '../../../models/postgresModel';
|
||||
|
||||
export class PostgresExtensionsPage extends DashboardPage {
|
||||
|
||||
private extensions: { name: string; }[] = [];
|
||||
private extensionsTable!: azdata.DeclarativeTableComponent;
|
||||
private extensionsLoading!: azdata.LoadingComponent;
|
||||
|
||||
private readonly _azdataApi: azdataExt.IExtension;
|
||||
|
||||
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _postgresModel: PostgresModel) {
|
||||
super(modelView, dashboard);
|
||||
this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
|
||||
|
||||
this.disposables.push(
|
||||
this._postgresModel.onConfigUpdated(() => this.eventuallyRunOnInitialized(() => this.handleConfigUpdated())));
|
||||
}
|
||||
|
||||
protected get title(): string {
|
||||
return loc.preLoadedExtensions;
|
||||
}
|
||||
|
||||
protected get id(): string {
|
||||
return 'postgres-extensions';
|
||||
}
|
||||
|
||||
protected get icon(): { dark: string; light: string; } {
|
||||
return IconPathHelper.extensions;
|
||||
}
|
||||
|
||||
protected get container(): azdata.Component {
|
||||
const root = this.modelView.modelBuilder.divContainer().component();
|
||||
const content = this.modelView.modelBuilder.divContainer().component();
|
||||
root.addItem(content, { CSSStyles: { 'margin': '10px 20px 0px 20px' } });
|
||||
|
||||
content.addItem(this.modelView.modelBuilder.text().withProps({
|
||||
value: this.title,
|
||||
CSSStyles: { ...cssStyles.title }
|
||||
}).component());
|
||||
|
||||
content.addItem(this.modelView.modelBuilder.text().withProps({
|
||||
value: loc.extensionsDescription,
|
||||
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
|
||||
}).component());
|
||||
|
||||
const info = this.modelView.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.extensionsFunction,
|
||||
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
|
||||
}).component();
|
||||
|
||||
const link = this.modelView.modelBuilder.hyperlink().withProperties<azdata.HyperlinkComponentProperties>({
|
||||
label: loc.extensionsLearnMore,
|
||||
url: 'https://docs.microsoft.com/azure/azure-arc/data/using-extensions-in-postgresql-hyperscale-server-group',
|
||||
}).component();
|
||||
|
||||
const infoAndLink = this.modelView.modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap' }).component();
|
||||
infoAndLink.addItem(info, { CSSStyles: { 'margin-right': '5px' } });
|
||||
infoAndLink.addItem(link);
|
||||
content.addItem(infoAndLink, { CSSStyles: { 'margin-bottom': '15px', 'margin-top': '25px' } });
|
||||
|
||||
this.extensionsTable = this.modelView.modelBuilder.declarativeTable().withProperties<azdata.DeclarativeTableProperties>({
|
||||
ariaLabel: loc.extensionsTableLabel,
|
||||
width: '100%',
|
||||
columns: [
|
||||
{
|
||||
displayName: loc.extensionName,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: '100%',
|
||||
headerCssStyles: cssStyles.tableHeader,
|
||||
rowCssStyles: cssStyles.tableRow
|
||||
}
|
||||
],
|
||||
data: []
|
||||
}).component();
|
||||
|
||||
this.extensionsLoading = this.modelView.modelBuilder.loadingComponent()
|
||||
.withItem(this.extensionsTable)
|
||||
.withProperties<azdata.LoadingComponentProperties>({
|
||||
loading: !this._postgresModel.configLastUpdated,
|
||||
loadingText: loc.extensionsTableLoading,
|
||||
loadingCompletedText: loc.extensionsTableLoadingComplete
|
||||
}).component();
|
||||
|
||||
content.addItem(this.extensionsLoading, { CSSStyles: cssStyles.text });
|
||||
|
||||
this.initialized = true;
|
||||
return root;
|
||||
}
|
||||
|
||||
protected get toolbarContainer(): azdata.ToolbarContainer {
|
||||
// Add extensions
|
||||
const addExtensionsButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
label: loc.addExtensions,
|
||||
iconPath: IconPathHelper.add
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
addExtensionsButton.onDidClick(async () => {
|
||||
addExtensionsButton.enabled = false;
|
||||
try {
|
||||
await vscode.window.withProgress(
|
||||
{
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: loc.updatingInstance(this._postgresModel.info.name),
|
||||
cancellable: false
|
||||
},
|
||||
async (_progress, _token): Promise<void> => {
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{
|
||||
extensions: ''
|
||||
},
|
||||
this._postgresModel.controllerModel.azdataAdditionalEnvVars);
|
||||
|
||||
try {
|
||||
await this._postgresModel.refresh();
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(loc.refreshFailed(error));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
vscode.window.showInformationMessage(loc.instanceUpdated(this._postgresModel.info.name));
|
||||
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(loc.instanceUpdateFailed(this._postgresModel.info.name, error));
|
||||
} finally {
|
||||
addExtensionsButton.enabled = true;
|
||||
}
|
||||
}));
|
||||
|
||||
return this.modelView.modelBuilder.toolbarContainer().component();
|
||||
}
|
||||
|
||||
private refreshExtensionsTable(): void {
|
||||
if (this._postgresModel.config) {
|
||||
this.extensions = this._postgresModel.config?.spec.engine.extensions;
|
||||
this.extensionsTable.data = this.extensions.map(e => [e.name]);
|
||||
}
|
||||
}
|
||||
|
||||
private handleConfigUpdated(): void {
|
||||
this.extensionsLoading.loading = false;
|
||||
this.refreshExtensionsTable();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user