From 96c7402597f7e6e11418dd6091696b53a39c5c21 Mon Sep 17 00:00:00 2001 From: JWaters02 Date: Tue, 18 Feb 2025 17:16:52 +0000 Subject: [PATCH] Fixed deleting too many jobs/uss files/datasets at once causes confirmation prompt to be oversized (#3448) * Fix #3254 Signed-off-by: JWaters02 * Fix oversized prompt for deleting USS files Signed-off-by: JWaters02 * Fix oversized prompt for deleting datasets Signed-off-by: JWaters02 Update changelog entry to be more generic Signed-off-by: JWaters02 * Fix duplicate changelog entries Signed-off-by: Timothy Johnson --------- Signed-off-by: JWaters02 Signed-off-by: Joshua Waters Signed-off-by: Billie Simmons Signed-off-by: Timothy Johnson Co-authored-by: Billie Simmons Co-authored-by: Timothy Johnson --- packages/zowe-explorer/CHANGELOG.md | 2 ++ .../trees/dataset/DatasetActions.unit.test.ts | 20 +++++++++--------- .../src/trees/dataset/DatasetActions.ts | 20 ++++++++++++------ .../zowe-explorer/src/trees/job/JobActions.ts | 17 ++++++++++----- .../zowe-explorer/src/trees/uss/USSActions.ts | 21 +++++++++---------- 5 files changed, 48 insertions(+), 32 deletions(-) diff --git a/packages/zowe-explorer/CHANGELOG.md b/packages/zowe-explorer/CHANGELOG.md index 2244d852ff..432525c152 100644 --- a/packages/zowe-explorer/CHANGELOG.md +++ b/packages/zowe-explorer/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen ### Bug fixes +- 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) + ## `3.1.1` ### New features and enhancements diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts index d82004ccf9..a1fd4f96f1 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts @@ -509,7 +509,7 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 1 item(s) were deleted: ${blockMocks.testDatasetNode.getLabel().toString()}` + `The following 1 item(s) were deleted:\n ${blockMocks.testDatasetNode.getLabel().toString()}` ); }); @@ -526,7 +526,7 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 1 item(s) were deleted: ` + + `The following 1 item(s) were deleted:\n ` + `${blockMocks.testMemberNode.getParent().getLabel().toString()}(${blockMocks.testMemberNode.getLabel().toString()})` ); }); @@ -543,7 +543,7 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 1 item(s) were deleted: ${blockMocks.testVsamNode.getLabel().toString()}` + `The following 1 item(s) were deleted:\n ${blockMocks.testVsamNode.getLabel().toString()}` ); }); @@ -559,7 +559,7 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 1 item(s) were deleted: ${blockMocks.testMigrNode.getLabel().toString()}` + `The following 1 item(s) were deleted:\n ${blockMocks.testMigrNode.getLabel().toString()}` ); }); @@ -575,8 +575,8 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 2 item(s) were deleted: ` + - `${blockMocks.testDatasetNode.getLabel().toString()}, ${blockMocks.testVsamNode.getLabel().toString()}` + `The following 2 item(s) were deleted:\n ` + + `${blockMocks.testDatasetNode.getLabel().toString()}\n ${blockMocks.testVsamNode.getLabel().toString()}` ); }); @@ -592,7 +592,7 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 1 item(s) were deleted: ${blockMocks.testDatasetNode.getLabel().toString()}` + `The following 1 item(s) were deleted:\n ${blockMocks.testDatasetNode.getLabel().toString()}` ); }); @@ -658,8 +658,8 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 2 item(s) were deleted: ` + - `${blockMocks.testDatasetNode.getLabel().toString()}, ${blockMocks.testFavoritedNode.getLabel().toString()}` + `The following 2 item(s) were deleted:\n ` + + `${blockMocks.testDatasetNode.getLabel().toString()}\n ${blockMocks.testFavoritedNode.getLabel().toString()}` ); }); @@ -685,7 +685,7 @@ describe("Dataset Actions Unit Tests - Function deleteDatasetPrompt", () => { await DatasetActions.deleteDatasetPrompt(blockMocks.testDatasetTree, blockMocks.testMemberNode); expect(mocked(Gui.showMessage)).toHaveBeenCalledWith( - `The following 1 item(s) were deleted: ` + + `The following 1 item(s) were deleted:\n ` + `${blockMocks.testMemberNode.getParent().getLabel().toString()}(${blockMocks.testMemberNode.getLabel().toString()})` ); }); diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts b/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts index 64559ef8f3..ab8a6ba401 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts @@ -587,6 +587,10 @@ export class DatasetActions { return SharedContext.isDsMember(deletedNode) ? deletedNode.getParent() : ` ${deletedNode.getLabel().toString()}`; }); + const MAX_DISPLAYED_DATASET_NAMES = 10; + const displayedDatasetNames = nodesToDelete.slice(0, MAX_DISPLAYED_DATASET_NAMES).join("\n"); + const additionalDatasetsCount = nodesToDelete.length - MAX_DISPLAYED_DATASET_NAMES; + // Confirm that the user really wants to delete ZoweLogger.debug( vscode.l10n.t({ @@ -597,9 +601,11 @@ export class DatasetActions { ); const deleteButton = vscode.l10n.t("Delete"); const message = vscode.l10n.t({ - 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}`, - args: [nodesToDelete.length, nodesToDelete.toString().replace(/(,)/g, "\n")], - comment: ["Data Sets to delete length", "Data Sets to delete"], + message: + `Are you sure you want to delete the following {0} item(s)?\n` + + `This will permanently remove these data sets and/or members from your system.\n\n{1}{2}`, + args: [nodesToDelete.length, displayedDatasetNames, additionalDatasetsCount > 0 ? `\n...and ${additionalDatasetsCount} more` : ""], + comment: ["Data Sets to delete length", "Data Sets to delete", "Additional datasets count"], }); await Gui.warningMessage(message, { items: [deleteButton], @@ -651,11 +657,13 @@ export class DatasetActions { } if (nodesDeleted.length > 0) { nodesDeleted.sort((a, b) => a.localeCompare(b)); + const displayedDeletedNames = nodesDeleted.slice(0, MAX_DISPLAYED_DATASET_NAMES).join("\n"); + const additionalDeletedCount = nodesDeleted.length - MAX_DISPLAYED_DATASET_NAMES; Gui.showMessage( vscode.l10n.t({ - message: "The following {0} item(s) were deleted: {1}", - args: [nodesDeleted.length, nodesDeleted.toString().trim()], - comment: ["Data Sets deleted length", "Data Sets deleted"], + message: "The following {0} item(s) were deleted:\n{1}{2}", + args: [nodesDeleted.length, displayedDeletedNames, additionalDeletedCount > 0 ? `\n...and ${additionalDeletedCount} more` : ""], + comment: ["Data Sets deleted length", "Data Sets deleted", "Additional datasets count"], }) ); } diff --git a/packages/zowe-explorer/src/trees/job/JobActions.ts b/packages/zowe-explorer/src/trees/job/JobActions.ts index 3d47b6016f..e838fb6586 100644 --- a/packages/zowe-explorer/src/trees/job/JobActions.ts +++ b/packages/zowe-explorer/src/trees/job/JobActions.ts @@ -62,11 +62,16 @@ export class JobActions { ZoweLogger.trace("job.actions.deleteMultipleJobs called."); const deleteButton = vscode.l10n.t("Delete"); const toJobname = (jobNode: IZoweJobTreeNode): string => `${jobNode.job.jobname}(${jobNode.job.jobid})`; + const jobNames = jobs.map(toJobname); + const MAX_DISPLAYED_JOB_NAMES = 10; + let displayedJobNames = jobNames.slice(0, MAX_DISPLAYED_JOB_NAMES).join("\n"); + let additionalJobsCount = jobNames.length - MAX_DISPLAYED_JOB_NAMES; const message = vscode.l10n.t({ 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}", - args: [jobs.length, jobs.map(toJobname).toString().replace(/(,)/g, "\n")], - comment: ["Jobs length", "Job names"], + "Are you sure you want to delete the following {0} items?\n" + + "This will permanently remove the following jobs from your system.\n\n{1}{2}", + args: [jobs.length, displayedJobNames, additionalJobsCount > 0 ? `\n...and ${additionalJobsCount} more` : ""], + comment: ["Jobs length", "Job names", "Additional jobs count"], }); const deleteChoice = await Gui.warningMessage(message, { items: [deleteButton], @@ -101,10 +106,12 @@ export class JobActions { }) .filter((result) => result !== undefined); if (deletedJobs.length) { + displayedJobNames = deletedJobs.slice(0, MAX_DISPLAYED_JOB_NAMES).map(toJobname).join(", "); + additionalJobsCount = deletedJobs.length - MAX_DISPLAYED_JOB_NAMES; Gui.showMessage( vscode.l10n.t({ - message: "The following jobs were deleted: {0}", - args: [deletedJobs.map(toJobname).toString().replace(/(,)/g, ", ")], + message: "The following jobs were deleted: {0}{1}", + args: [displayedJobNames, additionalJobsCount > 0 ? `, ...and ${additionalJobsCount} more` : ""], comment: ["Deleted jobs"], }) ); diff --git a/packages/zowe-explorer/src/trees/uss/USSActions.ts b/packages/zowe-explorer/src/trees/uss/USSActions.ts index 9e57618f27..10af54ee9b 100644 --- a/packages/zowe-explorer/src/trees/uss/USSActions.ts +++ b/packages/zowe-explorer/src/trees/uss/USSActions.ts @@ -243,20 +243,19 @@ export class USSActions { } else { selectedNodes = ussFileProvider.getTreeView().selection; } - selectedNodes = selectedNodes.filter( - (x) => SharedContext.isDocument(x) || SharedContext.isUssDirectory(x) || SharedContext.isBinary(x) - ); - const fileNames = selectedNodes.reduce((label, currentVal) => { - return `${label}${currentVal.label.toString()}\n`; - }, ""); - - const deleteButton = vscode.l10n.t("Delete"); + selectedNodes = selectedNodes.filter((x) => SharedContext.isDocument(x) || SharedContext.isUssDirectory(x) || SharedContext.isBinary(x)); + const fileNames = selectedNodes.map(({ label }) => label.toString()); + const MAX_DISPLAYED_FILE_NAMES = 10; + const displayedFileNames = fileNames.slice(0, MAX_DISPLAYED_FILE_NAMES).join("\n"); + const additionalFilesCount = fileNames.length - MAX_DISPLAYED_FILE_NAMES; const message = vscode.l10n.t({ 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}", - args: [fileNames.toString()], - comment: ["File names"], + "Are you sure you want to delete the following item?\n" + + "This will permanently remove the following file or folder from your system.\n\n{0}{1}", + args: [displayedFileNames, additionalFilesCount > 0 ? `\n...and ${additionalFilesCount} more` : ""], + comment: ["File names", "Additional files count"], }); + const deleteButton = vscode.l10n.t("Delete"); let cancelled = false; await Gui.warningMessage(message, { items: [deleteButton],