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

feat: Jobs tabular view #3050

Merged
merged 44 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
08e03c5
refactor: bring back jobs table view after merge
traeok Aug 9, 2024
b47d381
refactor: Move jobs table into JobsTableView class
traeok Aug 9, 2024
e5f2eeb
feat(table): respect conditions in Actions Bar; add 'Download job' op…
traeok Aug 12, 2024
3fdf169
refactor: Update 'Delete job' logic to use updated children
traeok Aug 12, 2024
c6afe2d
refactor: Move job table callbacks into static fns
traeok Aug 12, 2024
87a5b19
fix(eslint): Update parserOptions to point to right tsconfigs
traeok Aug 12, 2024
84cfbe2
wip: Implement feedback from UX
traeok Aug 13, 2024
a16d33b
fix(table): States for show/hide columns button
traeok Aug 13, 2024
5531e94
refactor(table): 'Reveal in tree' -> 'Display in tree'
traeok Aug 13, 2024
a67a0a8
feat: codicon support in webviews
traeok Aug 13, 2024
a558683
refactor(jobs/table): Improve title logic, add 'settings' to actions bar
traeok Aug 13, 2024
3b33c8f
fix(webviews): Make codicons work in VSIX
traeok Aug 13, 2024
3c0d6d5
tests: Resolve failing test cases
traeok Aug 13, 2024
724d857
refactor: improve column selector, add more job columns
traeok Aug 14, 2024
f2b1791
fix(job/table): Missing returns in buildTitle
traeok Aug 14, 2024
789eb9b
wip: unit tests for jobs table view
traeok Aug 14, 2024
97f2935
refactor: Organize JobTableView class
traeok Aug 15, 2024
3183f15
tests: Coverage for majority of fns in JobTableView
traeok Aug 15, 2024
35c85fb
Merge branch 'next' into rnd/tables
traeok Aug 15, 2024
5212acd
tests: Patch coverage for JobTableView.generateTable
traeok Aug 15, 2024
d5f7a40
chore: update ZE changelog
traeok Aug 15, 2024
d644e14
refactor: update changelog with issue #
traeok Aug 15, 2024
b5b5211
tests(jobs/table): cancelJobs, handleCommand cases
traeok Aug 15, 2024
13e0b1a
tests: Bump patch coverage for JobInit
traeok Aug 15, 2024
75c45e2
refactor: remove unused import in JobTableView
traeok Aug 15, 2024
16b7769
Bundle codicons in dist folder with Vite
t1m0thyj Aug 16, 2024
c4dad28
fix(lint): Update parserOptions.project globs in eslintrc
traeok Aug 16, 2024
dabef0b
fix(jobs/table): Invalid references to this
traeok Aug 16, 2024
4d311d0
refactor: add ret types, cleanup obj, reveal views
traeok Aug 19, 2024
036fff1
refactor: update jobPropertiesFor, fix tests
traeok Aug 19, 2024
c642330
refactor(table): Fix CSS styling; update reveal panel logic
traeok Aug 19, 2024
7f24fa8
l10n: Localize title/columns for jobs table
traeok Aug 19, 2024
e0fb97b
wip(test/table): Jobs table end-to-end test
traeok Aug 19, 2024
fae2baf
wip(fix): Use workbench view command if view is null
traeok Aug 19, 2024
a64fd71
refactor: update wdio-vscode-service dep, await setTableView
traeok Aug 19, 2024
3401da0
refactor(table/ux): Update disabled logic for actions bar items
traeok Aug 19, 2024
a7b477e
wip(test): Cleanup e2e table step; assign title to view
traeok Aug 19, 2024
fdfcce2
refactor(jobs/table): tabularView -> tableView
traeok Aug 19, 2024
a3c7eec
tests(e2e/table): Rename step/feature file, skip Job table e2e test o…
traeok Aug 20, 2024
4151c12
fix(tests): Finish e2e test for showing table, add test for toggle cols
traeok Aug 20, 2024
b07a19a
refactor: Move ActionsBar props into interface; update changelog
traeok Aug 20, 2024
75ae08c
fix(jobs/table): auto-size table columns
traeok Aug 20, 2024
153817a
refactor(ActionsBar): reference props in single object
traeok Aug 20, 2024
13e74b3
Merge branch 'next' into rnd/tables
traeok 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
29 changes: 16 additions & 13 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,29 @@ parserOptions:
ecmaVersion: 6
sourceType: module
project:
- "./tsconfig.json"
- "./tsconfig-tests.json"
- "**/tsconfig.json"
- "**/tsconfig-tests.json"
plugins:
- "@typescript-eslint"
- zowe-explorer
rules:
"@typescript-eslint/await-thenable": off
"@typescript-eslint/consistent-type-assertions": warn
"@typescript-eslint/explicit-function-return-type": [ 'error', {
# We only disallow the rules that provide value (i.e. that found some errors while configuring)
# Documentation: https://typescript-eslint.io/rules/explicit-function-return-type
allowHigherOrderFunctions: false,
allowFunctionsWithoutTypeParameters: false,
"@typescript-eslint/explicit-function-return-type": [
"error",
{
# We only disallow the rules that provide value (i.e. that found some errors while configuring)
# Documentation: https://typescript-eslint.io/rules/explicit-function-return-type
allowHigherOrderFunctions: false,
allowFunctionsWithoutTypeParameters: false,

# Disabling (i.e. setting to `false`) the following rule will force us to unnecessarily type built-in functions
# For example, to find the index of a profile in a profiles array we will have to go:
# FROM: profiles.findIndex((profile) => profile.name === "my_profile"))
# TO: profiles.findIndex((profile): boolean => profile.name === "my_profile"))
allowTypedFunctionExpressions: true,
}]
# Disabling (i.e. setting to `false`) the following rule will force us to unnecessarily type built-in functions
# For example, to find the index of a profile in a profiles array we will have to go:
# FROM: profiles.findIndex((profile) => profile.name === "my_profile"))
# TO: profiles.findIndex((profile): boolean => profile.name === "my_profile"))
allowTypedFunctionExpressions: true,
},
]
"@typescript-eslint/explicit-member-accessibility": error

# There are several errors falling under these rules; resolve
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ describe("Table.View", () => {
disk: {
build: Uri.parse(buildPath),
script: Uri.parse(scriptPath),
codicons: undefined,
css: undefined,
},
resource: {
build: buildPath,
script: scriptPath,
codicons: undefined,
css: undefined,
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ describe("TableViewProvider", () => {
const resolveForViewSpy = jest.spyOn(table, "resolveForView");
const fakeView = {
onDidDispose: jest.fn(),
show: jest.fn(),
viewType: "zowe.panel",
title: "SomeWebviewView",
webview: { asWebviewUri: jest.fn(), onDidReceiveMessage: jest.fn(), options: {} },
Expand Down
1 change: 1 addition & 0 deletions packages/zowe-explorer-api/src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export namespace Types {
build: Uri;
script: Uri;
css?: Uri;
codicons?: Uri;
};

export type FileAttributes = {
Expand Down
6 changes: 5 additions & 1 deletion packages/zowe-explorer-api/src/vscode/ui/TableView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export namespace Table {
export type Callback = SingleRowCallback | MultiRowCallback | CellCallback;

/** Conditional callback function - whether an action or option should be rendered. */
export type Conditional = (data: RowData | ContentTypes) => boolean;
export type Conditional = (data: RowData[] | RowData | ContentTypes) => boolean;
traeok marked this conversation as resolved.
Show resolved Hide resolved

// Defines the supported actions and related types.
export type ActionKind = "primary" | "secondary" | "icon";
Expand Down Expand Up @@ -200,6 +200,10 @@ export namespace Table {
columnMenu?: "legacy" | "new";
/** Set this to `true` to enable debugging information from the grid */
debug?: boolean;
/** Set this to `true` to allow checkbox selection, no matter what row is visible. */
selectEverything?: boolean;
/** Set this to suppress row-click selection, in favor of checkbox selection. */
suppressRowClickSelection?: boolean;
/** The height in pixels for the rows containing floating filters. */
floatingFiltersHeight?: number;
/** The height in pixels for the rows containing header column groups. */
Expand Down
6 changes: 4 additions & 2 deletions packages/zowe-explorer-api/src/vscode/ui/TableViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
*/

import { CancellationToken, WebviewView, WebviewViewProvider, WebviewViewResolveContext } from "vscode";
import { CancellationToken, commands, WebviewView, WebviewViewProvider, WebviewViewResolveContext } from "vscode";
import { Table } from "./TableView";

/**
Expand Down Expand Up @@ -60,7 +60,7 @@ export class TableViewProvider implements WebviewViewProvider {
* Provide a table view to display in the "Zowe Resources" view.
* @param tableView The table view to prepare for rendering
*/
public setTableView(tableView: Table.Instance | null): void {
public async setTableView(tableView: Table.Instance | null): Promise<void> {
traeok marked this conversation as resolved.
Show resolved Hide resolved
if (this.tableView != null) {
this.tableView.dispose();
}
Expand All @@ -75,6 +75,8 @@ export class TableViewProvider implements WebviewViewProvider {

if (this.view) {
this.tableView.resolveForView(this.view);
} else {
await commands.executeCommand("workbench.view.extension.zowe-panel");
}
}

Expand Down
10 changes: 9 additions & 1 deletion packages/zowe-explorer-api/src/vscode/ui/WebView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,31 +73,36 @@ export class WebView {

this.webviewOpts = opts;

const codiconPath = joinPath(context.extensionPath, "src", "webviews", "dist", "codicons", "codicon.css");
const cssPath = joinPath(context.extensionPath, "src", "webviews", "dist", "style", "style.css");
const codiconsExists = fs.existsSync(codiconPath);
const cssExists = fs.existsSync(cssPath);

// Build URIs for the webview directory and get the paths as VScode resources
this.uris.disk = {
build: Uri.file(joinPath(context.extensionPath, "src", "webviews")),
script: Uri.file(joinPath(context.extensionPath, "src", "webviews", "dist", webviewName, `${webviewName}.js`)),
codicons: codiconsExists ? Uri.file(codiconPath) : undefined,
css: cssExists ? Uri.file(cssPath) : undefined,
};

if (!(opts?.isView ?? false)) {
this.panel = window.createWebviewPanel("ZEAPIWebview", this.title, ViewColumn.Beside, {
enableScripts: true,
localResourceRoots: [this.uris.disk.build],
localResourceRoots: [this.uris.disk.build, this.uris.disk.codicons],
retainContextWhenHidden: opts?.retainContext ?? false,
});

// Associate URI resources with webview
this.uris.resource = {
build: this.panel.webview.asWebviewUri(this.uris.disk.build),
script: this.panel.webview.asWebviewUri(this.uris.disk.script),
codicons: this.uris.disk.codicons ? this.panel.webview.asWebviewUri(this.uris.disk.codicons) : undefined,
css: this.uris.disk.css ? this.panel.webview.asWebviewUri(this.uris.disk.css) : undefined,
};

const builtHtml = Mustache.render(HTMLTemplate, {
cspSource: this.panel.webview.cspSource,
unsafeEval: this.webviewOpts?.unsafeEval,
uris: this.uris,
nonce: this.nonce,
Expand All @@ -122,10 +127,12 @@ export class WebView {
this.uris.resource = {
build: webviewView.webview.asWebviewUri(this.uris.disk.build),
script: webviewView.webview.asWebviewUri(this.uris.disk.script),
codicons: this.uris.disk.codicons ? webviewView.webview.asWebviewUri(this.uris.disk.codicons) : undefined,
css: this.uris.disk.css ? webviewView.webview.asWebviewUri(this.uris.disk.css) : undefined,
};

const builtHtml = Mustache.render(HTMLTemplate, {
cspSource: webviewView.webview.cspSource,
unsafeEval: this.webviewOpts?.unsafeEval,
uris: this.uris,
nonce: this.nonce,
Expand All @@ -137,6 +144,7 @@ export class WebView {
}
webviewView.onDidDispose(() => this.dispose(), null, this.disposables);
webviewView.webview.html = this.webviewContent;
webviewView.show();
this.view = webviewView;
}

Expand Down
zFernand0 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*
*/

/* eslint-disable max-len */

/**
* HTML template that is compiled with Mustache to load a WebView instance at runtime.
*/
Expand All @@ -21,13 +23,16 @@ const HTMLTemplate: string = `
<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 {{#unsafeEval}}'unsafe-eval'{{/unsafeEval}} 'nonce-{{ nonce }}';
style-src vscode-resource: 'unsafe-inline' http: https: data:;"
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:;"
/>
<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}}
</head>
<body>
<noscript>You'll need to enable JavaScript to run this app.</noscript>
Expand Down
1 change: 1 addition & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Changed default base profile naming scheme in newly generated configuration files to prevent name and property conflicts between Global and Project profiles [#2682](https://github.com/zowe/zowe-explorer-vscode/issues/2682)
- Implemented the `onCredMgrUpdate` VSCode events to notify extenders when the local PC's credential manager has been updated by other applications. [#2994](https://github.com/zowe/zowe-explorer-vscode/pull/2994)
- Implemented support for building, exposing and displaying table views within Zowe Explorer. Tables can be customized and exposed using the helper facilities (`TableBuilder` and `TableMediator`) for an extender's specific use case. For more information on how to configure and show tables, please refer to the [wiki article on Table Views](https://github.com/zowe/zowe-explorer-vscode/wiki/Table-Views). [#2258](https://github.com/zowe/zowe-explorer-vscode/issues/2258)
- Implemented a "Show as Table" option for profile nodes in the Jobs tree, displaying lists of jobs in a tabular view. Jobs can be filtered and sorted within this view, and users can select jobs to cancel, delete or download. [#2258](https://github.com/zowe/zowe-explorer-vscode/issues/2258)

### Bug fixes

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Feature: Jobs table view

Scenario: User wants to list their jobs in the table view
Given a user who is looking at the Zowe Explorer tree views
And the user has a profile in their Data Sets tree
When a user sets a filter search on the profile
Then the profile node will list results of the filter search
And the user has a profile in their Jobs tree
When a user sets a filter search on the profile
Then the profile node will list results of the filter search
And the user can right-click on the jobs profile and select "Show as Table"
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* 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 { Then } from "@cucumber/cucumber";
import { ContextMenu } from "wdio-vscode-service";

Then('the user can right-click on the jobs profile and select "Show as Table"', async function () {
const ctxMenu: ContextMenu = await this.profileNode.openContextMenu();
await ctxMenu.wait();
traeok marked this conversation as resolved.
Show resolved Hide resolved
const showAsTableItem = await ctxMenu.getItem("Show as Table");
await (await showAsTableItem.elem).click();
const bottomBar = (await browser.getWorkbench()).getBottomBar();
await bottomBar.toggle(true);
await (bottomBar as any).openTab("Zowe Resources");
await (await $("#webviewRoot > div")).waitForExist();
});
11 changes: 11 additions & 0 deletions packages/zowe-explorer/__tests__/__mocks__/mockCreators/jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,17 @@ export function createJobNode(session: any, profile: imperative.IProfileLoaded)
return jobNode;
}

export function createJobInfoNode(session: any, profile: imperative.IProfileLoaded) {
const jobNode = new ZoweJobNode({
label: "Generic node for displaying information",
collapsibleState: vscode.TreeItemCollapsibleState.None,
parentNode: session.getSessionNode(),
profile,
});
jobNode.contextValue = Constants.INFORMATION_CONTEXT;
return jobNode;
}

export function createJobFavoritesNode() {
const jobFavoritesNode = new ZoweJobNode({
label: "Favorites",
Expand Down
16 changes: 10 additions & 6 deletions packages/zowe-explorer/__tests__/__mocks__/mockUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class MockedProperty {
#val: any;
#valType: MockedValueType;
#objRef: any;
#originalDescriptor?: PropertyDescriptor;
#originalDescriptor: PropertyDescriptor | undefined;

private initValueType() {
if (typeof this.#val === "function" || jest.isMockFunction(this.#val)) {
Expand All @@ -49,15 +49,19 @@ export class MockedProperty {
throw new Error("Null or undefined object passed to MockedProperty");
}
this.#objRef = object;
this.#originalDescriptor = descriptor ?? Object.getOwnPropertyDescriptor(object, key);
this.#originalDescriptor = Object.getOwnPropertyDescriptor(object, key);

if (!value) {
this.#val = jest.fn();
this.#valType = MockedValueType.Function;
Object.defineProperty(object, key, {
value: this.#val,
configurable: true,
});
Object.defineProperty(
object,
key,
descriptor ?? {
value: this.#val,
configurable: true,
}
);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ function createGlobalMocks() {
"zowe.jobs.sortBy",
"zowe.jobs.filterJobs",
"zowe.jobs.copyName",
"zowe.jobs.tabularView",
"zowe.updateSecureCredentials",
"zowe.manualPoll",
"zowe.editHistory",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { SharedActions } from "../../../../src/trees/shared/SharedActions";
import { SharedContext } from "../../../../src/trees/shared/SharedContext";
import { JobInit } from "../../../../src/trees/job/JobInit";
import { SharedInit } from "../../../../src/trees/shared/SharedInit";
import { JobTableView } from "../../../../src/trees/job/JobTableView";

describe("Test src/jobs/extension", () => {
describe("initJobsProvider", () => {
Expand Down Expand Up @@ -138,6 +139,10 @@ describe("Test src/jobs/extension", () => {
name: "zowe.jobs.filterJobs",
mock: [{ spy: jest.spyOn(jobsProvider, "filterJobsDialog"), arg: [test.value] }],
},
{
name: "zowe.jobs.tabularView",
mock: [{ spy: jest.spyOn(JobTableView, "handleCommand"), arg: [test.context, test.value, undefined] }],
},
];

beforeAll(async () => {
Expand Down
Loading
Loading