From 883d49dfc0010c0758f4915007334229d6448ab2 Mon Sep 17 00:00:00 2001 From: Ajinkya Udgirkar <ajinkyaudgirkar@gmail.com> Date: Fri, 4 Oct 2024 13:11:51 +0530 Subject: [PATCH] Add welcome page and update the title (#1475) * Code refactor and welcome page title update * ui tests for welcome page * Fix function name casing * Code refactor and welcome page title update * ui tests for welcome page * Fix function name casing * fix for lightspeed one click trial and auth test failure * Revert lightspeed test related changes * Remove duplicate code * Remove spacing * Skip tests for lightspeed one click trial feature * Update welcome page tests * Skip tests for lightspeed one click trial feature * Test container cleanup commands update --- .../style.css} | 4 + package.json | 4 +- src/extension.ts | 4 +- src/features/contentCreator/welcomePage.ts | 283 ---------------- .../playbookGeneration/welcomePage.ts | 309 ------------------ src/features/welcomePage/index.ts | 309 ++++++++++++++++++ .../welcomePageApp.ts | 0 test/ui-test/allTestsSuite.ts | 2 + test/ui-test/lightspeedUiTest.ts | 6 +- test/ui-test/welcomePageUITest.ts | 92 ++++++ webpack.config.ts | 4 +- 11 files changed, 416 insertions(+), 601 deletions(-) rename media/{playbookGeneration/playbookGeneration.css => welcomePage/style.css} (97%) delete mode 100644 src/features/contentCreator/welcomePage.ts delete mode 100644 src/features/playbookGeneration/welcomePage.ts create mode 100644 src/features/welcomePage/index.ts rename src/webview/apps/{contentCreator => welcomePage}/welcomePageApp.ts (100%) create mode 100644 test/ui-test/welcomePageUITest.ts diff --git a/media/playbookGeneration/playbookGeneration.css b/media/welcomePage/style.css similarity index 97% rename from media/playbookGeneration/playbookGeneration.css rename to media/welcomePage/style.css index 1633f42b6..c54f2c918 100644 --- a/media/playbookGeneration/playbookGeneration.css +++ b/media/welcomePage/style.css @@ -243,3 +243,7 @@ a .codicon { border-style: solid; border-radius: 4px; } + +.playbookGenerationContainer .playbookGenerationSlideCategories>.playbookGenerationCategoriesContainer > .header > .subtitle { + font-size: 1em; +} diff --git a/package.json b/package.json index 0d413f85a..715e3de7f 100644 --- a/package.json +++ b/package.json @@ -150,7 +150,7 @@ "ansible-explorer": [ { "id": "ansible-content-creator", - "name": "Ansible content creator" + "name": "Ansible Development Tools" }, { "id": "lightspeed-explorer-webview", @@ -296,7 +296,7 @@ }, { "command": "ansible.content-creator.menu", - "title": "Open Ansible Content Creator menu" + "title": "Open Ansible Development Tools menu" }, { "command": "ansible.content-creator.install", diff --git a/src/extension.ts b/src/extension.ts index 90fa27e53..ab3f29af2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -56,7 +56,7 @@ import { AnsibleToxProvider } from "./features/ansibleTox/provider"; import { findProjectDir } from "./features/ansibleTox/utils"; import { LightspeedFeedbackWebviewViewProvider } from "./features/lightspeed/feedbackWebviewViewProvider"; import { LightspeedFeedbackWebviewProvider } from "./features/lightspeed/feedbackWebviewProvider"; -import { AnsibleCreatorMenu } from "./features/playbookGeneration/welcomePage"; +import { AnsibleWelcomePage } from "./features/welcomePage"; import { CreateAnsibleCollection } from "./features/contentCreator/createAnsibleCollectionPage"; import { withInterpreter } from "./features/utils/commandRunner"; import { IFileSystemWatchers } from "./interfaces/watchers"; @@ -502,7 +502,7 @@ export async function activate(context: ExtensionContext): Promise<void> { // open ansible-content-creator menu context.subscriptions.push( vscode.commands.registerCommand("ansible.content-creator.menu", () => { - AnsibleCreatorMenu.render(context.extensionUri); + AnsibleWelcomePage.render(context.extensionUri); }), ); diff --git a/src/features/contentCreator/welcomePage.ts b/src/features/contentCreator/welcomePage.ts deleted file mode 100644 index 85dec977d..000000000 --- a/src/features/contentCreator/welcomePage.ts +++ /dev/null @@ -1,283 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import * as vscode from "vscode"; -import { getUri } from "../utils/getUri"; -import { getNonce } from "../utils/getNonce"; -import * as ini from "ini"; -import { getBinDetail } from "./utils"; - -export class AnsibleCreatorMenu { - public static currentPanel: AnsibleCreatorMenu | undefined; - private readonly _panel: vscode.WebviewPanel; - private _disposables: vscode.Disposable[] = []; - - private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { - this._panel = panel; - this._panel.webview.html = this._getWebviewContent( - this._panel.webview, - extensionUri, - ); - this._setWebviewMessageListener(this._panel.webview); - this._panel.onDidDispose(() => this.dispose(), null, this._disposables); - } - - public static render(extensionUri: vscode.Uri) { - if (AnsibleCreatorMenu.currentPanel) { - AnsibleCreatorMenu.currentPanel._panel.reveal(vscode.ViewColumn.One); - } else { - const panel = vscode.window.createWebviewPanel( - "content-creator-menu", - "Ansible Content Creator", - vscode.ViewColumn.One, - { - enableScripts: true, - localResourceRoots: [ - vscode.Uri.joinPath(extensionUri, "out"), - vscode.Uri.joinPath(extensionUri, "media"), - ], - enableCommandUris: true, - retainContextWhenHidden: true, - }, - ); - - AnsibleCreatorMenu.currentPanel = new AnsibleCreatorMenu( - panel, - extensionUri, - ); - } - } - - public dispose() { - AnsibleCreatorMenu.currentPanel = undefined; - - this._panel.dispose(); - - while (this._disposables.length) { - const disposable = this._disposables.pop(); - if (disposable) { - disposable.dispose(); - } - } - } - - private _getWebviewContent( - webview: vscode.Webview, - extensionUri: vscode.Uri, - ) { - const webviewUri = getUri(webview, extensionUri, [ - "out", - "client", - "webview", - "apps", - "contentCreator", - "welcomePageApp.js", - ]); - - const nonce = getNonce(); - const styleUri = getUri(webview, extensionUri, [ - "media", - "contentCreator", - "welcomePageStyle.css", - ]); - - const codiconsUri = getUri(webview, extensionUri, [ - "media", - "codicons", - "codicon.css", - ]); - - const contentCreatorIcon = getUri(webview, extensionUri, [ - "media", - "contentCreator", - "icons", - "ansible-logo-red.png", - ]); - - const initIcon = getUri(webview, extensionUri, [ - "media", - "contentCreator", - "icons", - "ansible-creator-init.png", - ]); - - const sampleIcon = getUri(webview, extensionUri, [ - "media", - "contentCreator", - "icons", - "ansible-creator-sample.png", - ]); - - const createIcon = getUri(webview, extensionUri, [ - "media", - "contentCreator", - "icons", - "ansible-creator-create.png", - ]); - - return /*html*/ ` - <html> - - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'nonce-${nonce}'; style-src ${webview.cspSource}; font-src ${webview.cspSource}; img-src ${webview.cspSource};"> - <title>AAA</title> - <link rel="stylesheet" href="${styleUri}"> - <link rel="stylesheet" href="${codiconsUri}"> - </head> - - <body> - <div class="intro"> - <div class="heading"> - <img src="${contentCreatorIcon}" alt="Ansible Creator Icon"> - <h1>nsible Content Creator</h1> - </div> - - <p>A tool for scaffolding ansible content. - <vscode-link href="https://github.com/ansible-community/ansible-creator#ansible-creator">Read our docs</vscode-link> - to learn more about this tool.</p> - - <div id="system-check"> - <div class="icon"> - <p>System requirements:</p> - </div> - - <div id=install-status></div> - - <div class="refresh-button-div"> - <vscode-button id="refresh"> - <span class="codicon codicon-refresh"></span> - Refresh - </vscode-button> - </div> - - </div> - </div> - - <vscode-divider role="presentation"></vscode-divider> - - <div class="menu"> - <div class="menu-item"> - <vscode-link href="command:ansible.content-creator.create-ansible-collection"> - <img src="${initIcon}" alt="Ansible Creator Icon"> - </vscode-link> - <p class="menu-item-heading">Initialize ansible collection</p> - </div> - - <div class="menu-item"> - <vscode-link href="command:ansible.lightspeed.playbookGeneration"> - <img src="${createIcon}" alt="Ansible Creator Icon"> - </vscode-link> - <p class="menu-item-heading">Create ansible content</p> - </div> - - <div class="menu-item"> - <vscode-link href="command:ansible.content-creator.sample"> - <img src="${sampleIcon}" alt="Ansible Creator Icon"> - </vscode-link> - <p class="menu-item-heading">Open sample manifest file</p> - </div> - </div> - - <!-- Component registration code --> - <script type="module" nonce="${nonce}" src="${webviewUri}"></script> - </body> - </html> - `; - } - - private _setWebviewMessageListener(webview: vscode.Webview) { - webview.onDidReceiveMessage( - async (message) => { - const command = message.message; - switch (command) { - case "refresh-page": - await this.refreshPage(); - return; - - case "set-system-status-view": - await this.getSystemDetails(webview); - return; - } - }, - undefined, - this._disposables, - ); - } - - private async refreshPage() { - await vscode.commands.executeCommand( - "workbench.action.webview.reloadWebviewAction", - ); - } - - private async getSystemDetails(webView: vscode.Webview) { - const systemInfo: any = {}; - - // get ansible version and path - const ansibleVersion = await getBinDetail("ansible", "--version"); - if (ansibleVersion !== "failed") { - const versionInfo = ini.parse(ansibleVersion.toString()); - - const versionInfoObjKeys = Object.keys(versionInfo); - - // return empty if ansible --version fails to execute - if (versionInfoObjKeys.length === 0) { - console.debug("[ansible-creator] No version information from ansible"); - } - - const ansibleCoreVersion = versionInfoObjKeys[0].includes(" [") - ? versionInfoObjKeys[0].split(" [") - : versionInfoObjKeys[0].split(" "); - - systemInfo["ansible version"] = ansibleCoreVersion[1] - .slice(0, -1) - .split(" ") - .pop() - ?.trim(); - - systemInfo["ansible location"] = versionInfo["executable location"]; - } - - // get python version - const pythonVersion = await getBinDetail("python3", "--version"); - if (pythonVersion !== "failed") { - systemInfo["python version"] = pythonVersion - .toString() - .trim() - .split(" ") - .pop() - ?.trim(); - } - - // get python path - const pythonPathResult = await getBinDetail( - "python3", - '-c "import sys; print(sys.executable)"', - ); - if (pythonPathResult !== "failed") { - systemInfo["python location"] = pythonPathResult.toString().trim(); - } - - // get ansible-creator version - const ansibleCreatorVersion = await getBinDetail( - "ansible-creator", - "--version", - ); - if (ansibleCreatorVersion !== "failed") { - systemInfo["ansible-creator version"] = ansibleCreatorVersion - .toString() - .trim(); - } - - // get ansible-creator version - const ansibleDevEnvironmentVersion = await getBinDetail("ade", "--version"); - if (ansibleDevEnvironmentVersion !== "failed") { - systemInfo["ansible-dev-environment version"] = - ansibleDevEnvironmentVersion.toString().trim(); - } - - // send the system details to the webview - webView.postMessage({ command: "systemDetails", arguments: systemInfo }); - } -} diff --git a/src/features/playbookGeneration/welcomePage.ts b/src/features/playbookGeneration/welcomePage.ts deleted file mode 100644 index db27288f0..000000000 --- a/src/features/playbookGeneration/welcomePage.ts +++ /dev/null @@ -1,309 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import * as vscode from "vscode"; -import { getUri } from "../utils/getUri"; -import { getNonce } from "../utils/getNonce"; -import * as ini from "ini"; -import { getBinDetail } from "../contentCreator/utils"; - -export class AnsibleCreatorMenu { - public static currentPanel: AnsibleCreatorMenu | undefined; - private readonly _panel: vscode.WebviewPanel; - private _disposables: vscode.Disposable[] = []; - - private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { - this._panel = panel; - this._panel.webview.html = this._getWebviewContent( - this._panel.webview, - extensionUri, - ); - this._setWebviewMessageListener(this._panel.webview); - this._panel.onDidDispose(() => this.dispose(), null, this._disposables); - } - - public static render(extensionUri: vscode.Uri) { - if (AnsibleCreatorMenu.currentPanel) { - AnsibleCreatorMenu.currentPanel._panel.reveal(vscode.ViewColumn.One); - } else { - const panel = vscode.window.createWebviewPanel( - "content-creator-menu", - "Ansible content creator", - vscode.ViewColumn.One, - { - enableScripts: true, - localResourceRoots: [ - vscode.Uri.joinPath(extensionUri, "out"), - vscode.Uri.joinPath(extensionUri, "media"), - ], - enableCommandUris: true, - retainContextWhenHidden: true, - }, - ); - - AnsibleCreatorMenu.currentPanel = new AnsibleCreatorMenu( - panel, - extensionUri, - ); - } - } - - public dispose() { - AnsibleCreatorMenu.currentPanel = undefined; - - this._panel.dispose(); - - while (this._disposables.length) { - const disposable = this._disposables.pop(); - if (disposable) { - disposable.dispose(); - } - } - } - - private _getWebviewContent( - webview: vscode.Webview, - extensionUri: vscode.Uri, - ) { - const webviewUri = getUri(webview, extensionUri, [ - "out", - "client", - "webview", - "apps", - "contentCreator", - "welcomePageApp.js", - ]); - - const nonce = getNonce(); - const styleUri = getUri(webview, extensionUri, [ - "media", - "playbookGeneration", - "playbookGeneration.css", - ]); - - const codiconsUri = getUri(webview, extensionUri, [ - "media", - "codicons", - "codicon.css", - ]); - - return /*html*/ ` - <html> - -<head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta http-equiv="Content-Security-Policy" - content="default-src 'none'; script-src 'nonce-${nonce}'; style-src ${webview.cspSource}; font-src ${webview.cspSource}; img-src ${webview.cspSource};"> - <title>AAA</title> - <link rel="stylesheet" href="${styleUri}"> - <link rel="stylesheet" href="${codiconsUri}"> -</head> - -<body> - <div class="playbookGenerationContainer"> - <div class="playbookGenerationSlideCategories"> - <div class="playbookGenerationCategoriesContainer"> - <div class="header"> - <h1 class="title caption">Welcome to Ansible content creator</h1> - <p class="subtitle description">Create Ansible content with ease</p> - - <div id="system-readiness" class="statusDisplay"></div> - - </div> - <div class="categories-column-left"> - <div class="index-list start-container"> - <h2>Create</h2> - <div class="catalogue"> - <h3> - <a href="command:ansible.lightspeed.playbookGeneration"> - <span class="codicon codicon-file-code"></span> Playbook with Ansible Lightspeed - </a> - </h3> - <p>Create a lists of tasks that automatically execute for your specified inventory or groups of hosts.</p> - </div> - <div class="catalogue"> - <h3> - <a href="command:ansible.content-creator.create-ansible-project"> - <span class="codicon codicon-file-zip"></span> Ansible playbook project - </a> - </h3> - <p>Create a foundational framework and structure for setting your Ansible project with playbooks, roles, variables, templates, and other files.</p> - </div> - <div class="catalogue"> - <h3> - <a href="command:ansible.content-creator.create-ansible-collection"> - <span class="codicon codicon-layers"></span> Ansible collection project - </a> - </h3> - <p>Create a structure for your Ansible collection that includes modules, plugins, molecule scenarios and tests. - </p> - </div> - </div> - - <!-- <div class="index-list start-container"> - <h2>Recent</h2> - <p>No recent activity</p> - </div> --> - - <div class="index-list start-container"> - <h2>Learn</h2> - <div class="catalogue"> - <h3> - <a href="https://docs.ansible.com"> - Ansible documentation - <span class="codicon codicon-link-external"></span> - </a> - </h3> - <p>Explore Ansible documentation, examples and more.</p> - </div> - <div class="catalogue"> - <h3> - <a href="https://docs.ansible.com/ansible/latest/getting_started/index.html"> - Learn Ansible development - <span class="codicon codicon-link-external"></span> - </a> - </h3> - <p>End to end course that will help you master automation development.</p> - </div> - <div class="catalogue"> - <h3>Once you are in the YAML file:</h3> - <p>click Ctrl+L to fire the Ansible Lightspeed AI assistance for editing and explaining code.</p> - </div> - </div> - - <div class="shadow"></div> - <div class="shadow"></div> - <div class="shadow"></div> - </div> - <div class="categories-column-right"> - <div class="index-list getting-started"> - <div id="system-check"> - <div class="icon"> - <h2>System requirements:</h2> - </div> - - <div id=install-status class="statusDisplay"></div> - - <div class="refresh-button-div"> - <vscode-button id="refresh"> - <span class="codicon codicon-refresh"></span> - Refresh - </vscode-button> - </div> - - </div> - </div> - <div class="shadow"></div> - <div class="shadow"></div> - <div class="shadow"></div> - </div> - <div class="footer"> - <p></p> - </div> - </div> - </div> - </div> - - <!-- Component registration code --> - <script type="module" nonce="${nonce}" src="${webviewUri}"></script> -</body> - -</html> - `; - } - - private _setWebviewMessageListener(webview: vscode.Webview) { - webview.onDidReceiveMessage( - async (message) => { - const command = message.message; - switch (command) { - case "refresh-page": - await this.refreshPage(); - return; - - case "set-system-status-view": - await this.getSystemDetails(webview); - return; - } - }, - undefined, - this._disposables, - ); - } - - private async refreshPage() { - await vscode.commands.executeCommand( - "workbench.action.webview.reloadWebviewAction", - ); - } - - private async getSystemDetails(webView: vscode.Webview) { - const systemInfo: any = {}; - - // get ansible version and path - const ansibleVersion = await getBinDetail("ansible", "--version"); - if (ansibleVersion !== "failed") { - const versionInfo = ini.parse(ansibleVersion.toString()); - - const versionInfoObjKeys = Object.keys(versionInfo); - - // return empty if ansible --version fails to execute - if (versionInfoObjKeys.length === 0) { - console.debug("[ansible-creator] No version information from ansible"); - } - - const ansibleCoreVersion = versionInfoObjKeys[0].includes(" [") - ? versionInfoObjKeys[0].split(" [") - : versionInfoObjKeys[0].split(" "); - - systemInfo["ansible version"] = ansibleCoreVersion[1] - .slice(0, -1) - .split(" ") - .pop() - ?.trim(); - - systemInfo["ansible location"] = versionInfo["executable location"]; - } - - // get python version - const pythonVersion = await getBinDetail("python3", "--version"); - if (pythonVersion !== "failed") { - systemInfo["python version"] = pythonVersion - .toString() - .trim() - .split(" ") - .pop() - ?.trim(); - } - - // get python path - const pythonPathResult = await getBinDetail( - "python3", - '-c "import sys; print(sys.executable)"', - ); - if (pythonPathResult !== "failed") { - systemInfo["python location"] = pythonPathResult.toString().trim(); - } - - // get ansible-creator version - const ansibleCreatorVersion = await getBinDetail( - "ansible-creator", - "--version", - ); - if (ansibleCreatorVersion !== "failed") { - systemInfo["ansible-creator version"] = ansibleCreatorVersion - .toString() - .trim(); - } - - // get ansible-creator version - const ansibleDevEnvironmentVersion = await getBinDetail("ade", "--version"); - if (ansibleDevEnvironmentVersion !== "failed") { - systemInfo["ansible-dev-environment version"] = - ansibleDevEnvironmentVersion.toString().trim(); - } - - // send the system details to the webview - webView.postMessage({ command: "systemDetails", arguments: systemInfo }); - } -} diff --git a/src/features/welcomePage/index.ts b/src/features/welcomePage/index.ts new file mode 100644 index 000000000..e3ed1151f --- /dev/null +++ b/src/features/welcomePage/index.ts @@ -0,0 +1,309 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import * as vscode from "vscode"; +import { getUri } from "../utils/getUri"; +import { getNonce } from "../utils/getNonce"; +import * as ini from "ini"; +import { getBinDetail } from "../contentCreator/utils"; + +export class AnsibleWelcomePage { + public static currentPanel: AnsibleWelcomePage | undefined; + private readonly _panel: vscode.WebviewPanel; + private _disposables: vscode.Disposable[] = []; + + private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { + this._panel = panel; + this._panel.webview.html = this._getWebviewContent( + this._panel.webview, + extensionUri, + ); + this._setWebviewMessageListener(this._panel.webview); + this._panel.onDidDispose(() => this.dispose(), null, this._disposables); + } + + public static render(extensionUri: vscode.Uri) { + if (AnsibleWelcomePage.currentPanel) { + AnsibleWelcomePage.currentPanel._panel.reveal(vscode.ViewColumn.One); + } else { + const panel = vscode.window.createWebviewPanel( + "content-creator-menu", + "Ansible Development Tools", + vscode.ViewColumn.One, + { + enableScripts: true, + localResourceRoots: [ + vscode.Uri.joinPath(extensionUri, "out"), + vscode.Uri.joinPath(extensionUri, "media"), + ], + enableCommandUris: true, + retainContextWhenHidden: true, + }, + ); + + AnsibleWelcomePage.currentPanel = new AnsibleWelcomePage( + panel, + extensionUri, + ); + } + } + + public dispose() { + AnsibleWelcomePage.currentPanel = undefined; + + this._panel.dispose(); + + while (this._disposables.length) { + const disposable = this._disposables.pop(); + if (disposable) { + disposable.dispose(); + } + } + } + + private _getWebviewContent( + webview: vscode.Webview, + extensionUri: vscode.Uri, + ) { + const webviewUri = getUri(webview, extensionUri, [ + "out", + "client", + "webview", + "apps", + "welcomePage", + "welcomePageApp.js", + ]); + + const nonce = getNonce(); + const styleUri = getUri(webview, extensionUri, [ + "media", + "welcomePage", + "style.css", + ]); + + const codiconsUri = getUri(webview, extensionUri, [ + "media", + "codicons", + "codicon.css", + ]); + + return /*html*/ ` + <html> + + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta http-equiv="Content-Security-Policy" + content="default-src 'none'; script-src 'nonce-${nonce}'; style-src ${webview.cspSource}; font-src ${webview.cspSource}; img-src ${webview.cspSource};"> + <title>Ansible Development Tools</title> + <link rel="stylesheet" href="${styleUri}"> + <link rel="stylesheet" href="${codiconsUri}"> + </head> + + <body> + <div class="playbookGenerationContainer"> + <div class="playbookGenerationSlideCategories"> + <div class="playbookGenerationCategoriesContainer"> + <div class="header"> + <h1 class="title caption">Ansible Development Tools</h1> + <p class="subtitle description">Create, test and deploy Ansible content in your IT environment</p> + + <div id="system-readiness" class="statusDisplay"></div> + + </div> + <div class="categories-column-left"> + <div class="index-list start-container"> + <h2>Create</h2> + <div class="catalogue"> + <h3> + <a href="command:ansible.lightspeed.playbookGeneration"> + <span class="codicon codicon-file-code"></span> Playbook with Ansible Lightspeed + </a> + </h3> + <p>Create a lists of tasks that automatically execute for your specified inventory or groups of hosts.</p> + </div> + <div class="catalogue"> + <h3> + <a href="command:ansible.content-creator.create-ansible-project"> + <span class="codicon codicon-file-zip"></span> Ansible playbook project + </a> + </h3> + <p>Create a foundational framework and structure for setting your Ansible project with playbooks, roles, variables, templates, and other files.</p> + </div> + <div class="catalogue"> + <h3> + <a href="command:ansible.content-creator.create-ansible-collection"> + <span class="codicon codicon-layers"></span> Ansible collection project + </a> + </h3> + <p>Create a structure for your Ansible collection that includes modules, plugins, molecule scenarios and tests. + </p> + </div> + </div> + + <!-- <div class="index-list start-container"> + <h2>Recent</h2> + <p>No recent activity</p> + </div> --> + + <div class="index-list start-container"> + <h2>Learn</h2> + <div class="catalogue"> + <h3> + <a href="https://docs.ansible.com"> + Ansible documentation + <span class="codicon codicon-link-external"></span> + </a> + </h3> + <p>Explore Ansible documentation, examples and more.</p> + </div> + <div class="catalogue"> + <h3> + <a href="https://docs.ansible.com/ansible/latest/getting_started/index.html"> + Learn Ansible development + <span class="codicon codicon-link-external"></span> + </a> + </h3> + <p>End to end course that will help you master automation development.</p> + </div> + <div class="catalogue"> + <h3>Once you are in the YAML file:</h3> + <p>click Ctrl+L to fire the Ansible Lightspeed AI assistance for editing and explaining code.</p> + </div> + </div> + + <div class="shadow"></div> + <div class="shadow"></div> + <div class="shadow"></div> + </div> + <div class="categories-column-right"> + <div class="index-list getting-started"> + <div id="system-check"> + <div class="icon"> + <h2>System requirements:</h2> + </div> + + <div id=install-status class="statusDisplay"></div> + + <div class="refresh-button-div"> + <vscode-button id="refresh"> + <span class="codicon codicon-refresh"></span> + Refresh + </vscode-button> + </div> + + </div> + </div> + <div class="shadow"></div> + <div class="shadow"></div> + <div class="shadow"></div> + </div> + <div class="footer"> + <p></p> + </div> + </div> + </div> + </div> + + <!-- Component registration code --> + <script type="module" nonce="${nonce}" src="${webviewUri}"></script> + </body> + + </html> + `; + } + + private _setWebviewMessageListener(webview: vscode.Webview) { + webview.onDidReceiveMessage( + async (message) => { + const command = message.message; + switch (command) { + case "refresh-page": + await this.refreshPage(); + return; + + case "set-system-status-view": + await this.getSystemDetails(webview); + return; + } + }, + undefined, + this._disposables, + ); + } + + private async refreshPage() { + await vscode.commands.executeCommand( + "workbench.action.webview.reloadWebviewAction", + ); + } + + private async getSystemDetails(webView: vscode.Webview) { + const systemInfo: any = {}; + + // get ansible version and path + const ansibleVersion = await getBinDetail("ansible", "--version"); + if (ansibleVersion !== "failed") { + const versionInfo = ini.parse(ansibleVersion.toString()); + + const versionInfoObjKeys = Object.keys(versionInfo); + + // return empty if ansible --version fails to execute + if (versionInfoObjKeys.length === 0) { + console.debug("[ansible-creator] No version information from ansible"); + } + + const ansibleCoreVersion = versionInfoObjKeys[0].includes(" [") + ? versionInfoObjKeys[0].split(" [") + : versionInfoObjKeys[0].split(" "); + + systemInfo["ansible version"] = ansibleCoreVersion[1] + .slice(0, -1) + .split(" ") + .pop() + ?.trim(); + + systemInfo["ansible location"] = versionInfo["executable location"]; + } + + // get python version + const pythonVersion = await getBinDetail("python3", "--version"); + if (pythonVersion !== "failed") { + systemInfo["python version"] = pythonVersion + .toString() + .trim() + .split(" ") + .pop() + ?.trim(); + } + + // get python path + const pythonPathResult = await getBinDetail( + "python3", + '-c "import sys; print(sys.executable)"', + ); + if (pythonPathResult !== "failed") { + systemInfo["python location"] = pythonPathResult.toString().trim(); + } + + // get ansible-creator version + const ansibleCreatorVersion = await getBinDetail( + "ansible-creator", + "--version", + ); + if (ansibleCreatorVersion !== "failed") { + systemInfo["ansible-creator version"] = ansibleCreatorVersion + .toString() + .trim(); + } + + // get ansible-creator version + const ansibleDevEnvironmentVersion = await getBinDetail("ade", "--version"); + if (ansibleDevEnvironmentVersion !== "failed") { + systemInfo["ansible-dev-environment version"] = + ansibleDevEnvironmentVersion.toString().trim(); + } + + // send the system details to the webview + webView.postMessage({ command: "systemDetails", arguments: systemInfo }); + } +} diff --git a/src/webview/apps/contentCreator/welcomePageApp.ts b/src/webview/apps/welcomePage/welcomePageApp.ts similarity index 100% rename from src/webview/apps/contentCreator/welcomePageApp.ts rename to src/webview/apps/welcomePage/welcomePageApp.ts diff --git a/test/ui-test/allTestsSuite.ts b/test/ui-test/allTestsSuite.ts index 89a3f4d95..5654055ac 100644 --- a/test/ui-test/allTestsSuite.ts +++ b/test/ui-test/allTestsSuite.ts @@ -3,12 +3,14 @@ import { lightspeedUILoginTest } from "./lightspeedAuthUiTest"; import { lightspeedOneClickTrialUITest } from "./lightspeedOneClickTrialUITest"; import { lightspeedUIAssetsTest } from "./lightspeedUiTest"; import { terminalUITests } from "./terminalUiTest"; +import { welcomePageUITest } from "./welcomePageUITest"; describe("VSCode Ansible - UI tests", function () { this.timeout(30000); extensionUIAssetsTest(); lightspeedUIAssetsTest(); terminalUITests(); + welcomePageUITest(); // Skip this on MacOS due to the functional limitation on menu support if (process.platform === "darwin") { diff --git a/test/ui-test/lightspeedUiTest.ts b/test/ui-test/lightspeedUiTest.ts index 88e55bf42..a7d617baa 100644 --- a/test/ui-test/lightspeedUiTest.ts +++ b/test/ui-test/lightspeedUiTest.ts @@ -194,7 +194,7 @@ export function lightspeedUIAssetsTest(): void { }); it("Playbook generation webview works as expected (full path) - part 1", async function () { - // Open Ansible Content Creator by clicking the Getting started button on the side bar + // Open Ansible Development Tools by clicking the Getting started button on the side bar const view = (await new ActivityBar().getViewControl( "Ansible", )) as ViewControl; @@ -212,7 +212,7 @@ export function lightspeedUIAssetsTest(): void { } await sleep(5000); - // Open Playbook Generation UI by clicking the create content button on Ansible Content Creator + // Open Playbook Generation UI by clicking the create content button on Ansible Development Tools const contentCreatorWebView = await new WebView(); expect( contentCreatorWebView, @@ -234,7 +234,7 @@ export function lightspeedUIAssetsTest(): void { await createContentButton.click(); } await contentCreatorWebView.switchBack(); - await new EditorView().closeEditor("Ansible content creator"); + await new EditorView().closeEditor("Ansible Development Tools"); await sleep(2000); // Start operations on Playbook Generation UI diff --git a/test/ui-test/welcomePageUITest.ts b/test/ui-test/welcomePageUITest.ts new file mode 100644 index 000000000..f1174662c --- /dev/null +++ b/test/ui-test/welcomePageUITest.ts @@ -0,0 +1,92 @@ +import { config, expect } from "chai"; +import { + ActivityBar, + By, + SideBarView, + ViewControl, + ViewSection, + WebView, +} from "vscode-extension-tester"; +import { sleep } from "./uiTestHelper"; + +config.truncateThreshold = 0; +export function welcomePageUITest(): void { + describe("Verify welcome page sidebar and title is displayed as expected", async () => { + let view: ViewControl; + let sideBar: SideBarView; + let adtSection: ViewSection; + + before(async () => { + // Open Ansible Development Tools by clicking the Getting started button on the side bar + view = (await new ActivityBar().getViewControl("Ansible")) as ViewControl; + sideBar = await view.openView(); + // to get the content part + adtSection = await sideBar + .getContent() + .getSection("Ansible Development Tools"); + }); + + after(async function () { + if (view) { + await view.closeView(); + } + }); + + it("check for title and get started button", async function () { + const title = await adtSection.getTitle(); + const getStartedButton = await adtSection.findElement( + By.xpath( + "//a[contains(@class, 'monaco-button') and " + + ".//span/text()='Get started']", + ), + ); + + expect(title).not.to.be.undefined; + expect(title).to.equals("Ansible Development Tools"); + expect(getStartedButton).not.to.be.undefined; + }); + + it("check for header and subtitle", async function () { + const getStartedButton = await adtSection.findElement( + By.xpath( + "//a[contains(@class, 'monaco-button') and " + + ".//span/text()='Get started']", + ), + ); + + expect(getStartedButton).not.to.be.undefined; + + if (getStartedButton) { + await getStartedButton.click(); + } + await sleep(3000); + + const welcomePageWebView = await new WebView(); + expect(welcomePageWebView, "welcomePageWebView should not be undefined") + .not.to.be.undefined; + await welcomePageWebView.switchToFrame(3000); + expect( + welcomePageWebView, + "welcomePageWebView should not be undefined after switching to its frame", + ).not.to.be.undefined; + + const adtHeaderTitle = await welcomePageWebView.findWebElement( + By.className("title caption"), + ); + expect(adtHeaderTitle).not.to.be.undefined; + expect(await adtHeaderTitle.getText()).to.equals( + "Ansible Development Tools", + ); + + const adtSubheader = await welcomePageWebView.findWebElement( + By.className("subtitle description"), + ); + expect(adtSubheader).not.to.be.undefined; + expect(await adtSubheader.getText()).includes( + "Create, test and deploy Ansible content", + ); + + await welcomePageWebView.switchBack(); + }); + }); +} diff --git a/webpack.config.ts b/webpack.config.ts index bbfee58c2..af483ce7b 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -121,11 +121,11 @@ const webviewConfig = { const contentCreatorMenuWebviewConfig = { ...config, target: ["web", "es2020"], - entry: "./src/webview/apps/contentCreator/welcomePageApp.ts", + entry: "./src/webview/apps/welcomePage/welcomePageApp.ts", experiments: { outputModule: true }, output: { path: path.resolve(__dirname, "out"), - filename: "./client/webview/apps/contentCreator/welcomePageApp.js", + filename: "./client/webview/apps/welcomePage/welcomePageApp.js", libraryTarget: "module", chunkFormat: "module", },