From c3fbce4b837dbfbf6077d593cdd9a5c573a2828d Mon Sep 17 00:00:00 2001 From: Charles Gagnon Date: Wed, 24 Jun 2020 15:15:27 -0700 Subject: [PATCH] Add dashboard links to arc controller dashboard (#11076) * Add dashboard links to arc controller dashboard * Fix compile error --- extensions/arc/src/models/controllerModel.ts | 8 +++---- .../controllerDashboardOverviewPage.ts | 17 +++++++++----- .../src/ui/tree/azureArcTreeDataProvider.ts | 22 +++++++++++++++++++ .../arc/src/ui/tree/controllerTreeNode.ts | 13 +++++++++++ 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/extensions/arc/src/models/controllerModel.ts b/extensions/arc/src/models/controllerModel.ts index 0b299c3788..a112446bf6 100644 --- a/extensions/arc/src/models/controllerModel.ts +++ b/extensions/arc/src/models/controllerModel.ts @@ -52,7 +52,7 @@ export class ControllerModel { return this._auth; } - constructor(private _treeDataProvider: AzureArcTreeDataProvider, public info: ControllerInfo, password?: string) { + constructor(public treeDataProvider: AzureArcTreeDataProvider, public info: ControllerInfo, password?: string) { this._endpointsRouter = new EndpointsRouterApi(this.info.url); this._tokenRouter = new TokenRouterApi(this.info.url); this._registrationRouter = new RegistrationRouterApi(this.info.url); @@ -68,17 +68,17 @@ export class ControllerModel { let password = ''; if (this.info.rememberPassword) { // It should be in the credentials store, get it from there - password = await this._treeDataProvider.getPassword(this.info); + password = await this.treeDataProvider.getPassword(this.info); } if (password) { this.setAuthentication(new BasicAuth(this.info.username, password)); } else { // No password yet so prompt for it from the user - const dialog = new ConnectToControllerDialog(this._treeDataProvider); + const dialog = new ConnectToControllerDialog(this.treeDataProvider); dialog.showDialog(this.info); const model = await dialog.waitForClose(); if (model) { - this._treeDataProvider.addOrUpdateController(model.controllerModel, model.password, false); + this.treeDataProvider.addOrUpdateController(model.controllerModel, model.password, false); this.setAuthentication(new BasicAuth(this.info.username, model.password)); } } diff --git a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts index bb81e404aa..e1b55e3c5a 100644 --- a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts +++ b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts @@ -9,7 +9,7 @@ import * as loc from '../../../localizedConstants'; import { DashboardPage } from '../../components/dashboardPage'; import { IconPathHelper, cssStyles, iconSize, ResourceType, Endpoints } from '../../../constants'; import { ControllerModel } from '../../../models/controllerModel'; -import { resourceTypeToDisplayName, getAzurecoreApi, getResourceTypeIcon, getConnectionModeDisplayText } from '../../../common/utils'; +import { resourceTypeToDisplayName, getAzurecoreApi, getResourceTypeIcon, getConnectionModeDisplayText, parseInstanceName } from '../../../common/utils'; import { RegistrationResponse } from '../../../controller/generated/v1/model/registrationResponse'; import { EndpointModel } from '../../../controller/generated/v1/api'; @@ -102,7 +102,7 @@ export class ControllerDashboardOverviewPage extends DashboardPage { }, { displayName: loc.name, - valueType: azdata.DeclarativeDataType.string, + valueType: azdata.DeclarativeDataType.component, width: '33%', isReadOnly: true, headerCssStyles: cssStyles.tableHeader, @@ -215,9 +215,16 @@ export class ControllerDashboardOverviewPage extends DashboardPage { iconPath: iconPath, iconHeight: iconSize, iconWidth: iconSize - }) - .component(); - return [imageComponent, r.instanceName, resourceTypeToDisplayName(r.instanceType), loc.numVCores(r.vCores)]; + }).component(); + const nameLink = this.modelView.modelBuilder.hyperlink() + .withProperties({ + label: r.instanceName || '', + url: '' + }).component(); + nameLink.onDidClick(async () => { + await this._controllerModel.treeDataProvider.openResourceDashboard(this._controllerModel, r.instanceType || '', r.instanceNamespace || '', parseInstanceName(r.instanceName)); + }); + return [imageComponent, nameLink, resourceTypeToDisplayName(r.instanceType), loc.numVCores(r.vCores)]; }); this._arcResourcesLoadingComponent.loading = false; } diff --git a/extensions/arc/src/ui/tree/azureArcTreeDataProvider.ts b/extensions/arc/src/ui/tree/azureArcTreeDataProvider.ts index 0942fee64a..d317e6e022 100644 --- a/extensions/arc/src/ui/tree/azureArcTreeDataProvider.ts +++ b/extensions/arc/src/ui/tree/azureArcTreeDataProvider.ts @@ -110,6 +110,28 @@ export class AzureArcTreeDataProvider implements vscode.TreeDataProvider node.model.info); await this._context.globalState.update(mementoToken, controllerInfo); } + + /** + * Opens the dashboard for the specified resource + * @param controllerModel The model for the controller containing the resource we want to open the dashboard for + * @param resourceType The resourceType for the resource + * @param namespace The namespace of the resource + * @param name The name of the resource + */ + public async openResourceDashboard(controllerModel: ControllerModel, resourceType: string, namespace: string, name: string): Promise { + const controllerNode = this._controllerNodes.find(n => n.model === controllerModel); + if (controllerNode) { + const resourceNode = controllerNode.getResourceNode(resourceType, namespace, name); + if (resourceNode) { + + } else { + console.log(`Couldn't find resource node for ${namespace}.${name} (${resourceType})`); + } + await resourceNode?.openDashboard(); + } else { + console.log('Couldn\'t find controller node for opening dashboard'); + } + } } function getCredentialId(info: ControllerInfo): string { diff --git a/extensions/arc/src/ui/tree/controllerTreeNode.ts b/extensions/arc/src/ui/tree/controllerTreeNode.ts index cd6d898cf5..70b1622164 100644 --- a/extensions/arc/src/ui/tree/controllerTreeNode.ts +++ b/extensions/arc/src/ui/tree/controllerTreeNode.ts @@ -52,6 +52,19 @@ export class ControllerTreeNode extends TreeNode { await controllerDashboard.showDashboard(); } + /** + * Finds and returns the ResourceTreeNode specified if it exists, otherwise undefined + * @param resourceType The resourceType of the node + * @param namespace The namespace of the node + * @param name The name of the node + */ + public getResourceNode(resourceType: string, namespace: string, name: string): ResourceTreeNode | undefined { + return this._children.find(c => + c.model?.info.resourceType === resourceType && + c.model?.info.namespace === namespace && + c.model.info.name === name); + } + private refreshChildren(registrations: Registration[]): void { const newChildren: ResourceTreeNode[] = []; registrations.forEach(registration => {