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

Expose Data Catalog and update child components to pass in routing/nav #1096

Merged
merged 11 commits into from
Sep 6, 2024
28 changes: 14 additions & 14 deletions app/scripts/components/common/card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,12 @@ import {
themeVal,
listReset,
} from '@devseed-ui/theme-provider';
import SmartLink from '../smart-link';
import { CardBody, CardBlank, CardHeader, CardHeadline, CardTitle, CardOverline } from './styles';
import HorizontalInfoCard, { HorizontalCardStyles } from './horizontal-info-card';
import { variableBaseType, variableGlsp } from '$styles/variable-utils';

import { ElementInteractive } from '$components/common/element-interactive';
import { Figure } from '$components/common/figure';



type CardType = 'classic' | 'cover' | 'featured' | 'horizontal-info';

interface CardItemProps {
Expand Down Expand Up @@ -223,9 +219,17 @@ export function ExternalLinkFlag() {
);
}

export interface LinkProperties {
LinkElement: JSX.Element | ((props: any) => JSX.Element);
pathAttributeKeyName: string;
onLinkClick?: MouseEventHandler;
}

export interface CardComponentProps {
title: JSX.Element | string;
linkTo: string;
linkProperties: {
linkTo: string,
} & LinkProperties;
linkLabel?: string;
className?: string;
cardType?: CardType;
Expand All @@ -238,7 +242,6 @@ export interface CardComponentProps {
tagLabels?: string[];
footerContent?: JSX.Element;
onCardClickCapture?: MouseEventHandler;
onLinkClick?: MouseEventHandler;
}

function CardComponent(props: CardComponentProps) {
Expand All @@ -248,7 +251,6 @@ function CardComponent(props: CardComponentProps) {
cardType,
description,
linkLabel,
linkTo,
date,
overline,
imgSrc,
Expand All @@ -257,24 +259,22 @@ function CardComponent(props: CardComponentProps) {
parentTo,
footerContent,
onCardClickCapture,
onLinkClick
linkProperties
} = props;

const isExternalLink = /^https?:\/\//.test(linkTo);
const isExternalLink = /^https?:\/\//.test(linkProperties.linkTo);

return (
<ElementInteractive
linkProps={{
as: SmartLink,
to: linkTo,
onLinkClick
as: linkProperties.LinkElement,
[linkProperties.pathAttributeKeyName]: linkProperties.linkTo,
onLinkClick: linkProperties.onLinkClick,
}}
as={CardItem}
cardType={cardType}
className={className}
linkLabel={linkLabel ?? 'View more'}
linkTo={linkTo}
onLinkClick={onLinkClick}
onClickCapture={onCardClickCapture}
>
{
Expand Down
11 changes: 7 additions & 4 deletions app/scripts/components/common/catalog/catalog-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled, { css } from "styled-components";
import { CollecticonPlus, CollecticonTickSmall, iconDataURI } from "@devseed-ui/collecticons";
import { glsp, themeVal } from "@devseed-ui/theme-provider";

import { Card } from "../card";
import { Card, LinkProperties } from "../card";
import { CardMeta, CardTopicsList } from "../card/styles";
import { DatasetClassification } from "../dataset-classification";
import { CardSourcesList } from "../card-sources";
Expand All @@ -20,6 +20,8 @@ interface CatalogCardProps {
selectable?: boolean;
selected?: boolean;
onDatasetClick?: () => void;
pathname?: string;
linkProperties: LinkProperties;
}

const CardSelectable = styled(Card)<{ checked?: boolean, selectable?: boolean }>`
Expand Down Expand Up @@ -90,7 +92,7 @@ const CardSelectable = styled(Card)<{ checked?: boolean, selectable?: boolean }>
`;

export const CatalogCard = (props: CatalogCardProps) => {
const { dataset, layer, searchTerm, selectable, selected, onDatasetClick } = props;
const { dataset, layer, searchTerm, selectable, selected, onDatasetClick, linkProperties, pathname} = props;

const topics = getTaxonomy(dataset, TAXONOMY_TOPICS)?.values;
const sources = getTaxonomy(dataset, TAXONOMY_SOURCE)?.values;
Expand All @@ -108,6 +110,8 @@ export const CatalogCard = (props: CatalogCardProps) => {
}
};

const linkTo = getDatasetPath(dataset, pathname);

return (
<CardSelectable
cardType='horizontal-info'
Expand All @@ -120,9 +124,7 @@ export const CatalogCard = (props: CatalogCardProps) => {
<CardSourcesList sources={sources} />
</CardMeta>
}
linkTo={getDatasetPath(dataset)}
linkLabel='View dataset'
onLinkClick={handleClick}
title={
<TextHighlight value={searchTerm} disabled={searchTerm.length < 3}>
{title}
Expand Down Expand Up @@ -153,6 +155,7 @@ export const CatalogCard = (props: CatalogCardProps) => {
) : null}
</>
}
linkProperties={{...linkProperties, linkTo: linkTo, onLinkClick: handleClick}}
/>
);
};
18 changes: 15 additions & 3 deletions app/scripts/components/common/catalog/catalog-content.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useState, useMemo, useEffect, useCallback } from 'react';
import styled from 'styled-components';

import { glsp, themeVal } from '@devseed-ui/theme-provider';
import TextHighlight from '../text-highlight';
import { CollecticonDatasetLayers } from '../icons/dataset-layers';
import { LinkProperties } from '../card';
import { prepareDatasets } from './prepare-datasets';
import FiltersControl from './filters-control';
import { CatalogCard } from './catalog-card';
Expand Down Expand Up @@ -34,6 +34,8 @@ export interface CatalogContentProps {
search: string;
taxonomies: Record<string, string[]>;
onAction: (action: FilterActions, value?: any) => void;
linkProperties: LinkProperties;
pathname?: string;
}

const DEFAULT_SORT_OPTION = 'asc';
Expand Down Expand Up @@ -70,10 +72,12 @@ function CatalogContent({
search,
taxonomies,
onAction,
pathname,
linkProperties
}: CatalogContentProps) {
const [exclusiveSourceSelected, setExclusiveSourceSelected] = useState<string | null>(null);
const isSelectable = selectedIds !== undefined;

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

Expand Down Expand Up @@ -202,6 +206,7 @@ function CatalogContent({
exclusiveSourceSelected={exclusiveSourceSelected}
customTopOffset={isSelectable ? 50 : 0}
openByDefault={isSelectable ? false : true}
pathname={pathname}
/>
<Catalog>
<CatalogTagsContainer
Expand Down Expand Up @@ -250,6 +255,8 @@ function CatalogContent({
selectable={true}
selected={selectedIds.includes(datasetLayer.id)}
onDatasetClick={() => onCardSelect(datasetLayer.id, currentDataset)}
linkProperties={linkProperties}
pathname={pathname}
/>
</li>
))}
Expand All @@ -261,7 +268,12 @@ function CatalogContent({
<Cards>
{datasetsToDisplay.map((d) => (
<li key={d.id}>
<CatalogCard dataset={d} searchTerm={search} />
<CatalogCard
dataset={d}
searchTerm={search}
linkProperties={linkProperties}
pathname={pathname}
/>
</li>
))}
</Cards>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useAtom } from 'jotai';
import { useCallback } from 'react';
import { useNavigate } from 'react-router';
import useQsStateCreator from 'qs-state-hook';
import { taxonomyAtom } from '../atoms/taxonomy-atom';
import { searchAtom } from '../atoms/search-atom';
import { FilterActions, FilterAction, onFilterAction } from '../../utils';
interface UseFiltersWithQueryResult {

export interface UseFiltersWithQueryResult {
search: string;
taxonomies: Record<string, string[]> | Record<string, never>;
onAction: FilterAction
Expand All @@ -32,11 +32,23 @@ export function useFiltersWithURLAtom(): UseFiltersWithQueryResult {
};
}

export function useFiltersWithQS(): UseFiltersWithQueryResult {
const navigate = useNavigate();
const useQsState = useQsStateCreator({
commit: navigate
});
export function useFiltersWithQS({
navigate,
push=false
}: {
navigate: any,
push?: boolean,
}): UseFiltersWithQueryResult {

let navCommit = navigate;

if (push) {
navCommit = ({ search }) => navigate.push(`?${search}`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a potential to make it even more flexible if we just let the instance to pass this whole thing as navigate props. ex. Replace this line: https://github.com/developmentseed/next-veda-ui/pull/3/files#diff-6578b281e50705562cdf8ba73c73ae2bb1df366e18e91e9595106b09cfbf3f89R14

 const controlVars = useFiltersWithQS({navigate: ({ search }) => router.push(`?${search}`)});

then let's say if the instance wants to replace the url instead of push, it can handle it on its level. (and no additional push props is needed) What do you think?

Copy link
Collaborator Author

@sandrahoang686 sandrahoang686 Sep 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that also makes sense but I think we should work on closing out the PR if this is not blocking we can address this in the routing ticket / make note of this. Is that fine with you?

}

const useQsState = useQsStateCreator({
commit: navCommit
});

const [search, setSearch] = useQsState.memo(
{
Expand Down
10 changes: 6 additions & 4 deletions app/scripts/components/common/catalog/filters-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ interface FiltersMenuProps {
exclusiveSourceSelected?: string | null;
customTopOffset?: number;
openByDefault?: boolean;
pathname?: string;
}

export default function FiltersControl(props: FiltersMenuProps) {
Expand All @@ -46,12 +47,13 @@ export default function FiltersControl(props: FiltersMenuProps) {
// has a different header reference as opposed to what the useSlidingStickyHeader hook
// uses as a reference (the main page header). To avoid changing the reference IDs in the
// main logic of the sliding sticky header hook, we provide this custom top offset for more control.
customTopOffset = 0
customTopOffset = 0,
pathname,
} = props;

const controlsRef = useRef<HTMLDivElement>(null);
const [controlsHeight, setControlsHeight] = useState<number>(0);
const { isHeaderHidden, wrapperHeight } = useSlidingStickyHeader();
const { isHeaderHidden, wrapperHeight } = useSlidingStickyHeader(pathname);

const handleChanges = useCallback((item: OptionItem, action: 'add' | 'remove') => {
const isSelected = allSelected.some(selected => selected.id === item.id && selected.taxonomy === item.taxonomy);
Expand Down Expand Up @@ -95,9 +97,9 @@ export default function FiltersControl(props: FiltersMenuProps) {
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [exclusiveSourceSelected]);

return (
<ControlsWrapper widthValue={width} heightValue={controlsHeight+'px'} topValue={isHeaderHidden ? '0px': `${wrapperHeight - customTopOffset}px`}>
<ControlsWrapper widthValue={width} heightValue={controlsHeight+'px'} topValue={isHeaderHidden && wrapperHeight ? '0px': `${wrapperHeight - customTopOffset}px`}>
<div ref={controlsRef}>
<SearchField
size='large'
Expand Down
18 changes: 15 additions & 3 deletions app/scripts/components/common/catalog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import styled from 'styled-components';
import { themeVal } from '@devseed-ui/theme-provider';
import { LinkProperties } from '../card';
import CatalogContent from './catalog-content';
import { useFiltersWithQS } from './controls/hooks/use-filters-with-query';
import { DatasetData } from '$types/veda';
import {
useSlidingStickyHeaderProps
Expand All @@ -14,7 +14,6 @@ import {
FoldTitle
} from '$components/common/fold';
import { variableGlsp } from '$styles/variable-utils';

/**
* CATALOG Feature component
* Allows you to browse through datasets and layers using the filters sidebar control
Expand All @@ -38,15 +37,26 @@ export const sortOptions = [{ id: 'name', name: 'Name' }];

export interface CatalogViewProps {
datasets: DatasetData[];
onFilterChanges: () => {
search: string,
taxonomies: Record<string, string[]> | Record<string, never>,
onAction: () => void,
} | any;
linkProperties: LinkProperties;
pathname: string;
}

function CatalogView({
datasets,
onFilterChanges,
pathname,
linkProperties,
}: CatalogViewProps) {

const { headerHeight } = useSlidingStickyHeaderProps();
const { search, taxonomies , onAction } = useFiltersWithQS();

const { search, taxonomies , onAction } = onFilterChanges();

return (
<CatalogWrapper>
<CatalogFoldHeader
Expand All @@ -63,6 +73,8 @@ function CatalogView({
search={search}
taxonomies={taxonomies}
onAction={onAction}
pathname={pathname}
linkProperties={linkProperties}
/>
</CatalogWrapper>
);
Expand Down
18 changes: 9 additions & 9 deletions app/scripts/components/common/element-interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@ import React, { useCallback, useState } from 'react';
import T from 'prop-types';
import styled from 'styled-components';

const InteractiveLink = styled.a`
position: absolute;
inset: 0;
z-index: -1;
pointer-events: auto;
font-size: 0;
margin: 0;
`;

export const Wrapper = styled.div`
position: relative;
z-index: 1;
Expand All @@ -20,6 +11,15 @@ export const Wrapper = styled.div`
}
`;

const InteractiveLink = styled.a`
position: absolute;
inset: 0;
z-index: -1;
pointer-events: auto;
font-size: 0;
margin: 0;
`;

/**
* The ElementInteractive allows you to create a link with actions "inside" it.
*
Expand Down
9 changes: 6 additions & 3 deletions app/scripts/components/common/featured-slider-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import React from 'react';
import styled from 'styled-components';
import { DatasetData, StoryData, datasets, stories, getString } from 'veda';
import { VerticalDivider } from '@devseed-ui/toolbar';

import SmartLink from './smart-link';
import PublishedDate from './pub-date';
import { CardSourcesList } from './card-sources';
import { DatasetClassification } from './dataset-classification';

import { Card } from '$components/common/card';
import { CardMeta, CardTopicsList } from '$components/common/card/styles';
import { FoldGrid, FoldHeader, FoldTitle } from '$components/common/fold';
Expand Down Expand Up @@ -108,7 +107,11 @@ function FeaturedSliderSection(props: FeaturedSliderSectionProps) {
}}
cardType='featured'
linkLabel='View more'
linkTo={d.asLink?.url ?? getItemPath(d)}
linkProperties={{
linkTo: `${d.asLink?.url ?? getItemPath(d)}`,
pathAttributeKeyName: 'to',
LinkElement: SmartLink
}}
title={d.name}
overline={
<CardMeta>
Expand Down
Loading
Loading