Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Contribute z/OS console panel #2925

Merged
merged 32 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
16070cf
Add zOS Console Panel
crshnburn May 3, 2024
d760b06
Remove debug and lint error
crshnburn May 7, 2024
cfa34fb
Fix linter error
crshnburn May 8, 2024
f322bf4
Fix unit tests
crshnburn May 12, 2024
f6257c7
Merge branch 'zowe:main' into zos-console-panel
crshnburn May 16, 2024
c8dcbae
Merge branch 'main' into zos-console-panel
JillieBeanSim May 30, 2024
6a298d7
Use monospace font
crshnburn Jun 5, 2024
f46a960
Make UI responsive to Panel size
crshnburn Jun 14, 2024
547c4c7
Scroll to bottom
crshnburn Jun 15, 2024
1e34e03
Fix SonarCloud warnings
crshnburn Jun 15, 2024
5da4132
Use secure RNG
crshnburn Jun 17, 2024
08d8d5a
Merge branch 'main' into zos-console-panel
crshnburn Jun 18, 2024
b0596f1
Merge branch 'main' into zos-console-panel
JillieBeanSim Jun 19, 2024
e24aa74
Merge branch 'main' into zos-console-panel
JillieBeanSim Jul 11, 2024
c3cefd4
Merge branch 'main' into zos-console-panel
JillieBeanSim Jul 25, 2024
ffbaccf
Merge branch 'main' into zos-console-panel
JillieBeanSim Jul 29, 2024
972ee8c
copyright added with yarn
JillieBeanSim Jul 29, 2024
cc2f733
update command and window view name to include ZE
JillieBeanSim Jul 30, 2024
79f45fe
Merge branch 'main' into zos-console-panel
JillieBeanSim Jul 31, 2024
b3483e4
Merge branch 'main' into zos-console-panel
SanthoshiBoyina1 Aug 3, 2024
f03daca
Allow project config and other registered profiles to appear in the p…
zFernand0 Aug 9, 2024
192036a
reuse HTML template from ZE APIs
zFernand0 Aug 9, 2024
8684693
Merge remote-tracking branch 'zowe/main' into zos-console-panel
JillieBeanSim Aug 13, 2024
96a0375
address lint and CHANGELOG checks
JillieBeanSim Aug 13, 2024
2885813
change VSC text field to Times New Roman option for webview
JillieBeanSim Aug 13, 2024
149f871
start of ZosConsolePanel unit test
JillieBeanSim Aug 14, 2024
f5eb0a1
fix
JillieBeanSim Aug 14, 2024
45574c6
Merge branch 'main' into zos-console-panel
JillieBeanSim Aug 16, 2024
75a042e
address format comments
JillieBeanSim Aug 20, 2024
1682960
update webview vite config
JillieBeanSim Aug 20, 2024
33f0e77
Update packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts
JillieBeanSim Aug 20, 2024
e50a578
Update codicon path in vite config
t1m0thyj Aug 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
{ "directory": "packages/zowe-explorer-ftp-extension", "changeProcessCWD": true },
{ "directory": "packages/zowe-explorer-api", "changeProcessCWD": true },
{ "directory": "packages/zowe-explorer", "changeProcessCWD": true }
]
],
"zopendebug.profileView.showWelcome": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IIssueParms {}

export class IssueCommand {}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jest.mock("util");
jest.mock("isbinaryfile");

async function createGlobalMocks() {
const mockReadProfilesFromDisk = jest.fn();
const mockReadProfilesFromDisk = jest.fn().mockReturnValue(Promise.resolve());
const globalMocks = {
mockLoadNamedProfile: jest.fn(),
mockMkdirSync: jest.fn(),
Expand All @@ -49,6 +49,7 @@ async function createGlobalMocks() {
mockCreateTreeView: jest.fn().mockReturnValue({ onDidCollapseElement: jest.fn() }),
mockExecuteCommand: jest.fn(),
mockRegisterCommand: jest.fn(),
mockRegisterWebviewViewProvider: jest.fn(),
mockOnDidCloseTextDocument: jest.fn(),
mockOnDidSaveTextDocument: jest.fn(),
mockOnDidChangeSelection: jest.fn(),
Expand Down Expand Up @@ -280,6 +281,10 @@ async function createGlobalMocks() {
value: globalMocks.mockRegisterCommand,
configurable: true,
});
Object.defineProperty(vscode.window, "registerWebviewViewProvider", {
value: globalMocks.mockRegisterWebviewViewProvider,
configurable: true,
});
Object.defineProperty(vscode.commands, "executeCommand", {
value: globalMocks.mockExecuteCommand,
configurable: true,
Expand Down
15 changes: 15 additions & 0 deletions packages/zowe-explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@
"title": "%viewsContainers.activitybar%",
"icon": "resources/zowe.svg"
}
],
"panel": [
{
"id": "zosconsole",
"title": "z/OS Console",
"icon": ""
}
]
},
"views": {
Expand All @@ -57,6 +64,13 @@
"id": "zowe.jobs.explorer",
"name": "%zowe.jobs.explorer%"
}
],
"zosconsole": [
{
"id": "zosconsole",
"name": "z/OS Console",
"type": "webview"
}
]
},
"keybindings": [
Expand Down Expand Up @@ -2107,6 +2121,7 @@
"sinon": "^6.1.0"
},
"dependencies": {
"@vscode/codicons": "^0.0.35",
"@zowe/secrets-for-zowe-sdk": "7.18.6",
"@zowe/zowe-explorer-api": "2.17.0-SNAPSHOT",
"dayjs": "^1.11.10",
Expand Down
3 changes: 3 additions & 0 deletions packages/zowe-explorer/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { initDatasetProvider } from "./dataset/init";
import { initUSSProvider } from "./uss/init";
import { initJobsProvider } from "./job/init";
import { ZoweLocalStorage } from "./utils/ZoweLocalStorage";
import { ZosConsoleViewProvider } from "./zosconsole/ZosConsolePanel";

/**
* The function that runs when the extension is loaded
Expand Down Expand Up @@ -65,6 +66,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<ZoweEx
await watchConfigProfile(context, providers);
globals.setActivated(true);
findRecoveredFiles();
const provider = new ZosConsoleViewProvider(context.extensionUri);
context.subscriptions.push(vscode.window.registerWebviewViewProvider(ZosConsoleViewProvider.viewType, provider));
return ZoweExplorerApiRegister.getInstance();
}
/**
Expand Down
80 changes: 80 additions & 0 deletions packages/zowe-explorer/src/webviews/src/zos-console/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Dropdown, Option, TextArea, TextField } from "@vscode/webview-ui-toolkit";
import { VSCodeDropdown, VSCodeTextArea, VSCodeTextField } from "@vscode/webview-ui-toolkit/react";
import { useEffect } from "preact/hooks";

declare const vscode: any;

export function App() {
useEffect(() => {
window.addEventListener("message", (event) => {
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
Dismissed Show dismissed Hide dismissed
github-advanced-security[bot] marked this conversation as resolved.
Show resolved Hide resolved
const message = event.data;
switch (message.type) {
case "commandResult":
const consoleResponse = document.getElementById("output") as TextArea;
consoleResponse!.value += `> ${message.cmd} (${message.profile})\n`;
consoleResponse!.value += message.result;
consoleResponse!.control.scrollTop = consoleResponse!.control.scrollHeight;
break;
case "optionsList":
const profileList = document.getElementById("systems") as Option;
for (const profile in message.profiles) {
const option = document.createElement("vscode-option");
option.textContent = message.profiles[profile];
if (message.profiles[profile] === message.defaultProfile) {
option.setAttribute("selected", "true");
}
profileList.appendChild(option);
}
break;
}
});
});

const sendCommand = (e: KeyboardEvent) => {
const consoleField = document.getElementById("command-input") as TextField;
const consoleResponse = document.getElementById("output") as TextArea;
const profileList = document.getElementById("systems") as Dropdown;
if (e.key === "Enter") {
if (consoleField!.value === "clear") {
consoleResponse.value = "";
consoleResponse.control.scrollTop = 0;
} else {
vscode.postMessage({
command: "opercmd",
profile: profileList.options[profileList.selectedIndex].text,
text: consoleField.value,
});
}
consoleField.value = "";
}
};

return (
<div>
<VSCodeDropdown id="systems" style={{ float: "right" }}></VSCodeDropdown>
<VSCodeTextArea
id="output"
readonly
rows="8"
resize="vertical"
style={{
width: "100%",
height: "100%",
overflow: "auto",
display: "block",
}}
></VSCodeTextArea>
<VSCodeTextField
id="command-input"
name="command-input"
type="text"
onKeyDown={(e: KeyboardEvent) => sendCommand(e)}
style={{
width: "100%",
}}
>
<span slot="start" class="codicon codicon-chevron-right"></span>
</VSCodeTextField>
</div>
);
}
12 changes: 12 additions & 0 deletions packages/zowe-explorer/src/webviews/src/zos-console/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>z/OS Console</title>
</head>
<body>
<div id="webviewRoot"></div>
<script type="module" src="./index.tsx"></script>
</body>
</html>
4 changes: 4 additions & 0 deletions packages/zowe-explorer/src/webviews/src/zos-console/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { render } from "preact";
import { App } from "./App";

render(<App />, document.getElementById("webviewRoot")!);
143 changes: 143 additions & 0 deletions packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/**
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*
*/

import * as vscode from "vscode";
import { ProfileInfo, IProfAttrs } from "@zowe/imperative";
import { IIssueParms, IssueCommand } from "@zowe/zos-console-for-zowe-sdk";

export class ZosConsoleViewProvider implements vscode.WebviewViewProvider {
public static readonly viewType = "zosconsole";

private _view?: vscode.WebviewView;

private profiles: Map<String, IProfAttrs> = new Map();
private defaultProfileName: string | undefined;

public constructor(private readonly _extensionUri: vscode.Uri) {
const profInfo = new ProfileInfo("zowe");
profInfo
.readProfilesFromDisk()
.then(() => {
const loadedProfiles = profInfo.getAllProfiles("zosmf");
const defaultProfile = profInfo.getDefaultProfile("zosmf");

Check warning on line 30 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L30

Added line #L30 was not covered by tests
this.defaultProfileName = defaultProfile?.profName;
loadedProfiles.forEach((profile) => {
this.profiles.set(profile.profName, profile);

Check warning on line 33 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L32-L33

Added lines #L32 - L33 were not covered by tests
});
})
.catch(() => {});
}

public resolveWebviewView(

Check warning on line 39 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L39

Added line #L39 was not covered by tests
webviewView: vscode.WebviewView,
_context: vscode.WebviewViewResolveContext<unknown>,
_token: vscode.CancellationToken

Check warning on line 42 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L42

Added line #L42 was not covered by tests
): void | Thenable<void> {
this._view = webviewView;

Check warning on line 44 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L44

Added line #L44 was not covered by tests

webviewView.webview.options = {

Check warning on line 46 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L46

Added line #L46 was not covered by tests
enableScripts: true,
localResourceRoots: [this._extensionUri],
};

webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);

Check warning on line 51 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L51

Added line #L51 was not covered by tests

webviewView.webview.onDidReceiveMessage(async (message: any) => {
const command = message.command;
const text = message.text;
const profile = message.profile;

Check warning on line 56 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L53-L56

Added lines #L53 - L56 were not covered by tests

switch (command) {
case "startup": {
const profileArray = [];
for (const profileName of this.profiles.keys()) {
profileArray.push(profileName);

Check warning on line 62 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L59-L62

Added lines #L59 - L62 were not covered by tests
}
webviewView.webview.postMessage({

Check warning on line 64 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L64

Added line #L64 was not covered by tests
type: "optionsList",
profiles: profileArray,
defaultProfile: this.defaultProfileName,
});
break;

Check warning on line 69 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L69

Added line #L69 was not covered by tests
}
case "opercmd":
webviewView.webview.postMessage({

Check warning on line 72 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L71-L72

Added lines #L71 - L72 were not covered by tests
type: "commandResult",
cmd: text,
profile: profile,
result: await this.runOperCmd(text, profile),
});
return;

Check warning on line 78 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L78

Added line #L78 was not covered by tests
}
});
}

private _getHtmlForWebview(webview: vscode.Webview): string {
const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, "src", "webviews", "dist", "zos-console", "zos-console.js"));
const codiconsUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, "node_modules", "@vscode/codicons", "dist", "codicon.css"));
JillieBeanSim marked this conversation as resolved.
Show resolved Hide resolved
const nonce = this.getNonce();

Check warning on line 86 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L83-L86

Added lines #L83 - L86 were not covered by tests

// Tip: Install the es6-string-html VS Code extension to enable code highlighting below
return /*html*/ `

Check warning on line 89 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L89

Added line #L89 was not covered by tests
<!DOCTYPE html>
<html lang="en">
<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'; font-src ${webview.cspSource};
style-src ${webview.cspSource}; script-src 'nonce-${nonce}';" />-->
<link href="${codiconsUri.toString()}" rel="stylesheet" />
</head>
<body>
<div id="webviewRoot"></div>
<script>
const vscode = acquireVsCodeApi();
window.onload = function() {
vscode.postMessage({ command: 'startup' });
};
</script>
<script type="module" nonce="${nonce}" src="${scriptUri.toString()}"></script>
</body>
</body>
</html>
`;
}

private async runOperCmd(command: string, profile: string): Promise<string> {
try {
const profInfo = new ProfileInfo("zowe");
await profInfo.readProfilesFromDisk();
const zosmfProfAttrs = this.profiles.get(profile);
const zosmfMergedArgs = profInfo.mergeArgsForProfile(zosmfProfAttrs, { getSecureVals: true });
const session = ProfileInfo.createSession(zosmfMergedArgs.knownArgs);

Check warning on line 120 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L114-L120

Added lines #L114 - L120 were not covered by tests

const parms: IIssueParms = {

Check warning on line 122 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L122

Added line #L122 was not covered by tests
command: command,
sysplexSystem: undefined,
solicitedKeyword: undefined,
async: "N",
};
const response = await IssueCommand.issue(session, parms);
return response.commandResponse;

Check warning on line 129 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L128-L129

Added lines #L128 - L129 were not covered by tests
} catch (e) {
return (e as Error).message;

Check warning on line 131 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L131

Added line #L131 was not covered by tests
}
}

private getNonce(): string {
let text = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));

Check warning on line 139 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L135-L139

Added lines #L135 - L139 were not covered by tests
}
return text;

Check warning on line 141 in packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts#L141

Added line #L141 was not covered by tests
}
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,11 @@
resolved "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.33.tgz"
integrity sha512-VdgpnD75swH9hpXjd34VBgQ2w2quK63WljodlUcOoJDPKiV+rPjHrcUc2sjLCNKxhl6oKqmsZgwOWcDAY2GKKQ==

"@vscode/codicons@^0.0.35":
version "0.0.35"
resolved "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.35.tgz#7424a647f39c6e71c86c1edf12bfc27196c8fba1"
integrity sha512-7iiKdA5wHVYSbO7/Mm0hiHD3i4h+9hKUe1O4hISAe/nHhagMwb2ZbFC8jU6d7Cw+JNT2dWXN2j+WHbkhT5/l2w==

"@vscode/webview-ui-toolkit@^1.2.2":
version "1.2.2"
resolved "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.2.2.tgz"
Expand Down
Loading