From 0bd3934dfec440a2bce95434e0c6e8dee2c4fe58 Mon Sep 17 00:00:00 2001 From: Chuck Skelton Date: Mon, 4 May 2026 15:36:59 -0700 Subject: [PATCH] Refactoring container copy strings so they can be locallized --- .../ContainerCopy/Actions/CopyJobActions.tsx | 8 +- .../ContainerCopy/CommandBar/Utils.ts | 14 +- .../ContainerCopy/ContainerCopyMessages.ts | 193 ------------------ .../AddManagedIdentity.test.tsx | 25 +-- .../AssignPermissions/AddManagedIdentity.tsx | 30 ++- ...ddReadPermissionToDefaultIdentity.test.tsx | 8 +- .../AddReadPermissionToDefaultIdentity.tsx | 18 +- .../AssignPermissions.test.tsx | 8 +- .../AssignPermissions/AssignPermissions.tsx | 10 +- .../DefaultManagedIdentity.test.tsx | 18 +- .../DefaultManagedIdentity.tsx | 21 +- .../OnlineCopyEnabled.test.tsx | 46 +++-- .../AssignPermissions/OnlineCopyEnabled.tsx | 20 +- .../AssignPermissions/PointInTimeRestore.tsx | 16 +- .../AddManagedIdentity.test.tsx.snap | 6 +- .../DefaultManagedIdentity.test.tsx.snap | 2 +- .../hooks/usePermissionsSection.tsx | 28 +-- .../Components/PopoverContainer.test.tsx | 4 +- .../Screens/Components/PopoverContainer.tsx | 4 +- .../AddCollectionPanelWrapper.test.tsx | 14 +- .../AddCollectionPanelWrapper.tsx | 10 +- .../PreviewCopyJob/PreviewCopyJob.test.tsx | 9 +- .../Screens/PreviewCopyJob/PreviewCopyJob.tsx | 8 +- .../Utils/PreviewCopyJobUtils.ts | 10 +- .../Components/AccountDropdown.test.tsx | 8 +- .../Components/AccountDropdown.tsx | 8 +- .../Components/MigrationType.test.tsx | 30 ++- .../Components/MigrationType.tsx | 12 +- .../Components/SubscriptionDropdown.test.tsx | 5 - .../Components/SubscriptionDropdown.tsx | 8 +- .../Screens/SelectAccount/SelectAccount.tsx | 4 +- .../SelectSourceAndTargetContainers.test.tsx | 50 ++--- .../SelectSourceAndTargetContainers.tsx | 8 +- .../DatabaseContainerSection.test.tsx | 84 +++++--- .../components/DatabaseContainerSection.tsx | 16 +- .../Components/CopyJobActionMenu.test.tsx | 32 +-- .../Components/CopyJobActionMenu.tsx | 20 +- .../Components/CopyJobColumns.test.tsx | 14 +- .../Components/CopyJobColumns.tsx | 12 +- .../Components/CopyJobDetails.test.tsx | 20 +- .../Components/CopyJobDetails.tsx | 20 +- .../Components/CopyJobStatusWithIcon.tsx | 17 +- .../Components/CopyJobs.NotFound.test.tsx | 12 +- .../Components/CopyJobs.NotFound.tsx | 8 +- .../PartitionKeyComponent.tsx | 39 ++-- .../ChangePartitionKeyPane.tsx | 39 ++-- src/Localization/en/Resources.json | 162 ++++++++++++++- 47 files changed, 559 insertions(+), 599 deletions(-) delete mode 100644 src/Explorer/ContainerCopy/ContainerCopyMessages.ts diff --git a/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx b/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx index 821f87bc9..ec8f60be7 100644 --- a/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx +++ b/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx @@ -15,7 +15,7 @@ import { CreateJobRequest, DataTransferJobGetResults, } from "../../../Utils/arm/generatedClients/dataTransferService/types"; -import ContainerCopyMessages from "../ContainerCopyMessages"; +import { Keys, t } from "Localization"; import { convertTime, convertToCamelCase, @@ -35,7 +35,7 @@ export const openCreateCopyJobPanel = (explorer: Explorer) => { const sidePanelState = useSidePanel.getState(); sidePanelState.setPanelHasConsole(false); sidePanelState.openSidePanel( - ContainerCopyMessages.createCopyJobPanelTitle, + t(Keys.containerCopy.createCopyJob.panelTitle), , "650px", ); @@ -45,7 +45,7 @@ export const openCopyJobDetailsPanel = (job: CopyJobType) => { const sidePanelState = useSidePanel.getState(); sidePanelState.setPanelHasConsole(false); sidePanelState.openSidePanel( - ContainerCopyMessages.copyJobDetailsPanelTitle(job.Name), + job.Name || t(Keys.containerCopy.jobDetails.panelTitleDefault), , "650px", ); @@ -193,7 +193,7 @@ export const updateCopyJobStatus = async (job: CopyJobType, action: string): Pro const pattern = new RegExp(`'(${statusList.join("|")})'`, "g"); const normalizedErrorMessage = errorMessage.replace( pattern, - `'${ContainerCopyMessages.MonitorJobs.Status.InProgress}'`, + `'${t(Keys.containerCopy.monitorJobs.status.inProgress)}'`, ); logError(`Error updating copy job status: ${normalizedErrorMessage}`, "CopyJob/CopyJobActions.updateCopyJobStatus"); throw error; diff --git a/src/Explorer/ContainerCopy/CommandBar/Utils.ts b/src/Explorer/ContainerCopy/CommandBar/Utils.ts index 5b96a6c37..5d8ba6c29 100644 --- a/src/Explorer/ContainerCopy/CommandBar/Utils.ts +++ b/src/Explorer/ContainerCopy/CommandBar/Utils.ts @@ -5,10 +5,10 @@ import RefreshIcon from "../../../../images/refresh-cosmos.svg"; import SunIcon from "../../../../images/SunIcon.svg"; import { configContext, Platform } from "../../../ConfigContext"; import { useThemeStore } from "../../../hooks/useTheme"; +import { Keys, t } from "Localization"; import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; import Explorer from "../../Explorer"; import * as Actions from "../Actions/CopyJobActions"; -import ContainerCopyMessages from "../ContainerCopyMessages"; import { MonitorCopyJobsRefState } from "../MonitorCopyJobs/MonitorCopyJobRefState"; import { CopyJobCommandBarBtnType } from "../Types/CopyJobTypes"; @@ -19,15 +19,15 @@ function getCopyJobBtns(explorer: Explorer, isDarkMode: boolean): CopyJobCommand { key: "createCopyJob", iconSrc: AddIcon, - label: ContainerCopyMessages.createCopyJobButtonLabel, - ariaLabel: ContainerCopyMessages.createCopyJobButtonAriaLabel, + label: t(Keys.containerCopy.commandBar.createCopyJobButtonLabel), + ariaLabel: t(Keys.containerCopy.commandBar.createCopyJobButtonAriaLabel), onClick: () => Actions.openCreateCopyJobPanel(explorer), }, { key: "refresh", iconSrc: RefreshIcon, - label: ContainerCopyMessages.refreshButtonLabel, - ariaLabel: ContainerCopyMessages.refreshButtonAriaLabel, + label: t(Keys.common.refresh), + ariaLabel: t(Keys.containerCopy.commandBar.refreshButtonAriaLabel), onClick: () => monitorCopyJobsRef?.refreshJobList(), }, { @@ -48,8 +48,8 @@ function getCopyJobBtns(explorer: Explorer, isDarkMode: boolean): CopyJobCommand buttons.push({ key: "feedback", iconSrc: FeedbackIcon, - label: ContainerCopyMessages.feedbackButtonLabel, - ariaLabel: ContainerCopyMessages.feedbackButtonAriaLabel, + label: t(Keys.containerCopy.commandBar.feedbackButtonLabel), + ariaLabel: t(Keys.containerCopy.commandBar.feedbackButtonAriaLabel), onClick: () => { explorer.openContainerCopyFeedbackBlade(); }, diff --git a/src/Explorer/ContainerCopy/ContainerCopyMessages.ts b/src/Explorer/ContainerCopy/ContainerCopyMessages.ts deleted file mode 100644 index 65b308b9b..000000000 --- a/src/Explorer/ContainerCopy/ContainerCopyMessages.ts +++ /dev/null @@ -1,193 +0,0 @@ -export default { - // Copy Job Command Bar - feedbackButtonLabel: "Feedback", - feedbackButtonAriaLabel: "Provide feedback on copy jobs", - refreshButtonLabel: "Refresh", - refreshButtonAriaLabel: "Refresh copy jobs", - createCopyJobButtonLabel: "Create Copy Job", - createCopyJobButtonAriaLabel: "Create a new container copy job", - - // No Copy Jobs Found - noCopyJobsTitle: "No copy jobs to show", - createCopyJobButtonText: "Create a container copy job", - - // Copy Job Details - copyJobDetailsPanelTitle: (jobName: string) => jobName || "Job Details", - errorTitle: "Error Details", - selectedContainers: "Selected Containers", - - // Create Copy Job Panel - createCopyJobPanelTitle: "Create copy job", - - // Select Account Screen - selectAccountDescription: "Please select a source account from which to copy.", - subscriptionDropdownLabel: "Subscription", - subscriptionDropdownPlaceholder: "Select a subscription", - sourceAccountDropdownLabel: "Account", - sourceAccountDropdownPlaceholder: "Select an account", - migrationTypeOptions: { - offline: { - title: "Offline mode", - description: - "Offline container copy jobs let you copy data from a source container to a destination Cosmos DB container for supported APIs. To ensure data integrity between the source and destination, we recommend stopping updates on the source container before creating the copy job. Learn more about [offline copy jobs](https://learn.microsoft.com/azure/cosmos-db/how-to-container-copy?tabs=offline-copy&pivots=api-nosql).", - }, - online: { - title: "Online mode", - description: - "Online container copy jobs let you copy data from a source container to a destination Cosmos DB NoSQL API container using the [All Versions and Delete](https://learn.microsoft.com/azure/cosmos-db/change-feed-modes?tabs=all-versions-and-deletes#all-versions-and-deletes-change-feed-mode-preview) change feed. This allows updates to continue on the source while data is copied. A brief downtime is required at the end to safely switch over client applications to the destination container. Learn more about [online copy jobs](https://learn.microsoft.com/azure/cosmos-db/container-copy?tabs=online-copy&pivots=api-nosql#getting-started).", - }, - }, - - // Select Source and Target Containers Screen - selectSourceAndTargetContainersDescription: - "Please select a source container and a destination container to copy to.", - sourceContainerSubHeading: "Source container", - targetContainerSubHeading: "Destination container", - databaseDropdownLabel: "Database", - databaseDropdownPlaceholder: "Select a database", - containerDropdownLabel: "Container", - containerDropdownPlaceholder: "Select a container", - createNewContainerSubHeading: "Select the properties for your container.", - createContainerButtonLabel: "Create a new container", - createContainerHeading: "Create new container", - - // Preview and Create Screen - jobNameLabel: "Job name", - sourceSubscriptionLabel: "Source subscription", - sourceAccountLabel: "Source account", - sourceDatabaseLabel: "Source database", - sourceContainerLabel: "Source container", - targetDatabaseLabel: "Destination database", - targetContainerLabel: "Destination container", - - // Assign Permissions Screen - assignPermissions: { - crossAccountDescription: - "To copy data from the source to the destination container, ensure that the managed identity of the destination account has read access to the source account by completing the following steps.", - intraAccountOnlineDescription: (accountName: string) => - `Follow the steps below to enable online copy on your "${accountName}" account.`, - crossAccountConfiguration: { - title: "Cross-account container copy", - description: (sourceAccount: string, destinationAccount: string) => - `Please follow the instruction below to grant requisite permissions to copy data from "${sourceAccount}" to "${destinationAccount}".`, - }, - onlineConfiguration: { - title: "Online container copy", - description: (accountName: string) => - `Please follow the instructions below to enable online copy on your "${accountName}" account.`, - }, - }, - toggleBtn: { - onText: "On", - offText: "Off", - }, - popoverOverlaySpinnerLabel: "Please wait while we process your request...", - addManagedIdentity: { - title: "System-assigned managed identity enabled.", - description: - "A system-assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. Once enabled, you can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Microsoft Entra ID, so you don’t have to store any credentials in code.", - descriptionHrefText: "Learn more about Managed identities.", - descriptionHref: "https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview", - toggleLabel: "System assigned managed identity", - tooltip: { - content: "Learn more about", - hrefText: "Managed Identities.", - href: "https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview", - }, - userAssignedIdentityTooltip: "You can select an existing user assigned identity or create a new one.", - userAssignedIdentityLabel: "You may also select a user assigned managed identity.", - createUserAssignedIdentityLink: "Create User Assigned Managed Identity", - enablementTitle: "Enable system assigned managed identity", - enablementDescription: (accountName: string) => - accountName - ? `Enable system-assigned managed identity on the ${accountName}. To confirm, click the "Yes" button.` - : "", - }, - defaultManagedIdentity: { - title: "System-assigned managed identity set as default.", - description: (accountName: string) => - `Set the system-assigned managed identity as default for "${accountName}" by switching it on.`, - tooltip: { - content: "Learn more about", - hrefText: "Default Managed Identities.", - href: "https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview", - }, - popoverTitle: "System assigned managed identity set as default", - popoverDescription: (accountName: string) => - `Assign the system-assigned managed identity as the default for "${accountName}". To confirm, click the "Yes" button. `, - }, - readPermissionAssigned: { - title: "Read permissions assigned to the default identity.", - description: - "To allow data copy from source to the destination container, provide read access of the source account to the default identity of the destination account.", - tooltip: { - content: "Learn more about", - hrefText: "Read permissions.", - href: "https://learn.microsoft.com/azure/cosmos-db/nosql/how-to-connect-role-based-access-control", - }, - popoverTitle: "Read permissions assigned to default identity.", - popoverDescription: - "Assign read permissions of the source account to the default identity of the destination account. To confirm click the “Yes” button.", - }, - pointInTimeRestore: { - title: "Point In Time Restore enabled", - description: (accessName: string) => - `To facilitate online container copy jobs, please update your "${accessName}" backup policy from periodic to continuous backup. Enabling continuous backup is required for this functionality.`, - tooltip: { - content: "Learn more about", - hrefText: "Continuous Backup", - href: "https://learn.microsoft.com/en-us/azure/cosmos-db/continuous-backup-restore-introduction", - }, - buttonText: "Enable Point In Time Restore", - }, - onlineCopyEnabled: { - title: "Online copy enabled", - description: (accountName: string) => - `Enable online container copy by clicking the button below on your "${accountName}" account.`, - hrefText: "Learn more about online copy jobs", - href: "https://learn.microsoft.com/en-us/azure/cosmos-db/container-copy?tabs=online-copy&pivots=api-nosql#enable-online-copy", - buttonText: "Enable Online Copy", - validateAllVersionsAndDeletesChangeFeedSpinnerLabel: - "Validating All versions and deletes change feed mode (preview)...", - enablingAllVersionsAndDeletesChangeFeedSpinnerLabel: - "Enabling All versions and deletes change feed mode (preview)...", - enablingOnlineCopySpinnerLabel: (accountName: string) => - `Enabling online copy on your "${accountName}" account ...`, - }, - MonitorJobs: { - Columns: { - lastUpdatedTime: "Date & time", - name: "Job name", - status: "Status", - completionPercentage: "Completion %", - duration: "Duration", - error: "Error message", - mode: "Mode", - actions: "Actions", - }, - Actions: { - pause: "Pause", - resume: "Resume", - cancel: "Cancel", - complete: "Complete", - viewDetails: "View Details", - }, - Status: { - Pending: "Queued", - InProgress: "Running", - Running: "Running", - Partitioning: "Running", - Paused: "Paused", - Completed: "Completed", - Failed: "Failed", - Faulted: "Failed", - Skipped: "Cancelled", - Cancelled: "Cancelled", - }, - dialog: { - heading: "", - confirmButtonText: "Confirm", - cancelButtonText: "Cancel", - }, - }, -}; diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.test.tsx index 6022b98d4..98ef7fae3 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.test.tsx @@ -2,9 +2,9 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import { DatabaseAccount } from "Contracts/DataModels"; import { CopyJobContextProviderType } from "Explorer/ContainerCopy/Types/CopyJobTypes"; +import { Keys, t } from "Localization"; import React from "react"; import { updateSystemIdentity } from "../../../../../Utils/arm/identityUtils"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { CopyJobContext } from "../../../Context/CopyJobContext"; import AddManagedIdentity from "./AddManagedIdentity"; @@ -133,16 +133,16 @@ describe("AddManagedIdentity", () => { it("renders all required elements", () => { renderWithContext(); - expect(screen.getByText(ContainerCopyMessages.addManagedIdentity.description)).toBeInTheDocument(); - expect(screen.getByText(ContainerCopyMessages.addManagedIdentity.descriptionHrefText)).toBeInTheDocument(); + expect(screen.getByText(t(Keys.containerCopy.addManagedIdentity.description))).toBeInTheDocument(); + expect(screen.getByText(t(Keys.containerCopy.addManagedIdentity.descriptionHrefText))).toBeInTheDocument(); expect(screen.getByRole("switch")).toBeInTheDocument(); }); it("renders description link with correct href", () => { renderWithContext(); - const link = screen.getByText(ContainerCopyMessages.addManagedIdentity.descriptionHrefText); - expect(link.closest("a")).toHaveAttribute("href", ContainerCopyMessages.addManagedIdentity.descriptionHref); + const link = screen.getByText(t(Keys.containerCopy.addManagedIdentity.descriptionHrefText)); + expect(link.closest("a")).toHaveAttribute("href", t(Keys.containerCopy.addManagedIdentity.descriptionHref)); expect(link.closest("a")).toHaveAttribute("target", "_blank"); expect(link.closest("a")).toHaveAttribute("rel", "noopener noreferrer"); }); @@ -175,7 +175,7 @@ describe("AddManagedIdentity", () => { const toggle = screen.getByRole("switch"); fireEvent.click(toggle); - expect(screen.getByText(ContainerCopyMessages.addManagedIdentity.enablementTitle)).toBeInTheDocument(); + expect(screen.getByText(t(Keys.containerCopy.addManagedIdentity.enablementTitle))).toBeInTheDocument(); }); it("hides popover when toggle is off", () => { @@ -185,7 +185,7 @@ describe("AddManagedIdentity", () => { fireEvent.click(toggle); fireEvent.click(toggle); - expect(screen.queryByText(ContainerCopyMessages.addManagedIdentity.enablementTitle)).not.toBeInTheDocument(); + expect(screen.queryByText(t(Keys.containerCopy.addManagedIdentity.enablementTitle))).not.toBeInTheDocument(); }); }); @@ -197,10 +197,11 @@ describe("AddManagedIdentity", () => { }); it("displays correct enablement description with account name", () => { - const expectedDescription = ContainerCopyMessages.addManagedIdentity.enablementDescription( - mockCopyJobState.target.account.name, - ); - expect(screen.getByText(expectedDescription)).toBeInTheDocument(); + expect( + screen.getByText( + t(Keys.containerCopy.addManagedIdentity.enablementDescription, { accountName: "test-target-account" }), + ), + ).toBeInTheDocument(); }); it("calls handleAddSystemIdentity when primary button clicked", async () => { @@ -220,7 +221,7 @@ describe("AddManagedIdentity", () => { const cancelButton = screen.getByText("Cancel"); fireEvent.click(cancelButton); - expect(screen.queryByText(ContainerCopyMessages.addManagedIdentity.enablementTitle)).not.toBeInTheDocument(); + expect(screen.queryByText(t(Keys.containerCopy.addManagedIdentity.enablementTitle))).not.toBeInTheDocument(); const toggle = screen.getByRole("switch"); expect(toggle).not.toBeChecked(); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.tsx index 86c59611c..c2387580a 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddManagedIdentity.tsx @@ -1,7 +1,7 @@ import { Link, Stack, Text, Toggle } from "@fluentui/react"; +import { Keys, t } from "Localization"; import React from "react"; import { updateSystemIdentity } from "../../../../../Utils/arm/identityUtils"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import InfoTooltip from "../Components/InfoTooltip"; import PopoverMessage from "../Components/PopoverContainer"; @@ -11,14 +11,14 @@ import useToggle from "./hooks/useToggle"; const managedIdentityTooltip = ( - {ContainerCopyMessages.addManagedIdentity.tooltip.content}   + {t(Keys.containerCopy.addManagedIdentity.tooltipContent)}   - {ContainerCopyMessages.addManagedIdentity.tooltip.hrefText} + {t(Keys.containerCopy.addManagedIdentity.tooltipHrefText)} ); @@ -32,28 +32,26 @@ const AddManagedIdentity: React.FC = () => { return ( - {ContainerCopyMessages.addManagedIdentity.description}  - - {ContainerCopyMessages.addManagedIdentity.descriptionHrefText} + {t(Keys.containerCopy.addManagedIdentity.description)}  + + {t(Keys.containerCopy.addManagedIdentity.descriptionHrefText)} {" "}   - + onToggle(null, false)} onPrimary={handleAddSystemIdentity} > - {ContainerCopyMessages.addManagedIdentity.enablementDescription(copyJobState.target?.account?.name)} + {copyJobState.target?.account?.name + ? t(Keys.containerCopy.addManagedIdentity.enablementDescription, { + accountName: copyJobState.target?.account?.name, + }) + : ""} ); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.test.tsx index 5ef3577b8..69c5bcc93 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.test.tsx @@ -1,7 +1,7 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { Keys, t } from "Localization"; import React from "react"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { CopyJobContext } from "../../../Context/CopyJobContext"; import { CopyJobContextProviderType } from "../../../Types/CopyJobTypes"; import AddReadPermissionToDefaultIdentity from "./AddReadPermissionToDefaultIdentity"; @@ -180,7 +180,7 @@ describe("AddReadPermissionToDefaultIdentity Component", () => { describe("Component Structure", () => { it("should display the description text", () => { renderComponent(); - expect(screen.getByText(ContainerCopyMessages.readPermissionAssigned.description)).toBeInTheDocument(); + expect(screen.getByText(t(Keys.containerCopy.readPermissionAssigned.description))).toBeInTheDocument(); }); it("should display the info tooltip", () => { @@ -212,10 +212,10 @@ describe("AddReadPermissionToDefaultIdentity Component", () => { expect(screen.getByTestId("popover-message")).toBeInTheDocument(); expect(screen.getByTestId("popover-title")).toHaveTextContent( - ContainerCopyMessages.readPermissionAssigned.popoverTitle, + t(Keys.containerCopy.readPermissionAssigned.popoverTitle), ); expect(screen.getByTestId("popover-content")).toHaveTextContent( - ContainerCopyMessages.readPermissionAssigned.popoverDescription, + t(Keys.containerCopy.readPermissionAssigned.popoverDescription), ); }); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx index 5af5630d7..691c8f1bc 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx @@ -1,8 +1,8 @@ import { Link, Stack, Text, Toggle } from "@fluentui/react"; +import { Keys, t } from "Localization"; import React from "react"; import { logError } from "../../../../../Common/Logger"; import { assignRole } from "../../../../../Utils/arm/RbacUtils"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import { getAccountDetailsFromResourceId } from "../../../CopyJobUtils"; import InfoTooltip from "../Components/InfoTooltip"; @@ -12,14 +12,14 @@ import useToggle from "./hooks/useToggle"; const TooltipContent = ( - {ContainerCopyMessages.readPermissionAssigned.tooltip.content}   + {t(Keys.containerCopy.readPermissionAssigned.tooltipContent)}   - {ContainerCopyMessages.readPermissionAssigned.tooltip.hrefText} + {t(Keys.containerCopy.readPermissionAssigned.tooltipHrefText)} ); @@ -66,14 +66,14 @@ const AddReadPermissionToDefaultIdentity: React.FC - {ContainerCopyMessages.readPermissionAssigned.description}  + {t(Keys.containerCopy.readPermissionAssigned.description)}  onToggle(null, false)} onPrimary={handleAddReadPermission} > - {ContainerCopyMessages.readPermissionAssigned.popoverDescription} + {t(Keys.containerCopy.readPermissionAssigned.popoverDescription)} ); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.test.tsx index 76f915c5e..1147f6b67 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.test.tsx @@ -1,7 +1,7 @@ import "@testing-library/jest-dom"; import { render, RenderResult } from "@testing-library/react"; +import { Keys, t } from "Localization"; import React from "react"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { CopyJobContext } from "../../../Context/CopyJobContext"; import { CopyJobMigrationType } from "../../../Enums/CopyJobEnums"; import { CopyJobContextProviderType, CopyJobContextState } from "../../../Types/CopyJobTypes"; @@ -154,7 +154,7 @@ describe("AssignPermissions Component", () => { const copyJobState = createMockCopyJobState(); const { getByText } = renderWithContext(copyJobState); - expect(getByText(ContainerCopyMessages.assignPermissions.crossAccountDescription)).toBeInTheDocument(); + expect(getByText(t(Keys.containerCopy.assignPermissions.crossAccountDescription))).toBeInTheDocument(); }); it("should display intra account description for same accounts with online migration", async () => { @@ -179,7 +179,9 @@ describe("AssignPermissions Component", () => { const { getByText } = renderWithContext(copyJobState); expect( - getByText(ContainerCopyMessages.assignPermissions.intraAccountOnlineDescription("Same Account")), + getByText( + t(Keys.containerCopy.assignPermissions.intraAccountOnlineDescription, { accountName: "Same Account" }), + ), ).toBeInTheDocument(); }); }); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.tsx index 40a657f59..b8c3b9bc7 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AssignPermissions.tsx @@ -4,7 +4,7 @@ import React, { useEffect } from "react"; import CheckmarkIcon from "../../../../../../images/successfulPopup.svg"; import WarningIcon from "../../../../../../images/warning.svg"; import ShimmerTree, { IndentLevel } from "../../../../../Common/ShimmerTree/ShimmerTree"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; +import { Keys, t } from "Localization"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import { isIntraAccountCopy } from "../../../CopyJobUtils"; import { CopyJobMigrationType } from "../../../Enums/CopyJobEnums"; @@ -107,10 +107,10 @@ const AssignPermissions = () => { > {isSameAccount && copyJobState.migrationType === CopyJobMigrationType.Online - ? ContainerCopyMessages.assignPermissions.intraAccountOnlineDescription( - copyJobState?.source?.account?.name || "", - ) - : ContainerCopyMessages.assignPermissions.crossAccountDescription} + ? t(Keys.containerCopy.assignPermissions.intraAccountOnlineDescription, { + accountName: copyJobState?.source?.account?.name || "", + }) + : t(Keys.containerCopy.assignPermissions.crossAccountDescription)} {totalSectionsCount === 0 ? ( diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.test.tsx index 93418859f..08e6b55cb 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.test.tsx @@ -1,8 +1,8 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; +import { Keys, t } from "Localization"; import React from "react"; import { updateDefaultIdentity } from "../../../../../Utils/arm/identityUtils"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { CopyJobContext } from "../../../Context/CopyJobContext"; import DefaultManagedIdentity from "./DefaultManagedIdentity"; @@ -117,7 +117,7 @@ describe("DefaultManagedIdentity", () => { renderComponent(); const description = screen.getByText( - /Set the system-assigned managed identity as default for "test-cosmos-account"/, + t(Keys.containerCopy.defaultManagedIdentity.description, { accountName: "test-cosmos-account" }), ); expect(description).toBeInTheDocument(); }); @@ -127,8 +127,8 @@ describe("DefaultManagedIdentity", () => { const tooltip = screen.getByTestId("info-tooltip"); expect(tooltip).toBeInTheDocument(); - expect(tooltip).toHaveTextContent("Learn more about"); - expect(tooltip).toHaveTextContent("Default Managed Identities."); + expect(tooltip).toHaveTextContent(t(Keys.containerCopy.defaultManagedIdentity.tooltipContent)); + expect(tooltip).toHaveTextContent(t(Keys.containerCopy.defaultManagedIdentity.tooltipHrefText)); }); it("should render the toggle button with correct initial state", () => { @@ -166,11 +166,11 @@ describe("DefaultManagedIdentity", () => { expect(popover).toBeInTheDocument(); const title = screen.getByTestId("popover-title"); - expect(title).toHaveTextContent(ContainerCopyMessages.defaultManagedIdentity.popoverTitle); + expect(title).toHaveTextContent(t(Keys.containerCopy.defaultManagedIdentity.popoverTitle)); const content = screen.getByTestId("popover-content"); expect(content).toHaveTextContent( - /Assign the system-assigned managed identity as the default for "test-cosmos-account"/, + t(Keys.containerCopy.defaultManagedIdentity.popoverDescription, { accountName: "test-cosmos-account" }).trim(), ); }); @@ -339,8 +339,8 @@ describe("DefaultManagedIdentity", () => { it("should display correct toggle button text", () => { renderComponent(); - const onText = screen.queryByText(ContainerCopyMessages.toggleBtn.onText); - const offText = screen.queryByText(ContainerCopyMessages.toggleBtn.offText); + const onText = screen.queryByText("On"); + const offText = screen.queryByText("Off"); expect(onText || offText).toBeTruthy(); }); @@ -348,7 +348,7 @@ describe("DefaultManagedIdentity", () => { it("should display correct link text in tooltip", () => { renderComponent(); - const linkText = screen.getByText(ContainerCopyMessages.defaultManagedIdentity.tooltip.hrefText); + const linkText = screen.getByText(t(Keys.containerCopy.defaultManagedIdentity.tooltipHrefText)); expect(linkText).toBeInTheDocument(); }); }); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.tsx index 92c752171..262e55c17 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/DefaultManagedIdentity.tsx @@ -1,7 +1,7 @@ import { Link, Stack, Text, Toggle } from "@fluentui/react"; +import { Keys, t } from "Localization"; import React from "react"; import { updateDefaultIdentity } from "../../../../../Utils/arm/identityUtils"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import InfoTooltip from "../Components/InfoTooltip"; import PopoverMessage from "../Components/PopoverContainer"; @@ -11,14 +11,14 @@ import useToggle from "./hooks/useToggle"; const managedIdentityTooltip = ( - {ContainerCopyMessages.defaultManagedIdentity.tooltip.content}   + {t(Keys.containerCopy.defaultManagedIdentity.tooltipContent)}   - {ContainerCopyMessages.defaultManagedIdentity.tooltip.hrefText} + {t(Keys.containerCopy.defaultManagedIdentity.tooltipHrefText)} ); @@ -32,14 +32,15 @@ const DefaultManagedIdentity: React.FC = () => { return (
- {ContainerCopyMessages.defaultManagedIdentity.description(copyJobState?.target?.account?.name)}   + {t(Keys.containerCopy.defaultManagedIdentity.description, { accountName: copyJobState?.target?.account?.name })}{" "} +  
= () => { onToggle(null, false)} onPrimary={handleAddSystemIdentity} > - {ContainerCopyMessages.defaultManagedIdentity.popoverDescription(copyJobState?.target?.account?.name)} + {t(Keys.containerCopy.defaultManagedIdentity.popoverDescription, { + accountName: copyJobState?.target?.account?.name, + })}
); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.test.tsx index 8d28f2482..92d68281d 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.test.tsx @@ -2,12 +2,12 @@ import "@testing-library/jest-dom"; import { act, fireEvent, render, screen, waitFor } from "@testing-library/react"; import { DatabaseAccount } from "Contracts/DataModels"; import { CopyJobContextProviderType } from "Explorer/ContainerCopy/Types/CopyJobTypes"; +import { Keys, t } from "Localization"; import React from "react"; import { fetchDatabaseAccount } from "Utils/arm/databaseAccountUtils"; import { CapabilityNames } from "../../../../../Common/Constants"; import { logError } from "../../../../../Common/Logger"; import { update as updateDatabaseAccount } from "../../../../../Utils/arm/generatedClients/cosmos/databaseAccounts"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { CopyJobContext } from "../../../Context/CopyJobContext"; import OnlineCopyEnabled from "./OnlineCopyEnabled"; @@ -97,7 +97,9 @@ describe("OnlineCopyEnabled", () => { it("should render the description with account name", () => { renderComponent(); - const description = screen.getByText(ContainerCopyMessages.onlineCopyEnabled.description("test-account")); + const description = screen.getByText( + t(Keys.containerCopy.onlineCopyEnabled.description, { accountName: "test-account" }), + ); expect(description).toBeInTheDocument(); }); @@ -105,10 +107,10 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const link = screen.getByRole("link", { - name: ContainerCopyMessages.onlineCopyEnabled.hrefText, + name: t(Keys.containerCopy.onlineCopyEnabled.hrefText), }); expect(link).toBeInTheDocument(); - expect(link).toHaveAttribute("href", ContainerCopyMessages.onlineCopyEnabled.href); + expect(link).toHaveAttribute("href", t(Keys.containerCopy.onlineCopyEnabled.href)); expect(link).toHaveAttribute("target", "_blank"); expect(link).toHaveAttribute("rel", "noopener noreferrer"); }); @@ -117,7 +119,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const button = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); expect(button).toBeInTheDocument(); expect(button).not.toBeDisabled(); @@ -134,7 +136,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const refreshButton = screen.queryByRole("button", { - name: ContainerCopyMessages.refreshButtonLabel, + name: "Refresh", }); expect(refreshButton).not.toBeInTheDocument(); }); @@ -167,7 +169,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -222,7 +224,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -246,7 +248,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -259,7 +261,9 @@ describe("OnlineCopyEnabled", () => { await waitFor(() => { expect( - screen.getByText(ContainerCopyMessages.onlineCopyEnabled.enablingOnlineCopySpinnerLabel("test-account")), + screen.getByText( + t(Keys.containerCopy.onlineCopyEnabled.enablingOnlineCopySpinnerLabel, { accountName: "test-account" }), + ), ).toBeInTheDocument(); }); }); @@ -272,7 +276,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -306,7 +310,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -318,7 +322,7 @@ describe("OnlineCopyEnabled", () => { }); const refreshButton = screen.getByRole("button", { - name: ContainerCopyMessages.refreshButtonLabel, + name: "Refresh", }); await act(async () => { @@ -349,7 +353,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -379,7 +383,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -401,7 +405,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -418,7 +422,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -436,7 +440,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); await act(async () => { @@ -450,7 +454,7 @@ describe("OnlineCopyEnabled", () => { mockFetchDatabaseAccount.mockImplementation(() => new Promise(() => {})); const refreshButton = screen.getByRole("button", { - name: ContainerCopyMessages.refreshButtonLabel, + name: "Refresh", }); await act(async () => { @@ -536,7 +540,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(contextWithNoCapabilities); const enableButton = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); expect(enableButton).toBeInTheDocument(); }); @@ -547,7 +551,7 @@ describe("OnlineCopyEnabled", () => { renderComponent(); const button = screen.getByRole("button", { - name: ContainerCopyMessages.onlineCopyEnabled.buttonText, + name: t(Keys.containerCopy.onlineCopyEnabled.buttonText), }); expect(button).toBeInTheDocument(); }); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.tsx index a6f0918c3..fb3c199e5 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/OnlineCopyEnabled.tsx @@ -1,12 +1,12 @@ import { Link, PrimaryButton, Stack } from "@fluentui/react"; import { DatabaseAccount } from "Contracts/DataModels"; +import { Keys, t } from "Localization"; import React from "react"; import { fetchDatabaseAccount } from "Utils/arm/databaseAccountUtils"; import { CapabilityNames } from "../../../../../Common/Constants"; import LoadingOverlay from "../../../../../Common/LoadingOverlay"; import { logError } from "../../../../../Common/Logger"; import { update as updateDatabaseAccount } from "../../../../../Utils/arm/generatedClients/cosmos/databaseAccounts"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import { getAccountDetailsFromResourceId } from "../../../CopyJobUtils"; import { AccountValidatorFn } from "../../../Types/CopyJobTypes"; @@ -76,21 +76,23 @@ const OnlineCopyEnabled: React.FC = () => { setShowRefreshButton(false); try { - setLoaderMessage(ContainerCopyMessages.onlineCopyEnabled.validateAllVersionsAndDeletesChangeFeedSpinnerLabel); + setLoaderMessage(t(Keys.containerCopy.onlineCopyEnabled.validateAllVersionsAndDeletesChangeFeedSpinnerLabel)); const sourAccountBeforeUpdate = await fetchDatabaseAccount( sourceSubscriptionId, sourceResourceGroup, sourceAccountName, ); if (!sourAccountBeforeUpdate?.properties.enableAllVersionsAndDeletesChangeFeed) { - setLoaderMessage(ContainerCopyMessages.onlineCopyEnabled.enablingAllVersionsAndDeletesChangeFeedSpinnerLabel); + setLoaderMessage(t(Keys.containerCopy.onlineCopyEnabled.enablingAllVersionsAndDeletesChangeFeedSpinnerLabel)); await updateDatabaseAccount(sourceSubscriptionId, sourceResourceGroup, sourceAccountName, { properties: { enableAllVersionsAndDeletesChangeFeed: true, }, }); } - setLoaderMessage(ContainerCopyMessages.onlineCopyEnabled.enablingOnlineCopySpinnerLabel(sourceAccountName)); + setLoaderMessage( + t(Keys.containerCopy.onlineCopyEnabled.enablingOnlineCopySpinnerLabel, { accountName: sourceAccountName }), + ); await updateDatabaseAccount(sourceSubscriptionId, sourceResourceGroup, sourceAccountName, { properties: { capabilities: [...sourceAccountCapabilities, { name: CapabilityNames.EnableOnlineCopyFeature }], @@ -132,16 +134,16 @@ const OnlineCopyEnabled: React.FC = () => { - {ContainerCopyMessages.onlineCopyEnabled.description(source?.account?.name || "")}  - - {ContainerCopyMessages.onlineCopyEnabled.hrefText} + {t(Keys.containerCopy.onlineCopyEnabled.description, { accountName: source?.account?.name || "" })}  + + {t(Keys.containerCopy.onlineCopyEnabled.hrefText)} {showRefreshButton ? ( { ) : ( - {ContainerCopyMessages.pointInTimeRestore.tooltip.content}   + {t(Keys.containerCopy.pointInTimeRestore.tooltipContent)}   - {ContainerCopyMessages.pointInTimeRestore.tooltip.hrefText} + {t(Keys.containerCopy.pointInTimeRestore.tooltipHrefText)} ); @@ -119,9 +119,9 @@ const PointInTimeRestore: React.FC = () => { return ( - + - {ContainerCopyMessages.pointInTimeRestore.description(source.account?.name ?? "")} + {t(Keys.containerCopy.pointInTimeRestore.description, { accessName: source.account?.name ?? "" })} {tooltipContent && ( <> {" "} @@ -134,7 +134,7 @@ const PointInTimeRestore: React.FC = () => { @@ -142,7 +142,7 @@ const PointInTimeRestore: React.FC = () => { - A system-assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. Once enabled, you can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Microsoft Entra ID, so you don’t have to store any credentials in code. + A system-assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. Once enabled, you can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Microsoft Entra ID, so you don't have to store any credentials in code.   - A system-assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. Once enabled, you can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Microsoft Entra ID, so you don’t have to store any credentials in code. + A system-assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. Once enabled, you can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Microsoft Entra ID, so you don't have to store any credentials in code.   - A system-assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. Once enabled, you can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Microsoft Entra ID, so you don’t have to store any credentials in code. + A system-assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. Once enabled, you can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Microsoft Entra ID, so you don't have to store any credentials in code.   - Set the system-assigned managed identity as default for "undefined" by switching it on. + Set the system-assigned managed identity as default for "" by switching it on.  
{ @@ -57,7 +57,7 @@ const PERMISSION_SECTIONS_CONFIG: PermissionSectionConfig[] = [ }, { id: SECTION_IDS.defaultManagedIdentity, - title: ContainerCopyMessages.defaultManagedIdentity.title, + title: t(Keys.containerCopy.defaultManagedIdentity.title), Component: DefaultManagedIdentity, disabled: true, validate: (state: CopyJobContextState) => { @@ -67,7 +67,7 @@ const PERMISSION_SECTIONS_CONFIG: PermissionSectionConfig[] = [ }, { id: SECTION_IDS.readPermissionAssigned, - title: ContainerCopyMessages.readPermissionAssigned.title, + title: t(Keys.containerCopy.readPermissionAssigned.title), Component: AddReadPermissionToDefaultIdentity, disabled: true, validate: async (state: CopyJobContextState) => { @@ -95,7 +95,7 @@ const PERMISSION_SECTIONS_CONFIG: PermissionSectionConfig[] = [ const PERMISSION_SECTIONS_FOR_ONLINE_JOBS: PermissionSectionConfig[] = [ { id: SECTION_IDS.pointInTimeRestore, - title: ContainerCopyMessages.pointInTimeRestore.title, + title: t(Keys.containerCopy.pointInTimeRestore.title), Component: PointInTimeRestore, disabled: true, validate: (state: CopyJobContextState) => { @@ -105,7 +105,7 @@ const PERMISSION_SECTIONS_FOR_ONLINE_JOBS: PermissionSectionConfig[] = [ }, { id: SECTION_IDS.onlineCopyEnabled, - title: ContainerCopyMessages.onlineCopyEnabled.title, + title: t(Keys.containerCopy.onlineCopyEnabled.title), Component: OnlineCopyEnabled, disabled: true, validate: (state: CopyJobContextState) => { @@ -194,11 +194,11 @@ const usePermissionSections = (state: CopyJobContextState): PermissionGroupConfi if (crossAccountSections.length > 0) { groups.push({ id: "crossAccountConfigs", - title: ContainerCopyMessages.assignPermissions.crossAccountConfiguration.title, - description: ContainerCopyMessages.assignPermissions.crossAccountConfiguration.description( - sourceAccountName, - targetAccountName, - ), + title: t(Keys.containerCopy.assignPermissions.crossAccountConfiguration.title), + description: t(Keys.containerCopy.assignPermissions.crossAccountConfiguration.description, { + sourceAccount: sourceAccountName, + destinationAccount: targetAccountName, + }), sections: crossAccountSections, }); } @@ -206,8 +206,10 @@ const usePermissionSections = (state: CopyJobContextState): PermissionGroupConfi if (state.migrationType === CopyJobMigrationType.Online) { groups.push({ id: "onlineConfigs", - title: ContainerCopyMessages.assignPermissions.onlineConfiguration.title, - description: ContainerCopyMessages.assignPermissions.onlineConfiguration.description(sourceAccountName), + title: t(Keys.containerCopy.assignPermissions.onlineConfiguration.title), + description: t(Keys.containerCopy.assignPermissions.onlineConfiguration.description, { + accountName: sourceAccountName, + }), sections: [...PERMISSION_SECTIONS_FOR_ONLINE_JOBS], }); } diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.test.tsx index 597159be8..cd1bb48d5 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.test.tsx @@ -1,7 +1,7 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; +import { Keys, t } from "Localization"; import React from "react"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import PopoverMessage from "./PopoverContainer"; jest.mock("../../../../../Common/LoadingOverlay", () => { @@ -181,7 +181,7 @@ describe("PopoverMessage Component", () => { it("should use correct loading overlay label", () => { render(); const loadingOverlay = screen.getByTestId("loading-overlay"); - expect(loadingOverlay).toHaveAttribute("aria-label", ContainerCopyMessages.popoverOverlaySpinnerLabel); + expect(loadingOverlay).toHaveAttribute("aria-label", t(Keys.containerCopy.popoverOverlaySpinnerLabel)); }); }); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.tsx index 8ec30dedc..619a21e62 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/Components/PopoverContainer.tsx @@ -1,9 +1,9 @@ /* eslint-disable react/prop-types */ /* eslint-disable react/display-name */ import { DefaultButton, PrimaryButton, Stack, Text } from "@fluentui/react"; +import { Keys, t } from "Localization"; import React from "react"; import LoadingOverlay from "../../../../../Common/LoadingOverlay"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; interface PopoverContainerProps { isLoading?: boolean; @@ -22,7 +22,7 @@ const PopoverContainer: React.FC = React.memo( tokens={{ childrenGap: 20 }} style={{ maxWidth: 450 }} > - + {title} diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.test.tsx index 226ea15af..42f47f6cc 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.test.tsx @@ -4,8 +4,8 @@ import { CopyJobMigrationType } from "Explorer/ContainerCopy/Enums/CopyJobEnums" import { CopyJobContextProviderType } from "Explorer/ContainerCopy/Types/CopyJobTypes"; import Explorer from "Explorer/Explorer"; import { useSidePanel } from "hooks/useSidePanel"; +import { Keys, t } from "Localization"; import React from "react"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import AddCollectionPanelWrapper from "./AddCollectionPanelWrapper"; @@ -109,7 +109,7 @@ describe("AddCollectionPanelWrapper", () => { expect(container.querySelector(".addCollectionPanelWrapper")).toBeInTheDocument(); expect(container.querySelector(".addCollectionPanelHeader")).toBeInTheDocument(); expect(container.querySelector(".addCollectionPanelBody")).toBeInTheDocument(); - expect(screen.getByText(ContainerCopyMessages.createNewContainerSubHeading)).toBeInTheDocument(); + expect(screen.getByText(t(Keys.containerCopy.selectContainers.createNewContainerSubHeading))).toBeInTheDocument(); expect(screen.getByTestId("add-collection-panel")).toBeInTheDocument(); }); @@ -138,7 +138,7 @@ describe("AddCollectionPanelWrapper", () => { it("should set header text to create container heading on mount", () => { render(); - expect(mockSetHeaderText).toHaveBeenCalledWith(ContainerCopyMessages.createContainerHeading); + expect(mockSetHeaderText).toHaveBeenCalledWith(t(Keys.containerCopy.selectContainers.createContainerHeading)); }); it("should reset header text to create copy job panel title on unmount", () => { @@ -146,13 +146,13 @@ describe("AddCollectionPanelWrapper", () => { unmount(); - expect(mockSetHeaderText).toHaveBeenCalledWith(ContainerCopyMessages.createCopyJobPanelTitle); + expect(mockSetHeaderText).toHaveBeenCalledWith(t(Keys.containerCopy.createCopyJob.panelTitle)); }); it("should not change header text if already set correctly", () => { const modifiedSidePanelState = { ...mockSidePanelState, - headerText: ContainerCopyMessages.createContainerHeading, + headerText: t(Keys.containerCopy.selectContainers.createContainerHeading), }; mockUseSidePanel.getState = jest.fn().mockReturnValue(modifiedSidePanelState); @@ -245,10 +245,10 @@ describe("AddCollectionPanelWrapper", () => { describe("Component Lifecycle", () => { it("should properly cleanup on unmount", () => { const { unmount } = render(); - expect(mockSetHeaderText).toHaveBeenCalledWith(ContainerCopyMessages.createContainerHeading); + expect(mockSetHeaderText).toHaveBeenCalledWith(t(Keys.containerCopy.selectContainers.createContainerHeading)); mockSetHeaderText.mockClear(); unmount(); - expect(mockSetHeaderText).toHaveBeenCalledWith(ContainerCopyMessages.createCopyJobPanelTitle); + expect(mockSetHeaderText).toHaveBeenCalledWith(t(Keys.containerCopy.createCopyJob.panelTitle)); }); it("should re-render correctly when props change", () => { diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.tsx index a274c9bbc..2243efbff 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/CreateContainer/AddCollectionPanelWrapper.tsx @@ -2,9 +2,9 @@ import { Stack, Text } from "@fluentui/react"; import Explorer from "Explorer/Explorer"; import { useSidePanel } from "hooks/useSidePanel"; import { produce } from "immer"; +import { Keys, t } from "Localization"; import React, { useCallback, useEffect } from "react"; import { AddCollectionPanel } from "../../../../Panes/AddCollectionPanel/AddCollectionPanel"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; type AddCollectionPanelWrapperProps = { @@ -17,11 +17,11 @@ const AddCollectionPanelWrapper: React.FunctionComponent { const sidePanelStore = useSidePanel.getState(); - if (sidePanelStore.headerText !== ContainerCopyMessages.createContainerHeading) { - sidePanelStore.setHeaderText(ContainerCopyMessages.createContainerHeading); + if (sidePanelStore.headerText !== t(Keys.containerCopy.selectContainers.createContainerHeading)) { + sidePanelStore.setHeaderText(t(Keys.containerCopy.selectContainers.createContainerHeading)); } return () => { - sidePanelStore.setHeaderText(ContainerCopyMessages.createCopyJobPanelTitle); + sidePanelStore.setHeaderText(t(Keys.containerCopy.createCopyJob.panelTitle)); }; }, []); @@ -41,7 +41,7 @@ const AddCollectionPanelWrapper: React.FunctionComponent - {ContainerCopyMessages.createNewContainerSubHeading} + {t(Keys.containerCopy.selectContainers.createNewContainerSubHeading)} diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.test.tsx index adaea1915..c4141e725 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.test.tsx @@ -1,6 +1,7 @@ import "@testing-library/jest-dom"; import { fireEvent, render, waitFor } from "@testing-library/react"; import { Subscription } from "Contracts/DataModels"; +import { Keys, t } from "Localization"; import React from "react"; import { CopyJobContext } from "../../../Context/CopyJobContext"; import { CopyJobMigrationType } from "../../../Enums/CopyJobEnums"; @@ -350,7 +351,7 @@ describe("PreviewCopyJob", () => { expect(mockSetCopyJobState).toHaveBeenCalledWith(expect.any(Function)); }); - it("should display proper field labels from ContainerCopyMessages", () => { + it("should display proper field labels", () => { const mockContext = createMockContext(); const { getByText } = render( @@ -359,8 +360,8 @@ describe("PreviewCopyJob", () => { , ); - expect(getByText(/Job name/i)).toBeInTheDocument(); - expect(getByText(/Source subscription/i)).toBeInTheDocument(); - expect(getByText(/Source account/i)).toBeInTheDocument(); + expect(getByText(new RegExp(t(Keys.containerCopy.preview.jobNameLabel), "i"))).toBeInTheDocument(); + expect(getByText(new RegExp(t(Keys.containerCopy.preview.sourceSubscriptionLabel), "i"))).toBeInTheDocument(); + expect(getByText(new RegExp(t(Keys.containerCopy.preview.sourceAccountLabel), "i"))).toBeInTheDocument(); }); }); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.tsx index 84abc0ece..798d5f39d 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/PreviewCopyJob.tsx @@ -1,6 +1,6 @@ import { DetailsList, DetailsListLayoutMode, Stack, Text, TextField } from "@fluentui/react"; +import { Keys, t } from "Localization"; import React, { useEffect } from "react"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import { getDefaultJobName } from "../../../CopyJobUtils"; import FieldRow from "../Components/FieldRow"; @@ -32,17 +32,17 @@ const PreviewCopyJob: React.FC = () => { }; return ( - + - {ContainerCopyMessages.sourceSubscriptionLabel} + {t(Keys.containerCopy.preview.sourceSubscriptionLabel)} {copyJobState.source?.subscription?.displayName} - {ContainerCopyMessages.sourceAccountLabel} + {t(Keys.containerCopy.preview.sourceAccountLabel)} {copyJobState.source?.account?.name} diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/Utils/PreviewCopyJobUtils.ts b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/Utils/PreviewCopyJobUtils.ts index 814073767..623873a41 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/Utils/PreviewCopyJobUtils.ts +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/PreviewCopyJob/Utils/PreviewCopyJobUtils.ts @@ -1,5 +1,5 @@ import { IColumn } from "@fluentui/react"; -import ContainerCopyMessages from "../../../../ContainerCopyMessages"; +import { Keys, t } from "Localization"; const commonProps = { minWidth: 130, @@ -17,25 +17,25 @@ export const getPreviewCopyJobDetailsListColumns = (): IColumn[] => { return [ { key: "sourcedbname", - name: ContainerCopyMessages.sourceDatabaseLabel, + name: t(Keys.containerCopy.preview.sourceDatabaseLabel), fieldName: "sourceDatabaseName", ...commonProps, }, { key: "sourcecolname", - name: ContainerCopyMessages.sourceContainerLabel, + name: t(Keys.containerCopy.preview.sourceContainerLabel), fieldName: "sourceContainerName", ...commonProps, }, { key: "targetdbname", - name: ContainerCopyMessages.targetDatabaseLabel, + name: t(Keys.containerCopy.preview.targetDatabaseLabel), fieldName: "targetDatabaseName", ...commonProps, }, { key: "targetcolname", - name: ContainerCopyMessages.targetContainerLabel, + name: t(Keys.containerCopy.preview.targetContainerLabel), fieldName: "targetContainerName", ...commonProps, }, diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.test.tsx index d56031fed..255deea22 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.test.tsx @@ -1,11 +1,11 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { Keys, t } from "Localization"; import React from "react"; import { configContext, Platform } from "../../../../../../ConfigContext"; import { DatabaseAccount } from "../../../../../../Contracts/DataModels"; import * as useDatabaseAccountsHook from "../../../../../../hooks/useDatabaseAccounts"; import { apiType, userContext } from "../../../../../../UserContext"; -import ContainerCopyMessages from "../../../../ContainerCopyMessages"; import { CopyJobContext } from "../../../../Context/CopyJobContext"; import { CopyJobMigrationType } from "../../../../Enums/CopyJobEnums"; import { CopyJobContextProviderType, CopyJobContextState } from "../../../../Types/CopyJobTypes"; @@ -129,11 +129,11 @@ describe("AccountDropdown", () => { renderWithContext(); expect( - screen.getByText(`${ContainerCopyMessages.sourceAccountDropdownLabel}:`, { exact: true }), + screen.getByText(`${t(Keys.containerCopy.selectAccount.sourceAccountDropdownLabel)}:`, { exact: true }), ).toBeInTheDocument(); expect(screen.getByRole("combobox")).toHaveAttribute( "aria-label", - ContainerCopyMessages.sourceAccountDropdownLabel, + t(Keys.containerCopy.selectAccount.sourceAccountDropdownLabel), ); }); @@ -409,7 +409,7 @@ describe("AccountDropdown", () => { renderWithContext(); const dropdown = screen.getByRole("combobox"); - expect(dropdown).toHaveAttribute("aria-label", ContainerCopyMessages.sourceAccountDropdownLabel); + expect(dropdown).toHaveAttribute("aria-label", t(Keys.containerCopy.selectAccount.sourceAccountDropdownLabel)); }); it("should have required attribute", () => { diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.tsx index 7c19790e3..0762f83bc 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/AccountDropdown.tsx @@ -2,11 +2,11 @@ /* eslint-disable react/display-name */ import { Dropdown } from "@fluentui/react"; import { configContext, Platform } from "ConfigContext"; +import { Keys, t } from "Localization"; import React, { useEffect } from "react"; import { DatabaseAccount } from "../../../../../../Contracts/DataModels"; import { useDatabaseAccounts } from "../../../../../../hooks/useDatabaseAccounts"; import { apiType, userContext } from "../../../../../../UserContext"; -import ContainerCopyMessages from "../../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../../Context/CopyJobContext"; import FieldRow from "../../Components/FieldRow"; @@ -80,10 +80,10 @@ export const AccountDropdown: React.FC = () => { const selectedAccountId = normalizeAccountId(copyJobState?.source?.account?.id ?? ""); return ( - + { expect(screen.getByRole("radiogroup")).toBeInTheDocument(); const offlineRadio = screen.getByRole("radio", { - name: ContainerCopyMessages.migrationTypeOptions.offline.title, + name: t(Keys.containerCopy.migrationType.offline.title), }); - const onlineRadio = screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.online.title }); + const onlineRadio = screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.online.title) }); expect(offlineRadio).toBeInTheDocument(); expect(onlineRadio).toBeInTheDocument(); @@ -65,9 +65,9 @@ describe("MigrationType", () => { it("should render with online mode selected by default", () => { render(); - const onlineRadio = screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.online.title }); + const onlineRadio = screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.online.title) }); const offlineRadio = screen.getByRole("radio", { - name: ContainerCopyMessages.migrationTypeOptions.offline.title, + name: t(Keys.containerCopy.migrationType.offline.title), }); expect(onlineRadio).toBeChecked(); @@ -86,9 +86,9 @@ describe("MigrationType", () => { render(); const offlineRadio = screen.getByRole("radio", { - name: ContainerCopyMessages.migrationTypeOptions.offline.title, + name: t(Keys.containerCopy.migrationType.offline.title), }); - const onlineRadio = screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.online.title }); + const onlineRadio = screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.online.title) }); expect(offlineRadio).toBeChecked(); expect(onlineRadio).not.toBeChecked(); @@ -141,7 +141,7 @@ describe("MigrationType", () => { render(); const offlineRadio = screen.getByRole("radio", { - name: ContainerCopyMessages.migrationTypeOptions.offline.title, + name: t(Keys.containerCopy.migrationType.offline.title), }); fireEvent.click(offlineRadio); @@ -167,7 +167,7 @@ describe("MigrationType", () => { render(); - const onlineRadio = screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.online.title }); + const onlineRadio = screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.online.title) }); fireEvent.click(onlineRadio); expect(mockSetCopyJobState).toHaveBeenCalledWith(expect.any(Function)); @@ -198,11 +198,9 @@ describe("MigrationType", () => { render(); expect( - screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.offline.title }), - ).toBeInTheDocument(); - expect( - screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.online.title }), + screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.offline.title) }), ).toBeInTheDocument(); + expect(screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.online.title) })).toBeInTheDocument(); }); }); @@ -220,11 +218,9 @@ describe("MigrationType", () => { expect(container.querySelector("[data-test='migration-type']")).toBeInTheDocument(); expect( - screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.offline.title }), - ).toBeInTheDocument(); - expect( - screen.getByRole("radio", { name: ContainerCopyMessages.migrationTypeOptions.online.title }), + screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.offline.title) }), ).toBeInTheDocument(); + expect(screen.getByRole("radio", { name: t(Keys.containerCopy.migrationType.online.title) })).toBeInTheDocument(); }); it("should handle null copyJobState gracefully", () => { diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/MigrationType.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/MigrationType.tsx index 35c2d6a63..410debc61 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/MigrationType.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/MigrationType.tsx @@ -3,20 +3,20 @@ import { ChoiceGroup, IChoiceGroupOption, Stack, Text } from "@fluentui/react"; import MarkdownRender from "@nteract/markdown"; import { useCopyJobContext } from "Explorer/ContainerCopy/Context/CopyJobContext"; +import { Keys, t } from "Localization"; import React from "react"; -import ContainerCopyMessages from "../../../../ContainerCopyMessages"; import { CopyJobMigrationType } from "../../../../Enums/CopyJobEnums"; interface MigrationTypeProps {} const options: IChoiceGroupOption[] = [ { key: CopyJobMigrationType.Offline, - text: ContainerCopyMessages.migrationTypeOptions.offline.title, + text: t(Keys.containerCopy.migrationType.offline.title), styles: { root: { width: "33%" } }, }, { key: CopyJobMigrationType.Online, - text: ContainerCopyMessages.migrationTypeOptions.online.title, + text: t(Keys.containerCopy.migrationType.online.title), styles: { root: { width: "33%" } }, }, ]; @@ -47,8 +47,8 @@ export const MigrationType: React.FC = React.memo(() => { }; const selectedKey = copyJobState?.migrationType ?? ""; - const selectedKeyLowercase = selectedKey.toLowerCase() as keyof typeof ContainerCopyMessages.migrationTypeOptions; - const selectedKeyContent = ContainerCopyMessages.migrationTypeOptions[selectedKeyLowercase]; + const selectedKeyLowercase = selectedKey.toLowerCase() as keyof typeof Keys.containerCopy.migrationType; + const selectedKeyContent = Keys.containerCopy.migrationType[selectedKeyLowercase]; return ( @@ -68,7 +68,7 @@ export const MigrationType: React.FC = React.memo(() => { className="migrationTypeDescription" data-test={`migration-type-description-${selectedKeyLowercase}`} > - + )} diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.test.tsx index c9356b8e5..4f011ba04 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.test.tsx @@ -8,14 +8,9 @@ import { SubscriptionDropdown } from "./SubscriptionDropdown"; jest.mock("../../../../../../hooks/useSubscriptions"); jest.mock("../../../../../../UserContext"); -jest.mock("../../../../ContainerCopyMessages"); const mockUseSubscriptions = jest.requireMock("../../../../../../hooks/useSubscriptions").useSubscriptions; const mockUserContext = jest.requireMock("../../../../../../UserContext").userContext; -const mockContainerCopyMessages = jest.requireMock("../../../../ContainerCopyMessages").default; - -mockContainerCopyMessages.subscriptionDropdownLabel = "Subscription"; -mockContainerCopyMessages.subscriptionDropdownPlaceholder = "Select a subscription"; describe("SubscriptionDropdown", () => { let mockExplorer: Explorer; diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.tsx index 9d38c2f57..15efa5d50 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/Components/SubscriptionDropdown.tsx @@ -1,11 +1,11 @@ /* eslint-disable react/prop-types */ /* eslint-disable react/display-name */ import { Dropdown } from "@fluentui/react"; +import { Keys, t } from "Localization"; import React, { useEffect } from "react"; import { Subscription } from "../../../../../../Contracts/DataModels"; import { useSubscriptions } from "../../../../../../hooks/useSubscriptions"; import { userContext } from "../../../../../../UserContext"; -import ContainerCopyMessages from "../../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../../Context/CopyJobContext"; import FieldRow from "../../Components/FieldRow"; @@ -64,10 +64,10 @@ export const SubscriptionDropdown: React.FC = React.m const selectedSubscriptionId = copyJobState?.source?.subscription?.subscriptionId; return ( - + { return ( - {ContainerCopyMessages.selectAccountDescription} + {t(Keys.containerCopy.selectAccount.description)} diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.test.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.test.tsx index 5b7a6b13f..1f51304c3 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.test.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.test.tsx @@ -1,5 +1,6 @@ import "@testing-library/jest-dom"; import { render, screen } from "@testing-library/react"; +import { Keys, t } from "Localization"; import { DatabaseModel } from "Contracts/DataModels"; import React from "react"; import Explorer from "../../../../../Explorer/Explorer"; @@ -15,15 +16,6 @@ jest.mock("../../../../../hooks/useDataContainers", () => ({ useDataContainers: jest.fn(), })); -jest.mock("../../../ContainerCopyMessages", () => ({ - __esModule: true, - default: { - selectSourceAndTargetContainersDescription: "Select source and target containers for migration", - sourceContainerSubHeading: "Source Container", - targetContainerSubHeading: "Target Container", - }, -})); - jest.mock("./Events/DropDownChangeHandler", () => ({ dropDownChangeHandler: jest.fn(() => () => jest.fn()), })); @@ -124,22 +116,26 @@ describe("SelectSourceAndTargetContainers", () => { describe("Component Rendering", () => { it("should render without crashing", () => { renderWithContext(); - expect(screen.getByText("Select source and target containers for migration")).toBeInTheDocument(); + expect( + screen.getByText("Please select a source container and a destination container to copy to."), + ).toBeInTheDocument(); }); it("should render description text", () => { renderWithContext(); - expect(screen.getByText("Select source and target containers for migration")).toBeInTheDocument(); + expect( + screen.getByText("Please select a source container and a destination container to copy to."), + ).toBeInTheDocument(); }); it("should render source container section", () => { renderWithContext(); - expect(screen.getByText("Source Container")).toBeInTheDocument(); + expect(screen.getByText("Source container")).toBeInTheDocument(); }); it("should render target container section", () => { renderWithContext(); - expect(screen.getByText("Target Container")).toBeInTheDocument(); + expect(screen.getByText("Destination container")).toBeInTheDocument(); }); it("should return null when source is not available", () => { @@ -238,14 +234,14 @@ describe("SelectSourceAndTargetContainers", () => { describe("Component Props", () => { it("should pass showAddCollectionPanel to DatabaseContainerSection", () => { renderWithContext(); - expect(screen.getByText("Target Container")).toBeInTheDocument(); + expect(screen.getByText("Destination container")).toBeInTheDocument(); }); it("should render without showAddCollectionPanel prop", () => { renderWithContext(); - expect(screen.getByText("Source Container")).toBeInTheDocument(); - expect(screen.getByText("Target Container")).toBeInTheDocument(); + expect(screen.getByText("Source container")).toBeInTheDocument(); + expect(screen.getByText("Destination container")).toBeInTheDocument(); }); }); @@ -310,13 +306,13 @@ describe("SelectSourceAndTargetContainers", () => { it("should pass correct props to source DatabaseContainerSection", () => { renderWithContext(); - expect(screen.getByText("Source Container")).toBeInTheDocument(); + expect(screen.getByText("Source container")).toBeInTheDocument(); }); it("should pass correct props to target DatabaseContainerSection", () => { renderWithContext(); - expect(screen.getByText("Target Container")).toBeInTheDocument(); + expect(screen.getByText("Destination container")).toBeInTheDocument(); }); it("should disable source container dropdown when no database is selected", () => { @@ -329,7 +325,7 @@ describe("SelectSourceAndTargetContainers", () => { } as ReturnType); renderWithContext(); - expect(screen.getByText("Source Container")).toBeInTheDocument(); + expect(screen.getByText("Source container")).toBeInTheDocument(); }); it("should disable target container dropdown when no database is selected", () => { @@ -342,7 +338,7 @@ describe("SelectSourceAndTargetContainers", () => { } as ReturnType); renderWithContext(); - expect(screen.getByText("Target Container")).toBeInTheDocument(); + expect(screen.getByText("Destination container")).toBeInTheDocument(); }); }); @@ -353,7 +349,9 @@ describe("SelectSourceAndTargetContainers", () => { renderWithContext(); - expect(screen.getByText("Select source and target containers for migration")).toBeInTheDocument(); + expect( + screen.getByText("Please select a source container and a destination container to copy to."), + ).toBeInTheDocument(); }); it("should handle hooks throwing errors gracefully", () => { @@ -421,7 +419,9 @@ describe("SelectSourceAndTargetContainers", () => { it("should apply correct spacing tokens", () => { renderWithContext(); - expect(screen.getByText("Select source and target containers for migration")).toBeInTheDocument(); + expect( + screen.getByText("Please select a source container and a destination container to copy to."), + ).toBeInTheDocument(); }); }); @@ -429,9 +429,9 @@ describe("SelectSourceAndTargetContainers", () => { it("should render description, source section, and target section in correct order", () => { renderWithContext(); - const description = screen.getByText("Select source and target containers for migration"); - const sourceSection = screen.getByText("Source Container"); - const targetSection = screen.getByText("Target Container"); + const description = screen.getByText("Please select a source container and a destination container to copy to."); + const sourceSection = screen.getByText("Source container"); + const targetSection = screen.getByText("Destination container"); expect(description).toBeInTheDocument(); expect(sourceSection).toBeInTheDocument(); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.tsx index 6a0ad3715..368976d33 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/SelectSourceAndTargetContainers.tsx @@ -1,9 +1,9 @@ import { Stack } from "@fluentui/react"; import { DatabaseModel } from "Contracts/DataModels"; +import { Keys, t } from "Localization"; import React from "react"; import { useDatabases } from "../../../../../hooks/useDatabases"; import { useDataContainers } from "../../../../../hooks/useDataContainers"; -import ContainerCopyMessages from "../../../ContainerCopyMessages"; import { useCopyJobContext } from "../../../Context/CopyJobContext"; import { DatabaseContainerSection } from "./components/DatabaseContainerSection"; import { dropDownChangeHandler } from "./Events/DropDownChangeHandler"; @@ -52,9 +52,9 @@ const SelectSourceAndTargetContainers = ({ showAddCollectionPanel }: SelectSourc className="selectSourceAndTargetContainers" tokens={{ childrenGap: 25 }} > - {ContainerCopyMessages.selectSourceAndTargetContainersDescription} + {t(Keys.containerCopy.selectContainers.description)} { render(); const databaseDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.databaseDropdownLabel, + name: t(Keys.containerCopy.selectContainers.databaseDropdownLabel), }); expect(databaseDropdown).toBeInTheDocument(); - expect(databaseDropdown).toHaveAttribute("aria-label", ContainerCopyMessages.databaseDropdownLabel); + expect(databaseDropdown).toHaveAttribute( + "aria-label", + t(Keys.containerCopy.selectContainers.databaseDropdownLabel), + ); expect(databaseDropdown).not.toBeDisabled(); }); @@ -72,30 +75,35 @@ describe("DatabaseContainerSection", () => { render(); const containerDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.containerDropdownLabel, + name: t(Keys.containerCopy.selectContainers.containerDropdownLabel), }); expect(containerDropdown).toBeInTheDocument(); - expect(containerDropdown).toHaveAttribute("aria-label", ContainerCopyMessages.containerDropdownLabel); + expect(containerDropdown).toHaveAttribute( + "aria-label", + t(Keys.containerCopy.selectContainers.containerDropdownLabel), + ); expect(containerDropdown).not.toBeDisabled(); }); it("renders database label correctly", () => { render(); - expect(screen.getByText(`${ContainerCopyMessages.databaseDropdownLabel}:`)).toBeInTheDocument(); + expect(screen.getByText(`${t(Keys.containerCopy.selectContainers.databaseDropdownLabel)}:`)).toBeInTheDocument(); }); it("renders container label correctly", () => { render(); - expect(screen.getByText(`${ContainerCopyMessages.containerDropdownLabel}:`)).toBeInTheDocument(); + expect(screen.getByText(`${t(Keys.containerCopy.selectContainers.containerDropdownLabel)}:`)).toBeInTheDocument(); }); it("does not render create container button when handleOnDemandCreateContainer is not provided", () => { render(); - expect(screen.queryByText(ContainerCopyMessages.createContainerButtonLabel)).not.toBeInTheDocument(); + expect( + screen.queryByText(t(Keys.containerCopy.selectContainers.createContainerButtonLabel)), + ).not.toBeInTheDocument(); }); it("renders create container button when handleOnDemandCreateContainer is provided", () => { @@ -107,7 +115,7 @@ describe("DatabaseContainerSection", () => { const createButton = container.querySelector(".create-container-link-btn"); expect(createButton).toBeInTheDocument(); - expect(createButton).toHaveTextContent(ContainerCopyMessages.createContainerButtonLabel); + expect(createButton).toHaveTextContent(t(Keys.containerCopy.selectContainers.createContainerButtonLabel)); }); }); @@ -121,7 +129,7 @@ describe("DatabaseContainerSection", () => { render(); const databaseDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.databaseDropdownLabel, + name: t(Keys.containerCopy.selectContainers.databaseDropdownLabel), }); expect(databaseDropdown).toHaveAttribute("aria-disabled", "true"); @@ -136,7 +144,7 @@ describe("DatabaseContainerSection", () => { render(); const containerDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.containerDropdownLabel, + name: t(Keys.containerCopy.selectContainers.containerDropdownLabel), }); expect(containerDropdown).toHaveAttribute("aria-disabled", "true"); @@ -152,10 +160,10 @@ describe("DatabaseContainerSection", () => { render(); const databaseDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.databaseDropdownLabel, + name: t(Keys.containerCopy.selectContainers.databaseDropdownLabel), }); const containerDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.containerDropdownLabel, + name: t(Keys.containerCopy.selectContainers.containerDropdownLabel), }); expect(databaseDropdown).not.toHaveAttribute("aria-disabled", "true"); @@ -167,21 +175,27 @@ describe("DatabaseContainerSection", () => { it("calls databaseOnChange when database dropdown selection changes", () => { render(); const databaseDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.databaseDropdownLabel, + name: t(Keys.containerCopy.selectContainers.databaseDropdownLabel), }); fireEvent.click(databaseDropdown); - expect(databaseDropdown).toHaveAttribute("aria-label", ContainerCopyMessages.databaseDropdownLabel); + expect(databaseDropdown).toHaveAttribute( + "aria-label", + t(Keys.containerCopy.selectContainers.databaseDropdownLabel), + ); }); it("calls containerOnChange when container dropdown selection changes", () => { render(); const containerDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.containerDropdownLabel, + name: t(Keys.containerCopy.selectContainers.containerDropdownLabel), }); fireEvent.click(containerDropdown); - expect(containerDropdown).toHaveAttribute("aria-label", ContainerCopyMessages.containerDropdownLabel); + expect(containerDropdown).toHaveAttribute( + "aria-label", + t(Keys.containerCopy.selectContainers.containerDropdownLabel), + ); }); it("calls handleOnDemandCreateContainer when create container button is clicked", () => { @@ -192,7 +206,7 @@ describe("DatabaseContainerSection", () => { render(); - const createButton = screen.getByText(ContainerCopyMessages.createContainerButtonLabel); + const createButton = screen.getByText(t(Keys.containerCopy.selectContainers.createContainerButtonLabel)); fireEvent.click(createButton); expect(mockHandleOnDemandCreateContainer).toHaveBeenCalledTimes(1); @@ -235,10 +249,10 @@ describe("DatabaseContainerSection", () => { render(); const databaseDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.databaseDropdownLabel, + name: t(Keys.containerCopy.selectContainers.databaseDropdownLabel), }); const containerDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.containerDropdownLabel, + name: t(Keys.containerCopy.selectContainers.containerDropdownLabel), }); expect(databaseDropdown).toBeInTheDocument(); @@ -251,24 +265,30 @@ describe("DatabaseContainerSection", () => { render(); const databaseDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.databaseDropdownLabel, + name: t(Keys.containerCopy.selectContainers.databaseDropdownLabel), }); const containerDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.containerDropdownLabel, + name: t(Keys.containerCopy.selectContainers.containerDropdownLabel), }); - expect(databaseDropdown).toHaveAttribute("aria-label", ContainerCopyMessages.databaseDropdownLabel); - expect(containerDropdown).toHaveAttribute("aria-label", ContainerCopyMessages.containerDropdownLabel); + expect(databaseDropdown).toHaveAttribute( + "aria-label", + t(Keys.containerCopy.selectContainers.databaseDropdownLabel), + ); + expect(containerDropdown).toHaveAttribute( + "aria-label", + t(Keys.containerCopy.selectContainers.containerDropdownLabel), + ); }); it("has proper required attributes for dropdowns", () => { render(); const databaseDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.databaseDropdownLabel, + name: t(Keys.containerCopy.selectContainers.databaseDropdownLabel), }); const containerDropdown = screen.getByRole("combobox", { - name: ContainerCopyMessages.containerDropdownLabel, + name: t(Keys.containerCopy.selectContainers.containerDropdownLabel), }); expect(databaseDropdown).toHaveAttribute("aria-required", "true"); @@ -278,8 +298,8 @@ describe("DatabaseContainerSection", () => { it("maintains proper label associations", () => { render(); - expect(screen.getByText(`${ContainerCopyMessages.databaseDropdownLabel}:`)).toBeInTheDocument(); - expect(screen.getByText(`${ContainerCopyMessages.containerDropdownLabel}:`)).toBeInTheDocument(); + expect(screen.getByText(`${t(Keys.containerCopy.selectContainers.databaseDropdownLabel)}:`)).toBeInTheDocument(); + expect(screen.getByText(`${t(Keys.containerCopy.selectContainers.containerDropdownLabel)}:`)).toBeInTheDocument(); }); }); @@ -299,7 +319,9 @@ describe("DatabaseContainerSection", () => { render(); expect(screen.getByText("Test Heading")).toBeInTheDocument(); - expect(screen.queryByText(ContainerCopyMessages.createContainerButtonLabel)).not.toBeInTheDocument(); + expect( + screen.queryByText(t(Keys.containerCopy.selectContainers.createContainerButtonLabel)), + ).not.toBeInTheDocument(); }); it("handles empty string selections", () => { @@ -366,7 +388,7 @@ describe("DatabaseContainerSection", () => { const { container } = render(); - const createButton = screen.getByText(ContainerCopyMessages.createContainerButtonLabel); + const createButton = screen.getByText(t(Keys.containerCopy.selectContainers.createContainerButtonLabel)); expect(createButton).toBeInTheDocument(); const containerSection = container.querySelector(".databaseContainerSection"); @@ -381,7 +403,7 @@ describe("DatabaseContainerSection", () => { render(); - expect(screen.getByText(ContainerCopyMessages.createContainerButtonLabel)).toBeInTheDocument(); + expect(screen.getByText(t(Keys.containerCopy.selectContainers.createContainerButtonLabel))).toBeInTheDocument(); }); }); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/components/DatabaseContainerSection.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/components/DatabaseContainerSection.tsx index ef0833ee1..7bab796fa 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/components/DatabaseContainerSection.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/components/DatabaseContainerSection.tsx @@ -1,6 +1,6 @@ import { ActionButton, Dropdown, Stack } from "@fluentui/react"; +import { Keys, t } from "Localization"; import React from "react"; -import ContainerCopyMessages from "../../../../ContainerCopyMessages"; import { DatabaseContainerSectionProps } from "../../../../Types/CopyJobTypes"; import FieldRow from "../../Components/FieldRow"; @@ -19,10 +19,10 @@ export const DatabaseContainerSection = ({ }: DatabaseContainerSectionProps) => ( - + - + handleOnDemandCreateContainer()} > - {ContainerCopyMessages.createContainerButtonLabel} + {t(Keys.containerCopy.selectContainers.createContainerButtonLabel)} )} diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.test.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.test.tsx index a0d6035a4..219c9bc44 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.test.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.test.tsx @@ -20,28 +20,6 @@ jest.mock("../../../Controls/Dialog", () => ({ }, })); -jest.mock("../../ContainerCopyMessages", () => ({ - __esModule: true, - default: { - MonitorJobs: { - Columns: { - actions: "Actions", - }, - Actions: { - pause: "Pause", - resume: "Resume", - cancel: "Cancel", - complete: "Complete", - }, - dialog: { - heading: "Confirm Action", - confirmButtonText: "Confirm", - cancelButtonText: "Cancel", - }, - }, - }, -})); - describe("CopyJobActionMenu", () => { const createMockJob = (overrides: Partial = {}): CopyJobType => ({ @@ -301,7 +279,7 @@ describe("CopyJobActionMenu", () => { fireEvent.click(cancelButton); expect(mockShowOkCancelModalDialog).toHaveBeenCalledWith( - "Confirm Action", + "", null, "Confirm", expect.any(Function), @@ -358,7 +336,7 @@ describe("CopyJobActionMenu", () => { fireEvent.click(completeButton); expect(mockShowOkCancelModalDialog).toHaveBeenCalledWith( - "Confirm Action", + "", null, "Confirm", expect.any(Function), @@ -402,7 +380,7 @@ describe("CopyJobActionMenu", () => { fireEvent.click(cancelButton); expect(mockShowOkCancelModalDialog).toHaveBeenCalledWith( - "Confirm Action", + "", null, "Confirm", expect.any(Function), @@ -433,7 +411,7 @@ describe("CopyJobActionMenu", () => { fireEvent.click(completeButton); expect(mockShowOkCancelModalDialog).toHaveBeenCalledWith( - "Confirm Action", + "", null, "Confirm", expect.any(Function), @@ -849,7 +827,7 @@ describe("CopyJobActionMenu", () => { fireEvent.click(cancelButton); expect(mockShowOkCancelModalDialog).toHaveBeenCalledWith( - "Confirm Action", // title + "", // title null, // subText "Confirm", // confirmLabel expect.any(Function), // onOk diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.tsx index 682e20c9a..df37eb628 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobActionMenu.tsx @@ -1,7 +1,7 @@ import { DirectionalHint, IconButton, IContextualMenuProps, Stack } from "@fluentui/react"; import React from "react"; import { useDialog } from "../../../Controls/Dialog"; -import ContainerCopyMessages from "../../ContainerCopyMessages"; +import { Keys, t } from "Localization"; import { CopyJobActions, CopyJobMigrationType, CopyJobStatusType } from "../../Enums/CopyJobEnums"; import { CopyJobType, HandleJobActionClickType } from "../../Types/CopyJobTypes"; @@ -49,11 +49,11 @@ const CopyJobActionMenu: React.FC = ({ job, handleClick useDialog .getState() .showOkCancelModalDialog( - ContainerCopyMessages.MonitorJobs.dialog.heading, + "", null, - ContainerCopyMessages.MonitorJobs.dialog.confirmButtonText, + t(Keys.common.confirm), () => handleClick(job, action, setUpdatingJobAction), - ContainerCopyMessages.MonitorJobs.dialog.cancelButtonText, + t(Keys.common.cancel), null, action in dialogBody ? dialogBody[action as keyof typeof dialogBody](job.Name) : null, ); @@ -65,21 +65,21 @@ const CopyJobActionMenu: React.FC = ({ job, handleClick const baseItems = [ { key: CopyJobActions.pause, - text: ContainerCopyMessages.MonitorJobs.Actions.pause, + text: t(Keys.containerCopy.monitorJobs.actions.pause), iconProps: { iconName: "Pause" }, onClick: () => handleClick(job, CopyJobActions.pause, setUpdatingJobAction), disabled: isThisJobUpdating, }, { key: CopyJobActions.cancel, - text: ContainerCopyMessages.MonitorJobs.Actions.cancel, + text: t(Keys.common.cancel), iconProps: { iconName: "Cancel" }, onClick: () => showActionConfirmationDialog(job, CopyJobActions.cancel), disabled: isThisJobUpdating, }, { key: CopyJobActions.resume, - text: ContainerCopyMessages.MonitorJobs.Actions.resume, + text: t(Keys.containerCopy.monitorJobs.actions.resume), iconProps: { iconName: "Play" }, onClick: () => handleClick(job, CopyJobActions.resume, setUpdatingJobAction), disabled: isThisJobUpdating, @@ -101,7 +101,7 @@ const CopyJobActionMenu: React.FC = ({ job, handleClick if ((job.Mode ?? "").toLowerCase() === CopyJobMigrationType.Online) { filteredItems.push({ key: CopyJobActions.complete, - text: ContainerCopyMessages.MonitorJobs.Actions.complete, + text: t(Keys.containerCopy.monitorJobs.actions.complete), iconProps: { iconName: "CheckMark" }, onClick: () => showActionConfirmationDialog(job, CopyJobActions.complete), disabled: isThisJobUpdating, @@ -124,8 +124,8 @@ const CopyJobActionMenu: React.FC = ({ job, handleClick iconProps={{ iconName: "More", styles: { root: { fontSize: "20px", fontWeight: "bold" } } }} menuProps={{ items: getMenuItems(), directionalHint: DirectionalHint.leftTopEdge, directionalHintFixed: false }} menuIconProps={{ iconName: "", className: "hidden" }} - ariaLabel={ContainerCopyMessages.MonitorJobs.Columns.actions} - title={ContainerCopyMessages.MonitorJobs.Columns.actions} + ariaLabel={t(Keys.containerCopy.monitorJobs.columns.actions)} + title={t(Keys.containerCopy.monitorJobs.columns.actions)} /> ); }; diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.test.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.test.tsx index 0dc436e15..70a380578 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.test.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.test.tsx @@ -1,8 +1,8 @@ import { IColumn } from "@fluentui/react"; import "@testing-library/jest-dom"; import { render } from "@testing-library/react"; +import { Keys, t } from "Localization"; import React from "react"; -import ContainerCopyMessages from "../../ContainerCopyMessages"; import { CopyJobStatusType } from "../../Enums/CopyJobEnums"; import { CopyJobType, HandleJobActionClickType } from "../../Types/CopyJobTypes"; import { getColumns } from "./CopyJobColumns"; @@ -79,14 +79,14 @@ describe("CopyJobColumns", () => { expect(actualKeys).toEqual(expectedKeys); }); - it("should have correct column names from ContainerCopyMessages", () => { + it("should have correct column names from i18n", () => { const columns = getColumns(mockHandleSort, mockHandleActionClick, undefined, false); - expect(columns[0].name).toBe(ContainerCopyMessages.MonitorJobs.Columns.lastUpdatedTime); - expect(columns[1].name).toBe(ContainerCopyMessages.MonitorJobs.Columns.name); - expect(columns[2].name).toBe(ContainerCopyMessages.MonitorJobs.Columns.mode); - expect(columns[3].name).toBe(ContainerCopyMessages.MonitorJobs.Columns.completionPercentage); - expect(columns[4].name).toBe(ContainerCopyMessages.MonitorJobs.Columns.status); + expect(columns[0].name).toBe(t(Keys.containerCopy.monitorJobs.columns.lastUpdatedTime)); + expect(columns[1].name).toBe(t(Keys.containerCopy.monitorJobs.columns.name)); + expect(columns[2].name).toBe(t(Keys.containerCopy.monitorJobs.columns.mode)); + expect(columns[3].name).toBe(t(Keys.containerCopy.monitorJobs.columns.completionPercentage)); + expect(columns[4].name).toBe(t(Keys.containerCopy.monitorJobs.columns.status)); expect(columns[5].name).toBe(""); }); diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.tsx index a1c7e1417..ec139d791 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobColumns.tsx @@ -1,6 +1,6 @@ import { IColumn } from "@fluentui/react"; import React from "react"; -import ContainerCopyMessages from "../../ContainerCopyMessages"; +import { Keys, t } from "Localization"; import { CopyJobType, HandleJobActionClickType } from "../../Types/CopyJobTypes"; import CopyJobActionMenu from "./CopyJobActionMenu"; import CopyJobStatusWithIcon from "./CopyJobStatusWithIcon"; @@ -13,7 +13,7 @@ export const getColumns = ( ): IColumn[] => [ { key: "LastUpdatedTime", - name: ContainerCopyMessages.MonitorJobs.Columns.lastUpdatedTime, + name: t(Keys.containerCopy.monitorJobs.columns.lastUpdatedTime), fieldName: "LastUpdatedTime", minWidth: 140, maxWidth: 300, @@ -24,7 +24,7 @@ export const getColumns = ( }, { key: "Name", - name: ContainerCopyMessages.MonitorJobs.Columns.name, + name: t(Keys.containerCopy.monitorJobs.columns.name), fieldName: "Name", minWidth: 140, maxWidth: 300, @@ -36,7 +36,7 @@ export const getColumns = ( }, { key: "Mode", - name: ContainerCopyMessages.MonitorJobs.Columns.mode, + name: t(Keys.containerCopy.monitorJobs.columns.mode), fieldName: "Mode", minWidth: 90, maxWidth: 200, @@ -47,7 +47,7 @@ export const getColumns = ( }, { key: "CompletionPercentage", - name: ContainerCopyMessages.MonitorJobs.Columns.completionPercentage, + name: t(Keys.containerCopy.monitorJobs.columns.completionPercentage), fieldName: "CompletionPercentage", minWidth: 110, maxWidth: 200, @@ -59,7 +59,7 @@ export const getColumns = ( }, { key: "CopyJobStatus", - name: ContainerCopyMessages.MonitorJobs.Columns.status, + name: t(Keys.containerCopy.monitorJobs.columns.status), fieldName: "Status", minWidth: 130, maxWidth: 200, diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.test.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.test.tsx index 1aa57ebca..05b33ea22 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.test.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.test.tsx @@ -13,22 +13,6 @@ jest.mock("./CopyJobStatusWithIcon", () => { return MockCopyJobStatusWithIcon; }); -jest.mock("../../ContainerCopyMessages", () => ({ - errorTitle: "Error Details", - sourceDatabaseLabel: "Source Database", - sourceContainerLabel: "Source Container", - targetDatabaseLabel: "Destination Database", - targetContainerLabel: "Destination Container", - sourceAccountLabel: "Source Account", - MonitorJobs: { - Columns: { - lastUpdatedTime: "Date & time", - status: "Status", - mode: "Mode", - }, - }, -})); - describe("CopyJobDetails", () => { const mockBasicJob: CopyJobType = { ID: "test-job-1", @@ -102,7 +86,7 @@ describe("CopyJobDetails", () => { expect(screen.getByText("Date & time")).toBeInTheDocument(); expect(screen.getByText("2024-01-01T10:00:00Z")).toBeInTheDocument(); - expect(screen.getByText("Source Account")).toBeInTheDocument(); + expect(screen.getByText("Source account")).toBeInTheDocument(); expect(screen.getByText("sourceAccount")).toBeInTheDocument(); expect(screen.getByText("Mode")).toBeInTheDocument(); @@ -322,7 +306,7 @@ describe("CopyJobDetails", () => { render(); const dateTimeHeading = screen.getByText("Date & time"); - const sourceAccountHeading = screen.getByText("Source Account"); + const sourceAccountHeading = screen.getByText("Source account"); const modeHeading = screen.getByText("Mode"); expect(dateTimeHeading).toHaveClass("bold"); diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.tsx index 63c7fcf46..4297605fb 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobDetails.tsx @@ -1,7 +1,7 @@ import { DetailsList, DetailsListLayoutMode, IColumn, Stack, Text } from "@fluentui/react"; import React, { memo } from "react"; import { useThemeStore } from "../../../../hooks/useTheme"; -import ContainerCopyMessages from "../../ContainerCopyMessages"; +import { Keys, t } from "Localization"; import { CopyJobStatusType } from "../../Enums/CopyJobEnums"; import { CopyJobType } from "../../Types/CopyJobTypes"; import CopyJobStatusWithIcon from "./CopyJobStatusWithIcon"; @@ -31,31 +31,31 @@ const getCopyJobDetailsListColumns = (): IColumn[] => { return [ { key: "sourcedbcol", - name: ContainerCopyMessages.sourceDatabaseLabel, + name: t(Keys.containerCopy.preview.sourceDatabaseLabel), fieldName: "sourceDatabaseName", ...commonProps, }, { key: "sourcecol", - name: ContainerCopyMessages.sourceContainerLabel, + name: t(Keys.containerCopy.preview.sourceContainerLabel), fieldName: "sourceContainerName", ...commonProps, }, { key: "targetdbcol", - name: ContainerCopyMessages.targetDatabaseLabel, + name: t(Keys.containerCopy.preview.targetDatabaseLabel), fieldName: "targetDatabaseName", ...commonProps, }, { key: "targetcol", - name: ContainerCopyMessages.targetContainerLabel, + name: t(Keys.containerCopy.preview.targetContainerLabel), fieldName: "targetContainerName", ...commonProps, }, { key: "statuscol", - name: ContainerCopyMessages.MonitorJobs.Columns.status, + name: t(Keys.containerCopy.monitorJobs.columns.status), fieldName: "jobStatus", onRender: ({ jobStatus }: { jobStatus: CopyJobStatusType }) => , ...commonProps, @@ -92,7 +92,7 @@ const CopyJobDetails: React.FC = ({ job }) => { {job.Error ? ( - {ContainerCopyMessages.errorTitle} + {t(Keys.containerCopy.jobDetails.errorTitle)} {job.Error.message} @@ -102,15 +102,15 @@ const CopyJobDetails: React.FC = ({ job }) => { - {ContainerCopyMessages.MonitorJobs.Columns.lastUpdatedTime} + {t(Keys.containerCopy.monitorJobs.columns.lastUpdatedTime)} {job.LastUpdatedTime} - {ContainerCopyMessages.sourceAccountLabel} + {t(Keys.containerCopy.preview.sourceAccountLabel)} {job.Source?.remoteAccountName} - {ContainerCopyMessages.MonitorJobs.Columns.mode} + {t(Keys.containerCopy.monitorJobs.columns.mode)} {job.Mode} diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobStatusWithIcon.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobStatusWithIcon.tsx index 1fb996639..8126dd89d 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobStatusWithIcon.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobStatusWithIcon.tsx @@ -1,7 +1,7 @@ import { FontIcon, mergeStyles, Spinner, SpinnerSize, Stack, Text } from "@fluentui/react"; import PropTypes from "prop-types"; import React from "react"; -import ContainerCopyMessages from "../../ContainerCopyMessages"; +import { Keys, t } from "Localization"; import { CopyJobStatusType } from "../../Enums/CopyJobEnums"; const iconClass = mergeStyles({ @@ -30,12 +30,25 @@ const statusIconColors: Partial> = { [CopyJobStatusType.Paused]: "var(--colorBrandForeground1)", }; +const statusKeyMap: Record = { + [CopyJobStatusType.Pending]: Keys.containerCopy.monitorJobs.status.pending, + [CopyJobStatusType.InProgress]: Keys.containerCopy.monitorJobs.status.inProgress, + [CopyJobStatusType.Running]: Keys.containerCopy.monitorJobs.status.running, + [CopyJobStatusType.Partitioning]: Keys.containerCopy.monitorJobs.status.partitioning, + [CopyJobStatusType.Paused]: Keys.containerCopy.monitorJobs.status.paused, + [CopyJobStatusType.Completed]: Keys.containerCopy.monitorJobs.status.completed, + [CopyJobStatusType.Failed]: Keys.containerCopy.monitorJobs.status.failed, + [CopyJobStatusType.Faulted]: Keys.containerCopy.monitorJobs.status.faulted, + [CopyJobStatusType.Skipped]: Keys.containerCopy.monitorJobs.status.skipped, + [CopyJobStatusType.Cancelled]: Keys.containerCopy.monitorJobs.status.cancelled, +}; + export interface CopyJobStatusWithIconProps { status: CopyJobStatusType; } const CopyJobStatusWithIcon: React.FC = React.memo(({ status }) => { - const statusText = ContainerCopyMessages.MonitorJobs.Status[status] || "Unknown"; + const statusText = statusKeyMap[status] ? t(statusKeyMap[status] as Parameters[0]) : "Unknown"; const isSpinnerStatus = [ CopyJobStatusType.Running, diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.test.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.test.tsx index d81f64289..7e4181e04 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.test.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.test.tsx @@ -3,9 +3,9 @@ jest.mock("../../Actions/CopyJobActions"); import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; import Explorer from "Explorer/Explorer"; +import { Keys, t } from "Localization"; import React from "react"; import * as Actions from "../../Actions/CopyJobActions"; -import ContainerCopyMessages from "../../ContainerCopyMessages"; import CopyJobsNotFound from "./CopyJobs.NotFound"; describe("CopyJobsNotFound", () => { @@ -22,10 +22,10 @@ describe("CopyJobsNotFound", () => { const image = container.querySelector(".notFoundContainer .ms-Image"); expect(image).toBeInTheDocument(); expect(image).toHaveAttribute("style", "width: 100px; height: 100px;"); - expect(getByText(ContainerCopyMessages.noCopyJobsTitle)).toBeInTheDocument(); + expect(getByText(t(Keys.containerCopy.noCopyJobs.title))).toBeInTheDocument(); const button = screen.getByRole("button", { - name: ContainerCopyMessages.createCopyJobButtonText, + name: t(Keys.containerCopy.noCopyJobs.createCopyJobButtonText), }); expect(button).toBeInTheDocument(); expect(button).toHaveClass("createCopyJobButton"); @@ -45,7 +45,7 @@ describe("CopyJobsNotFound", () => { render(); const button = screen.getByRole("button", { - name: ContainerCopyMessages.createCopyJobButtonText, + name: t(Keys.containerCopy.noCopyJobs.createCopyJobButtonText), }); fireEvent.click(button); @@ -58,11 +58,11 @@ describe("CopyJobsNotFound", () => { render(); const button = screen.getByRole("button", { - name: ContainerCopyMessages.createCopyJobButtonText, + name: t(Keys.containerCopy.noCopyJobs.createCopyJobButtonText), }); expect(button).toBeInTheDocument(); - expect(button.textContent).toBe(ContainerCopyMessages.createCopyJobButtonText); + expect(button.textContent).toBe(t(Keys.containerCopy.noCopyJobs.createCopyJobButtonText)); }); it("should use memo to prevent unnecessary re-renders", () => { diff --git a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.tsx b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.tsx index 3c9658d62..f59a4771e 100644 --- a/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.tsx +++ b/src/Explorer/ContainerCopy/MonitorCopyJobs/Components/CopyJobs.NotFound.tsx @@ -2,8 +2,8 @@ import { ActionButton, Image } from "@fluentui/react"; import Explorer from "Explorer/Explorer"; import React from "react"; import CopyJobIcon from "../../../../../images/ContainerCopy/copy-jobs.svg"; +import { Keys, t } from "Localization"; import * as Actions from "../../Actions/CopyJobActions"; -import ContainerCopyMessages from "../../ContainerCopyMessages"; interface CopyJobsNotFoundProps { explorer: Explorer; @@ -12,14 +12,14 @@ interface CopyJobsNotFoundProps { const CopyJobsNotFound: React.FC = ({ explorer }) => { return (
- {ContainerCopyMessages.noCopyJobsTitle} -

{ContainerCopyMessages.noCopyJobsTitle}

+ {t(Keys.containerCopy.noCopyJobs.title)} +

{t(Keys.containerCopy.noCopyJobs.title)}

Actions.openCreateCopyJobPanel(explorer)} > - {ContainerCopyMessages.createCopyJobButtonText} + {t(Keys.containerCopy.noCopyJobs.createCopyJobButtonText)}
); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/PartitionKeyComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/PartitionKeyComponent.tsx index eb140167f..975156d56 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/PartitionKeyComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/PartitionKeyComponent.tsx @@ -25,7 +25,6 @@ import { resumeDataTransferJob, } from "Common/dataAccess/dataTransfers"; import { Platform, configContext } from "ConfigContext"; -import ContainerCopyMessages from "Explorer/ContainerCopy/ContainerCopyMessages"; import { CopyJobActions, CopyJobMigrationType } from "Explorer/ContainerCopy/Enums/CopyJobEnums"; import { useDialog } from "Explorer/Controls/Dialog"; import Explorer from "Explorer/Explorer"; @@ -174,7 +173,8 @@ export const PartitionKeyComponent: React.FC = ({ action === CopyJobActions.cancel ? ( - {/*t(Keys.controls.settings.partitionKeyEditor.confirmCancel1)*/}
+ {/*t(Keys.controls.settings.partitionKeyEditor.confirmCancel1)*/} +
{jobName}
{/*t(Keys.controls.settings.partitionKeyEditor.confirmCancel2)*/} @@ -182,26 +182,17 @@ export const PartitionKeyComponent: React.FC = ({ ) : action === CopyJobActions.complete ? ( - {/*t(Keys.controls.settings.partitionKeyEditor.confirmComplete1)*/}
+ {/*t(Keys.controls.settings.partitionKeyEditor.confirmComplete1)*/} +
{jobName}
- - {/*t(Keys.controls.settings.partitionKeyEditor.confrimComplete2)*/} - + {/*t(Keys.controls.settings.partitionKeyEditor.confrimComplete2)*/}
) : null; useDialog .getState() - .showOkCancelModalDialog( - ContainerCopyMessages.MonitorJobs.dialog.heading, - null, - ContainerCopyMessages.MonitorJobs.dialog.confirmButtonText, - onConfirm, - ContainerCopyMessages.MonitorJobs.dialog.cancelButtonText, - null, - dialogBody, - ); + .showOkCancelModalDialog("", null, t(Keys.common.confirm), onConfirm, t(Keys.common.cancel), null, dialogBody); }; const getOnlineJobMenuProps = (currentJob: DataTransferJobGetResults): IContextualMenuProps => { @@ -213,7 +204,7 @@ export const PartitionKeyComponent: React.FC = ({ if (!isPaused) { items.push({ key: CopyJobActions.pause, - text: ContainerCopyMessages.MonitorJobs.Actions.pause, + text: t(Keys.containerCopy.monitorJobs.actions.pause), iconProps: { iconName: "Pause" }, onClick: () => { pauseRunningDataTransferJob(currentJob); @@ -224,7 +215,7 @@ export const PartitionKeyComponent: React.FC = ({ if (isPaused) { items.push({ key: CopyJobActions.resume, - text: ContainerCopyMessages.MonitorJobs.Actions.resume, + text: t(Keys.containerCopy.monitorJobs.actions.resume), iconProps: { iconName: "Play" }, onClick: () => { resumePausedDataTransferJob(currentJob); @@ -234,7 +225,7 @@ export const PartitionKeyComponent: React.FC = ({ items.push({ key: CopyJobActions.cancel, - text: ContainerCopyMessages.MonitorJobs.Actions.cancel, + text: t(Keys.common.cancel), iconProps: { iconName: "Cancel" }, onClick: () => showActionConfirmationDialog(currentJob, CopyJobActions.cancel, () => cancelRunningDataTransferJob(currentJob)), @@ -242,7 +233,7 @@ export const PartitionKeyComponent: React.FC = ({ items.push({ key: CopyJobActions.complete, - text: ContainerCopyMessages.MonitorJobs.Actions.complete, + text: t(Keys.containerCopy.monitorJobs.actions.complete), iconProps: { iconName: "CheckMark" }, onClick: () => showActionConfirmationDialog(currentJob, CopyJobActions.complete, () => @@ -290,9 +281,9 @@ export const PartitionKeyComponent: React.FC = ({ const processedCountString = totalCount > 0 ? t(Keys.controls.settings.partitionKeyEditor.documentsProcessed, { - processedCount: String(processedCount), - totalCount: String(totalCount), - }) + processedCount: String(processedCount), + totalCount: String(totalCount), + }) : ""; return `${portalDataTransferJob?.properties?.status} ${processedCountString}`; }; @@ -418,8 +409,8 @@ export const PartitionKeyComponent: React.FC = ({ }} menuProps={getOnlineJobMenuProps(portalDataTransferJob)} menuIconProps={{ iconName: "", className: "hidden" }} - ariaLabel={ContainerCopyMessages.MonitorJobs.Columns.actions} - title={ContainerCopyMessages.MonitorJobs.Columns.actions} + ariaLabel={t(Keys.containerCopy.monitorJobs.columns.actions)} + title={t(Keys.containerCopy.monitorJobs.columns.actions)} /> ) : ( = ({ const handleEnablePitr = () => { const featureUrl = `https://portal.azure.com/#@/resource/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/backupRestore`; setIsEnablingPrerequisite(true); - setPrerequisiteLoaderMessage(ContainerCopyMessages.popoverOverlaySpinnerLabel); + setPrerequisiteLoaderMessage(t(Keys.containerCopy.popoverOverlaySpinnerLabel)); window.open(featureUrl, "_blank"); startPollingForAccountUpdate(); }; @@ -182,12 +181,12 @@ export const ChangePartitionKeyPane: React.FC = ({ setIsEnablingPrerequisite(true); try { setPrerequisiteLoaderMessage( - ContainerCopyMessages.onlineCopyEnabled.validateAllVersionsAndDeletesChangeFeedSpinnerLabel, + t(Keys.containerCopy.onlineCopyEnabled.validateAllVersionsAndDeletesChangeFeedSpinnerLabel), ); const currentAccount = await fetchDatabaseAccount(subscriptionId, resourceGroup, accountName); if (!currentAccount?.properties?.enableAllVersionsAndDeletesChangeFeed) { setPrerequisiteLoaderMessage( - ContainerCopyMessages.onlineCopyEnabled.enablingAllVersionsAndDeletesChangeFeedSpinnerLabel, + t(Keys.containerCopy.onlineCopyEnabled.enablingAllVersionsAndDeletesChangeFeedSpinnerLabel), ); await updateDatabaseAccount(subscriptionId, resourceGroup, accountName, { properties: { @@ -196,7 +195,9 @@ export const ChangePartitionKeyPane: React.FC = ({ }); } const capabilities = currentAccount?.properties?.capabilities ?? []; - setPrerequisiteLoaderMessage(ContainerCopyMessages.onlineCopyEnabled.enablingOnlineCopySpinnerLabel(accountName)); + setPrerequisiteLoaderMessage( + t(Keys.containerCopy.onlineCopyEnabled.enablingOnlineCopySpinnerLabel, { accountName }), + ); await updateDatabaseAccount(subscriptionId, resourceGroup, accountName, { properties: { capabilities: [...capabilities, { name: CapabilityNames.EnableOnlineCopyFeature }], @@ -345,8 +346,8 @@ export const ChangePartitionKeyPane: React.FC = ({ data-test={`migration-type-description-${migrationType}`} > {migrationType === CopyJobMigrationType.Offline - ? ContainerCopyMessages.migrationTypeOptions.offline.description - : ContainerCopyMessages.migrationTypeOptions.online.description} + ? t(Keys.containerCopy.migrationType.offline.description) + : t(Keys.containerCopy.migrationType.online.description)}
)}
@@ -626,10 +627,10 @@ export const ChangePartitionKeyPane: React.FC = ({ - {ContainerCopyMessages.assignPermissions.onlineConfiguration.title} + {t(Keys.containerCopy.assignPermissions.onlineConfiguration.title)} - {ContainerCopyMessages.assignPermissions.onlineConfiguration.description(accountName)} + {t(Keys.containerCopy.assignPermissions.onlineConfiguration.description, { accountName })} {/* Point In Time Restore */} @@ -642,17 +643,17 @@ export const ChangePartitionKeyPane: React.FC = ({ }} /> - {ContainerCopyMessages.pointInTimeRestore.title} + {t(Keys.containerCopy.pointInTimeRestore.title)} {!pitrEnabled && ( - {ContainerCopyMessages.pointInTimeRestore.description(accountName)} + {t(Keys.containerCopy.pointInTimeRestore.description, { accessName: accountName })} = ({ }} /> - {ContainerCopyMessages.onlineCopyEnabled.title} + {t(Keys.containerCopy.onlineCopyEnabled.title)} {!onlineCopyFeatureEnabled && ( - {ContainerCopyMessages.onlineCopyEnabled.description(accountName)}  - - {ContainerCopyMessages.onlineCopyEnabled.hrefText} + {t(Keys.containerCopy.onlineCopyEnabled.description, { accountName })}  + + {t(Keys.containerCopy.onlineCopyEnabled.hrefText)}