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 all 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
1 change: 1 addition & 0 deletions packages/zowe-explorer-api/src/vscode/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
*/

export * from "./WebView";
export * as HTMLTemplate from "./utils/HTMLTemplate";
10 changes: 6 additions & 4 deletions packages/zowe-explorer-api/src/vscode/ui/utils/HTMLTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@
/**
* HTML template that is compiled with Mustache to load a WebView instance at runtime.
*/
const HTMLTemplate: string = `
const HTMLTemplate: string = /*html*/ `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; font-src data:; img-src data: vscode-resource: https:; script-src 'nonce-{{ nonce }}';
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; font-src data: https:; img-src data: vscode-resource: https:; script-src 'nonce-{{ nonce }}';
style-src vscode-resource: 'unsafe-inline' http: https: data:;"
/>
<base href="{{ uris.resource.build }}">
{{{ style }}}
</head>
<body>
<noscript>You'll need to enable JavaScript to run this app.</noscript>
{{{ startup }}}
<div id="webviewRoot"></div>
<script type="module" nonce="{{ nonce }}" src="{{ uris.resource.script }}" />
</body>
Expand Down
2 changes: 2 additions & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen

### New features and enhancements

- Added new Zowe Explorer z/OS Console webview with access via VS Code command pallete to issue MVS Console commands.

### Bug fixes

- Fixed issue where creating a new team configuration file could cause Zowe Explorer to crash, resulting in all sessions disappearing from trees. [#2906](https://github.com/zowe/zowe-explorer-vscode/issues/2906)
Expand Down
12 changes: 12 additions & 0 deletions packages/zowe-explorer/__mocks__/@zowe/zos-console-for-zowe-sdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* 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.
*
*/

export interface IIssueParms {}
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 @@ -281,6 +282,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
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* 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 { createInstanceOfProfile, createIProfile } from "../../../__mocks__/mockCreators/shared";
import { ZosConsoleViewProvider } from "../../../src/zosconsole/ZosConsolePanel";
import { Profiles } from "../../../src/Profiles";
import * as vscode from "vscode";

describe("ZosConsoleViewProvider", () => {
function createGlobalMocks(): any {
const newMocks = {
imperativeProfile: createIProfile(),
profileInstance: null,
testWebView: {},
};
newMocks.testWebView = {
webview: {
postMessage: jest.fn(),
asWebviewUri: jest.fn(),
onDidReceiveMessage: jest.fn(),
},
};
newMocks.profileInstance = createInstanceOfProfile(newMocks.imperativeProfile);
Object.defineProperty(Profiles, "getInstance", {
value: jest.fn().mockReturnValue(newMocks.profileInstance),
configurable: true,
});
Object.defineProperty(vscode.Uri, "joinPath", { value: jest.fn(), configurable: true });

return newMocks;
}
describe("resolveWebviewView", () => {
it("should submit command", () => {
const globalMocks = createGlobalMocks();
const myconsole = new ZosConsoleViewProvider({} as any);
myconsole.resolveWebviewView(globalMocks.testWebView, {} as any, { isCancellationRequested: false } as any);
expect(globalMocks.testWebView.webview.onDidReceiveMessage).toBeCalled();
});
});
});
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": "zowezosconsole",
"title": "Zowe Explorer z/OS Console",
"icon": ""
}
]
},
"views": {
Expand All @@ -57,6 +64,13 @@
"id": "zowe.jobs.explorer",
"name": "%zowe.jobs.explorer%"
}
],
"zowezosconsole": [
{
"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.18.0-SNAPSHOT",
"dayjs": "^1.11.10",
Expand Down
3 changes: 2 additions & 1 deletion packages/zowe-explorer/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { ProfilesUtils } from "./utils/ProfilesUtils";
import { initializeSpoolProvider } from "./SpoolProvider";
import { cleanTempDir, hideTempFolder, findRecoveredFiles } from "./utils/TempFolder";
import { SettingsConfig } from "./utils/SettingsConfig";
import { registerCommonCommands, registerCredentialManager, registerRefreshCommand, watchConfigProfile } from "./shared/init";
import { registerCommonCommands, registerCredentialManager, registerRefreshCommand, registerZosConsoleView, watchConfigProfile } from "./shared/init";
import { ZoweLogger } from "./utils/LoggerUtils";
import { ZoweSaveQueue } from "./abstract/ZoweSaveQueue";
import { PollDecorator } from "./utils/DecorationProviders";
Expand Down Expand Up @@ -60,6 +60,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<ZoweEx
const providers = await TreeProviders.initializeProviders(context, { ds: initDatasetProvider, uss: initUSSProvider, job: initJobsProvider });

registerCommonCommands(context, providers);
registerZosConsoleView(context);
ZoweExplorerExtender.createInstance(providers.ds, providers.uss, providers.job);
await SettingsConfig.standardizeSettings();
watchConfigProfile(context);
Expand Down
6 changes: 6 additions & 0 deletions packages/zowe-explorer/src/shared/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { DatasetTree } from "../dataset/DatasetTree";
import { USSTree } from "../uss/USSTree";
import { ZosJobsProvider } from "../job/ZosJobsProvider";
import { CertificateWizard } from "../utils/CertificateWizard";
import { ZosConsoleViewProvider } from "../zosconsole/ZosConsolePanel";

// Set up localization
nls.config({
Expand Down Expand Up @@ -265,6 +266,11 @@ export function watchConfigProfile(context: vscode.ExtensionContext): void {
});
}

export function registerZosConsoleView(context: vscode.ExtensionContext): void {
const provider = new ZosConsoleViewProvider(context.extensionUri);
context.subscriptions.push(vscode.window.registerWebviewViewProvider(ZosConsoleViewProvider.viewType, provider));
}

export function initSubscribers(context: vscode.ExtensionContext, theProvider: IZoweTree<IZoweTreeNode>): void {
ZoweLogger.trace("shared.init.initSubscribers called.");
const theTreeView = theProvider.getTreeView();
Expand Down
3 changes: 2 additions & 1 deletion packages/zowe-explorer/src/webviews/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@vscode/codicons": "^0.0.33",
"typescript": "^4.5.3",
"vite": "^4.5.3",
"vite-plugin-checker": "^0.6.4"
"vite-plugin-checker": "^0.6.4",
"vite-plugin-static-copy": "^0.17.1"
}
}
95 changes: 95 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,95 @@
import { Dropdown, Option, TextArea, TextField } from "@vscode/webview-ui-toolkit";
import { VSCodeDropdown, VSCodeTextArea, VSCodeTextField } from "@vscode/webview-ui-toolkit/react";
import { useEffect, useState } from "preact/hooks";

declare const vscode: any;

export function App() {
const [consoleContent, setConsoleContent] = useState("");
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
// Prevent users from sending data into webview outside of extension/webview context
const eventUrl = new URL(event.origin);
const isWebUser =
(eventUrl.protocol === document.location.protocol && eventUrl.hostname === document.location.hostname) ||
eventUrl.hostname.endsWith(".github.dev");
const isLocalVSCodeUser = eventUrl.protocol === "vscode-webview:";

if (!isWebUser && !isLocalVSCodeUser) {
return;
}

const message = event.data;
const profileList = document.getElementById("systems") as Option;

switch (message.type) {
case "commandResult":
setConsoleContent(consoleContent + `> ${message.cmd} (${message.profile})\n${message.result}`);
break;
case "optionsList":
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 consoleResponse = document.getElementById("output") as TextArea;
consoleResponse.control.scrollTop = consoleResponse.control.scrollHeight;
});

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

return (
<div className="box">
<div style="display: flex; align-items: center; gap: 10px;">
<VSCodeTextField
id="command-input"
name="command-input"
type="text"
placeholder="Enter command here..."
onKeyDown={sendCommand}
style={{
width: "100%",
"font-family": "Consolas,monospace",
}}
>
<span slot="start" className="codicon codicon-chevron-right"></span>
</VSCodeTextField>
<VSCodeDropdown id="systems"></VSCodeDropdown>
</div>
<VSCodeTextArea
id="output"
readonly
resize="none"
value={consoleContent}
style={{
width: "100%",
height: "100%",
overflow: "auto",
display: "flex",
"font-family": "Consolas,monospace",
}}
></VSCodeTextArea>
</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")!);
13 changes: 13 additions & 0 deletions packages/zowe-explorer/src/webviews/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import preact from "@preact/preset-vite";
import * as path from "path";
import { readdirSync } from "fs";
import checker from "vite-plugin-checker";
import { viteStaticCopy } from "vite-plugin-static-copy";

// https://vitejs.dev/config/

Expand All @@ -40,6 +41,18 @@ export default defineConfig({
checker({
typescript: true,
}),
viteStaticCopy({
targets: [
{
src: "../../../node_modules/@vscode/codicons/dist/codicon.css",
dest: "codicons/",
},
{
src: "../../../node_modules/@vscode/codicons/dist/codicon.ttf",
dest: "codicons/",
},
],
}),
],
root: path.resolve(__dirname, "src"),
build: {
Expand Down
Loading
Loading