diff --git a/package.json b/package.json index 239f6e31..803e9fb2 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,12 @@ "title": "%azureResourceGroups.logIn%", "category": "Azure" }, + { + "command": "azureTenantsView.addAccount", + "title": "%azureTenantsView.addAccount%", + "category": "Azure", + "icon": "$(add)" + }, { "command": "azureResourceGroups.selectSubscriptions", "title": "%azureResourceGroups.selectSubscriptions%", @@ -392,6 +398,11 @@ "submenu": "azureWorkspaceCreate", "when": "view == azureWorkspace", "group": "navigation@1" + }, + { + "command": "azureTenantsView.addAccount", + "when": "view == azureTenantsView", + "group": "navigation@1" } ], "view/item/context": [ @@ -511,6 +522,10 @@ { "command": "azureResourceGroups.installExtension", "when": "never" + }, + { + "command": "azureTenantsView.addAccount", + "when": "never" } ], "azureResourceGroups.groupBy": [ diff --git a/package.nls.json b/package.nls.json index e9f88088..e544f7e2 100644 --- a/package.nls.json +++ b/package.nls.json @@ -3,6 +3,7 @@ "azureResourceGroups.cloudShellPowerShell": "Azure Cloud Shell (PowerShell)", "azureResourceGroups.uploadToCloudShell": "Upload to Cloud Shell", "azureResourceGroups.logIn": "Sign In", + "azureTenantsView.addAccount": "Add account", "azureResourceGroups.signInToTenant": "Sign in to Tenant (Directory)...", "azureResourceGroups.selectSubscriptions": "Select Subscriptions...", "azureResourceGroups.createResourceGroup": "Create Resource Group...", diff --git a/src/commands/registerCommands.ts b/src/commands/registerCommands.ts index 6436b10a..e3fa93bf 100644 --- a/src/commands/registerCommands.ts +++ b/src/commands/registerCommands.ts @@ -79,6 +79,7 @@ export function registerCommands(): void { registerCommand('azureResourceGroups.unfocusGroup', unfocusGroup); registerCommand('azureResourceGroups.logIn', (context: IActionContext) => logIn(context)); + registerCommand('azureTenantsView.addAccount', (context: IActionContext) => logIn(context)); registerCommand('azureResourceGroups.selectSubscriptions', (context: IActionContext, options: SelectSubscriptionOptions) => selectSubscriptions(context, options)); registerCommand('azureResourceGroups.signInToTenant', async () => signInToTenant(await ext.subscriptionProviderFactory())); diff --git a/src/tree/tenants/TenantResourceTreeDataProvider.ts b/src/tree/tenants/TenantResourceTreeDataProvider.ts index 74aae739..744e3cb3 100644 --- a/src/tree/tenants/TenantResourceTreeDataProvider.ts +++ b/src/tree/tenants/TenantResourceTreeDataProvider.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { AzureSubscriptionProvider, getConfiguredAuthProviderId } from '@microsoft/vscode-azext-azureauth'; -import { nonNullProp, nonNullValueAndProp } from '@microsoft/vscode-azext-utils'; +import { callWithTelemetryAndErrorHandling, IActionContext, nonNullProp, nonNullValueAndProp } from '@microsoft/vscode-azext-utils'; import { ResourceModelBase } from 'api/src'; import * as vscode from 'vscode'; import { TenantResourceProviderManager } from '../../api/ResourceProviderManagers'; @@ -43,36 +43,39 @@ export class TenantResourceTreeDataProvider extends ResourceTreeDataProviderBase } async onGetChildren(element?: ResourceGroupsItem | undefined): Promise { - if (element) { - return await element.getChildren(); - } else { - const subscriptionProvider = await getAzureSubscriptionProvider(this); - const children: ResourceGroupsItem[] = await OnGetChildrenBase(subscriptionProvider); + return await callWithTelemetryAndErrorHandling('azureTenantsView.getChildren', async (context: IActionContext) => { + if (element) { + return await element.getChildren(); + } else { + const subscriptionProvider = await getAzureSubscriptionProvider(this); + const children: ResourceGroupsItem[] = await OnGetChildrenBase(subscriptionProvider); - if (children.length === 0) { - const accounts = await vscode.authentication.getAccounts(getConfiguredAuthProviderId()); - for (const account of accounts) { - const tenants = await subscriptionProvider.getTenants(account); - const tenantItems: ResourceGroupsItem[] = []; - for await (const tenant of tenants) { - const isSignedIn = await subscriptionProvider.isSignedIn(nonNullProp(tenant, 'tenantId'), account); - tenantItems.push(new TenantTreeItem(tenant, account, { - contextValue: isSignedIn ? 'tenantName' : 'tenantNameNotSignedIn', - checkboxState: (!isSignedIn || isTenantFilteredOut(nonNullProp(tenant, 'tenantId'), account.id)) ? - vscode.TreeItemCheckboxState.Unchecked : vscode.TreeItemCheckboxState.Checked, - description: tenant.tenantId + if (children.length === 0) { + const accounts = await vscode.authentication.getAccounts(getConfiguredAuthProviderId()); + context.telemetry.properties.accountCount = accounts.length.toString(); + for (const account of accounts) { + const tenants = await subscriptionProvider.getTenants(account); + const tenantItems: ResourceGroupsItem[] = []; + for await (const tenant of tenants) { + const isSignedIn = await subscriptionProvider.isSignedIn(nonNullProp(tenant, 'tenantId'), account); + tenantItems.push(new TenantTreeItem(tenant, account, { + contextValue: isSignedIn ? 'tenantName' : 'tenantNameNotSignedIn', + checkboxState: (!isSignedIn || isTenantFilteredOut(nonNullProp(tenant, 'tenantId'), account.id)) ? + vscode.TreeItemCheckboxState.Unchecked : vscode.TreeItemCheckboxState.Checked, + description: tenant.tenantId + })); + } + + children.push(new GenericItem(nonNullValueAndProp(account, 'label'), { + children: tenantItems, + iconPath: new vscode.ThemeIcon('account'), + contextValue: 'accountName', + collapsibleState: vscode.TreeItemCollapsibleState.Expanded, })); } - - children.push(new GenericItem(nonNullValueAndProp(account, 'label'), { - children: tenantItems, - iconPath: new vscode.ThemeIcon('account'), - contextValue: 'accountName', - collapsibleState: vscode.TreeItemCollapsibleState.Expanded, - })); } + return children; } - return children; - } + }); } } diff --git a/src/tree/tenants/registerTenantTree.ts b/src/tree/tenants/registerTenantTree.ts index 61b39e3a..25ad4e0d 100644 --- a/src/tree/tenants/registerTenantTree.ts +++ b/src/tree/tenants/registerTenantTree.ts @@ -50,14 +50,16 @@ export function registerTenantTree(context: vscode.ExtensionContext, options: Re return tenantResourceTreeDataProvider; } -async function updateTenantsSetting(_context: IActionContext, tenants: vscode.TreeCheckboxChangeEvent) { +async function updateTenantsSetting(context: IActionContext, tenants: vscode.TreeCheckboxChangeEvent) { const unselectedTenants = getUnselectedTenants(); const unselectedTenantsSet = new Set(unselectedTenants); for (const [tenantTreeItem, state] of tenants.items) { if (state === vscode.TreeItemCheckboxState.Unchecked) { + context.telemetry.properties.uncheckedTenant = 'true'; unselectedTenantsSet.add(getKeyForTenant(tenantTreeItem.tenantId, tenantTreeItem.account.id)); } else if (state === vscode.TreeItemCheckboxState.Checked) { + context.telemetry.properties.checkedTenant = 'true'; const treeItem = await tenantTreeItem.getTreeItem(); if (treeItem?.contextValue === 'tenantNameNotSignedIn') { await vscode.commands.executeCommand('azureTenantsView.signInToTenant', tenantTreeItem);