Skip to content

Commit ff78cc3

Browse files
committed
wip: Fixed ui for copy to metadata
1 parent f3a02eb commit ff78cc3

File tree

3 files changed

+152
-55
lines changed

3 files changed

+152
-55
lines changed

src/renderer/src/components/pages/MicroscopyImageMetadataFormPage/index.jsx

+132-41
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ const MicroscopyImageMetadataFormPage = () => {
4545
imageHasRequiredMetadata,
4646
copyImageMetadata,
4747
imageMetadataCopyFilterValue,
48-
setImageMetadataCopyFilterValue,
4948
} = useGlobalStore();
5049

5150
const [selectedCopyToImages, setSelectedCopyToImages] = useState([]);
51+
const [selectedCopyToFolders, setSelectedCopyToFolders] = useState([]);
5252
const [openFolders, setOpenFolders] = useState({});
5353

5454
const naturalSort = (a, b) =>
@@ -72,29 +72,26 @@ const MicroscopyImageMetadataFormPage = () => {
7272
}
7373
});
7474

75+
console.log("imageObject", imageObject);
7576
return imageObject;
7677
};
7778

7879
const microscopyImageFileNamesWithoutSelectedImage = confirmedMicroscopyImages.filter(
7980
(imageObj) => imageObj.filePath !== selectedImageFileObj?.filePath
8081
);
8182

82-
const filteredCopyToImages = microscopyImageFileNamesWithoutSelectedImage.filter((imageObj) =>
83-
imageObj.filePath.toLowerCase().includes(imageMetadataCopyFilterValue.toLowerCase())
84-
);
85-
86-
const allFilteredImagesSelected = filteredCopyToImages.length === selectedCopyToImages.length;
87-
88-
const handleToggleAllImages = () => {
89-
setSelectedCopyToImages(allFilteredImagesSelected ? [] : filteredCopyToImages);
90-
};
91-
92-
const handleImageSelection = (imageObj, isSelectedToBeCopiedTo) => {
93-
setSelectedCopyToImages((prevSelected) =>
94-
isSelectedToBeCopiedTo
95-
? prevSelected.filter((image) => image.filePath !== imageObj.filePath)
96-
: [...prevSelected, imageObj]
83+
const handleCopyToFileClick = (imageObj) => {
84+
const imageIsSelectedToBeCopiedTo = selectedCopyToImages.some(
85+
(image) => image.filePath === imageObj.filePath
9786
);
87+
88+
if (imageIsSelectedToBeCopiedTo) {
89+
setSelectedCopyToImages((prevSelected) =>
90+
prevSelected.filter((image) => image.filePath !== imageObj.filePath)
91+
);
92+
} else {
93+
setSelectedCopyToImages((prevSelected) => [...prevSelected, imageObj]);
94+
}
9895
};
9996

10097
const handleCopyMetadataFromImageButtonClick = () => {
@@ -121,6 +118,38 @@ const MicroscopyImageMetadataFormPage = () => {
121118
}));
122119
};
123120

121+
const handleSelectCopyToFolderClick = (event, folderName) => {
122+
event.stopPropagation();
123+
124+
const folderNameWasSelected = selectedCopyToFolders.includes(folderName);
125+
const imagesInFolder = microscopyImageObject[folderName];
126+
127+
if (folderNameWasSelected) {
128+
// Unselect the folder and all its files
129+
setSelectedCopyToFolders((prevSelected) =>
130+
prevSelected.filter((folder) => folder !== folderName)
131+
);
132+
setSelectedCopyToImages((prevSelected) =>
133+
prevSelected.filter(
134+
(image) =>
135+
!imagesInFolder.some((imageInFolder) => imageInFolder.filePath === image.filePath)
136+
)
137+
);
138+
} else {
139+
// Select the folder and all its files
140+
setSelectedCopyToFolders((prevSelected) => [...prevSelected, folderName]);
141+
setSelectedCopyToImages((prevSelected) => [
142+
...prevSelected,
143+
...imagesInFolder.filter(
144+
(imageInFolder) =>
145+
!prevSelected.some((image) => image.filePath === imageInFolder.filePath)
146+
),
147+
]);
148+
}
149+
};
150+
151+
const folderIsSelectedToBeCopiedTo = (folderName) => selectedCopyToFolders.includes(folderName);
152+
124153
const microscopyImageObject = createMicroscopyImageObject();
125154

126155
return (
@@ -135,32 +164,97 @@ const MicroscopyImageMetadataFormPage = () => {
135164
<GuidedModeSection bordered>
136165
{copyImageMetadataModeActive ? (
137166
<Stack>
138-
<NavigationButton
139-
buttonText="Cancel metadata copy"
140-
navIcon="left-arrow"
141-
buttonOnClick={handleCancelCopyImageMetadataButtonClick}
142-
/>
167+
<Flex justify="center" align="center" gap="md">
168+
<NavigationButton
169+
buttonText="Cancel metadata copy"
170+
navIcon="left-arrow"
171+
buttonOnClick={handleCancelCopyImageMetadataButtonClick}
172+
/>
173+
<Button color="cyan" onClick={handleCopyImageMetadataButtonClick} style={{ flex: 1 }}>
174+
Copy metadata to selected images
175+
</Button>
176+
</Flex>
143177
<Center mt="md">
144178
<Title order={2}>
145179
Select images to copy metadata from "{selectedImageFileObj?.fileName}" to
146180
</Title>
147181
</Center>
148-
<Flex align="flex-end" gap="md">
149-
<Button className={styles.toggleButton} onClick={handleToggleAllImages}>
150-
{allFilteredImagesSelected
151-
? `Deselect ${imageMetadataCopyFilterValue === "" ? "all" : "filtered"}`
152-
: `Select ${imageMetadataCopyFilterValue === "" ? "all" : "filtered"}`}
153-
</Button>
154-
<TextInput
155-
placeholder="Filter images using a file name or file path"
156-
value={imageMetadataCopyFilterValue}
157-
style={{ flexGrow: 1 }}
158-
onChange={(event) => setImageMetadataCopyFilterValue(event.target.value)}
159-
rightSection={<IconSearch size={20} />}
160-
/>
161-
</Flex>
182+
162183
<ScrollArea h={300} type="always">
163-
<Table miw={800} verticalSpacing="sm" withTableBorder highlightOnHover>
184+
<Stack gap="xs">
185+
{Object.keys(microscopyImageObject).map((folderKey) => (
186+
<Stack gap="2px" key={folderKey}>
187+
<Group
188+
m="0px"
189+
onClick={() => handleToggleFolder(folderKey)}
190+
style={{ cursor: "pointer" }}
191+
>
192+
<Checkbox
193+
checked={folderIsSelectedToBeCopiedTo(folderKey)}
194+
onClick={(e) => handleSelectCopyToFolderClick(e, folderKey)}
195+
readOnly
196+
/>
197+
{openFolders[folderKey] ? (
198+
<IconFolderOpen size={24} />
199+
) : (
200+
<IconFolder size={24} />
201+
)}
202+
<Text size="sm">{folderKey}</Text>
203+
{openFolders[folderKey] ? (
204+
<IconChevronDown size={24} />
205+
) : (
206+
<IconChevronRight size={24} />
207+
)}
208+
</Group>
209+
{openFolders[folderKey] &&
210+
microscopyImageObject[folderKey].map((fileObj) => {
211+
const isSelectedToBeCopiedTo = selectedCopyToImages.some(
212+
(image) => image.filePath === fileObj.filePath
213+
);
214+
return (
215+
<Tooltip
216+
openDelay={500}
217+
key={fileObj.filePath}
218+
label={
219+
<Stack gap="xs">
220+
<Text size="sm" mb="0px">
221+
Local file path:
222+
</Text>
223+
<Text size="xs" mt="-8px">
224+
{fileObj.filePath}
225+
</Text>
226+
<Text size="sm" mb="-7px" mt="4px">
227+
Location in dataset:
228+
</Text>
229+
{fileObj.relativeDatasetStructurePaths.map((path) => (
230+
<Text key={path} size="xs">
231+
{path}
232+
</Text>
233+
))}
234+
</Stack>
235+
}
236+
>
237+
<Button
238+
variant="subtle"
239+
justify="flex-start"
240+
size="compact-sm"
241+
className={
242+
fileObj.filePath === selectedImageFileObj?.filePath
243+
? styles.selectedImageInSidebar
244+
: ""
245+
}
246+
leftSection={<Checkbox checked={isSelectedToBeCopiedTo} readOnly />}
247+
onClick={() => handleCopyToFileClick(fileObj)}
248+
>
249+
<Text size="sm">{fileObj.fileName}</Text>
250+
</Button>
251+
</Tooltip>
252+
);
253+
})}
254+
</Stack>
255+
))}
256+
</Stack>
257+
{/*<Table miw={800} verticalSpacing="sm" withTableBorder highlightOnHover>
164258
<Table.Thead>
165259
<Table.Tr>
166260
<Table.Th></Table.Th>
@@ -176,7 +270,7 @@ const MicroscopyImageMetadataFormPage = () => {
176270
return (
177271
<Table.Tr
178272
key={imageObj.filePath}
179-
onClick={() => handleImageSelection(imageObj, isSelectedToBeCopiedTo)}
273+
onClick={() => handleCopyToFileClick(imageObj, isSelectedToBeCopiedTo)}
180274
>
181275
<Table.Td>
182276
<Checkbox checked={isSelectedToBeCopiedTo} readOnly />
@@ -187,11 +281,8 @@ const MicroscopyImageMetadataFormPage = () => {
187281
);
188282
})}
189283
</Table.Tbody>
190-
</Table>
284+
</Table>*/}
191285
</ScrollArea>
192-
<Button color="cyan" onClick={handleCopyImageMetadataButtonClick}>
193-
Copy metadata to selected images
194-
</Button>
195286
</Stack>
196287
) : (
197288
<Grid gutter="xl">

src/renderer/src/scripts/guided-mode/guided-curate-dataset.js

+13-6
Original file line numberDiff line numberDiff line change
@@ -14025,6 +14025,8 @@ $(".guided--radio-button").on("click", async function () {
1402514025
const selectedButton = $(this);
1402614026
const notSelectedButton = $(this).siblings(".guided--radio-button");
1402714027

14028+
let disableNonSelectedButtonHiding = false;
14029+
1402814030
if (selectedButton.data("requires-work-before-action") === true) {
1402914031
const buttonId = selectedButton.attr("id");
1403014032
if (buttonId === "guided-button-dataset-does-not-contain-code") {
@@ -14100,20 +14102,25 @@ $(".guided--radio-button").on("click", async function () {
1410014102
document
1410114103
.getElementById("guided-section-ask-if-dataset-contains-code")
1410214104
.classList.remove("hidden");
14105+
disableNonSelectedButtonHiding = true;
1410314106
}
1410414107
}
1410514108
}
1410614109

1410714110
notSelectedButton.removeClass("selected");
1410814111
notSelectedButton.addClass("not-selected basic");
1410914112

14113+
console.log("disableNonSelectedButtonHiding", disableNonSelectedButtonHiding);
14114+
1411014115
//Hide all child containers of non-selected buttons
14111-
notSelectedButton.each(function () {
14112-
if ($(this).data("next-element")) {
14113-
window.nextQuestionID = $(this).data("next-element");
14114-
$(`#${window.nextQuestionID}`).addClass("hidden");
14115-
}
14116-
});
14116+
if (!disableNonSelectedButtonHiding) {
14117+
notSelectedButton.each(function () {
14118+
if ($(this).data("next-element")) {
14119+
window.nextQuestionID = $(this).data("next-element");
14120+
$(`#${window.nextQuestionID}`).addClass("hidden");
14121+
}
14122+
});
14123+
}
1411714124

1411814125
//If button has prevent-radio-handler data attribute, other buttons, will be deselected
1411914126
//but all other radio button functions will be halted

src/renderer/src/sections/guided_mode/guided_curate_dataset.html

+7-8
Original file line numberDiff line numberDiff line change
@@ -798,14 +798,13 @@ <h1 class="text-sub-step-title">Describe the content of your dataset</h1>
798798
No
799799
</button>
800800
</div>
801-
</div>
802-
803-
<div
804-
data-component-type="microfileplus-installation-check-display"
805-
class="guided--section"
806-
id="guided-section-microfileplus-installation-check-display"
807-
>
808-
asdf
801+
<div
802+
data-component-type="microfileplus-installation-check-display"
803+
class="guided--section"
804+
id="guided-section-microfileplus-installation-check-display"
805+
>
806+
asdf
807+
</div>
809808
</div>
810809

811810
<div class="guided--section" id="guided-section-ask-if-dataset-contains-code">

0 commit comments

Comments
 (0)