mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-31 19:45:15 +02:00
Merge pull request #1035 from JoeMakuta/fix/derive-has-changes-and-use-functional-setstate
fix : derive has changes and use functional setstate
This commit is contained in:
commit
d836eea554
13 changed files with 46 additions and 52 deletions
|
|
@ -243,7 +243,7 @@ export const MCPConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitting })
|
|||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setShowDetails(!showDetails);
|
||||
setShowDetails(prev => !prev);
|
||||
}}
|
||||
>
|
||||
{showDetails ? (
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ export const ComposioDriveConfig: FC<ConnectorConfigProps> = ({ connector, onCon
|
|||
<div className="space-y-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsFolderTreeOpen(!isFolderTreeOpen)}
|
||||
onClick={() => setIsFolderTreeOpen(prev => !prev)}
|
||||
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-foreground transition-colors w-fit"
|
||||
>
|
||||
Change Selection
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ export const MCPConfig: FC<MCPConfigProps> = ({ connector, onConfigChange, onNam
|
|||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setShowDetails(!showDetails);
|
||||
setShowDetails(prev => !prev);
|
||||
}}
|
||||
>
|
||||
{showDetails ? (
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ export const OneDriveConfig: FC<ConnectorConfigProps> = ({ connector, onConfigCh
|
|||
<div className="space-y-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsFolderTreeOpen(!isFolderTreeOpen)}
|
||||
onClick={() => setIsFolderTreeOpen(prev => !prev)}
|
||||
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-foreground transition-colors w-fit"
|
||||
>
|
||||
Change Selection
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export const WebcrawlerConfig: FC<ConnectorConfigProps> = ({ connector, onConfig
|
|||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setShowApiKey(!showApiKey)}
|
||||
onClick={() => setShowApiKey(prev => !prev)}
|
||||
className="absolute right-1 top-1/2 -translate-y-1/2 h-7 px-2 text-xs text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
{showApiKey ? "Hide" : "Show"}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export const ThinkingStepsDisplay: FC<{ steps: ThinkingStep[]; isThreadRunning?:
|
|||
<div className="rounded-lg">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
onClick={() => setIsOpen(prev => !prev)}
|
||||
className={cn(
|
||||
"flex w-full items-center gap-1.5 text-left text-sm transition-colors",
|
||||
"text-muted-foreground hover:text-foreground"
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
|
|||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
onClick={() => setIsExpanded(prev => !prev)}
|
||||
className="flex w-full items-center gap-3 px-5 py-4 text-left transition-colors hover:bg-muted/50 focus:outline-none focus-visible:outline-none"
|
||||
>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ export function CommentThread({
|
|||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-6 px-2 text-xs text-muted-foreground hover:text-foreground"
|
||||
onClick={() => setIsRepliesExpanded(!isRepliesExpanded)}
|
||||
onClick={() => setIsRepliesExpanded(prev => !prev)}
|
||||
>
|
||||
{isRepliesExpanded ? (
|
||||
<ChevronDown className="mr-1 size-3" />
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ const MobileNav = ({ navItems, isScrolled, scrolledBgClassName }: any) => {
|
|||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(!open)}
|
||||
onClick={() => setOpen(prev => !prev)}
|
||||
className="relative z-50 flex items-center justify-center p-2 -mr-2 rounded-lg hover:bg-gray-100 dark:hover:bg-neutral-800 transition-colors touch-manipulation"
|
||||
aria-label={open ? "Close menu" : "Open menu"}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -37,8 +37,14 @@ export function useSidebarState(defaultCollapsed = false): UseSidebarStateReturn
|
|||
}, []);
|
||||
|
||||
const toggleCollapsed = useCallback(() => {
|
||||
setIsCollapsed(!isCollapsed);
|
||||
}, [isCollapsed, setIsCollapsed]);
|
||||
setIsCollapsedState(prev => {
|
||||
const next = !prev;
|
||||
try {
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${next}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
||||
} catch {}
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Keyboard shortcut: Cmd/Ctrl + \
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -666,27 +666,33 @@ export function OnboardingTour() {
|
|||
}, [targetEl, isActive]);
|
||||
|
||||
const handleNext = useCallback(() => {
|
||||
if (stepIndex < TOUR_STEPS.length - 1) {
|
||||
retryCountRef.current = 0;
|
||||
setShouldAnimate(true);
|
||||
setStepIndex(stepIndex + 1);
|
||||
} else {
|
||||
// Tour completed - save to localStorage
|
||||
if (user?.id) {
|
||||
const tourKey = `surfsense-tour-${user.id}`;
|
||||
localStorage.setItem(tourKey, "true");
|
||||
retryCountRef.current = 0;
|
||||
setShouldAnimate(true);
|
||||
setStepIndex(prev => {
|
||||
if (prev < TOUR_STEPS.length - 1) {
|
||||
return prev + 1;
|
||||
} else {
|
||||
// Tour completed - save to localStorage
|
||||
if (user?.id) {
|
||||
const tourKey = `surfsense-tour-${user.id}`;
|
||||
localStorage.setItem(tourKey, "true");
|
||||
}
|
||||
setIsActive(false);
|
||||
return prev;
|
||||
}
|
||||
setIsActive(false);
|
||||
}
|
||||
}, [stepIndex, user?.id]);
|
||||
});
|
||||
}, [user?.id]);
|
||||
|
||||
const handlePrev = useCallback(() => {
|
||||
if (stepIndex > 0) {
|
||||
retryCountRef.current = 0;
|
||||
setShouldAnimate(true);
|
||||
setStepIndex(stepIndex - 1);
|
||||
}
|
||||
}, [stepIndex]);
|
||||
retryCountRef.current = 0;
|
||||
setShouldAnimate(true);
|
||||
setStepIndex(prev => {
|
||||
if (prev > 0) {
|
||||
return prev - 1;
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleSkip = useCallback(() => {
|
||||
// Tour skipped - save to localStorage
|
||||
|
|
|
|||
|
|
@ -40,26 +40,17 @@ export function GeneralSettingsManager({ searchSpaceId }: GeneralSettingsManager
|
|||
const [name, setName] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [hasChanges, setHasChanges] = useState(false);
|
||||
|
||||
// Initialize state from fetched search space
|
||||
useEffect(() => {
|
||||
if (searchSpace) {
|
||||
setName(searchSpace.name || "");
|
||||
setDescription(searchSpace.description || "");
|
||||
setHasChanges(false);
|
||||
}
|
||||
}, [searchSpace]);
|
||||
|
||||
// Track changes
|
||||
useEffect(() => {
|
||||
if (searchSpace) {
|
||||
const currentName = searchSpace.name || "";
|
||||
const currentDescription = searchSpace.description || "";
|
||||
const changed = currentName !== name || currentDescription !== description;
|
||||
setHasChanges(changed);
|
||||
}
|
||||
}, [searchSpace, name, description]);
|
||||
// Derive hasChanges during render
|
||||
const hasChanges = !!searchSpace && ((searchSpace.name || "") !== name || (searchSpace.description || "") !== description);
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
|
|
@ -73,7 +64,6 @@ export function GeneralSettingsManager({ searchSpaceId }: GeneralSettingsManager
|
|||
},
|
||||
});
|
||||
|
||||
setHasChanges(false);
|
||||
await fetchSearchSpace();
|
||||
} catch (error: any) {
|
||||
console.error("Error saving search space details:", error);
|
||||
|
|
|
|||
|
|
@ -32,24 +32,16 @@ export function PromptConfigManager({ searchSpaceId }: PromptConfigManagerProps)
|
|||
|
||||
const [customInstructions, setCustomInstructions] = useState("");
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [hasChanges, setHasChanges] = useState(false);
|
||||
|
||||
// Initialize state from fetched search space
|
||||
useEffect(() => {
|
||||
if (searchSpace) {
|
||||
setCustomInstructions(searchSpace.qna_custom_instructions || "");
|
||||
setHasChanges(false);
|
||||
}
|
||||
}, [searchSpace]);
|
||||
|
||||
// Track changes
|
||||
useEffect(() => {
|
||||
if (searchSpace) {
|
||||
const currentCustom = searchSpace.qna_custom_instructions || "";
|
||||
const changed = currentCustom !== customInstructions;
|
||||
setHasChanges(changed);
|
||||
}
|
||||
}, [searchSpace, customInstructions]);
|
||||
// Derive hasChanges during render
|
||||
const hasChanges = !!searchSpace && (searchSpace.qna_custom_instructions || "") !== customInstructions;
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
|
|
@ -74,7 +66,7 @@ export function PromptConfigManager({ searchSpaceId }: PromptConfigManagerProps)
|
|||
}
|
||||
|
||||
toast.success("System instructions saved successfully");
|
||||
setHasChanges(false);
|
||||
|
||||
await fetchSearchSpace();
|
||||
} catch (error: any) {
|
||||
console.error("Error saving system instructions:", error);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue