diff --git a/openmetadata-ui/src/main/resources/ui/src/components/MyData/MyData.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/MyData/MyData.test.tsx index 0693aaf54b2..c07c832b07c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/MyData/MyData.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/MyData/MyData.test.tsx @@ -301,10 +301,6 @@ jest.mock( ) ); -jest.mock('../../utils/EntityVersionUtils', () => ({ - getFeedSummary: jest.fn().mockImplementation(() =>

EntityVersionUtils

), -})); - jest.mock('../../utils/ServiceUtils', () => ({ getAllServices: jest .fn() diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetailsV1.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetailsV1.tsx index f6d69c9798d..78ef856dad8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetailsV1.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetailsV1.tsx @@ -286,7 +286,7 @@ const TeamDetailsV1 = ({ disabled={!entityPermissions.EditAll} icon={ @@ -554,7 +554,7 @@ const TeamDetailsV1 = ({ showErrorToast( error as AxiosError, t('server.entity-fetch-error', { - entity: 'User Permissions', + entity: t('label.user-permissions'), }) ); } finally { @@ -639,7 +639,9 @@ const TeamDetailsV1 = ({ ); const restoreIcon = useMemo( - () => , + () => ( + + ), [currentTeam.isJoinable] ); @@ -1366,7 +1368,7 @@ const TeamDetailsV1 = ({ okText={t('label.confirm')} title={`${t('label.remove-entity', { entity: getEntityName(selectedEntity?.record), - })} ${t('label.from')} ${getEntityName(currentTeam)}`} + })} ${t('label.from-lowercase')} ${getEntityName(currentTeam)}`} visible={!isUndefined(selectedEntity.record)} onCancel={() => setEntity(undefined)} onOk={async () => { @@ -1380,7 +1382,7 @@ const TeamDetailsV1 = ({ {t('label.sure-to-remove')}{' '} {`${getEntityName( selectedEntity.record - )} t('label.from') ${getEntityName(currentTeam)}?`} + )} t('label.from-lowercase') ${getEntityName(currentTeam)}?`} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json index 8fba3d0ec8f..9ba224a323c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json @@ -81,7 +81,7 @@ "sure-to-remove": "Are you sure you want to remove the", "confirm": "Confirm", "remove-entity": "Remove {{entity}}", - "from": "from", + "from-lowercase": "from", "add": "Add", "add-policy": "Add Policy", "go-back": "Go Back", @@ -473,6 +473,25 @@ "retention-size": "retention-size", "clean-up-policies": "clean-up policies", "maximum-size": "maximum size", + "add-term": "Add Term", + "accept-suggestion": "Accept Suggestion", + "edit-amp-accept-suggestion": "Edit & Accept Suggestion", + "to-lowercase": "to", + "of-lowercase": "of", + "description-lowercase": "description", + "started-following": "Started following", + "unfollowed": "Unfollowed", + "data-asset-has-been-action-type": "Data asset has been {{actionType}}", + "deleted-lowercase": "deleted", + "restored-lowercase": "restored", + "edited": "Edited", + "added-lowercase": "added", + "updated-lowercase": "updated", + "has-been-action-type-lowercase": "has been {{actionType}}", + "rules": "Rules", + "manage-rule": "Manage Rule", + "users": "Users", + "user-permissions": "User Permissions", "openmetadata": "OpenMetadata", "activity-feeds": "Activity Feeds", "search": "Search", @@ -504,13 +523,20 @@ "search-entity": "Search {{entity}}", "more": "More", "update": "Update", + "reply-in-conversation": "Reply in conversation", + "older-reply-lowercase": "older reply", + "older-replies-lowercase": "older replies", + "created-a-task-lowercase": "created a task", + "posted-on-lowercase": "posted on", + "announcement": "Announcement", + "conversation": "Conversation", + "url-lowercase": "url", + "schemas": "Schemas", "deleted": "Deleted {{entity}}", "test-plural": "Tests", "test": "Test", - "profiler": "Profiler", "here-lowercase": "here", "insert": "Insert", - "update": "Update", "table-profile": "Table Profile", "column-profile": "Column Profile", "applied-advanced-search": "Applied advanced search" diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json index 03736da792a..33080d371a4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json @@ -81,7 +81,7 @@ "sure-to-remove": "Etes-vous sûr de vouloir supprimer le", "confirm": "Confirmer", "remove-entity": "Supprimer {{entity}}", - "from": "de", + "from-lowercase": "de", "add": "Ajouter", "add-policy": "Ajouter une Police", "go-back": "Retour en arrière", diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.test.tsx index 2a20f6958f9..02983b6a881 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.test.tsx @@ -108,6 +108,12 @@ jest.mock('../../../utils/ToastUtils', () => ({ showErrorToast: jest.fn().mockReturnValue(''), })); +jest.mock('react-i18next', () => ({ + useTranslation: jest.fn().mockReturnValue({ + t: (label: string) => label, + }), +})); + describe('Test Policy details page', () => { it('Should render the policy details page component', async () => { render(); @@ -118,11 +124,11 @@ describe('Test Policy details page', () => { const description = await screen.findByTestId('description-data'); - const rulesTab = await screen.findByText('Rules'); + const rulesTab = await screen.findByText('label.rules'); - const rolesTab = await screen.findByText('Roles'); + const rolesTab = await screen.findByText('label.roles'); - const teamsTab = await screen.findByText('Teams'); + const teamsTab = await screen.findByText('label.teams'); expect(container).toBeInTheDocument(); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx index 964dff4d9c2..b464d6918a0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx @@ -21,18 +21,16 @@ import { Modal, Row, Space, - Table, Tabs, Tooltip, Typography, } from 'antd'; -import { ColumnsType } from 'antd/lib/table'; import { AxiosError } from 'axios'; import { compare } from 'fast-json-patch'; import { isEmpty, isUndefined, startCase } from 'lodash'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Link, useHistory, useParams } from 'react-router-dom'; +import { useHistory, useParams } from 'react-router-dom'; import { getPolicyByName, getRoleByName, @@ -54,10 +52,6 @@ import { GlobalSettingOptions, GlobalSettingsMenuCategory, } from '../../../constants/GlobalSettings.constants'; -import { - NO_PERMISSION_FOR_ACTION, - NO_PERMISSION_TO_VIEW, -} from '../../../constants/HelperTextUtil'; import { EntityType } from '../../../enums/entity.enum'; import { Rule } from '../../../generated/api/policies/createPolicy'; import { Policy } from '../../../generated/entity/policies/policy'; @@ -67,105 +61,17 @@ import { DEFAULT_ENTITY_PERMISSION } from '../../../utils/PermissionsUtils'; import { getAddPolicyRulePath, getEditPolicyRulePath, - getRoleWithFqnPath, getSettingPath, - getTeamsWithFqnPath, } from '../../../utils/RouterUtils'; import SVGIcons, { Icons } from '../../../utils/SvgUtils'; import { showErrorToast } from '../../../utils/ToastUtils'; import './PoliciesDetail.less'; +import PoliciesDetailsList from './PoliciesDetailsList.component'; const { TabPane } = Tabs; type Attribute = 'roles' | 'teams'; -const List = ({ - list, - type, - onDelete, - hasAccess, -}: { - list: EntityReference[]; - type: 'role' | 'team'; - onDelete: (record: EntityReference) => void; - hasAccess: boolean; -}) => { - const columns: ColumnsType = useMemo(() => { - return [ - { - title: 'Name', - dataIndex: 'name', - width: '200px', - key: 'name', - render: (_, record) => { - let link = ''; - switch (type) { - case 'role': - link = getRoleWithFqnPath(record.fullyQualifiedName || ''); - - break; - case 'team': - link = getTeamsWithFqnPath(record.fullyQualifiedName || ''); - - break; - - default: - break; - } - - return ( - - {getEntityName(record)} - - ); - }, - }, - { - title: 'Description', - dataIndex: 'description', - key: 'description', - render: (_, record) => ( - - ), - }, - { - title: 'Actions', - dataIndex: 'actions', - width: '80px', - key: 'actions', - render: (_, record) => { - return ( - - - - ); - }, - }, - ]; - }, []); - - return ( - - ); -}; - const PoliciesDetailPage = () => { const { t } = useTranslation(); const history = useHistory(); @@ -191,7 +97,7 @@ const PoliciesDetailPage = () => { const breadcrumb = useMemo( () => [ { - name: 'Policies', + name: t('label.policies'), url: policiesPath, }, { @@ -402,8 +308,8 @@ const PoliciesDetailPage = () => { + + ); + }, + }, + ]; + }, []); + + return ( +
+ ); +}; + +export default PoliciesDetailsList; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.test.tsx index ac7895e2631..e21fe6fc432 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.test.tsx @@ -88,9 +88,9 @@ describe('Test Roles Details Page', () => { const tabs = await screen.findByTestId('tabs'); - const policiesTab = await screen.findByText('Policies'); - const teamsTab = await screen.findByText('Teams'); - const usersTab = await screen.findByText('Users'); + const policiesTab = await screen.findByText('label.policies'); + const teamsTab = await screen.findByText('label.teams'); + const usersTab = await screen.findByText('label.users'); expect(container).toBeInTheDocument(); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx index 168aaa480a9..e6dc074dceb 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx @@ -11,20 +11,18 @@ * limitations under the License. */ -import { Button, Modal, Space, Table, Tabs, Tooltip, Typography } from 'antd'; -import { ColumnsType } from 'antd/lib/table'; +import { Button, Modal, Space, Tabs, Tooltip, Typography } from 'antd'; import { AxiosError } from 'axios'; import { compare } from 'fast-json-patch'; import { isEmpty, isUndefined } from 'lodash'; import React, { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Link, useHistory, useParams } from 'react-router-dom'; +import { useHistory, useParams } from 'react-router-dom'; import { getRoleByName, patchRole } from '../../../axiosAPIs/rolesAPIV1'; import { getTeamByName, patchTeamDetail } from '../../../axiosAPIs/teamsAPI'; import { getUserByName, updateUserDetail } from '../../../axiosAPIs/userAPI'; import Description from '../../../components/common/description/Description'; import ErrorPlaceHolder from '../../../components/common/error-with-placeholder/ErrorPlaceHolder'; -import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer'; import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component'; import Loader from '../../../components/Loader/Loader'; import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider'; @@ -32,29 +30,20 @@ import { OperationPermission, ResourceEntity, } from '../../../components/PermissionProvider/PermissionProvider.interface'; -import { getUserPath } from '../../../constants/constants'; import { GlobalSettingOptions, GlobalSettingsMenuCategory, } from '../../../constants/GlobalSettings.constants'; -import { - NO_PERMISSION_FOR_ACTION, - NO_PERMISSION_TO_VIEW, -} from '../../../constants/HelperTextUtil'; import { EntityType } from '../../../enums/entity.enum'; import { Role } from '../../../generated/entity/teams/role'; import { EntityReference } from '../../../generated/type/entityReference'; import { getEntityName } from '../../../utils/CommonUtils'; import { DEFAULT_ENTITY_PERMISSION } from '../../../utils/PermissionsUtils'; -import { - getPolicyWithFqnPath, - getSettingPath, - getTeamsWithFqnPath, -} from '../../../utils/RouterUtils'; -import SVGIcons, { Icons } from '../../../utils/SvgUtils'; +import { getSettingPath } from '../../../utils/RouterUtils'; import { showErrorToast } from '../../../utils/ToastUtils'; import AddAttributeModal from '../AddAttributeModal/AddAttributeModal'; import './RolesDetail.less'; +import RolesDetailPageList from './RolesDetailPageList.component'; const { TabPane } = Tabs; @@ -65,101 +54,6 @@ interface AddAttribute { selectedData: EntityReference[]; } -const List = ({ - list, - type, - onDelete, - hasAccess, -}: { - list: EntityReference[]; - type: 'policy' | 'team' | 'user'; - onDelete: (record: EntityReference) => void; - hasAccess: boolean; -}) => { - const columns: ColumnsType = useMemo(() => { - return [ - { - title: 'Name', - dataIndex: 'name', - width: '200px', - key: 'name', - render: (_, record) => { - let link = ''; - switch (type) { - case 'policy': - link = getPolicyWithFqnPath(record.fullyQualifiedName || ''); - - break; - case 'team': - link = getTeamsWithFqnPath(record.fullyQualifiedName || ''); - - break; - case 'user': - link = getUserPath(record.fullyQualifiedName || ''); - - break; - - default: - break; - } - - return ( - - {getEntityName(record)} - - ); - }, - }, - { - title: 'Description', - dataIndex: 'description', - key: 'description', - render: (_, record) => ( - - ), - }, - { - title: 'Actions', - dataIndex: 'actions', - width: '80px', - key: 'actions', - render: (_, record) => { - return ( - - - - ); - }, - }, - ]; - }, []); - - return ( -
- ); -}; - const RolesDetailPage = () => { const history = useHistory(); const { t } = useTranslation(); @@ -187,7 +81,7 @@ const RolesDetailPage = () => { const breadcrumb = useMemo( () => [ { - name: 'Roles', + name: t('label.roles'), url: rolesPath, }, { @@ -393,13 +287,13 @@ const RolesDetailPage = () => { /> - + - { /> - - + { } /> - - + { )} ) : ( - {NO_PERMISSION_TO_VIEW} + + {t('message.no-permission-to-view')} + )} {selectedEntity && ( { okText={t('label.confirm')} title={`${t('label.remove-entity', { entity: getEntityName(selectedEntity.record), - })} ${t('label.from')} ${getEntityName(role)}`} + })} ${t('label.from-lowercase')} ${getEntityName(role)}`} visible={!isUndefined(selectedEntity.record)} onCancel={() => setEntity(undefined)} onOk={async () => { @@ -469,7 +365,7 @@ const RolesDetailPage = () => { {t('label.sure-to-remove')}{' '} {`${getEntityName(selectedEntity.record)} ${t( - 'label.from' + 'label.from-lowercase' )} ${getEntityName(role)}?`} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPageList.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPageList.component.tsx new file mode 100644 index 00000000000..f3a8c4f9922 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPageList.component.tsx @@ -0,0 +1,129 @@ +/* + * Copyright 2022 Collate + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Button, Table, Tooltip } from 'antd'; +import { ColumnsType } from 'antd/lib/table'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; +import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer'; +import { getUserPath } from '../../../constants/constants'; +import { EntityReference } from '../../../generated/type/entityReference'; +import { getEntityName } from '../../../utils/CommonUtils'; +import { + getPolicyWithFqnPath, + getTeamsWithFqnPath, +} from '../../../utils/RouterUtils'; +import SVGIcons, { Icons } from '../../../utils/SvgUtils'; + +const RolesDetailPageList = ({ + list, + type, + onDelete, + hasAccess, +}: { + list: EntityReference[]; + type: 'policy' | 'team' | 'user'; + onDelete: (record: EntityReference) => void; + hasAccess: boolean; +}) => { + const { t } = useTranslation(); + const columns: ColumnsType = useMemo(() => { + return [ + { + title: t('label.name'), + dataIndex: 'name', + width: '200px', + key: 'name', + render: (_, record) => { + let link = ''; + switch (type) { + case 'policy': + link = getPolicyWithFqnPath(record.fullyQualifiedName || ''); + + break; + case 'team': + link = getTeamsWithFqnPath(record.fullyQualifiedName || ''); + + break; + case 'user': + link = getUserPath(record.fullyQualifiedName || ''); + + break; + + default: + break; + } + + return ( + + {getEntityName(record)} + + ); + }, + }, + { + title: t('label.description'), + dataIndex: 'description', + key: 'description', + render: (_, record) => ( + + ), + }, + { + title: t('label.actions'), + dataIndex: 'actions', + width: '80px', + key: 'actions', + render: (_, record) => { + return ( + + + + ); + }, + }, + ]; + }, []); + + return ( +
+ ); +}; + +export default RolesDetailPageList; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DashboardDetailsUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/DashboardDetailsUtils.ts index 442be6e9941..1f005510d0d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/DashboardDetailsUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/DashboardDetailsUtils.ts @@ -11,6 +11,7 @@ * limitations under the License. */ +import i18next from 'i18next'; import { TabSpecificField } from '../enums/entity.enum'; import { ChartType } from '../pages/DashboardDetailsPage/DashboardDetailsPage.component'; import { sortTagsCaseInsensitive } from './CommonUtils'; @@ -20,21 +21,21 @@ ${TabSpecificField.USAGE_SUMMARY}, ${TabSpecificField.CHARTS},${TabSpecificField export const dashboardDetailsTabs = [ { - name: 'Details', + name: i18next.t('label.details'), path: 'details', }, { - name: 'Activity Feeds & Tasks', + name: i18next.t('label.activity-feed-and-task-plural'), path: 'activity_feed', field: TabSpecificField.ACTIVITY_FEED, }, { - name: 'Lineage', + name: i18next.t('label.lineage'), path: 'lineage', field: TabSpecificField.LINEAGE, }, { - name: 'Custom Properties', + name: i18next.t('label.custom-properties'), path: 'custom_properties', }, ]; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseDetailsUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseDetailsUtils.ts index 42a22094fa6..317f7e05466 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseDetailsUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/DatabaseDetailsUtils.ts @@ -1,12 +1,13 @@ +import i18next from 'i18next'; import { TabSpecificField } from '../enums/entity.enum'; export const databaseDetailsTabs = [ { - name: 'Schemas', + name: i18next.t('label.schemas'), path: 'schemas', }, { - name: 'Activity Feeds', + name: i18next.t('label.activity-feeds'), path: 'activity_feed', field: TabSpecificField.ACTIVITY_FEED, }, diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DatasetDetailsUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/DatasetDetailsUtils.ts index 01b7c99f7da..0b313407f5e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/DatasetDetailsUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/DatasetDetailsUtils.ts @@ -11,6 +11,7 @@ * limitations under the License. */ +import i18next from 'i18next'; import { TabSpecificField } from '../enums/entity.enum'; export const defaultFields = `${TabSpecificField.COLUMNS}, ${TabSpecificField.USAGE_SUMMARY}, @@ -19,41 +20,41 @@ ${TabSpecificField.DATAMODEL},${TabSpecificField.TABLE_CONSTRAINTS},${TabSpecifi export const datasetTableTabs = [ { - name: 'Schema', + name: i18next.t('label.schema'), path: 'schema', }, { - name: 'Activity Feeds & Tasks', + name: i18next.t('label.activity-feed-and-task-plural'), path: 'activity_feed', field: TabSpecificField.ACTIVITY_FEED, }, { - name: 'Sample Data', + name: i18next.t('label.sample-data'), path: 'sample_data', }, { - name: 'Queries', + name: i18next.t('label.query-plural'), path: 'table_queries', }, { - name: 'Profiler', + name: i18next.t('label.profiler'), path: 'profiler', }, { - name: 'Data Quality', + name: i18next.t('label.data-quality'), path: 'data-quality', }, { - name: 'Lineage', + name: i18next.t('label.lineage'), path: 'lineage', field: TabSpecificField.LINEAGE, }, { - name: 'DBT', + name: i18next.t('label.dbt-uppercase'), path: 'dbt', }, { - name: 'Custom Properties', + name: i18next.t('label.custom-properties'), path: 'custom_properties', }, ]; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx index eff1b2b11a0..eecb15c5686 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx @@ -11,6 +11,7 @@ * limitations under the License. */ +import i18next from 'i18next'; import { isEmpty, isNil, isUndefined, lowerCase, startCase } from 'lodash'; import { Bucket, LeafNodes, LineagePos } from 'Models'; import React, { Fragment } from 'react'; @@ -113,7 +114,7 @@ export const getEntityOverview = ( const overview = [ { - name: 'Service', + name: i18next.t('label.service'), value: service, url: getServiceDetailsPath( service, @@ -122,7 +123,7 @@ export const getEntityOverview = ( isLink: true, }, { - name: 'Database', + name: i18next.t('label.database'), value: database, url: getDatabaseDetailsPath( getPartialNameFromTableFQN( @@ -134,7 +135,7 @@ export const getEntityOverview = ( isLink: true, }, { - name: 'Schema', + name: i18next.t('label.schema'), value: schema, url: getDatabaseSchemaDetailsPath( getPartialNameFromTableFQN( @@ -146,33 +147,33 @@ export const getEntityOverview = ( isLink: true, }, { - name: 'Owner', + name: i18next.t('label.owner'), value: getEntityName(owner) || '--', url: getTeamAndUserDetailsPath(owner?.name || ''), isLink: owner ? owner.type === 'team' : false, }, { - name: 'Tier', + name: i18next.t('label.tier'), value: tier ? tier.split(FQN_SEPARATOR_CHAR)[1] : '--', isLink: false, }, { - name: 'Usage', + name: i18next.t('label.usage'), value: usage, isLink: false, }, { - name: 'Queries', + name: i18next.t('label.query-plural'), value: `${queries} past week`, isLink: false, }, { - name: 'Columns', + name: i18next.t('label.columns-plural'), value: columns ? columns.length : '--', isLink: false, }, { - name: 'Rows', + name: i18next.t('label.row-plural'), value: profile && profile?.rowCount ? profile.rowCount : '--', isLink: false, }, @@ -188,7 +189,7 @@ export const getEntityOverview = ( const overview = [ { - name: 'Service', + name: i18next.t('label.service'), value: service?.name as string, url: getServiceDetailsPath( service?.name as string, @@ -197,18 +198,18 @@ export const getEntityOverview = ( isLink: true, }, { - name: 'Owner', + name: i18next.t('label.owner'), value: getEntityName(owner) || '--', url: getTeamAndUserDetailsPath(owner?.name || ''), isLink: owner ? owner.type === 'team' : false, }, { - name: 'Tier', + name: i18next.t('label.tier'), value: tier ? tier.split(FQN_SEPARATOR_CHAR)[1] : '--', isLink: false, }, { - name: `${serviceType} url`, + name: `${serviceType} ${i18next.t('label.url-lowercase')}`, value: fullyQualifiedName?.split(FQN_SEPARATOR_CHAR)[1] as string, url: pipelineUrl as string, isLink: true, @@ -231,7 +232,7 @@ export const getEntityOverview = ( const overview = [ { - name: 'Service', + name: i18next.t('label.service'), value: service?.name as string, url: getServiceDetailsPath( service?.name as string, @@ -240,18 +241,18 @@ export const getEntityOverview = ( isLink: true, }, { - name: 'Owner', + name: i18next.t('label.owner'), value: getEntityName(owner) || '--', url: getTeamAndUserDetailsPath(owner?.name || ''), isLink: owner ? owner.type === 'team' : false, }, { - name: 'Tier', + name: i18next.t('label.tier'), value: tier ? tier.split(FQN_SEPARATOR_CHAR)[1] : '--', isLink: false, }, { - name: `${serviceType} url`, + name: `${serviceType} ${i18next.t('label.url-lowercase')}`, value: displayName || (fullyQualifiedName?.split(FQN_SEPARATOR_CHAR)[1] as string), diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx index 8aba97cf9c0..e9b7572efa3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx @@ -19,27 +19,19 @@ import { diffWords, diffWordsWithSpace, } from 'diff'; -import { isEmpty, isUndefined, uniqueId } from 'lodash'; +import { t } from 'i18next'; +import { isUndefined, uniqueId } from 'lodash'; import React, { Fragment } from 'react'; import ReactDOMServer from 'react-dom/server'; -import { Link } from 'react-router-dom'; -import { FQN_SEPARATOR_CHAR } from '../constants/char.constants'; -import { - DESCRIPTIONLENGTH, - getTeamAndUserDetailsPath, -} from '../constants/constants'; import { EntityField } from '../constants/Feeds.constants'; -import { ChangeType } from '../enums/entity.enum'; import { Column } from '../generated/entity/data/table'; import { ChangeDescription, FieldChange, } from '../generated/entity/services/databaseService'; import { TagLabel } from '../generated/type/tagLabel'; -import { getEntityName } from './CommonUtils'; import { TagLabelWithStatus } from './EntityVersionUtils.interface'; import { isValidJSONString } from './StringsUtils'; -import { getEntityLink } from './TableUtils'; export const getDiffByFieldName = ( name: string, @@ -143,328 +135,6 @@ export const getTagsDiff = ( return result; }; -export const getPreposition = (type: ChangeType) => { - switch (type) { - case 'Added': - return 'to'; - - case 'Removed': - return 'from'; - - case 'Updated': - return 'of'; - - default: - return ''; - } -}; - -const getColumnName = (column: string) => { - const name = column.split(FQN_SEPARATOR_CHAR); - const length = name.length; - - return name - .slice(length > 1 ? 1 : 0, length > 1 ? length - 1 : length) - .join(FQN_SEPARATOR_CHAR); -}; - -const getLinkWithColumn = (column: string, eFqn: string, eType: string) => { - return ( - - {getColumnName(column)} - - ); -}; - -const getDescriptionText = (value: string) => { - const length = value.length; - - return `${value.slice(0, DESCRIPTIONLENGTH)}${ - length > DESCRIPTIONLENGTH ? '...' : '' - }`; -}; - -const getDescriptionElement = (fieldChange: FieldChange) => { - return fieldChange?.newValue && fieldChange?.oldValue ? ( - -   - {`${getDescriptionText( - fieldChange?.newValue - )}`} - - ) : fieldChange?.newValue ? ( - -   - - {`${getDescriptionText(fieldChange?.newValue)}`} - - - ) : ( - -   - - {`${getDescriptionText(fieldChange?.oldValue)}`} - - - ); -}; - -export const feedSummaryFromatter = ( - fieldChange: FieldChange, - type: ChangeType, - _entityName: string, - entityType: string, - entityFQN: string -) => { - const value = JSON.parse( - isValidJSONString(fieldChange?.newValue) - ? fieldChange?.newValue - : isValidJSONString(fieldChange?.oldValue) - ? fieldChange?.oldValue - : '{}' - ); - const oldValue = JSON.parse( - isValidJSONString(fieldChange?.oldValue) ? fieldChange?.oldValue : '{}' - ); - const newValue = JSON.parse( - isValidJSONString(fieldChange?.newValue) ? fieldChange?.newValue : '{}' - ); - let summary: JSX.Element; - switch (true) { - case fieldChange?.name?.startsWith('column'): { - if (fieldChange?.name?.endsWith('tags')) { - summary = ( -

- {`${type} tags ${value - ?.map((val: TagLabel) => val?.tagFQN) - ?.join(', ')} ${getPreposition(type)} column`} - {getLinkWithColumn( - fieldChange?.name as string, - entityFQN, - entityType - )} -

- ); - - break; - } else if (fieldChange?.name?.endsWith(EntityField.DESCRIPTION)) { - summary = ( -

- {`${ - fieldChange?.newValue && fieldChange?.oldValue - ? type - : fieldChange?.newValue - ? 'Added' - : 'Removed' - } column description for`} - {getLinkWithColumn( - fieldChange?.name as string, - entityFQN, - entityType - )} - {isEmpty(value) ? getDescriptionElement(fieldChange) : ''} -

- ); - - break; - } else if (fieldChange?.name === EntityField.COLUMNS) { - const length = value?.length ?? 0; - summary = ( -

- {`${type} ${fieldChange?.name}`}{' '} - {value?.map((column: Column, i: number) => ( - - {getLinkWithColumn(column.name, entityFQN, entityType)}{' '} - {i !== length - 1 ? ', ' : ''} - - ))} -

- ); - - break; - } else { - summary = ( -

- {`${type}`} - {getLinkWithColumn( - fieldChange?.name as string, - entityFQN, - entityType - )} -

- ); - - break; - } - } - - case fieldChange?.name === 'tags': { - const tier = value?.find((t: TagLabel) => t?.tagFQN?.startsWith('Tier')); - const tags = value?.filter( - (t: TagLabel) => !t?.tagFQN?.startsWith('Tier') - ); - summary = ( -
- {tags?.length > 0 ? ( -

{`${type} tags ${tags - ?.map((val: TagLabel) => val?.tagFQN) - ?.join(', ')}`}

- ) : null} - {tier ? ( -

{`${type} tier ${ - tier?.tagFQN?.split(FQN_SEPARATOR_CHAR)[1] - }`}

- ) : null} -
- ); - - break; - } - - case fieldChange?.name === 'owner': { - const ownerName = getEntityName(newValue) || getEntityName(value); - const ownerText = - !isEmpty(oldValue) && !isEmpty(newValue) ? ( - - {newValue?.type === 'team' ? ( - - {ownerName} - - ) : ( - - {ownerName} - - )} - - ) : ( - - {value?.type === 'team' ? ( - - {ownerName} - - ) : ( - - {ownerName} - - )} - - ); - summary = ( -

32, - })} - key={uniqueId()}> - {`Assigned ownership to ${ownerText}`} -

- ); - - break; - } - - case fieldChange?.name === EntityField.DESCRIPTION: { - summary = ( -

- {`${ - fieldChange?.newValue && fieldChange?.oldValue - ? type - : fieldChange?.newValue - ? 'Added' - : 'Removed' - } description`} - {getDescriptionElement(fieldChange)} -

- ); - - break; - } - - case fieldChange?.name === 'followers': { - summary = ( -

{`${ - fieldChange?.newValue ? 'Started following' : 'Unfollowed' - } ${_entityName}`}

- ); - - break; - } - - default: - summary =

{`${type} ${fieldChange?.name}`}

; - - break; - } - - return summary; -}; - -export const getFeedSummary = ( - changeDescription: ChangeDescription, - entityName: string, - entityType: string, - entityFQN: string -) => { - const fieldsAdded = [...(changeDescription?.fieldsAdded || [])]; - const fieldsDeleted = [...(changeDescription?.fieldsDeleted || [])]; - const fieldsUpdated = [...(changeDescription?.fieldsUpdated || [])]; - - return ( - - {fieldsDeleted?.length ? ( -
- {fieldsDeleted?.map((d) => ( - - {feedSummaryFromatter( - d, - ChangeType.REMOVED, - entityName, - entityType, - entityFQN - )} - - ))} -
- ) : null} - {fieldsAdded?.length > 0 ? ( -
- {fieldsAdded?.map((a) => ( - - {feedSummaryFromatter( - a, - ChangeType.ADDED, - entityName, - entityType, - entityFQN - )} - - ))} -
- ) : null} - {fieldsUpdated?.length ? ( -
- {fieldsUpdated?.map((u) => ( - - {feedSummaryFromatter( - u, - ChangeType.UPDATED, - entityName, - entityType, - entityFQN - )} - - ))} -
- ) : null} -
- ); -}; - export const summaryFormatter = (fieldChange: FieldChange) => { const value = JSON.parse( isValidJSONString(fieldChange?.newValue) @@ -511,31 +181,53 @@ export const getSummary = ( {isDeleteUpdated .map((field) => { return field.newValue - ? 'Data asset has been deleted' - : 'Data asset has been restored'; + ? t('label.data-asset-has-been-action-type', { + actionType: t('label.deleted-lowercase'), + }) + : t('label.data-asset-has-been-action-type', { + actionType: t('label.restored-lowercase'), + }); }) .join(', ')}

) : null} {fieldsAdded?.length > 0 ? (

- {`${isPrefix ? '+ Added' : ''} ${fieldsAdded + {`${isPrefix ? `+ ${t('label.added')}` : ''} ${fieldsAdded .map(summaryFormatter) - .join(', ')} ${!isPrefix ? `has been added` : ''}`}{' '} + .join(', ')} ${ + !isPrefix + ? t('label.has-been-action-type-lowercase', { + actionType: t('label.added-lowercase'), + }) + : '' + }`}{' '}

) : null} {fieldsUpdated?.length ? (

- {`${isPrefix ? 'Edited' : ''} ${fieldsUpdated + {`${isPrefix ? t('label.edited') : ''} ${fieldsUpdated .map(summaryFormatter) - .join(', ')} ${!isPrefix ? `has been updated` : ''}`}{' '} + .join(', ')} ${ + !isPrefix + ? t('label.has-been-action-type-lowercase', { + actionType: t('label.updated-lowercase'), + }) + : '' + }`}{' '}

) : null} {fieldsDeleted?.length ? (

{`${isPrefix ? '- Removed' : ''} ${fieldsDeleted .map(summaryFormatter) - .join(', ')} ${!isPrefix ? `has been Deleted` : ''}`}{' '} + .join(', ')} ${ + !isPrefix + ? t('label.has-been-action-type-lowercase', { + actionType: t('label.deleted-lowercase'), + }) + : '' + }`}{' '}

) : null} diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx index c978b2d98d3..b18aa9e592e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/FeedUtils.tsx @@ -15,6 +15,7 @@ import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { AxiosError } from 'axios'; import { Operation } from 'fast-json-patch'; +import i18next from 'i18next'; import { isEqual } from 'lodash'; import { EntityFieldThreadCount, @@ -112,10 +113,15 @@ export const getReplyText = ( singular?: string, plural?: string ) => { - if (count === 0) return 'Reply in conversation'; - if (count === 1) return `${count} ${singular ? singular : 'older reply'}`; + if (count === 0) return i18next.t('label.reply-in-conversation'); + if (count === 1) + return `${count} ${ + singular ? singular : i18next.t('label.older-reply-lowercase') + }`; - return `${count} ${plural ? plural : 'older replies'}`; + return `${count} ${ + plural ? plural : i18next.t('label.older-replies-lowercase') + }`; }; export const getEntityFieldThreadCounts = ( @@ -481,10 +487,10 @@ export const updateThreadData = ( export const getFeedAction = (type: ThreadType) => { if (type === ThreadType.Task) { - return 'created a task'; + return i18next.t('label.created-a-task-lowercase'); } - return 'posted on'; + return i18next.t('label.posted-on-lowercase'); }; export const prepareFeedLink = (entityType: string, entityFQN: string) => { @@ -553,11 +559,11 @@ export const getFeedPanelHeaderText = ( ) => { switch (threadType) { case ThreadType.Announcement: - return 'Announcement'; + return i18next.t('label.announcement'); case ThreadType.Task: - return 'Task'; + return i18next.t('label.task'); case ThreadType.Conversation: default: - return 'Conversation'; + return i18next.t('label.Conversation'); } }; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts index 6489591323d..96a4922a3f6 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts @@ -12,6 +12,7 @@ */ import { AxiosError } from 'axios'; +import { t } from 'i18next'; import { cloneDeep, isEmpty } from 'lodash'; import { FormattedGlossarySuggestion } from 'Models'; import { DataNode } from 'rc-tree/lib/interface'; @@ -230,7 +231,7 @@ export const updateGlossaryListBySearchedTerms = ( export const getActionsList = () => { return [ { - name: 'Add Term', + name: t('label.add-term'), value: 'add_term', }, ]; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts index 0f6e3c9913d..40c08235e9c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts @@ -13,6 +13,7 @@ import { AxiosError } from 'axios'; import { Change, diffWordsWithSpace } from 'diff'; +import { t } from 'i18next'; import { isEqual, isUndefined } from 'lodash'; import { getDashboardByFqn } from '../axiosAPIs/dashboardAPI'; import { getUserSuggestions } from '../axiosAPIs/miscAPI'; @@ -311,11 +312,11 @@ export const fetchEntityDetail = ( export const TASK_ACTION_LIST = [ { - label: 'Accept Suggestion', + label: t('label.accept-suggestion'), key: TaskActionMode.VIEW, }, { - label: 'Edit & Accept Suggestion', + label: t('label.edit-amp-accept-suggestion'), key: TaskActionMode.EDIT, }, ];