diff --git a/CHANGELOG-unified-datasets-attribution.md b/CHANGELOG-unified-datasets-attribution.md new file mode 100644 index 0000000000..cbc1beb8ae --- /dev/null +++ b/CHANGELOG-unified-datasets-attribution.md @@ -0,0 +1 @@ +- Remove "Contact" section and add Attribution table with contributors for EPICs and Lab Processed datasets. \ No newline at end of file diff --git a/context/app/static/js/components/detailPage/Attribution/Attribution.tsx b/context/app/static/js/components/detailPage/Attribution/Attribution.tsx index f89afaa3de..3fa5c44085 100644 --- a/context/app/static/js/components/detailPage/Attribution/Attribution.tsx +++ b/context/app/static/js/components/detailPage/Attribution/Attribution.tsx @@ -16,7 +16,7 @@ const tooltips = { contact: 'This is the contact for this data.', }; -const DatasetAttribution = ( +export const DatasetAttributionDescription = ( Below is the information for the individuals who provided this dataset. For questions about this dataset, reach out to the individuals listed as contacts, either via the email address listed in the table or via contact information @@ -44,7 +44,7 @@ function Attribution({ children }: PropsWithChildren) { return ( - {isDataset && DatasetAttribution} + {isDataset && DatasetAttributionDescription} {sections.map((props) => ( diff --git a/context/app/static/js/components/detailPage/ProcessedData/HelperPanel/HelperPanel.tsx b/context/app/static/js/components/detailPage/ProcessedData/HelperPanel/HelperPanel.tsx index c5167951d3..e3f2198cae 100644 --- a/context/app/static/js/components/detailPage/ProcessedData/HelperPanel/HelperPanel.tsx +++ b/context/app/static/js/components/detailPage/ProcessedData/HelperPanel/HelperPanel.tsx @@ -86,7 +86,7 @@ function HelperPanelBody() { )} {currentDataset.pipeline} - {currentDataset.group_name} + {currentDataset.group_name} {date && formatDate(date, 'yyyy-MM-dd')} ); diff --git a/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/ProcessedDataset.tsx b/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/ProcessedDataset.tsx index bbeea4210a..757fdce06d 100644 --- a/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/ProcessedDataset.tsx +++ b/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/ProcessedDataset.tsx @@ -1,36 +1,43 @@ import React, { useState } from 'react'; -import LabelledSectionText from 'js/shared-styles/sections/LabelledSectionText'; import { formatDate } from 'date-fns/format'; -import { Tabs, Tab, TabPanel } from 'js/shared-styles/tabs'; + import FactCheckRounded from '@mui/icons-material/FactCheckRounded'; import SummarizeRounded from '@mui/icons-material/SummarizeRounded'; +import AttributionRoundedIcon from '@mui/icons-material/AttributionRounded'; import InsertDriveFileRounded from '@mui/icons-material/InsertDriveFileRounded'; +import Skeleton from '@mui/material/Skeleton'; +import Stack from '@mui/material/Stack'; + +import LabelledSectionText from 'js/shared-styles/sections/LabelledSectionText'; +import { Tabs, Tab, TabPanel } from 'js/shared-styles/tabs'; import { VisualizationIcon } from 'js/shared-styles/icons'; import { useVitessceConf } from 'js/pages/Dataset/hooks'; import { isSupport } from 'js/components/types'; import { useFlaskDataContext } from 'js/components/Contexts'; -import Skeleton from '@mui/material/Skeleton'; import ContactUsLink from 'js/shared-styles/Links/ContactUsLink'; -import Files from '../../files/Files'; -import DataProducts from '../../files/DataProducts'; -import VisualizationWrapper from '../../visualization/VisualizationWrapper'; -import AnalysisDetails from '../../AnalysisDetails'; -import Protocol from '../../Protocol'; +import ContributorsTable from 'js/components/detailPage/ContributorsTable'; +import { DatasetAttributionDescription } from 'js/components/detailPage/Attribution/Attribution'; +import Files from 'js/components/detailPage/files/Files'; +import DataProducts from 'js/components/detailPage/files/DataProducts'; +import VisualizationWrapper from 'js/components/detailPage/visualization/VisualizationWrapper'; +import AnalysisDetails from 'js/components/detailPage/AnalysisDetails'; +import Protocol from 'js/components/detailPage/Protocol'; +import { getDateLabelAndValue } from 'js/components/detailPage/utils'; +import { useSelectedVersionStore } from 'js/components/detailPage/VersionSelect/SelectedVersionStore'; +import { useVersions } from 'js/components/detailPage/VersionSelect/hooks'; +import { useTrackEntityPageEvent } from 'js/components/detailPage/useTrackEntityPageEvent'; + import { DatasetTitle } from './DatasetTitle'; import { ProcessedDatasetAccordion } from './ProcessedDatasetAccordion'; import { Subsection } from './Subsection'; import { SectionDescription } from './SectionDescription'; import useProcessedDataStore from '../store'; -import { getDateLabelAndValue } from '../../utils'; import { ProcessedDatasetContextProvider, useProcessedDatasetContext, ProcessedDataVisualizationProps, } from './ProcessedDatasetContext'; -import { useSelectedVersionStore } from '../../VersionSelect/SelectedVersionStore'; import { useProcessedDatasetDetails } from './hooks'; -import { useVersions } from '../../VersionSelect/hooks'; -import { useTrackEntityPageEvent } from '../../useTrackEntityPageEvent'; import { OldVersionAlert } from './OldVersionAlert'; function ProcessedDatasetDescription() { @@ -47,12 +54,13 @@ function ProcessedDatasetDescription() { function Contact() { const { - dataset: { mapped_consortium }, + dataset: { creation_action }, } = useProcessedDatasetContext(); - if (mapped_consortium !== 'HuBMAP') { + if (creation_action !== 'Central Process') { return null; } + return ( HuBMAP Help Desk @@ -65,12 +73,15 @@ function SummaryAccordion() { const [dateLabel, dateValue] = getDateLabelAndValue(dataset); return ( }> - - {dataset.group_name} - - - {dateValue ? formatDate(new Date(dateValue), 'yyyy-MM-dd') : 'N/A'} - + + + {dataset.group_name} + {dataset.mapped_consortium} + + + {dateValue ? formatDate(new Date(dateValue), 'yyyy-MM-dd') : 'N/A'} + + ); } @@ -182,6 +193,23 @@ function AnalysisDetailsAccordion() { ); } +function AttributionAccordion() { + const { + dataset: { creation_action, contributors, contacts }, + } = useProcessedDatasetContext(); + + if (creation_action === 'Central Process' || !contributors?.length) { + return null; + } + + return ( + }> + {DatasetAttributionDescription} + + + ); +} + export default function ProcessedDataset({ sectionDataset }: ProcessedDataVisualizationProps) { const selectedDatasetVersionUUID = useSelectedVersionStore((state) => state.selectedVersions.get(sectionDataset.uuid))?.uuid ?? sectionDataset.uuid; @@ -213,6 +241,7 @@ export default function ProcessedDataset({ sectionDataset }: ProcessedDataVisual + ); diff --git a/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/hooks.ts b/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/hooks.ts index 161ec0fde8..611742108e 100644 --- a/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/hooks.ts +++ b/context/app/static/js/components/detailPage/ProcessedData/ProcessedDataset/hooks.ts @@ -21,7 +21,6 @@ export type ProcessedDatasetDetails = ProcessedDatasetInfo & | 'metadata' | 'protocol_url' // TODO: This is present for non-dataset entities, but not for datasets. | 'dataset_type' - | 'creation_action' | 'mapped_consortium' >; @@ -53,6 +52,8 @@ export function useProcessedDatasetDetails(uuid: string) { 'dataset_type', 'creation_action', 'mapped_consortium', + 'contributors', + 'contacts', ], size: 10000, }; diff --git a/context/app/static/js/components/detailPage/ProcessedData/hooks.spec.ts b/context/app/static/js/components/detailPage/ProcessedData/hooks.spec.ts index cf7cf29c45..73044052ed 100644 --- a/context/app/static/js/components/detailPage/ProcessedData/hooks.spec.ts +++ b/context/app/static/js/components/detailPage/ProcessedData/hooks.spec.ts @@ -1,7 +1,24 @@ +import { CreationAction } from 'js/components/types'; import { renderHook } from 'test-utils/functions'; import { useSortedSearchHits, createdByCentralProcess, datasetIsPublished } from './hooks'; -const testDatasets = [ +const testDatasets: { + _id: string; + _index: string; + _score: number; + _source: { + assay_display_name: string[]; + created_timestamp: number; + creation_action: CreationAction; + entity_type: string; + hubmap_id: string; + pipeline: string; + status: string; + uuid: string; + visualization: boolean; + }; + _type: string; +}[] = [ { _id: 'c1fc38a4a6139a4830b8b2aec7227a8e', _index: 'hm_prod_consortium_portal', diff --git a/context/app/static/js/components/types.ts b/context/app/static/js/components/types.ts index 4d27af84c6..693a4d2fc5 100644 --- a/context/app/static/js/components/types.ts +++ b/context/app/static/js/components/types.ts @@ -84,6 +84,14 @@ export interface Sample extends Entity { origin_samples: Sample[]; } +export type CreationAction = + | 'Create Dataset Activity' + | 'Central Process' + | 'Multi-Assay Split' + | 'Lab Process' + | 'Create Publication Activity' + | 'External Process'; + export interface Dataset extends Entity { entity_type: 'Dataset'; processing: 'raw' | 'processed'; @@ -93,6 +101,7 @@ export interface Dataset extends Entity { assay_modality: 'single' | 'multiple'; donor: Donor; mapped_data_access_level: 'Public' | 'Protected' | 'Consortium'; + creation_action: CreationAction; origin_samples: Sample[]; origin_samples_unique_mapped_organs: string[]; mapped_data_types: string[]; diff --git a/context/app/static/js/pages/Dataset/hooks.ts b/context/app/static/js/pages/Dataset/hooks.ts index 0544abc856..9fc0ed1a7f 100644 --- a/context/app/static/js/pages/Dataset/hooks.ts +++ b/context/app/static/js/pages/Dataset/hooks.ts @@ -55,6 +55,8 @@ export type ProcessedDatasetInfo = Pick< | 'dbgap_sra_experiment_url' | 'is_component' | 'visualization' + | 'contributors' + | 'contacts' >; type VitessceConf = object | undefined; @@ -106,6 +108,7 @@ function useProcessedDatasets(includeComponents?: boolean) { 'dbgap_sra_experiment_url', 'is_component', 'visualization', + 'contributors', ], size: 10000, }; @@ -128,13 +131,14 @@ function getProcessedDatasetSection({ hit: Required>; conf?: VitessceConf; }) { - const { pipeline, hubmap_id, files, metadata, visualization } = hit._source; + const { pipeline, hubmap_id, files, metadata, visualization, creation_action, contributors } = hit._source; const shouldDisplaySection = { summary: true, visualization: visualization || Boolean(conf && 'data' in conf && conf?.data), - files: Boolean(files), + files: Boolean(files?.length), analysis: Boolean(metadata?.dag_provenance_list), + attribution: creation_action !== 'Central Process' && Boolean(contributors?.length), }; const sectionsToDisplay = Object.entries(shouldDisplaySection).filter(([_k, v]) => v === true);