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

Port zosconsole to next #3058

Merged
merged 33 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
973ba6e
Add zOS Console Panel
crshnburn May 3, 2024
17d2cb1
Remove debug and lint error
crshnburn May 7, 2024
bcd084c
Fix linter error
crshnburn May 8, 2024
994d7e2
Fix unit tests
crshnburn May 12, 2024
8cd0343
Use monospace font
crshnburn Jun 5, 2024
ceddc15
Make UI responsive to Panel size
crshnburn Jun 14, 2024
f50706e
Scroll to bottom
crshnburn Jun 15, 2024
5b7ac46
Fix SonarCloud warnings
crshnburn Jun 15, 2024
df11a12
Use secure RNG
crshnburn Jun 17, 2024
d378a59
add copyright with pnpm
JillieBeanSim Aug 21, 2024
c7ac218
update command and window view name to include ZE
JillieBeanSim Jul 30, 2024
cdb1b04
Allow project config and other registered profiles to appear in the p…
zFernand0 Aug 9, 2024
bf79d58
reuse HTML template from ZE APIs
zFernand0 Aug 9, 2024
49b9451
change VSC text field to Times New Roman option for webview
JillieBeanSim Aug 13, 2024
82f8be4
start of ZosConsolePanel unit test
JillieBeanSim Aug 14, 2024
b92d7f8
fix
JillieBeanSim Aug 14, 2024
95dc420
address format comments
JillieBeanSim Aug 20, 2024
5974634
Update packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts
JillieBeanSim Aug 20, 2024
bf51422
Update codicon path in vite config
t1m0thyj Aug 20, 2024
0da91e3
fix a test suite
JillieBeanSim Aug 21, 2024
1343aed
fix job action unit test failures
JillieBeanSim Aug 21, 2024
5882b81
remove duplicate registration code
JillieBeanSim Aug 21, 2024
0abb032
remove unused import
JillieBeanSim Aug 21, 2024
4cbaa56
repair merge fix for output in console
JillieBeanSim Aug 21, 2024
efcc273
revert HTMLTemplate changes
JillieBeanSim Aug 22, 2024
48b9b8c
Merge branch 'next' into port/zosconsole
JillieBeanSim Aug 28, 2024
508d390
re-revert HTMLTemplate
JillieBeanSim Aug 28, 2024
322b5f9
mark classes deprecated and localize zosconsole id names
JillieBeanSim Aug 28, 2024
9dd8b91
Merge branch 'next' into port/zosconsole
JillieBeanSim Sep 3, 2024
c64bef8
add uri html back
JillieBeanSim Sep 3, 2024
9e785cf
Merge branch 'next' into port/zosconsole
JillieBeanSim Sep 5, 2024
9814d93
fix(webviews): Keep cspSource and unsafeEval checks in HTMLTemplate
traeok Sep 5, 2024
91591c8
Merge branch 'next' into port/zosconsole
JillieBeanSim Sep 5, 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 @@ -14,3 +14,4 @@ export * from "./utils/TableMediator";
export * from "./TableView";
export * from "./TableViewProvider";
export * from "./WebView";
export * as HTMLTemplate from "./utils/HTMLTemplate";
18 changes: 7 additions & 11 deletions packages/zowe-explorer-api/src/vscode/ui/utils/HTMLTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,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: {{ cspSource }}; img-src data: vscode-resource: https:; script-src {{#unsafeEval}}'unsafe-eval'{{/unsafeEval}} 'nonce-{{ nonce }}';
style-src {{ cspSource }} vscode-resource: 'unsafe-inline' http: https: data:;"
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; font-src data: https:; img-src data: vscode-resource: https:; script-src 'nonce-{{ nonce }}';
zFernand0 marked this conversation as resolved.
Show resolved Hide resolved
style-src vscode-resource: 'unsafe-inline' http: https: data:;"
/>
<base href="{{ uris.resource.build }}">
{{#uris.resource.css}}
<link type="text/css" rel="stylesheet" href="{{ uris.resource.css }}" />
{{/uris.resource.css}}
{{#uris.resource.codicons}}
<link type="text/css" rel="stylesheet" href="{{ uris.resource.codicons }}" />
{{/uris.resource.codicons}}
Copy link
Member

@traeok traeok Aug 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is required to support our webviews in v3 - we should add these back to avoid breaking other webviews

{{{ style }}}
zFernand0 marked this conversation as resolved.
Show resolved Hide resolved
</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
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 {}
10 changes: 8 additions & 2 deletions packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ jest.mock("fs-extra");
jest.mock("util");
jest.mock("isbinaryfile");

function createGlobalMocks() {
const mockReadProfilesFromDisk = jest.fn();
async function createGlobalMocks() {
const mockReadProfilesFromDisk = jest.fn().mockReturnValue(Promise.resolve());
const globalMocks = {
mockLoadNamedProfile: jest.fn(),
mockMkdirSync: jest.fn(),
Expand All @@ -50,6 +50,8 @@ 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(),
mockOnDidChangeConfiguration: jest.fn(),
Expand Down Expand Up @@ -257,6 +259,10 @@ 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/configuration/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();
});
});
});
13 changes: 13 additions & 0 deletions packages/zowe-explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
"id": "zowe-panel",
"icon": "resources/zowe.svg",
"title": "%viewsContainers.panel.tableView%"
},
{
"id": "zowezosconsole",
"title": "Zowe Explorer z/OS Console",
"icon": ""
}
]
},
Expand All @@ -70,6 +75,13 @@
"id": "zowe-resources",
"name": "%zowe.resources.name%"
}
],
"zowezosconsole": [
{
"id": "zosconsole",
"name": "z/OS Console",
"type": "webview"
}
]
},
"keybindings": [
Expand Down Expand Up @@ -1841,6 +1853,7 @@
"@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202407232256",
"@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202407232256",
"@zowe/zowe-explorer-api": "3.0.0-next-SNAPSHOT",
"@vscode/codicons": "^0.0.35",
"dayjs": "^1.11.10",
"fs-extra": "8.0.1",
"isbinaryfile": "4.0.4",
Expand Down
4 changes: 4 additions & 0 deletions packages/zowe-explorer/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { SharedInit } from "./trees/shared/SharedInit";
import { SharedTreeProviders } from "./trees/shared/SharedTreeProviders";
import { USSInit } from "./trees/uss/USSInit";
import { ProfilesUtils } from "./utils/ProfilesUtils";
import { ZosConsoleViewProvider } from "./zosconsole/ZosConsolePanel";

/**
* The function that runs when the extension is loaded
Expand All @@ -47,11 +48,14 @@ export async function activate(context: vscode.ExtensionContext): Promise<ZoweEx
async () => SharedInit.setupRemoteWorkspaceFolders()
);
SharedInit.registerCommonCommands(context, providers);
SharedInit.registerZosConsoleView(context);
SharedInit.registerRefreshCommand(context, activate, deactivate);
ZoweExplorerExtender.createInstance(providers.ds, providers.uss, providers.job);

SharedInit.watchConfigProfile(context);
await SharedInit.watchForZoweButtonClick();
const provider = new ZosConsoleViewProvider(context.extensionUri);
context.subscriptions.push(vscode.window.registerWebviewViewProvider(ZosConsoleViewProvider.viewType, provider));

return ZoweExplorerApiRegister.getInstance();
}
Expand Down
6 changes: 6 additions & 0 deletions packages/zowe-explorer/src/trees/shared/SharedInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { SharedUtils } from "./SharedUtils";
import { SharedContext } from "./SharedContext";
import { TreeViewUtils } from "../../utils/TreeViewUtils";
import { CertificateWizard } from "../../utils/CertificateWizard";
import { ZosConsoleViewProvider } from "../../zosconsole/ZosConsolePanel";

export class SharedInit {
public static registerRefreshCommand(
Expand Down Expand Up @@ -423,6 +424,11 @@ export class SharedInit {
ZoweLogger.zeOutputChannel = await LoggerUtils.initVscLogger(context, logsPath);
}

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

/**
* Initialize Zowe Explorer UI functions
* Function can only run one time during runtime, otherwise it will immediately return
Expand Down
93 changes: 93 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,93 @@
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";

export function App() {
const [consoleContent, setConsoleContent] = useState("");
useEffect(() => {
window.addEventListener("message", (event) => {
Dismissed Show dismissed Hide dismissed
// 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 {
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")!);
4 changes: 2 additions & 2 deletions packages/zowe-explorer/src/webviews/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ export default defineConfig({
viteStaticCopy({
targets: [
{
src: "../node_modules/@vscode/codicons/dist/codicon.css",
src: "../../../node_modules/@vscode/codicons/dist/codicon.css",
dest: "codicons/",
},
{
src: "../node_modules/@vscode/codicons/dist/codicon.ttf",
src: "../../../node_modules/@vscode/codicons/dist/codicon.ttf",
dest: "codicons/",
},
],
Expand Down
Loading
Loading