Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vscode): Logic App and Workflows As Menu Items #6310

Merged
merged 33 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
31f64d6
Moved creation of new logic app and new workflows as right click menu…
lambrianmsft Dec 27, 2024
2c42e4b
Corrected opening of newly created workspace
lambrianmsft Dec 27, 2024
d9dfaa1
Added logic app project conversion to workspace and ensuring workspac…
lambrianmsft Dec 28, 2024
3fac56d
Updated console output messages
lambrianmsft Dec 28, 2024
86ff8c0
Added validation so that there can not be conflicting logic app or fu…
lambrianmsft Dec 30, 2024
edff132
Do not prompt for parameterization if there is nothing in the connect…
lambrianmsft Dec 31, 2024
8037c3c
Updated to use constant. Added check for workflow.json and the right …
lambrianmsft Dec 31, 2024
f4b0549
Adding logic app name to the panel as the workspace can have multiple…
lambrianmsft Jan 3, 2025
2c5739f
Merge branch 'main' into logic_app_and_workflow_menu
lambrianmsft Jan 3, 2025
e387fe1
Revert changes to strings.json
lambrianmsft Jan 3, 2025
7080e93
Merge branch 'main' into logic_app_and_workflow_menu
hartra344 Jan 6, 2025
5bf83a1
Updated convert to nuget project to have logic app project selection …
lambrianmsft Jan 8, 2025
be8e209
Merge branch 'logic_app_and_workflow_menu' of https://github.com/lamb…
lambrianmsft Jan 8, 2025
19c5afc
Merge branch 'main' into logic_app_and_workflow_menu
lambrianmsft Jan 9, 2025
0608c55
Fix for creating a new workspace when vscode has no folders loaded
lambrianmsft Jan 10, 2025
856aba6
Added additional check so that the ConvertToWorkspace prompt does not…
lambrianmsft Jan 14, 2025
f1f7a6f
Revert changes to strings.json and other files
lambrianmsft Jan 14, 2025
1578be8
Merge branch 'main' into logic_app_and_workflow_menu
lambrianmsft Jan 14, 2025
381b6e3
Added additional check to prevent create new project from triggering …
lambrianmsft Jan 14, 2025
e719e18
Merge branch 'main' into logic_app_and_workflow_menu
lambrianmsft Jan 15, 2025
89aa889
Correcting comments
lambrianmsft Jan 15, 2025
ee7fa15
Update to return boolean instead of using telemetry
lambrianmsft Jan 17, 2025
077afae
Update apps/vs-code-designer/src/app/commands/workflows/switchToDotne…
lambrianmsft Jan 21, 2025
0eb48e2
Update apps/vs-code-designer/src/app/commands/createNewCodeProject/Co…
lambrianmsft Jan 21, 2025
8626a29
Update apps/vs-code-designer/src/app/commands/workflows/switchToDotne…
lambrianmsft Jan 21, 2025
e986f28
Update apps/vs-code-designer/src/app/commands/createNewCodeProject/cr…
lambrianmsft Jan 21, 2025
deb12d3
Update apps/vs-code-designer/src/app/commands/createNewCodeProject/cr…
lambrianmsft Jan 21, 2025
d1a3346
Update apps/vs-code-designer/src/app/commands/createNewCodeProject/cr…
lambrianmsft Jan 21, 2025
bdd066c
Update apps/vs-code-designer/src/app/commands/createNewCodeProject/Co…
lambrianmsft Jan 21, 2025
9a299b6
Update apps/vs-code-designer/src/app/commands/createNewCodeProject/Co…
lambrianmsft Jan 21, 2025
713c2da
Merge branch 'main' into logic_app_and_workflow_menu
ccastrotrejo Jan 24, 2025
d7e9c58
Update strings
lambrianmsft Jan 24, 2025
e6405e4
Update another string
lambrianmsft Jan 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { extensionCommand, funcVersionSetting } from '../../../../constants';
import { localize } from '../../../../localize';
import { addLocalFuncTelemetry, tryGetLocalFuncVersion, tryParseFuncVersion } from '../../../utils/funcCoreTools/funcVersion';
import { getGlobalSetting } from '../../../utils/vsCodeConfig/settings';
import { FolderListStep } from '../../createNewProject/createProjectSteps/FolderListStep';
import { OpenFolderStepCodeProject } from './OpenFolderStepCodeProject';
import { AzureWizard, DialogResponses } from '@microsoft/vscode-azext-utils';
import type { IActionContext } from '@microsoft/vscode-azext-utils';
import { latestGAVersion } from '@microsoft/vscode-extension-logic-apps';
import type { IFunctionWizardContext } from '@microsoft/vscode-extension-logic-apps';
import * as vscode from 'vscode';
import { window } from 'vscode';
import { getWorkspaceFile, getWorkspaceFileInParentDirectory, getWorkspaceFolder, getWorkspaceRoot } from '../../../utils/workspace';
import { SetWorkspaceName } from './SetWorkspaceName';
import { SetWorkspaceContents } from './SetWorkspaceContents';
import { isLogicAppProjectInRoot } from '../../../utils/verifyIsProject';

export async function ConvertToWorkspace(context: IActionContext): Promise<boolean> {
const workspaceFolder = await getWorkspaceFolder(context, undefined, true);
if (await isLogicAppProjectInRoot(workspaceFolder)) {
addLocalFuncTelemetry(context);

const version: string = getGlobalSetting(funcVersionSetting) || (await tryGetLocalFuncVersion()) || latestGAVersion;
const wizardContext: Partial<IFunctionWizardContext> & IActionContext = Object.assign(context, {
version: tryParseFuncVersion(version),
});
context.telemetry.properties.isWorkspace = 'false';
wizardContext.workspaceCustomFilePath =
(await getWorkspaceFile(wizardContext)) ?? (await getWorkspaceFileInParentDirectory(wizardContext));
//save uri variable for open project folder command
wizardContext.customWorkspaceFolderPath = await getWorkspaceRoot(wizardContext);
if (wizardContext.workspaceCustomFilePath && !wizardContext.customWorkspaceFolderPath) {
const message = localize(
'openContainingWorkspace',
`Full functionality of the Azure Logic Apps (Standard) extension is available only when the workspace is opened. Workspace found at ${wizardContext.workspaceCustomFilePath} that contains the logic app project. Do you want to open the workspace before continuing?`
lambrianmsft marked this conversation as resolved.
Show resolved Hide resolved
lambrianmsft marked this conversation as resolved.
Show resolved Hide resolved
);
const result = await vscode.window.showInformationMessage(message, { modal: true }, DialogResponses.yes, DialogResponses.no);
if (result === DialogResponses.yes) {
await vscode.commands.executeCommand(extensionCommand.vscodeOpenFolder, vscode.Uri.file(wizardContext.workspaceCustomFilePath));
context.telemetry.properties.openContainingWorkspace = 'true';
return true;
}
context.telemetry.properties.openContainingWorkspace = 'false';
return false;
}
if (!wizardContext.workspaceCustomFilePath && !wizardContext.customWorkspaceFolderPath) {
const message = localize(
'createContainingWorkspace',
'Full functionality of the Azure Logic Apps (Standard) extension is available only when logic app project(s) are inside a workspace. Your project(s) will be copied over to the new workspace. Do you want to create the workspace before continuing?'
lambrianmsft marked this conversation as resolved.
Show resolved Hide resolved
lambrianmsft marked this conversation as resolved.
Show resolved Hide resolved
);
const result = await vscode.window.showInformationMessage(message, { modal: true }, DialogResponses.yes, DialogResponses.no);
if (result === DialogResponses.yes) {
const workspaceWizard: AzureWizard<IFunctionWizardContext> = new AzureWizard(wizardContext, {
title: localize('convertToWorkspace', 'Convert To Workspace'),
lambrianmsft marked this conversation as resolved.
Show resolved Hide resolved
promptSteps: [new FolderListStep(), new SetWorkspaceName(), new SetWorkspaceContents()],
executeSteps: [new OpenFolderStepCodeProject()],
});

await workspaceWizard.prompt();
await workspaceWizard.execute();
context.telemetry.properties.createContainingWorkspace = 'true';
window.showInformationMessage(localize('finishedConvertingWorkspace', 'Finished converting to workspace.'));
return true;
}
context.telemetry.properties.createContainingWorkspace = 'false';
return false;
}
context.telemetry.properties.isWorkspace = 'true';
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { funcVersionSetting, projectLanguageSetting, projectOpenBehaviorSetting, projectTemplateKeySetting } from '../../../../constants';
import { localize } from '../../../../localize';
import { createArtifactsFolder } from '../../../utils/codeless/artifacts';
import { addLocalFuncTelemetry, tryGetLocalFuncVersion, tryParseFuncVersion } from '../../../utils/funcCoreTools/funcVersion';
import { getGlobalSetting, getWorkspaceSetting } from '../../../utils/vsCodeConfig/settings';
import { FolderListStep } from '../../createNewProject/createProjectSteps/FolderListStep';
import { OpenFolderStepCodeProject } from './OpenFolderStepCodeProject';
import { AzureWizard } from '@microsoft/vscode-azext-utils';
import type { IActionContext } from '@microsoft/vscode-azext-utils';
import { latestGAVersion, OpenBehavior, ProjectType } from '@microsoft/vscode-extension-logic-apps';
import type { ICreateFunctionOptions, IFunctionWizardContext, ProjectLanguage } from '@microsoft/vscode-extension-logic-apps';
import * as fse from 'fs-extra';
import * as path from 'path';
import { window } from 'vscode';

export async function createRulesFiles(context: IFunctionWizardContext): Promise<void> {
if (context.projectType === ProjectType.rulesEngine) {
const xmlTemplatePath = path.join(__dirname, 'assets', 'RuleSetProjectTemplate', 'SampleRuleSet');
const xmlRuleSetPath = path.join(context.projectPath, 'Artifacts', 'Rules', 'SampleRuleSet.xml');
const xmlTemplateContent = await fse.readFile(xmlTemplatePath, 'utf-8');
const xmlFileContent = xmlTemplateContent.replace(/<%= methodName %>/g, context.methodName);
await fse.writeFile(xmlRuleSetPath, xmlFileContent);
}
}

export async function createLibFolder(context: IFunctionWizardContext): Promise<void> {
fse.mkdirSync(path.join(context.projectPath, 'lib', 'builtinOperationSdks', 'JAR'), { recursive: true });
fse.mkdirSync(path.join(context.projectPath, 'lib', 'builtinOperationSdks', 'net472'), { recursive: true });
fse.mkdirSync(path.join(context.projectPath, 'lib', 'custom', 'net472'), { recursive: true });
}

export async function createNewProjectInternalBase(
context: IActionContext,
options: ICreateFunctionOptions,
title: string,
message: string,
promptSteps: any[]
): Promise<void> {
addLocalFuncTelemetry(context);

const language: ProjectLanguage | string = (options.language as ProjectLanguage) || getGlobalSetting(projectLanguageSetting);
const version: string = options.version || getGlobalSetting(funcVersionSetting) || (await tryGetLocalFuncVersion()) || latestGAVersion;
const projectTemplateKey: string | undefined = getGlobalSetting(projectTemplateKeySetting);
const wizardContext: Partial<IFunctionWizardContext> & IActionContext = Object.assign(context, options, {
language,
version: tryParseFuncVersion(version),
projectTemplateKey,
});

if (options.folderPath) {
FolderListStep.setProjectPath(wizardContext, options.folderPath);
}

if (options.suppressOpenFolder) {
wizardContext.openBehavior = OpenBehavior.dontOpen;
} else if (!wizardContext.openBehavior) {
wizardContext.openBehavior = getWorkspaceSetting(projectOpenBehaviorSetting);
context.telemetry.properties.openBehaviorFromSetting = String(!!wizardContext.openBehavior);
}

const wizard: AzureWizard<IFunctionWizardContext> = new AzureWizard(wizardContext, {
title: localize(title, message),
promptSteps,
executeSteps: [new OpenFolderStepCodeProject()],
});

await wizard.prompt();
await wizard.execute();

await createArtifactsFolder(context as IFunctionWizardContext);
await createRulesFiles(context as IFunctionWizardContext);
await createLibFolder(context as IFunctionWizardContext);

window.showInformationMessage(localize('finishedCreating', 'Finished creating project.'));
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class NewCodeProjectTypeStep extends AzureWizardPromptStep<IProjectWizard
public hideStepCount = true;
private readonly templateId?: string;
private readonly functionSettings?: { [key: string]: string | undefined };
private readonly skipWorkflowStateTypeStep?: boolean;
private readonly skipWorkflowStateTypeStep: boolean;

/**
* The constructor initializes the NewCodeProjectTypeStep object with optional templateId and functionSettings parameters.
Expand All @@ -31,7 +31,7 @@ export class NewCodeProjectTypeStep extends AzureWizardPromptStep<IProjectWizard
public constructor(
templateId: string | undefined,
functionSettings: { [key: string]: string | undefined } | undefined,
skipWorkflowStateTypeStep: any
skipWorkflowStateTypeStep: boolean
) {
super();
this.templateId = templateId;
Expand All @@ -47,10 +47,8 @@ export class NewCodeProjectTypeStep extends AzureWizardPromptStep<IProjectWizard
// Set default project type and language
context.workflowProjectType = WorkflowProjectType.Bundle;
context.language = ProjectLanguage.JavaScript;

// Create directories based on user choices
const { workspacePath, isWorkspaceWithFunctions } = context;
await this.createDirectories(context, workspacePath, isWorkspaceWithFunctions);
const { workspacePath } = context;
await this.setPaths(context, workspacePath);
}

/**
Expand All @@ -76,46 +74,25 @@ export class NewCodeProjectTypeStep extends AzureWizardPromptStep<IProjectWizard
} else {
await this.setupRegularLogicApp(context, executeSteps, promptSteps);
}

return { promptSteps, executeSteps };
}

/**
* Creates required directories for the project
* Sets the paths required for the project
* @param context - Project wizard context
* @param workspacePath - Root path of the workspace
* @param isWorkspaceWithFunctions - Flag to check if it's a workspace with functions
*/
private async createDirectories(context: IProjectWizardContext, workspacePath: string, isWorkspaceWithFunctions: boolean): Promise<void> {
private async setPaths(context: IProjectWizardContext, workspacePath: string): Promise<void> {
await fs.ensureDir(workspacePath);
context.customWorkspaceFolderPath = workspacePath;

let logicAppFolderName = 'LogicApp';
if (!isWorkspaceWithFunctions && context.logicAppName) {
logicAppFolderName = context.logicAppName;
}
const logicAppFolderName = context.logicAppName;

const logicAppFolderPath = path.join(workspacePath, logicAppFolderName);
await fs.ensureDir(logicAppFolderPath);
context.logicAppFolderPath = logicAppFolderPath;

context.projectPath = logicAppFolderPath;
context.workspacePath = logicAppFolderPath;

if (isWorkspaceWithFunctions) {
await this.setupCustomDirectories(context, workspacePath);
}
await this.createWorkspaceFile(context);
}
/**
* Setup directories and configs for custom code logic app
* @param context - Project wizard context
* @param workspacePath - Root path of the workspace
*/
private async setupCustomDirectories(context: IProjectWizardContext, workspacePath: string): Promise<void> {
const functionFolderPath = path.join(workspacePath, 'Function');
await fs.ensureDir(functionFolderPath);
context.functionFolderPath = functionFolderPath;
}

/**
Expand Down Expand Up @@ -169,31 +146,4 @@ export class NewCodeProjectTypeStep extends AzureWizardPromptStep<IProjectWizard
);
}
}

/**
* Creates a .code-workspace file to group project directories in VS Code
* @param context - Project wizard context
*/
private async createWorkspaceFile(context: IProjectWizardContext): Promise<void> {
// Start with an empty folders array
const workspaceFolders = [];

// Add Functions folder first if it's a custom code code Logic App
if (context.isWorkspaceWithFunctions) {
workspaceFolders.push({ name: 'Functions', path: './Function' });
}

// Use context.logicAppName for the folder name; default to 'LogicApp' if not available
const logicAppName = context.logicAppName || 'LogicApp';
workspaceFolders.push({ name: logicAppName, path: `./${logicAppName}` });

const workspaceData = {
folders: workspaceFolders,
};

const workspaceFilePath = path.join(context.customWorkspaceFolderPath, `${context.workspaceName}.code-workspace`);
context.customWorkspaceFolderPath = workspaceFilePath;

await fs.writeJSON(workspaceFilePath, workspaceData, { spaces: 2 });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class OpenFolderStepCodeProject extends AzureWizardExecuteStep<IProjectWi
let uri: Uri;

// Check if .code-workspace file exists in project path
const workspaceFilePath = context.customWorkspaceFolderPath;
const workspaceFilePath = context.workspaceCustomFilePath;
context.workspaceFolder = getContainingWorkspace(workspaceFilePath);
if (fs.existsSync(workspaceFilePath)) {
uri = Uri.file(workspaceFilePath);
Expand All @@ -37,7 +37,9 @@ export class OpenFolderStepCodeProject extends AzureWizardExecuteStep<IProjectWi
}

if (context.openBehavior === OpenBehavior.addToWorkspace) {
workspace.updateWorkspaceFolders(openFolders.length, 0, { uri: uri });
if (!uri.path.endsWith('.code-workspace')) {
workspace.updateWorkspaceFolders(openFolders.length, 0, { uri: uri });
}
} else {
// Open folder using executeCommand method of commands object with vscode.openFolder command
await commands.executeCommand(
Expand Down

This file was deleted.

Loading
Loading