diff --git a/src/renderer/src/components/shared/DatasetContentSelector/index.jsx b/src/renderer/src/components/shared/DatasetContentSelector/index.jsx index c785061ad..1c8562cec 100644 --- a/src/renderer/src/components/shared/DatasetContentSelector/index.jsx +++ b/src/renderer/src/components/shared/DatasetContentSelector/index.jsx @@ -1,4 +1,6 @@ -import { Card, Stack, Text, Group, Tooltip, Checkbox } from "@mantine/core"; +import { useState, useCallback } from "react"; +import { Stack, Text, Group, Tooltip, Checkbox, Collapse, ActionIcon } from "@mantine/core"; +import { IconChevronDown, IconChevronUp } from "@tabler/icons-react"; import FullWidthContainer from "../../containers/FullWidthContainer"; import useGlobalStore from "../../../stores/globalStore"; import { toggleEntitySelection } from "../../../stores/slices/datasetContentSelectorSlice"; @@ -6,142 +8,163 @@ import { toggleEntitySelection } from "../../../stores/slices/datasetContentSele const contentOptionsMap = { subjects: { label: "I collected data from subjects", - description: - "Subjects are individual entities, such as humans, animals, or other biological specimens from which data was collected during the study.", - ml: "0px", + description: "Subjects are humans, animals, or other biological specimens.", + ml: 0, }, samples: { - label: "I collected data from samples", + label: "I collected samples from my subjects", description: - "Samples are biological or physical specimens collected from subjects, such as tissue samples, blood samples, or other biological materials.", + "Samples are biological or physical specimens like tissue or blood taken from subjects", dependsOn: ["subjects"], - ml: "20px", + dependsOnNotSatiatedMessage: "You must indicate that you collected data from subjects first.", + ml: 20, }, sites: { label: "I collected data from multiple distinct physical sites on subjects or samples.", description: "For example, if you collected data from multiple brain regions, different sections of a tissue sample, or distinct parts of an organ.", dependsOn: ["subjects"], - ml: "20px", + dependsOnNotSatiatedMessage: "You must indicate that you collected data from subjects first.", + ml: 20, }, "subject-sites": { - label: "I collected data from distinct physical sites of subjects.", + label: "I collected data from distinct physical sites on subjects.", description: "Select this option if the sites where data was collected correspond to specific locations or regions within the subjects, such as different anatomical regions or organs.", dependsOn: ["subjects", "samples", "sites"], - ml: "40px", + dependsOnNotSatiatedMessage: + "You must indicate that you collected data from subjects, samples, and sites first.", + ml: 40, }, "sample-sites": { - label: "I collected data from distinct physical sites of samples.", + label: "I collected data from distinct physical sites on samples.", description: "Select this option if the sites where data was collected correspond to specific regions within the samples, such as different sections of tissue or other biological materials.", dependsOn: ["subjects", "samples", "sites"], - ml: "40px", + dependsOnNotSatiatedMessage: + "You must indicate that you collected data from subjects, samples, and sites first.", + ml: 40, }, performances: { label: "I collected data from multiple performances of the same protocol.", description: - "Performances refer to the repeated execution of the same protocol or procedure during the study. This can involve tasks or experiments conducted multiple times on the subjects or samples.", + "Select this option if you repeated the same protocol or procedure multiple times (such as running repeated tests or experiments) and collected data from each repetition.", dependsOn: ["subjects"], - ml: "20px", + dependsOnNotSatiatedMessage: "You must indicate that you collected data from subjects first.", + ml: 20, }, "performances-on-subjects": { label: "The protocol performances were run on the subjects.", description: - "Select this option if the protocol performances (such as tasks, tests, or procedures) were conducted on subjects, such as humans or animals, and data was collected during those performances.", + "Choose this if tasks, tests, or procedures were performed directly on subjects (e.g., humans or animals) and data was collected during these sessions.", dependsOn: ["subjects", "samples", "performances"], - ml: "40px", + dependsOnNotSatiatedMessage: + "You must indicate that you collected data from subjects, samples, and performances first.", + ml: 40, }, "performances-on-samples": { label: "The protocol performances were run on the samples.", description: - "Select this option if the protocol performances (such as processing or testing procedures) were conducted on samples, like tissue or biological specimens, and data was collected during those procedures.", + "Choose this if tasks, tests, or procedures were performed directly on samples (e.g., tissues or blood) and data was collected during these sessions.", dependsOn: ["subjects", "samples", "performances"], - ml: "40px", + dependsOnNotSatiatedMessage: + "You must indicate that you collected data from subjects, samples, and performances first.", + ml: 40, }, code: { label: "I used code to generate or analyze the collected data", description: "Code includes scripts, computational models, analysis pipelines, or other software used to generate, process, or analyze the data.", - ml: "0px", + ml: 0, }, }; const DatasetContentSelector = () => { const selectedEntities = useGlobalStore((state) => state.selectedEntities); - const handleEntitySelection = (value) => { - const isSelected = selectedEntities.includes(value); + // State to track which option descriptions are expanded. + const [expanded, setExpanded] = useState({}); + + const toggleExpanded = (key) => { + setExpanded((prev) => ({ ...prev, [key]: !prev[key] })); + }; + + const handleEntitySelection = useCallback( + (value) => { + const isSelected = selectedEntities.includes(value); - if (isSelected) { - Object.keys(contentOptionsMap).forEach((key) => { - if (contentOptionsMap[key].dependsOn?.includes(value) && selectedEntities.includes(key)) { - toggleEntitySelection(key); - } - }); - } + if (isSelected) { + Object.entries(contentOptionsMap).forEach(([key, option]) => { + if (option.dependsOn?.includes(value) && selectedEntities.includes(key)) { + toggleEntitySelection(key); + } + }); + } - toggleEntitySelection(value); + toggleEntitySelection(value); + }, + [selectedEntities] + ); + + const renderOption = (key) => { + const option = contentOptionsMap[key]; + const isDisabled = option.dependsOn?.some((dep) => !selectedEntities.includes(dep)); + const isSelected = selectedEntities.includes(key) && !isDisabled; + + return ( + +
+ + + !isDisabled && handleEntitySelection(key)} + /> + + {option.label} + + + {option.description && ( + + toggleExpanded(key)} + aria-label={expanded[key] ? "Hide details" : "Read more"} + > + {expanded[key] ? : } + + + )} + + {option.description && ( + + + {option.description} + + + )} +
+
+ ); }; return ( - - {Object.keys(contentOptionsMap).map((key) => { - const option = contentOptionsMap[key]; - const isDisabled = option.dependsOn?.some((dep) => !selectedEntities.includes(dep)); - const isSelected = selectedEntities.includes(key) && !isDisabled; - - return ( - contentOptionsMap[dep].label) - .join(" and ")} must be selected first.` - : "" - } - disabled={!isDisabled} - zIndex={2999} - > - !isDisabled && handleEntitySelection(key)} - > - - !isDisabled && handleEntitySelection(key)} - style={{ cursor: isDisabled ? "not-allowed" : "pointer" }} - onClick={(event) => event.stopPropagation()} - /> - - {option.label} - - - {option.description && ( - - {option.description} - - )} - - - ); - })} - + {Object.keys(contentOptionsMap).map((key) => renderOption(key))} ); }; diff --git a/src/renderer/src/scripts/guided-mode/guided-curate-dataset.js b/src/renderer/src/scripts/guided-mode/guided-curate-dataset.js index 8e6b1bab0..d91245da0 100644 --- a/src/renderer/src/scripts/guided-mode/guided-curate-dataset.js +++ b/src/renderer/src/scripts/guided-mode/guided-curate-dataset.js @@ -2661,12 +2661,13 @@ const guidedTransitionToHome = () => { } window.CURRENT_PAGE = undefined; + document.getElementById("guided-header-div").classList.add("hidden"); document.getElementById("guided-footer-div").classList.add("hidden"); }; const guidedSaveProgress = async () => { const guidedProgressFileName = window.sodaJSONObj?.["digital-metadata"]?.["name"]; - //return if guidedProgressFileName is not a strnig greater than 0 + //return if guidedProgressFileName is not a string greater than 0 if ( !guidedProgressFileName || typeof guidedProgressFileName !== "string" || @@ -4638,6 +4639,56 @@ window.openPage = async (targetPageID) => { } if (targetPageID === "guided-unstructured-data-import-tab") { + if (0 === 1) { + const responseObject = await client.get(`manage_datasets/bf_dataset_account`, { + params: { + selected_account: window.defaultBfAccount, + }, + }); + const datasets = responseObject.data.datasets; + console.log("Got datasets", datasets); + + let fieldEntries = []; + for (const field of $("#guided-form-add-a-subject") + .children() + .find(".subjects-form-entry")) { + fieldEntries.push(field.name.toLowerCase()); + } + + const foundIDs = []; + + for (const dataset of datasets) { + try { + const subjectsMetadataResponse = await client.get( + `/prepare_metadata/import_metadata_file`, + { + params: { + selected_account: window.defaultBfAccount, + selected_dataset: dataset.id, + file_type: "subjects.xlsx", + ui_fields: fieldEntries.toString(), + }, + } + ); + const subjectFileRows = subjectsMetadataResponse.data.subject_file_rows; + // Get the first element of each row and add it to a new row + const newRows = []; + for (const row of subjectFileRows) { + newRows.push(row[0]); + } + foundIDs.push({ + dataset: dataset, + rows: newRows, + }); + + console.log("subjectsMetadataResponse", subjectsMetadataResponse); + } catch (error) { + console.error("Error fetching subjects metadata", error); + } + } + console.log("Found IDs", foundIDs); + } + guidedUpdateFolderStructureUI("data/"); } diff --git a/src/renderer/src/sections/guided_mode/guided_curate_dataset.html b/src/renderer/src/sections/guided_mode/guided_curate_dataset.html index a5094398f..8fb6eb01d 100644 --- a/src/renderer/src/sections/guided_mode/guided_curate_dataset.html +++ b/src/renderer/src/sections/guided_mode/guided_curate_dataset.html @@ -1053,7 +1053,8 @@

Describe the content of your dataset

- Select all of the following that apply to the data you collected: + Check the boxes that apply to the data collected or generated during your study in + order to help SODA determine the optimal workflow to organize your dataset.