mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-02 03:39:03 +00:00
feat(ui): Show all views in settings (#14971)
This commit is contained in:
parent
7628ab3fa4
commit
d0bd2d50e4
@ -1,51 +1,140 @@
|
||||
import { Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import { Button, PageTitle, Tabs, colors } from '@components';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Tab } from '@components/components/Tabs/Tabs';
|
||||
|
||||
import { ViewBuilder } from '@app/entity/view/builder/ViewBuilder';
|
||||
import { ViewBuilderMode } from '@app/entity/view/builder/types';
|
||||
import { ViewsList } from '@app/entityV2/view/ViewsList';
|
||||
|
||||
import { DataHubViewType } from '@types';
|
||||
|
||||
const PageContainer = styled.div`
|
||||
padding-top: 20px;
|
||||
padding: 16px 20px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
gap: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
`;
|
||||
|
||||
const PageHeaderContainer = styled.div`
|
||||
&& {
|
||||
padding-left: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
`;
|
||||
|
||||
const PageTitle = styled(Typography.Title)`
|
||||
&& {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
const TitleContainer = styled.div`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const HeaderActionsContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
`;
|
||||
|
||||
const ListContainer = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&&& .ant-tabs-nav {
|
||||
margin: 0;
|
||||
}
|
||||
color: ${colors.gray[600]};
|
||||
overflow: auto;
|
||||
`;
|
||||
|
||||
enum TabType {
|
||||
Personal = 'My Views',
|
||||
Global = 'Public Views',
|
||||
}
|
||||
|
||||
const tabUrlMap = {
|
||||
[TabType.Personal]: '/settings/views/personal',
|
||||
[TabType.Global]: '/settings/views/public',
|
||||
};
|
||||
|
||||
/**
|
||||
* Component used for displaying the 'Manage Views' experience.
|
||||
*/
|
||||
export const ManageViews = () => {
|
||||
const location = useLocation();
|
||||
const [showViewBuilder, setShowViewBuilder] = useState(false);
|
||||
const [selectedTab, setSelectedTab] = useState<TabType | undefined | null>();
|
||||
|
||||
const onCloseModal = () => {
|
||||
setShowViewBuilder(false);
|
||||
};
|
||||
|
||||
const tabs: Tab[] = [
|
||||
{
|
||||
component: <ViewsList viewType={DataHubViewType.Personal} />,
|
||||
key: TabType.Personal,
|
||||
name: TabType.Personal,
|
||||
},
|
||||
{
|
||||
component: <ViewsList viewType={DataHubViewType.Global} />,
|
||||
key: TabType.Global,
|
||||
name: TabType.Global,
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTab === undefined) {
|
||||
const currentPath = location.pathname;
|
||||
|
||||
const currentTab = Object.entries(tabUrlMap).find(([, url]) => url === currentPath)?.[0] as TabType;
|
||||
if (currentTab) {
|
||||
setSelectedTab(currentTab);
|
||||
} else {
|
||||
setSelectedTab(null);
|
||||
}
|
||||
}
|
||||
}, [selectedTab, location.pathname]);
|
||||
|
||||
const getCurrentUrl = useCallback(() => location.pathname, [location.pathname]);
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageHeaderContainer>
|
||||
<PageTitle level={3}>Manage Views</PageTitle>
|
||||
<Typography.Paragraph type="secondary">
|
||||
Create, edit, and remove your Views. Views allow you to save and share sets of filters for reuse
|
||||
when browsing DataHub.
|
||||
</Typography.Paragraph>
|
||||
<TitleContainer>
|
||||
<PageTitle
|
||||
title="Views"
|
||||
subTitle="Create, edit, and remove your Views. Views allow you to save and share sets of filters for reuse when browsing DataHub."
|
||||
/>
|
||||
</TitleContainer>
|
||||
<HeaderActionsContainer>
|
||||
<Button
|
||||
variant="filled"
|
||||
id="create-new-view-button"
|
||||
onClick={() => setShowViewBuilder(true)}
|
||||
data-testid="create-new-view-button"
|
||||
icon={{ icon: 'Plus', source: 'phosphor' }}
|
||||
disabled={false}
|
||||
>
|
||||
Create View
|
||||
</Button>
|
||||
</HeaderActionsContainer>
|
||||
</PageHeaderContainer>
|
||||
<ListContainer>
|
||||
<ViewsList />
|
||||
<Tabs
|
||||
tabs={tabs}
|
||||
selectedTab={selectedTab as string}
|
||||
onChange={(tab) => setSelectedTab(tab as TabType)}
|
||||
urlMap={tabUrlMap}
|
||||
defaultTab={TabType.Personal}
|
||||
getCurrentUrl={getCurrentUrl}
|
||||
/>
|
||||
</ListContainer>
|
||||
{showViewBuilder && (
|
||||
<ViewBuilder mode={ViewBuilderMode.EDITOR} onSubmit={onCloseModal} onCancel={onCloseModal} />
|
||||
)}
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,20 +1,10 @@
|
||||
import { GlobalOutlined, LockOutlined } from '@ant-design/icons';
|
||||
import { Icon, Tooltip } from '@components';
|
||||
import { Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { DataHubViewType } from '@types';
|
||||
|
||||
const StyledLockOutlined = styled(LockOutlined)<{ color }>`
|
||||
color: ${(props) => props.color};
|
||||
margin-right: 4px;
|
||||
`;
|
||||
|
||||
const StyledGlobalOutlined = styled(GlobalOutlined)<{ color }>`
|
||||
color: ${(props) => props.color};
|
||||
margin-right: 4px;
|
||||
`;
|
||||
|
||||
const StyledText = styled(Typography.Text)<{ color }>`
|
||||
&& {
|
||||
color: ${(props) => props.color};
|
||||
@ -27,31 +17,29 @@ type Props = {
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
const ViewNameContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
`;
|
||||
|
||||
/**
|
||||
* Label used to describe View Types
|
||||
*
|
||||
* @param param0 the color of the text and iconography
|
||||
*/
|
||||
export const ViewTypeLabel = ({ type, color, onClick }: Props) => {
|
||||
const copy =
|
||||
type === DataHubViewType.Personal ? (
|
||||
<>
|
||||
<b>Private</b> - only visible to you.
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<b>Public</b> - visible to everyone.
|
||||
</>
|
||||
);
|
||||
const Icon = type === DataHubViewType.Global ? StyledGlobalOutlined : StyledLockOutlined;
|
||||
|
||||
const isPersonal = type === DataHubViewType.Personal;
|
||||
return (
|
||||
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
|
||||
<div onClick={onClick}>
|
||||
<Icon color={color} />
|
||||
<StyledText color={color} type="secondary">
|
||||
{copy}
|
||||
</StyledText>
|
||||
</div>
|
||||
<Tooltip title={isPersonal ? 'Only visible to you' : 'Visible to everyone'}>
|
||||
<ViewNameContainer onClick={onClick}>
|
||||
{!isPersonal && <Icon source="phosphor" icon="Globe" size="md" />}
|
||||
{isPersonal && <Icon source="phosphor" icon="Lock" size="md" />}
|
||||
<StyledText color={color} type="secondary">
|
||||
{!isPersonal ? 'Public' : 'Private'}
|
||||
</StyledText>
|
||||
</ViewNameContainer>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,21 +1,15 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Pagination, message } from 'antd';
|
||||
import * as QueryString from 'query-string';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
import { SearchBar, Text } from '@components';
|
||||
import { Pagination, message } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import TabToolbar from '@app/entityV2/shared/components/styled/TabToolbar';
|
||||
import { ViewsTable } from '@app/entityV2/view/ViewsTable';
|
||||
import { ViewBuilder } from '@app/entityV2/view/builder/ViewBuilder';
|
||||
import { ViewBuilderMode } from '@app/entityV2/view/builder/types';
|
||||
import { DEFAULT_LIST_VIEWS_PAGE_SIZE, searchViews } from '@app/entityV2/view/utils';
|
||||
import { SearchBar } from '@app/search/SearchBar';
|
||||
import { Message } from '@app/shared/Message';
|
||||
import { scrollToTop } from '@app/shared/searchUtils';
|
||||
import { useEntityRegistry } from '@app/useEntityRegistry';
|
||||
|
||||
import { useListMyViewsQuery } from '@graphql/view.generated';
|
||||
import { useListGlobalViewsQuery, useListMyViewsQuery } from '@graphql/view.generated';
|
||||
import { DataHubViewType } from '@types';
|
||||
|
||||
const PaginationContainer = styled.div`
|
||||
display: flex;
|
||||
@ -26,67 +20,119 @@ const StyledPagination = styled(Pagination)`
|
||||
margin: 40px;
|
||||
`;
|
||||
|
||||
const searchBarStyle = {
|
||||
maxWidth: 220,
|
||||
padding: 0,
|
||||
type Props = {
|
||||
viewType?: DataHubViewType;
|
||||
};
|
||||
|
||||
const searchBarInputStyle = {
|
||||
height: 32,
|
||||
fontSize: 12,
|
||||
};
|
||||
const StyledTabToolbar = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 1px 0 16px 0; // 1px at the top to prevent Select's border outline from cutting-off
|
||||
height: auto;
|
||||
z-index: unset;
|
||||
box-shadow: none;
|
||||
flex-shrink: 0;
|
||||
`;
|
||||
|
||||
export const EmptyContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
gap: 16px;
|
||||
|
||||
svg {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
`;
|
||||
|
||||
const TableContainer = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
max-height: calc(100vh - 330px); /* Constrain to page height minus header/filters space */
|
||||
overflow: auto;
|
||||
|
||||
/* Make table header sticky */
|
||||
.ant-table-thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* Ensure header cells have proper background */
|
||||
.ant-table-thead > tr > th {
|
||||
background: white !important;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
`;
|
||||
|
||||
const SearchContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 8px;
|
||||
`;
|
||||
|
||||
const ViewsContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
padding-top: 7px;
|
||||
`;
|
||||
|
||||
const StyledSearchBar = styled(SearchBar)`
|
||||
width: 300px;
|
||||
`;
|
||||
|
||||
/**
|
||||
* This component renders a paginated, searchable list of Views.
|
||||
*/
|
||||
export const ViewsList = () => {
|
||||
/**
|
||||
* Context
|
||||
*/
|
||||
const location = useLocation();
|
||||
const entityRegistry = useEntityRegistry();
|
||||
|
||||
/**
|
||||
* Query Params
|
||||
*/
|
||||
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
||||
const paramsQuery = (params?.query as string) || undefined;
|
||||
|
||||
export const ViewsList = ({ viewType = DataHubViewType.Personal }: Props) => {
|
||||
/**
|
||||
* State
|
||||
*/
|
||||
const [page, setPage] = useState(1);
|
||||
const [selectedViewUrn, setSelectedViewUrn] = useState<undefined | string>(undefined);
|
||||
const [showViewBuilder, setShowViewBuilder] = useState<boolean>(false);
|
||||
const [query, setQuery] = useState<undefined | string>(undefined);
|
||||
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
||||
|
||||
/**
|
||||
* Queries
|
||||
*/
|
||||
const pageSize = DEFAULT_LIST_VIEWS_PAGE_SIZE;
|
||||
const start = (page - 1) * pageSize;
|
||||
const { loading, error, data } = useListMyViewsQuery({
|
||||
|
||||
const isPersonal = viewType === DataHubViewType.Personal;
|
||||
|
||||
const {
|
||||
loading: loadingPersonal,
|
||||
error: errorPersonal,
|
||||
data: dataPersonal,
|
||||
} = useListMyViewsQuery({
|
||||
variables: {
|
||||
start,
|
||||
count: pageSize,
|
||||
},
|
||||
fetchPolicy: 'cache-first',
|
||||
skip: !isPersonal,
|
||||
});
|
||||
|
||||
const onClickCreateView = () => {
|
||||
setShowViewBuilder(true);
|
||||
};
|
||||
|
||||
const onClickEditView = (urn: string) => {
|
||||
setShowViewBuilder(true);
|
||||
setSelectedViewUrn(urn);
|
||||
};
|
||||
|
||||
const onCloseModal = () => {
|
||||
setShowViewBuilder(false);
|
||||
setSelectedViewUrn(undefined);
|
||||
};
|
||||
const {
|
||||
loading: loadingGlobal,
|
||||
error: errorGlobal,
|
||||
data: dataGlobal,
|
||||
} = useListGlobalViewsQuery({
|
||||
variables: {
|
||||
start,
|
||||
count: pageSize,
|
||||
},
|
||||
fetchPolicy: 'cache-first',
|
||||
skip: isPersonal,
|
||||
});
|
||||
|
||||
const onChangePage = (newPage: number) => {
|
||||
scrollToTop();
|
||||
@ -96,51 +142,48 @@ export const ViewsList = () => {
|
||||
/**
|
||||
* Render variables.
|
||||
*/
|
||||
const totalViews = data?.listMyViews?.total || 0;
|
||||
const views = searchViews(data?.listMyViews?.views || [], query);
|
||||
const selectedView = (selectedViewUrn && views.find((view) => view.urn === selectedViewUrn)) || undefined;
|
||||
const viewsData = isPersonal ? dataPersonal?.listMyViews : dataGlobal?.listGlobalViews;
|
||||
const loading = loadingPersonal || loadingGlobal;
|
||||
const error = errorPersonal || errorGlobal;
|
||||
const totalViews = viewsData?.total || 0;
|
||||
const views = searchViews(viewsData?.views || [], query);
|
||||
|
||||
if (!totalViews) {
|
||||
return (
|
||||
<EmptyContainer>
|
||||
<Text size="md" color="gray" weight="bold">
|
||||
No Views yet!
|
||||
</Text>
|
||||
</EmptyContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{!data && loading && <Message type="loading" content="Loading Views..." />}
|
||||
{!viewsData && loading && <Message type="loading" content="Loading Views..." />}
|
||||
{error && message.error({ content: `Failed to load Views! An unexpected error occurred.`, duration: 3 })}
|
||||
<TabToolbar>
|
||||
<Button type="text" onClick={onClickCreateView}>
|
||||
<PlusOutlined /> Create new View
|
||||
</Button>
|
||||
<SearchBar
|
||||
initialQuery=""
|
||||
placeholderText="Search Views..."
|
||||
suggestions={[]}
|
||||
style={searchBarStyle}
|
||||
inputStyle={searchBarInputStyle}
|
||||
onSearch={() => null}
|
||||
onQueryChange={(q) => setQuery(q.length > 0 ? q : undefined)}
|
||||
entityRegistry={entityRegistry}
|
||||
/>
|
||||
</TabToolbar>
|
||||
<ViewsTable views={views} onEditView={onClickEditView} />
|
||||
{totalViews >= pageSize && (
|
||||
<PaginationContainer>
|
||||
<StyledPagination
|
||||
current={page}
|
||||
pageSize={pageSize}
|
||||
total={totalViews}
|
||||
showLessItems
|
||||
onChange={onChangePage}
|
||||
showSizeChanger={false}
|
||||
/>
|
||||
</PaginationContainer>
|
||||
)}
|
||||
{showViewBuilder && (
|
||||
<ViewBuilder
|
||||
mode={ViewBuilderMode.EDITOR}
|
||||
urn={selectedViewUrn}
|
||||
initialState={selectedView}
|
||||
onSubmit={onCloseModal}
|
||||
onCancel={onCloseModal}
|
||||
/>
|
||||
)}
|
||||
<ViewsContainer>
|
||||
<StyledTabToolbar>
|
||||
<SearchContainer>
|
||||
<StyledSearchBar placeholder="Search Views..." onChange={setQuery} value={query || ''} />
|
||||
</SearchContainer>
|
||||
</StyledTabToolbar>
|
||||
<TableContainer>
|
||||
<ViewsTable views={views} />
|
||||
</TableContainer>
|
||||
{totalViews >= pageSize && (
|
||||
<PaginationContainer>
|
||||
<StyledPagination
|
||||
current={page}
|
||||
pageSize={pageSize}
|
||||
total={totalViews}
|
||||
showLessItems
|
||||
onChange={onChangePage}
|
||||
showSizeChanger={false}
|
||||
/>
|
||||
</PaginationContainer>
|
||||
)}
|
||||
</ViewsContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { Empty } from 'antd';
|
||||
import { Table, Text } from '@components';
|
||||
import React from 'react';
|
||||
|
||||
import { StyledTable } from '@app/entityV2/shared/components/styled/StyledTable';
|
||||
import { AlignmentOptions } from '@components/theme/config';
|
||||
|
||||
import { EmptyContainer } from '@app/entityV2/view/ViewsList';
|
||||
import {
|
||||
ActionsColumn,
|
||||
DescriptionColumn,
|
||||
@ -13,7 +15,7 @@ import { DataHubView } from '@types';
|
||||
|
||||
type ViewsTableProps = {
|
||||
views: DataHubView[];
|
||||
onEditView: (urn) => void;
|
||||
onEditView?: (urn) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -25,24 +27,28 @@ export const ViewsTable = ({ views, onEditView }: ViewsTableProps) => {
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: (name, record) => <NameColumn name={name} record={record} onEditView={onEditView} />,
|
||||
width: '25%',
|
||||
render: (record) => <NameColumn name={record.name} record={record} onEditView={onEditView} />,
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
render: (description) => <DescriptionColumn description={description} />,
|
||||
render: (record) => <DescriptionColumn description={record.description} />,
|
||||
},
|
||||
{
|
||||
title: 'Type',
|
||||
dataIndex: 'viewType',
|
||||
key: 'viewType',
|
||||
render: (viewType) => <ViewTypeColumn viewType={viewType} />,
|
||||
width: '10%',
|
||||
render: (record) => <ViewTypeColumn viewType={record.viewType} />,
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
dataIndex: '',
|
||||
key: 'x',
|
||||
width: '5%',
|
||||
alignment: 'right' as AlignmentOptions,
|
||||
render: (record) => <ActionsColumn record={record} />,
|
||||
},
|
||||
];
|
||||
@ -50,19 +56,20 @@ export const ViewsTable = ({ views, onEditView }: ViewsTableProps) => {
|
||||
/**
|
||||
* The data for the Views List.
|
||||
*/
|
||||
const tableData = views.map((view) => ({
|
||||
...view,
|
||||
}));
|
||||
const tableData =
|
||||
views.map((view) => ({
|
||||
...view,
|
||||
})) || [];
|
||||
|
||||
return (
|
||||
<StyledTable
|
||||
columns={tableColumns}
|
||||
dataSource={tableData}
|
||||
rowKey="urn"
|
||||
locale={{
|
||||
emptyText: <Empty description="No Views found!" image={Empty.PRESENTED_IMAGE_SIMPLE} />,
|
||||
}}
|
||||
pagination={false}
|
||||
/>
|
||||
);
|
||||
if (!views.length) {
|
||||
return (
|
||||
<EmptyContainer>
|
||||
<Text size="md" color="gray" weight="bold">
|
||||
No results!
|
||||
</Text>
|
||||
</EmptyContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return <Table columns={tableColumns} data={tableData} isScrollable />;
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Button, Typography } from 'antd';
|
||||
import { Text } from '@components';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@ -15,13 +15,6 @@ const StyledDescription = styled.div`
|
||||
max-width: 300px;
|
||||
`;
|
||||
|
||||
const ActionButtonsContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-right: 8px;
|
||||
`;
|
||||
|
||||
const NameContainer = styled.span`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -37,7 +30,7 @@ const IconPlaceholder = styled.span`
|
||||
type NameColumnProps = {
|
||||
name: string;
|
||||
record: any;
|
||||
onEditView: (urn) => void;
|
||||
onEditView?: (urn) => void;
|
||||
};
|
||||
|
||||
export function NameColumn({ name, record, onEditView }: NameColumnProps) {
|
||||
@ -54,9 +47,9 @@ export function NameColumn({ name, record, onEditView }: NameColumnProps) {
|
||||
{isUserDefault && <UserDefaultViewIcon title="Your default View." />}
|
||||
{isGlobalDefault && <GlobalDefaultViewIcon title="Your organization's default View." />}
|
||||
</IconPlaceholder>
|
||||
<Button type="text" onClick={() => onEditView(record.urn)}>
|
||||
<Typography.Text strong>{name}</Typography.Text>
|
||||
</Button>
|
||||
<Text size="md" weight="semiBold" onClick={() => onEditView?.(record.urn)}>
|
||||
{name}
|
||||
</Text>
|
||||
</NameContainer>
|
||||
);
|
||||
}
|
||||
@ -66,11 +59,7 @@ type DescriptionColumnProps = {
|
||||
};
|
||||
|
||||
export function DescriptionColumn({ description }: DescriptionColumnProps) {
|
||||
return (
|
||||
<StyledDescription>
|
||||
{description || <Typography.Text type="secondary">No description</Typography.Text>}
|
||||
</StyledDescription>
|
||||
);
|
||||
return <StyledDescription>{description || '-'}</StyledDescription>;
|
||||
}
|
||||
|
||||
type ViewTypeColumnProps = {
|
||||
@ -86,9 +75,5 @@ type ActionColumnProps = {
|
||||
};
|
||||
|
||||
export function ActionsColumn({ record }: ActionColumnProps) {
|
||||
return (
|
||||
<ActionButtonsContainer>
|
||||
<ViewDropdownMenu view={record} visible />
|
||||
</ActionButtonsContainer>
|
||||
);
|
||||
return <ViewDropdownMenu view={record} visible />;
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ export const SettingsPage = () => {
|
||||
items: [
|
||||
{
|
||||
type: NavBarMenuItemTypes.Item,
|
||||
title: 'My Views',
|
||||
title: 'Views',
|
||||
key: 'views',
|
||||
link: `${url}/views`,
|
||||
isHidden: !showViews,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { ManageViews } from '@app/entity/view/ManageViews';
|
||||
import { ManageOwnership } from '@app/entityV2/ownership/ManageOwnership';
|
||||
import { ManageViews } from '@app/entityV2/view/ManageViews';
|
||||
import { ManageIdentities } from '@app/identity/ManageIdentities';
|
||||
import { ManagePermissions } from '@app/permissions/ManagePermissions';
|
||||
import { ManagePolicies } from '@app/permissions/policy/ManagePolicies';
|
||||
|
||||
@ -9,10 +9,8 @@ describe("manage views", () => {
|
||||
cy.goToViewsSettings();
|
||||
cy.waitTextVisible("Settings");
|
||||
cy.wait(1000);
|
||||
cy.clickOptionWithText("Create new View");
|
||||
cy.get(".ant-input-affix-wrapper > input[type='text']")
|
||||
.first()
|
||||
.type(viewName);
|
||||
cy.clickOptionWithText("Create View");
|
||||
cy.get('[data-testid="view-name-input"]').click().type(viewName);
|
||||
cy.clickOptionWithTestId("view-builder-save");
|
||||
|
||||
// Confirm that the test has been created.
|
||||
@ -21,8 +19,8 @@ describe("manage views", () => {
|
||||
// Now edit the View
|
||||
cy.clickFirstOptionWithTestId("views-table-dropdown");
|
||||
cy.get('[data-testid="view-dropdown-edit"]').click({ force: true });
|
||||
cy.get(".ant-input-affix-wrapper > input[type='text']")
|
||||
.first()
|
||||
cy.get('[data-testid="view-name-input"]')
|
||||
.click()
|
||||
.clear()
|
||||
.type("New View Name");
|
||||
cy.clickOptionWithTestId("view-builder-save");
|
||||
|
||||
@ -125,7 +125,7 @@ Cypress.Commands.add("goToDomainList", () => {
|
||||
|
||||
Cypress.Commands.add("goToViewsSettings", () => {
|
||||
cy.visit("/settings/views");
|
||||
cy.waitTextVisible("Manage Views");
|
||||
cy.waitTextVisible("Views");
|
||||
});
|
||||
|
||||
Cypress.Commands.add("goToOwnershipTypesSettings", () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user