Skip to content

Commit 8ab09b7

Browse files
committed
dataset virtualization
Signed-off-by: Colorado, Camilo <camilo.colorado@intel.com>
1 parent b48d2f6 commit 8ab09b7

File tree

13 files changed

+151
-189
lines changed

13 files changed

+151
-189
lines changed

application/ui/src/components/virtualizer-grid-layout/grid-media-item/grid-media-item.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
line-height: 0px;
1111
padding: var(--spectrum-global-dimension-size-125);
1212
border-radius: var(--spectrum-global-dimension-size-50);
13+
background-color: var(--spectrum-gray-100);
1314

1415
&:empty {
1516
display: none;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Image } from '@geti-inspect/icons';
2+
import { Flex } from '@geti/ui';
3+
import { clsx } from 'clsx';
4+
5+
import styles from './dataset-item-placeholder.module.scss';
6+
7+
export const DatasetItemPlaceholder = () => {
8+
return (
9+
<Flex justifyContent={'center'} alignItems={'center'} UNSAFE_className={clsx(styles.datasetItemPlaceholder)}>
10+
<Image />
11+
</Flex>
12+
);
13+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.datasetItemPlaceholder {
2+
width: 100%;
3+
height: 100%;
4+
aspect-ratio: auto;
5+
border: 1px dashed var(--spectrum-global-color-gray-700);
6+
background-color: var(--spectrum-global-color-gray-200);
7+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { MediaItem } from '../types';
2+
3+
const PLACEHOLDER_FILENAME = 'placeholder';
4+
5+
export const isPlaceholderItem = (name: string): boolean => {
6+
return name.includes(PLACEHOLDER_FILENAME);
7+
};
8+
9+
export const getPlaceholderItem = (index: number): MediaItem => {
10+
return {
11+
id: `${PLACEHOLDER_FILENAME}-${index}`,
12+
filename: PLACEHOLDER_FILENAME,
13+
project_id: '',
14+
size: 0,
15+
is_anomalous: false,
16+
width: 0,
17+
height: 0,
18+
};
19+
};

application/ui/src/features/inspect/dataset/dataset-item/dataset-item-placeholder.component.tsx

Lines changed: 0 additions & 19 deletions
This file was deleted.

application/ui/src/features/inspect/dataset/dataset-item/dataset-item.component.tsx

Lines changed: 0 additions & 49 deletions
This file was deleted.

application/ui/src/features/inspect/dataset/dataset-item/dataset-item.module.scss

Lines changed: 0 additions & 52 deletions
This file was deleted.

application/ui/src/features/inspect/dataset/dataset-list.component.tsx

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
import { DialogContainer, Flex, Grid, Heading, minmax, repeat } from '@geti/ui';
1+
import { DialogContainer, Flex, Heading, Selection, Size, View } from '@geti/ui';
2+
import { isNil } from 'lodash-es';
23
import isEmpty from 'lodash-es/isEmpty';
34
import { useQueryState } from 'nuqs';
5+
import { MediaThumbnail } from 'src/components/media-thumbnail/media-thumbnail.component';
6+
import { GridMediaItem } from 'src/components/virtualizer-grid-layout/grid-media-item/grid-media-item.component';
7+
import { VirtualizerGridLayout } from 'src/components/virtualizer-grid-layout/virtualizer-grid-layout.component';
48

5-
import { DatasetItemPlaceholder } from './dataset-item/dataset-item-placeholder.component';
6-
import { DatasetItem } from './dataset-item/dataset-item.component';
9+
import { getThumbnailUrl } from '../utils';
10+
import { DatasetItemPlaceholder } from './dataset-item-placeholder/dataset-item-placeholder.component';
11+
import { getPlaceholderItem, isPlaceholderItem } from './dataset-item-placeholder/util';
12+
import { DeleteMediaItem } from './delete-dataset-item/delete-dataset-item.component';
713
import { MediaPreview } from './media-preview/media-preview.component';
814
import { InferenceOpacityProvider } from './media-preview/providers/inference-opacity-provider.component';
915
import { MediaItem } from './types';
@@ -13,6 +19,13 @@ interface DatasetItemProps {
1319
mediaItems: MediaItem[];
1420
}
1521

22+
const layoutOptions = {
23+
maxColumns: 4,
24+
minSpace: new Size(8, 8),
25+
minItemSize: new Size(120, 120),
26+
preserveAspectRatio: true,
27+
};
28+
1629
export const DatasetList = ({ mediaItems }: DatasetItemProps) => {
1730
const [selectedMediaItemId, setSelectedMediaItem] = useQueryState('selectedMediaItem');
1831
//TODO: revisit implementation when dataset loading is paginated
@@ -22,34 +35,53 @@ export const DatasetList = ({ mediaItems }: DatasetItemProps) => {
2235
...mediaItems,
2336
...Array.from({
2437
length: Math.max(0, REQUIRED_NUMBER_OF_NORMAL_IMAGES_TO_TRIGGER_TRAINING - mediaItems.length),
25-
}).map(() => undefined),
38+
}).map((_, index): MediaItem => getPlaceholderItem(index)),
2639
];
2740

41+
const handleSelectionChange = (newKeys: Selection) => {
42+
const updatedSelectedKeys = new Set(newKeys);
43+
const firstKey = updatedSelectedKeys.values().next().value;
44+
const itemId = String(firstKey);
45+
46+
if (!isNil(firstKey) && !isPlaceholderItem(itemId)) {
47+
setSelectedMediaItem(itemId);
48+
}
49+
};
50+
2851
return (
2952
<Flex gap='size-200' direction={'column'} height={'100%'}>
3053
<Heading>Normal images</Heading>
3154

32-
<Grid
33-
flex={1}
34-
gap={'size-100'}
35-
rows={['max-content', '1fr']}
36-
alignContent={'start'}
37-
columns={repeat('auto-fill', minmax('size-1600', '1fr'))}
38-
>
39-
{mediaItemsToRender.map((mediaItem, index) =>
40-
isEmpty(mediaItem) ? (
41-
<DatasetItemPlaceholder key={index} />
42-
) : (
43-
<DatasetItem
44-
key={mediaItem.id}
45-
mediaItem={mediaItem}
46-
isSelected={selectedMediaItem?.id === mediaItem.id}
47-
onClick={() => setSelectedMediaItem(mediaItem?.id ?? null)}
48-
onDeleted={() => selectedMediaItem?.id === mediaItem.id && setSelectedMediaItem(null)}
49-
/>
50-
)
51-
)}
52-
</Grid>
55+
<View width={'100%'} height={'100%'}>
56+
<VirtualizerGridLayout
57+
items={mediaItemsToRender}
58+
ariaLabel='sidebar-items'
59+
selectionMode='single'
60+
layoutOptions={layoutOptions}
61+
onSelectionChange={handleSelectionChange}
62+
contentItem={(mediaItem) =>
63+
mediaItem.filename === 'placeholder' ? (
64+
<DatasetItemPlaceholder />
65+
) : (
66+
<GridMediaItem
67+
contentElement={() => (
68+
<MediaThumbnail
69+
alt={mediaItem.filename}
70+
url={getThumbnailUrl(mediaItem)}
71+
onClick={() => setSelectedMediaItem(mediaItem.id ?? null)}
72+
/>
73+
)}
74+
topRightElement={() => (
75+
<DeleteMediaItem
76+
itemsIds={[String(mediaItem.id)]}
77+
onDeleted={() => setSelectedMediaItem(null)}
78+
/>
79+
)}
80+
/>
81+
)
82+
}
83+
/>
84+
</View>
5385

5486
<DialogContainer onDismiss={() => setSelectedMediaItem(null)}>
5587
{!isEmpty(selectedMediaItem) && (

application/ui/src/features/inspect/dataset/media-preview/sidebar-items/sidebar-items.component.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Selection, Size, View } from '@geti/ui';
2-
import { MediaThumbnail } from 'src/components/media-thumbnail/media-thumbnail.component';
3-
import { GridMediaItem } from 'src/components/virtualizer-grid-layout/grid-media-item/grid-media-item.component';
4-
import { VirtualizerGridLayout } from 'src/components/virtualizer-grid-layout/virtualizer-grid-layout.component';
2+
import { getThumbnailUrl } from 'src/features/inspect/utils';
53

4+
import { GridMediaItem } from '../../../../..//components/virtualizer-grid-layout/grid-media-item/grid-media-item.component';
5+
import { VirtualizerGridLayout } from '../../../../..//components/virtualizer-grid-layout/virtualizer-grid-layout.component';
6+
import { MediaThumbnail } from '../../../../../components/media-thumbnail/media-thumbnail.component';
67
import { MediaItem } from '../../types';
78

89
interface SidebarItemsProps {
@@ -19,9 +20,6 @@ const layoutOptions = {
1920
preserveAspectRatio: true,
2021
};
2122

22-
const getThumbnailUrl = (mediaItem: MediaItem) =>
23-
`/api/projects/${mediaItem.project_id}/images/${mediaItem.id}/thumbnail`;
24-
2523
export const SidebarItems = ({ mediaItems, selectedMediaItem, onSelectedMediaItem }: SidebarItemsProps) => {
2624
const selectedIndex = mediaItems.findIndex((item) => item.id === selectedMediaItem.id);
2725

application/ui/src/features/inspect/toolbar/models-list/models-list.component.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const ModelsList = () => {
3838
key={model.id}
3939
variant='secondary'
4040
onPress={() => handleSelectionChange(String(model.id))}
41+
height={'size-800'}
4142
isPending={patchPipeline.isPending}
4243
isDisabled={patchPipeline.isPending}
4344
UNSAFE_className={clsx(classes.option, { [classes.active]: model.id === selectedModelId })}

0 commit comments

Comments
 (0)