mirror of
https://github.com/datahub-project/datahub.git
synced 2025-06-27 05:03:31 +00:00
fix(web): glossary term create buttons inlined in content area (#13571)
This commit is contained in:
parent
d8099da973
commit
f4a8d9e7fc
@ -1,14 +1,16 @@
|
||||
import React from 'react';
|
||||
import { Plus } from 'phosphor-react';
|
||||
import React, { useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useEntityData } from '@app/entity/shared/EntityContext';
|
||||
import CreateGlossaryEntityModal from '@app/entity/shared/EntityDropdown/CreateGlossaryEntityModal';
|
||||
import useGlossaryChildren from '@app/entityV2/glossaryNode/useGlossaryChildren';
|
||||
import { sortGlossaryNodes } from '@app/entityV2/glossaryNode/utils';
|
||||
import { sortGlossaryTerms } from '@app/entityV2/glossaryTerm/utils';
|
||||
import EmptyGlossarySection from '@app/glossaryV2/EmptyGlossarySection';
|
||||
import GlossaryEntitiesList from '@app/glossaryV2/GlossaryEntitiesList';
|
||||
import { useEntityRegistry } from '@app/useEntityRegistry';
|
||||
import { SearchBar } from '@src/alchemy-components';
|
||||
import { Button, SearchBar, Tooltip } from '@src/alchemy-components';
|
||||
import Loading from '@src/app/shared/Loading';
|
||||
|
||||
import { EntityType, GlossaryNode, GlossaryTerm } from '@types';
|
||||
@ -26,11 +28,34 @@ const LoadingWrapper = styled.div`
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const StyledPlusOutlined = styled(Plus)`
|
||||
font-size: 12px;
|
||||
`;
|
||||
|
||||
const CreateButtonWrapper = styled.div`
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: 16px;
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
const HeaderWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 16px;
|
||||
`;
|
||||
|
||||
function ChildrenTab() {
|
||||
const { entityData } = useEntityData();
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const entityUrn = entityData?.urn;
|
||||
const { scrollRef, data, loading, searchQuery, setSearchQuery } = useGlossaryChildren({ entityUrn });
|
||||
|
||||
const { scrollRef, data, loading, searchQuery, setSearchQuery, refetch } = useGlossaryChildren({ entityUrn });
|
||||
|
||||
const [isCreateNodeModalVisible, setIsCreateNodeModalVisible] = useState(false);
|
||||
const [isCreateTermModalVisible, setIsCreateTermModalVisible] = useState(false);
|
||||
|
||||
if (!entityData) return <></>;
|
||||
|
||||
@ -43,32 +68,75 @@ function ChildrenTab() {
|
||||
|
||||
const hasTermsOrNodes = !!childNodes?.length || !!childTerms?.length;
|
||||
|
||||
if (searchQuery || hasTermsOrNodes) {
|
||||
return (
|
||||
<ChildrenTabWrapper>
|
||||
<SearchBar
|
||||
placeholder="Search contents..."
|
||||
onChange={setSearchQuery}
|
||||
value={searchQuery}
|
||||
allowClear
|
||||
width="300px"
|
||||
style={{ marginLeft: 16, marginTop: 6 }}
|
||||
return (
|
||||
<>
|
||||
{searchQuery || hasTermsOrNodes ? (
|
||||
<ChildrenTabWrapper>
|
||||
<HeaderWrapper>
|
||||
<SearchBar
|
||||
placeholder="Search..."
|
||||
onChange={setSearchQuery}
|
||||
value={searchQuery}
|
||||
allowClear
|
||||
width={hasTermsOrNodes ? 'auto' : '300px'}
|
||||
/>
|
||||
{hasTermsOrNodes && (
|
||||
<CreateButtonWrapper>
|
||||
<Tooltip title="Create New Glossary Term" showArrow={false} placement="bottom">
|
||||
<Button
|
||||
data-testid="add-term-button"
|
||||
onClick={() => setIsCreateTermModalVisible(true)}
|
||||
>
|
||||
<StyledPlusOutlined /> Add Term
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="Create New Term Group" showArrow={false} placement="bottom">
|
||||
<Button
|
||||
data-testid="add-term-group-button-v2"
|
||||
variant="outline"
|
||||
onClick={() => setIsCreateNodeModalVisible(true)}
|
||||
>
|
||||
<StyledPlusOutlined /> Add Term Group
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</CreateButtonWrapper>
|
||||
)}
|
||||
</HeaderWrapper>
|
||||
<GlossaryEntitiesList
|
||||
nodes={(childNodes as GlossaryNode[]) || []}
|
||||
terms={(childTerms as GlossaryTerm[]) || []}
|
||||
/>
|
||||
{loading && (
|
||||
<LoadingWrapper>
|
||||
<Loading marginTop={0} height={24} />
|
||||
</LoadingWrapper>
|
||||
)}
|
||||
<div ref={scrollRef} />
|
||||
</ChildrenTabWrapper>
|
||||
) : (
|
||||
<EmptyGlossarySection
|
||||
description="No Terms or Term Groups"
|
||||
onAddTerm={() => setIsCreateTermModalVisible(true)}
|
||||
onAddtermGroup={() => setIsCreateNodeModalVisible(true)}
|
||||
/>
|
||||
<GlossaryEntitiesList
|
||||
nodes={(childNodes as GlossaryNode[]) || []}
|
||||
terms={(childTerms as GlossaryTerm[]) || []}
|
||||
/>
|
||||
{loading && (
|
||||
<LoadingWrapper>
|
||||
<Loading marginTop={0} height={24} />
|
||||
</LoadingWrapper>
|
||||
)}
|
||||
<div ref={scrollRef} />
|
||||
</ChildrenTabWrapper>
|
||||
);
|
||||
}
|
||||
)}
|
||||
|
||||
return <EmptyGlossarySection description="No Terms or Term Groups" />;
|
||||
{isCreateTermModalVisible && (
|
||||
<CreateGlossaryEntityModal
|
||||
entityType={EntityType.GlossaryTerm}
|
||||
onClose={() => setIsCreateTermModalVisible(false)}
|
||||
refetchData={refetch}
|
||||
/>
|
||||
)}
|
||||
{isCreateNodeModalVisible && (
|
||||
<CreateGlossaryEntityModal
|
||||
entityType={EntityType.GlossaryNode}
|
||||
onClose={() => setIsCreateNodeModalVisible(false)}
|
||||
refetchData={refetch}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChildrenTab;
|
||||
|
@ -12,7 +12,6 @@ import { SidebarAboutSection } from '@app/entityV2/shared/containers/profile/sid
|
||||
import { SidebarOwnerSection } from '@app/entityV2/shared/containers/profile/sidebar/Ownership/sidebar/SidebarOwnerSection';
|
||||
import StatusSection from '@app/entityV2/shared/containers/profile/sidebar/shared/StatusSection';
|
||||
import { getDataForEntityType } from '@app/entityV2/shared/containers/profile/utils';
|
||||
import { EntityActionItem } from '@app/entityV2/shared/entity/EntityActions';
|
||||
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||
@ -109,9 +108,12 @@ class GlossaryNodeEntity implements Entity<GlossaryNode> {
|
||||
},
|
||||
]}
|
||||
sidebarSections={this.getSidebarSections()}
|
||||
headerActionItems={
|
||||
new Set([EntityActionItem.ADD_CHILD_GLOSSARY_NODE, EntityActionItem.ADD_CHILD_GLOSSARY_TERM])
|
||||
}
|
||||
// NOTE: Hiding this for now as we've moved the actions to the content of ChildrenTab.tsx
|
||||
// The buttons are too big and causes other actions to overflow.
|
||||
// This component requires deeper refactoring to dynamically adapt to smaller screens.
|
||||
// headerActionItems={
|
||||
// new Set([EntityActionItem.ADD_CHILD_GLOSSARY_NODE, EntityActionItem.ADD_CHILD_GLOSSARY_TERM])
|
||||
// }
|
||||
headerDropdownItems={headerDropdownItems}
|
||||
sidebarTabs={this.getSidebarTabs()}
|
||||
/>
|
||||
|
@ -44,7 +44,11 @@ export default function useGlossaryChildren({ entityUrn, skip }: Props) {
|
||||
const [searchData, setSearchData] = useState<Entity[]>([]);
|
||||
const [dataUrnsSet, setDataUrnsSet] = useState<Set<string>>(new Set());
|
||||
const [data, setData] = useState<Entity[]>([]);
|
||||
const { data: scrollData, loading } = useScrollAcrossEntitiesQuery({
|
||||
const {
|
||||
data: scrollData,
|
||||
loading,
|
||||
refetch,
|
||||
} = useScrollAcrossEntitiesQuery({
|
||||
variables: {
|
||||
...getGlossaryChildrenScrollInput(entityUrn || '', scrollId),
|
||||
},
|
||||
@ -140,5 +144,6 @@ export default function useGlossaryChildren({ entityUrn, skip }: Props) {
|
||||
loading: loading || (shouldDoAutoComplete && autoCompleteLoading),
|
||||
searchQuery,
|
||||
setSearchQuery,
|
||||
refetch,
|
||||
};
|
||||
}
|
||||
|
@ -99,13 +99,12 @@ const BusinessGlossaryPage = () => {
|
||||
)}
|
||||
<GlossaryContentProvider
|
||||
setIsCreateNodeModalVisible={setIsCreateNodeModalVisible}
|
||||
setIsCreateTermModalVisible={setIsCreateTermModalVisible}
|
||||
hasTermsOrNodes={hasTermsOrNodes}
|
||||
nodes={nodes || []}
|
||||
terms={terms || []}
|
||||
termsLoading={termsLoading}
|
||||
nodesLoading={nodesLoading}
|
||||
refetchForNodes={refetchForNodes}
|
||||
refetchForTerms={refetchForTerms}
|
||||
/>
|
||||
</GlossaryWrapper>
|
||||
</MainWrapper>
|
||||
|
@ -1,14 +1,8 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Empty, Typography } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components/macro';
|
||||
|
||||
import { useUserContext } from '@app/context/useUserContext';
|
||||
import { useEntityData } from '@app/entity/shared/EntityContext';
|
||||
import CreateGlossaryEntityModal from '@app/entityV2/shared/EntityDropdown/CreateGlossaryEntityModal';
|
||||
|
||||
import { EntityType } from '@types';
|
||||
|
||||
const StyledEmpty = styled(Empty)`
|
||||
padding: 80px 40px;
|
||||
.ant-empty-footer {
|
||||
@ -25,20 +19,12 @@ const StyledButton = styled(Button)`
|
||||
interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
refetchForTerms?: () => void;
|
||||
refetchForNodes?: () => void;
|
||||
onAddTerm: () => void;
|
||||
onAddtermGroup: () => void;
|
||||
}
|
||||
|
||||
function EmptyGlossarySection(props: Props) {
|
||||
const { title, description, refetchForTerms, refetchForNodes } = props;
|
||||
|
||||
const [isCreateTermModalVisible, setIsCreateTermModalVisible] = useState(false);
|
||||
const [isCreateNodeModalVisible, setIsCreateNodeModalVisible] = useState(false);
|
||||
|
||||
const user = useUserContext();
|
||||
const canManageGlossaries = user?.platformPrivileges?.manageGlossaries;
|
||||
const { entityData } = useEntityData();
|
||||
const canCreateGlossaryEntity = !!entityData?.privileges?.canManageChildren || canManageGlossaries;
|
||||
const { title, description, onAddTerm, onAddtermGroup } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -51,29 +37,13 @@ function EmptyGlossarySection(props: Props) {
|
||||
}
|
||||
>
|
||||
{/* not disabled on acryl-main due to ability to propose */}
|
||||
<StyledButton onClick={() => setIsCreateTermModalVisible(true)}>
|
||||
<StyledButton data-testid="add-term-button" onClick={onAddTerm}>
|
||||
<PlusOutlined /> Add Term
|
||||
</StyledButton>
|
||||
<StyledButton onClick={() => setIsCreateNodeModalVisible(true)}>
|
||||
<StyledButton data-testid="add-term-group-button" onClick={onAddtermGroup}>
|
||||
<PlusOutlined /> Add Term Group
|
||||
</StyledButton>
|
||||
</StyledEmpty>
|
||||
{isCreateTermModalVisible && (
|
||||
<CreateGlossaryEntityModal
|
||||
entityType={EntityType.GlossaryTerm}
|
||||
canCreateGlossaryEntity={!!canCreateGlossaryEntity}
|
||||
onClose={() => setIsCreateTermModalVisible(false)}
|
||||
refetchData={refetchForTerms}
|
||||
/>
|
||||
)}
|
||||
{isCreateNodeModalVisible && (
|
||||
<CreateGlossaryEntityModal
|
||||
entityType={EntityType.GlossaryNode}
|
||||
canCreateGlossaryEntity={!!canCreateGlossaryEntity}
|
||||
onClose={() => setIsCreateNodeModalVisible(false)}
|
||||
refetchData={refetchForNodes}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -36,25 +36,23 @@ const ListWrapper = styled.div`
|
||||
|
||||
interface Props {
|
||||
setIsCreateNodeModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
setIsCreateTermModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
hasTermsOrNodes: boolean;
|
||||
nodes: (GlossaryNode | GlossaryNodeFragment)[];
|
||||
terms: (GlossaryTerm | ChildGlossaryTermFragment)[];
|
||||
termsLoading: boolean;
|
||||
nodesLoading: boolean;
|
||||
refetchForTerms: () => void;
|
||||
refetchForNodes: () => void;
|
||||
}
|
||||
|
||||
const GlossaryContentProvider = (props: Props) => {
|
||||
const {
|
||||
setIsCreateNodeModalVisible,
|
||||
setIsCreateTermModalVisible,
|
||||
hasTermsOrNodes,
|
||||
nodes,
|
||||
terms,
|
||||
termsLoading,
|
||||
nodesLoading,
|
||||
refetchForTerms,
|
||||
refetchForNodes,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
@ -84,8 +82,8 @@ const GlossaryContentProvider = (props: Props) => {
|
||||
<EmptyGlossarySection
|
||||
title="Empty Glossary"
|
||||
description="Create Terms and Term Groups to organize data assets using a shared vocabulary."
|
||||
refetchForTerms={refetchForTerms}
|
||||
refetchForNodes={refetchForNodes}
|
||||
onAddTerm={() => setIsCreateTermModalVisible(true)}
|
||||
onAddtermGroup={() => setIsCreateNodeModalVisible(true)}
|
||||
/>
|
||||
)}
|
||||
</MainContentWrapper>
|
||||
|
Loading…
x
Reference in New Issue
Block a user