Skip to content

Commit

Permalink
feat(vscode): Introduce onboarding experience (#3581)
Browse files Browse the repository at this point in the history
* feat(vscode): externalize connection parameterization (#2830)

connection parameterization

* feat(vscode): Azurite Start & Default Location (#3031)

Cherry Pick Autostart Azurite

* feat(vscode): Start Design time on project launch (#3037)

* Add first workspace changes

* Add validation for workspace and project

* +DesignTime settings

* +telemetry

* +PromptStartDesignTimeOption

* +Telemetry

* PR Feedback

* fix missing

---------

Co-authored-by: ccastrotrejo <[email protected]>

* feat(vscode): Binary Dependency Installation (Cherry Pick) (#3319)

* Cherry Picked: binaryInstallation

* overwrite existing tasks.json

* Change wording

---------

Co-authored-by: Alan Kai (from Dev Box) <[email protected]>

* fix(Designer): Fixes for single click installation bugs (#3505)

* async Timeout for Dependencies

* fix timeout, fix async/await, add csharp setting

* Rename to timeOutErrorOperation

---------

Co-authored-by: Alan Kai (from Dev Box) <[email protected]>

* feat(vscode): Opt-in/opt-out for installation of binaries (#3546)

* Add prompt to opt-in and opt-out for binaries installation

* Separate onboarding to different file

* Update onboarding ids

* Add default to binaries and update onboarding for binaries

* Add back functionality

* Separate functions according to binaries opt-in/out

* Add default value when get global setting

* Update dotnet command when there is no use of dotnet dependencies

* fix(vscode): Set default path when opt-out (#3564)

* Add prompt to opt-in and opt-out for binaries installation

* Separate onboarding to different file

* Update onboarding ids

* Add default to binaries and update onboarding for binaries

* Add back functionality

* Separate functions according to binaries opt-in/out

* Add default value when get global setting

* Update dotnet command when there is no use of dotnet dependencies

* Update to default path when opt out

* Update strings to be able to review

* Update strings

* Add final point

* fix(vscode): Update function core tools option when optout (#3570)

* Update tasks.json according to binaries

* Add warning message for install binaries command

* Revert "feat(vscode): externalize connection parameterization (#2830)"

This reverts commit b8e6e7c.

* Update imports

* Update binaries prompt to prompt always

* Remove esModuleInterop from tsconfig

* Update imports and command preview

* Add validation for auto start azurite

* Update setting name

* Update settings and remove warning message

* Update settings

* Add log and update settings

* Update azurite and look for project path

* Make azurite auto location

* Update to get logic app project

* Update string

---------

Co-authored-by: Yerko <[email protected]>
Co-authored-by: Alan Kai <[email protected]>
Co-authored-by: Alan Kai (from Dev Box) <[email protected]>
  • Loading branch information
4 people authored Nov 3, 2023
1 parent 0689a6d commit f28c4fa
Show file tree
Hide file tree
Showing 55 changed files with 2,268 additions and 220 deletions.
2 changes: 0 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,10 +599,8 @@

## [2.28.0](https://github.com/Azure/LogicAppsUX/compare/v2.27.0...v2.28.0) (2023-06-13)


## [2.23.0](https://github.com/Azure/LogicAppsUX/compare/v2.22.0...v2.23.0) (2023-05-31)


### Features

- **Data Mapper:** Able to select schemas from folders within 'Schemas' folder ([#2700](https://github.com/Azure/LogicAppsUX/issues/2700)) ([3999cd3](https://github.com/Azure/LogicAppsUX/commit/3999cd312d414e2a915ace6a65c0cda46d64db87))
Expand Down
3 changes: 2 additions & 1 deletion apps/vs-code-designer/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
{
"files": ["*.ts"],
"rules": {
"no-param-reassign": "off"
"no-param-reassign": "off",
"react-hooks/rules-of-hooks": "off"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { azuriteExtensionId } from '../../constants';
import { localize } from '../../localize';
import type { IActionContext } from '@microsoft/vscode-azext-utils';
import { extensions } from 'vscode';
import * as vscode from 'vscode';

export async function executeOnAzurite(context: IActionContext, command: string, ...args: any[]): Promise<void> {
const azuriteExtension = extensions.getExtension(azuriteExtensionId);

if (azuriteExtension?.isActive) {
vscode.commands.executeCommand(command, {
...args,
});
} else {
const message: string = localize('deactivatedAzuriteExt', 'Azurite extension is deactivated, make sure to activate it');
await context.ui.showWarningMessage(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class FunctionConfigFile extends AzureWizardPromptStep<IProjectWizardCont
tasks: [
{
label: 'build',
command: 'dotnet',
command: '${config:azureLogicAppsStandard.dotnetBinaryPath}',
type: 'process',
args: ['build', '${workspaceFolder}'],
group: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class ScriptProjectCreateStep extends ProjectCodeCreateStepBase {
'local.settings.json',
'test',
'.debug',
'global.json',
];
protected gitignore = '';
protected supportsManagedDependencies = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,37 +118,43 @@ export abstract class InitCodeProject extends AzureWizardExecuteStep<IProjectWiz
public async overwriteTasksJson(context: IProjectWizardContext): Promise<void> {
const tasksJsonPath: string = path.join(context.projectPath, '.vscode', 'Tasks.json');
const tasksJsonContent = `{
"version": "2.0.0",
"tasks": [
{
"label": "generateDebugSymbols",
"command": "dotnet",
"args": [
"\${input:getDebugSymbolDll}"
"version": "2.0.0",
"tasks": [
{
"label": "generateDebugSymbols",
"command": '\${config:azureLogicAppsStandard.dotnetBinaryPath}',
"args": [
"\${input:getDebugSymbolDll}"
],
"type": "process",
"problemMatcher": "$msCompile"
},
{
"type": "shell",
"command":"\${config:azureLogicAppsStandard.funcCoreToolsBinaryPath}",
"args" : ["host", "start"],
"options": {
"env": {
"PATH": "\${config:azureLogicAppsStandard.autoRuntimeDependenciesPath}\\\\NodeJs;\${config:azureLogicAppsStandard.autoRuntimeDependenciesPath}\\\\DotNetSDK;$env:PATH"
}
},
"problemMatcher": "$func-watch",
"isBackground": true,
"label": "func: host start",
"group": {
"kind": "build",
"isDefault": true
}
}
],
"type": "process",
"problemMatcher": "$msCompile"
},
{
"type": "func",
"command": "host start",
"problemMatcher": "$func-watch",
"isBackground": true,
"label": "func: host start",
"group": {
"kind": "build",
"isDefault": true
}
}
],
"inputs": [
{
"id": "getDebugSymbolDll",
"type": "command",
"command": "azureLogicAppsStandard.getDebugSymbolDll"
}
]
}`;
"inputs": [
{
"id": "getDebugSymbolDll",
"type": "command",
"command": "azureLogicAppsStandard.getDebugSymbolDll"
}
]
}`;

if (await confirmOverwriteFile(context, tasksJsonPath)) {
await fse.writeFile(tasksJsonPath, tasksJsonContent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { extInstallTaskName, func, funcWatchProblemMatcher, hostStartCommand } from '../../../../../../constants';
import { binariesExist } from '../../../../../../app/utils/binaries';
import { extInstallTaskName, func, funcDependencyName, funcWatchProblemMatcher, hostStartCommand } from '../../../../../../constants';
import { getLocalFuncCoreToolsVersion } from '../../../../../utils/funcCoreTools/funcVersion';
import { InitCodeProject } from './InitCodeProject';
import type { IProjectWizardContext } from '@microsoft/vscode-extension';
Expand All @@ -19,10 +20,23 @@ export class ScriptInit extends InitCodeProject {
protected useFuncExtensionsInstall = false;

protected getTasks(): TaskDefinition[] {
const funcBinariesExist = binariesExist(funcDependencyName);
const binariesOptions = funcBinariesExist
? {
options: {
env: {
PATH: '${config:azureLogicAppsStandard.autoRuntimeDependenciesPath}\\NodeJs;${config:azureLogicAppsStandard.autoRuntimeDependenciesPath}\\DotNetSDK;$env:PATH',
},
},
}
: {};
return [
{
type: func,
command: hostStartCommand,
label: 'func: host start',
type: funcBinariesExist ? 'shell' : func,
command: funcBinariesExist ? '${config:azureLogicAppsStandard.funcCoreToolsBinaryPath}' : hostStartCommand,
args: funcBinariesExist ? ['host', 'start'] : undefined,
...binariesOptions,
problemMatcher: funcWatchProblemMatcher,
dependsOn: this.useFuncExtensionsInstall ? extInstallTaskName : undefined,
isBackground: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { extensionCommand, func, funcWatchProblemMatcher, hostStartCommand } from '../../../../../../constants';
import { binariesExist } from '../../../../../../app/utils/binaries';
import { extensionCommand, func, funcDependencyName, funcWatchProblemMatcher, hostStartCommand } from '../../../../../../constants';
import { ScriptInit } from './ScriptInit';
import type { IProjectWizardContext, ITaskInputs, ISettingToAdd } from '@microsoft/vscode-extension';
import type { TaskDefinition } from 'vscode';
Expand All @@ -13,17 +14,29 @@ export class WorkflowInitCodeProject extends ScriptInit {
}

protected getTasks(): TaskDefinition[] {
const funcBinariesExist = binariesExist(funcDependencyName);
const binariesOptions = funcBinariesExist
? {
options: {
env: {
PATH: '${config:azureLogicAppsStandard.autoRuntimeDependenciesPath}\\NodeJs;${config:azureLogicAppsStandard.autoRuntimeDependenciesPath}\\DotNetSDK;$env:PATH',
},
},
}
: {};
return [
{
label: 'generateDebugSymbols',
command: 'dotnet',
command: '${config:azureLogicAppsStandard.dotnetBinaryPath}',
args: ['${input:getDebugSymbolDll}'],
type: 'process',
problemMatcher: '$msCompile',
},
{
type: func,
command: hostStartCommand,
type: funcBinariesExist ? 'shell' : func,
command: funcBinariesExist ? '${config:azureLogicAppsStandard.funcCoreToolsBinaryPath}' : hostStartCommand,
args: funcBinariesExist ? ['host', 'start'] : undefined,
...binariesOptions,
problemMatcher: funcWatchProblemMatcher,
isBackground: true,
label: 'func: host start',
Expand Down
21 changes: 21 additions & 0 deletions apps/vs-code-designer/src/app/commands/dotnet/installDotNet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*------------------p---------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { autoRuntimeDependenciesPathSettingKey, dotnetDependencyName } from '../../../constants';
import { ext } from '../../../extensionVariables';
import { downloadAndExtractBinaries, getDotNetBinariesReleaseUrl } from '../../utils/binaries';
import { getGlobalSetting } from '../../utils/vsCodeConfig/settings';
import type { IActionContext } from '@microsoft/vscode-azext-utils';

export async function installDotNet(context: IActionContext, majorVersion?: string): Promise<void> {
ext.outputChannel.show();
context.telemetry.properties.majorVersion = majorVersion;
const targetDirectory = getGlobalSetting<string>(autoRuntimeDependenciesPathSettingKey);

context.telemetry.properties.lastStep = 'getDotNetBinariesReleaseUrl';
const scriptUrl = getDotNetBinariesReleaseUrl();

context.telemetry.properties.lastStep = 'downloadAndExtractBinaries';
await downloadAndExtractBinaries(scriptUrl, targetDirectory, dotnetDependencyName, majorVersion);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { validateDotNetSDKSetting } from '../../../constants';
import { localize } from '../../../localize';
import { getDotNetCommand } from '../../utils/dotnet/dotnet';
import { executeCommand } from '../../utils/funcCoreTools/cpUtils';
import { getWorkspaceSetting } from '../../utils/vsCodeConfig/settings';
import { installDotNet } from './installDotNet';
import { callWithTelemetryAndErrorHandling, DialogResponses, openUrl } from '@microsoft/vscode-azext-utils';
import type { IActionContext } from '@microsoft/vscode-azext-utils';
import type { MessageItem } from 'vscode';

/**
* Checks if dotnet 6 is installed, and installs it if needed.
* @param {IActionContext} context - Workflow file path.
* @param {string} message - Message for warning.
* @param {string} fsPath - Workspace file system path.
* @returns {Promise<boolean>} Returns true if it is installed or was sucessfully installed, otherwise returns false.
*/
export async function validateDotNetIsInstalled(context: IActionContext, message: string, fsPath: string): Promise<boolean> {
let input: MessageItem | undefined;
let installed = false;
const install: MessageItem = { title: localize('install', 'Install') };

await callWithTelemetryAndErrorHandling('azureLogicAppsStandard.validateDotNetIsInstalled', async (innerContext: IActionContext) => {
innerContext.errorHandling.suppressDisplay = true;

if (!getWorkspaceSetting<boolean>(validateDotNetSDKSetting, fsPath)) {
innerContext.telemetry.properties.validateDotNet = 'false';
installed = true;
} else if (await isDotNetInstalled()) {
installed = true;
} else {
const items: MessageItem[] = [install, DialogResponses.learnMore];
input = await innerContext.ui.showWarningMessage(message, { modal: true }, ...items);
innerContext.telemetry.properties.dialogResult = input.title;

if (input === install) {
await installDotNet(innerContext);
installed = true;
} else if (input === DialogResponses.learnMore) {
await openUrl('https://dotnet.microsoft.com/download/dotnet/6.0');
}
}
});

// validate that DotNet was installed only if user confirmed
if (input === install && !installed) {
if (
(await context.ui.showWarningMessage(
localize('failedInstallDotNet', 'The .NET SDK installation failed. Please manually install instead.'),
DialogResponses.learnMore
)) === DialogResponses.learnMore
) {
await openUrl('https://dotnet.microsoft.com/download/dotnet/6.0');
}
}

return installed;
}

/**
* Check is dotnet is installed.
* @returns {Promise<boolean>} Returns true if installed, otherwise returns false.
*/
export async function isDotNetInstalled(): Promise<boolean> {
try {
await executeCommand(undefined, undefined, getDotNetCommand(), '--version');
return true;
} catch (error) {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { dotnetDependencyName } from '../../../constants';
import { localize } from '../../../localize';
import { binariesExist, getLatestDotNetVersion } from '../../utils/binaries';
import { getDotNetCommand, getLocalDotNetVersionFromBinaries } from '../../utils/dotnet/dotnet';
import { getWorkspaceSetting, updateGlobalSetting } from '../../utils/vsCodeConfig/settings';
import { installDotNet } from './installDotNet';
import { callWithTelemetryAndErrorHandling, DialogResponses, openUrl } from '@microsoft/vscode-azext-utils';
import type { IActionContext } from '@microsoft/vscode-azext-utils';
import * as semver from 'semver';
import type { MessageItem } from 'vscode';

export async function validateDotNetIsLatest(majorVersion?: string): Promise<void> {
await callWithTelemetryAndErrorHandling('azureLogicAppsStandard.validateDotNetIsLatest', async (context: IActionContext) => {
context.errorHandling.suppressDisplay = true;
context.telemetry.properties.isActivationEvent = 'true';

const showDotNetWarningKey = 'showDotNetWarning';
const showDotNetWarning = !!getWorkspaceSetting<boolean>(showDotNetWarningKey);
const binaries = binariesExist(dotnetDependencyName);
context.telemetry.properties.binariesExist = `${binaries}`;

if (!binaries) {
await installDotNet(context, majorVersion);
context.telemetry.properties.binaryCommand = `${getDotNetCommand()}`;
} else if (showDotNetWarning) {
context.telemetry.properties.binaryCommand = `${getDotNetCommand()}`;
const localVersion: string | null = await getLocalDotNetVersionFromBinaries();
context.telemetry.properties.localVersion = localVersion;
const newestVersion: string | undefined = await getLatestDotNetVersion(context, majorVersion);
if (semver.major(newestVersion) === semver.major(localVersion) && semver.gt(newestVersion, localVersion)) {
context.telemetry.properties.outOfDateDotNet = 'true';
const message: string = localize(
'outdatedDotNetRuntime',
'Update your local .NET SDK version ({0}) to the latest version ({1}) for the best experience.',
localVersion,
newestVersion
);
const update: MessageItem = { title: 'Update' };
let result: MessageItem;
do {
result =
newestVersion !== undefined
? await context.ui.showWarningMessage(message, update, DialogResponses.learnMore, DialogResponses.dontWarnAgain)
: await context.ui.showWarningMessage(message, DialogResponses.learnMore, DialogResponses.dontWarnAgain);
if (result === DialogResponses.learnMore) {
await openUrl('https://dotnet.microsoft.com/en-us/download/dotnet/6.0');
} else if (result === update) {
await installDotNet(context, majorVersion);
} else if (result === DialogResponses.dontWarnAgain) {
await updateGlobalSetting(showDotNetWarningKey, false);
}
} while (result === DialogResponses.learnMore);
}
}
});
}
Loading

0 comments on commit f28c4fa

Please sign in to comment.