From 007bc7918ed5ecdd6534fe332aa1b53ef8cfb067 Mon Sep 17 00:00:00 2001 From: "Alex Yang [MSFT]" <59073590+alexyaang@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:41:37 -0400 Subject: [PATCH] Throw Better Error when running registries commands when No Registries are Connected (#4101) * fix genericV2 root not showing up when adding registry * throw good error when no registries are connected * use hasTrackedRegistries function * use npm dot com --- package-lock.json | 8 ++--- package.json | 2 +- .../genericV2/addTrackedGenericV2Registry.ts | 9 ++++- .../removeTrackedGenericV2Registry.ts | 2 +- .../registries/ConnectRegistryTreeItem.ts | 33 +++++++++++++++++++ .../UnifiedRegistryTreeDataProvider.ts | 15 ++------- src/utils/registryExperience.ts | 21 ++++++++++-- 7 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 src/tree/registries/ConnectRegistryTreeItem.ts diff --git a/package-lock.json b/package-lock.json index 0185dbf2b5..8eb41ee63c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@microsoft/vscode-azext-azureutils": "^2.0.0", "@microsoft/vscode-azext-utils": "^2.1.1", "@microsoft/vscode-container-client": "^0.1.0", - "@microsoft/vscode-docker-registries": "^0.1.1", + "@microsoft/vscode-docker-registries": "^0.1.2", "dayjs": "^1.11.7", "dockerfile-language-server-nodejs": "^0.11.0", "fs-extra": "^11.1.1", @@ -812,9 +812,9 @@ } }, "node_modules/@microsoft/vscode-docker-registries": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-docker-registries/-/vscode-docker-registries-0.1.1.tgz", - "integrity": "sha512-cDO8iMTtx0wsBfN4MHWJimv8JQggx1SjRsbksaJoU3VUmsR55EypSKenSAZf9TvNLy2kKQzguihYzAQCNXQedw==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@microsoft/vscode-docker-registries/-/vscode-docker-registries-0.1.2.tgz", + "integrity": "sha512-NWy0VYHZq7g+RbJWUrcre+1/DzObhMBUmPfZo/1zZMS4vHVqpQzVlSnnbLilK2Xl0+XnwKDSjp7zY7XbOMCTvg==", "dependencies": { "dayjs": "^1.11.7", "node-fetch": "^2.6.11" diff --git a/package.json b/package.json index 73c3732750..b0d39f82d5 100644 --- a/package.json +++ b/package.json @@ -3007,7 +3007,7 @@ "@microsoft/vscode-azext-azureutils": "^2.0.0", "@microsoft/vscode-azext-utils": "^2.1.1", "@microsoft/vscode-container-client": "^0.1.0", - "@microsoft/vscode-docker-registries": "^0.1.1", + "@microsoft/vscode-docker-registries": "^0.1.2", "dayjs": "^1.11.7", "dockerfile-language-server-nodejs": "^0.11.0", "fs-extra": "^11.1.1", diff --git a/src/commands/registries/genericV2/addTrackedGenericV2Registry.ts b/src/commands/registries/genericV2/addTrackedGenericV2Registry.ts index 91baad9b44..801966c25f 100644 --- a/src/commands/registries/genericV2/addTrackedGenericV2Registry.ts +++ b/src/commands/registries/genericV2/addTrackedGenericV2Registry.ts @@ -8,7 +8,14 @@ import { ext } from "../../../extensionVariables"; import { UnifiedRegistryItem } from "../../../tree/registries/UnifiedRegistryTreeDataProvider"; export async function addTrackedGenericV2Registry(context: IActionContext, node?: UnifiedRegistryItem): Promise { - await ext.genericRegistryV2DataProvider.addTrackedRegistry(); + // if there are already registries, add a new registry to the existing root node + if (ext.genericRegistryV2DataProvider.hasTrackedRegistries()) { + await ext.genericRegistryV2DataProvider.addTrackedRegistry(); + } else { + // if there are no registries, connect as usual + await ext.registriesTree.connectRegistryProvider(ext.genericRegistryV2DataProvider); + } + // don't wait void ext.registriesTree.refresh(); } diff --git a/src/commands/registries/genericV2/removeTrackedGenericV2Registry.ts b/src/commands/registries/genericV2/removeTrackedGenericV2Registry.ts index 93dbe84464..de830a2549 100644 --- a/src/commands/registries/genericV2/removeTrackedGenericV2Registry.ts +++ b/src/commands/registries/genericV2/removeTrackedGenericV2Registry.ts @@ -20,7 +20,7 @@ export async function removeTrackedGenericV2Registry(context: IActionContext, no await ext.genericRegistryV2DataProvider.removeTrackedRegistry(node.wrappedItem); // remove the provider if it's the last one - if ((await ext.genericRegistryV2DataProvider.getRegistries(node.parent.wrappedItem)).length === 0) { + if (!ext.genericRegistryV2DataProvider.hasTrackedRegistries()) { await ext.registriesTree.disconnectRegistryProvider(node.parent); } diff --git a/src/tree/registries/ConnectRegistryTreeItem.ts b/src/tree/registries/ConnectRegistryTreeItem.ts new file mode 100644 index 0000000000..036c5957ee --- /dev/null +++ b/src/tree/registries/ConnectRegistryTreeItem.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CommonRegistryItem, isCommonRegistryItem } from '@microsoft/vscode-docker-registries'; +import * as vscode from 'vscode'; +import { UnifiedRegistryItem } from "./UnifiedRegistryTreeDataProvider"; + +export const ConnectRegistryContextValue: string = 'connectregistry'; + +export function isConnectRegistryTreeItem(item: unknown): item is UnifiedRegistryItem { + return isCommonRegistryItem(item) && item.type === ConnectRegistryContextValue; +} + +/** + * Creates a tree item that can be used to connect a new registry + */ +export function getConnectRegistryTreeItem(): UnifiedRegistryItem { + return { + provider: undefined, + parent: undefined, + wrappedItem: { + label: vscode.l10n.t('Connect Registry...'), + type: ConnectRegistryContextValue, + iconPath: new vscode.ThemeIcon('plug'), + command: { + command: 'vscode-docker.registries.connectRegistry' + }, + parent: undefined + } + }; +} diff --git a/src/tree/registries/UnifiedRegistryTreeDataProvider.ts b/src/tree/registries/UnifiedRegistryTreeDataProvider.ts index f4d23218bc..cbc87a93a8 100644 --- a/src/tree/registries/UnifiedRegistryTreeDataProvider.ts +++ b/src/tree/registries/UnifiedRegistryTreeDataProvider.ts @@ -2,6 +2,7 @@ import { CommonRegistry, CommonRegistryRoot, RegistryDataProvider, isCommonRegis import * as vscode from 'vscode'; import { ext } from '../../extensionVariables'; import { isAzureSubscriptionRegistryItem } from './Azure/AzureRegistryDataProvider'; +import { getConnectRegistryTreeItem } from './ConnectRegistryTreeItem'; interface WrappedElement { // eslint-disable-next-line @typescript-eslint/naming-convention @@ -85,18 +86,8 @@ export class UnifiedRegistryTreeDataProvider implements vscode.TreeDataProvider< // if there are no connected providers, show a command to connect one if (unifiedRegistryItems.length === 0) { - unifiedRegistryItems.push({ - provider: undefined, - wrappedItem: { - label: vscode.l10n.t('Connect Registry...'), - type: 'connectregistry', - iconPath: new vscode.ThemeIcon('plug'), - command: { - command: 'vscode-docker.registries.connectRegistry' - } - }, - parent: undefined, - }); + const connectRegistryItem = getConnectRegistryTreeItem(); + unifiedRegistryItems.push(connectRegistryItem); } } diff --git a/src/utils/registryExperience.ts b/src/utils/registryExperience.ts index 8eaf81aa47..0bd1b99f9a 100644 --- a/src/utils/registryExperience.ts +++ b/src/utils/registryExperience.ts @@ -3,10 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { AzureWizardPromptStep, ContextValueFilterQuickPickOptions, GenericQuickPickStep, IActionContext, PickFilter, QuickPickWizardContext, RecursiveQuickPickStep, runQuickPickWizard } from '@microsoft/vscode-azext-utils'; +import { AzureWizardPromptStep, ContextValueFilterQuickPickOptions, GenericQuickPickStep, IActionContext, PickFilter, QuickPickWizardContext, RecursiveQuickPickStep, UserCancelledError, runQuickPickWizard } from '@microsoft/vscode-azext-utils'; import { CommonRegistryItem } from '@microsoft/vscode-docker-registries'; -import { TreeItem, l10n } from 'vscode'; +import { MessageItem, TreeItem, commands, l10n, window } from 'vscode'; import { ext } from '../extensionVariables'; +import { isConnectRegistryTreeItem } from '../tree/registries/ConnectRegistryTreeItem'; import { UnifiedRegistryItem, UnifiedRegistryTreeDataProvider } from '../tree/registries/UnifiedRegistryTreeDataProvider'; export interface RegistryFilter { @@ -27,6 +28,22 @@ export interface RegistryExperienceOptions extends Partial(context: IActionContext, options?: RegistryExperienceOptions): Promise> { + const registryRoots = await ext.registriesTree.getChildren(); + // if there are no registry providers, throw an error with option to connect a registry provider + if (registryRoots.length === 0 || (registryRoots.length === 1 && isConnectRegistryTreeItem(registryRoots[0].wrappedItem))) { + const add: MessageItem = { title: l10n.t('Connect Registry...') }; + void window.showErrorMessage( + l10n.t('No registry providers are connected. Please connect a registry provider to continue.'), + ...[add]) + .then((result) => { + if (result === add) { + void commands.executeCommand('vscode-docker.registries.connectRegistry'); + } + }); + + throw new UserCancelledError(); + } + // get the registry provider unified item const promptSteps: AzureWizardPromptStep[] = [ new RegistryQuickPickStep(ext.registriesTree, options)