Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7826979
Make images responsive in grid view DM
nick-skriabin May 28, 2025
b0958d8
Grid view settings
nick-skriabin May 30, 2025
ccbeb0d
Fix image max height
nick-skriabin May 30, 2025
61cd390
Grouping same-type fields, cover text-only use case
nick-skriabin May 30, 2025
ad30190
Fix calculation
nick-skriabin May 30, 2025
cf64e52
Fix cell height for text-only case
nick-skriabin May 30, 2025
e789034
Look of the button
nick-skriabin May 30, 2025
c75df4f
fix stuff, remove fit toggle in no-image scenario, min 1 image
May 30, 2025
d6b0023
Add tests
May 31, 2025
bf89efb
Tests
nick-skriabin Jun 2, 2025
4f09f78
Cleanup test
nick-skriabin Jun 2, 2025
9401976
UI fine tuning
nick-skriabin Jun 2, 2025
db93f52
Apply pre-commit linters
yyassi-heartex Jun 2, 2025
1f9b59f
Merge branch 'develop' into 'fb-bros-62/dm-grid-images'
hlomzik Jun 2, 2025
26945dc
Update grid UI
nick-skriabin Jun 2, 2025
b7f9841
Merge branch 'develop' into fb-bros-62/dm-grid-images
nick-skriabin Jun 2, 2025
70ccc48
Update web/libs/datamanager/src/components/MainView/GridView/GridView…
nick-skriabin Jun 2, 2025
ac73777
Update web/libs/datamanager/src/components/DataManager/Toolbar/Toolba…
nick-skriabin Jun 2, 2025
fc12b15
Merge branch 'develop' into fb-bros-62/dm-grid-images
nick-skriabin Jun 2, 2025
ab64707
Rename constant to properly reflect the purpose
nick-skriabin Jun 2, 2025
ccd329e
Use header height as constant
nick-skriabin Jun 2, 2025
91102f1
Use `cnm` to properly merge TW classes
nick-skriabin Jun 2, 2025
8aa8a94
Update web/libs/datamanager/src/sdk/dm-sdk.js
nick-skriabin Jun 2, 2025
6150a51
Add `useCallback`
nick-skriabin Jun 2, 2025
5de8eb3
Grid size coefficient constant
nick-skriabin Jun 2, 2025
6bdd96b
Merge branch 'develop' into 'fb-bros-62/dm-grid-images'
nick-skriabin Jun 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { isDefined } from "../../../utils/utils";
import "./Button.scss";

export const Button = forwardRef(
({ children, type, extra, className, href, size, waiting, icon, tag, look, ...rest }, ref) => {
({ children, type, extra, className, href, size, waiting, icon, tag, look, rawClassName, ...rest }, ref) => {
const finalTag = (tag ?? href) ? "a" : "button";

const mods = {
Expand Down Expand Up @@ -38,6 +38,7 @@ export const Button = forwardRef(
mod={mods}
className={className?.toString()}
type={type}
rawClassName={rawClassName}
{...rest}
>
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,7 @@
display: flex;

&:not(.button-group-dm_collapsed) {
.button-dm+.button-dm {
margin-left: 16px;
}
gap: var(--spacing-tight)
}

&_collapsed {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ import { getRoot } from "mobx-state-tree";
import { AnnotationPreview } from "../Common/AnnotationPreview/AnnotationPreview";
import { Block } from "../../utils/bem";

export const IMAGE_SIZE_COEFFICIENT = 8;

export const ImageDataGroup = (column) => {
const {
value,
original,
field: { alias },
columnCount,
} = column;
const root = getRoot(original);
const imageHeight = ImageDataGroup.height * Math.max(1, IMAGE_SIZE_COEFFICIENT - columnCount);

return original.total_annotations === 0 || !root.showPreviews ? (
<Block name="grid-image-wrapper">
<img src={value} width="auto" height={ImageDataGroup.height} alt="" />
<img src={value} width="auto" style={{ height: imageHeight }} alt="" />
</Block>
) : (
<AnnotationPreview
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { format, isValid } from "date-fns";
import { dateTimeFormat } from "../CellViews/DateTimeCell";
import clsx from "clsx";

export const valueToString = (value) => {
if (typeof value === "string") return value;
Expand All @@ -15,18 +16,21 @@ export const valueToString = (value) => {
}
};

export const TextDataGroup = ({ value }) => {
export const TextDataGroup = ({ value, hasImage }) => {
const output = valueToString(value);
const style = {
padding: 5,
height: TextDataGroup.height,
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
height: hasImage ? TextDataGroup.height : "auto",
};

return (
<div style={style} title={output}>
<div
style={style}
title={output}
className={clsx("p-tight", {
"text-wrap leading-normal": !hasImage,
"text-nowrap": hasImage,
})}
>
{output}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,77 @@
import { inject } from "mobx-react";
import { useCallback, useState } from "react";
import { IconMinus, IconPlus } from "@humansignal/icons";
import { Button } from "../../Common/Button/Button";
import { Icon } from "../../Common/Icon/Icon";
import { Space } from "../../Common/Space/Space";
import { Dropdown } from "../../Common/Dropdown/DropdownComponent";
import { Toggle } from "../../Common/Form";
import { IconSettings, IconMinus, IconPlus } from "@humansignal/icons";

const injector = inject(({ store }) => {
const view = store?.currentView;

const cols = view.fieldsAsColumns ?? [];
const hasImage = cols.some(({ type }) => type === "Image") ?? false;

return {
view,
isGrid: view.type === "grid",
gridWidth: view?.gridWidth,
responsiveImage: view?.gridResponsiveImage,
hasImage,
};
});

export const GridWidthButton = injector(({ view, gridWidth, size }) => {
export const GridWidthButton = injector(({ view, isGrid, gridWidth, responsiveImage, hasImage, size }) => {
const [width, setWidth] = useState(gridWidth);

const setGridWidth = useCallback(
(width) => {
const newWidth = Math.max(3, Math.min(width, 10));
const newWidth = Math.max(1, Math.min(width, 10));

setWidth(newWidth);
view.setGridWidth(newWidth);
},
[view],
);

return view.type === "grid" ? (
<Space style={{ fontSize: 12 }}>
Columns: {width}
<Button.Group>
<Button
size={size}
icon={<Icon icon={IconMinus} size="12" color="#595959" />}
onClick={() => setGridWidth(width - 1)}
disabled={width === 3}
/>
<Button
size={size}
icon={<Icon icon={IconPlus} size="12" color="#595959" />}
onClick={() => setGridWidth(width + 1)}
disabled={width === 10}
/>
</Button.Group>
</Space>
const handleResponsiveImagesToggle = useCallback((e) => {
view.setGridResponsiveImage(!e.target.checked);
}, []);

return isGrid ? (
<Dropdown.Trigger
content={
<div className="p-tight min-w-wide space-y-base">
<div className="grid grid-cols-[1fr_min-content] gap-base items-center">
<span>Columns: {width}</span>
<Button.Group>
<Button
onClick={() => setGridWidth(width - 1)}
disabled={width === 1}
rawClassName="aspect-square h-6 !p-0"
>
<IconMinus />
</Button>
<Button
onClick={() => setGridWidth(width + 1)}
disabled={width === 10}
rawClassName="aspect-square h-6 !p-0"
>
<IconPlus />
</Button>
</Button.Group>
</div>
{hasImage && (
<div className="grid grid-cols-[1fr_min-content] gap-base items-center">
<span>Fit images to width</span>
<Toggle checked={!responsiveImage} onChange={handleResponsiveImagesToggle} />
</div>
)}
</div>
}
>
<Button size={size}>
<IconSettings />
</Button>
</Dropdown.Trigger>
) : null;
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type GridViewContextType = {
imageField: string | undefined;
currentTaskId: number | null;
setCurrentTaskId: (id: number | null) => void;
hasImage: boolean;
};

type TaskModalProps = GridViewContextType & { view: any; imageField: string };
Expand All @@ -29,6 +30,7 @@ export const GridViewContext = createContext<GridViewContextType>({
imageField: undefined,
currentTaskId: null,
setCurrentTaskId: () => {},
hasImage: false,
});

const TaskModal = observer(({ view, tasks, imageField, currentTaskId, setCurrentTaskId }: TaskModalProps) => {
Expand Down Expand Up @@ -131,6 +133,7 @@ export const GridViewProvider: React.FC<GridViewProviderProps> = ({ children, da
const [currentTaskId, setCurrentTaskId] = useState<number | null>(null);
const modalRef = useRef<{ update: (props: object) => void; close: () => void } | null>(null);
const imageField = fields.find((f) => f.currentType === "Image")?.alias;
const hasImage = fields.some((f) => f.currentType === "Image");

const onClose = useCallback(() => {
modalRef.current = null;
Expand All @@ -152,6 +155,7 @@ export const GridViewProvider: React.FC<GridViewProviderProps> = ({ children, da
imageField={imageField}
currentTaskId={currentTaskId}
setCurrentTaskId={setCurrentTaskId}
hasImage={hasImage}
/>
);

Expand All @@ -172,7 +176,7 @@ export const GridViewProvider: React.FC<GridViewProviderProps> = ({ children, da
useEffect(() => () => modalRef.current?.close(), []);

return (
<GridViewContext.Provider value={{ tasks: data, imageField, currentTaskId, setCurrentTaskId }}>
<GridViewContext.Provider value={{ tasks: data, imageField, currentTaskId, setCurrentTaskId, hasImage }}>
{children}
</GridViewContext.Provider>
);
Expand Down
Loading
Loading