fix: glossary feedbacks (#13594)

* fix: glossary feedbacks

* fix: localization keys

* fix: encoding issues in glossary

* fix: glossary approval reload

* fix: minor glossary issues

* fix: update position of custom attrs in settings page

* fix: sync permission and domain provider calls
This commit is contained in:
karanh37 2023-10-17 21:54:22 +05:30 committed by GitHub
parent 53576b0a7a
commit 4ecfc2ac5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 265 additions and 164 deletions

View File

@ -200,12 +200,10 @@ export const ActivityFeedTab = ({
}, [fqn]);
const { feedFilter, threadType } = useMemo(() => {
let filter;
if (!isUserEntity) {
filter = currentUser?.isAdmin
? FeedFilter.ALL
: FeedFilter.OWNER_OR_FOLLOWS;
}
const currentFilter = currentUser?.isAdmin
? FeedFilter.ALL
: FeedFilter.OWNER_OR_FOLLOWS;
const filter = isUserEntity ? currentFilter : undefined;
return {
threadType:

View File

@ -12,6 +12,7 @@
*/
import { ItemType, MenuItemType } from 'antd/lib/menu/hooks/useItems';
import { AxiosError } from 'axios';
import { isEmpty } from 'lodash';
import React, {
FC,
ReactNode,
@ -29,7 +30,7 @@ import {
import { Domain } from '../../../generated/entity/domains/domain';
import { getDomainList } from '../../../rest/domainAPI';
import { showErrorToast } from '../../../utils/ToastUtils';
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
import { usePermissionProvider } from '../../PermissionProvider/PermissionProvider';
import { DomainContextType } from './DomainProvider.interface';
export const DomainContext = React.createContext({} as DomainContextType);
@ -42,7 +43,7 @@ const DomainProvider: FC<Props> = ({ children }: Props) => {
const { t } = useTranslation();
const [domains, setDomains] = useState<Domain[]>([]);
const [domainLoading, setDomainLoading] = useState(false);
const { isAuthenticated } = useAuthContext();
const { permissions } = usePermissionProvider();
const localStorageData =
localStorage.getItem(ACTIVE_DOMAIN_STORAGE_KEY) ?? DEFAULT_DOMAIN_VALUE;
@ -121,10 +122,10 @@ const DomainProvider: FC<Props> = ({ children }: Props) => {
]);
useEffect(() => {
if (isAuthenticated) {
if (!isEmpty(permissions)) {
fetchDomainList();
}
}, [isAuthenticated]);
}, [permissions]);
return (
<DomainContext.Provider value={domainContextObj}>

View File

@ -22,7 +22,6 @@ import { EntityType } from '../../../enums/entity.enum';
import { ChangeDescription } from '../../../generated/entity/type';
import { getFeedCounts } from '../../../utils/CommonUtils';
import { getEntityVersionByField } from '../../../utils/EntityVersionUtils';
import { getEncodedFqn } from '../../../utils/StringsUtils';
import { ActivityFeedTab } from '../../ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import DescriptionV1 from '../../common/description/DescriptionV1';
import TabsLabel from '../../TabsLabel/TabsLabel.component';
@ -110,7 +109,7 @@ const GlossaryDetails = ({
const getEntityFeedCount = () => {
getFeedCounts(
EntityType.GLOSSARY,
getEncodedFqn(glossary.fullyQualifiedName ?? ''),
glossary.fullyQualifiedName ?? '',
setFeedCount
);
};

View File

@ -137,6 +137,14 @@ const GlossaryHeader = ({
}
};
const glossaryTermStatus: Status | null = useMemo(() => {
if (!isGlossary) {
return (selectedData as GlossaryTerm).status ?? Status.Approved;
}
return null;
}, [isGlossary, selectedData]);
const editDisplayNamePermission = useMemo(() => {
return permissions.EditAll || permissions.EditDisplayName;
}, [permissions]);
@ -419,25 +427,29 @@ const GlossaryHeader = ({
{t('label.add-entity', { entity: t('label.term-lowercase') })}
</Button>
) : (
<Dropdown
className="m-l-xs"
menu={{
items: addButtonContent,
}}
placement="bottomRight"
trigger={['click']}>
<Button type="primary">
<Space>
{t('label.add')}
<DownOutlined />
</Space>
</Button>
</Dropdown>
<>
{glossaryTermStatus && glossaryTermStatus === Status.Approved && (
<Dropdown
className="m-l-xs"
menu={{
items: addButtonContent,
}}
placement="bottomRight"
trigger={['click']}>
<Button type="primary">
<Space>
{t('label.add')}
<DownOutlined />
</Space>
</Button>
</Dropdown>
)}
</>
);
}
return null;
}, [isGlossary, permissions, addButtonContent]);
}, [isGlossary, permissions, addButtonContent, glossaryTermStatus]);
/**
* To create breadcrumb from the fqn
@ -529,7 +541,7 @@ const GlossaryHeader = ({
</Button>
)}
{!isVersionView && (
{!isVersionView && manageButtonContent.length > 0 && (
<Dropdown
align={{ targetOffset: [-12, 0] }}
className="m-l-xs"

View File

@ -95,6 +95,14 @@ const GlossaryTermTab = ({
const [isTableLoading, setIsTableLoading] = useState(false);
const [isTableHovered, setIsTableHovered] = useState(false);
const glossaryTermStatus: Status | null = useMemo(() => {
if (!isGlossary) {
return (selectedData as GlossaryTerm).status ?? Status.Approved;
}
return null;
}, [isGlossary, selectedData]);
const columns = useMemo(() => {
const data: ColumnsType<ModifiedGlossaryTerm> = [
{
@ -171,38 +179,48 @@ const GlossaryTermTab = ({
title: t('label.action-plural'),
key: 'new-term',
width: 80,
render: (_, record) => (
<div className="d-flex items-center">
<Tooltip
title={t('label.add-entity', {
entity: t('label.glossary-term'),
})}>
<Button
className="add-new-term-btn text-grey-muted flex-center"
data-testid="add-classification"
icon={<PlusOutlinedIcon color={DE_ACTIVE_COLOR} width="14px" />}
size="small"
type="text"
onClick={() => {
onAddGlossaryTerm(record as GlossaryTerm);
}}
/>
</Tooltip>
<Tooltip
title={t('label.edit-entity', {
entity: t('label.glossary-term'),
})}>
<Button
className="cursor-pointer flex-center"
data-testid="edit-button"
icon={<EditIcon color={DE_ACTIVE_COLOR} width="14px" />}
size="small"
type="text"
onClick={() => onEditGlossaryTerm(record as GlossaryTerm)}
/>
</Tooltip>
</div>
),
render: (_, record) => {
const status = record.status ?? Status.Approved;
const allowAddTerm = status === Status.Approved;
return (
<div className="d-flex items-center">
{allowAddTerm && (
<Tooltip
title={t('label.add-entity', {
entity: t('label.glossary-term'),
})}>
<Button
className="add-new-term-btn text-grey-muted flex-center"
data-testid="add-classification"
icon={
<PlusOutlinedIcon color={DE_ACTIVE_COLOR} width="14px" />
}
size="small"
type="text"
onClick={() => {
onAddGlossaryTerm(record as GlossaryTerm);
}}
/>
</Tooltip>
)}
<Tooltip
title={t('label.edit-entity', {
entity: t('label.glossary-term'),
})}>
<Button
className="cursor-pointer flex-center"
data-testid="edit-button"
icon={<EditIcon color={DE_ACTIVE_COLOR} width="14px" />}
size="small"
type="text"
onClick={() => onEditGlossaryTerm(record as GlossaryTerm)}
/>
</Tooltip>
</div>
);
},
});
}
@ -332,7 +350,7 @@ const GlossaryTermTab = ({
heading={t('label.glossary-term')}
permission={permissions.Create}
type={
permissions.Create
permissions.Create && glossaryTermStatus === Status.Approved
? ERROR_PLACEHOLDER_TYPE.CREATE
: ERROR_PLACEHOLDER_TYPE.NO_DATA
}

View File

@ -107,7 +107,7 @@ describe('Test GlossaryTermTab component', () => {
expect(getAllByText(container, 'OwnerLabel')).toHaveLength(2);
expect(getAllByTestId(container, 'add-classification')).toHaveLength(2);
expect(getAllByTestId(container, 'add-classification')).toHaveLength(1);
expect(getAllByTestId(container, 'edit-button')).toHaveLength(2);
});
});

View File

@ -13,51 +13,35 @@
import { Col, Row, Tabs } from 'antd';
import { t } from 'i18next';
import { noop } from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import { getGlossaryTermDetailsPath } from '../../../constants/constants';
import { EntityField } from '../../../constants/Feeds.constants';
import { myDataSearchIndex } from '../../../constants/Mydata.constants';
import { EntityTabs, EntityType } from '../../../enums/entity.enum';
import { GlossaryTerm } from '../../../generated/entity/data/glossaryTerm';
import {
GlossaryTerm,
Status,
} from '../../../generated/entity/data/glossaryTerm';
import { ChangeDescription } from '../../../generated/entity/type';
import { MOCK_GLOSSARY_NO_PERMISSIONS } from '../../../mocks/Glossary.mock';
import { searchData } from '../../../rest/miscAPI';
import { getCountBadge, getFeedCounts } from '../../../utils/CommonUtils';
import { getEntityVersionByField } from '../../../utils/EntityVersionUtils';
import { getQueryFilterToExcludeTerm } from '../../../utils/GlossaryUtils';
import { getGlossaryTermsVersionsPath } from '../../../utils/RouterUtils';
import { getEncodedFqn } from '../../../utils/StringsUtils';
import { ActivityFeedTab } from '../../ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import { AssetSelectionModal } from '../../Assets/AssetsSelectionModal/AssetSelectionModal';
import { CustomPropertyTable } from '../../common/CustomPropertyTable/CustomPropertyTable';
import { EntityDetailsObjectInterface } from '../../Explore/explore.interface';
import { OperationPermission } from '../../PermissionProvider/PermissionProvider.interface';
import TabsLabel from '../../TabsLabel/TabsLabel.component';
import { VotingDataProps } from '../../Voting/voting.interface';
import { GlossaryTabs } from '../GlossaryDetails/GlossaryDetails.interface';
import GlossaryHeader from '../GlossaryHeader/GlossaryHeader.component';
import GlossaryTermTab from '../GlossaryTermTab/GlossaryTermTab.component';
import { GlossaryTermsV1Props } from './GlossaryTermsV1.interface';
import AssetsTabs, { AssetsTabRef } from './tabs/AssetsTabs.component';
import { AssetsOfEntity } from './tabs/AssetsTabs.interface';
import GlossaryOverviewTab from './tabs/GlossaryOverviewTab.component';
type Props = {
isVersionView?: boolean;
permissions: OperationPermission;
glossaryTerm: GlossaryTerm;
childGlossaryTerms: GlossaryTerm[];
handleGlossaryTermUpdate: (data: GlossaryTerm) => Promise<void>;
handleGlossaryTermDelete: (id: string) => void;
refreshGlossaryTerms: () => void;
onAssetClick?: (asset?: EntityDetailsObjectInterface) => void;
isSummaryPanelOpen: boolean;
termsLoading: boolean;
onAddGlossaryTerm: (glossaryTerm: GlossaryTerm | undefined) => void;
onEditGlossaryTerm: (glossaryTerm: GlossaryTerm) => void;
updateVote?: (data: VotingDataProps) => Promise<void>;
};
const GlossaryTermsV1 = ({
glossaryTerm,
childGlossaryTerms,
@ -71,8 +55,9 @@ const GlossaryTermsV1 = ({
onAddGlossaryTerm,
onEditGlossaryTerm,
updateVote,
refreshActiveGlossaryTerm,
isVersionView,
}: Props) => {
}: GlossaryTermsV1Props) => {
const {
fqn: glossaryFqn,
tab,
@ -84,6 +69,14 @@ const GlossaryTermsV1 = ({
const [feedCount, setFeedCount] = useState<number>(0);
const [assetCount, setAssetCount] = useState<number>(0);
const assetPermissions = useMemo(() => {
const glossaryTermStatus = glossaryTerm.status ?? Status.Approved;
return glossaryTermStatus === Status.Approved
? permissions
: MOCK_GLOSSARY_NO_PERMISSIONS;
}, [glossaryTerm, permissions]);
const activeTab = useMemo(() => {
return tab ?? 'overview';
}, [tab]);
@ -99,7 +92,7 @@ const GlossaryTermsV1 = ({
const getEntityFeedCount = () => {
getFeedCounts(
EntityType.GLOSSARY_TERM,
getEncodedFqn(glossaryTerm.fullyQualifiedName ?? ''),
glossaryTerm.fullyQualifiedName ?? '',
setFeedCount
);
};
@ -170,7 +163,7 @@ const GlossaryTermsV1 = ({
<AssetsTabs
assetCount={assetCount}
isSummaryPanelOpen={isSummaryPanelOpen}
permissions={permissions}
permissions={assetPermissions}
ref={assetTabRef}
onAddAsset={() => setAssetModelVisible(true)}
onAssetClick={onAssetClick}
@ -192,34 +185,34 @@ const GlossaryTermsV1 = ({
entityType={EntityType.GLOSSARY_TERM}
fqn={glossaryTerm.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={noop}
onUpdateEntityDetails={refreshActiveGlossaryTerm}
/>
),
},
{
label: (
<TabsLabel
id={EntityTabs.CUSTOM_PROPERTIES}
name={t('label.custom-property-plural')}
/>
),
key: EntityTabs.CUSTOM_PROPERTIES,
children: (
<CustomPropertyTable
entityDetails={isVersionView ? glossaryTerm : undefined}
entityType={EntityType.GLOSSARY_TERM}
handleExtensionUpdate={onExtensionUpdate}
hasEditAccess={
!isVersionView &&
(permissions.EditAll || permissions.EditCustomFields)
}
hasPermission={permissions.ViewAll}
isVersionView={isVersionView}
/>
),
},
]
: []),
{
label: (
<TabsLabel
id={EntityTabs.CUSTOM_PROPERTIES}
name={t('label.custom-property-plural')}
/>
),
key: EntityTabs.CUSTOM_PROPERTIES,
children: (
<CustomPropertyTable
entityDetails={isVersionView ? glossaryTerm : undefined}
entityType={EntityType.GLOSSARY_TERM}
handleExtensionUpdate={onExtensionUpdate}
hasEditAccess={
!isVersionView &&
(permissions.EditAll || permissions.EditCustomFields)
}
hasPermission={permissions.ViewAll}
isVersionView={isVersionView}
/>
),
},
];
return items;
@ -232,6 +225,7 @@ const GlossaryTermsV1 = ({
feedCount,
isSummaryPanelOpen,
isVersionView,
assetPermissions,
]);
const fetchGlossaryTermAssets = async () => {

View File

@ -0,0 +1,33 @@
/*
* Copyright 2023 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 { GlossaryTerm } from '../../../generated/entity/data/glossaryTerm';
import { EntityDetailsObjectInterface } from '../../Explore/explore.interface';
import { OperationPermission } from '../../PermissionProvider/PermissionProvider.interface';
import { VotingDataProps } from '../../Voting/voting.interface';
export interface GlossaryTermsV1Props {
isVersionView?: boolean;
permissions: OperationPermission;
glossaryTerm: GlossaryTerm;
childGlossaryTerms: GlossaryTerm[];
handleGlossaryTermUpdate: (data: GlossaryTerm) => Promise<void>;
handleGlossaryTermDelete: (id: string) => void;
refreshGlossaryTerms: () => void;
onAssetClick?: (asset?: EntityDetailsObjectInterface) => void;
isSummaryPanelOpen: boolean;
termsLoading: boolean;
onAddGlossaryTerm: (glossaryTerm: GlossaryTerm | undefined) => void;
onEditGlossaryTerm: (glossaryTerm: GlossaryTerm) => void;
updateVote?: (data: VotingDataProps) => Promise<void>;
refreshActiveGlossaryTerm?: () => void;
}

View File

@ -80,6 +80,7 @@ const mockProps = {
onRelatedTermClick: jest.fn(),
handleGlossaryTermDelete: jest.fn(),
refreshGlossaryTerms: jest.fn(),
refreshActiveGlossaryTerm: jest.fn(),
onAddGlossaryTerm: jest.fn(),
onEditGlossaryTerm: jest.fn(),
};

View File

@ -446,7 +446,11 @@ const AssetsTabs = forwardRef(
doc={GLOSSARIES_DOCS}
heading={t('label.asset')}
permission={permissions.Create}
type={ERROR_PLACEHOLDER_TYPE.CREATE}
type={
permissions.Create
? ERROR_PLACEHOLDER_TYPE.CREATE
: ERROR_PLACEHOLDER_TYPE.NO_DATA
}
onClick={onAddAsset}
/>
)}

View File

@ -63,6 +63,7 @@ const GlossaryV1 = ({
isVersionsView,
onAssetClick,
isSummaryPanelOpen,
refreshActiveGlossaryTerm,
}: GlossaryV1Props) => {
const { t } = useTranslation();
const { action, tab } =
@ -338,6 +339,7 @@ const GlossaryV1 = ({
isSummaryPanelOpen={isSummaryPanelOpen}
isVersionView={isVersionsView}
permissions={glossaryTermPermission}
refreshActiveGlossaryTerm={refreshActiveGlossaryTerm}
refreshGlossaryTerms={() => loadGlossaryTerms(true)}
termsLoading={isTermsLoading}
updateVote={updateVote}

View File

@ -29,4 +29,5 @@ export type GlossaryV1Props = {
onAssetClick?: (asset?: EntityDetailsObjectInterface) => void;
isSummaryPanelOpen: boolean;
updateVote?: (data: VotingDataProps) => Promise<void>;
refreshActiveGlossaryTerm?: () => void;
};

View File

@ -13,7 +13,6 @@
import { CookieStorage } from 'cookie-storage';
import { isEmpty } from 'lodash';
import { observer } from 'mobx-react';
import React, {
createContext,
FC,
@ -32,10 +31,7 @@ import {
getLoggedInUserPermissions,
getResourcePermission,
} from '../../rest/permissionAPI';
import {
getUrlPathnameExpiryAfterRoute,
isProtectedRoute,
} from '../../utils/AuthProvider.util';
import { getUrlPathnameExpiryAfterRoute } from '../../utils/AuthProvider.util';
import {
getOperationPermissions,
getUIPermission,
@ -177,7 +173,7 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
/**
* Only fetch permissions if current user is present
*/
if (isProtectedRoute(location.pathname) && !isEmpty(currentUser)) {
if (!isEmpty(currentUser)) {
fetchLoggedInUserPermissions();
}
if (isEmpty(currentUser)) {
@ -209,4 +205,4 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
export const usePermissionProvider = () => useContext(PermissionContext);
export default observer(PermissionProvider);
export default PermissionProvider;

View File

@ -19,6 +19,7 @@ import {
MenuProps,
Row,
Space,
Tooltip,
Typography,
} from 'antd';
import { useForm } from 'antd/lib/form/Form';
@ -165,6 +166,10 @@ export const TaskTab = ({
.then(() => {
showSuccessToast(t('server.task-resolved-successfully'));
rest.onAfterClose?.();
if (isTaskGlossaryApproval) {
rest.onUpdateEntityDetails?.();
}
})
.catch((err: AxiosError) => showErrorToast(err));
};
@ -255,34 +260,53 @@ export const TaskTab = ({
.then(() => {
showSuccessToast(t('server.task-closed-successfully'));
rest.onAfterClose?.();
if (isTaskGlossaryApproval) {
rest.onUpdateEntityDetails?.();
}
})
.catch((err: AxiosError) => showErrorToast(err));
};
const approvalWorkflowActions = useMemo(() => {
const hasApprovalAccess = isAssignee || Boolean(isPartOfAssigneeTeam);
return (
<Space
className="m-t-sm items-end w-full"
data-testid="task-cta-buttons"
size="small">
{(isCreator || hasEditAccess) && (
<>
<Button data-testid="reject-task" onClick={onTaskReject}>
{t('label.reject')}
</Button>
{hasEditAccess && (
<Button
data-testid="approve-task"
type="primary"
onClick={onTaskResolve}>
{t('label.approve')}
</Button>
)}
</>
)}
<Tooltip
title={
!hasApprovalAccess
? t('message.only-reviewers-can-approve-or-reject')
: ''
}>
<Button
data-testid="reject-task"
disabled={!hasApprovalAccess}
onClick={onTaskReject}>
{t('label.reject')}
</Button>
</Tooltip>
<Tooltip
title={
!hasApprovalAccess
? t('message.only-reviewers-can-approve-or-reject')
: ''
}>
<Button
data-testid="approve-task"
disabled={!hasApprovalAccess}
type="primary"
onClick={onTaskResolve}>
{t('label.approve')}
</Button>
</Tooltip>
</Space>
);
}, [taskDetails, onTaskResolve, hasEditAccess, isCreator]);
}, [taskDetails, onTaskResolve, isAssignee, isPartOfAssigneeTeam]);
const actionButtons = useMemo(() => {
if (isTaskClosed) {

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "Daten funktionieren am besten, wenn sie einen Eigentümer haben. Sieh dir die Datenvermögenswerte an, die du besitzt, und beanspruche ihren Besitz.",
"onboarding-explore-data-description": "Schau dir die beliebten Datenvermögenswerte in deiner Organisation an.",
"onboarding-stay-up-to-date-description": "Folge den Datensätzen, die du häufig verwendest, um über sie informiert zu bleiben.",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "Optionale Konfiguration, um die Beschreibung von dbt zu aktualisieren oder nicht.",
"page-is-not-available": "Die von dir gesuchte Seite ist nicht verfügbar",
"page-sub-header-for-activity-feed": "Aktivitäts-Feed, der es dir ermöglicht, eine Zusammenfassung der Ereignisse zur Datenänderung anzuzeigen.",

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "Data works well when it is owned. Take a look at the data assets that you own and claim ownership.",
"onboarding-explore-data-description": "Look at the popular data assets in your organization.",
"onboarding-stay-up-to-date-description": "Follow the datasets that you frequently use to stay informed about it.",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "Optional configuration to update the description from dbt or not",
"page-is-not-available": "The page you are looking for is not available",
"page-sub-header-for-activity-feed": "Activity feed that enables you view a summary of data change events.",

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "Los datos funcionan bien cuando están tienen propietario. Revisa los activos de datos que posees y reclama su propiedad.",
"onboarding-explore-data-description": "Sigue los activos de datos populares en tu organización.",
"onboarding-stay-up-to-date-description": "Sigue los conjuntos de datos que usas con frecuencia para mantenerte informado acerca de ellos.",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "Configuración opcional para actualizar la descripción de dbt",
"page-is-not-available": "La página que estás buscando no está disponible",
"page-sub-header-for-activity-feed": "Activity feed that enables you view a summary of data change events.",

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "Les données fonctionnent mieux lorsqu'elles sont possédées. Revoyez les ressources de données que vous possédez et revendiquez la propriété.",
"onboarding-explore-data-description": "Découvrez les ressources de données populaires dans votre organisation.",
"onboarding-stay-up-to-date-description": "Suivez les ressources de données que vous utilisez fréquemment pour rester informé à leur sujet.",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "Configuration optionnelle pour mettre à jour la description à partir de dbt ou non",
"page-is-not-available": "La page que vous recherchez n'est pas disponible",
"page-sub-header-for-activity-feed": "Fil d'activité qui vous permet de voir un résumé des événements de modification des données.",

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "Data works well when it is owned. Take a look at the data assets that you own and claim ownership.",
"onboarding-explore-data-description": "あなたの組織で人気のデータアセットを見る。",
"onboarding-stay-up-to-date-description": "よく使うデータセットをフォローして、情報が通知されるようにする",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "Optional configuration to update the description from dbt or not",
"page-is-not-available": "お探しのページはご利用いただけません",
"page-sub-header-for-activity-feed": "Activity feed that enables you view a summary of data change events.",

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "Dados funcionam bem quando possuem um dono. Dê uma olhada nos ativos de dados que você é responsável e reivindique a propriedade.",
"onboarding-explore-data-description": "Olhe para os ativos de dados populares na sua organização.",
"onboarding-stay-up-to-date-description": "Siga os conjuntos de dados que você usa com frequência para se manter informado sobre eles.",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "Configuração opcional para atualizar ou não a descrição do dbt",
"page-is-not-available": "A página que você está procurando não está disponível",
"page-sub-header-for-activity-feed": "Activity feed that enables you view a summary of data change events.",

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "Данные работают хорошо, когда ими владеют. Взгляните на объекты данных, которыми вы владеете, и заявите о праве собственности.",
"onboarding-explore-data-description": "Посмотрите на популярные объекты данных в вашей организации.",
"onboarding-stay-up-to-date-description": "Следите за наборами данных, которые вы часто используете, чтобы быть в курсе.",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "Необязательная конфигурация для обновления описания из dbt или нет",
"page-is-not-available": "Страница, которую вы ищете, недоступна",
"page-sub-header-for-activity-feed": "Лента активности позволяет просматривать сводку событий изменения данных.",

View File

@ -1419,6 +1419,7 @@
"onboarding-claim-ownership-description": "查看数据资产并声明所有权,以更好的维护数据",
"onboarding-explore-data-description": "查看组织中热门的数据资产",
"onboarding-stay-up-to-date-description": "关注您经常使用的数据集以获取最新信息",
"only-reviewers-can-approve-or-reject": "Only Reviewers can Approve or Reject",
"optional-configuration-update-description-dbt": "可选配置,选择是否从 dbt 更新描述",
"page-is-not-available": "您要查找的页面不可用",
"page-sub-header-for-activity-feed": "活动信息流可用于查看数据的修改事件概览",

View File

@ -45,7 +45,7 @@ export const mockedGlossaryTerms = [
updatedBy: 'anonymous',
reviewers: [],
tags: [],
status: 'Draft' as Status,
status: Status.Draft,
deleted: false,
},
{
@ -71,7 +71,7 @@ export const mockedGlossaryTerms = [
updatedBy: 'anonymous',
reviewers: [],
tags: [],
status: 'Draft' as Status,
status: Status.Approved,
deleted: false,
},
];
@ -431,6 +431,13 @@ export const MOCK_PERMISSIONS = {
ViewUsage: true,
} as OperationPermission;
export const MOCK_GLOSSARY_NO_PERMISSIONS = {
Create: false,
Delete: false,
EditAll: false,
ViewAll: true,
} as OperationPermission;
export const MOCKED_GLOSSARY_TERMS = [
{
id: 'a735e9c0-a98f-43aa-8c15-490a55198f3c',

View File

@ -356,6 +356,7 @@ const GlossaryPage = () => {
isGlossaryActive={isGlossaryActive}
isSummaryPanelOpen={Boolean(previewAsset)}
isVersionsView={false}
refreshActiveGlossaryTerm={fetchGlossaryTermDetails}
selectedData={selectedData as Glossary}
updateGlossary={updateGlossary}
updateVote={updateVote}

View File

@ -249,6 +249,30 @@ export const getGlobalSettingsMenuWithPermission = (
},
],
},
{
category: i18next.t('label.open-metadata'),
key: 'openMetadata',
items: [
{
label: i18next.t('label.customize-landing-page'),
isProtected: Boolean(isAdminUser),
key: 'openMetadata.customizeLandingPage',
icon: <CustomDashboardLogoIcon className="w-4 side-panel-icons" />,
},
{
label: i18next.t('label.email'),
isProtected: Boolean(isAdminUser),
key: 'openMetadata.email',
icon: <EmailSettingsIcon className="w-4 side-panel-icons" />,
},
{
label: i18next.t('label.custom-logo'),
isProtected: Boolean(isAdminUser),
key: 'openMetadata.customLogo',
icon: <CustomLogoIcon className="w-4 side-panel-icons" />,
},
],
},
{
category: i18next.t('label.custom-attribute-plural'),
key: 'customAttributes',
@ -321,30 +345,6 @@ export const getGlobalSettingsMenuWithPermission = (
},
],
},
{
category: i18next.t('label.open-metadata'),
key: 'openMetadata',
items: [
{
label: i18next.t('label.customize-landing-page'),
isProtected: Boolean(isAdminUser),
key: 'openMetadata.customizeLandingPage',
icon: <CustomDashboardLogoIcon className="w-4 side-panel-icons" />,
},
{
label: i18next.t('label.email'),
isProtected: Boolean(isAdminUser),
key: 'openMetadata.email',
icon: <EmailSettingsIcon className="w-4 side-panel-icons" />,
},
{
label: i18next.t('label.custom-logo'),
isProtected: Boolean(isAdminUser),
key: 'openMetadata.customLogo',
icon: <CustomLogoIcon className="w-4 side-panel-icons" />,
},
],
},
];
};

View File

@ -228,7 +228,9 @@ export const StatusClass = {
[Status.Deprecated]: StatusType.Warning,
};
export const StatusFilters = Object.values(Status).map((status) => ({
text: status,
value: status,
}));
export const StatusFilters = Object.values(Status)
.filter((status) => status !== Status.Deprecated) // Deprecated not in use for this release
.map((status) => ({
text: status,
value: status,
}));