Skip to content

Commit

Permalink
Merge branch 'main' into fix/cred-loop-virtual-workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
JillieBeanSim authored Mar 4, 2025
2 parents 81d2501 + 0643906 commit d2a70f4
Show file tree
Hide file tree
Showing 16 changed files with 143 additions and 49 deletions.
2 changes: 2 additions & 0 deletions packages/zowe-explorer-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t
### New features and enhancements

- Added new `copyDataSetCrossLpar` API to provide ability to copy/paste data sets across LPARs. [#3012](https://github.com/zowe/zowe-explorer-vscode/issues/3012)
- Added new `fetchAttributes` API to `IZoweUSSTreeNode` to fetch latest attributes for UNIX files. [#3238](https://github.com/zowe/zowe-explorer-vscode/issues/3238)
- Added new `directConnectLogin` and `directConnectLogout` to the ZoweVsCodeExtension class. [#3346](https://github.com/zowe/zowe-explorer-vscode/issues/3346)
- Added new optional `refreshFavorites` to IZoweTree interface. [#3470](https://github.com/zowe/zowe-explorer-vscode/issues/3470)

### Bug fixes

Expand Down
6 changes: 6 additions & 0 deletions packages/zowe-explorer-api/src/tree/IZoweTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ export interface IZoweTree<T> extends vscode.TreeDataProvider<T>, Partial<vscode
*/
addFavorite(favorite: IZoweTreeNode): void | Promise<void>;

/**
* refresh favorites
* @param favorite Adds a favorite node
*/
refreshFavorites?(): void | Promise<void>;

/**
* Removes a favorite node
* @param favorite Adds a favorite node
Expand Down
5 changes: 5 additions & 0 deletions packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ export interface IZoweUSSTreeNode extends IZoweTreeNode {
*/
getAttributes(): Types.FileAttributes | PromiseLike<Types.FileAttributes>;

/**
* Fetches the attributes for the USS file/folder from host.
*/
fetchAttributes?(): Types.FileAttributes | PromiseLike<Types.FileAttributes>;

/**
* Sets the attributes for the USS file/folder.
*/
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 @@ -22,6 +22,8 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Fixed z/OS Console panel background colour to be in sync with the rest of the VS Code styling. [#3445](https://github.com/zowe/zowe-explorer-vscode/pull/3445)
- Fixed an issue seen with outdated profile information in the z/OS tree view data during upload and download of data set and USS files [#3457](https://github.com/zowe/zowe-explorer-vscode/issues/3457)
- Fixed issue where deleting too many nodes at once would cause the confirmation prompt to be oversized. [#3254](https://github.com/zowe/zowe-explorer-vscode/issues/3254)
- Fixed an issue with UNIX file edit attributes refresh button not updating/reverting values correctly. [#3238](https://github.com/zowe/zowe-explorer-vscode/issues/3238)
- Fixed an issue seen where extender favorites not showing in the tree views. [#3470](https://github.com/zowe/zowe-explorer-vscode/issues/3470)
- Fixed an issue where selecting items in table views would reset the column sort order. [#3473](https://github.com/zowe/zowe-explorer-vscode/issues/3473)
- Fixed an issue where data set migration status was incorrectly handled when the `migr` attribute was not present in the API response. [#3471](https://github.com/zowe/zowe-explorer-vscode/issues/3471)
- Fixed issue where users were prompted several times when using a profile with invalid credentials in a VS Code workspace. Now, the user is only prompted once per profile, allowing the user to enter in new credentials. [#3480](https://github.com/zowe/zowe-explorer-vscode/pull/3480)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ describe("ZoweExplorerExtender unit tests", () => {
const datasetTree = createDatasetTree(datasetSessionNode, blockMocks.altTypeProfile);
ZoweExplorerExtender.createInstance(datasetTree, undefined, undefined);
jest.spyOn(blockMocks.instTest.datasetProvider, "addSession");
jest.spyOn(blockMocks.instTest.datasetProvider, "refreshFavorites").mockImplementation();
await blockMocks.instTest.reloadProfiles();
expect(blockMocks.instTest.datasetProvider.addSession).toHaveBeenCalled();
});
Expand Down Expand Up @@ -129,6 +130,7 @@ describe("ZoweExplorerExtender unit tests", () => {
ZoweExplorerExtender.createInstance(datasetTree, ussTree, jobsTree);
jest.spyOn(SharedTreeProviders, "providers", "get").mockReturnValue({ ds: datasetTree, uss: ussTree, job: jobsTree });
jest.spyOn(blockMocks.instTest.datasetProvider, "addSession").mockImplementation(DatasetTree.prototype.addSession);
jest.spyOn(blockMocks.instTest.datasetProvider, "refreshFavorites").mockImplementation();
jest.spyOn(blockMocks.instTest.ussFileProvider, "addSession").mockImplementation(USSTree.prototype.addSession);
jest.spyOn(blockMocks.instTest.jobsProvider, "addSession").mockImplementation(JobTree.prototype.addSession);
const loadProfileSpy = jest.spyOn(ZoweTreeProvider.prototype as any, "loadProfileByPersistedProfile");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ describe("Tree Provider Unit Tests - function loadProfileByPersistedProfile", ()
globalMocks.testDSTree = DatasetInit.createDatasetTree(imperative.Logger.getAppLogger());
globalMocks.testDSTree.mSessionNodes = [{ label: "sestest", getProfileName: (): string => "profile1" }];
globalMocks.testDSTree.getSessions = (): string[] => ["profile1"];
globalMocks.testDSTree.addSingleSession = jest.fn();
globalMocks.testDSTree.addSingleSession = jest.fn().mockImplementationOnce(() => Promise.resolve());

const resetValidationSettingsSpy = jest.spyOn(SharedActions, "resetValidationSettings");
resetValidationSettingsSpy.mockImplementation();
Expand All @@ -596,7 +596,7 @@ describe("Tree Provider Unit Tests - function loadProfileByPersistedProfile", ()
const zoweLoggerWarnSpy = jest.spyOn(ZoweLogger, "warn");

await expect(ZoweTreeProvider.prototype["loadProfileByPersistedProfile"](globalMocks.testDSTree, "zosmf", true)).resolves.not.toThrow();
expect(globalMocks.testDSTree.addSingleSession).toHaveBeenCalledTimes(2);
expect(globalMocks.testDSTree.addSingleSession).toHaveBeenCalledTimes(1); // only once due to error thrown with getDefaultProfile
expect(resetValidationSettingsSpy).toHaveBeenCalled();
expect(zoweLoggerWarnSpy).toHaveBeenCalledTimes(1);
resetValidationSettingsSpy.mockClear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ describe("AttributeView unit tests", () => {
node.getParent = jest.fn().mockReturnValueOnce({ label: "parent node" } as IZoweUSSTreeNode);
await (view as any).onDidReceiveMessage({ command: "refresh" });
expect(treeProvider.refreshElement).toHaveBeenCalled();

expect(node.onUpdate).toHaveBeenCalledTimes(2);
});

it("dispatches node data to webview when 'ready' command is received", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,74 @@ describe("ZoweUSSNode Unit Tests - Function node.getAttributes", () => {
});
});

describe("ZoweUSSNode Unit Tests - Function node.fetchAttributes", () => {
const attrs1 = { owner: "aUser", uid: 0, gid: 1000, group: "USERS", perms: "rwxrwxrwx" };
const attrs2 = { owner: "bUser", uid: 0, gid: 1000, group: "USERS", perms: "rwxrw-rw-" };
const fileAttrs = [
{
gid: attrs2.gid,
uid: attrs2.uid,
group: attrs2.group,
mode: attrs2.perms,
user: attrs2.owner,
},
];
it("fetches the attributes for a file from host", async () => {
const fileEntry = new UssFile("testFile");
fileEntry.attributes = attrs1;
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(fileEntry);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: true,
apiResponse: { items: fileAttrs },
commandResponse: "",
});
jest.spyOn(node, "setAttributes").mockImplementation();
expect(await node.fetchAttributes()).toStrictEqual(attrs2);
lookupMock.mockRestore();
});
it("returns undefined if no entry is found", async () => {
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(undefined);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
it("returns undefined if API response success is false", async () => {
const fileEntry = new UssFile("testFile");
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(fileEntry);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: false,
apiResponse: { items: [] },
commandResponse: "",
});
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
it("returns undefined if API response apiResponse is empty array", async () => {
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(undefined);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: true,
apiResponse: { items: [] },
commandResponse: "",
});
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
it("returns undefined if API response apiResponse is more than 1 array/file attrs", async () => {
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(undefined);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: true,
apiResponse: { items: fileAttrs, fileAttrs },
commandResponse: "",
});
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
});

describe("ZoweUSSNode Unit Tests - Function node.setAttributes", () => {
const attrs = { owner: "aUser", uid: 0, gid: 1000, group: "USERS", perms: "rwxrwxrwx" };
it("sets the attributes for a file", () => {
Expand Down
31 changes: 6 additions & 25 deletions packages/zowe-explorer/l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -312,12 +312,6 @@
"Uploading file to USS tree": "Uploading file to USS tree",
"Upload action was cancelled.": "Upload action was cancelled.",
"Uploading USS file": "Uploading USS file",
"Are you sure you want to delete the following item?\nThis will permanently remove the following file or folder from your system.\n\n{0}/File names": {
"message": "Are you sure you want to delete the following item?\nThis will permanently remove the following file or folder from your system.\n\n{0}",
"comment": [
"File names"
]
},
"Delete action was canceled.": "Delete action was canceled.",
"Copying file structure...": "Copying file structure...",
"The paste operation is not supported for this node.": "The paste operation is not supported for this node.",
Expand Down Expand Up @@ -509,15 +503,8 @@
"Job name"
]
},
"Are you sure you want to delete the following {0} items?\nThis will permanently remove the following jobs from your system.\n\n{1}/Jobs lengthJob names": {
"message": "Are you sure you want to delete the following {0} items?\nThis will permanently remove the following jobs from your system.\n\n{1}",
"comment": [
"Jobs length",
"Job names"
]
},
"The following jobs were deleted: {0}/Deleted jobs": {
"message": "The following jobs were deleted: {0}",
"The following jobs were deleted: {0}{1}/Deleted jobs": {
"message": "The following jobs were deleted: {0}{1}",
"comment": [
"Deleted jobs"
]
Expand Down Expand Up @@ -757,19 +744,13 @@
"Data Sets to delete"
]
},
"Are you sure you want to delete the following {0} item(s)?\nThis will permanently remove these data sets and/or members from your system.\n\n{1}/Data Sets to delete lengthData Sets to delete": {
"message": "Are you sure you want to delete the following {0} item(s)?\nThis will permanently remove these data sets and/or members from your system.\n\n{1}",
"comment": [
"Data Sets to delete length",
"Data Sets to delete"
]
},
"Deleting items": "Deleting items",
"The following {0} item(s) were deleted: {1}/Data Sets deleted lengthData Sets deleted": {
"message": "The following {0} item(s) were deleted: {1}",
"The following {0} item(s) were deleted:\n{1}{2}/Data Sets deleted lengthData Sets deletedAdditional datasets count": {
"message": "The following {0} item(s) were deleted:\n{1}{2}",
"comment": [
"Data Sets deleted length",
"Data Sets deleted"
"Data Sets deleted",
"Additional datasets count"
]
},
"Name of member": "Name of member",
Expand Down
9 changes: 3 additions & 6 deletions packages/zowe-explorer/l10n/poeditor.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"Zowe Resources": ""
},
"zowe.zosconsole": {
"Zowe Explorer z/OS Console": ""
"z/OS Console": ""
},
"zowe.resources.name": {
"Zowe Resources": ""
Expand Down Expand Up @@ -593,7 +593,6 @@
"Uploading file to USS tree": "",
"Upload action was cancelled.": "",
"Uploading USS file": "",
"Are you sure you want to delete the following item?\nThis will permanently remove the following file or folder from your system.\n\n{0}": "",
"Delete action was canceled.": "",
"Copying file structure...": "",
"The paste operation is not supported for this node.": "",
Expand Down Expand Up @@ -687,8 +686,7 @@
"Failed to delete job {0}": "",
"Are you sure you want to delete the following item?\nThis will permanently remove the following job from your system.\n\n{0}": "",
"Job {0} was deleted.": "",
"Are you sure you want to delete the following {0} items?\nThis will permanently remove the following jobs from your system.\n\n{1}": "",
"The following jobs were deleted: {0}": "",
"The following jobs were deleted: {0}{1}": "",
"Download single spool operation not implemented by extender. Please contact the extension developer(s).": "",
"No spool files found for {0}": "",
"Modify Command": "",
Expand Down Expand Up @@ -779,9 +777,8 @@
"Uploading to data set": "",
"No data sets selected for deletion, cancelling...": "",
"Deleting data set(s): {0}": "",
"Are you sure you want to delete the following {0} item(s)?\nThis will permanently remove these data sets and/or members from your system.\n\n{1}": "",
"Deleting items": "",
"The following {0} item(s) were deleted: {1}": "",
"The following {0} item(s) were deleted:\n{1}{2}": "",
"Name of member": "",
"Creating new data set member {0}": "",
"Unable to create member.": "",
Expand Down
3 changes: 3 additions & 0 deletions packages/zowe-explorer/src/extending/ZoweExplorerExtender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,10 @@ export class ZoweExplorerExtender implements IApiExplorerExtender, IZoweExplorer
});
// profileType is used to load a default extender profile if no other profiles are populating the trees
await this.datasetProvider?.addSession({ profileType });
await this.datasetProvider?.refreshFavorites();
await this.ussFileProvider?.addSession({ profileType });
await this.ussFileProvider?.refreshFavorites();
await this.jobsProvider?.addSession({ profileType });
await this.jobsProvider?.refreshFavorites();
}
}
10 changes: 7 additions & 3 deletions packages/zowe-explorer/src/trees/dataset/DatasetTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,10 @@ export class DatasetTree extends ZoweTreeProvider<IZoweDatasetTreeNode> implemen
ZoweLogger.trace("DatasetTree.initializeFavorites called.");
this.log = log;
ZoweLogger.debug(vscode.l10n.t("Initializing profiles with data set favorites."));
await this.refreshFavorites();
}

public async refreshFavorites(): Promise<void> {
const lines: string[] = this.mHistory.readFavorites();
if (lines.length === 0) {
ZoweLogger.debug(vscode.l10n.t("No data set favorites found."));
Expand Down Expand Up @@ -437,8 +441,8 @@ export class DatasetTree extends ZoweTreeProvider<IZoweDatasetTreeNode> implemen
ZoweLogger.trace("DatasetTree.initializeFavChildNodeForProfile called.");
const profile = parentNode.getProfile();
let node: ZoweDatasetNode;
if (contextValue === Constants.DS_PDS_CONTEXT || contextValue === Constants.DS_DS_CONTEXT) {
if (contextValue === Constants.DS_PDS_CONTEXT) {
if (contextValue.includes(Constants.DS_PDS_CONTEXT) || contextValue.includes(Constants.DS_DS_CONTEXT)) {
if (contextValue.includes(Constants.DS_PDS_CONTEXT)) {
node = new ZoweDatasetNode({
label,
collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
Expand All @@ -465,7 +469,7 @@ export class DatasetTree extends ZoweTreeProvider<IZoweDatasetTreeNode> implemen
if (icon) {
node.iconPath = icon.path;
}
} else if (contextValue === Constants.DS_SESSION_CONTEXT) {
} else if (contextValue.includes(Constants.DS_SESSION_CONTEXT)) {
node = new ZoweDatasetNode({
label,
collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
Expand Down
4 changes: 4 additions & 0 deletions packages/zowe-explorer/src/trees/job/JobTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ export class JobTree extends ZoweTreeProvider<IZoweJobTreeNode> implements Types
ZoweLogger.trace("JobTree.initializeJobsTree called.");
this.log = log;
ZoweLogger.debug(vscode.l10n.t("Initializing profiles with jobs favorites."));
await this.refreshFavorites();
}

public async refreshFavorites(): Promise<void> {
const lines: string[] = this.mHistory.readFavorites();
if (lines.length === 0) {
ZoweLogger.debug(vscode.l10n.t("No jobs favorites found."));
Expand Down
19 changes: 8 additions & 11 deletions packages/zowe-explorer/src/trees/uss/USSAttributeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/

import { Types, Gui, MainframeInteraction, IZoweUSSTreeNode, WebView } from "@zowe/zowe-explorer-api";
import { Disposable, ExtensionContext } from "vscode";
import { ExtensionContext } from "vscode";
import { ZoweExplorerApiRegister } from "../../extending/ZoweExplorerApiRegister";
import { SharedContext } from "../shared/SharedContext";
import * as vscode from "vscode";
Expand All @@ -22,8 +22,6 @@ export class USSAttributeView extends WebView {
private readonly ussApi: MainframeInteraction.IUss;
private readonly canUpdate: boolean;

private onUpdateDisposable: Disposable;

public constructor(context: ExtensionContext, treeProvider: Types.IZoweUSSTreeType, node: IZoweUSSTreeNode) {
const label = node.label ? `Edit Attributes: ${node.label as string}` : "Edit Attributes";
super(label, "edit-attributes", context, {
Expand All @@ -45,14 +43,13 @@ export class USSAttributeView extends WebView {
switch (message.command) {
case "refresh":
if (this.canUpdate) {
this.onUpdateDisposable = this.ussNode.onUpdate(async (node) => {
await this.attachTag(node);
await this.panel.webview.postMessage({
attributes: await this.ussNode.getAttributes(),
name: node.fullPath,
readonly: this.ussApi.updateAttributes == null,
});
this.onUpdateDisposable.dispose();
const attrs = await this.ussNode.fetchAttributes();
await this.ussNode.setAttributes(attrs);
await this.attachTag(this.ussNode);
await this.panel.webview.postMessage({
attributes: await this.ussNode.getAttributes(),
name: this.ussNode.fullPath,
allowUpdate: false,
});

if (this.ussNode.getParent()) {
Expand Down
4 changes: 4 additions & 0 deletions packages/zowe-explorer/src/trees/uss/USSTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,10 @@ export class USSTree extends ZoweTreeProvider<IZoweUSSTreeNode> implements Types
ZoweLogger.trace("USSTree.initializeFavorites called.");
this.log = log;
ZoweLogger.debug(vscode.l10n.t("Initializing profiles with USS favorites."));
await this.refreshFavorites();
}

public async refreshFavorites(): Promise<void> {
const lines: string[] = this.mHistory.readFavorites();
if (lines.length === 0) {
ZoweLogger.debug(vscode.l10n.t("No USS favorites found."));
Expand Down
Loading

0 comments on commit d2a70f4

Please sign in to comment.