From 426e76701b00357cb64da83c9b41f7739d8fc7d8 Mon Sep 17 00:00:00 2001 From: muhammad-ahmed Date: Tue, 24 Sep 2024 16:40:10 +0800 Subject: [PATCH 1/8] ahmed/DAPI-727/chore--add-translation-to-dashboard --- src/components/AccountSwitcher/index.tsx | 4 +- src/components/ApiTokenNavbarItem/index.tsx | 3 +- .../Apiexplorer/LoginDialog/index.tsx | 4 +- .../Apiexplorer/RequestJSONBox/index.tsx | 4 +- .../Apiexplorer/ValidDialog/index.tsx | 4 +- src/features/Apiexplorer/index.tsx | 7 +- .../components/ApiTokenCard/index.tsx | 21 ++- .../ApiTokenForm/CreateTokenField/index.tsx | 9 +- .../ApiTokenForm/api-token.form.tsx | 72 +++++---- .../ApiTokenTable/CopyTokenDialog/index.tsx | 2 +- .../ApiTokenTable/DeleteTokenDialog/index.tsx | 5 +- .../ApiTokenTable/account.type.cell.tsx | 4 +- .../ApiTokenTable/delete.token.cell.tsx | 3 +- .../components/ApiTokenTable/index.tsx | 27 ++-- .../ApiTokenTable/responsive-table.tsx | 17 +- .../ApiTokenTable/table.lastused.cell.tsx | 3 +- .../AppDashboardContainer/index.tsx | 13 +- .../dashboard/components/AppForm/index.tsx | 150 ++++++++++++----- .../components/AppRegister/index.tsx | 21 ++- .../dashboard/components/AppRegister/types.ts | 15 +- .../AppsTable/AppsTableOptionDialog/index.tsx | 29 ++-- .../dashboard/components/AppsTable/index.tsx | 4 +- .../components/AppsTable/responsive-table.tsx | 16 +- .../Dialogs/DeleteAppDialog/index.tsx | 2 +- .../Dialogs/RegisterAppDialogError/index.tsx | 4 +- .../RegisterAppDialogSuccess/index.tsx | 6 +- .../TokenCreationDialogSuccess/index.tsx | 17 +- .../components/LoadingTable/index.tsx | 2 +- .../Modals/AppRegisterSuccessModal/index.tsx | 36 +++-- .../components/TokenRegister/index.tsx | 69 +++++--- .../components/TokenRegister/types.ts | 19 ++- src/features/dashboard/manage-apps/index.tsx | 5 +- .../dashboard/manage-dashboard/index.tsx | 24 +-- src/features/dashboard/types.ts | 28 +++- .../update-app/AppUpdateForm/index.tsx | 153 ++++++++++++------ .../MobileSidebar/PrimaryMenu/index.tsx | 5 +- 36 files changed, 532 insertions(+), 275 deletions(-) diff --git a/src/components/AccountSwitcher/index.tsx b/src/components/AccountSwitcher/index.tsx index 100247741..279ae4ae3 100644 --- a/src/components/AccountSwitcher/index.tsx +++ b/src/components/AccountSwitcher/index.tsx @@ -3,10 +3,10 @@ import { isNotDemoCurrency } from '@site/src/utils'; import useAuthContext from '@site/src/hooks/useAuthContext'; import useOnClickOutside from '@site/src/hooks/useOnClickOutside'; import CurrencyIcon from '../CurrencyIcon'; -import AccountDropdown from '../CustomSelectDropdown/account-dropdown/AccountDropdown'; import styles from './account_switcher.module.scss'; import { InputDropdown } from '@deriv-com/quill-ui'; import useAccountSelector from '@site/src/hooks/useAccountSelector'; +import { translate } from '@docusaurus/Translate'; const AccountSwitcher = () => { const { onSelectAccount } = useAccountSelector(); @@ -30,7 +30,7 @@ const AccountSwitcher = () => { return (
} placeholder={currentLoginAccount.name} diff --git a/src/components/ApiTokenNavbarItem/index.tsx b/src/components/ApiTokenNavbarItem/index.tsx index 9a4c40437..3f8e10a15 100644 --- a/src/components/ApiTokenNavbarItem/index.tsx +++ b/src/components/ApiTokenNavbarItem/index.tsx @@ -8,6 +8,7 @@ import useAppManager from '@site/src/hooks/useAppManager'; import styles from './api_token_switcher.module.scss'; import RenderOfficialContents from '../RenderOfficialContents'; import { TDashboardTab } from '@site/src/contexts/app-manager/app-manager.context'; +import Translate from '@docusaurus/Translate'; const ApiTokenNavbarItem = () => { const { is_logged_in, is_authorized } = useAuthContext(); @@ -39,7 +40,7 @@ const ApiTokenNavbarItem = () => { className={styles.createToken} to='/dashboard' > - Add new token + Add new token
)} diff --git a/src/features/Apiexplorer/LoginDialog/index.tsx b/src/features/Apiexplorer/LoginDialog/index.tsx index eb64560b0..fad17a52d 100644 --- a/src/features/Apiexplorer/LoginDialog/index.tsx +++ b/src/features/Apiexplorer/LoginDialog/index.tsx @@ -2,7 +2,7 @@ import React, { useCallback } from 'react'; import { Modal, Button } from '@deriv/ui'; import useLoginUrl from '@site/src/hooks/useLoginUrl'; import styles from './LoginDialog.module.scss'; -import Translate from '@docusaurus/Translate'; +import Translate, { translate } from '@docusaurus/Translate'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; type TLoginDialog = { @@ -34,7 +34,7 @@ export const LoginDialog = ({ setToggleModal }: TLoginDialog) => {
diff --git a/src/features/Apiexplorer/RequestJSONBox/index.tsx b/src/features/Apiexplorer/RequestJSONBox/index.tsx index ca5b9f59f..4f79766c3 100644 --- a/src/features/Apiexplorer/RequestJSONBox/index.tsx +++ b/src/features/Apiexplorer/RequestJSONBox/index.tsx @@ -5,7 +5,7 @@ import RequestResponseRenderer from '../RequestResponseRenderer'; import style from './RequestJSONBox.module.scss'; import SubscribeRenderer from '../SubscribeRenderer'; import { TSocketSubscribableEndpointNames } from '@site/src/configs/websocket/types'; -import Translate from '@docusaurus/Translate'; +import Translate, { translate } from '@docusaurus/Translate'; interface TRequestJSONBox { handleChange: React.ChangeEventHandler; @@ -33,7 +33,7 @@ function RequestJSONBox({ diff --git a/src/features/Apiexplorer/ValidDialog/index.tsx b/src/features/Apiexplorer/ValidDialog/index.tsx index 789044c74..a6a1d47fc 100644 --- a/src/features/Apiexplorer/ValidDialog/index.tsx +++ b/src/features/Apiexplorer/ValidDialog/index.tsx @@ -1,7 +1,7 @@ import React, { useCallback } from 'react'; import { Modal } from '@deriv/ui'; import styles from '../LoginDialog/LoginDialog.module.scss'; -import Translate from '@docusaurus/Translate'; +import Translate, { translate } from '@docusaurus/Translate'; type TValidDialog = { setIsNotValid: React.Dispatch>; @@ -24,7 +24,7 @@ export const ValidDialog = ({ setIsNotValid, setToggleModal }: TValidDialog) =>
diff --git a/src/features/Apiexplorer/index.tsx b/src/features/Apiexplorer/index.tsx index 664a9a928..01e521063 100644 --- a/src/features/Apiexplorer/index.tsx +++ b/src/features/Apiexplorer/index.tsx @@ -7,6 +7,7 @@ import SchemaWrapper from './Schema/SchemaWrapper'; import RequestJSONBox from './RequestJSONBox'; import useDynamicImportJSON from '@site/src/hooks/useDynamicImportJSON'; import Footer from '@site/src/components/Footer'; +import Translate from '@docusaurus/Translate'; export default function ApiExplorerFeatures() { const { text_data, @@ -24,12 +25,12 @@ export default function ApiExplorerFeatures() { Home, href: '/', target: '_self', }, { - content: 'API explorer', + content: API explorer, href: '/api-explorer', target: '_self', }, @@ -39,7 +40,7 @@ export default function ApiExplorerFeatures() {
- API Explorer + API Explorer
diff --git a/src/features/dashboard/components/ApiTokenCard/index.tsx b/src/features/dashboard/components/ApiTokenCard/index.tsx index ed81a15e6..3529f6325 100644 --- a/src/features/dashboard/components/ApiTokenCard/index.tsx +++ b/src/features/dashboard/components/ApiTokenCard/index.tsx @@ -7,6 +7,7 @@ import { Text, Heading, Modal, SectionMessage } from '@deriv-com/quill-ui'; import { StandaloneCircleExclamationRegularIcon } from '@deriv/quill-icons'; import { TApiTokenForm, TApiTokenFormItemsNames } from '../ApiTokenForm/api-token.form'; import styles from './api-token.card.module.scss'; +import Translate, { translate } from '@docusaurus/Translate'; interface IApiTokenCardProps { register: UseFormRegister; @@ -39,15 +40,17 @@ const ApiTokenCard = ({ register, name, label, description }: IApiTokenCardProps return ( <> handleAdminScopeChange(undefined, true)} secondaryButtonCallback={() => handleAdminScopeChange(undefined, false)} isMobile={deviceType !== 'desktop'} @@ -60,11 +63,15 @@ const ApiTokenCard = ({ register, name, label, description }: IApiTokenCardProps
- Are you sure you want to enable admin scope for your token? + + Are you sure you want to enable admin scope for your token? + - Granting admin access gives your token full control over your account and increases - security risks. We recommend granting this level of access only when it's - essential. + + Granting admin access gives your token full control over your account and increases + security risks. We recommend granting this level of access only when it's + essential. +
diff --git a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx index afc815680..7e04825e2 100644 --- a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx +++ b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx @@ -8,6 +8,7 @@ import TokenCreationDialogSuccess from '../../Dialogs/TokenCreationDialogSuccess import TokenNameRestrictions from '../../TokenNameRestrictions/TokenNameRestrictions'; import CustomErrors from './CustomErrors'; import styles from '../api-token.form.module.scss'; +import { translate } from '@docusaurus/Translate'; type TCreateTokenField = { register: UseFormRegisterReturn; @@ -88,8 +89,8 @@ const CreateTokenField = ({ >
diff --git a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx index f837d914e..eae4ca952 100644 --- a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx +++ b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx @@ -1,16 +1,16 @@ import React, { HTMLAttributes, useCallback, useEffect, useState } from 'react'; -import { Text } from '@deriv/ui'; +import * as yup from 'yup'; +import Translate, { translate } from '@docusaurus/Translate'; import { useForm } from 'react-hook-form'; -import Spinner from '@site/src/components/Spinner'; +import { Text } from '@deriv/ui'; import { yupResolver } from '@hookform/resolvers/yup'; import { scopesObjectToArray } from '@site/src/utils'; -import ApiTokenCard from '../ApiTokenCard'; +import Spinner from '@site/src/components/Spinner'; import useCreateToken from '@site/src/features/dashboard/hooks/useCreateToken'; -import * as yup from 'yup'; -import styles from './api-token.form.module.scss'; import TokenNameRestrictions from '../TokenNameRestrictions/TokenNameRestrictions'; +import ApiTokenCard from '../ApiTokenCard'; import CreateTokenField from './CreateTokenField'; -import useApiToken from '@site/src/hooks/useApiToken'; +import styles from './api-token.form.module.scss'; const schema = yup .object({ @@ -21,17 +21,21 @@ const schema = yup admin: yup.boolean(), name: yup .string() - .min(2, 'Your token name must be atleast 2 characters long.') - .max(32, 'Only up to 32 characters are allowed.') + .min(2, translate({ message: 'Your token name must be atleast 2 characters long.' })) + .max(32, translate({ message: 'Only up to 32 characters are allowed.' })) .matches(/^(?=.*[a-zA-Z0-9])[a-zA-Z0-9_ ]*$/, { - message: - 'Only alphanumeric characters with spaces and underscores are allowed. (Example: my_application)', + message: translate({ + message: + 'Only alphanumeric characters with spaces and underscores are allowed. (Example: my_application)', + }), excludeEmptyString: true, }) .matches( /^(?!.*deriv|.*d3r1v|.*der1v|.*d3riv|.*b1nary|.*binary|.*b1n4ry|.*bin4ry|.*blnary|.*b\|nary).*$/i, { - message: 'The name cannot contain “Binary”, “Deriv”, or similar words.', + message: translate({ + message: 'The name cannot contain “Binary”, “Deriv”, or similar words.', + }), excludeEmptyString: true, }, ), @@ -50,32 +54,42 @@ type TScope = { const scopes: TScope[] = [ { name: 'read', - description: - 'This scope will allow third-party apps to view your account activity, settings, limits, balance sheets, trade purchase history, and more.', - label: 'Read', + description: translate({ + message: + 'This scope will allow third-party apps to view your account activity, settings, limits, balance sheets, trade purchase history, and more.', + }), + label: translate({ message: 'Read' }), }, { name: 'trade', - description: - 'This scope will allow third-party apps to buy and sell contracts for you, renew your expired purchases, and top up your demo accounts.', - label: 'Trade', + description: translate({ + message: + 'This scope will allow third-party apps to buy and sell contracts for you, renew your expired purchases, and top up your demo accounts.', + }), + label: translate({ message: 'Trade' }), }, { name: 'payments', - description: - 'This scope will allow third-party apps to withdraw to payment agents and make inter-account transfers for you.', - label: 'Payments', + description: translate({ + message: + 'This scope will allow third-party apps to withdraw to payment agents and make inter-account transfers for you.', + }), + label: translate({ message: 'Payments' }), }, { name: 'trading_information', - description: 'This scope will allow third-party apps to view your trading history.', - label: 'Trading Information', + description: translate({ + message: 'This scope will allow third-party apps to view your trading history.', + }), + label: translate({ message: 'Trading Information' }), }, { name: 'admin', - description: - 'This scope will allow third-party apps to open accounts for you, manage your settings and token usage, and more.', - label: 'Admin', + description: translate({ + message: + 'This scope will allow third-party apps to open accounts for you, manage your settings and token usage, and more.', + }), + label: translate({ message: 'Admin' }), }, ]; @@ -133,8 +147,8 @@ const ApiTokenForm = (props: HTMLAttributes) => { {isCreatingToken && }
- - Select scopes based on the access you need. + + Select scopes based on the access you need.
@@ -165,8 +179,8 @@ const ApiTokenForm = (props: HTMLAttributes) => { {!hiderestrictions && }
- - Copy and paste the token into the app. + + Copy and paste the token into the app.
diff --git a/src/features/dashboard/components/ApiTokenTable/CopyTokenDialog/index.tsx b/src/features/dashboard/components/ApiTokenTable/CopyTokenDialog/index.tsx index 2b43ce0fa..be9ed70a4 100644 --- a/src/features/dashboard/components/ApiTokenTable/CopyTokenDialog/index.tsx +++ b/src/features/dashboard/components/ApiTokenTable/CopyTokenDialog/index.tsx @@ -1,8 +1,8 @@ import React, { useMemo, useCallback } from 'react'; +import Translate, { translate } from '@docusaurus/Translate'; import { Modal } from '@deriv/ui'; import { TModalActionButton } from '@deriv/ui/dist/types/src/components/core/modal/types'; import styles from './CopyTokenDialog.module.scss'; -import Translate, { translate } from '@docusaurus/Translate'; type TCopyTokenDialog = { setToggleModal: React.Dispatch>; diff --git a/src/features/dashboard/components/ApiTokenTable/DeleteTokenDialog/index.tsx b/src/features/dashboard/components/ApiTokenTable/DeleteTokenDialog/index.tsx index d3ceb125b..53f0e4657 100644 --- a/src/features/dashboard/components/ApiTokenTable/DeleteTokenDialog/index.tsx +++ b/src/features/dashboard/components/ApiTokenTable/DeleteTokenDialog/index.tsx @@ -1,13 +1,12 @@ import React, { useCallback, useContext } from 'react'; -import { TTokenType } from '@site/src/types'; +import { translate } from '@docusaurus/Translate'; import { Modal } from '@deriv-com/quill-ui'; import { StandaloneTrashRegularIcon } from '@deriv/quill-icons'; +import { TTokenType } from '@site/src/types'; import useDeviceType from '@site/src/hooks/useDeviceType'; import { ApiTokenContext } from '@site/src/contexts/api-token/api-token.context'; import useDisableScroll from '../../../hooks/useDisableScroll'; import useDeleteToken from '../../../hooks/useDeleteToken'; -import { translate } from '@docusaurus/Translate'; - import './delete-token-dialog.scss'; type TDeleteTokenDialogProps = { diff --git a/src/features/dashboard/components/ApiTokenTable/account.type.cell.tsx b/src/features/dashboard/components/ApiTokenTable/account.type.cell.tsx index 5b7b7ff92..9e98a0867 100644 --- a/src/features/dashboard/components/ApiTokenTable/account.type.cell.tsx +++ b/src/features/dashboard/components/ApiTokenTable/account.type.cell.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { getCurrencyObject } from '@site/src/utils'; +import { translate } from '@docusaurus/Translate'; import { isNotDemoCurrency } from '@site/src/utils'; import CurrencyIcon from '@site/src/components/CurrencyIcon'; import useAuthContext from '@site/src/hooks/useAuthContext'; @@ -13,7 +13,7 @@ const AccountTypeCell = () => { {currentLoginAccount.name && currentLoginAccount.currency ? `${currentLoginAccount.name}` - : 'Accounts'} + : translate({ message: 'Accounts' })}
); }; diff --git a/src/features/dashboard/components/ApiTokenTable/delete.token.cell.tsx b/src/features/dashboard/components/ApiTokenTable/delete.token.cell.tsx index 7779463d2..5223b6fde 100644 --- a/src/features/dashboard/components/ApiTokenTable/delete.token.cell.tsx +++ b/src/features/dashboard/components/ApiTokenTable/delete.token.cell.tsx @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import { translate } from '@docusaurus/Translate'; import { LabelPairedTrashMdRegularIcon } from '@deriv/quill-icons'; import CustomTooltip from '@site/src/components/CustomTooltip'; import useApiToken from '@site/src/hooks/useApiToken'; @@ -38,7 +39,7 @@ const TokenActionsCell = ({ tokenId }: TTokenActionsCellProps) => { data-testid={'delete-token-button'} className='tooltip-wrapper' > - + diff --git a/src/features/dashboard/components/ApiTokenTable/index.tsx b/src/features/dashboard/components/ApiTokenTable/index.tsx index 1e1c1a207..851b6bfad 100644 --- a/src/features/dashboard/components/ApiTokenTable/index.tsx +++ b/src/features/dashboard/components/ApiTokenTable/index.tsx @@ -2,11 +2,13 @@ import React, { HTMLAttributes } from 'react'; import { Column } from 'react-table'; import { Button, Heading, Text } from '@deriv-com/quill-ui'; import { LabelPairedCirclePlusMdRegularIcon } from '@deriv/quill-icons'; +import Translate from '@docusaurus/Translate'; import { TTokenType } from '@site/src/types'; import { TDashboardTab } from '@site/src/contexts/app-manager/app-manager.context'; import Spinner from '@site/src/components/Spinner'; import useApiToken from '@site/src/hooks/useApiToken'; import useDeviceType from '@site/src/hooks/useDeviceType'; +import useAppManager from '@site/src/hooks/useAppManager'; import AccountSwitcher from '@site/src/components/AccountSwitcher'; import ScopesCell from '../Table/scopes.cell'; import Table from '../Table'; @@ -15,37 +17,36 @@ import ApiLastUsedCell from './table.lastused.cell'; import TokenActionsCell from './delete.token.cell'; import AccountTypeCell from './account.type.cell'; import ResponsiveTable from './responsive-table'; -import useAppManager from '@site/src/hooks/useAppManager'; import styles from './api-table.module.scss'; export type TTokenColumn = Column; const tableColumns: TTokenColumn[] = [ { - Header: 'Name', + Header: Name, accessor: 'display_name', }, { - Header: 'Account Type', + Header: Account Type, Cell: AccountTypeCell, }, { - Header: 'Token', + Header: Token, accessor: 'token', Cell: ApiTokenCell, }, { - Header: 'Token scopes', + Header: Token scopes, accessor: 'scopes', Cell: ScopesCell, }, { - Header: 'Last used', + Header: Last used, accessor: 'last_used', Cell: ApiLastUsedCell, }, { - Header: 'Actions', + Header: Actions, id: 'actions', accessor: (originalRow) => originalRow.token, Cell: ({ row }) => , @@ -70,8 +71,12 @@ const ApiTokenTable = (props: HTMLAttributes) => {
- API token manager - Access all your API token details here. + + API token manager + + + Access all your API token details here. +
diff --git a/src/features/dashboard/components/ApiTokenTable/responsive-table.tsx b/src/features/dashboard/components/ApiTokenTable/responsive-table.tsx index 60df046d4..a3c00d3c3 100644 --- a/src/features/dashboard/components/ApiTokenTable/responsive-table.tsx +++ b/src/features/dashboard/components/ApiTokenTable/responsive-table.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { translate } from '@docusaurus/Translate'; import CustomAccordion from '@site/src/components/CustomAccordion'; import { TTokenType } from '@site/src/types'; import ScopesCell from '../Table/scopes.cell'; @@ -25,14 +26,20 @@ const AccordionItem: React.FC = ({ label, value }) => ( const generateContent = (token: TTokenType) => { return (
- - } /> - } /> + + } /> } + /> + } /> - } /> + } + />
); }; diff --git a/src/features/dashboard/components/ApiTokenTable/table.lastused.cell.tsx b/src/features/dashboard/components/ApiTokenTable/table.lastused.cell.tsx index a0bcb6426..f2f13a520 100644 --- a/src/features/dashboard/components/ApiTokenTable/table.lastused.cell.tsx +++ b/src/features/dashboard/components/ApiTokenTable/table.lastused.cell.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { formatDate } from '@site/src/utils'; import styles from './cells.module.scss'; +import { translate } from '@docusaurus/Translate'; type TApiLastUsedCellProps = { cell: { @@ -10,7 +11,7 @@ type TApiLastUsedCellProps = { const ApiLastUsedCell: React.FC = ({ cell }) => (
-
{cell.value ? formatDate(cell.value) : 'Never'}
+
{cell.value ? formatDate(cell.value) : translate({ message: 'Never' })}
); diff --git a/src/features/dashboard/components/AppDashboardContainer/index.tsx b/src/features/dashboard/components/AppDashboardContainer/index.tsx index e4876f3e4..d447bca25 100644 --- a/src/features/dashboard/components/AppDashboardContainer/index.tsx +++ b/src/features/dashboard/components/AppDashboardContainer/index.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { Heading, Text } from '@deriv-com/quill-ui'; -import './app-dashboard-container.scss'; +import Translate from '@docusaurus/Translate'; import useAppManager from '@site/src/hooks/useAppManager'; import { TDashboardTab } from '@site/src/contexts/app-manager/app-manager.context'; +import './app-dashboard-container.scss'; const hideHeaderForTabs = [TDashboardTab.UPDATE_APP, TDashboardTab.REGISTER_TOKENS]; @@ -14,10 +15,14 @@ const AppDashboardContainer: React.FC<{ children: React.ReactNode }> = ({ childr
{!hideHeaderForTabs.includes(currentTab) && (
- App Dashboard + + App Dashboard + - Start using Deriv API to bring custom integrations and powerful automation to your - apps. + + Start using Deriv API to bring custom integrations and powerful automation to your + apps. +
)} diff --git a/src/features/dashboard/components/AppForm/index.tsx b/src/features/dashboard/components/AppForm/index.tsx index b2b88c899..164d1bea2 100644 --- a/src/features/dashboard/components/AppForm/index.tsx +++ b/src/features/dashboard/components/AppForm/index.tsx @@ -1,9 +1,10 @@ -import React, { Dispatch, ReactNode, SetStateAction, useEffect, useMemo, useState } from 'react'; -import { Button, Text } from '@deriv/ui'; +import React, { Dispatch, ReactNode, SetStateAction, useEffect, useState } from 'react'; +import clsx from 'clsx'; import { useForm } from 'react-hook-form'; -import { isNotDemoCurrency } from '@site/src/utils'; +import { Button, Text } from '@deriv/ui'; +import Translate, { translate } from '@docusaurus/Translate'; import { yupResolver } from '@hookform/resolvers/yup'; -import { appRegisterSchema, appEditSchema, IRegisterAppForm } from '../../types'; +import useWS from '@site/src/hooks/useWs'; import useApiToken from '@site/src/hooks/useApiToken'; import useAuthContext from '@site/src/hooks/useAuthContext'; import CustomSelectDropdown from '@site/src/components/CustomSelectDropdown'; @@ -12,11 +13,10 @@ import TokenDropdown from '@site/src/components/CustomSelectDropdown/token-dropd import SelectedAccount from '@site/src/components/CustomSelectDropdown/account-dropdown/SelectedAccount'; import AccountDropdown from '@site/src/components/CustomSelectDropdown/account-dropdown/AccountDropdown'; import CustomCheckbox from '@site/src/components/CustomCheckbox'; -import styles from './app-form.module.scss'; -import clsx from 'clsx'; import useAppManager from '@site/src/hooks/useAppManager'; -import useWS from '@site/src/hooks/useWs'; +import { appRegisterSchema, appEditSchema, IRegisterAppForm } from '../../types'; import RestrictionsAppname from '../RestrictionsAppname'; +import styles from './app-form.module.scss'; type TAppFormProps = { initialValues?: Partial; @@ -93,7 +93,9 @@ const AppForm = ({ {!accountHasAdminToken() && ( - This account doesn't have API tokens with the admin scope. Choose another account. + + This account doesn't have API tokens with the admin scope. Choose another account. + )} @@ -110,7 +112,11 @@ const AppForm = ({ }} size='large' > - {is_update_mode ? 'Update Application' : 'Register Application'} + {is_update_mode ? ( + Update Application + ) : ( + Register Application + )} {is_update_mode && cancelButton()}
@@ -125,10 +131,12 @@ const AppForm = ({
-

App information

+

+ App information +

{!is_update_mode && ( - Select your api token ( it should have admin scope ) + Select your api token ( it should have admin scope ) )}
@@ -136,7 +144,7 @@ const AppForm = ({
- +
{errors && errors.name ? ( @@ -183,7 +193,7 @@ const AppForm = ({ ) : !is_update_mode && app_name_exists ? ( - That name is taken. Choose another. + That name is taken. Choose another. ) : ( display_restrictions && @@ -191,16 +201,22 @@ const AppForm = ({
-

Markup

+

+ Markup +

- You can earn commission by adding a markup to the price of each trade. Enter your - markup percentage here. + + You can earn commission by adding a markup to the price of each trade. Enter + your markup percentage here. +

- Note: Markup is only available for real accounts. + + Note: Markup is only available for real accounts. +

@@ -217,14 +233,18 @@ const AppForm = ({ defaultValue={0} placeholder=' ' /> - +
- Enter 0 if you don‘t want to earn a markup. Max markup: 3% + + Enter 0 if you don‘t want to earn a markup. Max markup: 3% + {errors && errors.app_markup_percentage && ( @@ -234,11 +254,15 @@ const AppForm = ({
-

OAuth details

+

+ OAuth details +

- This allows clients to log in to your app using their Deriv accounts without an - API token. + + This allows clients to log in to your app using their Deriv accounts without an + API token. +
@@ -250,15 +274,19 @@ const AppForm = ({ type='text' placeholder=' ' /> - +
- Please note that this URL will be used as the OAuth redirect URL for the OAuth - authorization. + + Please note that this URL will be used as the OAuth redirect URL for the OAuth + authorization. + {errors && errors?.redirect_uri && ( {errors.redirect_uri?.message} @@ -276,7 +304,9 @@ const AppForm = ({ type='text' placeholder=' ' /> - +
{errors && errors.verification_uri && ( {errors.verification_uri.message} @@ -286,9 +316,13 @@ const AppForm = ({
-

Scope of authorization

+

+ Scope of authorization +

- Select the scope for your app: + + Select the scope for your app: +
@@ -296,15 +330,26 @@ const AppForm = ({
@@ -315,8 +360,14 @@ const AppForm = ({ register={register('trading_information')} >
@@ -327,16 +378,27 @@ const AppForm = ({ register={register('payments')} >
@@ -344,15 +406,19 @@ const AppForm = ({
- By registering your application, you acknowledge that you‘ve read and accepted - the Deriv API{' '} + + By registering your application, you acknowledge that you‘ve read and + accepted the Deriv API + {' '} - terms and conditions + + terms and conditions +
{renderButtons &&
{renderButtons()}
} diff --git a/src/features/dashboard/components/AppRegister/index.tsx b/src/features/dashboard/components/AppRegister/index.tsx index a74c7b4e1..15c4bc43c 100644 --- a/src/features/dashboard/components/AppRegister/index.tsx +++ b/src/features/dashboard/components/AppRegister/index.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { Button } from '@deriv-com/quill-ui'; import { useForm } from 'react-hook-form'; +import { Button } from '@deriv-com/quill-ui'; import { yupResolver } from '@hookform/resolvers/yup'; -import './app-register.scss'; +import CustomCheckbox from '@site/src/components/CustomCheckbox'; import { IBaseRegisterAppForm, TAppRegisterProps, @@ -11,21 +11,26 @@ import { baseAppRegisterSchema, app_name_error_map, } from './types'; -import CustomCheckbox from '@site/src/components/CustomCheckbox'; +import './app-register.scss'; +import Translate, { translate } from '@docusaurus/Translate'; const TermsAndConditions: React.FC = ({ register }) => { return (
@@ -67,7 +72,7 @@ const AppRegister: React.FC = ({ submit }) => {
@@ -78,7 +83,7 @@ const AppRegister: React.FC = ({ submit }) => { variant='primary' role='submit' disabled={has_error} - label='Register now' + label={translate({ message: 'Register now' })} >
diff --git a/src/features/dashboard/components/AppRegister/types.ts b/src/features/dashboard/components/AppRegister/types.ts index 954d331eb..64719725f 100644 --- a/src/features/dashboard/components/AppRegister/types.ts +++ b/src/features/dashboard/components/AppRegister/types.ts @@ -1,16 +1,19 @@ +import { translate } from '@docusaurus/Translate'; import { UseFormRegisterReturn } from 'react-hook-form'; import * as yup from 'yup'; export const app_name_error_map = { - error_code_1: 'Use only letters, numbers, spaces, and underscores.', - error_code_2: `Your app's name can contain up to 48 characters.`, - error_code_3: `Your app's name cannot contain the words "Binary", "Deriv", or any of their variations.`, + error_code_1: translate({ message: 'Use only letters, numbers, spaces, and underscores.' }), + error_code_2: translate({ message: `Your app's name can contain up to 48 characters.` }), + error_code_3: translate({ + message: `Your app's name cannot contain the words "Binary", "Deriv", or any of their variations.`, + }), }; export const base_registration_schema = { name: yup .string() - .required('Enter your app name.') + .required(translate({ message: 'Enter your app name.' })) .max(48, app_name_error_map.error_code_2) .matches(/^(?=.*[a-zA-Z0-9])[a-zA-Z0-9_ ]*$/, { message: app_name_error_map.error_code_1, @@ -23,7 +26,9 @@ export const base_registration_schema = { excludeEmptyString: true, }, ), - tnc_approval: yup.boolean().oneOf([true], 'You must accept the terms and conditions.'), + tnc_approval: yup + .boolean() + .oneOf([true], translate({ message: 'You must accept the terms and conditions.' })), }; export type TTermsAndConditionsProps = { diff --git a/src/features/dashboard/components/AppsTable/AppsTableOptionDialog/index.tsx b/src/features/dashboard/components/AppsTable/AppsTableOptionDialog/index.tsx index 4bbb8d8c8..94bd6387e 100644 --- a/src/features/dashboard/components/AppsTable/AppsTableOptionDialog/index.tsx +++ b/src/features/dashboard/components/AppsTable/AppsTableOptionDialog/index.tsx @@ -1,25 +1,26 @@ import React from 'react'; import { Checkbox, Modal, RadioGroup } from '@deriv-com/quill-ui'; +import { translate } from '@docusaurus/Translate'; interface IAppsTableOption { [key: string]: string; } export const tableSortOptions: IAppsTableOption = { - appNameAscending: 'App name (A to Z)', - appNameDescending: 'App name (Z to A)', - appIdAscending: 'App ID (A to Z)', - appIdDescending: 'App ID (Z to A)', + appNameAscending: translate({ message: 'App name (A to Z)' }), + appNameDescending: translate({ message: 'App name (Z to A)' }), + appIdAscending: translate({ message: 'App ID (A to Z)' }), + appIdDescending: translate({ message: 'App ID (Z to A)' }), }; export const tableFilterOptions: IAppsTableOption = { - all: 'All', - no_scope: '(No scope)', - admin: 'Admin', - payments: 'Payments', - read: 'Read', - trade: 'Trade', - trading_information: 'Trading Information', + all: translate({ message: 'All' }), + no_scope: translate({ message: '(No scope)' }), + admin: translate({ message: 'Admin' }), + payments: translate({ message: 'Payments' }), + read: translate({ message: 'Read' }), + trade: translate({ message: 'Trade' }), + trading_information: translate({ message: 'Trading Information' }), }; interface IAppsTableOptionsProps { @@ -31,7 +32,7 @@ interface IAppsTableOptionsProps { const SortOptions: React.FC = ({ handleChange, selectedOption }) => { return ( <> - + {Object.keys(tableSortOptions).map((key) => ( @@ -51,7 +52,7 @@ const SortOptions: React.FC = ({ handleChange, selectedO const FilterOptions: React.FC = ({ handleChange, selectedOptions }) => { return ( <> - + {Object.keys(tableFilterOptions).map((option) => ( ; @@ -65,7 +65,7 @@ const AppsTableOptions: React.FC = ({
} diff --git a/src/features/dashboard/components/AppsTable/responsive-table.tsx b/src/features/dashboard/components/AppsTable/responsive-table.tsx index cd0ab30c0..c5480d937 100644 --- a/src/features/dashboard/components/AppsTable/responsive-table.tsx +++ b/src/features/dashboard/components/AppsTable/responsive-table.tsx @@ -1,11 +1,12 @@ import React from 'react'; -import CustomAccordion from '@site/src/components/CustomAccordion'; +import clsx from 'clsx'; import { ApplicationObject } from '@deriv/api-types'; +import CustomAccordion from '@site/src/components/CustomAccordion'; import CopyTextCell from '../Table/copy-text.cell'; import ScopesCell from '../Table/scopes.cell'; import AppActionsCell from './app-actions.cell'; -import clsx from 'clsx'; import './responsive-table.scss'; +import { translate } from '@docusaurus/Translate'; type TResponsiveTableProps = { apps: ApplicationObject[]; @@ -45,9 +46,12 @@ const AccordionItem: React.FC = ({ label, value, row_wise = const generateContent = (item: ApplicationObject, accordionActions: TAccordionActions) => { return (
- } /> } + /> + } row_wise /> void; @@ -16,7 +16,9 @@ export const RegisterAppDialogSuccess = ({ onClose }: IRegisterAppDialogSuccessP
-

Success!

+

+ Success! +

You have successfully registered your application.

diff --git a/src/features/dashboard/components/Dialogs/TokenCreationDialogSuccess/index.tsx b/src/features/dashboard/components/Dialogs/TokenCreationDialogSuccess/index.tsx index 457e059fd..0835bff9d 100644 --- a/src/features/dashboard/components/Dialogs/TokenCreationDialogSuccess/index.tsx +++ b/src/features/dashboard/components/Dialogs/TokenCreationDialogSuccess/index.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react'; +import Translate, { translate } from '@docusaurus/Translate'; import { Modal, Heading, Text } from '@deriv-com/quill-ui'; import styles from '../../ApiTokenTable/token-cell.module.scss'; import useApiToken from '@site/src/hooks/useApiToken'; @@ -43,7 +44,7 @@ export const TokenCreationDialogSuccess = ({ showHandleBar disableCloseOnOverlay isMobile={deviceType !== 'desktop'} - primaryButtonLabel='Ok' + primaryButtonLabel={translate({ message: 'Ok' })} primaryButtonCallback={handleToggle} >
- Token created successfully! + + Token created successfully! +

- Please save this token key. For security reasons, it can't be viewed or copied - again. If you lose this key, you'll need to generate a new token. + + Please save this token key. For security reasons, it can't be viewed or copied + again. If you lose this key, you'll need to generate a new token. +

- Key + + Key + {latestToken}
diff --git a/src/features/dashboard/components/LoadingTable/index.tsx b/src/features/dashboard/components/LoadingTable/index.tsx index beffa2af4..eb9617815 100644 --- a/src/features/dashboard/components/LoadingTable/index.tsx +++ b/src/features/dashboard/components/LoadingTable/index.tsx @@ -1,5 +1,5 @@ -import { SkeletonText } from '@site/src/components/SkeletonText'; import React, { HTMLAttributes } from 'react'; +import { SkeletonText } from '@site/src/components/SkeletonText'; interface ISkeletonRow { columnCount: number; diff --git a/src/features/dashboard/components/Modals/AppRegisterSuccessModal/index.tsx b/src/features/dashboard/components/Modals/AppRegisterSuccessModal/index.tsx index 58b2ae8db..b6713d4a3 100644 --- a/src/features/dashboard/components/Modals/AppRegisterSuccessModal/index.tsx +++ b/src/features/dashboard/components/Modals/AppRegisterSuccessModal/index.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import useAppManager from '@site/src/hooks/useAppManager'; -import { Heading, Modal } from '@deriv-com/quill-ui'; +import Translate, { translate } from '@docusaurus/Translate'; +import { Modal } from '@deriv-com/quill-ui'; import { StandaloneCircleCheckRegularIcon } from '@deriv/quill-icons'; +import useAppManager from '@site/src/hooks/useAppManager'; import useDeviceType from '@site/src/hooks/useDeviceType'; -import '../../Dialogs/DeleteAppDialog/delete-app-dialog.scss'; import useDisableScroll from '../../../hooks/useDisableScroll'; +import '../../Dialogs/DeleteAppDialog/delete-app-dialog.scss'; interface IAppRegisterSuccessModalProps { onConfigure: () => void; @@ -23,12 +24,12 @@ export const AppRegisterSuccessModal = ({ return ( { onConfigure(); onCancel(); }} - secondaryButtonLabel='Maybe later' + secondaryButtonLabel={translate({ message: 'Maybe later' })} secondaryButtonCallback={onCancel} isMobile={deviceType !== 'desktop'} showHandleBar @@ -40,17 +41,28 @@ export const AppRegisterSuccessModal = ({
-

Application registered successfully!

+

+ Application registered successfully! +

- Ready to take the next step? -

Optimise your app's capabilities by: + Ready to take the next step? +

+ Optimise your app's capabilities by:
    -
  • Creating an API token to use with your application.
  • -
  • Adding OAuth authentication in your app.
  • -
  • Selecting the scopes of OAuth authorisation for your app.
  • +
  • + Creating an API token to use with your application. +
  • +
  • + Adding OAuth authentication in your app. +
  • +
  • + Selecting the scopes of OAuth authorisation for your app. +
-
Note: You can make these changes later through the dashboard.
+
+ Note: You can make these changes later through the dashboard. +
diff --git a/src/features/dashboard/components/TokenRegister/index.tsx b/src/features/dashboard/components/TokenRegister/index.tsx index 29e73bdf3..0a467894e 100644 --- a/src/features/dashboard/components/TokenRegister/index.tsx +++ b/src/features/dashboard/components/TokenRegister/index.tsx @@ -1,6 +1,6 @@ import React, { HTMLAttributes, useCallback, useEffect, useState } from 'react'; import { Text, Heading } from '@deriv-com/quill-ui'; -import { useForm, FormProvider } from 'react-hook-form'; +import { useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import { scopesObjectToArray } from '@site/src/utils'; import ApiTokenCard from '../ApiTokenCard'; @@ -9,6 +9,7 @@ import * as yup from 'yup'; import './token-register.scss'; import CreateTokenField from '../ApiTokenForm/CreateTokenField'; import AccountSwitcher from '@site/src/components/AccountSwitcher'; +import Translate, { translate } from '@docusaurus/Translate'; const schema = yup .object({ @@ -19,17 +20,21 @@ const schema = yup admin: yup.boolean(), name: yup .string() - .min(2, 'Your token name must be atleast 2 characters long.') - .max(32, 'Only up to 32 characters are allowed.') + .min(2, translate({ message: 'Your token name must be atleast 2 characters long.' })) + .max(32, translate({ message: 'Only up to 32 characters are allowed.' })) .matches(/^(?=.*[a-zA-Z0-9])[a-zA-Z0-9_ ]*$/, { - message: - 'Only alphanumeric characters with spaces and underscores are allowed. (Example: my_application)', + message: translate({ + message: + 'Only alphanumeric characters with spaces and underscores are allowed. (Example: my_application)', + }), excludeEmptyString: true, }) .matches( /^(?!.*deriv|.*d3r1v|.*der1v|.*d3riv|.*b1nary|.*binary|.*b1n4ry|.*bin4ry|.*blnary|.*b\|nary).*$/i, { - message: 'The name cannot contain “Binary”, “Deriv”, or similar words.', + message: translate({ + message: 'The name cannot contain “Binary”, “Deriv”, or similar words.', + }), excludeEmptyString: true, }, ), @@ -48,37 +53,47 @@ type TScope = { const scopes: TScope[] = [ { name: 'read', - description: - 'This scope will allow third-party apps to view your account activity, settings, limits, balance sheets, trade purchase history, and more.', - label: 'Read', + description: translate({ + message: + 'This scope will allow third-party apps to view your account activity, settings, limits, balance sheets, trade purchase history, and more.', + }), + label: translate({ message: 'Read' }), }, { name: 'trade', - description: - 'This scope will allow third-party apps to buy and sell contracts for you, renew your expired purchases, and top up your demo accounts.', - label: 'Trade', + description: translate({ + message: + 'This scope will allow third-party apps to buy and sell contracts for you, renew your expired purchases, and top up your demo accounts.', + }), + label: translate({ message: 'Trade' }), }, { name: 'payments', - description: - 'This scope will allow third-party apps to withdraw to payment agents and make inter-account transfers for you.', - label: 'Payments', + description: translate({ + message: + 'This scope will allow third-party apps to withdraw to payment agents and make inter-account transfers for you.', + }), + label: translate({ message: 'Payments' }), }, { name: 'trading_information', - description: 'This scope will allow third-party apps to view your trading history.', - label: 'Trading information', + description: translate({ + message: 'This scope will allow third-party apps to view your trading history.', + }), + label: translate({ message: 'Trading information' }), }, { name: 'admin', - description: - 'This scope will allow third-party apps to open accounts for you, manage your settings and token usage, and more.', - label: 'Admin', + description: translate({ + message: + 'This scope will allow third-party apps to open accounts for you, manage your settings and token usage, and more.', + }), + label: translate({ message: 'Admin' }), }, ]; const TokenRegister = (props: HTMLAttributes) => { - const { createToken, isCreatingToken } = useCreateToken(); + const { createToken } = useCreateToken(); const [hiderestrictions, setHideRestrictions] = useState(false); const [formIsCleared, setFormIsCleared] = useState(false); const [is_toggle, setToggleModal] = useState(false); @@ -129,16 +144,22 @@ const TokenRegister = (props: HTMLAttributes) => {
- Create new token + + Create new token +
- Select your account type: + + Select your account type: +
- Select scopes based on the access you need: + + Select scopes based on the access you need: +
{scopes.map((item) => ( diff --git a/src/features/dashboard/components/TokenRegister/types.ts b/src/features/dashboard/components/TokenRegister/types.ts index b11e1494f..70f5c9476 100644 --- a/src/features/dashboard/components/TokenRegister/types.ts +++ b/src/features/dashboard/components/TokenRegister/types.ts @@ -1,18 +1,25 @@ +import { translate } from '@docusaurus/Translate'; import { UseFormRegisterReturn } from 'react-hook-form'; import * as yup from 'yup'; export const token_name_error_map = { - error_code_1: 'Only alphanumeric characters with spaces and underscores are allowed.', - error_code_2: `Only 2-32 characters are allowed`, - error_code_3: `No duplicate token names are allowed for the same account.`, - error_code_4: `No keywords "deriv" or "binary" or words that look similar, e.g. "_binary_" or "d3riv" are allowed.`, + error_code_1: translate({ + message: 'Only alphanumeric characters with spaces and underscores are allowed.', + }), + error_code_2: translate({ message: `Only 2-32 characters are allowed` }), + error_code_3: translate({ + message: `No duplicate token names are allowed for the same account.`, + }), + error_code_4: translate({ + message: `No keywords "deriv" or "binary" or words that look similar, e.g. "_binary_" or "d3riv" are allowed.`, + }), }; export const tokenRegisterSchema = yup.object({ - account_type: yup.string().required('Select an account type.'), + account_type: yup.string().required(translate({ message: 'Select an account type.' })), token_name: yup .string() - .required('Enter your token name.') + .required(translate({ message: 'Enter your token name.' })) .min(2, token_name_error_map.error_code_2) .max(32, token_name_error_map.error_code_2) .matches(/^(?=.*[a-zA-Z0-9])[a-zA-Z0-9_ ]*$/, { diff --git a/src/features/dashboard/manage-apps/index.tsx b/src/features/dashboard/manage-apps/index.tsx index 258c739ac..ad0b0d232 100644 --- a/src/features/dashboard/manage-apps/index.tsx +++ b/src/features/dashboard/manage-apps/index.tsx @@ -5,6 +5,7 @@ import TokenManagePage from '../manage-tokens/token-manage-page'; import CustomTabs from '@site/src/components/CustomTabs'; import './manage-apps.scss'; import { TDashboardTab } from '@site/src/contexts/app-manager/app-manager.context'; +import { translate } from '@docusaurus/Translate'; const AppManagement = () => { const { getApps, apps, currentTab } = useAppManager(); @@ -15,11 +16,11 @@ const AppManagement = () => { const tabs = [ { - label: 'Applications', + label: translate({ message: 'Applications' }), content: , }, { - label: 'API tokens', + label: translate({ message: 'API tokens' }), content: , }, ]; diff --git a/src/features/dashboard/manage-dashboard/index.tsx b/src/features/dashboard/manage-dashboard/index.tsx index 5cdd573b3..51c06dc93 100644 --- a/src/features/dashboard/manage-dashboard/index.tsx +++ b/src/features/dashboard/manage-dashboard/index.tsx @@ -1,20 +1,20 @@ import React, { useCallback, useEffect, useState } from 'react'; -import AppDashboardContainer from '../components/AppDashboardContainer'; -import AppRegister from '../components/AppRegister'; +import { translate } from '@docusaurus/Translate'; +import { ApplicationObject } from '@deriv/api-types'; import { Breadcrumbs } from '@deriv-com/quill-ui'; +import { TDashboardTab } from '@site/src/contexts/app-manager/app-manager.context'; import useAppManager from '@site/src/hooks/useAppManager'; import useApiToken from '@site/src/hooks/useApiToken'; import Spinner from '@site/src/components/Spinner'; import useWS from '@site/src/hooks/useWs'; import { RegisterAppDialogError } from '../components/Dialogs/RegisterAppDialogError'; import { AppRegisterSuccessModal } from '../components/Modals/AppRegisterSuccessModal'; +import AppDashboardContainer from '../components/AppDashboardContainer'; +import AppRegister from '../components/AppRegister'; +import TokenRegister from '../components/TokenRegister'; import AppManagement from '../manage-apps'; -import './manage-dashboard.scss'; -import { TDashboardTab } from '@site/src/contexts/app-manager/app-manager.context'; import UpdateApp from '../update-app'; -import { ApplicationObject } from '@deriv/api-types'; -import TokenRegister from '../components/TokenRegister'; -import TokenManagePage from '../manage-tokens/token-manage-page'; +import './manage-dashboard.scss'; const ManageDashboard = () => { const { @@ -92,23 +92,23 @@ const ManageDashboard = () => { }; const commonLinks = [ - { content: 'Home', href: '/', target: '_self' }, - { content: 'Dashboard', href: '/dashboard', target: '_self' }, + { content: translate({ message: 'Home' }), href: '/', target: '_self' }, + { content: translate({ message: 'Dashboard' }), href: '/dashboard', target: '_self' }, ]; const tabSecndryLinks = { [TDashboardTab.REGISTER_APP]: { - content: 'Register application', + content: translate({ message: 'Register application' }), href: '/dashboard', target: '_self', }, [TDashboardTab.UPDATE_APP]: { - content: 'Edit application', + content: translate({ message: 'Edit application' }), href: '/dashboard', target: '_self', }, [TDashboardTab.REGISTER_TOKENS]: { - content: 'Create token', + content: translate({ message: 'Create token' }), href: '/dashboard', target: '_self', }, diff --git a/src/features/dashboard/types.ts b/src/features/dashboard/types.ts index a6ebfa972..73a64ceb9 100644 --- a/src/features/dashboard/types.ts +++ b/src/features/dashboard/types.ts @@ -7,7 +7,11 @@ const urlRegex = /^[a-z][a-z0-9.+-]*:\/\/[0-9a-zA-Z.-]+[%/\w .-]*$/; const base_schema = { name: yup .string() - .required('Enter your app name.') + .required( + translate({ + message: 'Enter your app name.', + }), + ) .max(48, app_name_error_map.error_code_2) .matches(/^(?=.*[a-zA-Z0-9])[a-zA-Z0-9_ ]*$/, { message: app_name_error_map.error_code_1, @@ -58,10 +62,24 @@ const base_schema = { app_markup_percentage: yup .number() .required() - .min(0, 'Your markup value must be equal to or above 0.00') - .max(3, 'Your markup value must be no more than 3.00.') - .test('is-decimal', 'Your markup value cannot be more than 4 characters.', (value) => - value ? /^\d+(\.\d{1,2})?$/.test(value.toString()) : true, + .min( + 0, + translate({ + message: 'Your markup value must be equal to or above 0.00', + }), + ) + .max( + 3, + translate({ + message: 'Your markup value must be no more than 3.00.', + }), + ) + .test( + 'is-decimal', + translate({ + message: 'Your markup value cannot be more than 4 characters.', + }), + (value) => (value ? /^\d+(\.\d{1,2})?$/.test(value.toString()) : true), ), app_id: yup.number(), }; diff --git a/src/features/dashboard/update-app/AppUpdateForm/index.tsx b/src/features/dashboard/update-app/AppUpdateForm/index.tsx index c90fbaaba..2eed02f71 100644 --- a/src/features/dashboard/update-app/AppUpdateForm/index.tsx +++ b/src/features/dashboard/update-app/AppUpdateForm/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import { appEditSchema, IRegisterAppForm } from '../../types'; @@ -10,6 +10,7 @@ import useDeviceType from '@site/src/hooks/useDeviceType'; import './app-update-form.scss'; import { StandaloneCircleExclamationRegularIcon } from '@deriv/quill-icons'; import useDisableScroll from '../../hooks/useDisableScroll'; +import Translate, { translate } from '@docusaurus/Translate'; type TAppFormProps = { initialValues?: Partial; @@ -81,15 +82,17 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm
- App’s name + + App’s name + - Enter the name of the application you want to register: + Enter the name of the application you want to register:
- Markup + + Markup + - Add a markup to the price of each trade to help you earn a commission. Enter your markup - percentage below. Learn more about markup calculations in our detailed{' '} + + Add a markup to the price of each trade to help you earn a commission. Enter your + markup percentage below. Learn more about markup calculations in our detailed + {' '} . {errors.app_markup_percentage?.message} )} - OAuth settings + + OAuth settings + - Log in to your app using your Deriv account without an API token. With OAuth, - third-party applications can securely authorise access without requiring password - sharing, enhancing both security and user control. + + Log in to your app using your Deriv account without an API token. With OAuth, + third-party applications can securely authorise access without requiring password + sharing, enhancing both security and user control. + -
  • Use OAuth if your application requires other users to sign in.
  • -
  • Authorisation URL is mandatory to enable OAuth on your app.
  • +
  • + + Use OAuth if your application requires other users to sign in. + +
  • +
  • + Authorisation URL is mandatory to enable OAuth on your app. +
  • } size='md' @@ -161,10 +180,14 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm />
    - URL Configuration + + URL Configuration + - To set up OAuth for your app, specify the URL where users should be redirected after - authorisation. + + To set up OAuth for your app, specify the URL where users should be redirected + after authorisation. +
    @@ -172,8 +195,8 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm - If your app includes verification logic, enter the email verification URL below - (e.g. for account opening, verification, and password reset): + + If your app includes verification logic, enter the email verification URL below + (e.g. for account opening, verification, and password reset): + {errors.verification_uri.message} )} - If provided, the verification URL will be appended with a token and sent to the - user's email. Otherwise, the authorisation URL with the token will be used. + + If provided, the verification URL will be appended with a token and sent to the + user's email. Otherwise, the authorisation URL with the token will be used. +
    - Scopes of authorisation + + Scopes of authorisation + - Select the scope for your app: + Select the scope for your app:
    @@ -222,15 +251,26 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm
    @@ -241,8 +281,14 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm register={register('trading_information')} >
    @@ -253,7 +299,13 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm register={register('payments')} >
    @@ -267,14 +319,21 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm onChange={handleCheckboxChange} >
    @@ -307,8 +366,8 @@ const AppUpdateForm = ({ initialValues, submit, onCancel, is_loading }: TAppForm
    - Enable admin access for your app? + + Enable admin access for your app? + - For better security, enable admin access only when it's necessary. This approach - limits access to client activities, minimising risks and safeguarding both workflow - efficiency and client trust. + + For better security, enable admin access only when it's necessary. This approach + limits access to client activities, minimising risks and safeguarding both workflow + efficiency and client trust. +
    diff --git a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx index 99cf26f3e..31d551a80 100644 --- a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx +++ b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx @@ -14,6 +14,7 @@ import { import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { useLocation } from '@docusaurus/router'; import classnames from 'classnames'; +import Translate from '@docusaurus/Translate'; export function useNavbarItems() { return useThemeConfig().navbar.items; @@ -61,7 +62,7 @@ const SidebarBottomAction: React.FC = ({ mobileSidebar }) => {
    {!is_logged_in ? ( ) : ( )}
    From 0f0757fe4327fb47526bca53fe935d0255970365 Mon Sep 17 00:00:00 2001 From: muhammad-ahmed Date: Tue, 24 Sep 2024 16:46:49 +0800 Subject: [PATCH 2/8] add strings to en file --- i18n/en/code.json | 258 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/i18n/en/code.json b/i18n/en/code.json index 8b10e554e..9fa2d6a2f 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -930,5 +930,263 @@ }, "Register tokens": { "message": "Register tokens" + }, + "Account type": { + "message": "Account type" + }, + "Add new token": { + "message": "Add new token" + }, + "Home": { + "message": "Home" + }, + "API Explorer": { + "message": "API Explorer" + }, + "Enter your app name.": { + "message": "Enter your app name." + }, + "Your markup value must be equal to or above 0.00": { + "message": "Your markup value must be equal to or above 0.00" + }, + "Your markup value must be no more than 3.00.": { + "message": "Your markup value must be no more than 3.00." + }, + "Authorisation required": { + "message": "Authorisation required" + }, + "Invalid JSON": { + "message": "Invalid JSON" + }, + "Applications": { + "message": "Applications" + }, + "API tokens": { + "message": "API tokens" + }, + "Edit application": { + "message": "Edit application" + }, + "Create token": { + "message": "Create token" + }, + "Do not share tokens with the admin scope with unauthorized parties.": { + "message": "Do not share tokens with the admin scope with unauthorized parties." + }, + "Enable admin access": { + "message": "Enable admin access" + }, + "Are you sure you want to enable admin scope for your token?": { + "message": "Are you sure you want to enable admin scope for your token?" + }, + "Granting admin access gives your token full control over your account and increases security risks. We recommend granting this level of access only when it's essential.": { + "message": "Granting admin access gives your token full control over your account and increases security risks. We recommend granting this level of access only when it's essential." + }, + "Trading Information": { + "message": "Trading Information" + }, + "App Dashboard": { + "message": "App Dashboard" + }, + "Start using Deriv API to bring custom integrations and powerful automation to your apps.": { + "message": "Start using Deriv API to bring custom integrations and powerful automation to your apps." + }, + "Accounts": { + "message": "Accounts" + }, + "Account Type": { + "message": "Account Type" + }, + "Token scopes": { + "message": "Token scopes" + }, + "Last used": { + "message": "Last used" + }, + "API token manager": { + "message": "API token manager" + }, + "Access all your API token details here.": { + "message": "Access all your API token details here." + }, + "Create new token": { + "message": "Create new token" + }, + "Never": { + "message": "Never" + }, + "You'll have full access to your clients' information.": { + "message": "You'll have full access to your clients' information." + }, + "You'll be able to buy and sell contracts on your clients' behalf.": { + "message": "You'll be able to buy and sell contracts on your clients' behalf." + }, + "You‘ll be able to view your clients’ trading information, including their account balance.": { + "message": "You‘ll be able to view your clients’ trading information, including their account balance." + }, + "You‘ll be able to perform deposits and withdrawals on your clients’ behalf.": { + "message": "You‘ll be able to perform deposits and withdrawals on your clients’ behalf." + }, + "Full account access, including the access to manage security tokens.": { + "message": "Full account access, including the access to manage security tokens." + }, + "Enter your app's name": { + "message": "Enter your app's name" + }, + "Use only letters, numbers, spaces, and underscores.": { + "message": "Use only letters, numbers, spaces, and underscores." + }, + "Your app's name can contain up to 48 characters.": { + "message": "Your app's name can contain up to 48 characters." + }, + "Your app's name cannot contain the words \"Binary\", \"Deriv\", or any of their variations.": { + "message": "Your app's name cannot contain the words \"Binary\", \"Deriv\", or any of their variations." + }, + "You must accept the terms and conditions.": { + "message": "You must accept the terms and conditions." + }, + "Filter by OAuth scopes": { + "message": "Filter by OAuth scopes" + }, + "OAuth Scopes": { + "message": "OAuth Scopes" + }, + "OAuth Redirect URL": { + "message": "OAuth Redirect URL" + }, + "Select your account type:": { + "message": "Select your account type:" + }, + "Select scopes based on the access you need:": { + "message": "Select scopes based on the access you need:" + }, + "No keywords \"deriv\" or \"binary\" or words that look similar, e.g. \"_binary_\" or \"d3riv\" are allowed.": { + "message": "No keywords \"deriv\" or \"binary\" or words that look similar, e.g. \"_binary_\" or \"d3riv\" are allowed." + }, + "Select an account type.": { + "message": "Select an account type." + }, + "Enter your token name.": { + "message": "Enter your token name." + }, + "Enter the name of the application you want to register:": { + "message": "Enter the name of the application you want to register:" + }, + "Add a markup to the price of each trade to help you earn a commission. Enter your markup percentage below. Learn more about markup calculations in our detailed": { + "message": "Add a markup to the price of each trade to help you earn a commission. Enter your markup percentage below. Learn more about markup calculations in our detailed" + }, + "Markup is only available for real accounts and trading applications.": { + "message": "Markup is only available for real accounts and trading applications." + }, + "OAuth settings": { + "message": "OAuth settings" + }, + "Log in to your app using your Deriv account without an API token. With OAuth, third-party applications can securely authorise access without requiring password sharing, enhancing both security and user control.": { + "message": "Log in to your app using your Deriv account without an API token. With OAuth, third-party applications can securely authorise access without requiring password sharing, enhancing both security and user control." + }, + "Use OAuth if your application requires other users to sign in.": { + "message": "Use OAuth if your application requires other users to sign in." + }, + "Authorisation URL is mandatory to enable OAuth on your app.": { + "message": "Authorisation URL is mandatory to enable OAuth on your app." + }, + "URL Configuration": { + "message": "URL Configuration" + }, + "To set up OAuth for your app, specify the URL where users should be redirected after authorisation.": { + "message": "To set up OAuth for your app, specify the URL where users should be redirected after authorisation." + }, + "Authorisation URL": { + "message": "Authorisation URL" + }, + "If your app includes verification logic, enter the email verification URL below (e.g. for account opening, verification, and password reset):": { + "message": "If your app includes verification logic, enter the email verification URL below (e.g. for account opening, verification, and password reset):" + }, + "If provided, the verification URL will be appended with a token and sent to the user's email. Otherwise, the authorisation URL with the token will be used.": { + "message": "If provided, the verification URL will be appended with a token and sent to the user's email. Otherwise, the authorisation URL with the token will be used." + }, + "Scopes of authorisation": { + "message": "Scopes of authorisation" + }, + "You'll be able to process your clients’ payments.": { + "message": "You'll be able to process your clients’ payments." + }, + "Grant admin access only when it’s essential for your app's workflow.": { + "message": "Grant admin access only when it’s essential for your app's workflow." + }, + "Update application": { + "message": "Update application" + }, + "Enable admin access for your app?": { + "message": "Enable admin access for your app?" + }, + "For better security, enable admin access only when it's necessary. This approach limits access to client activities, minimising risks and safeguarding both workflow efficiency and client trust.": { + "message": "For better security, enable admin access only when it's necessary. This approach limits access to client activities, minimising risks and safeguarding both workflow efficiency and client trust." + }, + "Enter your token name": { + "message": "Enter your token name" + }, + "Token name": { + "message": "Token name" + }, + "App name (A to Z)": { + "message": "App name (A to Z)" + }, + "App name (Z to A)": { + "message": "App name (Z to A)" + }, + "App ID (A to Z)": { + "message": "App ID (A to Z)" + }, + "App ID (Z to A)": { + "message": "App ID (Z to A)" + }, + "All": { + "message": "All" + }, + "(No scope)": { + "message": "(No scope)" + }, + "Sort by": { + "message": "Sort by" + }, + "Apply": { + "message": "Apply" + }, + "Error!": { + "message": "Error!" + }, + "Success!": { + "message": "Success!" + }, + "Ok": { + "message": "Ok" + }, + "Configure now": { + "message": "Configure now" + }, + "Maybe later": { + "message": "Maybe later" + }, + "Application registered successfully!": { + "message": "Application registered successfully!" + }, + "Ready to take the next step?": { + "message": "Ready to take the next step?" + }, + "Optimise your app's capabilities by:": { + "message": "Optimise your app's capabilities by:" + }, + "Creating an API token to use with your application.": { + "message": "Creating an API token to use with your application." + }, + "Adding OAuth authentication in your app.": { + "message": "Adding OAuth authentication in your app." + }, + "Selecting the scopes of OAuth authorisation for your app.": { + "message": "Selecting the scopes of OAuth authorisation for your app." + }, + "Note: You can make these changes later through the dashboard.": { + "message": "Note: You can make these changes later through the dashboard." } } From 4dd33706d15202b7103cea75b7525742f6371053 Mon Sep 17 00:00:00 2001 From: muhammad-ahmed Date: Tue, 24 Sep 2024 17:04:10 +0800 Subject: [PATCH 3/8] skip delete dialog test cases --- .../dashboard/components/ApiTokenTable/__tests__/index.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx b/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx index cdc061c4a..82908f019 100644 --- a/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx +++ b/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx @@ -71,7 +71,7 @@ describe('Api Token Table', () => { }); }); -describe('DeleteTokenDialog', () => { +describe.skip('DeleteTokenDialog', () => { beforeEach(() => { mockUseApiToken.mockImplementation(() => ({ tokens: fakeTokens, From c424cb17f5edd7b646977a244d4276eefa8f10ab Mon Sep 17 00:00:00 2001 From: muhammad-ahmed Date: Tue, 24 Sep 2024 17:13:14 +0800 Subject: [PATCH 4/8] fix crashing issue and update translation --- .../ApiTokenTable/__tests__/index.test.tsx | 2 +- .../dashboard/components/ApiTokenTable/index.tsx | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx b/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx index 82908f019..cdc061c4a 100644 --- a/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx +++ b/src/features/dashboard/components/ApiTokenTable/__tests__/index.test.tsx @@ -71,7 +71,7 @@ describe('Api Token Table', () => { }); }); -describe.skip('DeleteTokenDialog', () => { +describe('DeleteTokenDialog', () => { beforeEach(() => { mockUseApiToken.mockImplementation(() => ({ tokens: fakeTokens, diff --git a/src/features/dashboard/components/ApiTokenTable/index.tsx b/src/features/dashboard/components/ApiTokenTable/index.tsx index 851b6bfad..697de1226 100644 --- a/src/features/dashboard/components/ApiTokenTable/index.tsx +++ b/src/features/dashboard/components/ApiTokenTable/index.tsx @@ -2,7 +2,7 @@ import React, { HTMLAttributes } from 'react'; import { Column } from 'react-table'; import { Button, Heading, Text } from '@deriv-com/quill-ui'; import { LabelPairedCirclePlusMdRegularIcon } from '@deriv/quill-icons'; -import Translate from '@docusaurus/Translate'; +import Translate, { translate } from '@docusaurus/Translate'; import { TTokenType } from '@site/src/types'; import { TDashboardTab } from '@site/src/contexts/app-manager/app-manager.context'; import Spinner from '@site/src/components/Spinner'; @@ -23,30 +23,30 @@ export type TTokenColumn = Column; const tableColumns: TTokenColumn[] = [ { - Header: Name, + Header: translate({ message: 'Name' }), accessor: 'display_name', }, { - Header: Account Type, + Header: translate({ message: 'Account Type' }), Cell: AccountTypeCell, }, { - Header: Token, + Header: translate({ message: 'Token' }), accessor: 'token', Cell: ApiTokenCell, }, { - Header: Token scopes, + Header: translate({ message: 'Token scopes' }), accessor: 'scopes', Cell: ScopesCell, }, { - Header: Last used, + Header: translate({ message: 'Last used' }), accessor: 'last_used', Cell: ApiLastUsedCell, }, { - Header: Actions, + Header: translate({ message: 'Actions' }), id: 'actions', accessor: (originalRow) => originalRow.token, Cell: ({ row }) => , From 6438ef5486fc5d241dc35fbfff96c5122eeed1f3 Mon Sep 17 00:00:00 2001 From: muhammad-ahmed Date: Fri, 27 Sep 2024 11:53:04 +0800 Subject: [PATCH 5/8] translation fixes --- i18n/en/code.json | 18 ++++++------- .../UserNavbarItem/item.desktop.tsx | 14 +++++++++- src/features/Apiexplorer/index.tsx | 18 ++++++++++++- .../dashboard/manage-dashboard/index.tsx | 26 +++++++++++++++---- .../update-app/AppUpdateForm/index.tsx | 18 ++++++++----- src/styles/index.scss | 1 - 6 files changed, 71 insertions(+), 24 deletions(-) diff --git a/i18n/en/code.json b/i18n/en/code.json index 9fa2d6a2f..4fe7e7a17 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -760,9 +760,6 @@ "Application ID": { "message": "Application ID" }, - "Redirect URL": { - "message": "Redirect URL" - }, "Actions": { "message": "Actions" }, @@ -1087,8 +1084,8 @@ "Use OAuth if your application requires other users to sign in.": { "message": "Use OAuth if your application requires other users to sign in." }, - "Authorisation URL is mandatory to enable OAuth on your app.": { - "message": "Authorisation URL is mandatory to enable OAuth on your app." + "Redirect URL is mandatory to enable OAuth on your app.": { + "message": "Redirect URL is mandatory to enable OAuth on your app." }, "URL Configuration": { "message": "URL Configuration" @@ -1096,14 +1093,14 @@ "To set up OAuth for your app, specify the URL where users should be redirected after authorisation.": { "message": "To set up OAuth for your app, specify the URL where users should be redirected after authorisation." }, - "Authorisation URL": { - "message": "Authorisation URL" + "Redirect URL": { + "message": "Redirect URL" }, "If your app includes verification logic, enter the email verification URL below (e.g. for account opening, verification, and password reset):": { "message": "If your app includes verification logic, enter the email verification URL below (e.g. for account opening, verification, and password reset):" }, - "If provided, the verification URL will be appended with a token and sent to the user's email. Otherwise, the authorisation URL with the token will be used.": { - "message": "If provided, the verification URL will be appended with a token and sent to the user's email. Otherwise, the authorisation URL with the token will be used." + "If provided, the verification URL will be appended with a token and sent to the user's email. Otherwise, the Redirect URL with the token will be used.": { + "message": "If provided, the verification URL will be appended with a token and sent to the user's email. Otherwise, the Redirect URL with the token will be used." }, "Scopes of authorisation": { "message": "Scopes of authorisation" @@ -1188,5 +1185,8 @@ }, "Note: You can make these changes later through the dashboard.": { "message": "Note: You can make these changes later through the dashboard." + }, + "documentation": { + "message": "documentation" } } diff --git a/src/components/UserNavbarItem/item.desktop.tsx b/src/components/UserNavbarItem/item.desktop.tsx index 7bb2bdf30..7bbd9594d 100644 --- a/src/components/UserNavbarItem/item.desktop.tsx +++ b/src/components/UserNavbarItem/item.desktop.tsx @@ -1,6 +1,7 @@ import React from 'react'; import clsx from 'clsx'; import Translate from '@docusaurus/Translate'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { Button } from '@deriv-com/quill-ui'; import { LabelPairedGridLgRegularIcon, @@ -8,6 +9,7 @@ import { } from '@deriv/quill-icons'; import useLogout from '@site/src/hooks/useLogout'; import useDeviceType from '@site/src/hooks/useDeviceType'; + import { IUserNavbarItemProps } from './item.types'; import styles from './UserNavbarItem.module.scss'; @@ -17,10 +19,20 @@ interface IActionProps { } const DashboardActions: React.FC = ({ handleClick, isDesktop }) => { + const { + i18n: { currentLocale }, + } = useDocusaurusContext(); + + const onClickDashboard = () => { + const is_en = currentLocale === 'en'; + const pathInfo = `${!is_en ? `/${currentLocale}` : ''}/dashboard`; + location.assign(pathInfo); + }; + return (