Skip to content

Commit

Permalink
Merge pull request #248 from bento-platform/feat/experiment-breadcrumbs
Browse files Browse the repository at this point in the history
feat: nav scope title + breadcrumbs
  • Loading branch information
davidlougheed authored Feb 14, 2025
2 parents c707c2f + 8e3890e commit 07b902b
Show file tree
Hide file tree
Showing 30 changed files with 561 additions and 175 deletions.
8 changes: 2 additions & 6 deletions src/js/components/Beacon/BeaconCommon/BeaconQueryFormUi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,8 @@ const BeaconQueryFormUi = ({
const searchButtonText = t(`beacon.${isNetworkQuery ? 'search_network' : 'search_beacon'}`);

return (
<div style={{ paddingBottom: 8, display: 'flex', justifyContent: 'center', width: '100%' }}>
<Card
title={t('Search')}
style={{ borderRadius: '10px', maxWidth: '1200px', width: '100%', ...BOX_SHADOW }}
styles={CARD_STYLES}
>
<div className="container margin-auto" style={{ paddingBottom: 8 }}>
<Card title={t('Search')} style={{ borderRadius: '10px', width: '100%', ...BOX_SHADOW }} styles={CARD_STYLES}>
<p style={{ margin: '-8px 0 8px 0', padding: '0', color: 'grey' }}>{t(uiInstructions)}</p>
<Form form={form} onFinish={handleFinish} layout="vertical" onValuesChange={handleValuesChange}>
<Row gutter={FORM_ROW_GUTTERS}>
Expand Down
8 changes: 8 additions & 0 deletions src/js/components/Beacon/BeaconLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { ComponentProps } from 'react';
import Icon from '@ant-design/icons';
import BeaconSvg from './BeaconSvg';

type CustomIconComponentProps = ComponentProps<typeof Icon>;

const BeaconLogo = (props: Partial<CustomIconComponentProps>) => <Icon component={BeaconSvg} {...props} />;
export default BeaconLogo;
2 changes: 1 addition & 1 deletion src/js/components/Beacon/BeaconNetwork/NetworkBeacons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const NetworkBeacons = () => {
// They could be shown optionally if network is very large (ie could just show only beacons with non-zero responses).
// The response prop may be undefined if the response for the beacon is not yet loaded.
return (
<Row gutter={[8, 8]} style={{ width: '100%', maxWidth: 1200 }}>
<Row gutter={[8, 8]} className="container">
{beacons.map((b) => (
<Col span={24} xl={12} key={b.id}>
<NodeDetails beacon={b} key={b.id} response={beaconResponses[b.id]} />
Expand Down
2 changes: 1 addition & 1 deletion src/js/components/BentoAppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const BentoAppRouter = () => {
}, [dispatch]);

if (isAutoAuthenticating || projectsStatus === RequestStatus.Pending) {
return <Loader />;
return <Loader fullHeight={true} />;
}

return (
Expand Down
21 changes: 19 additions & 2 deletions src/js/components/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import { Row, Col, Spin } from 'antd';
import { Loading3QuartersOutlined } from '@ant-design/icons';

const Loader = () => {
// This could be computed by JavaScript, but that's a waste of resources. Instead, we'll store approximate height.
const APPROX_FOOTER_HEIGHT = 222;

// If we're not in a full-height context (i.e., we're inside a page), remove the height of header + footer + padding
// to give back a (roughly) full-page loading screen.
const CSS_HEIGHT_TO_REMOVE = [
'var(--content-scoped-title-height)',
'var(--content-scoped-title-margin-bottom)',
`${APPROX_FOOTER_HEIGHT}px`,
'2 * var(--content-padding-v)',
'var(--header-height)',
].join(' + ');

const Loader = ({ fullHeight }: { fullHeight?: boolean }) => {
return (
<Row justify="center" align="middle" style={{ height: '100vh' }}>
<Row
justify="center"
align="middle"
style={{ height: fullHeight ? '100vh' : `calc(100vh - (${CSS_HEIGHT_TO_REMOVE})` }}
>
<Col>
<Spin indicator={<Loading3QuartersOutlined style={{ fontSize: 40 }} spin />} />
</Col>
Expand Down
18 changes: 15 additions & 3 deletions src/js/components/Overview/AboutBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,39 @@ import { Card, Divider, Skeleton } from 'antd';

import { BOX_SHADOW } from '@/constants/overviewConstants';
import { useAppSelector } from '@/hooks';
import { useSmallScreen } from '@/hooks/useResponsiveContext';
import { RequestStatus } from '@/types/requests';

const ABOUT_CARD_STYLE: CSSProperties = { width: '100%', maxWidth: '1390px', borderRadius: '11px', ...BOX_SHADOW };
const ABOUT_CARD_STYLE: CSSProperties = { borderRadius: '11px', ...BOX_SHADOW };

const AboutBox = ({ style, bottomDivider }: { style?: CSSProperties; bottomDivider?: boolean }) => {
const { i18n } = useTranslation();

const isSmallScreen = useSmallScreen();

const { status: aboutStatus, about } = useAppSelector((state) => state.content);
const aboutContent = useMemo(() => about[i18n.language].trim(), [about, i18n.language]);

// If about is blank after loading, we don't have anything - so don't render the box.
return aboutStatus === RequestStatus.Fulfilled && !aboutContent ? null : (
<>
<Card style={{ ...ABOUT_CARD_STYLE, ...(style ?? {}) }}>
<Card className="container" style={{ ...ABOUT_CARD_STYLE, ...(style ?? {}) }}>
{aboutStatus === RequestStatus.Idle || aboutStatus === RequestStatus.Pending ? (
<Skeleton title={false} paragraph={{ rows: 2 }} />
) : (
<div className="about-content" dangerouslySetInnerHTML={{ __html: aboutContent }} />
)}
</Card>
{bottomDivider && <Divider style={{ maxWidth: 1310, minWidth: 'auto', margin: '32px auto' }} />}
{bottomDivider && (
<Divider
style={{
// Divider looks a bit nicer when it's always a little narrower than the about box / data catalogue:
maxWidth: 'min(var(--content-max-width) - 32px, 100% - 32px)',
minWidth: 'auto',
margin: `${isSmallScreen ? 16 : 32}px auto`,
}}
/>
)}
</>
);
};
Expand Down
12 changes: 8 additions & 4 deletions src/js/components/Overview/OverviewChartDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import Dataset from '@/components/Provenance/Dataset';
import { useTranslationFn } from '@/hooks';
import { useData, useSearchableFields } from '@/features/data/hooks';
import { useSelectedProject, useSelectedScope } from '@/features/metadata/hooks';
import { useSmallScreen } from '@/hooks/useResponsiveContext';

const MANAGE_CHARTS_BUTTON_STYLE: CSSProperties = { right: '5em', bottom: '1.5em', transform: 'scale(125%)' };
// The 'right' position will be set based on small screen status dynamically
const MANAGE_CHARTS_BUTTON_STYLE: CSSProperties = { bottom: '1.5em', transform: 'scale(125%)' };

const saveToLocalStorage = (sections: Sections) => {
saveValue(LOCALSTORAGE_CHARTS_KEY, convertSequenceAndDisplayData(sections));
Expand All @@ -35,6 +37,8 @@ const OverviewChartDashboard = () => {
const { scope } = useSelectedScope();
const selectedProject = useSelectedProject();

const isSmallScreen = useSmallScreen();

// Lazy-loading hooks means these are called only if OverviewChartDashboard is rendered ---
const { status: overviewDataStatus, sections } = useData();
const searchableFields = useSearchableFields();
Expand All @@ -58,7 +62,7 @@ const OverviewChartDashboard = () => {
return WAITING_STATES.includes(overviewDataStatus) ? (
<Loader />
) : (
<>
<div className="container margin-auto">
<AboutBox />

<Row>
Expand Down Expand Up @@ -99,10 +103,10 @@ const OverviewChartDashboard = () => {
type="primary"
icon={<AppstoreAddOutlined rotate={270} />}
tooltip={t('Manage Charts')}
style={MANAGE_CHARTS_BUTTON_STYLE}
style={{ ...MANAGE_CHARTS_BUTTON_STYLE, right: isSmallScreen ? '1em' : '5em' }}
onClick={onManageChartsOpen}
/>
</>
</div>
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/js/components/Overview/PublicOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const PublicOverview = () => {
// In which case this can be reverted.
return showCatalogue ? (
<>
<AboutBox style={{ maxWidth: 1325, margin: 'auto' }} bottomDivider={true} />
<AboutBox style={{ margin: 'auto' }} bottomDivider={true} />
<Catalogue />
</>
) : (
Expand Down
2 changes: 1 addition & 1 deletion src/js/components/Provenance/Catalogue/CatalogueCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const CatalogueCard = ({ project }: { project: Project }) => {
];

return (
<Card className="container" style={BOX_SHADOW} size={isSmallScreen ? 'small' : 'default'}>
<Card className="container margin-auto" style={BOX_SHADOW} size={isSmallScreen ? 'small' : 'default'}>
<CatalogueCardInner
firstContent={
<Flex vertical={true} gap={8} style={{ height: '100%' }}>
Expand Down
2 changes: 1 addition & 1 deletion src/js/components/Provenance/DatasetProvenance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const DatasetProvenance = ({ dataset, loading }: DatasetProvenanceProps) => {
const metadata = dataset.dats_file;

return (
<div className="container" style={{ paddingBottom: '40px' }}>
<div className="container margin-auto">
<Card
title={<Title level={3}>{t(metadata.title ?? dataset.title)}</Title>}
extra={
Expand Down
6 changes: 3 additions & 3 deletions src/js/components/Provenance/ProvenanceTab.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMemo } from 'react';
import { Row } from 'antd';
import { Flex } from 'antd';

import { useMetadata } from '@/features/metadata/hooks';
import type { Dataset } from '@/types/metadata';
Expand All @@ -23,11 +23,11 @@ const ProvenanceTab = () => {
}, [projects, scope]);

return (
<Row justify="center">
<Flex vertical={true} gap={32} justify="center">
{datasets.map((dataset, i) => (
<DatasetProvenance key={i} dataset={dataset} loading={projectsStatus === RequestStatus.Pending} />
))}
</Row>
</Flex>
);
};

Expand Down
5 changes: 3 additions & 2 deletions src/js/components/Scope/DatasetScopePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { useMemo } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { List, Space, Typography } from 'antd';

import Dataset from '@/components/Provenance/Dataset';
import TruncatedParagraph from '@/components/Util/TruncatedParagraph';
import type { DiscoveryScope } from '@/features/metadata/metadata.store';
import { useTranslationFn } from '@/hooks';
import type { Project } from '@/types/metadata';
import { getCurrentPage, scopeToUrl } from '@/utils/router';
import Dataset from '@/components/Provenance/Dataset';
import { useSelectedScope } from '@/features/metadata/hooks';

type DatasetScopePickerProps = {
Expand Down Expand Up @@ -41,7 +42,7 @@ const DatasetScopePicker = ({ parentProject }: DatasetScopePickerProps) => {
</Typography.Title>
{showSelectProject && <Link to={projectURL}>{t('Select')}</Link>}
</Space>
<Typography.Text>{t(parentProject.description)}</Typography.Text>
<TruncatedParagraph>{t(parentProject.description)}</TruncatedParagraph>
<Space align="baseline" size="large">
<Typography.Title level={5} className="no-margin-top">
{t('Datasets')}
Expand Down
11 changes: 9 additions & 2 deletions src/js/components/Scope/ProjectScopePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const styles: Record<string, CSSProperties> = {
},
};

const ProjectScopePicker = () => {
const ProjectScopePicker = ({ onCancel }: { onCancel: () => void }) => {
const t = useTranslationFn();

const { projects, selectedScope } = useMetadata();
Expand Down Expand Up @@ -47,7 +47,14 @@ const ProjectScopePicker = () => {
tabPosition="left"
activeKey={selectedProject}
onChange={onTabChange}
tabBarExtraContent={<Button onClick={onProjectClear}>{t('Clear')}</Button>}
// If no project is selected, don't have "Clear" since we don't have anything to clear.
tabBarExtraContent={
scopeObj.project ? (
<Button onClick={onProjectClear}>{t('Clear')}</Button>
) : (
<Button onClick={onCancel}>{t('Cancel')}</Button>
)
}
items={tabItems}
style={styles.tabs}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/js/components/Scope/ScopePickerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const ScopePickerModal = ({ isModalOpen, setIsModalOpen }: ScopePickerModalProps
const closeModal = () => setIsModalOpen(false);
return (
<Modal title={t('Select Scope')} open={isModalOpen} onCancel={closeModal} footer={null} width={700}>
<ProjectScopePicker />
<ProjectScopePicker onCancel={closeModal} />
</Modal>
);
};
Expand Down
Loading

0 comments on commit 07b902b

Please sign in to comment.