From 0fc58f768b6202b86d9b5544134d11296f99a131 Mon Sep 17 00:00:00 2001 From: Billie Simmons Date: Thu, 17 Oct 2024 16:10:35 -0400 Subject: [PATCH] Prepare 3.0.2 patch release (#3247) * Improve process to build l10n bundle without comments (#3191) Signed-off-by: Timothy Johnson Co-authored-by: Billie Simmons * Port 3.0.1 missing release changes to main (#3231) * Fix 401 error when opening PDS members after cred change (#3157) * Temporarily disable ON_VAULT_CHANGED event to prevent double refresh Signed-off-by: Timothy Johnson * Propagate profile updates to child nodes Signed-off-by: Timothy Johnson * Skip vault change events triggered by ZE Signed-off-by: Timothy Johnson * Update changelog Signed-off-by: Timothy Johnson * fix(tests): Add EventProcessor stub to imperative module mock Signed-off-by: Trae Yelovich * refactor: Move logic into separate functions; tests: add patch coverage Signed-off-by: Trae Yelovich * chore: update ZE API changelog Signed-off-by: Trae Yelovich * ran prepublish Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * fix: pass processor as function arg instead of bind Signed-off-by: Trae Yelovich * fix(tests): Pass fake event processor to hook function Signed-off-by: Trae Yelovich * Make error handling consistent across all trees Signed-off-by: Timothy Johnson * Move 401 error handling back into node methods Signed-off-by: Timothy Johnson * Update unit tests for error handling and placeholder nodes Signed-off-by: Timothy Johnson * Fix duplicate expand for jobs, clean up logging, update changelog Signed-off-by: Timothy Johnson * Fix log statements in wrong place Signed-off-by: Timothy Johnson * Use contextOverride when building session nodes Signed-off-by: Timothy Johnson * Add tests for memberPattern on ds node Signed-off-by: Timothy Johnson * Add unit test for USS placeholder node Signed-off-by: Timothy Johnson * Fix extra tree refresh on credential update Signed-off-by: Timothy Johnson * Store saved profile contents by URI path Signed-off-by: Timothy Johnson * Fix update creds cancelling and node not refreshing Signed-off-by: Timothy Johnson * Fix failing USS actions test Signed-off-by: Timothy Johnson * Handle scenario of falsy node to refresh Signed-off-by: Timothy Johnson * Add unit test for syncSessionNode Signed-off-by: Timothy Johnson * Don't show placeholder node when there is error Signed-off-by: Timothy Johnson --------- Signed-off-by: Timothy Johnson Signed-off-by: Trae Yelovich Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Trae Yelovich Co-authored-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Billie Simmons Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * resolve FTP getContents bug for MVS and USS (#3200) Signed-off-by: Trae Yelovich Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * Fix children in tree nodes persisting on error (#3224) * Fix children in tree nodes persisting on error Signed-off-by: Timothy Johnson * Update unit tests to ensure children don't persist Signed-off-by: Timothy Johnson --------- Signed-off-by: Timothy Johnson Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * ci: change node versions on lint & deployment workflows (#3228) Signed-off-by: Trae Yelovich Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * Prep 3.0.1 (#3202) * check path instead of file name Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * add changelog, fix test, run package Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * To address issue with opening project config in zowe dir Signed-off-by: Santhoshi Boyina * To fix pnpm lint failure Signed-off-by: Santhoshi Boyina * To update CHANGELOG.md file Signed-off-by: Santhoshi Boyina * fix(ZoweDatasetNode): Add contextOverride to PS node Signed-off-by: Trae Yelovich * chore: add PR number to ZE changelog Signed-off-by: Trae Yelovich * fix: Add check for binary in contextOverride Signed-off-by: Trae Yelovich * Update release.config.js for Zowe V3 GA Signed-off-by: Timothy Johnson * chore: missing newline in ZE changelog Signed-off-by: Trae Yelovich * fix(ProfilesUtils): Pass paths to new ProfileInfo instance Signed-off-by: Trae Yelovich * chore: add changelog entry for ZE Signed-off-by: Trae Yelovich * chore: adjust changelog to match v2 port Signed-off-by: Trae Yelovich * tests: Add unit test to verify readProfilesFromDisk behavior Signed-off-by: Trae Yelovich * To revert back logic to open the global config file Signed-off-by: Santhoshi Boyina * chore: update ZE changelog entries Signed-off-by: Trae Yelovich * Remove sample VSCEs and restore carets for SDK deps (#3173) * Remove sample VSCEs and restore carets for SDK deps Signed-off-by: Timothy Johnson * Update Zowe SDKs to remove prerelease peer deps Signed-off-by: Timothy Johnson * Ignore issueTsoCommand deprecation warning for now Signed-off-by: Timothy Johnson --------- Signed-off-by: Timothy Johnson Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> * Add Sonar scan properties and remove old system test files (#3194) Signed-off-by: Timothy Johnson Co-authored-by: Trae Yelovich * fix: prompt optimizations for create file/dir; address case of skipping prompt (#3189) * fix: prompt optimizations for create file/dir; fix session case Signed-off-by: Trae Yelovich * chore: update ZE changelog Signed-off-by: Trae Yelovich * fix: resolve failing tests, remove unused isTopLevel parameter Signed-off-by: Trae Yelovich * refactor: remove unused createUSSNodeDialog function Signed-off-by: Trae Yelovich * fix: use path.posix.join when building full path Signed-off-by: Trae Yelovich * tests: add test case for prompting user w/ location Signed-off-by: Trae Yelovich * chore: add additional bugfix to ZE changelog Signed-off-by: Trae Yelovich * tests: add case for dismissing location prompt Signed-off-by: Trae Yelovich * tests: add case for createUSSNode - trailing slashes Signed-off-by: Trae Yelovich * refactor: use isTopLevel earlier in createUSSNode Signed-off-by: Trae Yelovich --------- Signed-off-by: Trae Yelovich Co-authored-by: Billie Simmons * fix(ds): File extension detection misidentifies types (#3182) * fix(ds): File extension detection misidentifies types Signed-off-by: Timothy Johnson * Simplify ds extension mapping Signed-off-by: Timothy Johnson --------- Signed-off-by: Timothy Johnson Signed-off-by: Billie Simmons Co-authored-by: Billie Simmons * deps: update lockfile to resolve audit failure (#3195) Signed-off-by: Trae Yelovich Co-authored-by: Timothy Johnson * Fix 401 error when opening PDS members after cred change (#3157) * Temporarily disable ON_VAULT_CHANGED event to prevent double refresh Signed-off-by: Timothy Johnson * Propagate profile updates to child nodes Signed-off-by: Timothy Johnson * Skip vault change events triggered by ZE Signed-off-by: Timothy Johnson * Update changelog Signed-off-by: Timothy Johnson * fix(tests): Add EventProcessor stub to imperative module mock Signed-off-by: Trae Yelovich * refactor: Move logic into separate functions; tests: add patch coverage Signed-off-by: Trae Yelovich * chore: update ZE API changelog Signed-off-by: Trae Yelovich * ran prepublish Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * fix: pass processor as function arg instead of bind Signed-off-by: Trae Yelovich * fix(tests): Pass fake event processor to hook function Signed-off-by: Trae Yelovich * Make error handling consistent across all trees Signed-off-by: Timothy Johnson * Move 401 error handling back into node methods Signed-off-by: Timothy Johnson * Update unit tests for error handling and placeholder nodes Signed-off-by: Timothy Johnson * Fix duplicate expand for jobs, clean up logging, update changelog Signed-off-by: Timothy Johnson * Fix log statements in wrong place Signed-off-by: Timothy Johnson * Use contextOverride when building session nodes Signed-off-by: Timothy Johnson * Add tests for memberPattern on ds node Signed-off-by: Timothy Johnson * Add unit test for USS placeholder node Signed-off-by: Timothy Johnson * Fix extra tree refresh on credential update Signed-off-by: Timothy Johnson * Store saved profile contents by URI path Signed-off-by: Timothy Johnson * Fix update creds cancelling and node not refreshing Signed-off-by: Timothy Johnson * Fix failing USS actions test Signed-off-by: Timothy Johnson * Handle scenario of falsy node to refresh Signed-off-by: Timothy Johnson * Add unit test for syncSessionNode Signed-off-by: Timothy Johnson * Don't show placeholder node when there is error Signed-off-by: Timothy Johnson --------- Signed-off-by: Timothy Johnson Signed-off-by: Trae Yelovich Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Trae Yelovich Co-authored-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Billie Simmons * resolve FTP getContents bug for MVS and USS (#3200) Signed-off-by: Trae Yelovich Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> * chore: add missing license header Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * patch: update lerna.json in preparation for a release Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * chore: update changelog files Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * chore: update changelog :yum: Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * Fix children in tree nodes persisting on error (#3224) * Fix children in tree nodes persisting on error Signed-off-by: Timothy Johnson * Update unit tests to ensure children don't persist Signed-off-by: Timothy Johnson --------- Signed-off-by: Timothy Johnson --------- Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Signed-off-by: SanthoshiBoyina1 <142206957+SanthoshiBoyina1@users.noreply.github.com> Signed-off-by: Santhoshi Boyina Signed-off-by: Trae Yelovich Signed-off-by: Timothy Johnson Signed-off-by: Billie Simmons Signed-off-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> Co-authored-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: SanthoshiBoyina1 <142206957+SanthoshiBoyina1@users.noreply.github.com> Co-authored-by: Santhoshi Boyina Co-authored-by: Trae Yelovich Co-authored-by: Timothy Johnson Co-authored-by: Billie Simmons * Bump version to 3.0.1 [ci skip] Signed-off-by: zowe-robot Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * Bump version to 3.0.1-SNAPSHOT [ci skip] Signed-off-by: zowe-robot Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * chore: add dco remediation paths Third-Party DCO Remediation Commit for Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> On behalf of Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com>, I, zFernand0 <37381190+zFernand0@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 950524f Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * chore: revert version changes after rebase to fix DCO Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * chore: remove duplicate changelog items. thanks @t1m0thyj Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> * address comment Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --------- Signed-off-by: Timothy Johnson Signed-off-by: Trae Yelovich Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> Signed-off-by: SanthoshiBoyina1 <142206957+SanthoshiBoyina1@users.noreply.github.com> Signed-off-by: Santhoshi Boyina Signed-off-by: Billie Simmons Signed-off-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Signed-off-by: zowe-robot Co-authored-by: Timothy Johnson Co-authored-by: Trae Yelovich Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Co-authored-by: SanthoshiBoyina1 <142206957+SanthoshiBoyina1@users.noreply.github.com> Co-authored-by: Santhoshi Boyina Co-authored-by: zowe-robot Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * fix(ci): Use `ubuntu-22.04` images to get access to libsecret (#3233) * ci: use ubuntu-22.04 image for libsecret fix Signed-off-by: Trae Yelovich * ci: update checks for matrix.os Signed-off-by: Trae Yelovich --------- Signed-off-by: Trae Yelovich * Removing icon names from translated strings (#3239) * Removing icon names from translated strings Signed-off-by: Peter Haumer <4391934+phaumer@users.noreply.github.com> * Changelog updated Signed-off-by: Peter Haumer <4391934+phaumer@users.noreply.github.com> * Changelog for API package Signed-off-by: Peter Haumer <4391934+phaumer@users.noreply.github.com> --------- Signed-off-by: Peter Haumer <4391934+phaumer@users.noreply.github.com> * update lerna Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * ZE Webview Localization (#3162) * Webview Loc Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * Add unit tests and changelog Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * Update tests Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * Add more test suites Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * Address issue seen with edit history Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * Edit Attributes permissions localization Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * Address table-view No items selected and Page Size localization Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * Add changelog Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> * run package; nls Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * Add code coverage Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> --------- Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Co-authored-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * fix: Move v1 conversion prompt into initialization (#3246) * fix: Move v1 conversion prompt into initialization Signed-off-by: Trae Yelovich * chore: update ZE changelog Signed-off-by: Trae Yelovich * refactor: fix failing tests, move test cases & fn call Signed-off-by: Trae Yelovich * refactor: move migration check before creating profiles instance Signed-off-by: Trae Yelovich * chore: update changelog and l10n Signed-off-by: Trae Yelovich * tests: check for return values in v1ProfileOptions Signed-off-by: Trae Yelovich * run package Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * chore: address changelog Signed-off-by: Trae Yelovich --------- Signed-off-by: Trae Yelovich Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Billie Simmons * refactor(jobs): Update contents of editor during polling / "Pull from Mainframe" (#3249) * refactor: revert contents in editor for jobs when pulling data Signed-off-by: Trae Yelovich * chore: add ZE changelog entry Signed-off-by: Trae Yelovich * fix: update mtime, size in fetchSpoolAtUri Signed-off-by: Trae Yelovich * tests: resolve failing test cases Signed-off-by: Trae Yelovich * add changelog # Signed-off-by: Trae Yelovich --------- Signed-off-by: Trae Yelovich Signed-off-by: Billie Simmons Co-authored-by: Billie Simmons * address comments for changelogs Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * fix(uss): Fix encoding of USS file not automatically detected (#3253) * fix(uss): Fix encoding of USS file not automatically detected Signed-off-by: Timothy Johnson * run pre-publish Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --------- Signed-off-by: Timothy Johnson Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Co-authored-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * remove extra space in ZE package.json build script Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> * fix: add ProfileInfo.getTeamConfig.exists check to v1 profile prompt (#3256) Signed-off-by: Trae Yelovich --------- Signed-off-by: Timothy Johnson Signed-off-by: Trae Yelovich Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Signed-off-by: zFernand0 <37381190+zFernand0@users.noreply.github.com> Signed-off-by: SanthoshiBoyina1 <142206957+SanthoshiBoyina1@users.noreply.github.com> Signed-off-by: Santhoshi Boyina Signed-off-by: Billie Simmons Signed-off-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Signed-off-by: zowe-robot Signed-off-by: Peter Haumer <4391934+phaumer@users.noreply.github.com> Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> Co-authored-by: Timothy Johnson Co-authored-by: Trae Yelovich Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Co-authored-by: SanthoshiBoyina1 <142206957+SanthoshiBoyina1@users.noreply.github.com> Co-authored-by: Santhoshi Boyina Co-authored-by: zowe-robot Co-authored-by: Peter Haumer <4391934+phaumer@users.noreply.github.com> Co-authored-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com> --- .github/dco.yml | 3 + .github/workflows/zowe-explorer-ci.yml | 14 +- lerna.json | 2 +- packages/zowe-explorer-api/CHANGELOG.md | 3 + .../__unit__/vscode/ui/TableView.unit.test.ts | 18 ++ .../zowe-explorer-api/src/fs/BaseProvider.ts | 6 +- .../src/vscode/ui/TableView.ts | 17 +- packages/zowe-explorer/CHANGELOG.md | 8 +- .../__tests__/__unit__/extension.unit.test.ts | 5 + .../trees/job/JobFSProvider.unit.test.ts | 12 +- .../shared/SharedHistoryView.unit.test.ts | 40 ++- .../trees/shared/SharedUtils.unit.test.ts | 17 ++ .../trees/uss/USSAttributeView.unit.test.ts | 33 ++ .../trees/uss/UssFSProvider.unit.test.ts | 25 ++ .../utils/CertificateWizard.unit.test.ts | 51 +++- .../__unit__/utils/ProfilesUtils.unit.test.ts | 287 ++++++++++-------- .../zosconsole/ZosConsolePanel.unit.test.ts | 36 ++- packages/zowe-explorer/l10n/bundle.l10n.json | 158 ++++++---- packages/zowe-explorer/l10n/poeditor.json | 134 ++++---- packages/zowe-explorer/package.json | 6 +- .../scripts/generatePoeditorJson.js | 15 +- .../scripts/stripL10nComments.js | 11 - .../src/commands/MvsCommandHandler.ts | 2 +- .../src/commands/TsoCommandHandler.ts | 2 +- .../src/commands/UnixCommandHandler.ts | 6 +- .../src/configuration/Definitions.ts | 2 +- packages/zowe-explorer/src/extension.ts | 2 +- .../src/management/ProfileManagement.ts | 40 +-- .../src/trees/dataset/DatasetActions.ts | 2 +- .../src/trees/dataset/DatasetFSProvider.ts | 2 +- .../src/trees/dataset/DatasetInit.ts | 2 +- .../src/trees/dataset/DatasetTree.ts | 30 +- .../src/trees/dataset/DatasetUtils.ts | 15 +- .../zowe-explorer/src/trees/job/JobActions.ts | 15 +- .../src/trees/job/JobFSProvider.ts | 9 +- .../zowe-explorer/src/trees/job/JobInit.ts | 2 +- .../zowe-explorer/src/trees/job/JobTree.ts | 26 +- .../zowe-explorer/src/trees/job/JobUtils.ts | 18 +- .../src/trees/shared/SharedHistoryView.ts | 18 ++ .../src/trees/shared/SharedUtils.ts | 2 +- .../src/trees/uss/USSAttributeView.ts | 19 ++ .../zowe-explorer/src/trees/uss/USSInit.ts | 4 +- .../zowe-explorer/src/trees/uss/USSTree.ts | 4 +- .../src/trees/uss/UssFSProvider.ts | 4 +- .../src/utils/CertificateWizard.ts | 18 ++ .../zowe-explorer/src/utils/ProfilesUtils.ts | 58 ++-- .../webviews/src/certificate-wizard/App.tsx | 42 +-- .../src/webviews/src/edit-attributes/App.tsx | 67 ++-- .../src/webviews/src/edit-history/App.tsx | 18 +- .../PersistentManagerHeader.tsx | 11 +- .../PersistentDataGridHeaders.tsx | 6 +- .../PersistentTable/PersistentDataPanel.tsx | 14 +- .../PersistentTable/PersistentTableData.tsx | 3 +- .../PersistentAddNewHistoryItemButton.tsx | 8 +- .../PersistentClearAllButton.tsx | 6 +- .../PersistentDeleteSelectedButton.tsx | 8 +- .../PersistentDropdownOptions.tsx | 11 +- .../PersistentRefreshButton.tsx | 6 +- .../components/PersistentUtils.ts | 3 +- .../webviews/src/table-view/ActionsBar.tsx | 4 +- .../src/webviews/src/table-view/TableView.tsx | 39 ++- .../src/webviews/src/zos-console/App.tsx | 13 +- .../src/zosconsole/ZosConsolePanel.ts | 16 + 63 files changed, 993 insertions(+), 485 deletions(-) create mode 100644 .github/dco.yml delete mode 100644 packages/zowe-explorer/scripts/stripL10nComments.js diff --git a/.github/dco.yml b/.github/dco.yml new file mode 100644 index 0000000000..cab92eb79e --- /dev/null +++ b/.github/dco.yml @@ -0,0 +1,3 @@ +allowRemediationCommits: + individual: true + thirdParty: true \ No newline at end of file diff --git a/.github/workflows/zowe-explorer-ci.yml b/.github/workflows/zowe-explorer-ci.yml index b8a078ffd6..c13a9b7819 100644 --- a/.github/workflows/zowe-explorer-ci.yml +++ b/.github/workflows/zowe-explorer-ci.yml @@ -26,7 +26,7 @@ jobs: matrix: node-version: [18.x, 20.x] # order operating systems from best to worst - os: [windows-latest, ubuntu-latest, macos-latest] + os: [windows-latest, ubuntu-22.04, macos-latest] if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && !contains(github.event.head_commit.message, '[ci skip]') @@ -51,24 +51,24 @@ jobs: - name: Unlock Keyring id: unlock-keyring - if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20.x' + if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x' uses: t1m0thyj/unlock-keyring@v1 - name: Integration tests - if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20.x' + if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x' run: xvfb-run pnpm test:integration --exclude "Activation.feature" working-directory: packages/zowe-explorer - name: Upload test results uses: actions/upload-artifact@v4 - if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20.x' + if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x' with: name: zowe-explorer-results path: packages/zowe-explorer/results/ - name: Upload API test results uses: actions/upload-artifact@v4 - if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20.x' + if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x' with: name: zowe-explorer-api-results path: packages/zowe-explorer-api/results/ @@ -80,12 +80,12 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - name: Package VSIX - if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20.x' + if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x' run: pnpm package working-directory: packages/zowe-explorer - name: Archive VSIX artifact - if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20.x' + if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x' uses: actions/upload-artifact@v4 with: name: zowe-explorer-vsix diff --git a/lerna.json b/lerna.json index 8ae28340eb..a5fbadeb1b 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.0.1-SNAPSHOT", + "version": "3.0.2", "command": { "version": { "forcePublish": true, diff --git a/packages/zowe-explorer-api/CHANGELOG.md b/packages/zowe-explorer-api/CHANGELOG.md index 7e0091fa24..b08e59e64b 100644 --- a/packages/zowe-explorer-api/CHANGELOG.md +++ b/packages/zowe-explorer-api/CHANGELOG.md @@ -6,6 +6,9 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t ### New features and enhancements +- Zowe Explorer now includes support for the [VS Code display languages](https://code.visualstudio.com/docs/getstarted/locales) French, German, Japanese, Portuguese, and Spanish. [#3239](https://github.com/zowe/zowe-explorer-vscode/pull/3239) +- Localization of strings within the webviews. [#2983](https://github.com/zowe/zowe-explorer-vscode/issues/2983) + ### Bug fixes ## `3.0.1` diff --git a/packages/zowe-explorer-api/__tests__/__unit__/vscode/ui/TableView.unit.test.ts b/packages/zowe-explorer-api/__tests__/__unit__/vscode/ui/TableView.unit.test.ts index 10d136a585..df4041c186 100644 --- a/packages/zowe-explorer-api/__tests__/__unit__/vscode/ui/TableView.unit.test.ts +++ b/packages/zowe-explorer-api/__tests__/__unit__/vscode/ui/TableView.unit.test.ts @@ -14,7 +14,9 @@ import { Table, TableBuilder, WebView } from "../../../../src"; import { env, EventEmitter, Uri, window } from "vscode"; import * as crypto from "crypto"; import { diff } from "deep-object-diff"; +import * as fs from "fs"; +jest.mock("fs"); function createGlobalMocks() { const mockPanel = { dispose: jest.fn(), @@ -23,6 +25,10 @@ function createGlobalMocks() { }; // Mock `vscode.window.createWebviewPanel` to return a usable panel object const createWebviewPanelMock = jest.spyOn(window, "createWebviewPanel").mockReturnValueOnce(mockPanel as any); + const spyReadFile = jest.fn((path, encoding, callback) => { + callback(null, "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); return { createWebviewPanelMock, @@ -273,6 +279,18 @@ describe("Table.View", () => { globalMocks.updateWebviewMock.mockRestore(); }); + it("should handle the case where 'GET_LOCALIZATION' is the command sent", async () => { + const globalMocks = await createGlobalMocks(); + const view = new Table.View(globalMocks.context as any, false, { title: "Table" } as any); + const postMessageSpy = jest.spyOn(view.panel.webview, "postMessage"); + await view.onMessageReceived({ command: "GET_LOCALIZATION" }); + expect(postMessageSpy).toHaveBeenCalledWith({ + command: "GET_LOCALIZATION", + contents: "file contents", + }); + globalMocks.updateWebviewMock.mockRestore(); + }); + it("calls vscode.env.clipboard.writeText when handling the 'copy' command", async () => { const globalMocks = createGlobalMocks(); const view = new Table.View(globalMocks.context as any, { title: "Table w/ copy" } as any); diff --git a/packages/zowe-explorer-api/src/fs/BaseProvider.ts b/packages/zowe-explorer-api/src/fs/BaseProvider.ts index 3d099f3060..9f1206157c 100644 --- a/packages/zowe-explorer-api/src/fs/BaseProvider.ts +++ b/packages/zowe-explorer-api/src/fs/BaseProvider.ts @@ -52,11 +52,11 @@ export class BaseProvider { } await vscode.workspace.fs.writeFile(uri.with({ query: "forceUpload=true" }), fsEntry.data); Gui.setStatusBarMessage( - vscode.l10n.t({ - message: "$(check) Overwrite applied for {0}", + `$(check) ${vscode.l10n.t({ + message: "Overwrite applied for {0}", args: [fsEntry.name], comment: "File name", - }), + })}`, this.FS_PROVIDER_UI_TIMEOUT ); fsEntry.conflictData = null; diff --git a/packages/zowe-explorer-api/src/vscode/ui/TableView.ts b/packages/zowe-explorer-api/src/vscode/ui/TableView.ts index 6879d42065..2f0de8d2cb 100644 --- a/packages/zowe-explorer-api/src/vscode/ui/TableView.ts +++ b/packages/zowe-explorer-api/src/vscode/ui/TableView.ts @@ -14,7 +14,8 @@ import { Event, EventEmitter, ExtensionContext, env } from "vscode"; import { randomUUID } from "crypto"; import { diff } from "deep-object-diff"; import { TableMediator } from "./utils/TableMediator"; - +import * as vscode from "vscode"; +import * as fs from "fs"; export namespace Table { /* The types of supported content for the table and how they are represented in callback functions. */ export type ContentTypes = string | number | boolean | string[]; @@ -360,6 +361,20 @@ export namespace Table { case "copy-cell": await env.clipboard.writeText(message.data.cell); return; + case "GET_LOCALIZATION": { + const filePath = vscode.l10n.uri?.fsPath + ""; + fs.readFile(filePath, "utf8", (err, data) => { + if (err) { + // File doesn't exist, fallback to English strings + return; + } + (this.panel ?? this.view).webview.postMessage({ + command: "GET_LOCALIZATION", + contents: data, + }); + }); + return; + } default: break; } diff --git a/packages/zowe-explorer/CHANGELOG.md b/packages/zowe-explorer/CHANGELOG.md index bdbfb3b7a3..093b1c475b 100644 --- a/packages/zowe-explorer/CHANGELOG.md +++ b/packages/zowe-explorer/CHANGELOG.md @@ -6,8 +6,15 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen ### New features and enhancements +- Zowe Explorer now includes support for the [VS Code display languages](https://code.visualstudio.com/docs/getstarted/locales) French, German, Japanese, Portuguese, and Spanish. Download the respective language pack and switch. [#3239](https://github.com/zowe/zowe-explorer-vscode/pull/3239) +- Localization of strings within the webviews. [#2983](https://github.com/zowe/zowe-explorer-vscode/issues/2983) + ### Bug fixes +- Fixed an issue where the contents of an editor did not update when polling spool content or using the "Pull from Mainframe" action with jobs. [#3249](https://github.com/zowe/zowe-explorer-vscode/pull/3249) +- Fixed an issue where Zowe Explorer sometimes prompted the user to convert V1 profiles when changes were made to a team configuration after initialization. [#3246](https://github.com/zowe/zowe-explorer-vscode/pull/3246) +- Fixed an issue where the encoding of a USS file was not automatically detected when opened for the first time. [#3253](https://github.com/zowe/zowe-explorer-vscode/pull/3253) + ## `3.0.1` ### Bug fixes @@ -20,7 +27,6 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen - Fixed an issue where the `Create Directory` and `Create File` features would continue processing when the first prompt was dismissed, causing an incorrect URI to be generated. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183) - Fixed an issue where the `Create Directory` and `Create File` features would incorrectly handle user-specified locations with trailing slashes. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183) - Fixed an issue where a 401 error could occur when opening PDS members after updating credentials within the same user session. [#3150](https://github.com/zowe/zowe-explorer-vscode/issues/3150) -- Fixed issue where switching from token-based authentication to user/password would cause an error for nested profiles. [#3142](https://github.com/zowe/zowe-explorer-vscode/issues/3142) - Fixed the "Edit Profile" operation to open the correct files when both global and project team configs are present. [#3125](https://github.com/zowe/zowe-explorer-vscode/issues/3125) ## `3.0.0` diff --git a/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts index 02844adc82..d1a3631f85 100644 --- a/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts @@ -351,6 +351,11 @@ async function createGlobalMocks() { "zowe.automaticProfileValidation": true, }), }); + jest.spyOn(ProfilesUtils, "getProfileInfo").mockResolvedValue({ + getTeamConfig: jest.fn().mockReturnValue({ + exists: jest.fn(), + }), + } as any); Object.defineProperty(globalMocks.mockProfilesCache, "getProfileInfo", { value: jest.fn(() => { return { value: globalMocks.mockProfCacheProfileInfo, configurable: true }; diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/job/JobFSProvider.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/job/JobFSProvider.unit.test.ts index 09fb65c8ab..4a8a588976 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/job/JobFSProvider.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/job/JobFSProvider.unit.test.ts @@ -9,7 +9,7 @@ * */ -import { Disposable, FilePermission, FileType, Uri } from "vscode"; +import { Disposable, FilePermission, FileType, Uri, window } from "vscode"; import { FsJobsUtils, FilterEntry, Gui, JobEntry, SpoolEntry, ZoweScheme } from "@zowe/zowe-explorer-api"; import { createIProfile } from "../../../__mocks__/mockCreators/shared"; import { createIJobFile, createIJobObject } from "../../../__mocks__/mockCreators/jobs"; @@ -91,16 +91,22 @@ describe("refreshSpool", () => { }); it("calls fetchSpoolAtUri for a valid spool node", async () => { + const node = { resourceUri: testUris.spool, contextValue: "spool" } as any; + const editorListMock = new MockedProperty(window, "visibleTextEditors", { + value: [{ document: { uri: testUris.spool } }], + }); const fetchSpoolAtUriMock = jest.spyOn(JobFSProvider.instance, "fetchSpoolAtUri").mockImplementation(); const disposeMock = jest.fn(); const statusBarMsgMock = jest.spyOn(Gui, "setStatusBarMessage").mockReturnValue({ dispose: disposeMock }); - const node = { resourceUri: testUris.spool, contextValue: "spool" } as any; await JobFSProvider.refreshSpool(node); expect(statusBarMsgMock).toHaveBeenCalledWith("$(sync~spin) Fetching spool file..."); - expect(fetchSpoolAtUriMock).toHaveBeenCalledWith(node.resourceUri); + expect(fetchSpoolAtUriMock).toHaveBeenCalledWith(node.resourceUri, { + document: { uri: { path: "/sestest/TESTJOB(JOB1234) - ACTIVE/JES2.JESMSGLG.2", scheme: "zowe-jobs" } }, + }); expect(disposeMock).toHaveBeenCalled(); fetchSpoolAtUriMock.mockRestore(); statusBarMsgMock.mockRestore(); + editorListMock[Symbol.dispose](); }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedHistoryView.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedHistoryView.unit.test.ts index ef0187ff00..39784dc520 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedHistoryView.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedHistoryView.unit.test.ts @@ -25,7 +25,9 @@ import { Gui } from "@zowe/zowe-explorer-api"; import { Profiles } from "../../../../src/configuration/Profiles"; import { ZoweLocalStorage } from "../../../../src/tools/ZoweLocalStorage"; import { UssFSProvider } from "../../../../src/trees/uss/UssFSProvider"; +import * as fs from "fs"; +jest.mock("fs"); async function initializeHistoryViewMock(blockMocks: any, globalMocks: any): Promise { return new SharedHistoryView( { @@ -67,7 +69,10 @@ function createGlobalMocks(): any { }, configurable: true, }); - + const spyReadFile = jest.fn((path, encoding, callback) => { + callback(null, "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); return globalMocks; } @@ -278,6 +283,39 @@ describe("HistoryView Unit Tests", () => { expect(historyView["currentSelection"]).toEqual({ ds: "search", jobs: "search", uss: "search" }); expect(resetEncodingHistorySpy).toHaveBeenCalledTimes(2); }); + + it("should handle the case where 'GET_LOCALIZATION' is the command sent", async () => { + const globalMocks = await createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + const historyView = await initializeHistoryViewMock(blockMocks, globalMocks); + const postMessageSpy = jest.spyOn(historyView.panel.webview, "postMessage"); + await historyView["onDidReceiveMessage"]({ command: "GET_LOCALIZATION" }); + expect(postMessageSpy).toHaveBeenCalledWith({ + command: "GET_LOCALIZATION", + contents: "file contents", + }); + }); + + it("if this.panel doesn't exist in GET_LOCALIZATION", async () => { + const globalMocks = await createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + const historyView = await initializeHistoryViewMock(blockMocks, globalMocks); + historyView.panel = undefined as any; + await historyView["onDidReceiveMessage"]({ command: "GET_LOCALIZATION" }); + expect(historyView.panel).toBeUndefined(); + }); + + it("if read file throwing an error in GET_LOCALIZATION", async () => { + const globalMocks = await createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + const spyReadFile = jest.fn((path, encoding, callback) => { + callback("error", "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + const historyView = await initializeHistoryViewMock(blockMocks, globalMocks); + await historyView["onDidReceiveMessage"]({ command: "GET_LOCALIZATION" }); + expect(spyReadFile).toHaveBeenCalledTimes(1); + }); }); describe("getHistoryData", () => { diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts index 645f8de4d8..181ee8c6a9 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts @@ -421,6 +421,23 @@ describe("Shared utils unit tests - function promptForEncoding", () => { ); }); + it("prompts for encoding for tagged USS binary file", async () => { + const blockMocks = createBlockMocks(); + const node = new ZoweUSSNode({ + label: "testFile", + collapsibleState: vscode.TreeItemCollapsibleState.None, + session: blockMocks.session, + profile: blockMocks.profile, + parentPath: "/root", + }); + node.setEncoding(binaryEncoding); + blockMocks.showQuickPick.mockImplementationOnce(async (items) => items[0]); + const encoding = await SharedUtils.promptForEncoding(node, "binary"); + expect(blockMocks.showQuickPick).toHaveBeenCalled(); + expect(await blockMocks.showQuickPick.mock.calls[0][0][0]).toEqual({ label: "binary", description: "USS file tag" }); + expect(encoding).toEqual({ kind: "binary" }); + }); + it("prompts for encoding for USS file when profile contains encoding", async () => { const blockMocks = createBlockMocks(); (blockMocks.profile.profile as any).encoding = "IBM-1047"; diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSAttributeView.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSAttributeView.unit.test.ts index 5ea37ccb43..6254493206 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSAttributeView.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSAttributeView.unit.test.ts @@ -19,7 +19,9 @@ import { ZoweUSSNode } from "../../../../src/trees/uss/ZoweUSSNode"; import { ZoweExplorerApiRegister } from "../../../../src/extending/ZoweExplorerApiRegister"; import { MainframeInteraction } from "../../../../../zowe-explorer-api/src/extend"; import { SharedContext } from "../../../../src/trees/shared/SharedContext"; +import * as fs from "fs"; +jest.mock("fs"); describe("AttributeView unit tests", () => { let view: USSAttributeView; const context = { extensionPath: "some/fake/ext/path" } as unknown as vscode.ExtensionContext; @@ -125,4 +127,35 @@ describe("AttributeView unit tests", () => { updated: false, }); }); + + it("handles GET_LOCALIZATION command", async () => { + const spyReadFile = jest.fn((path, encoding, callback) => { + callback(null, "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + await (view as any).onDidReceiveMessage({ command: "GET_LOCALIZATION" }); + expect(view.panel.webview.postMessage).toHaveBeenCalledWith({ + command: "GET_LOCALIZATION", + contents: "file contents", + }); + }); + + it("if this.panel doesn't exist in GET_LOCALIZATION", async () => { + const spyReadFile = jest.fn((path, encoding, callback) => { + callback(null, "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + view.panel = undefined as any; + await (view as any).onDidReceiveMessage({ command: "GET_LOCALIZATION" }); + expect(view.panel).toBeUndefined(); + }); + + it("if read file throwing an error in GET_LOCALIZATION", async () => { + const spyReadFile = jest.fn((path, encoding, callback) => { + callback("error", "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + await (view as any).onDidReceiveMessage({ command: "GET_LOCALIZATION" }); + expect(spyReadFile).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/UssFSProvider.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/UssFSProvider.unit.test.ts index 446f20b28f..7e53ac1699 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/UssFSProvider.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/UssFSProvider.unit.test.ts @@ -322,6 +322,31 @@ describe("fetchFileAtUri", () => { expect(fileEntry.data?.byteLength).toBe(exampleData.length); autoDetectEncodingMock.mockRestore(); }); + it("calls getContents to get the data for a file entry with encoding", async () => { + const fileEntry = { ...testEntries.file }; + const lookupAsFileMock = jest.spyOn((UssFSProvider as any).prototype, "_lookupAsFile").mockReturnValueOnce(fileEntry); + const exampleData = "hello world!"; + const getContentsMock = jest.fn().mockImplementationOnce((filePath, opts) => { + opts.stream.write(exampleData); + return { + apiResponse: { + etag: "123abc", + }, + }; + }); + jest.spyOn(ZoweExplorerApiRegister, "getUssApi") + .mockReturnValueOnce({ + getTag: jest.fn().mockResolvedValueOnce("binary"), + } as any) + .mockReturnValueOnce({ getContents: getContentsMock } as any); + + await UssFSProvider.instance.fetchFileAtUri(testUris.file); + + expect(lookupAsFileMock).toHaveBeenCalledWith(testUris.file); + expect(fileEntry.data?.toString()).toBe(exampleData); + expect(fileEntry.encoding).toEqual({ kind: "binary" }); + expect(getContentsMock).toHaveBeenCalledWith("/aFile.txt", expect.objectContaining({ binary: true })); + }); it("assigns conflictData if the 'isConflict' option is specified", async () => { const fileEntry = { ...testEntries.file }; const lookupAsFileMock = jest.spyOn((UssFSProvider as any).prototype, "_lookupAsFile").mockReturnValueOnce(fileEntry); diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/CertificateWizard.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/CertificateWizard.unit.test.ts index 3b6986754d..960b22b688 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/CertificateWizard.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/CertificateWizard.unit.test.ts @@ -10,13 +10,14 @@ */ import { Gui } from "@zowe/zowe-explorer-api"; +import * as fs from "fs"; import { CertificateWizard } from "../../../src/utils/CertificateWizard"; import { ExtensionContext, Uri } from "vscode"; import { ZoweLogger } from "../../../src/tools/ZoweLogger"; +jest.mock("fs"); describe("CertificateWizard", () => { const context = { extensionPath: "some/fake/ext/path" } as unknown as ExtensionContext; - it("handles the promptCert message", async () => { const certWizard = new CertificateWizard(context, { cert: "/a/b/cert.pem", @@ -103,4 +104,52 @@ describe("CertificateWizard", () => { }); expect(traceMock).toHaveBeenCalledWith("User dismissed the certificate wizard."); }); + + it("handles the get_localization message", async () => { + const spyReadFile = jest.fn((path, encoding, callback) => { + callback(null, "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + const certWizard = new CertificateWizard(context, { + cert: "/a/b/cert.pem", + certKey: "/a/b/cert.key.pem", + }); + const postMessageMock = jest.spyOn(certWizard.panel.webview, "postMessage").mockImplementation(); + (certWizard as any).onDidReceiveMessage({ + command: "GET_LOCALIZATION", + }); + (certWizard as any).data = "file contents"; + expect(postMessageMock).toHaveBeenCalledWith({ command: "GET_LOCALIZATION", contents: (certWizard as any).data }); + }); + + it("if this.panel doesn't exist in GET_LOCALIZATION", async () => { + const spyReadFile = jest.fn((path, encoding, callback) => { + callback(null, "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + const certWizard = new CertificateWizard(context, { + cert: "/a/b/cert.pem", + certKey: "/a/b/cert.key.pem", + }); + certWizard.panel = undefined as any; + (certWizard as any).onDidReceiveMessage({ + command: "GET_LOCALIZATION", + }); + expect(certWizard.panel).toBeUndefined(); + }); + + it("if read file throwing an error in GET_LOCALIZATION", async () => { + const spyReadFile = jest.fn((path, encoding, callback) => { + callback("error", "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + const certWizard = new CertificateWizard(context, { + cert: "/a/b/cert.pem", + certKey: "/a/b/cert.key.pem", + }); + (certWizard as any).onDidReceiveMessage({ + command: "GET_LOCALIZATION", + }); + expect(spyReadFile).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts index c276a01e3e..2f20c7d619 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts @@ -22,7 +22,7 @@ import { SettingsConfig } from "../../../src/configuration/SettingsConfig"; import { Profiles } from "../../../src/configuration/Profiles"; import { ZoweExplorerExtender } from "../../../src/extending/ZoweExplorerExtender"; import { FilterItem } from "../../../src/management/FilterManagement"; -import { ProfilesUtils } from "../../../src/utils/ProfilesUtils"; +import { ProfilesConvertStatus, ProfilesUtils } from "../../../src/utils/ProfilesUtils"; import { AuthUtils } from "../../../src/utils/AuthUtils"; import { ZoweLocalStorage } from "../../../src/tools/ZoweLocalStorage"; import { Definitions } from "../../../src/configuration/Definitions"; @@ -334,112 +334,6 @@ describe("ProfilesUtils unit tests", () => { ); profInfoSpy.mockRestore(); }); - - it("should reload the window once if the user just migrated from v1", async () => { - const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValueOnce({ - readProfilesFromDisk: jest.fn(), - hasValidSchema: false, - getTeamConfig: () => ({ - exists: false, - }), - } as never); - const getConfigurationMock = jest.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({ - persistent: true, - get: jest.fn(), - has: jest.fn(), - inspect: jest.fn(), - update: jest.fn(), - }); - const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { - configurable: true, - get: () => true, - }); - const executeCommandMock = jest.spyOn(vscode.commands, "executeCommand").mockImplementation(); - const getValueMock = jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(undefined); - const setValueMock = jest.spyOn(ZoweLocalStorage, "setValue").mockImplementation(); - await ProfilesUtils.readConfigFromDisk(true); - expect(getConfigurationMock).toHaveBeenCalledWith("Zowe-USS-Persistent"); - expect(getValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); - expect(setValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, Definitions.V1MigrationStatus.JustMigrated); - expect(executeCommandMock).toHaveBeenCalledWith("workbench.action.reloadWindow"); - executeCommandMock.mockRestore(); - getConfigurationMock.mockRestore(); - getValueMock.mockRestore(); - setValueMock.mockRestore(); - onlyV1ProfsExistMock[Symbol.dispose](); - - profInfoSpy.mockRestore(); - }); - - it("should not reload the window during migration if imperative.ProfileInfo.onlyV1ProfilesExist is false", async () => { - const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValueOnce({ - readProfilesFromDisk: jest.fn(), - hasValidSchema: false, - getTeamConfig: () => ({ - exists: false, - }), - } as never); - const getConfigurationMock = jest.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({ - persistent: true, - get: jest.fn(), - has: jest.fn(), - inspect: jest.fn(), - update: jest.fn(), - }); - const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { - configurable: true, - get: () => false, - }); - const executeCommandMock = jest.spyOn(vscode.commands, "executeCommand").mockImplementation(); - const getValueMock = jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(undefined); - const setValueMock = jest.spyOn(ZoweLocalStorage, "setValue").mockImplementation(); - await ProfilesUtils.readConfigFromDisk(true); - expect(getConfigurationMock).toHaveBeenCalledWith("Zowe-USS-Persistent"); - expect(getValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); - expect(executeCommandMock).not.toHaveBeenCalledWith("workbench.action.reloadWindow"); - executeCommandMock.mockRestore(); - getConfigurationMock.mockRestore(); - getValueMock.mockRestore(); - setValueMock.mockRestore(); - onlyV1ProfsExistMock[Symbol.dispose](); - - profInfoSpy.mockRestore(); - }); - - it("should call v1ProfileOptions if team config does not exist and only v1 profiles exist", async () => { - const fakeProfInfo = { - readProfilesFromDisk: jest.fn(), - hasValidSchema: false, - getTeamConfig: () => ({ - exists: false, - }), - onlyV1ProfilesExist: () => true, - }; - const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { - configurable: true, - get: () => true, - }); - const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValueOnce(fakeProfInfo as any); - const getConfigurationMock = jest.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({ - persistent: true, - get: jest.fn(), - has: jest.fn(), - inspect: jest.fn(), - update: jest.fn(), - }); - const v1ProfileOptionsMock = jest.spyOn(ProfilesUtils as any, "v1ProfileOptions").mockImplementation(); - const getValueMock = jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(Definitions.V1MigrationStatus.JustMigrated); - await ProfilesUtils.readConfigFromDisk(true); - expect(getConfigurationMock).toHaveBeenCalledWith("Zowe-USS-Persistent"); - expect(getValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); - expect(v1ProfileOptionsMock).toHaveBeenCalled(); - getConfigurationMock.mockRestore(); - getValueMock.mockRestore(); - v1ProfileOptionsMock.mockRestore(); - onlyV1ProfsExistMock[Symbol.dispose](); - - profInfoSpy.mockRestore(); - }); }); describe("promptCredentials", () => { @@ -1139,6 +1033,8 @@ describe("ProfilesUtils unit tests", () => { { name: null, type: "zosmf", error: "failed" as any }, ], } as any); + jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(Definitions.V1MigrationStatus.JustMigrated); + jest.spyOn(ZoweLocalStorage, "setValue").mockImplementation(); Object.defineProperty(vscode.workspace, "openTextDocument", { value: jest.fn().mockReturnValue({}), configurable: true }); Object.defineProperty(Gui, "showTextDocument", { value: jest.fn(), configurable: true }); const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { @@ -1146,7 +1042,7 @@ describe("ProfilesUtils unit tests", () => { get: () => true, }); - await expect((ProfilesUtils as any).v1ProfileOptions()).resolves.not.toThrow(); + await expect((ProfilesUtils as any).v1ProfileOptions()).resolves.toBe(ProfilesConvertStatus.ConvertSelected); onlyV1ProfsExistMock[Symbol.dispose](); expect(infoMsgSpy).toHaveBeenCalledTimes(2); @@ -1154,15 +1050,14 @@ describe("ProfilesUtils unit tests", () => { profInfoSpy.mockRestore(); }); - it("should prompt user if v1 profiles detected and queue a Create Config prompt when Create New is chosen", async () => { + it("should prompt user if v1 profiles detected and return if nothing chosen", async () => { const mockReadProfilesFromDisk = jest.fn(); const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockResolvedValue({ readProfilesFromDisk: mockReadProfilesFromDisk, getTeamConfig: jest.fn().mockReturnValue([]), getAllProfiles: jest.fn().mockReturnValue([createValidIProfile(), createAltTypeIProfile()]), } as never); - const msgSpy = jest.spyOn(Gui, "infoMessage").mockResolvedValueOnce("Create New" as any); - const setValueMock = jest.spyOn(ZoweLocalStorage, "setValue").mockImplementation(); + const infoMsgSpy = jest.spyOn(Gui, "infoMessage").mockResolvedValueOnce(undefined); const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { configurable: true, @@ -1171,33 +1066,35 @@ describe("ProfilesUtils unit tests", () => { await expect((ProfilesUtils as any).v1ProfileOptions()).resolves.not.toThrow(); onlyV1ProfsExistMock[Symbol.dispose](); - expect(msgSpy).toHaveBeenCalledWith(expect.stringContaining("Zowe V1 profiles in use."), { - items: ["Convert Existing Profiles", "Create New"], - vsCodeOpts: { modal: true }, - }); - expect(setValueMock).toHaveBeenCalledWith("zowe.v1MigrationStatus", Definitions.V1MigrationStatus.CreateConfigSelected); - msgSpy.mockRestore(); + infoMsgSpy.mockRestore(); profInfoSpy.mockRestore(); }); - it("should prompt user if v1 profiles detected and return Operation Cancelled if nothing chosen", async () => { + it("should prompt user if v1 profiles detected and Create New is selected", async () => { const mockReadProfilesFromDisk = jest.fn(); + jest.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({ + persistent: true, + get: jest.fn(), + has: jest.fn(), + inspect: jest.fn(), + update: jest.fn(), + }); const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockResolvedValue({ readProfilesFromDisk: mockReadProfilesFromDisk, getTeamConfig: jest.fn().mockReturnValue([]), getAllProfiles: jest.fn().mockReturnValue([createValidIProfile(), createAltTypeIProfile()]), } as never); - const infoMsgSpy = jest.spyOn(Gui, "infoMessage").mockResolvedValueOnce(undefined); + const infoMsgSpy = jest.spyOn(Gui, "infoMessage").mockResolvedValueOnce("Create New"); + jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(Definitions.V1MigrationStatus.JustMigrated); + jest.spyOn(ZoweLocalStorage, "setValue").mockImplementation(); const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { configurable: true, get: () => true, }); - await expect((ProfilesUtils as any).v1ProfileOptions()).resolves.not.toThrow(); + await expect((ProfilesUtils as any).v1ProfileOptions()).resolves.toBe(ProfilesConvertStatus.CreateNewSelected); onlyV1ProfsExistMock[Symbol.dispose](); - expect(infoMsgSpy).toHaveBeenCalledTimes(2); - expect(infoMsgSpy).toHaveBeenLastCalledWith("Operation cancelled"); infoMsgSpy.mockRestore(); profInfoSpy.mockRestore(); }); @@ -1211,30 +1108,150 @@ describe("ProfilesUtils unit tests", () => { }; } - it("should return early if the migration status is nullish", async () => { - const blockMocks = getBlockMocks(); - blockMocks.getValueMock.mockReturnValueOnce(undefined); - await ProfilesUtils.handleV1MigrationStatus(); - expect(blockMocks.setValueMock).not.toHaveBeenCalled(); - blockMocks.getValueMock.mockRestore(); - }); - it("should call executeCommand with zowe.ds.addSession if the migration status is CreateConfigSelected", async () => { const blockMocks = getBlockMocks(); const executeCommandMock = jest.spyOn(vscode.commands, "executeCommand").mockImplementation(); - blockMocks.getValueMock.mockReturnValueOnce(Definitions.V1MigrationStatus.CreateConfigSelected); + blockMocks.getValueMock.mockReturnValueOnce(Definitions.V1MigrationStatus.JustMigrated); blockMocks.setValueMock.mockImplementation(); + jest.spyOn(ProfilesUtils, "getProfileInfo").mockResolvedValue({ + getTeamConfig: jest.fn().mockReturnValue({ exists: false }), + } as any); + const onlyV1ProfilesExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { get: () => true }); + const v1ProfileOptsMock = jest.spyOn(ProfilesUtils as any, "v1ProfileOptions").mockResolvedValue(ProfilesConvertStatus.CreateNewSelected); await ProfilesUtils.handleV1MigrationStatus(); expect(executeCommandMock.mock.lastCall?.[0]).toBe("zowe.ds.addSession"); + expect(v1ProfileOptsMock).toHaveBeenCalled(); blockMocks.getValueMock.mockRestore(); blockMocks.setValueMock.mockRestore(); + onlyV1ProfilesExistMock[Symbol.dispose](); }); - it("should clear the v1 migration status once the migration status is handled", async () => { - const blockMocks = getBlockMocks(); - blockMocks.getValueMock.mockReturnValueOnce(Definitions.V1MigrationStatus.JustMigrated); + it("should reload the window once if the user just migrated from v1", async () => { + const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValueOnce({ + readProfilesFromDisk: jest.fn(), + hasValidSchema: false, + getTeamConfig: () => ({ + exists: false, + }), + } as never); + const getConfigurationMock = jest.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({ + persistent: true, + get: jest.fn(), + has: jest.fn(), + inspect: jest.fn(), + update: jest.fn(), + }); + const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { + configurable: true, + get: () => true, + }); + const executeCommandMock = jest.spyOn(vscode.commands, "executeCommand").mockImplementation(); + const getValueMock = jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(undefined); + const setValueMock = jest.spyOn(ZoweLocalStorage, "setValue").mockImplementation(); await ProfilesUtils.handleV1MigrationStatus(); - blockMocks.getValueMock.mockRestore(); + expect(getConfigurationMock).toHaveBeenCalledWith("Zowe-USS-Persistent"); + expect(getValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); + expect(setValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, Definitions.V1MigrationStatus.JustMigrated); + expect(executeCommandMock).toHaveBeenCalledWith("workbench.action.reloadWindow"); + executeCommandMock.mockRestore(); + getConfigurationMock.mockRestore(); + getValueMock.mockRestore(); + setValueMock.mockRestore(); + onlyV1ProfsExistMock[Symbol.dispose](); + + profInfoSpy.mockRestore(); + }); + + it("should not reload the window during migration if imperative.ProfileInfo.onlyV1ProfilesExist is false", async () => { + const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValueOnce({ + readProfilesFromDisk: jest.fn(), + hasValidSchema: false, + getTeamConfig: () => ({ + exists: false, + }), + } as never); + const getConfigurationMock = jest.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({ + persistent: true, + get: jest.fn(), + has: jest.fn(), + inspect: jest.fn(), + update: jest.fn(), + }); + const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { + configurable: true, + get: () => false, + }); + const executeCommandMock = jest.spyOn(vscode.commands, "executeCommand").mockImplementation(); + const getValueMock = jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(undefined); + const setValueMock = jest.spyOn(ZoweLocalStorage, "setValue").mockImplementation(); + await ProfilesUtils.handleV1MigrationStatus(); + expect(getConfigurationMock).toHaveBeenCalledWith("Zowe-USS-Persistent"); + expect(getValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); + expect(executeCommandMock).not.toHaveBeenCalledWith("workbench.action.reloadWindow"); + executeCommandMock.mockRestore(); + getConfigurationMock.mockRestore(); + getValueMock.mockRestore(); + setValueMock.mockRestore(); + onlyV1ProfsExistMock[Symbol.dispose](); + + profInfoSpy.mockRestore(); + }); + + it("should call v1ProfileOptions if team config does not exist and only v1 profiles exist", async () => { + const fakeProfInfo = { + readProfilesFromDisk: jest.fn(), + hasValidSchema: false, + getTeamConfig: () => ({ + exists: false, + }), + onlyV1ProfilesExist: () => true, + }; + const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { + configurable: true, + get: () => true, + }); + const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValueOnce(fakeProfInfo as any); + const getConfigurationMock = jest.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({ + persistent: true, + get: jest.fn(), + has: jest.fn(), + inspect: jest.fn(), + update: jest.fn(), + }); + const v1ProfileOptionsMock = jest.spyOn(ProfilesUtils as any, "v1ProfileOptions").mockImplementation(); + const getValueMock = jest.spyOn(ZoweLocalStorage, "getValue").mockReturnValue(Definitions.V1MigrationStatus.JustMigrated); + await ProfilesUtils.handleV1MigrationStatus(); + expect(getConfigurationMock).toHaveBeenCalledWith("Zowe-USS-Persistent"); + expect(getValueMock).toHaveBeenCalledWith(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); + expect(v1ProfileOptionsMock).toHaveBeenCalled(); + getConfigurationMock.mockRestore(); + getValueMock.mockRestore(); + v1ProfileOptionsMock.mockRestore(); + onlyV1ProfsExistMock[Symbol.dispose](); + + profInfoSpy.mockRestore(); + }); + + it("should show the Create Config prompt when Create New is chosen", async () => { + const mockReadProfilesFromDisk = jest.fn(); + const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockResolvedValue({ + readProfilesFromDisk: mockReadProfilesFromDisk, + getTeamConfig: jest.fn().mockReturnValue([]), + getAllProfiles: jest.fn().mockReturnValue([createValidIProfile(), createAltTypeIProfile()]), + } as never); + const msgSpy = jest.spyOn(Gui, "infoMessage").mockResolvedValueOnce("Create New" as any); + + const onlyV1ProfsExistMock = new MockedProperty(imperative.ProfileInfo, "onlyV1ProfilesExist", { + configurable: true, + get: () => true, + }); + const v1ProfOptsMock = jest.spyOn(ProfilesUtils as any, "v1ProfileOptions").mockResolvedValue(ProfilesConvertStatus.CreateNewSelected); + await expect((ProfilesUtils as any).v1ProfileOptions()).resolves.not.toThrow(); + expect(v1ProfOptsMock).toHaveBeenCalled(); + onlyV1ProfsExistMock[Symbol.dispose](); + + msgSpy.mockRestore(); + profInfoSpy.mockRestore(); }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/zosconsole/ZosConsolePanel.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/zosconsole/ZosConsolePanel.unit.test.ts index 7260408033..c5a3c48705 100644 --- a/packages/zowe-explorer/__tests__/__unit__/zosconsole/ZosConsolePanel.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/zosconsole/ZosConsolePanel.unit.test.ts @@ -13,7 +13,9 @@ import { createInstanceOfProfile, createIProfile } from "../../__mocks__/mockCre import { ZosConsoleViewProvider } from "../../../src/zosconsole/ZosConsolePanel"; import { Profiles } from "../../../src/configuration/Profiles"; import * as vscode from "vscode"; +import * as fs from "fs"; +jest.mock("fs"); jest.mock("@zowe/zowe-explorer-api", () => ({ ...jest.requireActual("@zowe/zowe-explorer-api"), HTMLTemplate: jest.requireActual("../../../../zowe-explorer-api/src/vscode/ui/utils/HTMLTemplate"), @@ -39,7 +41,10 @@ describe("ZosConsoleViewProvider", () => { configurable: true, }); Object.defineProperty(vscode.Uri, "joinPath", { value: jest.fn(), configurable: true }); - + const spyReadFile = jest.fn((path, encoding, callback) => { + callback(null, "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); return newMocks; } describe("resolveWebviewView", () => { @@ -49,5 +54,34 @@ describe("ZosConsoleViewProvider", () => { myconsole.resolveWebviewView(globalMocks.testWebView, {} as any, { isCancellationRequested: false } as any); expect(globalMocks.testWebView.webview.onDidReceiveMessage).toHaveBeenCalled(); }); + it("handles the get_localization message", async () => { + const globalMocks = createGlobalMocks(); + const myconsole = new ZosConsoleViewProvider({} as any); + const postMessageMock = jest.spyOn(globalMocks.testWebView.webview, "postMessage").mockImplementation(); + const onDidReceiveMessageCallback = jest + .spyOn(globalMocks.testWebView.webview, "onDidReceiveMessage") + .mockImplementation((callback: any) => { + callback({ command: "GET_LOCALIZATION" }); + }); + (myconsole as any).data = "file contents"; + myconsole.resolveWebviewView(globalMocks.testWebView, {} as any, { isCancellationRequested: false } as any); + expect(onDidReceiveMessageCallback).toHaveBeenCalled(); + expect(postMessageMock).toHaveBeenCalledWith({ type: "GET_LOCALIZATION", contents: (myconsole as any).data }); + }); + it("handles the get_localization message", async () => { + const globalMocks = createGlobalMocks(); + const spyReadFile = jest.fn((path, encoding, callback) => { + callback("error", "file contents"); + }); + Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true }); + const myconsole = new ZosConsoleViewProvider({} as any); + const onDidReceiveMessageCallback = jest + .spyOn(globalMocks.testWebView.webview, "onDidReceiveMessage") + .mockImplementation((callback: any) => { + callback({ command: "GET_LOCALIZATION" }); + }); + myconsole.resolveWebviewView(globalMocks.testWebView, {} as any, { isCancellationRequested: false } as any); + expect(onDidReceiveMessageCallback).toHaveBeenCalled(); + }); }); }); diff --git a/packages/zowe-explorer/l10n/bundle.l10n.json b/packages/zowe-explorer/l10n/bundle.l10n.json index 69f6380b85..ef955fbf6b 100644 --- a/packages/zowe-explorer/l10n/bundle.l10n.json +++ b/packages/zowe-explorer/l10n/bundle.l10n.json @@ -1,11 +1,53 @@ { + "Enter command here...": "Enter command here...", + "Page Size:": "Page Size:", + "Page": "Page", + "No": "No", + "item": "item", + "s": "s", + "selected": "selected", + "Data Sets": "Data Sets", + "Unix System Services (USS)": "Unix System Services (USS)", + "Jobs": "Jobs", + "DataPanelContext has to be used within ": "DataPanelContext has to be used within ", "Refresh": "Refresh", + "Search History": "Search History", + "Favorites": "Favorites", + "File History": "File History", + "Sessions": "Sessions", + "Encoding History": "Encoding History", "Delete Selected": "Delete Selected", "Select an item before deleting": "Select an item before deleting", + "Delete": "Delete", "Clear All": "Clear All", "Add New History Item": "Add New History Item", + "Add": "Add", + "No records found": "No records found", "Item": "Item", "Select": "Select", + "Last refreshed:": "Last refreshed:", + "Manage Persistent Properties": "Manage Persistent Properties", + "Read": "Read", + "Write": "Write", + "Execute": "Execute", + "User": "User", + "Group": "Group", + "All": "All", + "File properties": "File properties", + "Tag": "Tag", + "Owner": "Owner", + "Apply changes": "Apply changes", + "The API does not support updating attributes for this": "The API does not support updating attributes for this", + "Waiting for data from extension...": "Waiting for data from extension...", + "Log in to Authentication Service": "Log in to Authentication Service", + "Select a certificate and certificate key in PEM format:": "Select a certificate and certificate key in PEM format:", + "Value": "Value", + "Actions": "Actions", + "Certificate File": "Certificate File", + "Browse": "Browse", + "Certificate Key File": "Certificate Key File", + "Submit": "Submit", + "Cancel": "Cancel", "Zowe explorer profiles are being set as unsecured.": "Zowe explorer profiles are being set as unsecured.", "Zowe explorer profiles are being set as secured.": "Zowe explorer profiles are being set as secured.", "Custom credential manager failed to activate": "Custom credential manager failed to activate", @@ -15,7 +57,6 @@ "Credential manager display name" ] }, - "No": "No", "Yes, globally": "Yes, globally", "Only for this workspace": "Only for this workspace", "Zowe Explorer failed to activate since the default credential manager is not supported in your environment.": "Zowe Explorer failed to activate since the default credential manager is not supported in your environment.", @@ -87,7 +128,6 @@ }, "Zowe Profiles initialized successfully.": "Zowe Profiles initialized successfully.", "Convert Existing Profiles": "Convert Existing Profiles", - "Operation cancelled": "Operation cancelled", "Tree Item is not a Zowe Explorer item.": "Tree Item is not a Zowe Explorer item.", "Zowe Explorer": "Zowe Explorer", "Initialized logger for Zowe Explorer": "Initialized logger for Zowe Explorer", @@ -132,7 +172,6 @@ "Label" ] }, - "Log in to Authentication Service": "Log in to Authentication Service", "Update Credentials": "Update Credentials", "Profile Name {0} is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct./Profile name": { "message": "Profile Name {0} is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct.", @@ -140,7 +179,6 @@ "Profile name" ] }, - "Favorites": "Favorites", "Use the search button to list USS files": "Use the search button to list USS files", "Invalid node": "Invalid node", "Delete action was cancelled.": "Delete action was cancelled.", @@ -174,7 +212,7 @@ "The 'move' function is not implemented for this USS API.": "The 'move' function is not implemented for this USS API.", "Could not list USS files: Empty path provided in URI": "Could not list USS files: Empty path provided in URI", "Profile does not exist for this file.": "Profile does not exist for this file.", - "$(sync~spin) Saving USS file...": "$(sync~spin) Saving USS file...", + "Saving USS file...": "Saving USS file...", "Renaming {0} failed due to API error: {1}/File pathError message": { "message": "Renaming {0} failed due to API error: {1}", "comment": [ @@ -210,11 +248,11 @@ ] }, "Binary": "Binary", - "$(plus) Create a new filter": "$(plus) Create a new filter", + "Create a new filter": "Create a new filter", "Failed to move file {0}: {1}": "Failed to move file {0}: {1}", "Confirm": "Confirm", "One or more items may be overwritten from this drop operation. Confirm or cancel?": "One or more items may be overwritten from this drop operation. Confirm or cancel?", - "$(sync~spin) Moving USS files...": "$(sync~spin) Moving USS files...", + "Moving USS files...": "Moving USS files...", "Unable to rename {0} because you have unsaved changes in this {1}. Please save your work before renaming the {1}./Node pathNode type": { "message": "Unable to rename {0} because you have unsaved changes in this {1}. Please save your work before renaming the {1}.", "comment": [ @@ -266,7 +304,7 @@ }, "initializeUSSFavorites.error.buttonRemove": "initializeUSSFavorites.error.buttonRemove", "File does not exist. It may have been deleted.": "File does not exist. It may have been deleted.", - "$(sync~spin) Pulling from Mainframe...": "$(sync~spin) Pulling from Mainframe...", + "Pulling from Mainframe...": "Pulling from Mainframe...", "{0} location/Node type": { "message": "{0} location", "comment": [ @@ -284,7 +322,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", - "Delete": "Delete", "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": [ @@ -353,21 +390,21 @@ "No spool files found": "No spool files found", "No jobs found": "No jobs found", "Retrieving response from JES list API": "Retrieving response from JES list API", - "$(list-ordered) Job ID (default)": "$(list-ordered) Job ID (default)", - "$(calendar) Date Submitted": "$(calendar) Date Submitted", - "$(calendar) Date Completed": "$(calendar) Date Completed", - "$(case-sensitive) Job Name": "$(case-sensitive) Job Name", - "$(symbol-numeric) Return Code": "$(symbol-numeric) Return Code", - "$(fold) Sort Direction": "$(fold) Sort Direction", + "Job ID (default)": "Job ID (default)", + "Date Submitted": "Date Submitted", + "Date Completed": "Date Completed", + "Job Name": "Job Name", + "Return Code": "Return Code", + "Sort Direction": "Sort Direction", "Go to Local Filtering": "Go to Local Filtering", - "$(clear-all) Clear filter for profile": "$(clear-all) Clear filter for profile", + "Clear filter for profile": "Clear filter for profile", "Create new...": "Create new...", - "$(check) Submit this query": "$(check) Submit this query", + "Submit this query": "Submit this query", "Enter job owner ID": "Enter job owner ID", "Enter job prefix": "Enter job prefix", "Enter job status": "Enter job status", - "$(plus) Create job search filter": "$(plus) Create job search filter", - "$(search) Search by job ID": "$(search) Search by job ID", + "Create job search filter": "Create job search filter", + "Search by job ID": "Search by job ID", "Initializing profiles with jobs favorites.": "Initializing profiles with jobs favorites.", "No jobs favorites found.": "No jobs favorites found.", "Loading profile: {0} for jobs favorites/Profile name": { @@ -399,8 +436,8 @@ "URI path" ] }, - "$(sync~spin) Polling: {0}.../Unique Spool name": { - "message": "$(sync~spin) Polling: {0}...", + "Polling: {0}.../Unique Spool name": { + "message": "Polling: {0}...", "comment": [ "Unique Spool name" ] @@ -412,22 +449,21 @@ ] }, "Set a filter...": "Set a filter...", - "$(check) Filter cleared for {0}/Job label": { - "message": "$(check) Filter cleared for {0}", + "Filter cleared for {0}/Job label": { + "message": "Filter cleared for {0}", "comment": [ "Job label" ] }, "Enter local filter...": "Enter local filter...", - "$(check) Filter updated for {0}/Job label": { - "message": "$(check) Filter updated for {0}", + "Filter updated for {0}/Job label": { + "message": "Filter updated for {0}", "comment": [ "Job label" ] }, "Get JCL": "Get JCL", "Display in Tree": "Display in Tree", - "Cancel": "Cancel", "Download": "Download", "Jobs with ID: {0}/Job Search ID": { "message": "Jobs with ID: {0}", @@ -443,12 +479,9 @@ "Job Status" ] }, - "Jobs": "Jobs", "Name": "Name", "Class": "Class", - "Owner": "Owner", "ID": "ID", - "Return Code": "Return Code", "Status": "Status", "Subsystem": "Subsystem", "Type": "Type", @@ -456,7 +489,7 @@ "Phase": "Phase", "Phase Name": "Phase Name", "Error Details": "Error Details", - "$(sync~spin) Fetching spool file...": "$(sync~spin) Fetching spool file...", + "Fetching spool file...": "Fetching spool file...", "Failed to fetch jobs: getJobsByParameters is not implemented for this session's JES API.": "Failed to fetch jobs: getJobsByParameters is not implemented for this session's JES API.", "Are you sure you want to delete the following item?\nThis will permanently remove the following job from your system.\n\n{0}/Job name": { "message": "Are you sure you want to delete the following item?\nThis will permanently remove the following job from your system.\n\n{0}", @@ -490,8 +523,8 @@ "Spool node label" ] }, - "$(sync~spin) Polling: {0}.../Document file name": { - "message": "$(sync~spin) Polling: {0}...", + "Polling: {0}.../Document file name": { + "message": "Polling: {0}...", "comment": [ "Document file name" ] @@ -528,8 +561,8 @@ ] }, "Select a sorting direction": "Select a sorting direction", - "$(check) Sorting updated for {0}/Session label": { - "message": "$(check) Sorting updated for {0}", + "Sorting updated for {0}/Session label": { + "message": "Sorting updated for {0}", "comment": [ "Session label" ] @@ -540,11 +573,11 @@ "No data sets found": "No data sets found", "Retrieving response from MVS list API": "Retrieving response from MVS list API", "Cannot download, item invalid.": "Cannot download, item invalid.", - "$(case-sensitive) Name (default)": "$(case-sensitive) Name (default)", - "$(calendar) Date Created": "$(calendar) Date Created", - "$(calendar) Date Modified": "$(calendar) Date Modified", - "$(account) User ID": "$(account) User ID", - "$(plus) Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)": "$(plus) Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)", + "Name (default)": "Name (default)", + "Date Created": "Date Created", + "Date Modified": "Date Modified", + "User ID": "User ID", + "Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)": "Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)", "Initializing profiles with data set favorites.": "Initializing profiles with data set favorites.", "No data set favorites found.": "No data set favorites found.", "Error creating data set favorite node: {0} for profile {1}./LabelProfile name": { @@ -604,8 +637,8 @@ "Specifier" ] }, - "$(check) Sorting updated for {0}/Node label": { - "message": "$(check) Sorting updated for {0}", + "Sorting updated for {0}/Node label": { + "message": "Sorting updated for {0}", "comment": [ "Node label" ] @@ -616,15 +649,15 @@ "Filter value" ] }, - "$(clear-all) Clear filter for PDS": "$(clear-all) Clear filter for PDS", + "Clear filter for PDS": "Clear filter for PDS", "Set a filter for {0}/Specifier": { "message": "Set a filter for {0}", "comment": [ "Specifier" ] }, - "$(check) Filter cleared for {0}/Node label": { - "message": "$(check) Filter cleared for {0}", + "Filter cleared for {0}/Node label": { + "message": "Filter cleared for {0}", "comment": [ "Node label" ] @@ -632,8 +665,8 @@ "Invalid date format specified": "Invalid date format specified", "Enter a value to filter by": "Enter a value to filter by", "Invalid filter specified": "Invalid filter specified", - "$(check) Filter updated for {0}/Node label": { - "message": "$(check) Filter updated for {0}", + "Filter updated for {0}/Node label": { + "message": "Filter updated for {0}", "comment": [ "Node label" ] @@ -646,7 +679,7 @@ "Choose the setting location to save the data set template...": "Choose the setting location to save the data set template...", "Save as User setting": "Save as User setting", "Save as Workspace setting": "Save as Workspace setting", - "$(sync~spin) Saving data set...": "$(sync~spin) Saving data set...", + "Saving data set...": "Saving data set...", "Deleting {0} failed due to API error: {1}/File pathError message": { "message": "Deleting {0} failed due to API error: {1}", "comment": [ @@ -795,7 +828,7 @@ ] }, "Item invalid.": "Item invalid.", - "$(sync~spin) Fetching data set...": "$(sync~spin) Fetching data set...", + "Fetching data set...": "Fetching data set...", "Error encountered when refreshing data set view. {0}/Stringified JSON error": { "message": "Error encountered when refreshing data set view. {0}", "comment": [ @@ -832,24 +865,23 @@ ] }, "Error encountered while activating and initializing logger": "Error encountered while activating and initializing logger", - "$(plus) Add Credentials": "$(plus) Add Credentials", + "Add Credentials": "Add Credentials", "Add username and password for basic authentication": "Add username and password for basic authentication", - "$(refresh) Update Credentials": "$(refresh) Update Credentials", "Update stored username and password": "Update stored username and password", - "$(trash) Delete Profile": "$(trash) Delete Profile", - "$(workspace-untrusted) Disable Profile Validation": "$(workspace-untrusted) Disable Profile Validation", + "Delete Profile": "Delete Profile", + "Disable Profile Validation": "Disable Profile Validation", "Disable validation of server check for profile": "Disable validation of server check for profile", - "$(workspace-trusted) Enable Profile Validation": "$(workspace-trusted) Enable Profile Validation", + "Enable Profile Validation": "Enable Profile Validation", "Enable validation of server check for profile": "Enable validation of server check for profile", - "$(pencil) Edit Profile": "$(pencil) Edit Profile", + "Edit Profile": "Edit Profile", "Update profile connection information": "Update profile connection information", - "$(eye-closed) Hide Profile": "$(eye-closed) Hide Profile", + "Hide Profile": "Hide Profile", "Hide profile name from tree view": "Hide profile name from tree view", - "$(key) Change the Authentication Method": "$(key) Change the Authentication Method", + "Change the Authentication Method": "Change the Authentication Method", "Change the authentication method": "Change the authentication method", - "$(arrow-right) Log in to authentication service": "$(arrow-right) Log in to authentication service", + "Log in to authentication service": "Log in to authentication service", "Log in to obtain a new token value": "Log in to obtain a new token value", - "$(arrow-left) Log out of authentication service": "$(arrow-left) Log out of authentication service", + "Log out of authentication service": "Log out of authentication service", "Log out to invalidate and remove stored token value": "Log out to invalidate and remove stored token value", "Profile {0} is using basic authentication. Choose a profile action./Profile name": { "message": "Profile {0} is using basic authentication. Choose a profile action.", @@ -1034,7 +1066,7 @@ "All jobs": "All jobs", "Ascending": "Ascending", "Descending": "Descending", - "$(plus) Create a new Unix command": "$(plus) Create a new Unix command", + "Create a new Unix command": "Create a new Unix command", "Issuing commands is not supported for this profile type, {0}./Profile type": { "message": "Issuing commands is not supported for this profile type, {0}.", "comment": [ @@ -1047,14 +1079,14 @@ "Profile type" ] }, - "Error preparring SSH connection for issueing UNIX commands, please check SSH profile for correctness.": "Error preparring SSH connection for issueing UNIX commands, please check SSH profile for correctness.", + "Error preparing SSH connection for issuing UNIX commands, please check SSH profile for correctness.": "Error preparing SSH connection for issuing UNIX commands, please check SSH profile for correctness.", "No SSH profile found. Please create an SSH profile.": "No SSH profile found. Please create an SSH profile.", "SSH profile missing connection details. Please update.": "SSH profile missing connection details. Please update.", "No profiles available.": "No profiles available.", "Redirecting to Home Directory": "Redirecting to Home Directory", "Zowe Unix Command": "Zowe Unix Command", "An SSH profile will be used for issuing UNIX commands with the profile {0}.": "An SSH profile will be used for issuing UNIX commands with the profile {0}.", - "Error checking if SSH profile type required for issueing UNIX commands, setting requirement to false for profile {0}.": "Error checking if SSH profile type required for issueing UNIX commands, setting requirement to false for profile {0}.", + "Error checking if SSH profile type required for issuing UNIX commands, setting requirement to false for profile {0}.": "Error checking if SSH profile type required for issuing UNIX commands, setting requirement to false for profile {0}.", "Enter the path of the directory in order to execute the command": "Enter the path of the directory in order to execute the command", "Not implemented yet for profile of type: {0}/Profile type": { "message": "Not implemented yet for profile of type: {0}", @@ -1078,7 +1110,7 @@ }, "Enter or update the Unix command": "Enter or update the Unix command", "Unix command submitted.": "Unix command submitted.", - "$(plus) Create a new TSO command": "$(plus) Create a new TSO command", + "Create a new TSO command": "Create a new TSO command", "Zowe TSO Command": "Zowe TSO Command", "Select the Profile to use to submit the TSO command": "Select the Profile to use to submit the TSO command", "Profile is invalid": "Profile is invalid", @@ -1102,7 +1134,7 @@ "Account Number": "Account Number", "Enter the account number for the TSO connection.": "Enter the account number for the TSO connection.", "Operation Cancelled.": "Operation Cancelled.", - "$(plus) Create a new MVS command": "$(plus) Create a new MVS command", + "Create a new MVS command": "Create a new MVS command", "Zowe MVS Command": "Zowe MVS Command", "Select the Profile to use to submit the command": "Select the Profile to use to submit the command", "Select an MVS command to run against {0} (An option to edit will follow)/Host name": { diff --git a/packages/zowe-explorer/l10n/poeditor.json b/packages/zowe-explorer/l10n/poeditor.json index 6e38e9d54b..c5ed995fce 100644 --- a/packages/zowe-explorer/l10n/poeditor.json +++ b/packages/zowe-explorer/l10n/poeditor.json @@ -410,18 +410,59 @@ "zowe.history.deprecationMsg": { "Changes made here will not be reflected in Zowe Explorer, use right-click Edit History option to access information from local storage.": "" }, + "Enter command here...": "", + "Page Size:": "", + "Page": "", + "No": "", + "item": "", + "s": "", + "selected": "", + "Data Sets": "", + "Unix System Services (USS)": "", + "Jobs": "", + "DataPanelContext has to be used within ": "", "Refresh": "", + "Search History": "", + "Favorites": "", + "File History": "", + "Sessions": "", + "Encoding History": "", "Delete Selected": "", "Select an item before deleting": "", + "Delete": "", "Clear All": "", "Add New History Item": "", + "Add": "", + "No records found": "", "Item": "", "Select": "", + "Last refreshed:": "", + "Manage Persistent Properties": "", + "Read": "", + "Write": "", + "Execute": "", + "User": "", + "Group": "", + "All": "", + "File properties": "", + "Tag": "", + "Owner": "", + "Apply changes": "", + "The API does not support updating attributes for this": "", + "Waiting for data from extension...": "", + "Log in to Authentication Service": "", + "Select a certificate and certificate key in PEM format:": "", + "Value": "", + "Actions": "", + "Certificate File": "", + "Browse": "", + "Certificate Key File": "", + "Submit": "", + "Cancel": "", "Zowe explorer profiles are being set as unsecured.": "", "Zowe explorer profiles are being set as secured.": "", "Custom credential manager failed to activate": "", "Custom credential manager {0} found, attempting to activate.": "", - "No": "", "Yes, globally": "", "Only for this workspace": "", "Zowe Explorer failed to activate since the default credential manager is not supported in your environment.": "", @@ -452,7 +493,6 @@ "Failed to initialize Zowe folder: {0}": "", "Zowe Profiles initialized successfully.": "", "Convert Existing Profiles": "", - "Operation cancelled": "", "Tree Item is not a Zowe Explorer item.": "", "Zowe Explorer": "", "Initialized logger for Zowe Explorer": "", @@ -472,10 +512,8 @@ "Required parameter 'host' must not be blank.": "", "Invalid Credentials for profile '{0}'. Please ensure the username and password are valid or this may lead to a lock-out.": "", "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection.": "", - "Log in to Authentication Service": "", "Update Credentials": "", "Profile Name {0} is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct.": "", - "Favorites": "", "Use the search button to list USS files": "", "Invalid node": "", "Delete action was cancelled.": "", @@ -494,7 +532,7 @@ "The 'move' function is not implemented for this USS API.": "", "Could not list USS files: Empty path provided in URI": "", "Profile does not exist for this file.": "", - "$(sync~spin) Saving USS file...": "", + "Saving USS file...": "", "Renaming {0} failed due to API error: {1}": "", "Deleting {0} failed due to API error: {1}": "", "No error details given": "", @@ -502,11 +540,11 @@ "Downloaded: {0}": "", "Encoding: {0}": "", "Binary": "", - "$(plus) Create a new filter": "", + "Create a new filter": "", "Failed to move file {0}: {1}": "", "Confirm": "", "One or more items may be overwritten from this drop operation. Confirm or cancel?": "", - "$(sync~spin) Moving USS files...": "", + "Moving USS files...": "", "Unable to rename {0} because you have unsaved changes in this {1}. Please save your work before renaming the {1}.": "", "Enter a new name for the {0}": "", "Unable to rename node:": "", @@ -526,7 +564,7 @@ "Error: You have Zowe USS favorites that refer to a non-existent CLI profile named: {0}.\n To resolve this, you can remove {0} from the Favorites section of Zowe Explorer's USS view.\n Would you like to do this now? {1}": "", "initializeUSSFavorites.error.buttonRemove": "", "File does not exist. It may have been deleted.": "", - "$(sync~spin) Pulling from Mainframe...": "", + "Pulling from Mainframe...": "", "{0} location": "", "Choose a location to create the {0}": "", "Name of file or directory": "", @@ -534,7 +572,6 @@ "Uploading file to USS tree": "", "Upload action was cancelled.": "", "Uploading USS file": "", - "Delete": "", "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...": "", @@ -573,21 +610,21 @@ "No spool files found": "", "No jobs found": "", "Retrieving response from JES list API": "", - "$(list-ordered) Job ID (default)": "", - "$(calendar) Date Submitted": "", - "$(calendar) Date Completed": "", - "$(case-sensitive) Job Name": "", - "$(symbol-numeric) Return Code": "", - "$(fold) Sort Direction": "", + "Job ID (default)": "", + "Date Submitted": "", + "Date Completed": "", + "Job Name": "", + "Return Code": "", + "Sort Direction": "", "Go to Local Filtering": "", - "$(clear-all) Clear filter for profile": "", + "Clear filter for profile": "", "Create new...": "", - "$(check) Submit this query": "", + "Submit this query": "", "Enter job owner ID": "", "Enter job prefix": "", "Enter job status": "", - "$(plus) Create job search filter": "", - "$(search) Search by job ID": "", + "Create job search filter": "", + "Search by job ID": "", "Initializing profiles with jobs favorites.": "", "No jobs favorites found.": "", "Loading profile: {0} for jobs favorites": "", @@ -598,24 +635,20 @@ "Job search cancelled.": "", "The polling interval must be greater than or equal to 1000ms.": "", "Poll interval (in ms) for: {0}": "", - "$(sync~spin) Polling: {0}...": "", + "Polling: {0}...": "", "Filter: {0}": "", "Set a filter...": "", - "$(check) Filter cleared for {0}": "", + "Filter cleared for {0}": "", "Enter local filter...": "", - "$(check) Filter updated for {0}": "", + "Filter updated for {0}": "", "Get JCL": "", "Display in Tree": "", - "Cancel": "", "Download": "", "Jobs with ID: {0}": "", "Jobs: {0} | {1} | {2}": "", - "Jobs": "", "Name": "", "Class": "", - "Owner": "", "ID": "", - "Return Code": "", "Status": "", "Subsystem": "", "Type": "", @@ -623,7 +656,7 @@ "Phase": "", "Phase Name": "", "Error Details": "", - "$(sync~spin) Fetching spool file...": "", + "Fetching spool file...": "", "Failed to fetch jobs: getJobsByParameters is not implemented for this session's JES API.": "", "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.": "", @@ -643,18 +676,18 @@ "Cancelled selected jobs successfully.": "", "Select a sorting option for jobs in {0}": "", "Select a sorting direction": "", - "$(check) Sorting updated for {0}": "", + "Sorting updated for {0}": "", "Use the search button to display data sets": "", "The response from Zowe CLI was not successful": "", "{0} members failed to load due to invalid name errors for {1}": "", "No data sets found": "", "Retrieving response from MVS list API": "", "Cannot download, item invalid.": "", - "$(case-sensitive) Name (default)": "", - "$(calendar) Date Created": "", - "$(calendar) Date Modified": "", - "$(account) User ID": "", - "$(plus) Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)": "", + "Name (default)": "", + "Date Created": "", + "Date Modified": "", + "User ID": "", + "Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)": "", "Initializing profiles with data set favorites.": "", "No data set favorites found.": "", "Error creating data set favorite node: {0} for profile {1}.": "", @@ -672,7 +705,7 @@ "all PDS members in {0}": "", "the PDS members in {0}": "", "Select a sorting option for {0}": "", - "$(clear-all) Clear filter for PDS": "", + "Clear filter for PDS": "", "Set a filter for {0}": "", "Invalid date format specified": "", "Enter a value to filter by": "", @@ -685,7 +718,7 @@ "Choose the setting location to save the data set template...": "", "Save as User setting": "", "Save as Workspace setting": "", - "$(sync~spin) Saving data set...": "", + "Saving data set...": "", "Partitioned Data Set: Binary": "", "Partitioned Data Set: C": "", "Partitioned Data Set: Classic": "", @@ -739,7 +772,7 @@ "Error encountered when deleting data set. {0}": "", "Unable to find file {0}": "", "Item invalid.": "", - "$(sync~spin) Fetching data set...": "", + "Fetching data set...": "", "Error encountered when refreshing data set view. {0}": "", "Cannot perform the copy operation as the data sets selected have different types": "", "Migration of data set {0} requested.": "", @@ -755,24 +788,23 @@ "Unable to copy data set.": "", "Failed to upload changes for {0}: {1}": "", "Error encountered while activating and initializing logger": "", - "$(plus) Add Credentials": "", + "Add Credentials": "", "Add username and password for basic authentication": "", - "$(refresh) Update Credentials": "", "Update stored username and password": "", - "$(trash) Delete Profile": "", - "$(workspace-untrusted) Disable Profile Validation": "", + "Delete Profile": "", + "Disable Profile Validation": "", "Disable validation of server check for profile": "", - "$(workspace-trusted) Enable Profile Validation": "", + "Enable Profile Validation": "", "Enable validation of server check for profile": "", - "$(pencil) Edit Profile": "", + "Edit Profile": "", "Update profile connection information": "", - "$(eye-closed) Hide Profile": "", + "Hide Profile": "", "Hide profile name from tree view": "", - "$(key) Change the Authentication Method": "", + "Change the Authentication Method": "", "Change the authentication method": "", - "$(arrow-right) Log in to authentication service": "", + "Log in to authentication service": "", "Log in to obtain a new token value": "", - "$(arrow-left) Log out of authentication service": "", + "Log out of authentication service": "", "Log out to invalidate and remove stored token value": "", "Profile {0} is using basic authentication. Choose a profile action.": "", "Profile {0} is using token authentication. Choose a profile action.": "", @@ -854,17 +886,17 @@ "All jobs": "", "Ascending": "", "Descending": "", - "$(plus) Create a new Unix command": "", + "Create a new Unix command": "", "Issuing commands is not supported for this profile type, {0}.": "", "Issuing UNIX commands is not supported for this profile type, {0}.": "", - "Error preparring SSH connection for issueing UNIX commands, please check SSH profile for correctness.": "", + "Error preparing SSH connection for issuing UNIX commands, please check SSH profile for correctness.": "", "No SSH profile found. Please create an SSH profile.": "", "SSH profile missing connection details. Please update.": "", "No profiles available.": "", "Redirecting to Home Directory": "", "Zowe Unix Command": "", "An SSH profile will be used for issuing UNIX commands with the profile {0}.": "", - "Error checking if SSH profile type required for issueing UNIX commands, setting requirement to false for profile {0}.": "", + "Error checking if SSH profile type required for issuing UNIX commands, setting requirement to false for profile {0}.": "", "Enter the path of the directory in order to execute the command": "", "Select the ssh Profile.": "", "Select the Profile to use to submit the Unix command": "", @@ -872,7 +904,7 @@ "Select a Unix command to run immediately against {0}": "", "Enter or update the Unix command": "", "Unix command submitted.": "", - "$(plus) Create a new TSO command": "", + "Create a new TSO command": "", "Zowe TSO Command": "", "Select the Profile to use to submit the TSO command": "", "Profile is invalid": "", @@ -886,7 +918,7 @@ "Account Number": "", "Enter the account number for the TSO connection.": "", "Operation Cancelled.": "", - "$(plus) Create a new MVS command": "", + "Create a new MVS command": "", "Zowe MVS Command": "", "Select the Profile to use to submit the command": "", "Select an MVS command to run against {0} (An option to edit will follow)": "", diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 0610c589bb..3f8d79240d 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -1768,7 +1768,7 @@ ] }, "scripts": { - "build": "pnpm copy-secrets && pnpm clean:bundle && pnpm license && webpack --mode development && pnpm madge", + "build": "pnpm copy-secrets && pnpm clean:bundle && pnpm license && pnpm build:nls && webpack --mode development && pnpm madge", "test": "pnpm test:unit", "test:e2e": "cd __tests__/__e2e__/ && wdio run ./wdio.conf.ts", "test:integration": "cd __tests__/__integration__/bdd && wdio run ./wdio.conf.ts", @@ -1795,7 +1795,9 @@ "pretty": "prettier --write .", "generateLocalization": "pnpm dlx @vscode/l10n-dev export --o ./l10n ./src && node ./scripts/generatePoeditorJson.js", "copy-secrets": "node ./scripts/getSecretsPrebuilds.js", - "strip-l10n": "node ./scripts/stripL10nComments.js" + "build:nlsExtract": "pnpm dlx @vscode/l10n-dev export --outDir ./l10n ./src", + "build:nlsPseudo": "pnpm dlx @vscode/l10n-dev generate-pseudo -o ./l10n/ ./l10n/bundle.l10n.json ./package.nls.json", + "build:nls": "pnpm run build:nlsExtract && pnpm run build:nlsPseudo" }, "engines": { "vscode": "^1.79.0" diff --git a/packages/zowe-explorer/scripts/generatePoeditorJson.js b/packages/zowe-explorer/scripts/generatePoeditorJson.js index 90753e24e9..afd8bac577 100644 --- a/packages/zowe-explorer/scripts/generatePoeditorJson.js +++ b/packages/zowe-explorer/scripts/generatePoeditorJson.js @@ -5,7 +5,7 @@ */ const fs = require("fs"); -const langId = process.argv[2]; +const langId = process.argv.slice(2).find(arg => !arg.startsWith("-")); const fileSuffix = langId ? `${langId}.json` : "json"; const poeditorJson = {}; const packageNls = require(__dirname + "/../package.nls." + fileSuffix); @@ -25,3 +25,16 @@ for (const [k, v] of Object.entries(l10nBundle)) { } } fs.writeFileSync(__dirname + "/../l10n/poeditor." + fileSuffix, JSON.stringify(poeditorJson, null, 2) + "\n"); + +if (process.argv.includes("--strip")) { + // Strip comments out of bundle.l10n.json and sort properties by key + const jsonFilePath = __dirname + "/../l10n/bundle.l10n.json"; + let l10nBundle = JSON.parse(fs.readFileSync(jsonFilePath, "utf-8")); + for (const [k, v] of Object.entries(l10nBundle)) { + if (typeof v === "object") { + l10nBundle[k] = l10nBundle[k].message; + } + } + l10nBundle = Object.fromEntries(Object.entries(l10nBundle).sort(([a], [b]) => a.localeCompare(b))); + fs.writeFileSync(jsonFilePath, JSON.stringify(l10nBundle, null, 2) + "\n"); +} diff --git a/packages/zowe-explorer/scripts/stripL10nComments.js b/packages/zowe-explorer/scripts/stripL10nComments.js deleted file mode 100644 index 23c60b78eb..0000000000 --- a/packages/zowe-explorer/scripts/stripL10nComments.js +++ /dev/null @@ -1,11 +0,0 @@ -// Strip comments out of bundle.l10n.json and sort properties by key -const fs = require("fs"); -const jsonFilePath = process.argv[2] || (__dirname + "/../l10n/bundle.l10n.json"); -let l10nBundle = JSON.parse(fs.readFileSync(jsonFilePath, "utf-8")); -for (const [k, v] of Object.entries(l10nBundle)) { - if (typeof v === "object") { - l10nBundle[k] = l10nBundle[k].message; - } -} -l10nBundle = Object.fromEntries(Object.entries(l10nBundle).sort(([a], [b]) => a.localeCompare(b))); -fs.writeFileSync(jsonFilePath + ".template", JSON.stringify(l10nBundle, null, 2) + "\n"); diff --git a/packages/zowe-explorer/src/commands/MvsCommandHandler.ts b/packages/zowe-explorer/src/commands/MvsCommandHandler.ts index b938233430..d0890f4be9 100644 --- a/packages/zowe-explorer/src/commands/MvsCommandHandler.ts +++ b/packages/zowe-explorer/src/commands/MvsCommandHandler.ts @@ -42,7 +42,7 @@ export class MvsCommandHandler extends ZoweCommandProvider { return this.instance; } - private static readonly defaultDialogText: string = vscode.l10n.t("$(plus) Create a new MVS command"); + private static readonly defaultDialogText: string = `$(plus) ${vscode.l10n.t("Create a new MVS command")}`; private static instance: MvsCommandHandler; public outputChannel: vscode.OutputChannel; diff --git a/packages/zowe-explorer/src/commands/TsoCommandHandler.ts b/packages/zowe-explorer/src/commands/TsoCommandHandler.ts index 2f380f2dfe..a83612f748 100644 --- a/packages/zowe-explorer/src/commands/TsoCommandHandler.ts +++ b/packages/zowe-explorer/src/commands/TsoCommandHandler.ts @@ -43,7 +43,7 @@ export class TsoCommandHandler extends ZoweCommandProvider { return this.instance; } - private static readonly defaultDialogText: string = vscode.l10n.t("$(plus) Create a new TSO command"); + private static readonly defaultDialogText: string = `$(plus) ${vscode.l10n.t("Create a new TSO command")}`; private static instance: TsoCommandHandler; public outputChannel: vscode.OutputChannel; diff --git a/packages/zowe-explorer/src/commands/UnixCommandHandler.ts b/packages/zowe-explorer/src/commands/UnixCommandHandler.ts index f9518df971..6e3fbfa72a 100644 --- a/packages/zowe-explorer/src/commands/UnixCommandHandler.ts +++ b/packages/zowe-explorer/src/commands/UnixCommandHandler.ts @@ -43,7 +43,7 @@ export class UnixCommandHandler extends ZoweCommandProvider { return this.instance; } - private static readonly defaultDialogText: string = vscode.l10n.t("$(plus) Create a new Unix command"); + private static readonly defaultDialogText: string = `$(plus) ${vscode.l10n.t("Create a new Unix command")}`; private static instance: UnixCommandHandler; private serviceProf: imperative.IProfileLoaded = undefined; private unixCmdMsgs = { @@ -58,7 +58,7 @@ export class UnixCommandHandler extends ZoweCommandProvider { args: [this.serviceProf?.type], comment: ["Profile type"], }), - sshSessionErrorMsg: vscode.l10n.t("Error preparring SSH connection for issueing UNIX commands, please check SSH profile for correctness."), + sshSessionErrorMsg: vscode.l10n.t("Error preparing SSH connection for issuing UNIX commands, please check SSH profile for correctness."), sshProfNotFoundMsg: vscode.l10n.t("No SSH profile found. Please create an SSH profile."), sshProfMissingInfoMsg: vscode.l10n.t("SSH profile missing connection details. Please update."), noProfilesAvailableMsg: vscode.l10n.t("No profiles available."), @@ -117,7 +117,7 @@ export class UnixCommandHandler extends ZoweCommandProvider { // error would be due to missing API, assuming SSH profile not required ZoweLogger.warn( vscode.l10n.t( - "Error checking if SSH profile type required for issueing UNIX commands, setting requirement to false for profile {0}.", + "Error checking if SSH profile type required for issuing UNIX commands, setting requirement to false for profile {0}.", [this.serviceProf?.name] ) ); diff --git a/packages/zowe-explorer/src/configuration/Definitions.ts b/packages/zowe-explorer/src/configuration/Definitions.ts index 94713a6d9f..46eb078898 100644 --- a/packages/zowe-explorer/src/configuration/Definitions.ts +++ b/packages/zowe-explorer/src/configuration/Definitions.ts @@ -127,7 +127,7 @@ export namespace Definitions { AllJobs, } export enum V1MigrationStatus { - CreateConfigSelected, + None, JustMigrated, } export enum LocalStorageKey { diff --git a/packages/zowe-explorer/src/extension.ts b/packages/zowe-explorer/src/extension.ts index 8cc3e76434..8176f3df87 100644 --- a/packages/zowe-explorer/src/extension.ts +++ b/packages/zowe-explorer/src/extension.ts @@ -36,6 +36,7 @@ export async function activate(context: vscode.ExtensionContext): Promise ZoweExplorerExtender.showZoweConfigError(msg)); + await ProfilesUtils.handleV1MigrationStatus(); await Profiles.createInstance(ZoweLogger.imperativeLogger); const providers = await SharedTreeProviders.initializeProviders( @@ -55,7 +56,6 @@ export async function activate(context: vscode.ExtensionContext): Promise = { + public static readonly basicAuthAddQpItems: Record = { [ProfileManagement.AuthQpLabels.add]: { - label: vscode.l10n.t("$(plus) Add Credentials"), + label: `$(plus) ${vscode.l10n.t("Add Credentials")}`, description: vscode.l10n.t("Add username and password for basic authentication"), }, }; - public static basicAuthUpdateQpItems: Record = { + public static readonly basicAuthUpdateQpItems: Record = { [ProfileManagement.AuthQpLabels.update]: { - label: vscode.l10n.t("$(refresh) Update Credentials"), + label: `$(refresh) ${vscode.l10n.t("Update Credentials")}`, description: vscode.l10n.t("Update stored username and password"), }, }; - public static deleteProfileQpItem: Record = { + public static readonly deleteProfileQpItem: Record = { [ProfileManagement.AuthQpLabels.delete]: { - label: vscode.l10n.t("$(trash) Delete Profile"), + label: `$(trash) ${vscode.l10n.t("Delete Profile")}`, }, }; - public static disableProfileValildationQpItem: Record = { + public static readonly disableProfileValildationQpItem: Record = { [ProfileManagement.AuthQpLabels.disable]: { - label: vscode.l10n.t("$(workspace-untrusted) Disable Profile Validation"), + label: `$(workspace-untrusted) ${vscode.l10n.t("Disable Profile Validation")}`, description: vscode.l10n.t("Disable validation of server check for profile"), }, }; - public static enableProfileValildationQpItem: Record = { + public static readonly enableProfileValildationQpItem: Record = { [ProfileManagement.AuthQpLabels.enable]: { - label: vscode.l10n.t("$(workspace-trusted) Enable Profile Validation"), + label: `$(workspace-trusted) ${vscode.l10n.t("Enable Profile Validation")}`, description: vscode.l10n.t("Enable validation of server check for profile"), }, }; - public static editProfileQpItems: Record = { + public static readonly editProfileQpItems: Record = { [ProfileManagement.AuthQpLabels.edit]: { - label: vscode.l10n.t("$(pencil) Edit Profile"), + label: `$(pencil) ${vscode.l10n.t("Edit Profile")}`, description: vscode.l10n.t("Update profile connection information"), }, }; - public static hideProfileQpItems: Record = { + public static readonly hideProfileQpItems: Record = { [ProfileManagement.AuthQpLabels.hide]: { - label: vscode.l10n.t("$(eye-closed) Hide Profile"), + label: `$(eye-closed) ${vscode.l10n.t("Hide Profile")}`, description: vscode.l10n.t("Hide profile name from tree view"), }, }; - public static switchAuthenticationQpItems: Record = { + public static readonly switchAuthenticationQpItems: Record = { [ProfileManagement.AuthQpLabels.switch]: { - label: vscode.l10n.t("$(key) Change the Authentication Method"), + label: `$(key) ${vscode.l10n.t("Change the Authentication Method")}`, description: vscode.l10n.t("Change the authentication method"), }, }; - public static tokenAuthLoginQpItem: Record = { + public static readonly tokenAuthLoginQpItem: Record = { [ProfileManagement.AuthQpLabels.login]: { - label: vscode.l10n.t("$(arrow-right) Log in to authentication service"), + label: `$(arrow-right) ${vscode.l10n.t("Log in to authentication service")}`, description: vscode.l10n.t("Log in to obtain a new token value"), }, }; - public static tokenAuthLogoutQpItem: Record = { + public static readonly tokenAuthLogoutQpItem: Record = { [ProfileManagement.AuthQpLabels.logout]: { - label: vscode.l10n.t("$(arrow-left) Log out of authentication service"), + label: `$(arrow-left) ${vscode.l10n.t("Log out of authentication service")}`, description: vscode.l10n.t("Log out to invalidate and remove stored token value"), }, }; diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts b/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts index ab8919fdd8..6b469cd61e 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts @@ -1254,7 +1254,7 @@ export class DatasetActions { } ZoweLogger.info(`Refreshing data set ${label}`); - const statusMsg = Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Fetching data set...")); + const statusMsg = Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Fetching data set...")}`); await DatasetFSProvider.instance.fetchDatasetAtUri(node.resourceUri, { editor: vscode.window.visibleTextEditors.find((v) => v.document.uri.path === node.resourceUri.path), }); diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetFSProvider.ts b/packages/zowe-explorer/src/trees/dataset/DatasetFSProvider.ts index bf6ddc1455..fc9512b336 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetFSProvider.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetFSProvider.ts @@ -427,7 +427,7 @@ export class DatasetFSProvider extends BaseProvider implements vscode.FileSystem } private async uploadEntry(parent: DirEntry, entry: DsEntry, content: Uint8Array, forceUpload?: boolean): Promise { - const statusMsg = Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Saving data set...")); + const statusMsg = Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Saving data set...")}`); let resp: IZosFilesResponse; try { const mvsApi = ZoweExplorerApiRegister.getMvsApi(entry.metadata.profile); diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts b/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts index 8a7a60d428..309aa722c2 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts @@ -53,7 +53,7 @@ export class DatasetInit { ); context.subscriptions.push( vscode.commands.registerCommand("zowe.ds.refreshNode", async (node, nodeList) => { - const statusMsg = Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Pulling from Mainframe...")); + const statusMsg = Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Pulling from Mainframe...")}`); let selectedNodes = SharedUtils.getSelectedNodeList(node, nodeList); selectedNodes = selectedNodes.filter((element) => SharedContext.isDs(element) || SharedContext.isDsMember(element)); for (const item of selectedNodes) { diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts b/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts index b99db6fd30..2369002022 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts @@ -52,9 +52,9 @@ import { DataSetTemplates } from "./DatasetTemplates"; */ export class DatasetTree extends ZoweTreeProvider implements Types.IZoweDatasetTreeType { private static readonly persistenceSchema: PersistenceSchemaEnum = PersistenceSchemaEnum.Dataset; - private static readonly defaultDialogText: string = vscode.l10n.t( - "$(plus) Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)" - ); + private static readonly defaultDialogText: string = `$(plus) ${vscode.l10n.t( + "Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)" + )}`; public mFavoriteSession: ZoweDatasetNode; public mSessionNodes: IZoweDatasetTreeNode[] = []; @@ -1319,7 +1319,7 @@ export class DatasetTree extends ZoweTreeProvider implemen return; } - if (selection.label === vscode.l10n.t("$(fold) Sort Direction")) { + if (selection.label === DatasetUtils.DATASET_SORT_OPTS[4]) { // Update sort direction (if a new one was provided) const dir = await Gui.showQuickPick(Constants.SORT_DIRS, { placeHolder: vscode.l10n.t("Select a sorting direction"), @@ -1343,11 +1343,11 @@ export class DatasetTree extends ZoweTreeProvider implemen // Update sort for node based on selections this.updateSortForNode(node, { ...sortOpts, method: sortMethod }, isSession); Gui.setStatusBarMessage( - vscode.l10n.t({ - message: "$(check) Sorting updated for {0}", + `$(check) ${vscode.l10n.t({ + message: "Sorting updated for {0}", args: [node.label as string], comment: ["Node label"], - }), + })}`, Constants.MS_PER_SEC * 4 ); } @@ -1436,7 +1436,9 @@ export class DatasetTree extends ZoweTreeProvider implemen args: [node.label as string], comment: ["Node label"], }); - const clearFilter = isSession ? vscode.l10n.t("$(clear-all) Clear filter for profile") : vscode.l10n.t("$(clear-all) Clear filter for PDS"); + const clearFilter = isSession + ? `$(clear-all) ${vscode.l10n.t("Clear filter for profile")}` + : `$(clear-all) ${vscode.l10n.t("Clear filter for PDS")}`; const selection = ( await Gui.showQuickPick( [...DatasetUtils.DATASET_FILTER_OPTS.map((sortOpt, i) => (node.filter?.method === i ? `${sortOpt} $(check)` : sortOpt)), clearFilter], @@ -1457,11 +1459,11 @@ export class DatasetTree extends ZoweTreeProvider implemen if (selection === clearFilter) { this.updateFilterForNode(node, null, isSession); Gui.setStatusBarMessage( - vscode.l10n.t({ - message: "$(check) Filter cleared for {0}", + `$(check) ${vscode.l10n.t({ + message: "Filter cleared for {0}", args: [node.label as string], comment: ["Node label"], - }), + })}`, Constants.MS_PER_SEC * 4 ); } @@ -1497,11 +1499,11 @@ export class DatasetTree extends ZoweTreeProvider implemen isSession ); Gui.setStatusBarMessage( - vscode.l10n.t({ - message: "$(check) Filter updated for {0}", + `$(check) ${vscode.l10n.t({ + message: "Filter updated for {0}", args: [node.label as string], comment: ["Node label"], - }), + })}`, Constants.MS_PER_SEC * 4 ); } diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts b/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts index 73444e3628..7c04fefab7 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts @@ -15,15 +15,16 @@ import { Constants } from "../../configuration/Constants"; import { ZoweLogger } from "../../tools/ZoweLogger"; export class DatasetUtils { - public static DATASET_SORT_OPTS = [ - vscode.l10n.t("$(case-sensitive) Name (default)"), - vscode.l10n.t("$(calendar) Date Created"), - vscode.l10n.t("$(calendar) Date Modified"), - vscode.l10n.t("$(account) User ID"), - vscode.l10n.t("$(fold) Sort Direction"), + public static readonly DATASET_SORT_OPTS = [ + `$(case-sensitive) ${vscode.l10n.t("Name (default)")}`, + `$(calendar) ${vscode.l10n.t("Date Created")}`, + `$(calendar) ${vscode.l10n.t("Date Modified")}`, + `$(account) ${vscode.l10n.t("User ID")}`, + `$(fold) ${vscode.l10n.t("Sort Direction")}`, ]; - public static DATASET_FILTER_OPTS = [vscode.l10n.t("$(calendar) Date Modified"), vscode.l10n.t("$(account) User ID")]; + // eslint-disable-next-line no-magic-numbers + public static readonly DATASET_FILTER_OPTS = [this.DATASET_SORT_OPTS[2], this.DATASET_SORT_OPTS[3]]; public static getProfileAndDataSetName(node: Types.IZoweNodeType): { profileName: string; diff --git a/packages/zowe-explorer/src/trees/job/JobActions.ts b/packages/zowe-explorer/src/trees/job/JobActions.ts index 920f21d80d..7f01135a1d 100644 --- a/packages/zowe-explorer/src/trees/job/JobActions.ts +++ b/packages/zowe-explorer/src/trees/job/JobActions.ts @@ -237,11 +237,11 @@ export class JobActions { */ public static async spoolFilePollEvent(doc: vscode.TextDocument): Promise { const statusMsg = Gui.setStatusBarMessage( - vscode.l10n.t({ - message: `$(sync~spin) Polling: {0}...`, + `$(sync~spin) ${vscode.l10n.t({ + message: `Polling: {0}...`, args: [doc.fileName], comment: ["Document file name"], - }) + })}` ); await JobFSProvider.instance.fetchSpoolAtUri(doc.uri); statusMsg.dispose(); @@ -499,7 +499,8 @@ export class JobActions { if (selection == null) { return; } - if (selection.label === vscode.l10n.t("$(fold) Sort Direction")) { + // eslint-disable-next-line no-magic-numbers + if (selection.label === JobUtils.JOB_SORT_OPTS[5]) { const dir = await Gui.showQuickPick(Constants.SORT_DIRS, { placeHolder: vscode.l10n.t("Select a sorting direction"), }); @@ -516,11 +517,11 @@ export class JobActions { session.sort.method = JobUtils.JOB_SORT_OPTS.indexOf(selection.label.replace(" $(check)", "")); jobsProvider.sortBy(session); Gui.setStatusBarMessage( - vscode.l10n.t({ - message: "$(check) Sorting updated for {0}", + `$(check) ${vscode.l10n.t({ + message: "Sorting updated for {0}", args: [session.label as string], comment: ["Session label"], - }), + })}`, Constants.MS_PER_SEC * 4 ); } diff --git a/packages/zowe-explorer/src/trees/job/JobFSProvider.ts b/packages/zowe-explorer/src/trees/job/JobFSProvider.ts index 3228c65f14..cb998c0924 100644 --- a/packages/zowe-explorer/src/trees/job/JobFSProvider.ts +++ b/packages/zowe-explorer/src/trees/job/JobFSProvider.ts @@ -56,8 +56,11 @@ export class JobFSProvider extends BaseProvider implements vscode.FileSystemProv if (!SharedContext.isSpoolFile(node)) { return; } - const statusBarMsg = Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Fetching spool file...")); - await JobFSProvider.instance.fetchSpoolAtUri(node.resourceUri); + const statusBarMsg = Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Fetching spool file...")}`); + await JobFSProvider.instance.fetchSpoolAtUri( + node.resourceUri, + vscode.window.visibleTextEditors.find((v) => v.document.uri.path === node.resourceUri.path) + ); statusBarMsg.dispose(); } @@ -202,6 +205,8 @@ export class JobFSProvider extends BaseProvider implements vscode.FileSystemProv this._fireSoon({ type: vscode.FileChangeType.Changed, uri }); spoolEntry.data = bufBuilder.read() ?? new Uint8Array(); + spoolEntry.mtime = Date.now(); + spoolEntry.size = spoolEntry.data.byteLength; if (editor) { await this._updateResourceInEditor(uri); } diff --git a/packages/zowe-explorer/src/trees/job/JobInit.ts b/packages/zowe-explorer/src/trees/job/JobInit.ts index 2f4516ba08..93a13ad490 100644 --- a/packages/zowe-explorer/src/trees/job/JobInit.ts +++ b/packages/zowe-explorer/src/trees/job/JobInit.ts @@ -72,7 +72,7 @@ export class JobInit { ); context.subscriptions.push( vscode.commands.registerCommand("zowe.jobs.refreshSpool", async (node) => { - const statusMsg = Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Pulling from Mainframe...")); + const statusMsg = Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Pulling from Mainframe...")}`); await JobFSProvider.refreshSpool(node); statusMsg.dispose(); }) diff --git a/packages/zowe-explorer/src/trees/job/JobTree.ts b/packages/zowe-explorer/src/trees/job/JobTree.ts index 0262ab49ec..3fa17e221f 100644 --- a/packages/zowe-explorer/src/trees/job/JobTree.ts +++ b/packages/zowe-explorer/src/trees/job/JobTree.ts @@ -39,7 +39,7 @@ export class JobTree extends ZoweTreeProvider implements Types public static readonly Status = "Status: "; public static readonly defaultDialogText: string = vscode.l10n.t("Create new..."); private static readonly persistenceSchema: PersistenceSchemaEnum = PersistenceSchemaEnum.Job; - private static readonly submitJobQueryLabel = vscode.l10n.t("$(check) Submit this query"); + private static readonly submitJobQueryLabel = `$(check) ${vscode.l10n.t("Submit this query")}`; private static readonly chooseJobStatusLabel = "Job Status"; public dragMimeTypes: string[] = ["application/vnd.code.tree.zowe.jobs.explorer"]; public dropMimeTypes: string[] = ["application/vnd.code.tree.zowe.jobs.explorer"]; @@ -74,11 +74,11 @@ export class JobTree extends ZoweTreeProvider implements Types public mFavorites: IZoweJobTreeNode[] = []; public lastOpened: Types.ZoweNodeInteraction = {}; public searchByQuery = new FilterItem({ - text: vscode.l10n.t("$(plus) Create job search filter"), + text: `$(plus) ${vscode.l10n.t("Create job search filter")}`, menuType: Definitions.JobPickerTypes.QuerySearch, }); public searchById = new FilterItem({ - text: vscode.l10n.t("$(search) Search by job ID"), + text: `$(search) ${vscode.l10n.t("Search by job ID")}`, menuType: Definitions.JobPickerTypes.IdSearch, }); private treeView: vscode.TreeView; @@ -1052,11 +1052,11 @@ export class JobTree extends ZoweTreeProvider implements Types msInterval: pollInterval, request: async () => { const statusMsg = Gui.setStatusBarMessage( - vscode.l10n.t({ - message: `$(sync~spin) Polling: {0}...`, + `$(sync~spin) ${vscode.l10n.t({ + message: "Polling: {0}...", args: [path.posix.basename(node.resourceUri.path)], comment: ["Unique Spool name"], - }), + })}`, Constants.STATUS_BAR_TIMEOUT_MS ); await JobFSProvider.instance.fetchSpoolAtUri(node.resourceUri); @@ -1110,16 +1110,16 @@ export class JobTree extends ZoweTreeProvider implements Types const filterMethod = JobUtils.JOB_FILTER_OPTS.indexOf(selection); const userDismissed = filterMethod < 0; - const clearFilterOpt = vscode.l10n.t("$(clear-all) Clear filter for profile"); + const clearFilterOpt = `$(clear-all) ${vscode.l10n.t("Clear filter for profile")}`; if (userDismissed || selection === clearFilterOpt) { if (selection === clearFilterOpt) { this.updateFilterForJob(job, null); Gui.setStatusBarMessage( - vscode.l10n.t({ - message: "$(check) Filter cleared for {0}", + `$(check) ${vscode.l10n.t({ + message: "Filter cleared for {0}", args: [job.label as string], comment: ["Job label"], - }), + })}`, Constants.MS_PER_SEC * 4 ); } @@ -1146,11 +1146,11 @@ export class JobTree extends ZoweTreeProvider implements Types SharedTreeProviders.job.refresh(); this.updateFilterForJob(job, query); Gui.setStatusBarMessage( - vscode.l10n.t({ - message: "$(check) Filter updated for {0}", + `$(check) ${vscode.l10n.t({ + message: "Filter updated for {0}", args: [job.label as string], comment: ["Job label"], - }), + })}`, Constants.MS_PER_SEC * 4 ); }); diff --git a/packages/zowe-explorer/src/trees/job/JobUtils.ts b/packages/zowe-explorer/src/trees/job/JobUtils.ts index f0bfb007bd..02611e2db5 100644 --- a/packages/zowe-explorer/src/trees/job/JobUtils.ts +++ b/packages/zowe-explorer/src/trees/job/JobUtils.ts @@ -13,16 +13,16 @@ import * as vscode from "vscode"; import * as zosjobs from "@zowe/zos-jobs-for-zowe-sdk"; import { Sorting } from "@zowe/zowe-explorer-api"; export class JobUtils { - public static JOB_SORT_OPTS = [ - vscode.l10n.t("$(list-ordered) Job ID (default)"), - vscode.l10n.t("$(calendar) Date Submitted"), - vscode.l10n.t("$(calendar) Date Completed"), - vscode.l10n.t("$(case-sensitive) Job Name"), - vscode.l10n.t("$(symbol-numeric) Return Code"), - vscode.l10n.t("$(fold) Sort Direction"), + public static readonly JOB_SORT_OPTS = [ + `$(list-ordered) ${vscode.l10n.t("Job ID (default)")}`, + `$(calendar) ${vscode.l10n.t("Date Submitted")}`, + `$(calendar) ${vscode.l10n.t("Date Completed")}`, + `$(case-sensitive) ${vscode.l10n.t("Job Name")}`, + `$(symbol-numeric) ${vscode.l10n.t("Return Code")}`, + `$(fold) ${vscode.l10n.t("Sort Direction")}`, ]; - public static JOB_SORT_KEYS: Record = { + public static readonly JOB_SORT_KEYS: Record = { [Sorting.JobSortOpts.Id]: "jobid", [Sorting.JobSortOpts.DateSubmitted]: "exec-submitted", [Sorting.JobSortOpts.DateCompleted]: "exec-ended", @@ -30,5 +30,5 @@ export class JobUtils { [Sorting.JobSortOpts.ReturnCode]: "retcode", }; - public static JOB_FILTER_OPTS = [vscode.l10n.t("Go to Local Filtering"), vscode.l10n.t("$(clear-all) Clear filter for profile")]; + public static readonly JOB_FILTER_OPTS = [vscode.l10n.t("Go to Local Filtering"), `$(clear-all) ${vscode.l10n.t("Clear filter for profile")}`]; } diff --git a/packages/zowe-explorer/src/trees/shared/SharedHistoryView.ts b/packages/zowe-explorer/src/trees/shared/SharedHistoryView.ts index c1ac2382a2..1133cbb676 100644 --- a/packages/zowe-explorer/src/trees/shared/SharedHistoryView.ts +++ b/packages/zowe-explorer/src/trees/shared/SharedHistoryView.ts @@ -17,6 +17,7 @@ import { ZoweLogger } from "../../tools/ZoweLogger"; import { JobTree } from "../job/JobTree"; import { Constants } from "../../configuration/Constants"; import { ZoweLocalStorage } from "../../tools/ZoweLocalStorage"; +import * as fs from "fs"; export class SharedHistoryView extends WebView { private treeProviders: Definitions.IZoweProviders; @@ -62,6 +63,23 @@ export class SharedHistoryView extends WebView { case "clear-all": await this.clearAll(message); break; + case "GET_LOCALIZATION": { + const filePath = vscode.l10n.uri?.fsPath + ""; + fs.readFile(filePath, "utf8", (err, data) => { + if (err) { + // File doesn't exist, fallback to English strings + return; + } + if (!this.panel) { + return; + } + this.panel.webview.postMessage({ + command: "GET_LOCALIZATION", + contents: data, + }); + }); + break; + } default: break; } diff --git a/packages/zowe-explorer/src/trees/shared/SharedUtils.ts b/packages/zowe-explorer/src/trees/shared/SharedUtils.ts index 9892a229fd..0288f84d91 100644 --- a/packages/zowe-explorer/src/trees/shared/SharedUtils.ts +++ b/packages/zowe-explorer/src/trees/shared/SharedUtils.ts @@ -277,7 +277,7 @@ export class SharedUtils { break; default: if (response != null) { - encoding = { kind: "other", codepage: response }; + encoding = response === "binary" ? { kind: "binary" } : { kind: "other", codepage: response }; } break; } diff --git a/packages/zowe-explorer/src/trees/uss/USSAttributeView.ts b/packages/zowe-explorer/src/trees/uss/USSAttributeView.ts index 8c84c610e1..72f2a5084c 100644 --- a/packages/zowe-explorer/src/trees/uss/USSAttributeView.ts +++ b/packages/zowe-explorer/src/trees/uss/USSAttributeView.ts @@ -13,6 +13,8 @@ import { Types, Gui, MainframeInteraction, IZoweUSSTreeNode, WebView } from "@zo import { Disposable, ExtensionContext } from "vscode"; import { ZoweExplorerApiRegister } from "../../extending/ZoweExplorerApiRegister"; import { SharedContext } from "../shared/SharedContext"; +import * as vscode from "vscode"; +import * as fs from "fs"; export class USSAttributeView extends WebView { private treeProvider: Types.IZoweUSSTreeType; @@ -71,6 +73,23 @@ export class USSAttributeView extends WebView { case "update-attributes": await this.updateAttributes(message); break; + case "GET_LOCALIZATION": { + const filePath = vscode.l10n.uri?.fsPath + ""; + fs.readFile(filePath, "utf8", (err, data) => { + if (err) { + // File doesn't exist, fallback to English strings + return; + } + if (!this.panel) { + return; + } + this.panel.webview.postMessage({ + command: "GET_LOCALIZATION", + contents: data, + }); + }); + break; + } default: break; } diff --git a/packages/zowe-explorer/src/trees/uss/USSInit.ts b/packages/zowe-explorer/src/trees/uss/USSInit.ts index 91bba48005..ac38f9273e 100644 --- a/packages/zowe-explorer/src/trees/uss/USSInit.ts +++ b/packages/zowe-explorer/src/trees/uss/USSInit.ts @@ -53,7 +53,7 @@ export class USSInit { ); context.subscriptions.push( vscode.commands.registerCommand("zowe.uss.refreshUSS", async (node, nodeList) => { - const statusMsg = Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Pulling from Mainframe...")); + const statusMsg = Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Pulling from Mainframe...")}`); let selectedNodes = SharedUtils.getSelectedNodeList(node, nodeList) as IZoweUSSTreeNode[]; selectedNodes = selectedNodes.filter((x) => SharedContext.isDocument(x)); for (const item of selectedNodes) { @@ -64,7 +64,7 @@ export class USSInit { if (!(await FsAbstractUtils.confirmForUnsavedDoc(node.resourceUri))) { return; } - const statusMsg2 = Gui.setStatusBarMessage("$(sync~spin) Fetching USS file..."); + const statusMsg2 = Gui.setStatusBarMessage(`$(sync~spin) ${"Fetching USS file..."}`); // need to pull content for file and apply to FS entry await UssFSProvider.instance.fetchFileAtUri(item.resourceUri, { editor: vscode.window.visibleTextEditors.find((v) => v.document.uri.path === item.resourceUri.path), diff --git a/packages/zowe-explorer/src/trees/uss/USSTree.ts b/packages/zowe-explorer/src/trees/uss/USSTree.ts index f0098ac766..3e574829fc 100644 --- a/packages/zowe-explorer/src/trees/uss/USSTree.ts +++ b/packages/zowe-explorer/src/trees/uss/USSTree.ts @@ -45,7 +45,7 @@ import { AuthUtils } from "../../utils/AuthUtils"; * @implements {vscode.TreeDataProvider} */ export class USSTree extends ZoweTreeProvider implements Types.IZoweUSSTreeType { - public static readonly defaultDialogText: string = vscode.l10n.t("$(plus) Create a new filter"); + public static readonly defaultDialogText: string = `$(plus) ${vscode.l10n.t("Create a new filter")}`; private static readonly persistenceSchema: PersistenceSchemaEnum = PersistenceSchemaEnum.USS; public mFavoriteSession: ZoweUSSNode; public mSessionNodes: IZoweUSSTreeNode[] = []; @@ -207,7 +207,7 @@ export class USSTree extends ZoweTreeProvider implements Types } } - const movingMsg = Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Moving USS files...")); + const movingMsg = Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Moving USS files...")}`); const parentsToUpdate = new Set(); for (const item of droppedItems.value) { diff --git a/packages/zowe-explorer/src/trees/uss/UssFSProvider.ts b/packages/zowe-explorer/src/trees/uss/UssFSProvider.ts index d2a830f85d..6938072482 100644 --- a/packages/zowe-explorer/src/trees/uss/UssFSProvider.ts +++ b/packages/zowe-explorer/src/trees/uss/UssFSProvider.ts @@ -260,6 +260,7 @@ export class UssFSProvider extends BaseProvider implements vscode.FileSystemProv const bufBuilder = new BufferBuilder(); const filePath = uri.path.substring(uriInfo.slashAfterProfilePos); const metadata = file.metadata; + await this.autoDetectEncoding(file as UssFile); const profileEncoding = file.encoding ? null : file.metadata.profile.profile?.encoding; const resp = await ZoweExplorerApiRegister.getUssApi(metadata.profile).getContents(filePath, { binary: file.encoding?.kind === "binary", @@ -268,7 +269,6 @@ export class UssFSProvider extends BaseProvider implements vscode.FileSystemProv returnEtag: true, stream: bufBuilder, }); - await this.autoDetectEncoding(file as UssFile); const data: Uint8Array = bufBuilder.read() ?? new Uint8Array(); if (options?.isConflict) { @@ -375,7 +375,7 @@ export class UssFSProvider extends BaseProvider implements vscode.FileSystemProv // or if the entry does not exist and the new contents are empty (new placeholder entry) options?.noStatusMsg || (!entry && content.byteLength === 0) ? new vscode.Disposable(() => {}) - : Gui.setStatusBarMessage(vscode.l10n.t("$(sync~spin) Saving USS file...")); + : Gui.setStatusBarMessage(`$(sync~spin) ${vscode.l10n.t("Saving USS file...")}`); let resp: IZosFilesResponse; try { diff --git a/packages/zowe-explorer/src/utils/CertificateWizard.ts b/packages/zowe-explorer/src/utils/CertificateWizard.ts index ed550267d7..a1de63292e 100644 --- a/packages/zowe-explorer/src/utils/CertificateWizard.ts +++ b/packages/zowe-explorer/src/utils/CertificateWizard.ts @@ -12,6 +12,7 @@ import { Gui, WebView } from "@zowe/zowe-explorer-api"; import * as vscode from "vscode"; import { ZoweLogger } from "../tools/ZoweLogger"; +import * as fs from "fs"; export type CertWizardOpts = { cert?: string; @@ -115,6 +116,23 @@ export class CertificateWizard extends WebView { }); ZoweLogger.trace(userDismissed); break; + case "GET_LOCALIZATION": { + const filePath = vscode.l10n.uri?.fsPath + ""; + fs.readFile(filePath, "utf8", (err, data) => { + if (err) { + // File doesn't exist, fallback to English strings + return; + } + if (!this.panel) { + return; + } + this.panel.webview.postMessage({ + command: "GET_LOCALIZATION", + contents: data, + }); + }); + break; + } default: break; } diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 9e1a87b569..a7369eaef5 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -21,6 +21,11 @@ import { ZoweLocalStorage } from "../tools/ZoweLocalStorage"; import { Definitions } from "../configuration/Definitions"; import { SharedTreeProviders } from "../trees/shared/SharedTreeProviders"; +export enum ProfilesConvertStatus { + ConvertSelected, + CreateNewSelected, +} + export class ProfilesUtils { public static PROFILE_SECURITY: string | boolean = Constants.ZOWE_CLI_SCM; @@ -354,32 +359,28 @@ export class ProfilesUtils { } ` ); ZoweLogger.debug(`Summary of team configuration files considered for Zowe Explorer: ${JSON.stringify(layerSummary)}`); - } else { - // For users upgrading from v1 to v3, we must force a "Reload Window" operation to make sure that - // VS Code registers our updated TreeView IDs. Otherwise, VS Code's "Refresh Extensions" option will break v3 init. - const ussPersistentSettings = vscode.workspace.getConfiguration("Zowe-USS-Persistent"); - const upgradingFromV1 = ZoweLocalStorage.getValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); - if (ussPersistentSettings != null && upgradingFromV1 == null && imperative.ProfileInfo.onlyV1ProfilesExist) { - await ZoweLocalStorage.setValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, Definitions.V1MigrationStatus.JustMigrated); - await vscode.commands.executeCommand("workbench.action.reloadWindow"); - } - if (imperative.ProfileInfo.onlyV1ProfilesExist) { - await this.v1ProfileOptions(); - } } } public static async handleV1MigrationStatus(): Promise { - const migrationStatus = ZoweLocalStorage.getValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); - if (migrationStatus == null) { - // If there is no v1 migration status, return. + // For users upgrading from v1 to v3, we must force a "Reload Window" operation to make sure that + // VS Code registers our updated TreeView IDs. Otherwise, VS Code's "Refresh Extensions" option will break v3 init. + const ussPersistentSettings = vscode.workspace.getConfiguration("Zowe-USS-Persistent"); + const upgradingFromV1 = ZoweLocalStorage.getValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS); + const mProfileInfo = await ProfilesUtils.getProfileInfo(); + if (ussPersistentSettings != null && upgradingFromV1 == null && imperative.ProfileInfo.onlyV1ProfilesExist) { + await ZoweLocalStorage.setValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, Definitions.V1MigrationStatus.JustMigrated); + await vscode.commands.executeCommand("workbench.action.reloadWindow"); + } + + if (upgradingFromV1 == null || mProfileInfo.getTeamConfig().exists || !imperative.ProfileInfo.onlyV1ProfilesExist) { return; } + const userSelection = await this.v1ProfileOptions(); // Open the "Add Session" quick pick if the user selected "Create New" in the v1 migration prompt. - if (migrationStatus === Definitions.V1MigrationStatus.CreateConfigSelected) { - vscode.commands.executeCommand("zowe.ds.addSession", SharedTreeProviders.ds); - await ZoweLocalStorage.setValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, Definitions.V1MigrationStatus.JustMigrated); + if (userSelection === ProfilesConvertStatus.CreateNewSelected) { + await vscode.commands.executeCommand("zowe.ds.addSession", SharedTreeProviders.ds); } } @@ -555,7 +556,7 @@ export class ProfilesUtils { } } - private static async v1ProfileOptions(): Promise { + private static async v1ProfileOptions(): Promise { const v1ProfileErrorMsg = vscode.l10n.t( // eslint-disable-next-line max-len "Zowe V1 profiles in use.\nZowe Explorer no longer supports V1 profiles. Choose to convert existing profiles to a team configuration or create new profiles." @@ -565,20 +566,17 @@ export class ProfilesUtils { const createButton = vscode.l10n.t("Create New"); const selection = await Gui.infoMessage(v1ProfileErrorMsg, { items: [convertButton, createButton], vsCodeOpts: { modal: true } }); switch (selection) { - case createButton: { + case createButton: ZoweLogger.info("Create new team configuration chosen."); - await ZoweLocalStorage.setValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, Definitions.V1MigrationStatus.CreateConfigSelected); - break; - } - case convertButton: { + await ZoweLocalStorage.setValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, undefined); + return ProfilesConvertStatus.CreateNewSelected; + case convertButton: ZoweLogger.info("Convert v1 profiles to team configuration chosen."); await this.convertV1Profs(); - break; - } - default: { - void Gui.infoMessage(vscode.l10n.t("Operation cancelled")); - break; - } + await ZoweLocalStorage.setValue(Definitions.LocalStorageKey.V1_MIGRATION_STATUS, undefined); + return ProfilesConvertStatus.ConvertSelected; + default: + return undefined; } } diff --git a/packages/zowe-explorer/src/webviews/src/certificate-wizard/App.tsx b/packages/zowe-explorer/src/webviews/src/certificate-wizard/App.tsx index 6eb130c061..0cd19f345f 100644 --- a/packages/zowe-explorer/src/webviews/src/certificate-wizard/App.tsx +++ b/packages/zowe-explorer/src/webviews/src/certificate-wizard/App.tsx @@ -1,12 +1,6 @@ import { useEffect, useState } from "preact/hooks"; -import { - VSCodeButton, - //VSCodeCheckbox, - VSCodeDataGrid, - VSCodeDataGridCell, - VSCodeDataGridRow, - VSCodeDivider, -} from "@vscode/webview-ui-toolkit/react"; +import { VSCodeButton, VSCodeDataGrid, VSCodeDataGridCell, VSCodeDataGridRow, VSCodeDivider } from "@vscode/webview-ui-toolkit/react"; +import * as l10n from "@vscode/l10n"; import { isSecureOrigin } from "../utils"; const vscodeApi = acquireVsCodeApi(); @@ -14,6 +8,7 @@ const vscodeApi = acquireVsCodeApi(); export function App() { const [certPath, setCertPath] = useState(""); const [certKeyPath, setCertKeyPath] = useState(""); + const [localizationState, setLocalizationState] = useState(null); useEffect(() => { window.addEventListener("message", (event) => { @@ -21,7 +16,13 @@ export function App() { if (!isSecureOrigin(event.origin)) { return; } - + if (event.data.command === "GET_LOCALIZATION") { + const { contents } = event.data; + l10n.config({ + contents: contents, + }); + setLocalizationState(contents); + } if (!event.data.opts || Object.keys(event.data.opts).length === 0) { return; } @@ -35,51 +36,52 @@ export function App() { } }); + vscodeApi.postMessage({ command: "GET_LOCALIZATION" }); vscodeApi.postMessage({ command: "ready" }); - }, []); + }, [localizationState]); return (
-

Log in to Authentication Service

+

{l10n.t("Log in to Authentication Service")}

-

Select a certificate and certificate key in PEM format:

+

{l10n.t("Select a certificate and certificate key in PEM format:")}

- Value + {l10n.t("Value")} - Actions + {l10n.t("Actions")} - Certificate File + {l10n.t("Certificate File")} {certPath} vscodeApi.postMessage({ command: "promptCert" })}> - Browse + {l10n.t("Browse")} - Certificate Key File + {l10n.t("Certificate Key File")} {certKeyPath} vscodeApi.postMessage({ command: "promptCertKey" })}> - Browse + {l10n.t("Browse")} @@ -91,7 +93,7 @@ export function App() { vscodeApi.postMessage({ command: "submitted" }); }} > - Submit + {l10n.t("Submit")} - Cancel + {l10n.t("Cancel")}
diff --git a/packages/zowe-explorer/src/webviews/src/edit-attributes/App.tsx b/packages/zowe-explorer/src/webviews/src/edit-attributes/App.tsx index 04224f6836..8388d4357e 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-attributes/App.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-attributes/App.tsx @@ -11,6 +11,7 @@ import { VSCodeTextField, } from "@vscode/webview-ui-toolkit/react"; import { isEqual } from "es-toolkit"; +import * as l10n from "@vscode/l10n"; import { isSecureOrigin } from "../utils"; const vscodeApi = acquireVsCodeApi(); @@ -26,6 +27,18 @@ export function App() { const [isUpdating, setIsUpdating] = useState(false); const [timestamp, setTimestamp] = useState(); + const localizedPermissionTypes = [ + { key: "read", localized: l10n.t("Read") }, + { key: "write", localized: l10n.t("Write") }, + { key: "execute", localized: l10n.t("Execute") }, + ]; + + const localizedPermissionGroups = [ + { key: "user", localized: l10n.t("User") }, + { key: "group", localized: l10n.t("Group") }, + { key: "all", localized: l10n.t("All") }, + ]; + const updateButtons = (newAttributes: FileAttributes) => setAllowUpdate(!isEqual(attributes.initial, newAttributes)); const updateFileAttributes = (key: keyof FileAttributes, value: unknown) => { @@ -66,11 +79,17 @@ export function App() { if (!isSecureOrigin(event.origin)) { return; } - if (!event.data) { return; } + if (event.data.command === "GET_LOCALIZATION") { + const { contents } = event.data; + l10n.config({ + contents: contents, + }); + } + if ("readonly" in event.data && event.data.readonly) { setReadonly(true); } @@ -125,6 +144,7 @@ export function App() { }); // signal to extension that webview is ready for data; prevents race condition during initialization vscodeApi.postMessage({ command: "ready" }); + vscodeApi.postMessage({ command: "GET_LOCALIZATION" }); }, []); const updatePerm = (group: keyof FilePermissions, perm: keyof PermissionSet, value: boolean) => { @@ -146,11 +166,16 @@ export function App() { return attributes.current ? (
-

File properties

+

{l10n.t("File properties")}

- {timestamp &&

Last refreshed: {timestamp.toLocaleString(navigator.language)}

} + {timestamp && ( +

+ {l10n.t("Last refreshed:")} {timestamp.toLocaleString(navigator.language)} +

+ )} vscodeApi.postMessage({ command: "refresh" })}> - Refresh + + {l10n.t("Refresh")}
@@ -165,7 +190,7 @@ export function App() { value={attributes.current.tag} onInput={(e: any) => updateFileAttributes("tag", e.target.value)} > - Tag + {l10n.t("Tag")}
)} @@ -173,41 +198,39 @@ export function App() {
updateFileAttributes("owner", e.target.value)}> - Owner + {l10n.t("Owner")} updateFileAttributes("group", e.target.value)} value={attributes.current.group} > - Group + {l10n.t("Group")}
{attributes.current.perms ? ( - {PERMISSION_TYPES.map((perm, i) => { - const capitalizedPerm = perm.charAt(0).toUpperCase() + perm.slice(1); + {localizedPermissionTypes.map(({ key, localized }, i) => { return ( - - {capitalizedPerm} + + {localized} ); })} - {PERMISSION_GROUPS.map((group) => { - const capitalizedGroup = group.charAt(0).toUpperCase() + group.slice(1); + {localizedPermissionGroups.map(({ key, localized }) => { return ( - + - {capitalizedGroup} + {localized} {PERMISSION_TYPES.map((perm, i) => ( - + updatePerm(group, perm, e.target.checked)} + checked={attributes.current!.perms[key as keyof FilePermissions][perm]} + onChange={(e: any) => updatePerm(key as keyof FilePermissions, perm, e.target.checked)} /> ))} @@ -223,13 +246,13 @@ export function App() { applyAttributes(); }} > - Apply changes + {l10n.t("Apply changes")} {isUpdating && }
{readonly && ( - The API does not support updating attributes for this {attributes.initial?.directory ?? false ? "directory" : "file"}. + {l10n.t("The API does not support updating attributes for this")} {attributes.initial?.directory ?? false ? "directory" : "file"}. )}
@@ -238,11 +261,11 @@ export function App() { ) : (
-

File properties

+

{l10n.t("File properties")}

-

Waiting for data from extension...

+

{l10n.t("Waiting for data from extension...")}

); } diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/App.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/App.tsx index 5929236632..859cfa36a3 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/App.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/App.tsx @@ -16,24 +16,34 @@ import { isSecureOrigin } from "../utils"; import PersistentDataPanel from "./components/PersistentTable/PersistentDataPanel"; import PersistentVSCodeAPI from "./components/PersistentVSCodeAPI"; import PersistentManagerHeader from "./components/PersistentManagerHeader/PersistentManagerHeader"; +import * as l10n from "@vscode/l10n"; export function App(): JSXInternal.Element { const [timestamp, setTimestamp] = useState(); const [currentTab, setCurrentTab] = useState<{ [key: string]: string }>({}); - useEffect(() => { window.addEventListener("message", (event) => { if (!isSecureOrigin(event.origin)) { return; } + if (!event.data) { + return; + } if ("tab" in event.data) { setCurrentTab(() => ({ tab: event.data.tab, })); } setTimestamp(new Date()); + if (event.data.command === "GET_LOCALIZATION") { + const { contents } = event.data; + l10n.config({ + contents: contents, + }); + } }); PersistentVSCodeAPI.getVSCodeAPI().postMessage({ command: "ready" }); + PersistentVSCodeAPI.getVSCodeAPI().postMessage({ command: "GET_LOCALIZATION" }); }, []); return ( @@ -42,13 +52,13 @@ export function App(): JSXInternal.Element { -

Data Sets

+

{l10n.t("Data Sets")}

-

Unix System Services (USS)

+

{l10n.t("Unix System Services (USS)")}

-

Jobs

+

{l10n.t("Jobs")}

diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentManagerHeader/PersistentManagerHeader.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentManagerHeader/PersistentManagerHeader.tsx index 9020c76f8a..767f73a2b7 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentManagerHeader/PersistentManagerHeader.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentManagerHeader/PersistentManagerHeader.tsx @@ -10,15 +10,22 @@ */ import { JSXInternal } from "preact/src/jsx"; +import * as l10n from "@vscode/l10n"; export default function PersistentManagerHeader({ timestamp }: Readonly<{ timestamp: Readonly }>): JSXInternal.Element { const renderTimestamp = () => { - return timestamp &&

Last refreshed: {timestamp.toLocaleString(navigator.language)}

; + return ( + timestamp && ( +

+ {l10n.t("Last refreshed:")} {timestamp.toLocaleString(navigator.language)} +

+ ) + ); }; return (
-

Manage Persistent Properties

+

{l10n.t("Manage Persistent Properties")}

{renderTimestamp()}
); diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataGridHeaders.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataGridHeaders.tsx index eeb223da29..79400031ee 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataGridHeaders.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataGridHeaders.tsx @@ -12,14 +12,14 @@ import { VSCodeDataGridRow, VSCodeDataGridCell } from "@vscode/webview-ui-toolkit/react"; import { JSXInternal } from "preact/src/jsx"; import { useDataPanelContext } from "../PersistentUtils"; -import * as nls from "@vscode/l10n"; +import * as l10n from "@vscode/l10n"; export default function PersistentDataGridHeaders(): JSXInternal.Element { const { type, selection } = useDataPanelContext(); - const itemText = nls.t("Item"); + const itemText = l10n.t("Item"); const renderSelectHeader = () => { - const deleteText = nls.t("Select"); + const deleteText = l10n.t("Select"); return selection[type] === "search" || selection[type] === "fileHistory" ? ( {deleteText} diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataPanel.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataPanel.tsx index 6757938843..78a41ae7bc 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataPanel.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentDataPanel.tsx @@ -43,7 +43,6 @@ export default function PersistentDataPanel({ type }: Readonly<{ type: Readonly< type, }, }); - const newSelectedItems: { [key: string]: boolean } = { ...selectedItemsMemo.val }; Object.keys(newSelectedItems).forEach((item) => { newSelectedItems[item] = false; @@ -56,13 +55,14 @@ export default function PersistentDataPanel({ type }: Readonly<{ type: Readonly< if (!isSecureOrigin(event.origin)) { return; } + if (event.data.ds && event.data.uss && event.data.jobs) { + setData(event.data); - setData(event.data); - - if ("selection" in event.data) { - setSelection(() => ({ - [type]: event.data.selection[type], - })); + if ("selection" in event.data) { + setSelection(() => ({ + [type]: event.data.selection[type], + })); + } } }); }, []); diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentTableData.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentTableData.tsx index bff46f7772..919d8cf898 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentTableData.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentTable/PersistentTableData.tsx @@ -14,6 +14,7 @@ import { JSXInternal } from "preact/src/jsx"; import { useDataPanelContext } from "../PersistentUtils"; import { useEffect, useState } from "preact/hooks"; import { isEqual } from "es-toolkit"; +import * as l10n from "@vscode/l10n"; export default function PersistentTableData({ persistentProp }: Readonly<{ persistentProp: readonly string[] }>): JSXInternal.Element { const { type, selection, selectedItems } = useDataPanelContext(); @@ -57,7 +58,7 @@ export default function PersistentTableData({ persistentProp }: Readonly<{ persi const renderNoRecordsFound = () => { return ( - No records found + {l10n.t("No records found")} ); }; diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentAddNewHistoryItemButton.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentAddNewHistoryItemButton.tsx index cf9628d450..7f25e39aa4 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentAddNewHistoryItemButton.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentAddNewHistoryItemButton.tsx @@ -13,7 +13,7 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; import { JSXInternal } from "preact/src/jsx"; import { useDataPanelContext } from "../PersistentUtils"; import PersistentVSCodeAPI from "../PersistentVSCodeAPI"; -import * as nls from "@vscode/l10n"; +import * as l10n from "@vscode/l10n"; export default function PersistentAddNewHistoryItemButton(): JSXInternal.Element { const { type, selection } = useDataPanelContext(); @@ -27,12 +27,12 @@ export default function PersistentAddNewHistoryItemButton(): JSXInternal.Element }); }; - const newHistoryItemText = nls.t("Add New History Item"); + const newHistoryItemText = l10n.t("Add New History Item"); const renderAddItemButton = () => { - return selection[type] === "search" && type !== "jobs" ? ( + return selection && selection[type] === "search" && type !== "jobs" ? ( - Add + {l10n.t("Add")} ) : null; }; diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentClearAllButton.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentClearAllButton.tsx index 943fd88d74..3e5ae65577 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentClearAllButton.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentClearAllButton.tsx @@ -13,7 +13,7 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; import { JSXInternal } from "preact/src/jsx"; import { useDataPanelContext } from "../PersistentUtils"; import PersistentVSCodeAPI from "../PersistentVSCodeAPI"; -import * as nls from "@vscode/l10n"; +import * as l10n from "@vscode/l10n"; export default function PersistentClearAllButton(): JSXInternal.Element { const { type, selection } = useDataPanelContext(); @@ -29,11 +29,11 @@ export default function PersistentClearAllButton(): JSXInternal.Element { }; const renderClearAllButton = () => { - const clearAllText = nls.t("Clear All"); + const clearAllText = l10n.t("Clear All"); const selectionType = ["search", "fileHistory", "encodingHistory"]; return selectionType.includes(selection[type]) ? ( - Clear All + {clearAllText} ) : null; }; diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDeleteSelectedButton.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDeleteSelectedButton.tsx index 3299e683c5..efe38ea4ac 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDeleteSelectedButton.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDeleteSelectedButton.tsx @@ -2,10 +2,10 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; import { JSXInternal } from "preact/src/jsx"; import { useDataPanelContext } from "../PersistentUtils"; import PersistentVSCodeAPI from "../PersistentVSCodeAPI"; -import * as nls from "@vscode/l10n"; +import * as l10n from "@vscode/l10n"; export default function PersistentDeleteSelectedButton(): JSXInternal.Element { - const deleteSelectedText = nls.t("Delete Selected"); + const deleteSelectedText = l10n.t("Delete Selected"); const { selection, type, selectedItems } = useDataPanelContext(); const handleClick = async () => { @@ -14,7 +14,7 @@ export default function PersistentDeleteSelectedButton(): JSXInternal.Element { PersistentVSCodeAPI.getVSCodeAPI().postMessage({ command: "show-error", attrs: { - errorMsg: nls.t("Select an item before deleting"), + errorMsg: l10n.t("Select an item before deleting"), }, }); return; @@ -45,7 +45,7 @@ export default function PersistentDeleteSelectedButton(): JSXInternal.Element { style={{ maxWidth: "20vw", marginRight: "15px" }} onClick={async () => await handleClick()} > - Delete + {l10n.t("Delete")} ) : null; }; diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDropdownOptions.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDropdownOptions.tsx index b45396c8bc..3843302fdc 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDropdownOptions.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentDropdownOptions.tsx @@ -12,28 +12,29 @@ import { VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"; import { JSXInternal } from "preact/src/jsx"; import { useDataPanelContext } from "../PersistentUtils"; +import * as l10n from "@vscode/l10n"; export default function PersistentDropdownOptions({ handleChange }: Readonly<{ handleChange: Readonly }>): JSXInternal.Element { const dataPanelContext = useDataPanelContext(); const options = [ - Search History + {l10n.t("Search History")} , - Favorites + {l10n.t("Favorites")} , - File History + {l10n.t("File History")} , - Sessions + {l10n.t("Sessions")} , ]; const optionsEncodingHistory = [ - Encoding History + {l10n.t("Encoding History")} , ].filter((option) => dataPanelContext.type === "uss" || dataPanelContext.type === "ds" || option.props.value !== "encodingHistory"); diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentRefreshButton.tsx b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentRefreshButton.tsx index 5e6b99eb66..1502733099 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentRefreshButton.tsx +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentToolBar/PersistentRefreshButton.tsx @@ -13,7 +13,7 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; import { JSXInternal } from "preact/src/jsx"; import { useDataPanelContext } from "../PersistentUtils"; import PersistentVSCodeAPI from "../PersistentVSCodeAPI"; -import * as nls from "@vscode/l10n"; +import * as l10n from "@vscode/l10n"; export default function PersistentRefreshButton(): JSXInternal.Element { const { type } = useDataPanelContext(); @@ -27,11 +27,11 @@ export default function PersistentRefreshButton(): JSXInternal.Element { }); }; - const refreshText = nls.t("Refresh"); + const refreshText = l10n.t("Refresh"); return ( - Refresh + {refreshText} ); } diff --git a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentUtils.ts b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentUtils.ts index 7e5880c439..4e2daa69f9 100644 --- a/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentUtils.ts +++ b/packages/zowe-explorer/src/webviews/src/edit-history/components/PersistentUtils.ts @@ -12,13 +12,14 @@ import { createContext } from "preact"; import { DataPanelContextType } from "../types"; import { useContext } from "preact/hooks"; +import * as l10n from "@vscode/l10n"; export const DataPanelContext = createContext(null); export function useDataPanelContext(): DataPanelContextType { const dataPanelContext = useContext(DataPanelContext); if (!dataPanelContext) { - throw new Error("DataPanelContext has to be used within "); + throw new Error(l10n.t("DataPanelContext has to be used within ")); } return dataPanelContext; } diff --git a/packages/zowe-explorer/src/webviews/src/table-view/ActionsBar.tsx b/packages/zowe-explorer/src/webviews/src/table-view/ActionsBar.tsx index e08dfc5e9a..6edcf8c6a0 100644 --- a/packages/zowe-explorer/src/webviews/src/table-view/ActionsBar.tsx +++ b/packages/zowe-explorer/src/webviews/src/table-view/ActionsBar.tsx @@ -5,6 +5,7 @@ import { GridApi } from "ag-grid-community"; import { wrapFn } from "./types"; import { FocusableItem, Menu, MenuGroup, MenuItem } from "@szhsin/react-menu"; import "@szhsin/react-menu/dist/index.css"; +import * as l10n from "@vscode/l10n"; interface ActionsProps { actions: Table.Action[]; @@ -80,7 +81,8 @@ export const ActionsBar = (props: ActionsProps) => {

- {props.selectionCount === 0 ? "No" : props.selectionCount} item{props.selectionCount > 1 || props.selectionCount === 0 ? "s" : ""} selected + {props.selectionCount === 0 ? l10n.t("No") : props.selectionCount} {l10n.t("item")} + {props.selectionCount > 1 || props.selectionCount === 0 ? l10n.t("s") : ""} {l10n.t("selected")}

{props.actions .filter((action) => (props.itemCount > 1 ? action.callback.typ === "multi-row" : action.callback.typ.endsWith("row"))) diff --git a/packages/zowe-explorer/src/webviews/src/table-view/TableView.tsx b/packages/zowe-explorer/src/webviews/src/table-view/TableView.tsx index 822e89dc1a..7b71fdbaf3 100644 --- a/packages/zowe-explorer/src/webviews/src/table-view/TableView.tsx +++ b/packages/zowe-explorer/src/webviews/src/table-view/TableView.tsx @@ -13,6 +13,8 @@ import "./style.css"; import { ActionsBar } from "./ActionsBar"; import { actionsColumn } from "./actionsColumn"; import { CheckboxSelectionCallbackParams, HeaderCheckboxSelectionCallbackParams } from "ag-grid-community"; +import { GetLocaleTextParams } from "ag-grid-community"; +import * as l10n from "@vscode/l10n"; const vscodeApi = acquireVsCodeApi(); @@ -23,6 +25,7 @@ function isFirstColumn(params: CheckboxSelectionCallbackParams | HeaderCheckboxS } export const TableView = ({ actionsCellRenderer, baseTheme, data }: TableViewProps) => { + const [localization, setLocalizationContents] = useState<{ [key: string]: string }>({}); const [tableData, setTableData] = useState(data); const [theme, setTheme] = useState(baseTheme ?? "ag-theme-quartz"); const [selectionCount, setSelectionCount] = useState(0); @@ -76,6 +79,14 @@ export const TableView = ({ actionsCellRenderer, baseTheme, data }: TableViewPro return; } + if (event.data.command === "GET_LOCALIZATION") { + const { contents } = event.data; + setLocalizationContents(contents); + l10n.config({ + contents: contents, + }); + } + const response = event.data; if (response.command === "ondatachanged") { // Update received from a VS Code extender; update table state @@ -103,7 +114,13 @@ export const TableView = ({ actionsCellRenderer, baseTheme, data }: TableViewPro // Once the listener is in place, send a "ready signal" to the TableView instance to handle new data. vscodeApi.postMessage({ command: "ready" }); - }, []); + vscodeApi.postMessage({ command: "GET_LOCALIZATION" }); + }, [localization]); + + const localizationMap = [ + { key: "Page Size:", localized: l10n.t("Page Size:") }, + { key: "Page", localized: l10n.t("Page") }, + ]; // Observe attributes of the `body` element to detect VS Code theme changes. useMutableObserver( @@ -115,6 +132,22 @@ export const TableView = ({ actionsCellRenderer, baseTheme, data }: TableViewPro { attributes: true } ); + let getLocaleText = (params: GetLocaleTextParams): string => { + switch (params.key) { + case "thousandSeparator": + return "."; + case "decimalSeparator": + return ","; + default: + if (params.defaultValue) { + const localizedObj = localizationMap.find((item) => item.key === params.defaultValue); + const localizedVal = localizedObj ? localizedObj.localized : params.defaultValue; + return localizedVal; + } + return ""; + } + }; + return (
{contextMenu.component} @@ -129,7 +162,9 @@ export const TableView = ({ actionsCellRenderer, baseTheme, data }: TableViewPro setVisibleColumns={setVisibleColumns} vscodeApi={vscodeApi} /> - {tableData ? : null} + {tableData ? ( + + ) : null}
); }; diff --git a/packages/zowe-explorer/src/webviews/src/zos-console/App.tsx b/packages/zowe-explorer/src/webviews/src/zos-console/App.tsx index ca3f79a4a8..eb8ba1487b 100644 --- a/packages/zowe-explorer/src/webviews/src/zos-console/App.tsx +++ b/packages/zowe-explorer/src/webviews/src/zos-console/App.tsx @@ -1,6 +1,7 @@ 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"; +import * as l10n from "@vscode/l10n"; import { isSecureOrigin } from "../utils"; declare const vscode: any; @@ -11,6 +12,7 @@ declare const vscode: any; */ export function App() { const [consoleContent, setConsoleContent] = useState(""); + const [placeholder, setPlaceholder] = useState(""); useEffect(() => { window.addEventListener("message", (event) => { // Prevent users from sending data into webview outside of extension/webview context @@ -35,10 +37,19 @@ export function App() { profileList.appendChild(option); } break; + case "GET_LOCALIZATION": { + const { contents } = event.data; + l10n.config({ + contents: contents, + }); + setPlaceholder(l10n.t("Enter command here...")); + break; + } } }); const consoleResponse = document.getElementById("output") as TextArea; consoleResponse.control.scrollTop = consoleResponse.control.scrollHeight; + vscode.postMessage({ command: "GET_LOCALIZATION" }); }); const sendCommand = (e: KeyboardEvent) => { @@ -65,7 +76,7 @@ export function App() { id="command-input" name="command-input" type="text" - placeholder="Enter command here..." + placeholder={placeholder} onKeyDown={sendCommand} style={{ width: "100%", diff --git a/packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts b/packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts index f66d876f0f..b6d6901674 100644 --- a/packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts +++ b/packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts @@ -17,6 +17,7 @@ import { Profiles } from "../configuration/Profiles"; import { randomUUID } from "crypto"; import { Definitions } from "../configuration/Definitions"; import Mustache = require("mustache"); +import * as fs from "fs"; /** * @deprecated @@ -81,6 +82,21 @@ export class ZosConsoleViewProvider implements vscode.WebviewViewProvider { profile: profile, result: await this.runOperCmd(text, profile), }); + break; + case "GET_LOCALIZATION": + { + const filePath = vscode.l10n.uri?.fsPath + ""; + fs.readFile(filePath, "utf8", (err, data) => { + if (err) { + // File doesn't exist, fallback to English strings + return; + } + webviewView.webview.postMessage({ + type: "GET_LOCALIZATION", + contents: data, + }); + }); + } return; } });