feat: add custom field type of image

This commit is contained in:
Carlos Valente
2025-02-19 20:29:13 +01:00
committed by Carlos Valente
parent d0b4c6a279
commit 570ff59cfc
18 changed files with 306 additions and 56 deletions
@@ -0,0 +1,23 @@
.imageCell {
position: relative;
min-height: 2rem;
&:hover {
.overlay {
display: grid;
place-content: center;
background-color: $black-60;
}
}
}
.overlay {
position: absolute;
inset: 0;
display: none;
}
.image {
background-color: $gray-1350;
min-height: 2rem;
}
@@ -0,0 +1,55 @@
import { memo } from 'react';
import { Input } from '@chakra-ui/react';
import style from './EditableImage.module.scss';
interface EditableImageProps {
initialValue: string;
updateValue: (newValue: string) => void;
}
export default memo(EditableImage);
function EditableImage(props: EditableImageProps) {
const { initialValue, updateValue } = props;
const handleUpdate = (newValue: string) => {
if (newValue === initialValue) {
return;
}
if (newValue !== '' && !newValue.startsWith('http')) {
return;
}
updateValue(newValue);
};
if (!initialValue) {
return (
<Input
size='sm'
variant='ontime-transparent'
padding={0}
fontSize='md'
placeholder='Paste image URL'
onBlur={(event) => handleUpdate(event.currentTarget.value)}
onKeyDown={(event) => {
if (event.key === 'Enter') {
handleUpdate(event.currentTarget.value);
}
}}
defaultValue={initialValue}
spellCheck={false}
autoComplete='off'
/>
);
}
return (
<div className={style.imageCell}>
<div className={style.overlay}>
<button onClick={() => handleUpdate('')}>Delete</button>
</div>
<img loading='lazy' src={initialValue} className={style.image} />
</div>
);
}
@@ -6,6 +6,7 @@ import { millisToString, removeSeconds } from 'ontime-utils';
import DelayIndicator from '../../../../common/components/delay-indicator/DelayIndicator';
import { formatDuration } from '../../../../common/utils/time';
import EditableImage from './EditableImage';
import MultiLineCell from './MultiLineCell';
import SingleLineCell from './SingleLineCell';
import TimeInput from './TimeInput';
@@ -105,6 +106,24 @@ function MakeMultiLineField({ row, column, table }: CellContext<OntimeRundownEnt
return <MultiLineCell initialValue={initialValue} handleUpdate={update} />;
}
function LazyImage({ row, column, table }: CellContext<OntimeRundownEntry, unknown>) {
const update = useCallback(
(newValue: string) => {
table.options.meta?.handleUpdate(row.index, column.id, newValue, true);
},
// eslint-disable-next-line react-hooks/exhaustive-deps -- we skip table.options.meta since the reference seems unstable
[column.id, row.index],
);
const event = row.original;
if (!isOntimeEvent(event)) {
return null;
}
const initialValue = event.custom[column.id];
return <EditableImage initialValue={initialValue} updateValue={update} />;
}
function MakeSingleLineField({ row, column, table }: CellContext<OntimeRundownEntry, unknown>) {
const update = useCallback(
(newValue: string) => {
@@ -139,7 +158,6 @@ function MakeCustomField({ row, column, table }: CellContext<OntimeRundownEntry,
}
const initialValue = event.custom[column.id] ?? '';
return <MultiLineCell initialValue={initialValue} handleUpdate={update} />;
}
@@ -148,8 +166,8 @@ export function makeCuesheetColumns(customFields: CustomFields): ColumnDef<Ontim
accessorKey: key,
id: key,
header: customFields[key].label,
meta: { colour: customFields[key].colour },
cell: MakeCustomField,
meta: { colour: customFields[key].colour, type: customFields[key].type },
cell: customFields[key].type === 'string' ? MakeCustomField : LazyImage,
size: 250,
minSize: 75,
}));