diff --git a/extensions/arc/images/miaa.svg b/extensions/arc/images/miaa.svg
new file mode 100644
index 0000000000..789ed2f565
--- /dev/null
+++ b/extensions/arc/images/miaa.svg
@@ -0,0 +1,21 @@
+
diff --git a/extensions/arc/src/common/utils.ts b/extensions/arc/src/common/utils.ts
index 4230c2f17b..eb09c1ec05 100644
--- a/extensions/arc/src/common/utils.ts
+++ b/extensions/arc/src/common/utils.ts
@@ -6,12 +6,8 @@
import * as vscode from 'vscode';
import * as azurecore from '../../../azurecore/src/azurecore';
import * as loc from '../localizedConstants';
+import { IconPathHelper, IconPath, ResourceType, Connectionmode } from '../constants';
-export enum ResourceType {
- dataControllers = 'dataControllers',
- postgresInstances = 'postgresInstances',
- sqlManagedInstances = 'sqlManagedInstances'
-}
/**
* Converts the resource type name into the localized Display Name for that type.
* @param resourceType The resource type name to convert
@@ -49,3 +45,24 @@ export async function getAzurecoreApi(): Promise {
}
return azurecoreApi;
}
+
+export function getResourceTypeIcon(resourceType: string): IconPath | undefined {
+ switch (resourceType) {
+ case ResourceType.sqlManagedInstances:
+ return IconPathHelper.miaa;
+ case ResourceType.postgresInstances:
+ return IconPathHelper.postgres;
+ }
+ return undefined;
+}
+
+export function getConnectionModeDisplayText(connectionMode: string | undefined): string {
+ connectionMode = connectionMode ?? '';
+ switch (connectionMode) {
+ case Connectionmode.connected:
+ return loc.connected;
+ case Connectionmode.disconnected:
+ return loc.disconnected;
+ }
+ return connectionMode;
+}
diff --git a/extensions/arc/src/constants.ts b/extensions/arc/src/constants.ts
index 6969f55af1..f20c9d4b1d 100644
--- a/extensions/arc/src/constants.ts
+++ b/extensions/arc/src/constants.ts
@@ -30,6 +30,7 @@ export class IconPathHelper {
public static refresh: IconPath;
public static support: IconPath;
public static wrench: IconPath;
+ public static miaa: IconPath;
public static setExtensionContext(context: vscode.ExtensionContext) {
IconPathHelper.context = context;
@@ -101,12 +102,36 @@ export class IconPathHelper {
light: context.asAbsolutePath('images/wrench.svg'),
dark: context.asAbsolutePath('images/wrench.svg')
};
+ IconPathHelper.miaa = {
+ light: context.asAbsolutePath('images/miaa.svg'),
+ dark: context.asAbsolutePath('images/miaa.svg'),
+ };
}
}
+export const enum ResourceType {
+ dataControllers = 'dataControllers',
+ postgresInstances = 'postgresInstances',
+ sqlManagedInstances = 'sqlManagedInstances'
+}
+
+export const enum Endpoints {
+ mgmtproxy = 'mgmtproxy',
+ logsui = 'logsui',
+ metricsui = 'metricsui',
+ controller = 'controller'
+}
+
+export const enum Connectionmode {
+ connected = 'connected',
+ disconnected = 'disconnected'
+}
+
export namespace cssStyles {
export const text = { 'user-select': 'text', 'cursor': 'text' };
export const title = { ...text, 'font-weight': 'bold', 'font-size': '14px' };
export const tableHeader = { ...text, 'text-align': 'left', 'border': 'none' };
export const tableRow = { ...text, 'border-top': 'solid 1px #ccc', 'border-bottom': 'solid 1px #ccc', 'border-left': 'none', 'border-right': 'none' };
}
+
+export const iconSize = '20px';
diff --git a/extensions/arc/src/localizedConstants.ts b/extensions/arc/src/localizedConstants.ts
index 9d976ee140..98d59b1dad 100644
--- a/extensions/arc/src/localizedConstants.ts
+++ b/extensions/arc/src/localizedConstants.ts
@@ -41,6 +41,7 @@ export const name = localize('arc.name', "Name");
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 dataController = localize('arc.dataController', "Data controller");
export const kibanaDashboard = localize('arc.kibanaDashboard', "Kibana Dashboard");
export const grafanaDashboard = localize('arc.grafanaDashboard', "Grafana Dashboard");
@@ -60,6 +61,8 @@ export const refresh = localize('arc.refresh', "Refresh");
export const troubleshoot = localize('arc.troubleshoot', "Troubleshoot");
export const clickTheNewSupportRequestButton = localize('arc.clickTheNewSupportRequestButton', "Click the new support request button to file a support request in the Azure Portal.");
export const running = localize('arc.running', "Running");
+export const connected = localize('arc.connected', "Connected");
+export const disconnected = localize('arc.disconnected', "Disconnected");
// Postgres constants
export const coordinatorEndpoint = localize('arc.coordinatorEndpoint', "Coordinator endpoint");
diff --git a/extensions/arc/src/models/controllerModel.ts b/extensions/arc/src/models/controllerModel.ts
index a5854489cf..8c851d7207 100644
--- a/extensions/arc/src/models/controllerModel.ts
+++ b/extensions/arc/src/models/controllerModel.ts
@@ -6,7 +6,8 @@
import * as vscode from 'vscode';
import { Authentication } from '../controller/auth';
import { EndpointsRouterApi, EndpointModel, RegistrationRouterApi, RegistrationResponse, TokenRouterApi, SqlInstanceRouterApi } from '../controller/generated/v1/api';
-import { ResourceType, parseEndpoint } from '../common/utils';
+import { parseEndpoint } from '../common/utils';
+import { ResourceType } from '../constants';
export interface Registration extends RegistrationResponse {
externalIp?: string;
diff --git a/extensions/arc/src/models/postgresModel.ts b/extensions/arc/src/models/postgresModel.ts
index b18de9dd88..539470a789 100644
--- a/extensions/arc/src/models/postgresModel.ts
+++ b/extensions/arc/src/models/postgresModel.ts
@@ -108,7 +108,7 @@ export class PostgresModel {
/** Creates a SQL database in the service */
public async createDatabase(db: DuskyObjectModelsDatabase): Promise {
- return await (await this._databaseRouter.createDuskyDatabase(this.namespace, this.name, db)).body;
+ return (await this._databaseRouter.createDuskyDatabase(this.namespace, this.name, db)).body;
}
/**
diff --git a/extensions/arc/src/test/common/utils.test.ts b/extensions/arc/src/test/common/utils.test.ts
index e9889730cb..272af9aadc 100644
--- a/extensions/arc/src/test/common/utils.test.ts
+++ b/extensions/arc/src/test/common/utils.test.ts
@@ -5,9 +5,10 @@
import * as should from 'should';
import 'mocha';
-import { resourceTypeToDisplayName, ResourceType, parseEndpoint } from '../../common/utils';
+import { resourceTypeToDisplayName, parseEndpoint } from '../../common/utils';
import * as loc from '../../localizedConstants';
+import { ResourceType } from '../../constants';
describe('resourceTypeToDisplayName Method Tests', () => {
it('Display Name should be correct for valid ResourceType', function (): void {
diff --git a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts
index 22588c5113..f558676490 100644
--- a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts
+++ b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts
@@ -7,16 +7,33 @@ import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as loc from '../../../localizedConstants';
import { DashboardPage } from '../../components/dashboardPage';
-import { IconPathHelper, cssStyles } from '../../../constants';
+import { IconPathHelper, cssStyles, iconSize, ResourceType, Endpoints } from '../../../constants';
import { ControllerModel } from '../../../models/controllerModel';
-import { resourceTypeToDisplayName, ResourceType, getAzurecoreApi } from '../../../common/utils';
+import { resourceTypeToDisplayName, getAzurecoreApi, getResourceTypeIcon, getConnectionModeDisplayText } from '../../../common/utils';
import { RegistrationResponse } from '../../../controller/generated/v1/model/registrationResponse';
+import { EndpointModel } from '../../../controller/generated/v1/api';
export class ControllerDashboardOverviewPage extends DashboardPage {
+ private _propertiesLoadingComponent!: azdata.LoadingComponent;
+ private _arcResourcesLoadingComponent!: azdata.LoadingComponent;
+
private _arcResourcesTable!: azdata.DeclarativeTableComponent;
private _propertiesContainer!: azdata.PropertiesContainerComponent;
+ private controllerProperties = {
+ instanceName: '-',
+ resourceGroupName: '-',
+ location: '-',
+ subscriptionId: '-',
+ controllerEndpoint: '-',
+ connectionMode: '-',
+ instanceNamespace: '-',
+ };
+
+ private _endpointsRetrieved = false;
+ private _registrationsRetrieved = false;
+
constructor(modelView: azdata.ModelView, private _controllerModel: ControllerModel) {
super(modelView);
this._controllerModel.onRegistrationsUpdated((_: RegistrationResponse[]) => {
@@ -24,6 +41,11 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
this.handleRegistrationsUpdated().catch(e => console.log(e));
});
});
+ this._controllerModel.onEndpointsUpdated(endpoints => {
+ this.eventuallyRunOnInitialized(() => {
+ this.handleEndpointsUpdated(endpoints);
+ });
+ });
this.refresh().catch(e => {
console.log(e);
});
@@ -55,8 +77,9 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
rootContainer.addItem(contentContainer, { CSSStyles: { 'margin': '10px 20px 0px 20px' } });
this._propertiesContainer = this.modelView.modelBuilder.propertiesContainer().component();
+ this._propertiesLoadingComponent = this.modelView.modelBuilder.loadingComponent().withItem(this._propertiesContainer).component();
- contentContainer.addItem(this._propertiesContainer);
+ contentContainer.addItem(this._propertiesLoadingComponent);
const arcResourcesTitle = this.modelView.modelBuilder.text()
.withProperties({ value: loc.arcResources })
@@ -69,6 +92,14 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
this._arcResourcesTable = this.modelView.modelBuilder.declarativeTable().withProperties({
data: [],
columns: [
+ {
+ displayName: '',
+ valueType: azdata.DeclarativeDataType.component,
+ width: iconSize,
+ isReadOnly: true,
+ headerCssStyles: cssStyles.tableHeader,
+ rowCssStyles: cssStyles.tableRow
+ },
{
displayName: loc.name,
valueType: azdata.DeclarativeDataType.string,
@@ -100,7 +131,9 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
.withItems([this._arcResourcesTable])
.component();
- contentContainer.addItem(arcResourcesTableContainer);
+ this._arcResourcesLoadingComponent = this.modelView.modelBuilder.loadingComponent().withItem(arcResourcesTableContainer).component();
+
+ contentContainer.addItem(this._arcResourcesLoadingComponent);
this.initialized = true;
return rootContainer;
}
@@ -112,10 +145,9 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
iconPath: IconPathHelper.add
}).component();
- const deleteButton = this.modelView.modelBuilder.button().withProperties({
- label: loc.deleteText,
- iconPath: IconPathHelper.delete
- }).component();
+ createNewButton.onDidClick(async () => {
+ await vscode.commands.executeCommand('azdata.resource.deploy');
+ });
const openInAzurePortalButton = this.modelView.modelBuilder.button().withProperties({
label: loc.openInAzurePortal,
@@ -134,8 +166,7 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems(
[
- { component: createNewButton },
- { component: deleteButton, toolbarSeparatorAfter: true },
+ { component: createNewButton, toolbarSeparatorAfter: true },
{ component: openInAzurePortalButton }
]
).component();
@@ -143,45 +174,79 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
private async handleRegistrationsUpdated(): Promise {
const reg = this._controllerModel.controllerRegistration;
- if (reg) {
+ this.controllerProperties.instanceName = reg?.instanceName || this.controllerProperties.instanceName;
+ this.controllerProperties.resourceGroupName = reg?.resourceGroupName || this.controllerProperties.resourceGroupName;
+ this.controllerProperties.location = (await getAzurecoreApi()).getRegionDisplayName(reg?.location) || this.controllerProperties.location;
+ this.controllerProperties.subscriptionId = reg?.subscriptionId || this.controllerProperties.subscriptionId;
+ this.controllerProperties.connectionMode = getConnectionModeDisplayText(reg?.connectionMode) || this.controllerProperties.connectionMode;
+ this.controllerProperties.instanceNamespace = reg?.instanceNamespace || this.controllerProperties.instanceNamespace;
+ this._registrationsRetrieved = true;
+ this.refreshDisplayedProperties();
+
+ this._arcResourcesTable.data = this._controllerModel.registrations
+ .filter(r => r.instanceType !== ResourceType.dataControllers)
+ .map(r => {
+ const iconPath = getResourceTypeIcon(r.instanceType ?? '');
+ const imageComponent = this.modelView.modelBuilder.image()
+ .withProperties({
+ width: iconSize,
+ height: iconSize,
+ iconPath: iconPath,
+ iconHeight: iconSize,
+ iconWidth: iconSize
+ })
+ .component();
+ return [imageComponent, r.instanceName, resourceTypeToDisplayName(r.instanceType), r.vCores];
+ });
+ this._arcResourcesLoadingComponent.loading = false;
+ }
+
+ private handleEndpointsUpdated(endpoints: EndpointModel[]): void {
+ const controllerEndpoint = endpoints.find(endpoint => endpoint.name === Endpoints.controller);
+ this.controllerProperties.controllerEndpoint = controllerEndpoint?.endpoint || this.controllerProperties.controllerEndpoint;
+ this._endpointsRetrieved = true;
+ this.refreshDisplayedProperties();
+ }
+
+ private refreshDisplayedProperties(): void {
+ // Only update once we've retrieved all the necessary properties
+ if (this._endpointsRetrieved && this._registrationsRetrieved) {
this._propertiesContainer.propertyItems = [
{
displayName: loc.name,
- value: reg.instanceName || '-'
+ value: this.controllerProperties.instanceName
},
{
displayName: loc.resourceGroup,
- value: reg.resourceGroupName || '-'
+ value: this.controllerProperties.resourceGroupName
},
{
displayName: loc.region,
- value: (await getAzurecoreApi()).getRegionDisplayName(reg.location) || '-'
+ value: this.controllerProperties.location
},
{
displayName: loc.subscriptionId,
- value: reg.subscriptionId || '-'
+ value: this.controllerProperties.subscriptionId
},
{
displayName: loc.type,
value: loc.dataControllersType
},
{
- displayName: loc.coordinatorEndpoint,
- value: '-'
+ displayName: loc.controllerEndpoint,
+ value: this.controllerProperties.controllerEndpoint
},
{
displayName: loc.connectionMode,
- value: reg.connectionMode || '-'
+ value: this.controllerProperties.connectionMode
},
{
displayName: loc.namespace,
- value: reg.instanceNamespace || '-'
+ value: this.controllerProperties.instanceNamespace
}
];
+ this._propertiesLoadingComponent.loading = false;
}
- this._arcResourcesTable.data = this._controllerModel.registrations
- .filter(r => r.instanceType !== ResourceType.dataControllers)
- .map(r => [r.instanceName, resourceTypeToDisplayName(r.instanceType), r.vCores]);
}
}
diff --git a/extensions/arc/src/ui/dashboards/miaa/miaaConnectionStringsPage.ts b/extensions/arc/src/ui/dashboards/miaa/miaaConnectionStringsPage.ts
index e7de54d42c..38b0db9e3b 100644
--- a/extensions/arc/src/ui/dashboards/miaa/miaaConnectionStringsPage.ts
+++ b/extensions/arc/src/ui/dashboards/miaa/miaaConnectionStringsPage.ts
@@ -5,11 +5,10 @@
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
-import { IconPathHelper, cssStyles } from '../../../constants';
+import { IconPathHelper, cssStyles, ResourceType } from '../../../constants';
import { KeyValueContainer, KeyValue, InputKeyValue, MultilineInputKeyValue } from '../../components/keyValueContainer';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel, Registration } from '../../../models/controllerModel';
-import { ResourceType } from '../../../common/utils';
import { MiaaModel } from '../../../models/miaaModel';
export class MiaaConnectionStringsPage extends DashboardPage {
diff --git a/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts b/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts
index b6995af9d3..e14984da9c 100644
--- a/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts
+++ b/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts
@@ -6,9 +6,9 @@
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { DashboardPage } from '../../components/dashboardPage';
-import { IconPathHelper, cssStyles } from '../../../constants';
+import { IconPathHelper, cssStyles, ResourceType } from '../../../constants';
import { ControllerModel, Registration } from '../../../models/controllerModel';
-import { ResourceType, getAzurecoreApi } from '../../../common/utils';
+import { getAzurecoreApi } from '../../../common/utils';
import { MiaaModel, DatabaseModel } from '../../../models/miaaModel';
import { HybridSqlNsNameGetResponse } from '../../../controller/generated/v1/model/hybridSqlNsNameGetResponse';
import { EndpointModel } from '../../../controller/generated/v1/api';
diff --git a/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts b/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts
index be587e1fc5..dc583df589 100644
--- a/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts
+++ b/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts
@@ -6,12 +6,11 @@
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
-import { IconPathHelper, cssStyles } from '../../../constants';
+import { IconPathHelper, cssStyles, ResourceType } from '../../../constants';
import { DuskyObjectModelsDatabase, DuskyObjectModelsDatabaseServiceArcPayload, V1Pod } from '../../../controller/generated/dusky/api';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel, PodRole } from '../../../models/postgresModel';
-import { ResourceType } from '../../../common/utils';
export class PostgresOverviewPage extends DashboardPage {
private propertiesLoading?: azdata.LoadingComponent;
diff --git a/extensions/arc/src/ui/dashboards/postgres/postgresPropertiesPage.ts b/extensions/arc/src/ui/dashboards/postgres/postgresPropertiesPage.ts
index 60a79c041b..5271209bc8 100644
--- a/extensions/arc/src/ui/dashboards/postgres/postgresPropertiesPage.ts
+++ b/extensions/arc/src/ui/dashboards/postgres/postgresPropertiesPage.ts
@@ -6,12 +6,11 @@
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
-import { IconPathHelper, cssStyles } from '../../../constants';
+import { IconPathHelper, cssStyles, ResourceType } from '../../../constants';
import { KeyValueContainer, InputKeyValue, LinkKeyValue, TextKeyValue } from '../../components/keyValueContainer';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
-import { ResourceType } from '../../../common/utils';
export class PostgresPropertiesPage extends DashboardPage {
private keyValueContainer?: KeyValueContainer;
diff --git a/extensions/arc/src/ui/dashboards/postgres/postgresSupportRequestPage.ts b/extensions/arc/src/ui/dashboards/postgres/postgresSupportRequestPage.ts
index 7a32b56070..e7b8e76270 100644
--- a/extensions/arc/src/ui/dashboards/postgres/postgresSupportRequestPage.ts
+++ b/extensions/arc/src/ui/dashboards/postgres/postgresSupportRequestPage.ts
@@ -6,11 +6,10 @@
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
-import { IconPathHelper, cssStyles } from '../../../constants';
+import { IconPathHelper, cssStyles, ResourceType } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
-import { ResourceType } from '../../../common/utils';
export class PostgresSupportRequestPage extends DashboardPage {
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {