diff --git a/.sonarcloud.properties b/.sonarcloud.properties index 5d815d248..6ce5fb5fe 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -1,4 +1,6 @@ sonar.cpd.exclusions=\ src/features/lightspeed/playbookGeneration.ts, \ src/features/lightspeed/roleGeneration.ts, \ + src/features/contentCreator/createSampleExecutionEnvPage.ts, \ + src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts, \ test/ui-test/*.ts diff --git a/.vscodeignore b/.vscodeignore index b862baf2d..af325efa6 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -24,6 +24,7 @@ !media/contentCreator/createAnsibleCollectionPageStyle.css !media/contentCreator/createAnsibleProjectPageStyle.css !media/contentCreator/createDevfilePageStyle.css +!media/contentCreator/createSampleExecutionEnvPageStyle.css !media/contentCreator/welcomePageStyle.css !media/lightspeedExplorerView/style.css !media/quickLinks/lightspeed.png @@ -44,6 +45,7 @@ !out/client/webview/apps/contentCreator/createAnsibleCollectionPageApp.js !out/client/webview/apps/contentCreator/createAnsibleProjectPageApp.js !out/client/webview/apps/contentCreator/createDevfilePageApp.js +!out/client/webview/apps/contentCreator/createSampleExecutionEnvPageApp.js !out/client/webview/apps/quickLinks/quickLinksApp.js !out/client/webview/apps/welcomePage/welcomePageApp.js !out/server/src/server.js diff --git a/codecov.yml b/codecov.yml index 419df937b..bbe11cfda 100644 --- a/codecov.yml +++ b/codecov.yml @@ -19,5 +19,6 @@ ignore: - src/webview/apps/contentCreator/createAnsibleCollectionPageApp.ts - src/webview/apps/contentCreator/createAnsibleProjectPageApp.ts - src/webview/apps/contentCreator/createDevfilePageApp.ts + - src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts - src/webview/apps/welcomePage/welcomePageApp.ts - src/webview/apps/quickLinks/quickLinksApp.ts diff --git a/media/contentCreator/createSampleExecutionEnvPageStyle.css b/media/contentCreator/createSampleExecutionEnvPageStyle.css new file mode 100644 index 000000000..35c6e1215 --- /dev/null +++ b/media/contentCreator/createSampleExecutionEnvPageStyle.css @@ -0,0 +1,99 @@ +@import url(../baseStyles/baseFormStyle.css); + +.container { + display: flex; + flex-direction: column; +} + +.element { + margin-bottom: 14px; +} + +vscode-text-field { + margin-top: 6px; + margin-bottom: 6px; +} + +vscode-text-area { + margin-top: 6px; + margin-bottom: 6px; +} + +.checkbox-div { + display: flex; /* Use flexbox */ + flex-direction: column; /* Arrange child elements vertically */ + margin-top: 22px; + margin-bottom: 10px; + width: 100%; +} + +.verbose-div { + display: flex; /* Use flexbox */ + flex-direction: row; /* Arrange child elements vertically */ + margin-top: 12px; + margin-bottom: 30px; + width: 100%; +} + +vscode-dropdown { + width: 200px; +} + +.full-destination-path { + display: flex; /* Use flexbox */ + flex-direction: row; /* Arrange child elements vertically */ + color: var(--vscode-descriptionForeground); +} + +.group-buttons { + display: flex; /* Use flexbox */ + flex-direction: row; /* Arrange child elements vertically */ +} + +.p-collection-name { + font-style: italic; +} + +vscode-button { + margin: 0px 3px; +} + +vscode-checkbox i { + color: var(--vscode-descriptionForeground); + font-size: small; +} + +#ade-docs-link { + margin-left: 30px; + font-style: italic; +} + +.dropdown-container { + box-sizing: border-box; + display: flex; + flex-flow: column nowrap; + align-items: flex-start; + justify-content: flex-start; +} + +.dropdown-container label { + display: block; + color: var(--vscode-foreground); + cursor: pointer; + font-size: var(--vscode-font-size); + line-height: normal; + margin-bottom: 2px; +} + +#log-to-file-options-div { + display: none; + flex-direction: column; + border-style: dotted; + border-color: var(--focus-border); + border-width: 0.5px; + padding: 8px; +} + +.log-level-div { + margin: 4px 0px; +} diff --git a/package.json b/package.json index b631d0e9b..88ef97944 100644 --- a/package.json +++ b/package.json @@ -350,6 +350,10 @@ "command": "ansible.content-creator.create-devfile", "title": "Ansible: Create a Devfile" }, + { + "command": "ansible.content-creator.create-sample-execution-env-file", + "title": "Ansible: Create a Sample Execution Environment file" + }, { "command": "ansible.content-creator.create", "title": "Ansible Content Creator: Create" diff --git a/src/definitions/constants.ts b/src/definitions/constants.ts index 67759a1e4..83c92c83d 100644 --- a/src/definitions/constants.ts +++ b/src/definitions/constants.ts @@ -46,6 +46,8 @@ export const ANSIBLE_CREATOR_VERSION_MIN = "24.10.1"; export const ANSIBLE_CREATOR_COLLECTION_VERSION_MIN = "24.7.1"; +export const ANSIBLE_CREATOR_EE_VERSION_MIN = "25.1.0"; + export const DevfileImages = { Upstream: "ghcr.io/ansible/ansible-workspace-env-reference:latest", }; diff --git a/src/extension.ts b/src/extension.ts index 9942ce5a7..8c3b3ee1a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -72,6 +72,7 @@ import { } from "./features/lightspeed/lightspeedUser"; import { PlaybookFeedbackEvent } from "./interfaces/lightspeed"; import { CreateDevfile } from "./features/contentCreator/createDevfilePage"; +import { CreateSampleExecutionEnv } from "./features/contentCreator/createSampleExecutionEnvPage"; export let client: LanguageClient; export let lightSpeedManager: LightSpeedManager; @@ -550,6 +551,16 @@ export async function activate(context: ExtensionContext): Promise { ), ); + // open web-view for creating sample Execution Environment file + context.subscriptions.push( + vscode.commands.registerCommand( + "ansible.content-creator.create-sample-execution-env-file", + () => { + CreateSampleExecutionEnv.render(context.extensionUri); + }, + ), + ); + // open ansible-creator create context.subscriptions.push( vscode.commands.registerCommand("ansible.content-creator.create", () => { diff --git a/src/features/contentCreator/createSampleExecutionEnvPage.ts b/src/features/contentCreator/createSampleExecutionEnvPage.ts new file mode 100644 index 000000000..650d39bd2 --- /dev/null +++ b/src/features/contentCreator/createSampleExecutionEnvPage.ts @@ -0,0 +1,464 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import * as vscode from "vscode"; +import * as os from "os"; +import * as semver from "semver"; +import { getUri } from "../utils/getUri"; +import { getNonce } from "../utils/getNonce"; +import { AnsibleSampleExecutionEnvInterface, PostMessageEvent } from "./types"; +import { withInterpreter } from "../utils/commandRunner"; +import { SettingsManager } from "../../settings"; +import { expandPath, runCommand, getCreatorVersion } from "./utils"; +import { ANSIBLE_CREATOR_EE_VERSION_MIN } from "../../definitions/constants"; + +export class CreateSampleExecutionEnv { + public static currentPanel: CreateSampleExecutionEnv | 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 (CreateSampleExecutionEnv.currentPanel) { + CreateSampleExecutionEnv.currentPanel._panel.reveal( + vscode.ViewColumn.One, + ); + } else { + const panel = vscode.window.createWebviewPanel( + "create-sample-execution-env", + "Create Sample Ansible Execution Environment", + vscode.ViewColumn.One, + { + enableScripts: true, + localResourceRoots: [ + vscode.Uri.joinPath(extensionUri, "out"), + vscode.Uri.joinPath(extensionUri, "media"), + ], + enableCommandUris: true, + retainContextWhenHidden: true, + }, + ); + + CreateSampleExecutionEnv.currentPanel = new CreateSampleExecutionEnv( + panel, + extensionUri, + ); + } + } + + public dispose() { + CreateSampleExecutionEnv.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", + "createSampleExecutionEnvPageApp.js", + ]); + + const nonce = getNonce(); + const styleUri = getUri(webview, extensionUri, [ + "media", + "contentCreator", + "createSampleExecutionEnvPageStyle.css", + ]); + + const codiconsUri = getUri(webview, extensionUri, [ + "media", + "codicons", + "codicon.css", + ]); + + const workspaceDir = this.getWorkspaceFolder(); + const tempDir = os.tmpdir(); + + return /*html*/ ` + + + + + + + AAA + + + + + +
+

Create a sample Ansible Execution Environment file

+

Streamlining automation

+
+ +
+
+ + Destination path +
+ + + +
+
+ +
+

Default Destination path: 

+
+ +
+ +
+ +
+ Log output to a file
Default path: + ${tempDir}/ansible-creator.log.
+
+ +
+ Log file path +
+ + + +
+
+ + Append + +
+ +
+ +
+ +
+ Overwrite
Overwrite the existing execution-environment.yml file.
+
+ +
+ + +   Clear All + + + +   Create + +
+ +
+ +
+ Logs + +
+ + +   Clear Logs + + + +   Copy Logs + + + +   Open Log File + + + +   Open Execution Environment file + +
+
+
+ + + + + + `; + } + + private _setWebviewMessageListener(webview: vscode.Webview) { + webview.onDidReceiveMessage( + async (message: any) => { + const command = message.command; + let payload; + + switch (command) { + case "open-explorer": { + payload = message.payload; + const selectedUri = await this.openExplorerDialog( + payload.selectOption, + ); + webview.postMessage({ + command: "file-uri", + arguments: { selectedUri: selectedUri }, + } as PostMessageEvent); + return; + } + case "init-create": + payload = message.payload as AnsibleSampleExecutionEnvInterface; + await this.runInitCommand(payload, webview); + return; + + case "init-copy-logs": + payload = message.payload; + vscode.env.clipboard.writeText(payload.initExecutionLogs); + await vscode.window.showInformationMessage( + "Logs copied to clipboard", + ); + return; + + case "init-open-log-file": + payload = message.payload; + await this.openLogFile(payload.logFileUrl); + return; + + case "init-open-scaffolded-file": + payload = message.payload; + this.openFileInWorkspace(payload.projectUrl); + return; + } + }, + undefined, + this._disposables, + ); + } + + public async getCreatorCommand(url: string): Promise { + let command = ""; + + command = `ansible-creator add resource execution-environment ${url} --no-ansi`; + return command; + } + + public async openExplorerDialog( + selectOption: string, + ): Promise { + const options: vscode.OpenDialogOptions = { + canSelectMany: false, + openLabel: "Select", + canSelectFiles: selectOption === "file", + canSelectFolders: selectOption === "folder", + defaultUri: vscode.Uri.parse(os.homedir()), + }; + + let selectedUri: string | undefined; + await vscode.window.showOpenDialog(options).then((fileUri) => { + if (fileUri && fileUri[0]) { + selectedUri = fileUri[0].fsPath; + } + }); + + return selectedUri; + } + + public getWorkspaceFolder() { + let folder: string = ""; + if (vscode.workspace.workspaceFolders) { + folder = vscode.workspace.workspaceFolders[0].uri.path; + } + return folder; + } + + public async runInitCommand( + payload: AnsibleSampleExecutionEnvInterface, + webView: vscode.Webview, + ) { + const { + destinationPath, + logToFile, + logFilePath, + logFileAppend, + logLevel, + verbosity, + isOverwritten, + } = payload; + + const destinationPathUrl = destinationPath + ? destinationPath + : this.getWorkspaceFolder(); + + let ansibleCreatorSampleEECommand = + await this.getCreatorCommand(destinationPathUrl); + + if (isOverwritten) { + ansibleCreatorSampleEECommand += " --overwrite"; + } + + switch (verbosity) { + case "Off": + ansibleCreatorSampleEECommand += ""; + break; + case "Low": + ansibleCreatorSampleEECommand += " -v"; + break; + case "Medium": + ansibleCreatorSampleEECommand += " -vv"; + break; + case "High": + ansibleCreatorSampleEECommand += " -vvv"; + break; + } + + let logFilePathUrl = ""; + + if (logToFile) { + if (logFilePath) { + logFilePathUrl = logFilePath; + } else { + logFilePathUrl = `${os.tmpdir()}/ansible-creator.log`; + } + + ansibleCreatorSampleEECommand += ` --lf=${logFilePathUrl}`; + + ansibleCreatorSampleEECommand += ` --ll=${logLevel.toLowerCase()}`; + + if (logFileAppend) { + ansibleCreatorSampleEECommand += ` --la=true`; + } else { + ansibleCreatorSampleEECommand += ` --la=false`; + } + } + + console.debug("[ansible-creator] command: ", ansibleCreatorSampleEECommand); + + const extSettings = new SettingsManager(); + await extSettings.initialize(); + + const { command, env } = withInterpreter( + extSettings.settings, + ansibleCreatorSampleEECommand, + "", + ); + + let commandOutput = ""; + let commandResult: string; + + commandOutput += `------------------------------------ ansible-creator logs ------------------------------------\n`; + const creatorVersion = await getCreatorVersion(); + if (semver.gte(creatorVersion, ANSIBLE_CREATOR_EE_VERSION_MIN)) { + // execute ansible-creator command + const ansibleCreatorExecutionResult = await runCommand(command, env); + commandOutput += ansibleCreatorExecutionResult.output; + commandResult = ansibleCreatorExecutionResult.status; + } else { + commandOutput += ansibleCreatorSampleEECommand; + commandOutput += `\nMinimum ansible-creator version needed to scaffold an execution-environment.yml file is 25.1.0\n`; + commandOutput += `Please upgrade ansible-creator to minimum required version and try again.`; + commandResult = "failed"; + } + + await webView.postMessage({ + command: "execution-log", + arguments: { + commandOutput: commandOutput, + logFileUrl: logFilePathUrl, + projectUrl: destinationPathUrl, + status: commandResult, + }, + } as PostMessageEvent); + + if (commandResult === "passed") { + const selection = await vscode.window.showInformationMessage( + `Ansible Sample Execution Environment file created at: ${destinationPathUrl}`, + `Open Sample Execution Environment file ↗`, + ); + if (selection === "Open Sample Execution Environment file ↗") { + this.openFileInWorkspace(destinationPathUrl); + } + } + } + + public async openLogFile(fileUrl: string) { + const logFileUrl = vscode.Uri.file(expandPath(fileUrl)).fsPath; + console.log(`[ansible-creator] New Log file url: ${logFileUrl}`); + const parsedUrl = vscode.Uri.parse(`vscode://file${logFileUrl}`); + console.log(`[ansible-creator] Parsed log file url: ${parsedUrl}`); + this.openFileInEditor(parsedUrl.toString()); + } + + public async openFileInWorkspace(fileUrl: string) { + const fileUri = vscode.Uri.parse(expandPath(fileUrl)); + + if (vscode.workspace.workspaceFolders?.length === 0) { + vscode.workspace.updateWorkspaceFolders(0, null, { uri: fileUri }); + } else { + await vscode.commands.executeCommand("vscode.openFolder", fileUri, { + forceNewWindow: true, + }); + } + + // open the sample execution environment file in the editor + const eeFileUrl = vscode.Uri.joinPath( + vscode.Uri.parse(fileUrl), + "execution-environment.yml", + ).fsPath; + console.log( + `[ansible-creator] Execution Environment file url: ${eeFileUrl}`, + ); + const parsedUrl = vscode.Uri.parse(`vscode://file${eeFileUrl}`); + console.log( + `[ansible-creator] Parsed Execution Environment file url: ${parsedUrl}`, + ); + this.openFileInEditor(parsedUrl.toString()); + } + + public openFileInEditor(fileUrl: string) { + const updatedUrl = expandPath(fileUrl); + console.log(`[ansible-creator] Updated url: ${updatedUrl}`); + + vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(updatedUrl)); + } +} diff --git a/src/features/contentCreator/types.ts b/src/features/contentCreator/types.ts index 85ef58ebc..6517b6500 100644 --- a/src/features/contentCreator/types.ts +++ b/src/features/contentCreator/types.ts @@ -30,6 +30,16 @@ export type DevfileFormInterface = { isOverwritten: boolean; }; +export type AnsibleSampleExecutionEnvInterface = { + destinationPath: string; + verbosity: string; + logToFile: boolean; + logFilePath: string; + logFileAppend: boolean; + logLevel: string; + isOverwritten: boolean; +}; + export type PostMessageEvent = | { command: "ADEPresence"; diff --git a/src/features/quickLinks/quickLinksView.ts b/src/features/quickLinks/quickLinksView.ts index e9c36b457..89e138cb3 100644 --- a/src/features/quickLinks/quickLinksView.ts +++ b/src/features/quickLinks/quickLinksView.ts @@ -121,6 +121,14 @@ export function getWebviewQuickLinks(webview: Webview, extensionUri: Uri) { + diff --git a/src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts b/src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts new file mode 100644 index 000000000..273a06897 --- /dev/null +++ b/src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts @@ -0,0 +1,275 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { + allComponents, + Button, + Checkbox, + TextArea, + TextField, + provideVSCodeDesignSystem, + Dropdown, +} from "@vscode/webview-ui-toolkit"; +import { + AnsibleSampleExecutionEnvInterface, + PostMessageEvent, +} from "../../../features/contentCreator/types"; + +provideVSCodeDesignSystem().register(allComponents); + +const vscode = acquireVsCodeApi(); +window.addEventListener("load", main); + +let destinationPathUrlTextField: TextField; +let folderExplorerButton: Button; + +let initCreateButton: Button; +let initClearButton: Button; + +let overwriteCheckbox: Checkbox; + +let logToFileCheckbox: Checkbox; +let logToFileOptionsDiv: HTMLElement | null; +let logFilePath: TextField; +let fileExplorerButton: Button; +let logFileAppendCheckbox: Checkbox; +let logLevelDropdown: Dropdown; + +let verboseDropdown: Dropdown; + +let initDestinationPathDiv: HTMLElement | null; +let initDestinationPathElement: HTMLElement; + +let initLogsTextArea: TextArea; +let initClearLogsButton: Button; +let initOpenLogFileButton: Button; +let initCopyLogsButton: Button; +let initOpenScaffoldedFileButton: Button; + +let logFileUrl = ""; +let projectUrl = ""; + +function main() { + destinationPathUrlTextField = document.getElementById( + "path-url", + ) as TextField; + folderExplorerButton = document.getElementById("folder-explorer") as Button; + + overwriteCheckbox = document.getElementById("overwrite-checkbox") as Checkbox; + + logToFileCheckbox = document.getElementById( + "log-to-file-checkbox", + ) as Checkbox; + logToFileCheckbox.addEventListener("change", toggleLogToFileOptions); + + logToFileOptionsDiv = document.getElementById("log-to-file-options-div"); + + logFilePath = document.getElementById("log-file-path") as TextField; + fileExplorerButton = document.getElementById("file-explorer") as Button; + logFileAppendCheckbox = document.getElementById( + "log-file-append-checkbox", + ) as Checkbox; + logLevelDropdown = document.getElementById("log-level-dropdown") as Dropdown; + + verboseDropdown = document.getElementById("verbosity-dropdown") as Dropdown; + initCreateButton = document.getElementById("create-button") as Button; + initClearButton = document.getElementById("clear-button") as Button; + + initLogsTextArea = document.getElementById("log-text-area") as TextArea; + initClearLogsButton = document.getElementById("clear-logs-button") as Button; + initOpenLogFileButton = document.getElementById( + "open-log-file-button", + ) as Button; + initCopyLogsButton = document.getElementById("copy-logs-button") as Button; + initOpenScaffoldedFileButton = document.getElementById( + "open-file-button", + ) as Button; + + destinationPathUrlTextField.addEventListener("input", toggleCreateButton); + + folderExplorerButton.addEventListener("click", openExplorer); + fileExplorerButton.addEventListener("click", openExplorer); + + initCreateButton.addEventListener("click", handleInitCreateClick); + initCreateButton.disabled = false; + + initClearButton.addEventListener("click", handleInitClearClick); + + initClearLogsButton.addEventListener("click", handleInitClearLogsClick); + initOpenLogFileButton.addEventListener("click", handleInitOpenLogFileClick); + initCopyLogsButton.addEventListener("click", handleInitCopyLogsClick); + initOpenScaffoldedFileButton.addEventListener( + "click", + handleInitOpenScaffoldedFileClick, + ); + + initDestinationPathDiv = document.getElementById("full-destination-path"); + + initDestinationPathElement = document.createElement("p"); + initDestinationPathElement.innerHTML = + destinationPathUrlTextField.placeholder; + initDestinationPathDiv?.appendChild(initDestinationPathElement); +} + +function openExplorer(event: any) { + const source = event.target.parentNode.id; + + let selectOption; + + if (source === "folder-explorer") { + selectOption = "folder"; + } else { + selectOption = "file"; + } + + vscode.postMessage({ + command: "open-explorer", + payload: { + selectOption: selectOption, + }, + }); + + window.addEventListener( + "message", + (event: MessageEvent) => { + const message = event.data; + + if (message.command === "file-uri") { + const selectedUri = message.arguments.selectedUri; + + if (selectedUri) { + if (source === "folder-explorer") { + destinationPathUrlTextField.value = selectedUri; + initDestinationPathElement.innerHTML = selectedUri; + } else { + logFilePath.value = selectedUri; + } + } + } + }, + ); +} + +function handleInitClearClick() { + destinationPathUrlTextField.value = ""; + + initDestinationPathElement.innerHTML = + destinationPathUrlTextField.placeholder; + + overwriteCheckbox.checked = false; + verboseDropdown.currentValue = "Off"; + + initCreateButton.disabled = false; + + logToFileCheckbox.checked = false; + logFilePath.value = ""; + logFileAppendCheckbox.checked = false; + logLevelDropdown.currentValue = "Debug"; + initOpenScaffoldedFileButton.disabled = true; +} + +function toggleCreateButton() { + // update destination path

tag + initDestinationPathElement.innerHTML = + destinationPathUrlTextField.value.trim(); + + initCreateButton.disabled = false; +} + +function toggleLogToFileOptions() { + if (logToFileCheckbox.checked) { + if ( + logToFileOptionsDiv?.style.display === "" || + logToFileOptionsDiv?.style.display === "none" + ) { + logToFileOptionsDiv.style.display = "flex"; + } + } else { + if (logToFileOptionsDiv?.style.display === "flex") { + logToFileOptionsDiv.style.display = "none"; + } + } +} + +function handleInitCreateClick() { + initCreateButton.disabled = false; + + vscode.postMessage({ + command: "init-create", + payload: { + destinationPath: destinationPathUrlTextField.value.trim(), + verbosity: verboseDropdown.currentValue.trim(), + logToFile: logToFileCheckbox.checked, + logFilePath: logFilePath.value.trim(), + logFileAppend: logFileAppendCheckbox.checked, + logLevel: logLevelDropdown.currentValue.trim(), + isOverwritten: overwriteCheckbox.checked, + } as AnsibleSampleExecutionEnvInterface, + }); + + window.addEventListener( + "message", + async (event: MessageEvent) => { + const message = event.data; + + switch (message.command) { + case "execution-log": + initLogsTextArea.value = message.arguments.commandOutput; + logFileUrl = message.arguments.logFileUrl; + + if (logFileUrl) { + initOpenLogFileButton.disabled = false; + } else { + initOpenLogFileButton.disabled = true; + } + + if ( + message.arguments.status && + message.arguments.status === "passed" + ) { + initOpenScaffoldedFileButton.disabled = false; + } else { + initOpenScaffoldedFileButton.disabled = true; + } + + projectUrl = message.arguments.projectUrl + ? message.arguments.projectUrl + : ""; + + initCreateButton.disabled = false; + + return; + } + }, + ); +} + +function handleInitClearLogsClick() { + initLogsTextArea.value = ""; +} + +function handleInitOpenLogFileClick() { + vscode.postMessage({ + command: "init-open-log-file", + payload: { + logFileUrl: logFileUrl, + }, + }); +} + +function handleInitCopyLogsClick() { + vscode.postMessage({ + command: "init-copy-logs", + payload: { + initExecutionLogs: initLogsTextArea.value, + }, + }); +} + +function handleInitOpenScaffoldedFileClick() { + vscode.postMessage({ + command: "init-open-scaffolded-file", + payload: { + projectUrl: projectUrl, + }, + }); +} diff --git a/test/ui-test/contentCreatorUiTest.ts b/test/ui-test/contentCreatorUiTest.ts index 64243b7b1..4f35fe48a 100644 --- a/test/ui-test/contentCreatorUiTest.ts +++ b/test/ui-test/contentCreatorUiTest.ts @@ -84,3 +84,57 @@ describe("Test Ansible playbook project scaffolding", () => { ); }); }); + +describe("Test Ansible sample execution environment file scaffolding", () => { + let createEEButton: WebElement; + let editorView: EditorView; + + async function testWebViewElements(command: string, editorTitle: string) { + await workbenchExecuteCommand(command); + await sleep(4000); + + await new EditorView().openEditor(editorTitle); + const eeWebview = await getWebviewByLocator( + By.xpath("//vscode-text-field[@id='path-url']"), + ); + + const eeDestination = await eeWebview.findWebElement( + By.xpath("//vscode-text-field[@id='path-url']"), + ); + expect(eeDestination, "eeDestination should not be undefined").not.to.be + .undefined; + await eeDestination.sendKeys("~"); + + const overwriteCheckbox = await eeWebview.findWebElement( + By.xpath("//vscode-checkbox[@id='overwrite-checkbox']"), + ); + expect(overwriteCheckbox, "overwriteCheckbox should not be undefined").not + .to.be.undefined; + await overwriteCheckbox.click(); + + createEEButton = await eeWebview.findWebElement( + By.xpath("//vscode-button[@id='create-button']"), + ); + expect(createEEButton, "createEEButton should not be undefined").not.to.be + .undefined; + + expect( + await createEEButton.isEnabled(), + "createEEbutton should be enabled now", + ).to.be.true; + + await createEEButton.click(); + await eeWebview.switchBack(); + editorView = new EditorView(); + if (editorView) { + await editorView.closeAllEditors(); + } + } + + it("Check create-sample-execution-env-file webview elements", async () => { + await testWebViewElements( + "Ansible: Create a sample Ansible Execution Environment file", + "Create Sample Ansible Execution Environment", + ); + }); +}); diff --git a/webpack.config.ts b/webpack.config.ts index 28dbe79c6..53df1c1d4 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -237,6 +237,20 @@ const createDevfileWebviewConfig = { }, }; +const createSampleExecutionEnvWebviewConfig = { + ...config, + target: ["web", "es2020"], + entry: "./src/webview/apps/contentCreator/createSampleExecutionEnvPageApp.ts", + experiments: { outputModule: true }, + output: { + path: path.resolve(__dirname, "out"), + filename: + "./client/webview/apps/contentCreator/createSampleExecutionEnvPageApp.js", + libraryTarget: "module", + chunkFormat: "module", + }, +}; + // eslint-disable-next-line @typescript-eslint/no-explicit-any module.exports = (_env: any, argv: { mode: string }) => { // Use non-bundled js for client/server in dev environment @@ -256,5 +270,6 @@ module.exports = (_env: any, argv: { mode: string }) => { createAnsibleProjectWebviewConfig, createDevfileWebviewConfig, quickLinksWebviewConfig, + createSampleExecutionEnvWebviewConfig, ]; };