Skip to content

Commit

Permalink
Merge branch 'main' into john-conroy/replace-searchkit
Browse files Browse the repository at this point in the history
  • Loading branch information
john-conroy committed Oct 18, 2024
2 parents 97372ef + a04e89f commit f105649
Show file tree
Hide file tree
Showing 61 changed files with 787 additions and 550 deletions.
33 changes: 33 additions & 0 deletions context/app/markdown/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
# Changelog

## v1.12.2 - 2024-10-17

- Add access levels to processed dataset helper panels.
- Use relevant access levels when determining whether or not to show workspace buttons on dataset detail pages.
- Add title to changelog page.
- Ensure visualizations for image pyramids use parent UUID to fetch notebooks.
- Restore missing columns to derived entities section.
- Remove Provenance section from donor page in favor of using derived data tables.
- Fix Webkit-specific bugs that caused the entity header to become misaligned.
- Resolve issues of header cutting off the top of detail pages and header shifting off-screen when scrolling.
- Switch to using metadata table with tabs component in the Sample and Donor pages.
- In the metadata sections of Dataset, Sample, and Donor pages, add tabs for any entities in the Provenance section with metadata.
- Update the metadata table component to show unique labels for each tab and to be scrollable when many tabs are present.
- Fix issue of Workspaces button being available for protected datasets in the Visualization section.



## v1.12.1 - 2024-10-10

- Prevent collections without a DOI from being counted on the homepage.
- Avoid page scrolling from using arrow keys on vitessce visualization.
- Prevent malformed provenance graph data from crashing the entire page.
- Improve readability of pipeline list in processed dataset sections.
- Append HuBMAP ID to errored datasets' URL anchors to avoid anchor duplication on dataset pages with multiple failed processing attempts.
- Improve entity header state handling of page resizes.
- Fix push script to correctly check latest minor version date.
- Sort publications by their date of publication.
- Update Unified View redirect toast to be more informative.
- Update group for HIVE-processed datasets to be 'HIVE'.


## v1.12.0 - 2024-10-07

- Fix bug on dataset detail page for workspace dialogs opened in succession for different processed datasets.
Expand Down
6 changes: 5 additions & 1 deletion context/app/routes_browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ def details(type, uuid):
type='dataset',
uuid=supported_entity[0]['uuid'],
_anchor=anchor,
redirected=True))
redirected=True,
redirectedFromId=entity.get('hubmap_id'),
redirectedFromPipeline=entity.get('pipeline')))

if type != actual_type:
return redirect(url_for('routes_browse.details', type=actual_type, uuid=uuid))
Expand All @@ -89,6 +91,8 @@ def details(type, uuid):
**get_default_flask_data(),
'entity': entity,
'redirected': redirected,
'redirectedFromId': request.args.get('redirectedFromId'),
'redirectedFromPipeline': request.args.get('redirectedFromPipeline')
}

if type == 'publication':
Expand Down
2 changes: 2 additions & 0 deletions context/app/static/js/components/Contexts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export interface FlaskDataContextType {
title: string; // preview page title
vis_lifted_uuid?: string;
redirected?: boolean;
redirectedFromId?: string | null;
redirectedFromPipeline?: string | null;
}

export const FlaskDataContext = createContext<FlaskDataContextType>('FlaskDataContext');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ function DetailPageSection({ children, ...rest }: PropsWithChildren<React.HTMLAt
const strippedHash = initialHash.slice(1);
if (strippedHash === rest.id) {
setTimeout(() => {
sectionRef.current?.scrollIntoView({
// Manually scroll to section and account for header offset
const sectionTop = sectionRef.current?.getBoundingClientRect().top ?? 0;
const scrollPosition = window.scrollY + sectionTop - offset;

window.scrollTo({
top: Math.max(scrollPosition, 0),
behavior: 'smooth',
});
}, 1000);
}
}
// We do not want to re-scroll down to the section if the header view changes (aka offset changes)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [initialHash, rest.id]);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,66 +6,14 @@ import { CollapsibleDetailPageSection } from 'js/components/detailPage/DetailPag
import { useTrackEntityPageEvent } from 'js/components/detailPage/useTrackEntityPageEvent';
import { tableToDelimitedString, createDownloadUrl } from 'js/helpers/functions';
import { useMetadataFieldDescriptions } from 'js/hooks/useUBKG';
import { getMetadata, hasMetadata } from 'js/helpers/metadata';
import { ESEntityType, isDataset } from 'js/components/types';
import { useProcessedDatasets } from 'js/pages/Dataset/hooks';
import { entityIconMap } from 'js/shared-styles/icons/entityIconMap';
import { Dataset, Donor, Sample, isDataset } from 'js/components/types';
import withShouldDisplay from 'js/helpers/withShouldDisplay';
import { sectionIconMap } from 'js/shared-styles/icons/sectionIconMap';
import { getTableEntities } from 'js/components/detailPage/MetadataSection/utils';
import { DownloadIcon, StyledWhiteBackgroundIconButton } from '../MetadataTable/style';
import MetadataTabs from '../multi-assay/MultiAssayMetadataTabs';
import { Columns, defaultTSVColumns } from './columns';
import { SectionDescription } from '../ProcessedData/ProcessedDataset/SectionDescription';
import MetadataTable from '../MetadataTable';
import { nodeIcons } from '../DatasetRelationships/nodeTypes';

export function getDescription(
field: string,
metadataFieldDescriptions: Record<string, string> | Record<string, never>,
) {
const [prefix, stem] = field.split('.');
if (!stem) {
return metadataFieldDescriptions?.[field];
}
const description = metadataFieldDescriptions?.[stem];
if (!description) {
return undefined;
}
if (prefix === 'donor') {
return `For the original donor: ${metadataFieldDescriptions?.[stem]}`;
}
if (prefix === 'sample') {
return `For the original sample: ${metadataFieldDescriptions?.[stem]}`;
}
throw new Error(`Unrecognized metadata field prefix: ${prefix}`);
}

export function buildTableData(
tableData: Record<string, string | object | unknown[]>,
metadataFieldDescriptions: Record<string, string> | Record<string, never>,
extraValues: Record<string, string> = {},
) {
return (
Object.entries(tableData)
// Filter out nested objects, like nested "metadata" for Samples...
// but allow arrays. Remember, in JS: typeof [] === 'object'
.filter((entry) => typeof entry[1] !== 'object' || Array.isArray(entry[1]))
// Filter out fields from TSV that aren't really metadata:
.filter((entry) => !['contributors_path', 'antibodies_path', 'version'].includes(entry[0]))
.map((entry) => ({
...extraValues,
key: entry[0],
// eslint-disable-next-line @typescript-eslint/no-base-to-string
value: Array.isArray(entry[1]) ? entry[1].join(', ') : entry[1].toString(),
description: getDescription(entry[0], metadataFieldDescriptions),
}))
);
}

function useTableData(tableData: Record<string, string>) {
const { data: fieldDescriptions } = useMetadataFieldDescriptions();
return buildTableData(tableData, fieldDescriptions);
}
import { Columns, defaultTSVColumns } from './columns';

interface TableRow {
key: string;
Expand Down Expand Up @@ -124,76 +72,25 @@ function MetadataWrapper({ allTableRows, tsvColumns = defaultTSVColumns, childre
);
}

function SingleMetadata({ metadata }: { metadata: Record<string, string> }) {
const tableRows = useTableData(metadata);

return (
<MetadataWrapper allTableRows={tableRows}>
<MetadataTable tableRows={tableRows} />
</MetadataWrapper>
);
}

function getEntityIcon(entity: { entity_type: ESEntityType; is_component?: boolean; processing?: string }) {
if (isDataset(entity)) {
if (entity.is_component) {
return nodeIcons.componentDataset;
}
if (entity.processing === 'processed') {
return nodeIcons.processedDataset;
}
return nodeIcons.primaryDataset;
}
return entityIconMap[entity.entity_type];
}

interface MetadataProps {
metadata?: Record<string, string>;
entities: (Donor | Dataset | Sample)[];
}

function Metadata({ metadata }: MetadataProps) {
const { searchHits: datasetsWithMetadata, isLoading } = useProcessedDatasets(true);
function Metadata({ entities }: MetadataProps) {
const { data: fieldDescriptions } = useMetadataFieldDescriptions();
const {
entity: { uuid },
} = useFlaskDataContext();

const { entity } = useFlaskDataContext();

if (!isDataset(entity)) {
return <SingleMetadata metadata={metadata!} />;
}

if (isLoading || !datasetsWithMetadata) {
return null;
}

const { donor, source_samples } = entity;

const entities = [entity, ...datasetsWithMetadata.map((d) => d._source), ...source_samples, donor]
.filter((e) => hasMetadata({ targetEntityType: e.entity_type, currentEntity: e }))
.map((e) => {
const label = isDataset(e) ? e.assay_display_name : e.entity_type;
return {
uuid: e.uuid,
label,
icon: getEntityIcon(e),
tableRows: buildTableData(
getMetadata({
targetEntityType: e.entity_type,
currentEntity: e,
}),
fieldDescriptions,
{ hubmap_id: e.hubmap_id, label },
),
};
});

const allTableRows = entities.map((d) => d.tableRows).flat();
const tableEntities = getTableEntities({ entities, uuid, fieldDescriptions });
const allTableRows = tableEntities.map((d) => d.tableRows).flat();

return (
<MetadataWrapper
allTableRows={allTableRows}
tsvColumns={[{ id: 'hubmap_id', label: 'HuBMAP ID' }, { id: 'label', label: 'Entity' }, ...defaultTSVColumns]}
>
<MetadataTabs entities={entities} />
<MetadataTabs entities={tableEntities} />
</MetadataWrapper>
);
}
Expand Down

This file was deleted.

Loading

0 comments on commit f105649

Please sign in to comment.