mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-01 19:25:56 +00:00
feat(search): embedded view dropdown (#8598)
This commit is contained in:
parent
d3fd025b11
commit
0d03f4b7bb
@ -20,6 +20,13 @@ export const ANTD_GRAY = {
|
||||
9: '#434343',
|
||||
};
|
||||
|
||||
export const ANTD_GRAY_V2 = {
|
||||
2: '#F3F5F6',
|
||||
5: '#DDE0E4',
|
||||
8: '#5E666E',
|
||||
10: '#1B1E22',
|
||||
};
|
||||
|
||||
export const EMPTY_MESSAGES = {
|
||||
documentation: {
|
||||
title: 'No documentation yet',
|
||||
|
||||
@ -33,6 +33,17 @@ const MenuButton = styled(MoreOutlined)`
|
||||
}
|
||||
`;
|
||||
|
||||
const MenuStyled = styled(Menu)`
|
||||
&&& {
|
||||
.ant-dropdown-menu-item:not(:hover) {
|
||||
background: none;
|
||||
}
|
||||
.ant-dropdown-menu-item:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const DEFAULT_VIEW_BUILDER_STATE = {
|
||||
mode: ViewBuilderMode.EDITOR,
|
||||
visible: false,
|
||||
@ -233,7 +244,7 @@ export const ViewDropdownMenu = ({
|
||||
<>
|
||||
<Dropdown
|
||||
overlay={
|
||||
<Menu>
|
||||
<MenuStyled>
|
||||
{(canManageView && <EditViewItem key="0" onClick={onEditView} />) || (
|
||||
<PreviewViewItem key="0" onClick={onPreviewView} />
|
||||
)}
|
||||
@ -247,7 +258,7 @@ export const ViewDropdownMenu = ({
|
||||
<SetGlobalDefaultItem key="2" onClick={() => setGlobalDefault(view.urn)} />
|
||||
)}
|
||||
{canManageView && <DeleteViewItem key="3" onClick={confirmDeleteView} />}
|
||||
</Menu>
|
||||
</MenuStyled>
|
||||
}
|
||||
trigger={[trigger]}
|
||||
>
|
||||
|
||||
@ -17,7 +17,7 @@ type Props = {
|
||||
|
||||
export const ViewOptionName = ({ name, description }: Props) => {
|
||||
return (
|
||||
<Tooltip placement="left" title={<ViewOptionTooltipTitle name={name} description={description} />}>
|
||||
<Tooltip placement="bottom" showArrow title={<ViewOptionTooltipTitle name={name} description={description} />}>
|
||||
<ViewName>{name}</ViewName>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@ -1,24 +1,18 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { Select } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import { VscTriangleDown } from 'react-icons/vsc';
|
||||
import { useListMyViewsQuery, useListGlobalViewsQuery } from '../../../../graphql/view.generated';
|
||||
import { useUserContext } from '../../../context/useUserContext';
|
||||
import { DataHubView, DataHubViewType } from '../../../../types.generated';
|
||||
import { ViewBuilder } from '../builder/ViewBuilder';
|
||||
import { DEFAULT_LIST_VIEWS_PAGE_SIZE } from '../utils';
|
||||
import { PageRoutes } from '../../../../conf/Global';
|
||||
import { ViewSelectToolTip } from './ViewSelectToolTip';
|
||||
import { ViewBuilderMode } from '../builder/types';
|
||||
import { ViewSelectDropdown } from './ViewSelectDropdown';
|
||||
import { renderViewOptionGroup } from './renderViewOptionGroup';
|
||||
|
||||
const selectStyle = {
|
||||
width: 240,
|
||||
};
|
||||
|
||||
const dropdownStyle = {
|
||||
position: 'fixed',
|
||||
} as any;
|
||||
import { ANTD_GRAY_V2 } from '../../shared/constants';
|
||||
|
||||
type ViewBuilderDisplayState = {
|
||||
mode: ViewBuilderMode;
|
||||
@ -26,12 +20,46 @@ type ViewBuilderDisplayState = {
|
||||
view?: DataHubView;
|
||||
};
|
||||
|
||||
const TriangleIcon = styled(VscTriangleDown)<{ isOpen: boolean }>`
|
||||
color: ${(props) => (props.isOpen ? props.theme.styles['primary-color'] : ANTD_GRAY_V2[10])};
|
||||
`;
|
||||
|
||||
const DEFAULT_VIEW_BUILDER_DISPLAY_STATE = {
|
||||
mode: ViewBuilderMode.EDITOR,
|
||||
visible: false,
|
||||
view: undefined,
|
||||
};
|
||||
|
||||
const ViewSelectContainer = styled.div`
|
||||
&&& {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.ant-select {
|
||||
.ant-select-selection-search {
|
||||
position: absolute;
|
||||
}
|
||||
&.ant-select-open {
|
||||
.ant-select-selection-placeholder,
|
||||
.ant-select-selection-item {
|
||||
color: ${(props) => props.theme.styles['primary-color']};
|
||||
}
|
||||
}
|
||||
&:not(.ant-select-open) {
|
||||
.ant-select-selection-placeholder,
|
||||
.ant-select-selection-item {
|
||||
color: ${ANTD_GRAY_V2[10]};
|
||||
}
|
||||
}
|
||||
.ant-select-selection-placeholder,
|
||||
.ant-select-selection-item {
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* The View Select component allows you to select a View to apply to query on the current page. For example,
|
||||
* search, recommendations, and browse.
|
||||
@ -44,6 +72,7 @@ const DEFAULT_VIEW_BUILDER_DISPLAY_STATE = {
|
||||
export const ViewSelect = () => {
|
||||
const history = useHistory();
|
||||
const userContext = useUserContext();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [viewBuilderDisplayState, setViewBuilderDisplayState] = useState<ViewBuilderDisplayState>(
|
||||
DEFAULT_VIEW_BUILDER_DISPLAY_STATE,
|
||||
);
|
||||
@ -153,54 +182,62 @@ export const ViewSelect = () => {
|
||||
(publicViews.filter((view) => view.urn === selectedUrn)?.length || 0) > 0 ||
|
||||
false;
|
||||
|
||||
const handleDropdownVisibleChange = (isNowOpen: boolean) => {
|
||||
setIsOpen(isNowOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewSelectToolTip visible={selectedUrn === undefined}>
|
||||
<Select
|
||||
data-testid="view-select"
|
||||
style={selectStyle}
|
||||
onChange={() => (selectRef?.current as any)?.blur()}
|
||||
value={(foundSelectedUrn && selectedUrn) || undefined}
|
||||
placeholder="Select a View"
|
||||
onSelect={onSelectView}
|
||||
onClear={onClear}
|
||||
allowClear
|
||||
ref={selectRef}
|
||||
optionLabelProp="label"
|
||||
dropdownStyle={dropdownStyle}
|
||||
dropdownRender={(menu) => (
|
||||
<ViewSelectDropdown
|
||||
menu={menu}
|
||||
hasViews={hasViews}
|
||||
onClickCreateView={onClickCreateView}
|
||||
onClickClear={onClear}
|
||||
onClickManageViews={onClickManageViews}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{privateViewCount > 0 &&
|
||||
renderViewOptionGroup({
|
||||
views: privateViews,
|
||||
label: 'Private',
|
||||
isOwnedByUser: true,
|
||||
userContext,
|
||||
hoverViewUrn,
|
||||
setHoverViewUrn,
|
||||
onClickEditView,
|
||||
onClickPreviewView,
|
||||
})}
|
||||
{publicViewCount > 0 &&
|
||||
renderViewOptionGroup({
|
||||
views: publicViews,
|
||||
label: 'Public',
|
||||
userContext,
|
||||
hoverViewUrn,
|
||||
setHoverViewUrn,
|
||||
onClickEditView,
|
||||
onClickPreviewView,
|
||||
})}
|
||||
</Select>
|
||||
</ViewSelectToolTip>
|
||||
<ViewSelectContainer>
|
||||
<Select
|
||||
data-testid="view-select"
|
||||
style={{ minWidth: '120px', maxWidth: '200px' }}
|
||||
onChange={() => (selectRef?.current as any)?.blur()}
|
||||
value={(foundSelectedUrn && selectedUrn) || undefined}
|
||||
placeholder="All Entities"
|
||||
onSelect={onSelectView}
|
||||
onClear={onClear}
|
||||
ref={selectRef}
|
||||
optionLabelProp="label"
|
||||
bordered={false}
|
||||
dropdownMatchSelectWidth={false}
|
||||
suffixIcon={<TriangleIcon isOpen={isOpen} />}
|
||||
dropdownStyle={{
|
||||
position: 'fixed',
|
||||
paddingBottom: 0,
|
||||
}}
|
||||
onDropdownVisibleChange={handleDropdownVisibleChange}
|
||||
dropdownRender={(menu) => (
|
||||
<ViewSelectDropdown
|
||||
menu={menu}
|
||||
hasViews={hasViews}
|
||||
onClickCreateView={onClickCreateView}
|
||||
onClickClear={onClear}
|
||||
onClickManageViews={onClickManageViews}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{privateViewCount > 0 &&
|
||||
renderViewOptionGroup({
|
||||
views: privateViews,
|
||||
label: 'Private',
|
||||
isOwnedByUser: true,
|
||||
userContext,
|
||||
hoverViewUrn,
|
||||
setHoverViewUrn,
|
||||
onClickEditView,
|
||||
onClickPreviewView,
|
||||
})}
|
||||
{publicViewCount > 0 &&
|
||||
renderViewOptionGroup({
|
||||
views: publicViews,
|
||||
label: 'Public',
|
||||
userContext,
|
||||
hoverViewUrn,
|
||||
setHoverViewUrn,
|
||||
onClickEditView,
|
||||
onClickPreviewView,
|
||||
})}
|
||||
</Select>
|
||||
{viewBuilderDisplayState.visible && (
|
||||
<ViewBuilder
|
||||
urn={viewBuilderDisplayState.view?.urn || undefined}
|
||||
@ -210,6 +247,6 @@ export const ViewSelect = () => {
|
||||
onCancel={onCloseViewBuilder}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</ViewSelectContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -13,9 +13,13 @@ type Props = {
|
||||
export const ViewSelectDropdown = ({ menu, hasViews, onClickCreateView, onClickManageViews, onClickClear }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<ViewSelectHeader onClickCreateView={onClickCreateView} onClickClear={onClickClear} />
|
||||
<ViewSelectHeader onClickClear={onClickClear} />
|
||||
{hasViews && menu}
|
||||
<ViewSelectFooter onClickManageViews={onClickManageViews} />
|
||||
<ViewSelectFooter
|
||||
hasViews={hasViews}
|
||||
onClickCreateView={onClickCreateView}
|
||||
onClickManageViews={onClickManageViews}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,33 +1,47 @@
|
||||
import React, { useRef } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Button } from 'antd';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import { ANTD_GRAY } from '../../shared/constants';
|
||||
import { Button, Typography } from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { ANTD_GRAY, ANTD_GRAY_V2 } from '../../shared/constants';
|
||||
import { NoMarginButton } from './styledComponents';
|
||||
|
||||
const ButtonContainer = styled.div`
|
||||
display: flex;
|
||||
color: ${ANTD_GRAY[6]};
|
||||
width: 100%;
|
||||
justify-content: left;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const StyledRightOutlined = styled(RightOutlined)`
|
||||
&& {
|
||||
font-size: 8px;
|
||||
color: ${ANTD_GRAY[7]};
|
||||
const CreateViewButton = styled(NoMarginButton)<{ bordered: boolean }>`
|
||||
&&& {
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
padding-left: 0px;
|
||||
|
||||
${(props) => props.bordered && `border-top: 1px solid ${ANTD_GRAY_V2[5]};`}
|
||||
}
|
||||
`;
|
||||
|
||||
const ManageViewsButton = styled(Button)`
|
||||
font-weight: normal;
|
||||
color: ${ANTD_GRAY[7]};
|
||||
&&& {
|
||||
color: ${(props) => props.theme.styles['primary-color']};
|
||||
border-top: 1px solid ${ANTD_GRAY_V2[5]};
|
||||
background-color: ${ANTD_GRAY_V2[2]};
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
hasViews: boolean;
|
||||
onClickCreateView: () => void;
|
||||
onClickManageViews: () => void;
|
||||
};
|
||||
|
||||
export const ViewSelectFooter = ({ onClickManageViews }: Props) => {
|
||||
export const ViewSelectFooter = ({ hasViews, onClickCreateView, onClickManageViews }: Props) => {
|
||||
const manageViewsButtonRef = useRef(null);
|
||||
|
||||
const onHandleClickManageViews = () => {
|
||||
@ -37,9 +51,17 @@ export const ViewSelectFooter = ({ onClickManageViews }: Props) => {
|
||||
|
||||
return (
|
||||
<ButtonContainer>
|
||||
<CreateViewButton
|
||||
data-testid="view-select-create"
|
||||
type="text"
|
||||
bordered={hasViews}
|
||||
onClick={onClickCreateView}
|
||||
>
|
||||
<PlusOutlined />
|
||||
<Typography.Text>Create new view</Typography.Text>
|
||||
</CreateViewButton>
|
||||
<ManageViewsButton type="text" ref={manageViewsButtonRef} onClick={onHandleClickManageViews}>
|
||||
Manage Views
|
||||
<StyledRightOutlined />
|
||||
</ManageViewsButton>
|
||||
</ButtonContainer>
|
||||
);
|
||||
|
||||
@ -1,25 +1,32 @@
|
||||
import React, { useRef } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Button, Typography } from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { NoMarginButton } from './styledComponents';
|
||||
import { ANTD_GRAY_V2 } from '../../shared/constants';
|
||||
|
||||
const ButtonContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
const NoMarginButton = styled(Button)`
|
||||
&& {
|
||||
margin: 0px;
|
||||
const AllEntitiesButton = styled(NoMarginButton)`
|
||||
&&& {
|
||||
font-weight: normal;
|
||||
border-bottom: 1px solid ${ANTD_GRAY_V2[5]};
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
onClickCreateView: () => void;
|
||||
onClickClear: () => void;
|
||||
};
|
||||
|
||||
export const ViewSelectHeader = ({ onClickCreateView, onClickClear }: Props) => {
|
||||
export const ViewSelectHeader = ({ onClickClear }: Props) => {
|
||||
const clearButtonRef = useRef(null);
|
||||
|
||||
const onHandleClickClear = () => {
|
||||
@ -29,18 +36,14 @@ export const ViewSelectHeader = ({ onClickCreateView, onClickClear }: Props) =>
|
||||
|
||||
return (
|
||||
<ButtonContainer>
|
||||
<NoMarginButton data-testid="view-select-create" type="text" onClick={onClickCreateView}>
|
||||
<PlusOutlined />
|
||||
<Typography.Text strong> Create View</Typography.Text>
|
||||
</NoMarginButton>
|
||||
<NoMarginButton
|
||||
<AllEntitiesButton
|
||||
data-testid="view-select-clear"
|
||||
type="link"
|
||||
type="text"
|
||||
ref={clearButtonRef}
|
||||
onClick={onHandleClickClear}
|
||||
>
|
||||
Clear
|
||||
</NoMarginButton>
|
||||
All Entities
|
||||
</AllEntitiesButton>
|
||||
</ButtonContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Tooltip } from 'antd';
|
||||
|
||||
const HeaderText = styled.div`
|
||||
margin-bottom: 8px;
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
visible?: boolean;
|
||||
};
|
||||
|
||||
export const ViewSelectToolTip = ({ children, visible = true }: Props) => {
|
||||
return (
|
||||
<Tooltip
|
||||
overlayStyle={{ display: !visible ? 'none' : undefined }}
|
||||
placement="right"
|
||||
title={
|
||||
<>
|
||||
<HeaderText>Select a View to apply to search results.</HeaderText>
|
||||
<div>Views help narrow down search results to those that matter most to you.</div>
|
||||
</>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,17 @@
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import { Button } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import { ANTD_GRAY } from '../../shared/constants';
|
||||
|
||||
export const NoMarginButton = styled(Button)`
|
||||
&& {
|
||||
margin: 0px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledRightOutlined = styled(RightOutlined)`
|
||||
&& {
|
||||
font-size: 8px;
|
||||
color: ${ANTD_GRAY[7]};
|
||||
}
|
||||
`;
|
||||
@ -152,6 +152,7 @@ export const HomePageHeader = () => {
|
||||
const showAcrylInfo = useIsShowAcrylInfoEnabled();
|
||||
const { user } = userContext;
|
||||
const viewUrn = userContext.localState?.selectedViewUrn;
|
||||
const viewsEnabled = appConfig.config?.viewsConfig?.enabled || false;
|
||||
|
||||
useEffect(() => {
|
||||
if (suggestionsData !== undefined) {
|
||||
@ -271,6 +272,7 @@ export const HomePageHeader = () => {
|
||||
onQueryChange={onAutoComplete}
|
||||
autoCompleteStyle={styles.searchBox}
|
||||
entityRegistry={entityRegistry}
|
||||
viewsEnabled={viewsEnabled}
|
||||
showQuickFilters
|
||||
/>
|
||||
{searchResultsToShow && searchResultsToShow.length > 0 && (
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState, useRef, useCallback } from 'react';
|
||||
import React, { useEffect, useMemo, useState, useRef, useCallback, EventHandler, SyntheticEvent } from 'react';
|
||||
import { Input, AutoComplete, Button } from 'antd';
|
||||
import { CloseCircleFilled, SearchOutlined } from '@ant-design/icons';
|
||||
import styled from 'styled-components/macro';
|
||||
@ -6,7 +6,7 @@ import { useHistory } from 'react-router';
|
||||
import { AutoCompleteResultForEntity, Entity, EntityType, FacetFilterInput, ScenarioType } from '../../types.generated';
|
||||
import EntityRegistry from '../entity/EntityRegistry';
|
||||
import filterSearchQuery from './utils/filterSearchQuery';
|
||||
import { ANTD_GRAY } from '../entity/shared/constants';
|
||||
import { ANTD_GRAY, ANTD_GRAY_V2 } from '../entity/shared/constants';
|
||||
import { getEntityPath } from '../entity/shared/containers/profile/utils';
|
||||
import { EXACT_SEARCH_PREFIX } from './utils/constants';
|
||||
import { useListRecommendationsQuery } from '../../graphql/recommendations.generated';
|
||||
@ -22,6 +22,7 @@ import { useUserContext } from '../context/useUserContext';
|
||||
import { navigateToSearchUrl } from './utils/navigateToSearchUrl';
|
||||
import { getQuickFilterDetails } from './autoComplete/quickFilters/utils';
|
||||
import ViewAllSearchItem from './ViewAllSearchItem';
|
||||
import { ViewSelect } from '../entity/view/select/ViewSelect';
|
||||
|
||||
const StyledAutoComplete = styled(AutoComplete)`
|
||||
width: 100%;
|
||||
@ -39,9 +40,14 @@ const StyledSearchBar = styled(Input)`
|
||||
height: 40px;
|
||||
font-size: 20px;
|
||||
color: ${ANTD_GRAY[7]};
|
||||
background-color: ${ANTD_GRAY_V2[2]};
|
||||
}
|
||||
> .ant-input {
|
||||
font-size: 14px;
|
||||
background-color: ${ANTD_GRAY_V2[2]};
|
||||
}
|
||||
> .ant-input::placeholder {
|
||||
color: ${ANTD_GRAY_V2[10]};
|
||||
}
|
||||
.ant-input-clear-icon {
|
||||
height: 15px;
|
||||
@ -56,6 +62,16 @@ const ClearIcon = styled(CloseCircleFilled)`
|
||||
}
|
||||
`;
|
||||
|
||||
const ViewSelectContainer = styled.div`
|
||||
&&& {
|
||||
border-right: 1px solid ${ANTD_GRAY_V2[5]};
|
||||
}
|
||||
`;
|
||||
|
||||
const SearchIcon = styled(SearchOutlined)`
|
||||
color: ${ANTD_GRAY_V2[8]};
|
||||
`;
|
||||
|
||||
const EXACT_AUTOCOMPLETE_OPTION_TYPE = 'exact_query';
|
||||
const RECOMMENDED_QUERY_OPTION_TYPE = 'recommendation';
|
||||
|
||||
@ -89,6 +105,10 @@ const renderRecommendedQuery = (query: string) => {
|
||||
};
|
||||
};
|
||||
|
||||
const handleStopPropagation: EventHandler<SyntheticEvent> = (e) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
interface Props {
|
||||
initialQuery?: string;
|
||||
placeholderText: string;
|
||||
@ -102,6 +122,7 @@ interface Props {
|
||||
fixAutoComplete?: boolean;
|
||||
hideRecommendations?: boolean;
|
||||
showQuickFilters?: boolean;
|
||||
viewsEnabled?: boolean;
|
||||
setIsSearchBarFocused?: (isSearchBarFocused: boolean) => void;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
@ -127,6 +148,7 @@ export const SearchBar = ({
|
||||
fixAutoComplete,
|
||||
hideRecommendations,
|
||||
showQuickFilters,
|
||||
viewsEnabled = false,
|
||||
setIsSearchBarFocused,
|
||||
onFocus,
|
||||
onBlur,
|
||||
@ -326,6 +348,7 @@ export const SearchBar = ({
|
||||
listHeight={480}
|
||||
>
|
||||
<StyledSearchBar
|
||||
bordered={false}
|
||||
placeholder={placeholderText}
|
||||
onPressEnter={() => {
|
||||
handleSearch(
|
||||
@ -334,7 +357,7 @@ export const SearchBar = ({
|
||||
getFiltersWithQuickFilter(selectedQuickFilter),
|
||||
);
|
||||
}}
|
||||
style={inputStyle}
|
||||
style={{ ...inputStyle, color: 'red' }}
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
data-testid="search-input"
|
||||
@ -342,15 +365,28 @@ export const SearchBar = ({
|
||||
onBlur={handleBlur}
|
||||
allowClear={{ clearIcon: <ClearIcon /> }}
|
||||
prefix={
|
||||
<SearchOutlined
|
||||
onClick={() => {
|
||||
handleSearch(
|
||||
filterSearchQuery(searchQuery || ''),
|
||||
undefined,
|
||||
getFiltersWithQuickFilter(selectedQuickFilter),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
{viewsEnabled && (
|
||||
<ViewSelectContainer
|
||||
onClick={handleStopPropagation}
|
||||
onFocus={handleStopPropagation}
|
||||
onMouseDown={handleStopPropagation}
|
||||
onKeyUp={handleStopPropagation}
|
||||
onKeyDown={handleStopPropagation}
|
||||
>
|
||||
<ViewSelect />
|
||||
</ViewSelectContainer>
|
||||
)}
|
||||
<SearchIcon
|
||||
onClick={() => {
|
||||
handleSearch(
|
||||
filterSearchQuery(searchQuery || ''),
|
||||
undefined,
|
||||
getFiltersWithQuickFilter(selectedQuickFilter),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</StyledAutoComplete>
|
||||
|
||||
@ -11,7 +11,6 @@ import { ANTD_GRAY } from '../entity/shared/constants';
|
||||
import { HeaderLinks } from '../shared/admin/HeaderLinks';
|
||||
import { useAppConfig, useIsShowAcrylInfoEnabled } from '../useAppConfig';
|
||||
import { DEFAULT_APP_CONFIG } from '../../appConfigContext';
|
||||
import { ViewSelect } from '../entity/view/select/ViewSelect';
|
||||
import DemoButton from '../entity/shared/components/styled/DemoButton';
|
||||
|
||||
const { Header } = Layout;
|
||||
@ -49,10 +48,6 @@ const NavGroup = styled.div`
|
||||
min-width: 200px;
|
||||
`;
|
||||
|
||||
const ViewSelectContainer = styled.span`
|
||||
margin-right: 14px;
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
initialQuery: string;
|
||||
placeholderText: string;
|
||||
@ -85,7 +80,7 @@ export const SearchHeader = ({
|
||||
const themeConfig = useTheme();
|
||||
const showAcrylInfo = useIsShowAcrylInfoEnabled();
|
||||
const appConfig = useAppConfig();
|
||||
const viewsEnabled = appConfig.config?.viewsConfig?.enabled;
|
||||
const viewsEnabled = appConfig.config?.viewsConfig?.enabled || false;
|
||||
|
||||
return (
|
||||
<Header style={styles.header as any}>
|
||||
@ -108,16 +103,12 @@ export const SearchHeader = ({
|
||||
onQueryChange={onQueryChange}
|
||||
entityRegistry={entityRegistry}
|
||||
setIsSearchBarFocused={setIsSearchBarFocused}
|
||||
viewsEnabled={viewsEnabled}
|
||||
fixAutoComplete
|
||||
showQuickFilters
|
||||
/>
|
||||
</LogoSearchContainer>
|
||||
<NavGroup>
|
||||
{viewsEnabled && (
|
||||
<ViewSelectContainer>
|
||||
<ViewSelect />
|
||||
</ViewSelectContainer>
|
||||
)}
|
||||
<HeaderLinks areLinksHidden={isSearchBarFocused} />
|
||||
<ManageAccount urn={authenticatedUserUrn} pictureLink={authenticatedUserPictureLink || ''} />
|
||||
{showAcrylInfo && <DemoButton />}
|
||||
|
||||
@ -1,86 +1,88 @@
|
||||
function openViewEditDropDownAndClickId(data_id) {
|
||||
cy.openMultiSelect('view-select');
|
||||
cy.get('[data-testid="view-select-item"]').first().trigger('mouseover')
|
||||
cy.get('[data-testid="views-table-dropdown"]').first().trigger('mouseover');
|
||||
cy.openMultiSelect("view-select");
|
||||
cy.get('[data-testid="view-select-item"]').first().trigger("mouseover");
|
||||
cy.get('[data-testid="views-table-dropdown"]').first().trigger("mouseover");
|
||||
cy.clickOptionWithTestId(data_id);
|
||||
}
|
||||
|
||||
describe("view select", () => {
|
||||
it("click view select, create view, clear view, make defaults, clear view", () => {
|
||||
cy.login();
|
||||
let randomNumber = Math.floor(Math.random() * 100000);
|
||||
const viewName = `Test View ${randomNumber}`
|
||||
const newViewName = `New View Name ${randomNumber}`
|
||||
|
||||
// Resize Observer Loop warning can be safely ignored - ref. https://github.com/cypress-io/cypress/issues/22113
|
||||
const resizeObserverLoopErrRe = "ResizeObserver loop limit exceeded";
|
||||
cy.on('uncaught:exception', (err) => {
|
||||
if (err.message.includes(resizeObserverLoopErrRe)) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
cy.goToStarSearchList();
|
||||
|
||||
cy.log("Create a View from the select")
|
||||
cy.multiSelect('view-select', 'Create View');
|
||||
cy.waitTextVisible("Create new View")
|
||||
|
||||
cy.enterTextInTestId("view-name-input", viewName);
|
||||
|
||||
cy.log("Add Column Glossary Term Filter")
|
||||
cy.clickOptionWithText("Add Filter");
|
||||
cy.clickOptionWithText("Column Glossary Term");
|
||||
|
||||
cy.waitTextVisible("Add Glossary Terms");
|
||||
cy.selectOptionInTagTermModal("CypressColumnInfoType");
|
||||
|
||||
cy.clickOptionWithText("Save");
|
||||
cy.ensureTextNotPresent("Save");
|
||||
cy.waitTextVisible(viewName);
|
||||
|
||||
cy.log("Ensure the View filter has been applied correctly.")
|
||||
cy.contains("SampleCypressHdfsDataset");
|
||||
cy.contains("cypress_logging_events");
|
||||
cy.contains("of 2 results");
|
||||
|
||||
cy.log("Clear the selected view")
|
||||
cy.clearView(viewName);
|
||||
cy.ensureTextNotPresent("of 2 results");
|
||||
|
||||
cy.log("Now edit the view")
|
||||
openViewEditDropDownAndClickId('view-dropdown-edit');
|
||||
cy.get(".ant-input-affix-wrapper > input[type='text']").first().clear().type(newViewName);
|
||||
cy.log("Update the actual filters by adding another filter")
|
||||
cy.contains("Add Filter").click();
|
||||
cy.clickOptionWithTestId('adv-search-add-filter-description');
|
||||
cy.enterTextInTestId('edit-text-input', "log event");
|
||||
cy.clickOptionWithTestId('edit-text-done-btn');
|
||||
|
||||
cy.log("Save View")
|
||||
cy.clickOptionWithTestId("view-builder-save");
|
||||
|
||||
cy.contains("cypress_logging_events");
|
||||
cy.contains("of 1 result");
|
||||
|
||||
cy.log("Now set the View as the personal Default")
|
||||
cy.clearView(viewName);
|
||||
openViewEditDropDownAndClickId('view-dropdown-set-user-default');
|
||||
|
||||
cy.contains("of 1 result");
|
||||
cy.clearView(newViewName);
|
||||
cy.log("Now unset as the personal default")
|
||||
openViewEditDropDownAndClickId('view-dropdown-remove-user-default');
|
||||
|
||||
cy.log("Now delete the View")
|
||||
cy.clearView(newViewName);
|
||||
openViewEditDropDownAndClickId('view-dropdown-delete');
|
||||
cy.clickOptionWithText("Yes");
|
||||
|
||||
cy.log("Ensure that the view was deleted.")
|
||||
cy.goToViewsSettings();
|
||||
cy.ensureTextNotPresent(newViewName);
|
||||
cy.ensureTextNotPresent("of 1 result");
|
||||
it("click view select, create view, clear view, make defaults, clear view", () => {
|
||||
cy.login();
|
||||
let randomNumber = Math.floor(Math.random() * 100000);
|
||||
const viewName = `Test View ${randomNumber}`;
|
||||
const newViewName = `New View Name ${randomNumber}`;
|
||||
|
||||
// Resize Observer Loop warning can be safely ignored - ref. https://github.com/cypress-io/cypress/issues/22113
|
||||
const resizeObserverLoopErrRe = "ResizeObserver loop limit exceeded";
|
||||
cy.on("uncaught:exception", (err) => {
|
||||
if (err.message.includes(resizeObserverLoopErrRe)) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
cy.goToStarSearchList();
|
||||
|
||||
cy.log("Create a View from the select");
|
||||
cy.multiSelect("view-select", "Create new view");
|
||||
cy.waitTextVisible("Create new view");
|
||||
|
||||
cy.enterTextInTestId("view-name-input", viewName);
|
||||
|
||||
cy.log("Add Column Glossary Term Filter");
|
||||
cy.clickOptionWithText("Add Filter");
|
||||
cy.clickOptionWithText("Column Glossary Term");
|
||||
|
||||
cy.waitTextVisible("Add Glossary Terms");
|
||||
cy.selectOptionInTagTermModal("CypressColumnInfoType");
|
||||
|
||||
cy.clickOptionWithText("Save");
|
||||
cy.ensureTextNotPresent("Save");
|
||||
cy.waitTextVisible(viewName);
|
||||
|
||||
cy.log("Ensure the View filter has been applied correctly.");
|
||||
cy.contains("SampleCypressHdfsDataset");
|
||||
cy.contains("cypress_logging_events");
|
||||
cy.contains("of 2 results");
|
||||
|
||||
cy.log("Clear the selected view");
|
||||
cy.clearView(viewName);
|
||||
cy.ensureTextNotPresent("of 2 results");
|
||||
|
||||
cy.log("Now edit the view");
|
||||
openViewEditDropDownAndClickId("view-dropdown-edit");
|
||||
cy.get(".ant-input-affix-wrapper > input[type='text']")
|
||||
.first()
|
||||
.clear()
|
||||
.type(newViewName);
|
||||
cy.log("Update the actual filters by adding another filter");
|
||||
cy.contains("Add Filter").click();
|
||||
cy.clickOptionWithTestId("adv-search-add-filter-description");
|
||||
cy.enterTextInTestId("edit-text-input", "log event");
|
||||
cy.clickOptionWithTestId("edit-text-done-btn");
|
||||
|
||||
cy.log("Save View");
|
||||
cy.clickOptionWithTestId("view-builder-save");
|
||||
|
||||
cy.contains("cypress_logging_events");
|
||||
cy.contains("of 1 result");
|
||||
|
||||
cy.log("Now set the View as the personal Default");
|
||||
cy.clearView(viewName);
|
||||
openViewEditDropDownAndClickId("view-dropdown-set-user-default");
|
||||
|
||||
cy.contains("of 1 result");
|
||||
cy.clearView(newViewName);
|
||||
cy.log("Now unset as the personal default");
|
||||
openViewEditDropDownAndClickId("view-dropdown-remove-user-default");
|
||||
|
||||
cy.log("Now delete the View");
|
||||
cy.clearView(newViewName);
|
||||
openViewEditDropDownAndClickId("view-dropdown-delete");
|
||||
cy.clickOptionWithText("Yes");
|
||||
|
||||
cy.log("Ensure that the view was deleted.");
|
||||
cy.goToViewsSettings();
|
||||
cy.ensureTextNotPresent(newViewName);
|
||||
cy.ensureTextNotPresent("of 1 result");
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user