diff --git a/packages/cli/resource/newParam.json b/packages/cli/resource/newParam.json index 4123a6cf6b1..b72e457891a 100644 --- a/packages/cli/resource/newParam.json +++ b/packages/cli/resource/newParam.json @@ -273,31 +273,25 @@ { "id": "in-meeting-app", "label": "In-meeting App", - "detail": "In-meeting app is a hello-world template which shows how to build an app working in the context of a Teams meeting. ", + "detail": "A template for apps using only in the context of a Teams meeting", "data": "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" }, { "id": "todo-list-with-Azure-backend", "label": "Todo List with backend on Azure", - "detail": "Todo List provides easy way to manage to-do items in Teams Client.", + "detail": "Todo List app with Azure Function backend and Azure SQL database", "data": "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" }, { "id": "todo-list-SPFx", "label": "Todo List with SPFx", - "detail": "Todo List with SPFx is a Todo List for individual user to manage his/her personal to-do items in the format of an app installed on Teams client.", + "detail": "Todo List app hosting on SharePoint", "data": "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" }, { "id": "share-now", "label": "Share Now", - "detail": "The Share Now promotes the exchange of information between colleagues by enabling users to share content within the Teams environment. ", - "data": "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" - }, - { - "id": "faq-plus", - "label": "FAQ Plus", - "detail": "FAQ Plus is a conversational Q&A bot providing an easy way to answer frequently asked questions by users. ", + "detail": "Knowledge sharing app contains a Tab and a Message Extension", "data": "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" } ], diff --git a/packages/cli/src/cmds/new.ts b/packages/cli/src/cmds/new.ts index bed987dca89..f48c96e0a72 100644 --- a/packages/cli/src/cmds/new.ts +++ b/packages/cli/src/cmds/new.ts @@ -23,18 +23,28 @@ import { Question, isAutoSkipSelect, SingleSelectQuestion, - MultiSelectQuestion + MultiSelectQuestion, } from "@microsoft/teamsfx-api"; import activate from "../activate"; import * as constants from "../constants"; -import { NotFoundInputedFolder, SampleAppClonedFailed } from "../error"; +import { NotFoundInputedFolder, SampleAppDownloadFailed } from "../error"; import { validateAndUpdateAnswers, visitInteractively } from "../question/question"; import { YargsCommand } from "../yargsCommand"; -import { flattenNodes, getJson, getSingleOptionString, toConfigMap, toYargsOptions } from "../utils"; +import { + flattenNodes, + getJson, + getSingleOptionString, + toConfigMap, + toYargsOptions, +} from "../utils"; import CliTelemetry from "../telemetry/cliTelemetry"; import { TelemetryClient } from "applicationinsights"; -import { TelemetryEvent, TelemetryProperty, TelemetrySuccess } from "../telemetry/cliTelemetryEvents"; +import { + TelemetryEvent, + TelemetryProperty, + TelemetrySuccess, +} from "../telemetry/cliTelemetryEvents"; export default class New extends YargsCommand { public readonly commandHead = `new`; @@ -65,19 +75,21 @@ export default class New extends YargsCommand { const data = node.data as Question; if (isAutoSkipSelect(data)) { // set the only option to default value so yargs will auto fill it. - data.default = getSingleOptionString(data as (SingleSelectQuestion | MultiSelectQuestion)); + data.default = getSingleOptionString(data as SingleSelectQuestion | MultiSelectQuestion); (data as any).hide = true; } this.params[data.name] = toYargsOptions(data); }); - yargs.options({ - "interactive": { - description: "Select the options interactively", - boolean: true, - default: true, - global: false - } - }).options(this.params); + yargs + .options({ + interactive: { + description: "Select the options interactively", + boolean: true, + default: true, + global: false, + }, + }) + .options(this.params); } return yargs.version(false); } @@ -123,7 +135,7 @@ export default class New extends YargsCommand { } CliTelemetry.sendTelemetryEvent(TelemetryEvent.CreateProject, { - [TelemetryProperty.Success]: TelemetrySuccess.Yes + [TelemetryProperty.Success]: TelemetrySuccess.Yes, }); return ok(null); } @@ -141,20 +153,18 @@ class NewTemplete extends YargsCommand { this.subCommands.forEach((cmd) => { yargs.command(cmd.command, cmd.description, cmd.builder.bind(cmd), cmd.handler.bind(cmd)); }); - const templatesNames = constants.templates.map(t => t.sampleAppName); + const templatesNames = constants.templates.map((t) => t.sampleAppName); yargs - .positional( - "template-name", { - description: "Enter the template name", - type: "string", - choices: templatesNames, - default: templatesNames[0] - } - ) + .positional("template-name", { + description: "Enter the template name", + type: "string", + choices: templatesNames, + default: templatesNames[0], + }) .options(RootFolderNodeData.name, { type: "string", description: RootFolderNodeData.description, - default: RootFolderNodeData.default + default: RootFolderNodeData.default, }); return yargs; } @@ -162,25 +172,27 @@ class NewTemplete extends YargsCommand { public async runCommand(args: { [argName: string]: string | string[]; }): Promise> { - const folder = path.resolve(args.folder as string || "./"); + const folder = path.resolve((args.folder as string) || "./"); if (!fs.pathExistsSync(folder)) { throw NotFoundInputedFolder(folder); } CliTelemetry.sendTelemetryEvent(TelemetryEvent.DownloadSampleStart); const templateName = args["template-name"] as string; - const template = constants.templates.find(t => t.sampleAppName === templateName)!; - + const template = constants.templates.find((t) => t.sampleAppName === templateName)!; + const result = await this.fetchCodeZip(template.sampleAppUrl); await this.saveFilesRecursively(new AdmZip(result.data), template.sampleAppName, folder); console.log( colors.green( - `Downloaded the '${colors.yellow(template.sampleAppName)}' sample to '${colors.yellow(path.join(folder, template.sampleAppName))}'.` + `Downloaded the '${colors.yellow(template.sampleAppName)}' sample to '${colors.yellow( + path.join(folder, template.sampleAppName) + )}'.` ) ); CliTelemetry.sendTelemetryEvent(TelemetryEvent.DownloadSample, { [TelemetryProperty.Success]: TelemetrySuccess.Yes, - [TelemetryProperty.SampleName]: templateName + [TelemetryProperty.SampleName]: templateName, }); return ok(null); } @@ -188,14 +200,14 @@ class NewTemplete extends YargsCommand { private async fetchCodeZip(url: string) { try { const result = await axios.get(url, { - responseType: "arraybuffer" + responseType: "arraybuffer", }); if (result.status === 200 || result.status === 201) { return result; } - throw SampleAppClonedFailed(url, new Error(result.statusText)); + throw SampleAppDownloadFailed(url, new Error(result.statusText)); } catch (e) { - throw SampleAppClonedFailed(url, e); + throw SampleAppDownloadFailed(url, e); } } @@ -235,7 +247,9 @@ class NewTempleteList extends YargsCommand { console.log(constants.templates); console.log( colors.green( - `Use the command ${colors.yellow("teamsfx new template ")} to create an application from the sample app.` + `Use the command ${colors.yellow( + "teamsfx new template " + )} to create an application from the sample app.` ) ); return ok(null); diff --git a/packages/cli/src/constants.ts b/packages/cli/src/constants.ts index d418a897837..a0703e4d3cf 100644 --- a/packages/cli/src/constants.ts +++ b/packages/cli/src/constants.ts @@ -63,38 +63,31 @@ export const templates: { { tags: ["React", "Azure function", "Azure SQL", "JS"], title: "Todo List with Azure backend", - description: "Todo List provides an easy way to manage to-do items in Teams Client. This app helps enabling task collaboration and management for your team. The frontend is a React app and the backend is hosted on Azure. You will need an Azure subscription to run the app.", + description: "Todo List app with Azure Function backend and Azure SQL database", sampleAppName: "todo-list-with-Azure-backend", - sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" + sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", }, { tags: ["SharePoint", "SPFx", "TS"], title: "Todo List with SPFx ", - description: "Todo List with SPFx is a Todo List for individuals to manage his/her personal to-do items. This app is hosted on Sharepoint. There is no requirements to deploy Azure resources.", + description: "Todo List app hosting on SharePoint", sampleAppName: "todo-list-SPFx", - sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" + sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", }, { tags: ["Tab", "Message Extension", "TS"], title: "Share Now", - description: "Share Now promotes the exchange of information between colleagues by enabling users to share content within the Teams environment. Users engage the app to share items of interest, discover new shared content, set preferences, and bookmark favorites for later reading.", + description: "Knowledge sharing app contains a Tab and a Message Extension", sampleAppName: "share-now", - sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" - }, - { - tags: ["Easy QnA", "Bot", "JS"], - title: "FAQ Plus", - description: "FAQ Plus is a conversational Q&A bot providing an easy way to answer frequently asked questions by users. One can ask a question and the bot responds with information in the knowledge base. If the answer is not in the knowledge base, the bot submits the question to a pre-configured team of experts who help provide support.", - sampleAppName: "faq-plus", - sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" + sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", }, { tags: ["Meeting extension", "JS"], title: "In-meeting App", - description: "In-meeting app is a hello-world template which shows how to build an app in the context of a Teams meeting. This is a hello-world sample which does not provide any functional feature. This app contains a side panel and a Bot which only shows user profile and can only be added to a Teams meeting.", + description: "A template for apps using only in the context of a Teams meeting", sampleAppName: "in-meeting-app", - sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip" - } + sampleAppUrl: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", + }, ]; export enum CLILogLevel { diff --git a/packages/cli/src/error.ts b/packages/cli/src/error.ts index 766cfd58de3..5fac2d2ab3b 100644 --- a/packages/cli/src/error.ts +++ b/packages/cli/src/error.ts @@ -79,9 +79,9 @@ export function ConfigNotFoundError(configpath: string): SystemError { ); } -export function SampleAppClonedFailed(sampleAppUrl: string, e: Error): SystemError { - e.message = `Cannot clone this sample app from ${sampleAppUrl}. Error: ${e.message}`; - return returnSystemError(e, constants.cliSource, "SampleAppClonedFailed"); +export function SampleAppDownloadFailed(sampleAppUrl: string, e: Error): SystemError { + e.message = `Cannot download this sample app from ${sampleAppUrl}. Error: ${e.message}`; + return returnSystemError(e, constants.cliSource, "SampleAppDownloadFailed"); } export function ReadFileError(e: Error): SystemError { diff --git a/packages/fx-core/src/core/error.ts b/packages/fx-core/src/core/error.ts index 98fca48a052..b6726631f81 100644 --- a/packages/fx-core/src/core/error.ts +++ b/packages/fx-core/src/core/error.ts @@ -64,7 +64,7 @@ export function NotSupportedProjectType(): UserError { export function DownloadSampleFail(): SystemError { return returnUserError( - new Error("Failed to clone sample app"), + new Error("Failed to download sample app"), CoreSource, CoreErrorNames.DownloadSampleFail ); diff --git a/packages/fx-core/src/core/index.ts b/packages/fx-core/src/core/index.ts index 89ad083ad76..b76f7bc328c 100644 --- a/packages/fx-core/src/core/index.ts +++ b/packages/fx-core/src/core/index.ts @@ -269,13 +269,13 @@ class CoreImpl implements Core { const answer = ( await this.ctx.dialog?.communicate( new DialogMsg(DialogType.Show, { - description: `Clone '${samples.label}' from Github. This will clone '${samples.label}' repository to your local machine`, + description: `Download '${samples.label}' from Github. This will download '${samples.label}' repository and open to your local machine`, level: MsgLevel.Info, - items: ["Clone", "Cancel"], + items: ["Download", "Cancel"], }) ) )?.getAnswer(); - if (answer === "Clone") { + if (answer === "Download") { const url = samples.data as string; const sampleId = samples.id; const progress = this.ctx.dialog.createProgressBar("Fetch sample app", 2); diff --git a/packages/fx-core/src/core/question.ts b/packages/fx-core/src/core/question.ts index dae53fb770c..9232ab9e0d7 100644 --- a/packages/fx-core/src/core/question.ts +++ b/packages/fx-core/src/core/question.ts @@ -95,35 +95,25 @@ export const SampleSelect: SingleSelectQuestion = { { id: "in-meeting-app", label: "In-meeting App", - detail: - "In-meeting app is a hello-world template which shows how to build an app working in the context of a Teams meeting. ", + detail: "A template for apps using only in the context of a Teams meeting", data: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", }, { id: "todo-list-with-Azure-backend", label: "Todo List with backend on Azure", - detail: "Todo List provides easy way to manage to-do items in Teams Client.", + detail: "Todo List app with Azure Function backend and Azure SQL database", data: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", }, { id: "todo-list-SPFx", label: "Todo List with SPFx", - detail: - "Todo List with SPFx is a Todo List for individual user to manage his/her personal to-do items in the format of an app installed on Teams client.", + detail: "Todo List app hosting on SharePoint", data: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", }, { id: "share-now", label: "Share Now", - detail: - "The Share Now promotes the exchange of information between colleagues by enabling users to share content within the Teams environment. ", - data: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", - }, - { - id: "faq-plus", - label: "FAQ Plus", - detail: - "FAQ Plus is a conversational Q&A bot providing an easy way to answer frequently asked questions by users. ", + detail: "Knowledge sharing app contains a Tab and a Message Extension", data: "https://github.com/OfficeDev/TeamsFx-Samples/archive/refs/heads/main.zip", }, ], diff --git a/packages/vscode-extension/src/controls/webviewPanel.ts b/packages/vscode-extension/src/controls/webviewPanel.ts index 24158a02dd0..0f6eff030ca 100644 --- a/packages/vscode-extension/src/controls/webviewPanel.ts +++ b/packages/vscode-extension/src/controls/webviewPanel.ts @@ -74,17 +74,17 @@ export class WebviewPanel { break; case Commands.CloneSampleApp: const selection = await vscode.window.showInformationMessage( - `Clone '${msg.data.appName}' from Github. This will clone '${msg.data.appName}' repository to your local machine`, + `Download '${msg.data.appName}' from Github. This will download '${msg.data.appName}' repository and open to your local machine`, { modal: false }, - "Clone", + "Download", "Cancel" ); - if (selection === "Clone") { + if (selection === "Download") { const folder = await vscode.window.showOpenDialog({ canSelectFiles: false, canSelectFolders: true, canSelectMany: false, - title: "Select folder to clone the sample app", + title: "Select folder to download the sample app", }); if (folder !== undefined) { const dialogManager = DialogManager.getInstance(); @@ -105,7 +105,7 @@ export class WebviewPanel { vscode.Uri.file(path.join(folder[0].fsPath, msg.data.appFolder)) ); } else { - vscode.window.showErrorMessage("Failed to clone sample app"); + vscode.window.showErrorMessage("Failed to download sample app"); } } finally { progress.end();