Skip to content

Commit 1fce986

Browse files
committed
converted remaining manual kb fetches
1 parent 08cefa6 commit 1fce986

File tree

6 files changed

+343
-220
lines changed

6 files changed

+343
-220
lines changed

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
} from '@/hooks/kb/use-knowledge-base-tag-definitions'
2626
import { useNextAvailableSlot } from '@/hooks/kb/use-next-available-slot'
2727
import { type TagDefinitionInput, useTagDefinitions } from '@/hooks/kb/use-tag-definitions'
28+
import { useUpdateDocumentTags } from '@/hooks/queries/knowledge'
2829

2930
const logger = createLogger('DocumentTagsModal')
3031

@@ -58,8 +59,6 @@ function formatValueForDisplay(value: string, fieldType: string): string {
5859
try {
5960
const date = new Date(value)
6061
if (Number.isNaN(date.getTime())) return value
61-
// For UTC dates, display the UTC date to prevent timezone shifts
62-
// e.g., 2002-05-16T00:00:00.000Z should show as "May 16, 2002" not "May 15, 2002"
6362
if (typeof value === 'string' && (value.endsWith('Z') || /[+-]\d{2}:\d{2}$/.test(value))) {
6463
return new Date(
6564
date.getUTCFullYear(),
@@ -96,6 +95,7 @@ export function DocumentTagsModal({
9695
const documentTagHook = useTagDefinitions(knowledgeBaseId, documentId)
9796
const kbTagHook = useKnowledgeBaseTagDefinitions(knowledgeBaseId)
9897
const { getNextAvailableSlot: getServerNextSlot } = useNextAvailableSlot(knowledgeBaseId)
98+
const { mutateAsync: updateDocumentTags } = useUpdateDocumentTags()
9999

100100
const { saveTagDefinitions, tagDefinitions, fetchTagDefinitions } = documentTagHook
101101
const { tagDefinitions: kbTagDefinitions, fetchTagDefinitions: refreshTagDefinitions } = kbTagHook
@@ -118,7 +118,6 @@ export function DocumentTagsModal({
118118
const definition = definitions.find((def) => def.tagSlot === slot)
119119

120120
if (rawValue !== null && rawValue !== undefined && definition) {
121-
// Convert value to string for storage
122121
const stringValue = String(rawValue).trim()
123122
if (stringValue) {
124123
tags.push({
@@ -142,41 +141,34 @@ export function DocumentTagsModal({
142141
async (tagsToSave: DocumentTag[]) => {
143142
if (!documentData) return
144143

145-
try {
146-
const tagData: Record<string, string> = {}
147-
148-
// Only include tags that have values (omit empty ones)
149-
// Use empty string for slots that should be cleared
150-
ALL_TAG_SLOTS.forEach((slot) => {
151-
const tag = tagsToSave.find((t) => t.slot === slot)
152-
if (tag?.value.trim()) {
153-
tagData[slot] = tag.value.trim()
154-
} else {
155-
// Use empty string to clear a tag (API schema expects string, not null)
156-
tagData[slot] = ''
157-
}
158-
})
159-
160-
const response = await fetch(`/api/knowledge/${knowledgeBaseId}/documents/${documentId}`, {
161-
method: 'PUT',
162-
headers: {
163-
'Content-Type': 'application/json',
164-
},
165-
body: JSON.stringify(tagData),
166-
})
167-
168-
if (!response.ok) {
169-
throw new Error('Failed to update document tags')
144+
const tagData: Record<string, string> = {}
145+
146+
ALL_TAG_SLOTS.forEach((slot) => {
147+
const tag = tagsToSave.find((t) => t.slot === slot)
148+
if (tag?.value.trim()) {
149+
tagData[slot] = tag.value.trim()
150+
} else {
151+
tagData[slot] = ''
170152
}
153+
})
171154

172-
onDocumentUpdate?.(tagData as Record<string, string>)
173-
await fetchTagDefinitions()
174-
} catch (error) {
175-
logger.error('Error updating document tags:', error)
176-
throw error
177-
}
155+
await updateDocumentTags({
156+
knowledgeBaseId,
157+
documentId,
158+
tags: tagData,
159+
})
160+
161+
onDocumentUpdate?.(tagData)
162+
await fetchTagDefinitions()
178163
},
179-
[documentData, knowledgeBaseId, documentId, fetchTagDefinitions, onDocumentUpdate]
164+
[
165+
documentData,
166+
knowledgeBaseId,
167+
documentId,
168+
updateDocumentTags,
169+
fetchTagDefinitions,
170+
onDocumentUpdate,
171+
]
180172
)
181173

182174
const handleRemoveTag = async (index: number) => {

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/base-tags-modal/base-tags-modal.tsx

Lines changed: 20 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import {
2222
type TagDefinition,
2323
useKnowledgeBaseTagDefinitions,
2424
} from '@/hooks/kb/use-knowledge-base-tag-definitions'
25+
import { useCreateTagDefinition, useDeleteTagDefinition } from '@/hooks/queries/knowledge'
2526

2627
const logger = createLogger('BaseTagsModal')
2728

28-
/** Field type display labels */
2929
const FIELD_TYPE_LABELS: Record<string, string> = {
3030
text: 'Text',
3131
number: 'Number',
@@ -45,7 +45,6 @@ interface DocumentListProps {
4545
totalCount: number
4646
}
4747

48-
/** Displays a list of documents affected by tag operations */
4948
function DocumentList({ documents, totalCount }: DocumentListProps) {
5049
const displayLimit = 5
5150
const hasMore = totalCount > displayLimit
@@ -95,13 +94,14 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
9594
const { tagDefinitions: kbTagDefinitions, fetchTagDefinitions: refreshTagDefinitions } =
9695
useKnowledgeBaseTagDefinitions(knowledgeBaseId)
9796

97+
const createTagMutation = useCreateTagDefinition()
98+
const deleteTagMutation = useDeleteTagDefinition()
99+
98100
const [deleteTagDialogOpen, setDeleteTagDialogOpen] = useState(false)
99101
const [selectedTag, setSelectedTag] = useState<TagDefinition | null>(null)
100102
const [viewDocumentsDialogOpen, setViewDocumentsDialogOpen] = useState(false)
101-
const [isDeletingTag, setIsDeletingTag] = useState(false)
102103
const [tagUsageData, setTagUsageData] = useState<TagUsageData[]>([])
103104
const [isCreatingTag, setIsCreatingTag] = useState(false)
104-
const [isSavingTag, setIsSavingTag] = useState(false)
105105
const [createTagForm, setCreateTagForm] = useState({
106106
displayName: '',
107107
fieldType: 'text',
@@ -177,27 +177,24 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
177177
}
178178

179179
const tagNameConflict =
180-
isCreatingTag && !isSavingTag && hasTagNameConflict(createTagForm.displayName)
180+
isCreatingTag && !createTagMutation.isPending && hasTagNameConflict(createTagForm.displayName)
181181

182182
const canSaveTag = () => {
183183
return createTagForm.displayName.trim() && !hasTagNameConflict(createTagForm.displayName)
184184
}
185185

186-
/** Get slot usage counts per field type */
187186
const getSlotUsageByFieldType = (fieldType: string): { used: number; max: number } => {
188187
const config = TAG_SLOT_CONFIG[fieldType as keyof typeof TAG_SLOT_CONFIG]
189188
if (!config) return { used: 0, max: 0 }
190189
const used = kbTagDefinitions.filter((def) => def.fieldType === fieldType).length
191190
return { used, max: config.maxSlots }
192191
}
193192

194-
/** Check if a field type has available slots */
195193
const hasAvailableSlots = (fieldType: string): boolean => {
196194
const { used, max } = getSlotUsageByFieldType(fieldType)
197195
return used < max
198196
}
199197

200-
/** Field type options for Combobox */
201198
const fieldTypeOptions: ComboboxOption[] = useMemo(() => {
202199
return SUPPORTED_FIELD_TYPES.filter((type) => hasAvailableSlots(type)).map((type) => {
203200
const { used, max } = getSlotUsageByFieldType(type)
@@ -211,43 +208,17 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
211208
const saveTagDefinition = async () => {
212209
if (!canSaveTag()) return
213210

214-
setIsSavingTag(true)
215211
try {
216-
// Check if selected field type has available slots
217212
if (!hasAvailableSlots(createTagForm.fieldType)) {
218213
throw new Error(`No available slots for ${createTagForm.fieldType} type`)
219214
}
220215

221-
// Get the next available slot from the API
222-
const slotResponse = await fetch(
223-
`/api/knowledge/${knowledgeBaseId}/next-available-slot?fieldType=${createTagForm.fieldType}`
224-
)
225-
if (!slotResponse.ok) {
226-
throw new Error('Failed to get available slot')
227-
}
228-
const slotResult = await slotResponse.json()
229-
if (!slotResult.success || !slotResult.data?.nextAvailableSlot) {
230-
throw new Error('No available tag slots for this field type')
231-
}
232-
233-
const newTagDefinition = {
234-
tagSlot: slotResult.data.nextAvailableSlot,
216+
await createTagMutation.mutateAsync({
217+
knowledgeBaseId,
235218
displayName: createTagForm.displayName.trim(),
236219
fieldType: createTagForm.fieldType,
237-
}
238-
239-
const response = await fetch(`/api/knowledge/${knowledgeBaseId}/tag-definitions`, {
240-
method: 'POST',
241-
headers: {
242-
'Content-Type': 'application/json',
243-
},
244-
body: JSON.stringify(newTagDefinition),
245220
})
246221

247-
if (!response.ok) {
248-
throw new Error('Failed to create tag definition')
249-
}
250-
251222
await Promise.all([refreshTagDefinitions(), fetchTagUsage()])
252223

253224
setCreateTagForm({
@@ -257,36 +228,24 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
257228
setIsCreatingTag(false)
258229
} catch (error) {
259230
logger.error('Error creating tag definition:', error)
260-
} finally {
261-
setIsSavingTag(false)
262231
}
263232
}
264233

265234
const confirmDeleteTag = async () => {
266235
if (!selectedTag) return
267236

268-
setIsDeletingTag(true)
269237
try {
270-
const response = await fetch(
271-
`/api/knowledge/${knowledgeBaseId}/tag-definitions/${selectedTag.id}`,
272-
{
273-
method: 'DELETE',
274-
}
275-
)
276-
277-
if (!response.ok) {
278-
const errorText = await response.text()
279-
throw new Error(`Failed to delete tag definition: ${response.status} ${errorText}`)
280-
}
238+
await deleteTagMutation.mutateAsync({
239+
knowledgeBaseId,
240+
tagDefinitionId: selectedTag.id,
241+
})
281242

282243
await Promise.all([refreshTagDefinitions(), fetchTagUsage()])
283244

284245
setDeleteTagDialogOpen(false)
285246
setSelectedTag(null)
286247
} catch (error) {
287248
logger.error('Error deleting tag definition:', error)
288-
} finally {
289-
setIsDeletingTag(false)
290249
}
291250
}
292251

@@ -433,11 +392,11 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
433392
className='flex-1'
434393
disabled={
435394
!canSaveTag() ||
436-
isSavingTag ||
395+
createTagMutation.isPending ||
437396
!hasAvailableSlots(createTagForm.fieldType)
438397
}
439398
>
440-
{isSavingTag ? 'Creating...' : 'Create Tag'}
399+
{createTagMutation.isPending ? 'Creating...' : 'Create Tag'}
441400
</Button>
442401
</div>
443402
</div>
@@ -481,13 +440,17 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
481440
<ModalFooter>
482441
<Button
483442
variant='default'
484-
disabled={isDeletingTag}
443+
disabled={deleteTagMutation.isPending}
485444
onClick={() => setDeleteTagDialogOpen(false)}
486445
>
487446
Cancel
488447
</Button>
489-
<Button variant='destructive' onClick={confirmDeleteTag} disabled={isDeletingTag}>
490-
{isDeletingTag ? <>Deleting...</> : 'Delete Tag'}
448+
<Button
449+
variant='destructive'
450+
onClick={confirmDeleteTag}
451+
disabled={deleteTagMutation.isPending}
452+
>
453+
{deleteTagMutation.isPending ? 'Deleting...' : 'Delete Tag'}
491454
</Button>
492455
</ModalFooter>
493456
</ModalContent>

0 commit comments

Comments
 (0)