Skip to content

Commit 1074c58

Browse files
committed
adding fnf, fix removing tags, rename modal title
1 parent 0bdf4cc commit 1074c58

1 file changed

Lines changed: 41 additions & 16 deletions

File tree

src/renderer/components/Experiment/TagEditorModal.tsx

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
Box,
33
Button,
44
Chip,
5+
ChipDelete,
56
IconButton,
67
Input,
78
Modal,
@@ -10,8 +11,8 @@ import {
1011
Stack,
1112
Typography,
1213
} from '@mui/joy';
13-
import { PencilIcon, XIcon } from 'lucide-react';
14-
import { useState } from 'react';
14+
import { PencilIcon } from 'lucide-react';
15+
import { useEffect, useState } from 'react';
1516
import * as chatAPI from 'renderer/lib/transformerlab-api-sdk';
1617
import { fetcher } from 'renderer/lib/transformerlab-api-sdk';
1718
import { parseTagInput } from './tagUtils';
@@ -33,19 +34,33 @@ export default function TagEditor({
3334
const [error, setError] = useState<string | null>(null);
3435
const [busy, setBusy] = useState(false);
3536
const [open, setOpen] = useState(false);
37+
const [localTags, setLocalTags] = useState<string[]>(tags);
38+
39+
// Sync local state when parent data refreshes or modal reopens.
40+
useEffect(() => {
41+
setLocalTags(tags);
42+
}, [tags, open]);
3643

3744
const id = experimentId || experimentName;
3845

39-
async function callTagApi(url: string, tagList: string[]) {
46+
async function callTagApi(
47+
url: string,
48+
tagList: string[],
49+
optimistic: string[],
50+
previous: string[],
51+
) {
4052
setBusy(true);
4153
setError(null);
54+
setLocalTags(optimistic);
4255
try {
4356
await fetcher(url, {
4457
method: 'POST',
4558
body: JSON.stringify({ tags: tagList }),
4659
});
47-
await onChanged();
60+
// Fire-and-forget parent refresh so UI stays snappy.
61+
void onChanged();
4862
} catch (e: any) {
63+
setLocalTags(previous);
4964
const detail =
5065
e?.response && typeof e.response === 'object' && 'detail' in e.response
5166
? String(e.response.detail)
@@ -61,12 +76,26 @@ export default function TagEditor({
6176
async function handleAdd() {
6277
const parsed = parseTagInput(draft);
6378
if (parsed.length === 0) return;
64-
await callTagApi(chatAPI.Endpoints.Experiment.TagsAdd(id), parsed);
79+
const previous = localTags;
80+
const merged = Array.from(new Set([...previous, ...parsed]));
6581
setDraft('');
82+
await callTagApi(
83+
chatAPI.Endpoints.Experiment.TagsAdd(id),
84+
parsed,
85+
merged,
86+
previous,
87+
);
6688
}
6789

6890
async function handleRemove(tag: string) {
69-
await callTagApi(chatAPI.Endpoints.Experiment.TagsRemove(id), [tag]);
91+
const previous = localTags;
92+
const next = previous.filter((t) => t !== tag);
93+
await callTagApi(
94+
chatAPI.Endpoints.Experiment.TagsRemove(id),
95+
[tag],
96+
next,
97+
previous,
98+
);
7099
}
71100

72101
return (
@@ -82,29 +111,25 @@ export default function TagEditor({
82111
<Modal open={open} onClose={() => setOpen(false)}>
83112
<ModalDialog sx={{ minWidth: 360 }}>
84113
<ModalClose />
85-
<Typography level="title-md">Edit tags {experimentName}</Typography>
114+
<Typography level="title-md">Edit tags ({experimentName})</Typography>
86115
<Stack spacing={1.5} sx={{ mt: 1 }}>
87116
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>
88-
{tags.length === 0 && (
117+
{localTags.length === 0 && (
89118
<Typography level="body-sm" color="neutral">
90119
No tags yet.
91120
</Typography>
92121
)}
93-
{tags.map((t) => (
122+
{localTags.map((t) => (
94123
<Chip
95124
key={t}
96125
size="sm"
97126
variant="soft"
98127
color="neutral"
99128
endDecorator={
100-
<IconButton
101-
size="sm"
102-
variant="plain"
103-
onClick={() => handleRemove(t)}
129+
<ChipDelete
130+
onDelete={() => handleRemove(t)}
104131
disabled={busy}
105-
>
106-
<XIcon size={10} />
107-
</IconButton>
132+
/>
108133
}
109134
>
110135
{t}

0 commit comments

Comments
 (0)