feat: Add optimistic updates and improve component reliability
- Add optimistic updates for knowledge_type changes in useUpdateKnowledgeItem - Update both detail and summary caches to prevent visual reversion - Refactor KnowledgeCardType to use controlled Radix Select component - Remove manual click-outside detection in favor of Radix onOpenChange - Protect tag editing state from being overwritten by external updates - Ensure user input is preserved during active editing sessions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
53d4bf8804
commit
09bb36f9b6
@ -28,10 +28,12 @@ export const KnowledgeCardTags: React.FC<KnowledgeCardTagsProps> = ({ sourceId,
|
||||
// Determine how many tags to show (2 rows worth, approximately 6-8 tags depending on length)
|
||||
const MAX_TAGS_COLLAPSED = 6;
|
||||
|
||||
// Update local state when props change
|
||||
// Update local state when props change, but only when not editing to avoid overwriting user input
|
||||
useEffect(() => {
|
||||
setEditingTags(tags);
|
||||
}, [tags]);
|
||||
if (!isEditing) {
|
||||
setEditingTags(tags);
|
||||
}
|
||||
}, [tags, isEditing]);
|
||||
|
||||
// Focus input when starting to add a new tag
|
||||
useEffect(() => {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { Briefcase, Terminal } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/primitives";
|
||||
import { cn } from "../../ui/primitives/styles";
|
||||
import { SimpleTooltip } from "../../ui/primitives/tooltip";
|
||||
@ -20,31 +20,8 @@ export const KnowledgeCardType: React.FC<KnowledgeCardTypeProps> = ({
|
||||
knowledgeType,
|
||||
}) => {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const selectRef = useRef<HTMLDivElement>(null);
|
||||
const updateMutation = useUpdateKnowledgeItem();
|
||||
|
||||
// Handle click outside to cancel editing
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (isEditing && selectRef.current && event.target) {
|
||||
const target = event.target as Element;
|
||||
|
||||
// Don't close if clicking on the select component or its dropdown content
|
||||
if (!selectRef.current.contains(target) &&
|
||||
!target.closest('[data-radix-select-content]') &&
|
||||
!target.closest('[data-radix-select-item]') &&
|
||||
!target.closest('[data-radix-popper-content-wrapper]')) {
|
||||
setIsEditing(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (isEditing) {
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||
}
|
||||
}, [isEditing]);
|
||||
|
||||
const isTechnical = knowledgeType === "technical";
|
||||
|
||||
const handleTypeChange = async (newType: "technical" | "business") => {
|
||||
@ -85,11 +62,12 @@ export const KnowledgeCardType: React.FC<KnowledgeCardTypeProps> = ({
|
||||
if (isEditing) {
|
||||
return (
|
||||
<div
|
||||
ref={selectRef}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Select
|
||||
open={isEditing}
|
||||
onOpenChange={(open) => setIsEditing(open)}
|
||||
value={knowledgeType}
|
||||
onValueChange={(value) => handleTypeChange(value as "technical" | "business")}
|
||||
disabled={updateMutation.isPending}
|
||||
|
||||
@ -566,6 +566,13 @@ export function useUpdateKnowledgeItem() {
|
||||
updatedItem.metadata = { ...updatedItem.metadata, tags: newTags };
|
||||
}
|
||||
|
||||
if ('knowledge_type' in updates) {
|
||||
const newType = updates.knowledge_type as string;
|
||||
// Update both top-level knowledge_type and metadata.knowledge_type for consistency
|
||||
updatedItem.knowledge_type = newType as "technical" | "business";
|
||||
updatedItem.metadata = { ...updatedItem.metadata, knowledge_type: newType };
|
||||
}
|
||||
|
||||
queryClient.setQueryData<KnowledgeItem>(knowledgeKeys.detail(sourceId), updatedItem);
|
||||
}
|
||||
|
||||
@ -584,6 +591,12 @@ export function useUpdateKnowledgeItem() {
|
||||
updatedItem.tags = newTags;
|
||||
updatedItem.metadata = { ...updatedItem.metadata, tags: newTags };
|
||||
}
|
||||
if ('knowledge_type' in updates) {
|
||||
const newType = updates.knowledge_type as string;
|
||||
// Update both top-level knowledge_type and metadata.knowledge_type for consistency
|
||||
updatedItem.knowledge_type = newType as "technical" | "business";
|
||||
updatedItem.metadata = { ...updatedItem.metadata, knowledge_type: newType };
|
||||
}
|
||||
return updatedItem;
|
||||
}
|
||||
return item;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user