Skip to content

Commit

Permalink
Improve sticky behavior, Make syntax coherent
Browse files Browse the repository at this point in the history
  • Loading branch information
hanbyul-here committed May 3, 2024
1 parent 7f51c39 commit ae04d76
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 73 deletions.
81 changes: 38 additions & 43 deletions app/scripts/components/data-catalog/filters-control.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import React, {useCallback } from 'react';
import React, { useState, useRef, useEffect, useCallback } from 'react';
import styled from 'styled-components';
import { Taxonomy } from 'veda';
import SearchField from '$components/common/search-field';
import CheckableFilters, { OptionItem } from '$components/common/form/checkable-filter';
import { Actions, useBrowserControls } from '$components/common/browse-controls/use-browse-controls';
import { useSlidingStickyHeader, HEADER_TRANSITION_DURATION } from '$utils/use-sliding-sticky-header';

const ControlsWrapper = styled.div<{ width?: string; height?: string }>`
const ControlsWrapper = styled.div<{ widthValue?: string; heightValue?: string; topValue: string }>`
min-width: 20rem;
width: ${props => props.width ?? '20rem'};
width: ${props => props.widthValue ?? '20rem'};
position: sticky;
top: 0;
height: ${props => props.height == '100%' ? `${props.height}` : `calc(100vh + ${props.height}px)`};
top: calc(${props => props.topValue} + 1rem);
height: ${props => props.heightValue};
transition: top ${HEADER_TRANSITION_DURATION}ms ease-out;
`;

interface FiltersMenuProps extends ReturnType<typeof useBrowserControls> {
Expand All @@ -20,7 +22,6 @@ interface FiltersMenuProps extends ReturnType<typeof useBrowserControls> {
setClearedTagItem?: React.Dispatch<React.SetStateAction<OptionItem | undefined>>;
width?: string;
onChangeToFilters?: (item: OptionItem, action: 'add' | 'remove') => void;
areaHeight?: number;
}

export default function FiltersControl(props: FiltersMenuProps) {
Expand All @@ -32,13 +33,12 @@ export default function FiltersControl(props: FiltersMenuProps) {
width,
onChangeToFilters,
clearedTagItem,
setClearedTagItem,
areaHeight,
setClearedTagItem
} = props;

const searchRef = React.useRef<HTMLDivElement>(null);
const [controlsHeight, setControlsHeight] = React.useState<number>(0);
const [heightStyle, setHeightStyle] = React.useState<string>();
const controlRef = useRef<HTMLDivElement>(null);
const [controlsHeight, setControlsHeight] = useState<number>(0);
const { isHeaderHidden, wrapperHeight } = useSlidingStickyHeader();

const handleChanges = useCallback((item: OptionItem) => {
if(allSelected.some((selected) => selected.id == item.id && selected.taxonomy == item.taxonomy)) {
Expand All @@ -51,53 +51,48 @@ export default function FiltersControl(props: FiltersMenuProps) {
}
}, [allSelected, setClearedTagItem, onChangeToFilters]);

const calculateHeightOfAllFilters = (height: number) => {
setControlsHeight(prev => prev + height);
};


React.useEffect(() => {
if(searchRef.current) {
const height = searchRef.current.offsetHeight;
setControlsHeight(prev => prev + height);
}
}, [searchRef]);
useEffect(() => {
if (!controlRef.current) return;

const height = controlRef.current.offsetHeight;
setControlsHeight(height);
// Observe the height change of controls (from accordion folding)
const resizeObserver = new ResizeObserver(([entry]) => {
if (entry.contentBoxSize.length > 0) {
const contentBoxSize = entry.contentBoxSize[0];
setControlsHeight(contentBoxSize.blockSize);
}
});
resizeObserver.observe(controlRef.current);
return () => resizeObserver.disconnect(); // clean up
}, [controlRef]);

React.useEffect(() => {
if (areaHeight && (controlsHeight >= areaHeight)) {
setHeightStyle('100%');
} else if (areaHeight) {
const total = (areaHeight - controlsHeight) / 3;
setHeightStyle(`${total}`);
}
}, [controlsHeight, areaHeight]);

return (
<ControlsWrapper width={width} height={heightStyle}>
<div ref={searchRef}>
<ControlsWrapper widthValue={width} heightValue={controlsHeight+'px'} topValue={isHeaderHidden? '0px': `${wrapperHeight}px`}>
<div ref={controlRef}>
<SearchField
size='large'
placeholder='Search by title, description'
value={search ?? ''}
onChange={(v) => onAction(Actions.SEARCH, v)}
/>
</div>
{
taxonomiesOptions.map((taxonomy) => {
const items = taxonomy.values.map((t) => ({...t, taxonomy: taxonomy.name}));
return (
<CheckableFilters
key={taxonomy.name}
items={items}
title={taxonomy.name}
onChanges={handleChanges}
globallySelected={allSelected}
tagItemCleared={{item: clearedTagItem, callback: setClearedTagItem}}
calculateHeightCallback={calculateHeightOfAllFilters}
/>
<CheckableFilters
key={taxonomy.name}
items={items}
title={taxonomy.name}
onChanges={handleChanges}
globallySelected={allSelected}
tagItemCleared={{item: clearedTagItem, callback: setClearedTagItem}}
/>
);
})
}
</div>
</ControlsWrapper>
);
}
}
47 changes: 17 additions & 30 deletions app/scripts/components/data-catalog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef } from 'react';
import React, { useRef, useState, useMemo, useEffect, useCallback } from 'react';
import styled from 'styled-components';
import { DatasetData } from 'veda';
import { Link, useNavigate } from 'react-router-dom';
Expand Down Expand Up @@ -114,17 +114,15 @@ function DataCatalog({ datasets }: DataCatalogProps) {

const { taxonomies, sortField, sortDir, onAction } = controlVars;
const search = controlVars.search ?? '';
let urlTaxonomyItems: OptionItem[] = [];

const datasetTaxonomies = generateTaxonomies(datasets);

if (taxonomies) {
urlTaxonomyItems = Object.entries(taxonomies).map(([key, val]) => getTaxonomyByIds(key, val, datasetTaxonomies)).flat() || [];
}

const allDatasetsWithEnhancedLayers = React.useMemo(() => getAllDatasetsWithEnhancedLayers(datasets), [datasets]);

const urlTaxonomyItems = taxonomies? Object.entries(taxonomies).map(([key, val]) => getTaxonomyByIds(key, val, datasetTaxonomies)).flat(): [];

const allDatasetsWithEnhancedLayers = useMemo(() => getAllDatasetsWithEnhancedLayers(datasets), [datasets]);

const [datasetsToDisplay, setDatasetsToDisplay] = React.useState<DatasetData[]>(
const [datasetsToDisplay, setDatasetsToDisplay] = useState<DatasetData[]>(
prepareDatasets(allDatasetsWithEnhancedLayers, {
search,
taxonomies,
Expand All @@ -133,16 +131,13 @@ function DataCatalog({ datasets }: DataCatalogProps) {
filterLayers: false
}));

const [allSelectedFilters, setAllSelectedFilters] = React.useState<OptionItem[]>(urlTaxonomyItems);
const [clearedTagItem, setClearedTagItem] = React.useState<OptionItem>();
const [allSelectedFilters, setAllSelectedFilters] = useState<OptionItem[]>(urlTaxonomyItems);
const [clearedTagItem, setClearedTagItem] = useState<OptionItem>();

const prevSelectedFilters = usePreviousValue(allSelectedFilters) || [];

const targetRef = React.useRef<HTMLOListElement>(null);
const [targetHeight, setTargetHeight] = React.useState<number>(0);

// Handlers
const handleChangeAllSelectedFilters = React.useCallback((item: OptionItem, action: 'add' | 'remove') => {
const handleChangeAllSelectedFilters = useCallback((item: OptionItem, action: 'add' | 'remove') => {
if(action == 'add') {
setAllSelectedFilters([...allSelectedFilters, item]);
}
Expand All @@ -153,38 +148,31 @@ function DataCatalog({ datasets }: DataCatalogProps) {
onAction(Actions.TAXONOMY_MULTISELECT, { key: item.taxonomy, value: item.id });
}, [setAllSelectedFilters, allSelectedFilters, onAction]);

const handleClearTag = React.useCallback((item: OptionItem) => {
const handleClearTag = useCallback((item: OptionItem) => {
setAllSelectedFilters(allSelectedFilters.filter((selected) => selected !== item));
setClearedTagItem(item);

}, [allSelectedFilters]);

const handleClearTags = React.useCallback(() => {
const handleClearTags = useCallback(() => {
setAllSelectedFilters([]);
}, [setAllSelectedFilters]);

React.useEffect(() => {
if(targetRef.current) {
const height = targetRef.current.offsetHeight;
setTargetHeight(height);
}
}, [targetRef]);

React.useEffect(() => {
useEffect(() => {
if (clearedTagItem && (allSelectedFilters.length == prevSelectedFilters.length-1)) {
onAction(Actions.TAXONOMY_MULTISELECT, { key: clearedTagItem.taxonomy, value: clearedTagItem.id});
setClearedTagItem(undefined);
}
}, [allSelectedFilters, clearedTagItem]);

React.useEffect(() => {
useEffect(() => {
if(!allSelectedFilters.length) {
onAction(Actions.CLEAR);
navigate(DATASETS_PATH);
}
}, [allSelectedFilters]);

React.useEffect(() => {
useEffect(() => {
const updated = prepareDatasets(allDatasetsWithEnhancedLayers, {
search,
taxonomies,
Expand All @@ -198,8 +186,8 @@ function DataCatalog({ datasets }: DataCatalogProps) {
const browseControlsHeaderRef = useRef<HTMLDivElement>(null);
const { headerHeight } = useSlidingStickyHeaderProps();

const renderTags = React.useMemo(() => {
if(allSelectedFilters.length > 0 || urlTaxonomyItems.length > 0) {
const renderTags = useMemo(() => {
if (allSelectedFilters.length > 0 || urlTaxonomyItems.length > 0) {
return (
<Tags>
{
Expand Down Expand Up @@ -236,12 +224,11 @@ function DataCatalog({ datasets }: DataCatalogProps) {
clearedTagItem={clearedTagItem}
setClearedTagItem={setClearedTagItem}
allSelected={allSelectedFilters}
areaHeight={targetHeight}
/>
<CatalogWrapper>
{renderTags}
{datasetsToDisplay.length ? (
<Cards ref={targetRef}>
<Cards>
{datasetsToDisplay.map((d) => {
const topics = getTaxonomy(d, TAXONOMY_TOPICS)?.values;
const allTaxonomyValues = getAllTaxonomyValues(d).map((v) => v.name);
Expand Down

0 comments on commit ae04d76

Please sign in to comment.