Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(siblings) Add flag to prevent combining siblings in the UI #10952

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ public class FeatureFlags {
private boolean schemaFieldEntityFetchEnabled = false;
private boolean businessAttributeEntityEnabled = false;
private boolean dataContractsEnabled = false;
private boolean showSeparateSiblings = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ public CompletableFuture<AppConfig> get(final DataFetchingEnvironment environmen
.setNestedDomainsEnabled(_featureFlags.isNestedDomainsEnabled())
.setPlatformBrowseV2(_featureFlags.isPlatformBrowseV2())
.setDataContractsEnabled(_featureFlags.isDataContractsEnabled())
.setShowSeparateSiblings(_featureFlags.isShowSeparateSiblings())
.build();

appConfig.setFeatureFlags(featureFlagsConfig);
Expand Down
5 changes: 5 additions & 0 deletions datahub-graphql-core/src/main/resources/app.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,11 @@ type FeatureFlagsConfig {
Whether data contracts should be enabled
"""
dataContractsEnabled: Boolean!

"""
If turned on, all siblings will be separated with no way to get to a "combined" sibling view
"""
showSeparateSiblings: Boolean!
}

"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
StyledTooltip,
} from './ParentNodesView';
import ParentEntities from '../../../../../../search/filters/ParentEntities';
import { useIsShowSeparateSiblingsEnabled } from '../../../../../../useAppConfig';

export const LogoIcon = styled.span`
display: flex;
Expand Down Expand Up @@ -100,6 +101,10 @@ function PlatformContentView(props: Props) {
const directParentContainer = parentContainers && parentContainers[0];
const remainingParentContainers = parentContainers && parentContainers.slice(1, parentContainers.length);

const shouldShowSeparateSiblings = useIsShowSeparateSiblingsEnabled();
const showSiblingPlatformLogos = !shouldShowSeparateSiblings && !!platformLogoUrls;
const showSiblingPlatformNames = !shouldShowSeparateSiblings && !!platformNames;

return (
<PlatformContentWrapper>
{typeIcon && <LogoIcon>{typeIcon}</LogoIcon>}
Expand All @@ -110,10 +115,10 @@ function PlatformContentView(props: Props) {
{platformName && (
<LogoIcon>
{!platformLogoUrl && !platformLogoUrls && entityLogoComponent}
{!!platformLogoUrl && !platformLogoUrls && (
{!!platformLogoUrl && !showSiblingPlatformLogos && (
<PreviewImage preview={false} src={platformLogoUrl} alt={platformName} />
)}
{!!platformLogoUrls &&
{showSiblingPlatformLogos &&
platformLogoUrls.slice(0, 2).map((platformLogoUrlsEntry) => (
<>
<PreviewImage preview={false} src={platformLogoUrlsEntry || ''} alt={platformName} />
Expand All @@ -122,7 +127,7 @@ function PlatformContentView(props: Props) {
</LogoIcon>
)}
<PlatformText>
{platformNames ? platformNames.join(' & ') : platformName}
{showSiblingPlatformNames ? platformNames.join(' & ') : platformName}
{(directParentContainer || instanceId) && <StyledRightOutlined data-testid="right-arrow" />}
</PlatformText>
{instanceId && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CompactEntityNameList } from '../../../../../recommendations/renderer/c
import { Dataset, Entity } from '../../../../../../types.generated';
import { SEPARATE_SIBLINGS_URL_PARAM, stripSiblingsFromEntity, useIsSeparateSiblingsMode } from '../../../siblingUtils';
import { GetDatasetQuery } from '../../../../../../graphql/dataset.generated';
import { useIsShowSeparateSiblingsEnabled } from '../../../../../useAppConfig';

const EntityListContainer = styled.div`
margin-left: -8px;
Expand All @@ -16,13 +17,15 @@ export const SidebarSiblingsSection = () => {
const { entityData } = useEntityData();
const dataNotCombinedWithSiblings = useDataNotCombinedWithSiblings<GetDatasetQuery>();

const showSeparateSiblings = useIsShowSeparateSiblingsEnabled();
const isHideSiblingMode = useIsSeparateSiblingsMode();

if (!entityData) {
return <></>;
}

if (isHideSiblingMode) {
// showSeparateSiblings disables the combined view, but with this flag on we show siblings in the sidebar to navigate to them
if (!showSeparateSiblings && isHideSiblingMode) {
return (
<div>
<SidebarHeader title="Part Of" />
Expand All @@ -36,13 +39,19 @@ export const SidebarSiblingsSection = () => {
const siblingEntities = entityData?.siblings?.siblings || [];
const entityDataWithoutSiblings = stripSiblingsFromEntity(dataNotCombinedWithSiblings.dataset);

const allSiblingsInGroup = [...siblingEntities, entityDataWithoutSiblings] as Dataset[];
const allSiblingsInGroup = showSeparateSiblings
? (siblingEntities as Dataset[])
: ([...siblingEntities, entityDataWithoutSiblings] as Dataset[]);

const allSiblingsInGroupThatExist = allSiblingsInGroup.filter((sibling) => sibling.exists);

if (!allSiblingsInGroupThatExist.length) {
return <></>;
}

// you are always going to be in the sibling group, so if the sibling group is just you do not render.
// The less than case is likely not neccessary but just there as a safety case for unexpected scenarios
if (allSiblingsInGroupThatExist.length <= 1) {
if (!showSeparateSiblings && allSiblingsInGroupThatExist.length <= 1) {
return <></>;
}

Expand Down
4 changes: 3 additions & 1 deletion datahub-web-react/src/app/entity/shared/siblingUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useLocation } from 'react-router-dom';
import * as QueryString from 'query-string';
import { Dataset, Entity, Maybe, SiblingProperties } from '../../../types.generated';
import { GenericEntityProperties } from './types';
import { useIsShowSeparateSiblingsEnabled } from '../../useAppConfig';

export function stripSiblingsFromEntity(entity: any) {
return {
Expand Down Expand Up @@ -267,8 +268,9 @@ export const SEPARATE_SIBLINGS_URL_PARAM = 'separate_siblings';

// used to determine whether sibling entities should be shown merged or not
export function useIsSeparateSiblingsMode() {
const showSeparateSiblings = useIsShowSeparateSiblingsEnabled();
const location = useLocation();
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });

return params[SEPARATE_SIBLINGS_URL_PARAM] === 'true';
return showSeparateSiblings || params[SEPARATE_SIBLINGS_URL_PARAM] === 'true';
}
44 changes: 24 additions & 20 deletions datahub-web-react/src/app/lineage/controls/LineageVizToggles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ANTD_GRAY } from '../../entity/shared/constants';
import { navigateToLineageUrl } from '../utils/navigateToLineageUrl';
import { useIsSeparateSiblingsMode } from '../../entity/shared/siblingUtils';
import { useIsShowColumnsMode } from '../utils/useIsShowColumnsMode';
import { useIsShowSeparateSiblingsEnabled } from '../../useAppConfig';

const ControlDiv = styled.div`
display: flex;
Expand Down Expand Up @@ -38,6 +39,7 @@ export function LineageVizToggles({ showExpandedTitles, setShowExpandedTitles }:
const location = useLocation();
const isHideSiblingMode = useIsSeparateSiblingsMode();
const showColumns = useIsShowColumnsMode();
const showSeparateSiblings = useIsShowSeparateSiblingsEnabled();

return (
<>
Expand All @@ -51,26 +53,28 @@ export function LineageVizToggles({ showExpandedTitles, setShowExpandedTitles }:
<b>Show Full Titles</b>
</ControlLabel>
</ControlDiv>
<ControlDiv>
<ControlsSwitch
data-testid="compress-lineage-toggle"
checked={!isHideSiblingMode}
onChange={(checked) => {
navigateToLineageUrl({
location,
history,
isLineageMode: true,
isHideSiblingMode: !checked,
});
}}
/>{' '}
<ControlLabel>
<b>Compress Lineage</b>
<Tooltip title="Collapses related entities into a single lineage node" placement="topRight">
<HelpIcon />
</Tooltip>
</ControlLabel>
</ControlDiv>
{!showSeparateSiblings && (
<ControlDiv>
<ControlsSwitch
data-testid="compress-lineage-toggle"
checked={!isHideSiblingMode}
onChange={(checked) => {
navigateToLineageUrl({
location,
history,
isLineageMode: true,
isHideSiblingMode: !checked,
});
}}
/>{' '}
<ControlLabel>
<b>Compress Lineage</b>
<Tooltip title="Collapses related entities into a single lineage node" placement="topRight">
<HelpIcon />
</Tooltip>
</ControlLabel>
</ControlDiv>
)}
<ControlDiv>
<ControlsSwitch
data-testid="column-toggle"
Expand Down
11 changes: 8 additions & 3 deletions datahub-web-react/src/app/search/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import ViewAllSearchItem from './ViewAllSearchItem';
import { ViewSelect } from '../entity/view/select/ViewSelect';
import { combineSiblingsInAutoComplete } from './utils/combineSiblingsInAutoComplete';
import { CommandK } from './CommandK';
import { useIsShowSeparateSiblingsEnabled } from '../useAppConfig';

const StyledAutoComplete = styled(AutoComplete)`
width: 100%;
Expand Down Expand Up @@ -157,6 +158,8 @@ export const SearchBar = ({
const [selected, setSelected] = useState<string>();
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
const [isFocused, setIsFocused] = useState(false);
const isShowSeparateSiblingsEnabled = useIsShowSeparateSiblingsEnabled();
const finalCombineSiblings = isShowSeparateSiblingsEnabled ? false : combineSiblings;

useEffect(() => setSelected(initialQuery), [initialQuery]);

Expand Down Expand Up @@ -223,7 +226,9 @@ export const SearchBar = ({

const autoCompleteEntityOptions = useMemo(() => {
return suggestions.map((suggestion: AutoCompleteResultForEntity) => {
const combinedSuggestion = combineSiblingsInAutoComplete(suggestion, { combineSiblings });
const combinedSuggestion = combineSiblingsInAutoComplete(suggestion, {
combineSiblings: finalCombineSiblings,
});
return {
label: <SectionHeader entityType={combinedSuggestion.type} />,
options: combinedSuggestion.combinedEntities.map((combinedEntity) => ({
Expand All @@ -232,15 +237,15 @@ export const SearchBar = ({
<AutoCompleteItem
query={effectiveQuery}
entity={combinedEntity.entity}
siblings={combineSiblings ? combinedEntity.matchedEntities : undefined}
siblings={finalCombineSiblings ? combinedEntity.matchedEntities : undefined}
/>
),
type: combinedEntity.entity.type,
style: { padding: '12px 12px 12px 16px' },
})),
};
});
}, [combineSiblings, effectiveQuery, suggestions]);
}, [finalCombineSiblings, effectiveQuery, suggestions]);

const previousSelectedQuickFilterValue = usePrevious(selectedQuickFilter?.value);
useEffect(() => {
Expand Down
7 changes: 6 additions & 1 deletion datahub-web-react/src/app/search/SearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import SearchQuerySuggester from './suggestions/SearchQuerySugggester';
import { ANTD_GRAY_V2 } from '../entity/shared/constants';
import { formatNumberWithoutAbbreviation } from '../shared/formatNumber';
import SearchResultsLoadingSection from './SearchResultsLoadingSection';
import { useIsShowSeparateSiblingsEnabled } from '../useAppConfig';

const SearchResultsWrapper = styled.div<{ v2Styles: boolean }>`
display: flex;
Expand Down Expand Up @@ -173,7 +174,11 @@ export const SearchResults = ({
const totalResults = searchResponse?.total || 0;
const lastResultIndex = pageStart + pageSize > totalResults ? totalResults : pageStart + pageSize;
const authenticatedUserUrn = useUserContext().user?.urn;
const combinedSiblingSearchResults = combineSiblingsInSearchResults(searchResponse?.searchResults);
const showSeparateSiblings = useIsShowSeparateSiblingsEnabled();
const combinedSiblingSearchResults = combineSiblingsInSearchResults(
showSeparateSiblings,
searchResponse?.searchResults,
);

const searchResultUrns = combinedSiblingSearchResults.map((result) => result.entity.urn) || [];
const selectedEntityUrns = selectedEntities.map((entity) => entity.urn);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,13 @@ export default function AutoCompleteEntity({ query, entity, siblings, hasParentT
const displayName = entityRegistry.getDisplayName(entity.type, entity);
const { matchedText, unmatchedText } = getAutoCompleteEntityText(displayName, query);
const entities = siblings?.length ? siblings : [entity];
const platformsToShow =
/* Only show sibling platforms if there are > 0 explicitly included siblings */
siblings?.length
? genericEntityProps?.siblingPlatforms
: (genericEntityProps?.platform && [genericEntityProps?.platform]) || undefined;
const platforms =
genericEntityProps?.siblingPlatforms
platformsToShow
?.map(
(platform) =>
getPlatformName(entityRegistry.getGenericEntityProperties(EntityType.DataPlatform, platform)) || '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ const searchResultWithGhostSiblings = [
describe('siblingUtils', () => {
describe('combineSiblingsInSearchResults', () => {
it('combines search results to deduplicate siblings', () => {
const result = combineSiblingsInSearchResults(searchResultWithSiblings as any);
const result = combineSiblingsInSearchResults(false, searchResultWithSiblings as any);

expect(result).toHaveLength(1);
expect(result?.[0]?.matchedEntities?.[0]?.urn).toEqual(
Expand All @@ -507,7 +507,7 @@ describe('siblingUtils', () => {
});

it('will not combine an entity with a ghost node', () => {
const result = combineSiblingsInSearchResults(searchResultWithGhostSiblings as any);
const result = combineSiblingsInSearchResults(false, searchResultWithGhostSiblings as any);

expect(result).toHaveLength(1);
expect(result?.[0]?.matchedEntities?.[0]?.urn).toEqual(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ type UncombinedSeaerchResults = {
export type CombinedSearchResult = CombinedEntity & Pick<UncombinedSeaerchResults, 'matchedFields'>;

export function combineSiblingsInSearchResults(
showSeparateSiblings: boolean,
searchResults: Array<UncombinedSeaerchResults> | undefined = [],
): Array<CombinedSearchResult> {
const combine = createSiblingEntityCombiner();
const combinedSearchResults: Array<CombinedSearchResult> = [];

searchResults.forEach((searchResult) => {
const combinedResult = combine(searchResult.entity);
const combinedResult = showSeparateSiblings
? { combinedEntity: searchResult.entity, skipped: false }
: combine(searchResult.entity);
if (!combinedResult.skipped) {
combinedSearchResults.push({
...searchResult,
Expand Down
5 changes: 5 additions & 0 deletions datahub-web-react/src/app/useAppConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ export function useIsAppConfigContextLoaded() {
const appConfig = useAppConfig();
return appConfig.loaded;
}

export function useIsShowSeparateSiblingsEnabled() {
const appConfig = useAppConfig();
return appConfig.config.featureFlags.showSeparateSiblings;
}
1 change: 1 addition & 0 deletions datahub-web-react/src/appConfigContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const DEFAULT_APP_CONFIG = {
platformBrowseV2: false,
businessAttributeEntityEnabled: false,
dataContractsEnabled: false,
showSeparateSiblings: false,
},
};

Expand Down
1 change: 1 addition & 0 deletions datahub-web-react/src/graphql/app.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ query appConfig {
platformBrowseV2
businessAttributeEntityEnabled
dataContractsEnabled
showSeparateSiblings
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ featureFlags:
schemaFieldEntityFetchEnabled: ${SCHEMA_FIELD_ENTITY_FETCH_ENABLED:true} # Enables fetching for schema field entities from the database when we hydrate them on schema fields
businessAttributeEntityEnabled: ${BUSINESS_ATTRIBUTE_ENTITY_ENABLED:false} # Enables business attribute entity which can be associated with field of dataset
dataContractsEnabled: ${DATA_CONTRACTS_ENABLED:true} # Enables the Data Contracts feature (Tab) in the UI
showSeparateSiblings: ${SHOW_SEPARATE_SIBLINGS:false} # If turned on, all siblings will be separated with no way to get to a "combined" sibling view

entityChangeEvents:
enabled: ${ENABLE_ENTITY_CHANGE_EVENTS_HOOK:true}
Expand Down
Loading