Skip to content

Commit 59dc145

Browse files
committed
feat(sam): "Sync SAM" info if no bucket/stack/ECR items
Problem: The "Sync SAM" wizard has steps for S3, ECR, and CFN. If there are no items it is not obvious what to do. Solution: - For each step, - provide a "Open AWS Console" button - show a "No X items found. Click to open AWS Console" message.
1 parent c4f47a2 commit 59dc145

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "\"Sync SAM Application\" command provides Create and Help actions at each step (SAM template, S3 bucket, ECR repo, CloudFormation stack)"
4+
}

src/shared/awsConsole.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*!
2+
* Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as vscode from 'vscode'
7+
8+
export function getAwsConsoleUrl(service: 'ecr' | 'cloudformation', region: string): vscode.Uri {
9+
switch (service) {
10+
case 'ecr':
11+
return vscode.Uri.parse(`https://${region}.console.aws.amazon.com/ecr/repositories?region=${region}`)
12+
case 'cloudformation':
13+
return vscode.Uri.parse(`https://${region}.console.aws.amazon.com/cloudformation/home?region=${region}`)
14+
default:
15+
throw Error()
16+
}
17+
}

src/shared/sam/sync.ts

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { isAutomation } from '../vscode/env'
4242
import { getOverriddenParameters } from '../../lambda/config/parameterUtils'
4343
import { addTelemetryEnvVar } from './cli/samCliInvokerUtils'
4444
import { samSyncUrl, samInitDocUrl } from '../constants'
45+
import { getAwsConsoleUrl } from '../awsConsole'
4546

4647
const localize = nls.loadMessageBundle()
4748

@@ -71,13 +72,22 @@ function createBucketPrompter(client: DefaultS3Client) {
7172

7273
return createQuickPick(items, {
7374
title: 'Select an S3 Bucket',
74-
placeholder: 'Filter or enter a new bucket name',
75+
placeholder: 'Select a bucket (or enter a name to create one)',
7576
buttons: createCommonButtons(samSyncUrl),
7677
filterBoxInputSettings: {
7778
label: 'Create a New Bucket',
7879
// This is basically a hack. I need to refactor `createQuickPick` a bit.
7980
transform: v => prefixNewBucketName(v),
8081
},
82+
noItemsFoundItem: {
83+
label: localize(
84+
'aws.cfn.noStacks',
85+
'No S3 buckets for region "{0}". Enter a name to create a new one.',
86+
client.regionCode
87+
),
88+
data: undefined,
89+
onClick: undefined,
90+
},
8191
})
8292
}
8393

@@ -87,6 +97,7 @@ const canShowStack = (s: StackSummary) =>
8797

8898
function createStackPrompter(client: DefaultCloudFormationClient) {
8999
const recentStack = getRecentResponse(client.regionCode, 'stackName')
100+
const consoleUrl = getAwsConsoleUrl('cloudformation', client.regionCode)
90101
const items = client.listAllStacks().map(stacks =>
91102
stacks.filter(canShowStack).map(s => ({
92103
label: s.StackName,
@@ -99,17 +110,27 @@ function createStackPrompter(client: DefaultCloudFormationClient) {
99110

100111
return createQuickPick(items, {
101112
title: 'Select a CloudFormation Stack',
102-
placeholder: 'Filter or enter a new stack name',
113+
placeholder: 'Select a stack (or enter a name to create one)',
103114
filterBoxInputSettings: {
104115
label: 'Create a New Stack',
105116
transform: v => v,
106117
},
107-
buttons: createCommonButtons(samSyncUrl),
118+
buttons: createCommonButtons(samSyncUrl, consoleUrl),
119+
noItemsFoundItem: {
120+
label: localize(
121+
'aws.cfn.noStacks',
122+
'No stacks in region "{0}". Enter a name to create a new one.',
123+
client.regionCode
124+
),
125+
data: undefined,
126+
onClick: undefined,
127+
},
108128
})
109129
}
110130

111131
function createEcrPrompter(client: DefaultEcrClient) {
112132
const recentEcrRepo = getRecentResponse(client.regionCode, 'ecrRepoUri')
133+
const consoleUrl = getAwsConsoleUrl('ecr', client.regionCode)
113134
const items = client.listAllRepositories().map(list =>
114135
list.map(repo => ({
115136
label: repo.repositoryName,
@@ -121,12 +142,21 @@ function createEcrPrompter(client: DefaultEcrClient) {
121142

122143
return createQuickPick(items, {
123144
title: 'Select an ECR Repository',
124-
placeholder: 'Filter or enter an existing repository URI',
125-
buttons: createCommonButtons(samSyncUrl),
145+
placeholder: 'Select a repository (or enter repository URI)',
146+
buttons: createCommonButtons(samSyncUrl, consoleUrl),
126147
filterBoxInputSettings: {
127148
label: 'Existing repository URI',
128149
transform: v => v,
129150
},
151+
noItemsFoundItem: {
152+
label: localize(
153+
'aws.ecr.noRepos',
154+
'No ECR repositories in region "{0}". Enter a name to create a new one.',
155+
client.regionCode
156+
),
157+
data: undefined,
158+
onClick: undefined,
159+
},
130160
})
131161
}
132162

@@ -141,6 +171,7 @@ export function createEnvironmentPrompter(config: SamConfig, environments = conf
141171

142172
return createQuickPick(items, {
143173
title: 'Select an Environment to Use',
174+
placeholder: 'Select an environment',
144175
buttons: createCommonButtons(samSyncUrl),
145176
})
146177
}

src/shared/ui/buttons.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import * as nls from 'vscode-nls'
88
import { documentationUrl } from '../constants'
99
import { getIcon } from '../icons'
1010
import { WizardControl, WIZARD_EXIT, WIZARD_RETRY } from '../wizards/wizard'
11+
import { getIdeProperties } from '../extensionUtilities'
1112

1213
const localize = nls.loadMessageBundle()
1314
const helpTooltip = localize('AWS.command.help', 'View Toolkit Documentation')
15+
const awsConsoleTooltip = () => localize('AWS.button.awsConsole', 'Open {0} Console', getIdeProperties().company)
1416

1517
type WizardButton<T> = QuickInputButton<T | WizardControl> | QuickInputButton<void>
1618
export type PrompterButtons<T> = readonly WizardButton<T>[]
@@ -109,6 +111,14 @@ export function createBackButton(): QuickInputButton<WizardControl> {
109111
return vscode.QuickInputButtons.Back as QuickInputButton<WizardControl>
110112
}
111113

114+
export function createAwsConsoleButton(
115+
uri: string | vscode.Uri,
116+
tooltip: string = awsConsoleTooltip()
117+
): QuickInputLinkButton {
118+
const iconPath = getIcon('vscode-link-external')
119+
return new QuickInputLinkButton(uri, iconPath, tooltip)
120+
}
121+
112122
export function createExitButton(): QuickInputButton<WizardControl> {
113123
return {
114124
iconPath: getIcon('vscode-close'),
@@ -137,8 +147,14 @@ export function createPlusButton(tooltip?: string): QuickInputButton<void> {
137147
* Currently has: 'help', 'exit', and 'back'
138148
*
139149
* @param helpUri optional URI to link to for the 'help' button (see {@link createHelpButton} for defaults)
150+
* @param awsConsoleUri optional URI to AWS web console
140151
* @returns An array of buttons
141152
*/
142-
export function createCommonButtons(helpUri?: string | vscode.Uri): PrompterButtons<WizardControl> {
143-
return [createHelpButton(helpUri), createBackButton(), createExitButton()]
153+
export function createCommonButtons(
154+
helpUri?: string | vscode.Uri,
155+
awsConsoleUri?: string | vscode.Uri
156+
): PrompterButtons<WizardControl> {
157+
const buttons2 = [createHelpButton(helpUri), createBackButton(), createExitButton()]
158+
const buttons1: typeof buttons2 = awsConsoleUri ? [createAwsConsoleButton(awsConsoleUri)] : []
159+
return buttons1.concat(buttons2)
144160
}

0 commit comments

Comments
 (0)