Skip to content

Commit 6f40f43

Browse files
authored
Create from Deploy feature and some local UX changes (#4130)
* merge from main * Add the unique step that got removed * ignore eslint any errors for now * Fix up some typings to fix the build * Some fixes for the tests * Remove local project UX changes * More reverting * Save files * Move create function button * Some clean up * Change label for new project * Add deploy button and context menu action * Remove extra create step * PR feedback
1 parent a6b2452 commit 6f40f43

16 files changed

+424
-189
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@
207207
"title": "%azureFunctions.deleteSlot%",
208208
"category": "Azure Functions"
209209
},
210+
{
211+
"command": "azureFunctions.deployProject",
212+
"title": "%azureFunctions.deployProject%",
213+
"category": "Azure Functions",
214+
"icon": "$(cloud-upload)",
215+
"enablement": "!virtualWorkspace"
216+
},
210217
{
211218
"command": "azureFunctions.deploy",
212219
"title": "%azureFunctions.deploy%",
@@ -389,16 +396,8 @@
389396
"group": "1_projects@3"
390397
},
391398
{
392-
"command": "azureFunctions.deploy",
399+
"command": "azureFunctions.deployProject",
393400
"group": "2_deploy@1"
394-
},
395-
{
396-
"command": "azureFunctions.createFunctionApp",
397-
"group": "3_create@1"
398-
},
399-
{
400-
"command": "azureFunctions.createFunctionAppAdvanced",
401-
"group": "3_create@2"
402401
}
403402
],
404403
"view/title": [
@@ -409,6 +408,26 @@
409408
}
410409
],
411410
"view/item/context": [
411+
{
412+
"command": "azureFunctions.createFunction",
413+
"when": "view == azureWorkspace && viewItem =~ /azFuncLocalProject/i",
414+
"group": "inline"
415+
},
416+
{
417+
"command": "azureFunctions.createFunction",
418+
"when": "view == azureWorkspace && viewItem =~ /azFuncLocalProject/i",
419+
"group": "1@1"
420+
},
421+
{
422+
"command": "azureFunctions.deployProject",
423+
"when": "view == azureWorkspace && viewItem =~ /azFuncLocalProject/i",
424+
"group": "inline"
425+
},
426+
{
427+
"command": "azureFunctions.deployProject",
428+
"when": "view == azureWorkspace && viewItem =~ /azFuncLocalProject/i",
429+
"group": "1@2"
430+
},
412431
{
413432
"command": "azureFunctions.createFunctionApp",
414433
"when": "view == azureResourceGroups && viewItem =~ /functionapp/i && viewItem =~ /azureResourceTypeGroup/i",
@@ -1114,7 +1133,7 @@
11141133
"id": "create",
11151134
"title": "%azureFunctions.walkthrough.functionsStart.create.title%",
11161135
"completionEvents": [
1117-
"onCommand:azureFunctions.createNewProject"
1136+
"onCommand:azureFunctions.createFunction"
11181137
],
11191138
"description": "%azureFunctions.walkthrough.functionsStart.create.description%",
11201139
"media": {
@@ -1204,7 +1223,7 @@
12041223
"@microsoft/vscode-azext-azureappsettings": "^0.2.1",
12051224
"@microsoft/vscode-azext-azureutils": "^3.0.0",
12061225
"@microsoft/vscode-azext-serviceconnector": "^0.1.3",
1207-
"@microsoft/vscode-azext-utils": "^2.3.1",
1226+
"@microsoft/vscode-azext-utils": "^2.5.0",
12081227
"@microsoft/vscode-azureresources-api": "^2.0.4",
12091228
"cross-fetch": "^4.0.0",
12101229
"escape-string-regexp": "^4.0.0",

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"azureFunctions.deleteFunction": "Delete Function...",
2525
"azureFunctions.deleteFunctionApp": "Delete Function App...",
2626
"azureFunctions.deleteSlot": "Delete Slot...",
27+
"azureFunctions.deployProject": "Deploy to Azure...",
2728
"azureFunctions.deploy": "Deploy to Function App...",
2829
"azureFunctions.deployByFunctionAppId": "Deploy to Function App by ID...",
2930
"azureFunctions.deploySlot": "Deploy to Slot...",

src/LocalResourceProvider.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
* Copyright (c) Microsoft Corporation. All rights reserved.
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
5-
import { type AzExtParentTreeItem, type AzExtTreeItem } from "@microsoft/vscode-azext-utils";
5+
import { GenericTreeItem, type AzExtParentTreeItem, type AzExtTreeItem } from "@microsoft/vscode-azext-utils";
66
import { type WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi";
77
import { Disposable } from "vscode";
8+
import { localize } from "./localize";
89
import { InitLocalProjectTreeItem } from "./tree/localProject/InitLocalProjectTreeItem";
910
import { InvalidLocalProjectTreeItem } from "./tree/localProject/InvalidLocalProjectTreeItem";
1011
import { LocalProjectTreeItem } from "./tree/localProject/LocalProjectTreeItem";
12+
import { treeUtils } from "./utils/treeUtils";
1113
import { listLocalProjects, type LocalProjectInternal } from "./workspace/listLocalProjects";
1214

1315
export class FunctionsLocalResourceProvider implements WorkspaceResourceProvider {
@@ -21,6 +23,7 @@ export class FunctionsLocalResourceProvider implements WorkspaceResourceProvider
2123
this._projectDisposables = [];
2224

2325
const localProjects = await listLocalProjects();
26+
let hasLocalProject = false;
2427

2528
for (const project of localProjects.initializedProjects) {
2629
const treeItem: LocalProjectTreeItem = new LocalProjectTreeItem(parent, project as LocalProjectInternal);
@@ -29,13 +32,26 @@ export class FunctionsLocalResourceProvider implements WorkspaceResourceProvider
2932
}
3033

3134
for (const unintializedProject of localProjects.unintializedProjects) {
35+
hasLocalProject = true;
3236
children.push(new InitLocalProjectTreeItem(parent, unintializedProject.projectPath, unintializedProject.workspaceFolder));
3337
}
3438

3539
for (const invalidProject of localProjects.invalidProjects) {
40+
hasLocalProject = true;
3641
children.push(new InvalidLocalProjectTreeItem(parent, invalidProject.projectPath, invalidProject.error, invalidProject.workspaceFolder));
3742
}
3843

44+
if (!hasLocalProject && children.length === 0) {
45+
const ti: GenericTreeItem = new GenericTreeItem(parent, {
46+
label: localize('createFunctionLocally', 'Create Function Project...'),
47+
commandId: 'azureFunctions.createNewProject',
48+
contextValue: 'createNewProject',
49+
iconPath: treeUtils.getThemedIconPath('CreateNewProject')
50+
});
51+
ti.commandArgs = [];
52+
children.push(ti);
53+
}
54+
3955
return children;
4056
}
4157
private _projectDisposables: Disposable[] = [];

src/agent/agentIntegration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export async function getCommands(): Promise<(WizardCommandConfig | SimpleComman
2323
{
2424
type: "simple",
2525
name: createFunctionProjectCommandName,
26-
commandId: "azureFunctions.createNewProject",
27-
displayName: "Create Function Project",
26+
commandId: "azureFunctions.createFunction",
27+
displayName: "Create Function Locally",
2828
intentDescription: "This is best when users ask to create a new function project in VS Code. They may also refer to creating a function project by asking to create a project based upon a function project template.",
2929
requiresAzureLogin: true,
3030
},

src/commands/SubscriptionListStep.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.md in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { AzureWizardPromptStep, type IAzureQuickPickItem } from "@microsoft/vscode-azext-utils";
7+
import { type AzureSubscription } from "@microsoft/vscode-azureresources-api";
8+
import { l10n } from "vscode";
9+
import { ext } from "../extensionVariables";
10+
import { type IFuncDeployContext } from "./deploy/deploy";
11+
12+
export class SubscriptionListStep extends AzureWizardPromptStep<IFuncDeployContext> {
13+
private _picks: IAzureQuickPickItem<AzureSubscription>[] = [];
14+
private _oneSubscription: boolean = false;
15+
public async prompt(context: IFuncDeployContext): Promise<void> {
16+
context.subscription = (await context.ui.showQuickPick(this._picks, { placeHolder: l10n.t("Select a subscription") })).data;
17+
}
18+
19+
public shouldPrompt(_: IFuncDeployContext): boolean {
20+
return !this._oneSubscription;
21+
}
22+
23+
public async configureBeforePrompt(context: IFuncDeployContext): Promise<void> {
24+
this._picks = await this.getPicks();
25+
// auto select if only one subscription
26+
if (this._picks.length === 1) {
27+
this._oneSubscription = true;
28+
context.subscription = this._picks[0].data;
29+
}
30+
}
31+
32+
private async getPicks(): Promise<IAzureQuickPickItem<AzureSubscription>[]> {
33+
return (await ext.rgApi.getSubscriptions(true)).map(s => {
34+
return { label: s.name, description: s.subscriptionId, data: s };
35+
});
36+
}
37+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { type IAppServiceWizardContext } from "@microsoft/vscode-azext-azureappservice";
7+
import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils";
8+
import { localize } from "../../localize";
9+
import { setConsumptionPlanProperties } from "./FunctionAppHostingPlanStep";
10+
import { type IFunctionAppWizardContext } from "./IFunctionAppWizardContext";
11+
12+
export class ConfigureCommonNamesStep extends AzureWizardPromptStep<IAppServiceWizardContext> {
13+
public async prompt(_context: IAppServiceWizardContext): Promise<void> {
14+
// do nothing, will be handled in configuration
15+
}
16+
17+
public shouldPrompt(_context: IAppServiceWizardContext): boolean {
18+
// never prompt
19+
return false;
20+
}
21+
22+
public async configureBeforePrompt(context: IFunctionAppWizardContext): Promise<void> {
23+
if (!context.advancedCreation) {
24+
const newName: string | undefined = await context.relatedNameTask;
25+
if (!newName) {
26+
throw new Error(localize('noUniqueName', 'Failed to generate unique name for resources. Use advanced creation to manually enter resource names.'));
27+
}
28+
context.newResourceGroupName = context.newResourceGroupName || newName;
29+
setConsumptionPlanProperties(context);
30+
context.newStorageAccountName = newName;
31+
context.newAppInsightsName = newName;
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)