Changed frontend to not reference local storage
This commit is contained in:
parent
633afde224
commit
527bc7f67e
9 changed files with 157 additions and 202 deletions
|
|
@ -12,6 +12,7 @@ import { FILE_CONFIRMATION, FILES_REGEX } from "@/lib/constants";
|
|||
import { useLoadingStore } from "@/stores/loadingStore";
|
||||
import { useGetConversationsQuery } from "../api/queries/useGetConversationsQuery";
|
||||
import { useGetNudgesQuery } from "../api/queries/useGetNudgesQuery";
|
||||
import { useGetSettingsQuery } from "../api/queries/useGetSettingsQuery";
|
||||
import { AssistantMessage } from "./_components/assistant-message";
|
||||
import { ChatInput, type ChatInputHandle } from "./_components/chat-input";
|
||||
import Nudges from "./_components/nudges";
|
||||
|
|
@ -638,27 +639,14 @@ function ChatPage() {
|
|||
};
|
||||
}, [endpoint, setPreviousResponseIds, setLoading]);
|
||||
|
||||
// Check if onboarding is complete by looking at local storage
|
||||
const [isOnboardingComplete, setIsOnboardingComplete] = useState(() => {
|
||||
if (typeof window === "undefined") return false;
|
||||
return localStorage.getItem("onboarding-step") === null;
|
||||
});
|
||||
|
||||
// Listen for storage changes to detect when onboarding completes
|
||||
useEffect(() => {
|
||||
const checkOnboarding = () => {
|
||||
if (typeof window !== "undefined") {
|
||||
setIsOnboardingComplete(
|
||||
localStorage.getItem("onboarding-step") === null,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Check periodically since storage events don't fire in the same tab
|
||||
const interval = setInterval(checkOnboarding, 500);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
// Get settings to check onboarding completion
|
||||
const { data: settings } = useGetSettingsQuery();
|
||||
|
||||
// Check if onboarding is complete (current_step >= 4 means complete)
|
||||
const TOTAL_ONBOARDING_STEPS = 4;
|
||||
const isOnboardingComplete =
|
||||
settings?.onboarding?.current_step !== undefined &&
|
||||
settings.onboarding.current_step >= TOTAL_ONBOARDING_STEPS;
|
||||
|
||||
// Prepare filters for nudges (same as chat)
|
||||
const processedFiltersForNudges = parsedFilterData?.filters
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import {
|
|||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { ONBOARDING_CARD_STEPS_KEY } from "@/lib/constants";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function AnimatedProviderSteps({
|
||||
|
|
@ -18,7 +17,6 @@ export function AnimatedProviderSteps({
|
|||
isCompleted,
|
||||
setCurrentStep,
|
||||
steps,
|
||||
storageKey = ONBOARDING_CARD_STEPS_KEY,
|
||||
processingStartTime,
|
||||
hasError = false,
|
||||
}: {
|
||||
|
|
@ -26,25 +24,19 @@ export function AnimatedProviderSteps({
|
|||
isCompleted: boolean;
|
||||
setCurrentStep: (step: number) => void;
|
||||
steps: string[];
|
||||
storageKey?: string;
|
||||
processingStartTime?: number | null;
|
||||
hasError?: boolean;
|
||||
}) {
|
||||
const [startTime, setStartTime] = useState<number | null>(null);
|
||||
const [elapsedTime, setElapsedTime] = useState<number>(0);
|
||||
|
||||
// Initialize start time from prop or local storage
|
||||
// Initialize start time from prop
|
||||
useEffect(() => {
|
||||
const storedElapsedTime = localStorage.getItem(storageKey);
|
||||
|
||||
if (isCompleted && storedElapsedTime) {
|
||||
// If completed, use stored elapsed time
|
||||
setElapsedTime(parseFloat(storedElapsedTime));
|
||||
} else if (processingStartTime) {
|
||||
if (processingStartTime) {
|
||||
// Use the start time passed from parent (when user clicked Complete)
|
||||
setStartTime(processingStartTime);
|
||||
}
|
||||
}, [storageKey, isCompleted, processingStartTime]);
|
||||
}, [processingStartTime]);
|
||||
|
||||
// Progress through steps
|
||||
useEffect(() => {
|
||||
|
|
@ -56,14 +48,13 @@ export function AnimatedProviderSteps({
|
|||
}
|
||||
}, [currentStep, setCurrentStep, steps, isCompleted]);
|
||||
|
||||
// Calculate and store elapsed time when completed
|
||||
// Calculate elapsed time when completed
|
||||
useEffect(() => {
|
||||
if (isCompleted && startTime) {
|
||||
const elapsed = Date.now() - startTime;
|
||||
setElapsedTime(elapsed);
|
||||
localStorage.setItem(storageKey, elapsed.toString());
|
||||
}
|
||||
}, [isCompleted, startTime, storageKey]);
|
||||
}, [isCompleted, startTime]);
|
||||
|
||||
const isDone = currentStep >= steps.length && !isCompleted && !hasError;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
useOnboardingMutation,
|
||||
} from "@/app/api/mutations/useOnboardingMutation";
|
||||
import { useOnboardingRollbackMutation } from "@/app/api/mutations/useOnboardingRollbackMutation";
|
||||
import { useUpdateOnboardingStateMutation } from "@/app/api/mutations/useUpdateOnboardingStateMutation";
|
||||
import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery";
|
||||
import { useGetTasksQuery } from "@/app/api/queries/useGetTasksQuery";
|
||||
import type { ProviderHealthResponse } from "@/app/api/queries/useProviderHealthQuery";
|
||||
|
|
@ -25,7 +26,6 @@ import {
|
|||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { ONBOARDING_CARD_STEPS_KEY } from "@/lib/constants";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { AnimatedProviderSteps } from "./animated-provider-steps";
|
||||
import { AnthropicOnboarding } from "./anthropic-onboarding";
|
||||
|
|
@ -173,6 +173,8 @@ const OnboardingCard = ({
|
|||
|
||||
// Track which tasks we've already handled to prevent infinite loops
|
||||
const handledFailedTasksRef = useRef<Set<string>>(new Set());
|
||||
|
||||
const updateOnboardingMutation = useUpdateOnboardingStateMutation();
|
||||
|
||||
// Query tasks to track completion
|
||||
const { data: tasks } = useGetTasksQuery({
|
||||
|
|
@ -307,11 +309,12 @@ const OnboardingCard = ({
|
|||
console.log("Onboarding completed successfully", data);
|
||||
|
||||
// Save OpenRAG docs filter ID if sample data was ingested
|
||||
if (data.openrag_docs_filter_id && typeof window !== "undefined") {
|
||||
localStorage.setItem(
|
||||
"onboarding_openrag_docs_filter_id",
|
||||
data.openrag_docs_filter_id
|
||||
);
|
||||
if (data.openrag_docs_filter_id) {
|
||||
// Save to backend
|
||||
updateOnboardingMutation.mutateAsync({
|
||||
openrag_docs_filter_id: data.openrag_docs_filter_id,
|
||||
});
|
||||
|
||||
console.log("Saved OpenRAG docs filter ID:", data.openrag_docs_filter_id);
|
||||
}
|
||||
|
||||
|
|
@ -674,7 +677,6 @@ const OnboardingCard = ({
|
|||
setCurrentStep={setCurrentStep}
|
||||
steps={isEmbedding ? EMBEDDING_STEP_LIST : STEP_LIST}
|
||||
processingStartTime={processingStartTime}
|
||||
storageKey={ONBOARDING_CARD_STEPS_KEY}
|
||||
hasError={!!error}
|
||||
/>
|
||||
</motion.div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { StickToBottom } from "use-stick-to-bottom";
|
||||
import { getFilterById } from "@/app/api/queries/useGetFilterByIdQuery";
|
||||
import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery";
|
||||
import { useUpdateOnboardingStateMutation } from "@/app/api/mutations/useUpdateOnboardingStateMutation";
|
||||
import { AssistantMessage } from "@/app/chat/_components/assistant-message";
|
||||
import Nudges from "@/app/chat/_components/nudges";
|
||||
import { UserMessage } from "@/app/chat/_components/user-message";
|
||||
|
|
@ -10,11 +12,6 @@ import type { Message, SelectedFilters } from "@/app/chat/_types/types";
|
|||
import OnboardingCard from "@/app/onboarding/_components/onboarding-card";
|
||||
import { useChat } from "@/contexts/chat-context";
|
||||
import { useChatStreaming } from "@/hooks/useChatStreaming";
|
||||
import {
|
||||
ONBOARDING_ASSISTANT_MESSAGE_KEY,
|
||||
ONBOARDING_OPENRAG_DOCS_FILTER_ID_KEY,
|
||||
ONBOARDING_SELECTED_NUDGE_KEY,
|
||||
} from "@/lib/constants";
|
||||
|
||||
import { OnboardingStep } from "./onboarding-step";
|
||||
import OnboardingUpload from "./onboarding-upload";
|
||||
|
|
@ -36,43 +33,46 @@ export function OnboardingContent({
|
|||
currentStep: number;
|
||||
}) {
|
||||
const { setConversationFilter, setCurrentConversationId } = useChat();
|
||||
const { data: settings } = useGetSettingsQuery();
|
||||
const updateOnboardingMutation = useUpdateOnboardingStateMutation();
|
||||
const parseFailedRef = useRef(false);
|
||||
const [responseId, setResponseId] = useState<string | null>(null);
|
||||
|
||||
// Initialize from backend settings
|
||||
const [selectedNudge, setSelectedNudge] = useState<string>(() => {
|
||||
// Retrieve selected nudge from localStorage on mount
|
||||
if (typeof window === "undefined") return "";
|
||||
return localStorage.getItem(ONBOARDING_SELECTED_NUDGE_KEY) || "";
|
||||
return settings?.onboarding?.selected_nudge || "";
|
||||
});
|
||||
|
||||
const [assistantMessage, setAssistantMessage] = useState<Message | null>(
|
||||
() => {
|
||||
// Retrieve assistant message from localStorage on mount
|
||||
if (typeof window === "undefined") return null;
|
||||
const savedMessage = localStorage.getItem(
|
||||
ONBOARDING_ASSISTANT_MESSAGE_KEY,
|
||||
);
|
||||
if (savedMessage) {
|
||||
try {
|
||||
const parsed = JSON.parse(savedMessage);
|
||||
// Convert timestamp string back to Date object
|
||||
return {
|
||||
...parsed,
|
||||
timestamp: new Date(parsed.timestamp),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Failed to parse saved assistant message:", error);
|
||||
parseFailedRef.current = true;
|
||||
// Clear corrupted data - will go back a step in useEffect
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.removeItem(ONBOARDING_ASSISTANT_MESSAGE_KEY);
|
||||
localStorage.removeItem(ONBOARDING_SELECTED_NUDGE_KEY);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Get from backend settings
|
||||
if (settings?.onboarding?.assistant_message) {
|
||||
const msg = settings.onboarding.assistant_message;
|
||||
return {
|
||||
role: msg.role as "user" | "assistant",
|
||||
content: msg.content,
|
||||
timestamp: new Date(msg.timestamp),
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
|
||||
// Sync state when settings change
|
||||
useEffect(() => {
|
||||
if (settings?.onboarding?.selected_nudge) {
|
||||
setSelectedNudge(settings.onboarding.selected_nudge);
|
||||
}
|
||||
if (settings?.onboarding?.assistant_message) {
|
||||
const msg = settings.onboarding.assistant_message;
|
||||
setAssistantMessage({
|
||||
role: msg.role as "user" | "assistant",
|
||||
content: msg.content,
|
||||
timestamp: new Date(msg.timestamp),
|
||||
});
|
||||
}
|
||||
}, [settings?.onboarding]);
|
||||
|
||||
// Handle parse errors by going back a step
|
||||
useEffect(() => {
|
||||
if (parseFailedRef.current && currentStep >= 2) {
|
||||
|
|
@ -83,28 +83,23 @@ export function OnboardingContent({
|
|||
const { streamingMessage, isLoading, sendMessage } = useChatStreaming({
|
||||
onComplete: async (message, newResponseId) => {
|
||||
setAssistantMessage(message);
|
||||
// Save assistant message to localStorage when complete
|
||||
if (typeof window !== "undefined") {
|
||||
try {
|
||||
localStorage.setItem(
|
||||
ONBOARDING_ASSISTANT_MESSAGE_KEY,
|
||||
JSON.stringify(message),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Failed to save assistant message to localStorage:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Save assistant message to backend
|
||||
await updateOnboardingMutation.mutateAsync({
|
||||
assistant_message: {
|
||||
role: message.role,
|
||||
content: message.content,
|
||||
timestamp: message.timestamp.toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
if (newResponseId) {
|
||||
setResponseId(newResponseId);
|
||||
|
||||
// Set the current conversation ID
|
||||
setCurrentConversationId(newResponseId);
|
||||
|
||||
// Save the filter association for this conversation
|
||||
const openragDocsFilterId = localStorage.getItem(ONBOARDING_OPENRAG_DOCS_FILTER_ID_KEY);
|
||||
// Get filter ID from backend settings
|
||||
const openragDocsFilterId = settings?.onboarding?.openrag_docs_filter_id;
|
||||
if (openragDocsFilterId) {
|
||||
try {
|
||||
// Load the filter and set it in the context with explicit responseId
|
||||
|
|
@ -136,21 +131,17 @@ export function OnboardingContent({
|
|||
|
||||
const handleNudgeClick = async (nudge: string) => {
|
||||
setSelectedNudge(nudge);
|
||||
// Save selected nudge to localStorage
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem(ONBOARDING_SELECTED_NUDGE_KEY, nudge);
|
||||
}
|
||||
setAssistantMessage(null);
|
||||
// Clear saved assistant message when starting a new conversation
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.removeItem(ONBOARDING_ASSISTANT_MESSAGE_KEY);
|
||||
}
|
||||
|
||||
// Save selected nudge to backend and clear assistant message
|
||||
await updateOnboardingMutation.mutateAsync({
|
||||
selected_nudge: nudge,
|
||||
assistant_message: null,
|
||||
});
|
||||
|
||||
setTimeout(async () => {
|
||||
// Check if we have the OpenRAG docs filter ID (sample data was ingested)
|
||||
const openragDocsFilterId =
|
||||
typeof window !== "undefined"
|
||||
? localStorage.getItem(ONBOARDING_OPENRAG_DOCS_FILTER_ID_KEY)
|
||||
: null;
|
||||
const openragDocsFilterId = settings?.onboarding?.openrag_docs_filter_id;
|
||||
|
||||
// Load and set the OpenRAG docs filter if available
|
||||
let filterToUse = null;
|
||||
|
|
|
|||
|
|
@ -3,14 +3,11 @@ import { AnimatePresence, motion } from "motion/react";
|
|||
import { type ChangeEvent, useEffect, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { useCreateFilter } from "@/app/api/mutations/useCreateFilter";
|
||||
import { useUpdateOnboardingStateMutation } from "@/app/api/mutations/useUpdateOnboardingStateMutation";
|
||||
import { useGetNudgesQuery } from "@/app/api/queries/useGetNudgesQuery";
|
||||
import { useGetTasksQuery } from "@/app/api/queries/useGetTasksQuery";
|
||||
import { AnimatedProviderSteps } from "@/app/onboarding/_components/animated-provider-steps";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
ONBOARDING_UPLOAD_STEPS_KEY,
|
||||
ONBOARDING_USER_DOC_FILTER_ID_KEY,
|
||||
} from "@/lib/constants";
|
||||
import { uploadFile } from "@/lib/upload-utils";
|
||||
|
||||
interface OnboardingUploadProps {
|
||||
|
|
@ -27,6 +24,7 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => {
|
|||
const [isCreatingFilter, setIsCreatingFilter] = useState(false);
|
||||
|
||||
const createFilterMutation = useCreateFilter();
|
||||
const updateOnboardingMutation = useUpdateOnboardingStateMutation();
|
||||
|
||||
const STEP_LIST = [
|
||||
"Uploading your document",
|
||||
|
|
@ -103,12 +101,13 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => {
|
|||
description: `Filter for ${filename}`,
|
||||
queryData: queryData,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.filter?.id && typeof window !== "undefined") {
|
||||
localStorage.setItem(
|
||||
ONBOARDING_USER_DOC_FILTER_ID_KEY,
|
||||
result.filter.id,
|
||||
);
|
||||
.then(async (result) => {
|
||||
if (result.filter?.id) {
|
||||
// Save to backend
|
||||
await updateOnboardingMutation.mutateAsync({
|
||||
user_doc_filter_id: result.filter.id,
|
||||
});
|
||||
|
||||
console.log(
|
||||
"Created knowledge filter for uploaded document",
|
||||
result.filter.id,
|
||||
|
|
@ -267,7 +266,6 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => {
|
|||
setCurrentStep={setCurrentStep}
|
||||
isCompleted={false}
|
||||
steps={STEP_LIST}
|
||||
storageKey={ONBOARDING_UPLOAD_STEPS_KEY}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from "@/app/api/queries/useGetConversationsQuery";
|
||||
import { getFilterById } from "@/app/api/queries/useGetFilterByIdQuery";
|
||||
import type { Settings } from "@/app/api/queries/useGetSettingsQuery";
|
||||
import { useUpdateOnboardingStateMutation } from "@/app/api/mutations/useUpdateOnboardingStateMutation";
|
||||
import { OnboardingContent } from "@/app/onboarding/_components/onboarding-content";
|
||||
import { ProgressBar } from "@/app/onboarding/_components/progress-bar";
|
||||
import { AnimatedConditional } from "@/components/animated-conditional";
|
||||
|
|
@ -19,13 +20,6 @@ import { useChat } from "@/contexts/chat-context";
|
|||
import {
|
||||
ANIMATION_DURATION,
|
||||
HEADER_HEIGHT,
|
||||
ONBOARDING_ASSISTANT_MESSAGE_KEY,
|
||||
ONBOARDING_CARD_STEPS_KEY,
|
||||
ONBOARDING_OPENRAG_DOCS_FILTER_ID_KEY,
|
||||
ONBOARDING_SELECTED_NUDGE_KEY,
|
||||
ONBOARDING_STEP_KEY,
|
||||
ONBOARDING_UPLOAD_STEPS_KEY,
|
||||
ONBOARDING_USER_DOC_FILTER_ID_KEY,
|
||||
SIDEBAR_WIDTH,
|
||||
TOTAL_ONBOARDING_STEPS,
|
||||
} from "@/lib/constants";
|
||||
|
|
@ -50,21 +44,27 @@ export function ChatRenderer({
|
|||
setOnboardingComplete,
|
||||
} = useChat();
|
||||
|
||||
// Initialize onboarding state based on local storage and settings
|
||||
// Initialize onboarding state from backend settings
|
||||
const [currentStep, setCurrentStep] = useState<number>(() => {
|
||||
if (typeof window === "undefined") return 0;
|
||||
const savedStep = localStorage.getItem(ONBOARDING_STEP_KEY);
|
||||
return savedStep !== null ? parseInt(savedStep, 10) : 0;
|
||||
return settings?.onboarding?.current_step ?? 0;
|
||||
});
|
||||
|
||||
const [showLayout, setShowLayout] = useState<boolean>(() => {
|
||||
if (typeof window === "undefined") return false;
|
||||
const savedStep = localStorage.getItem(ONBOARDING_STEP_KEY);
|
||||
// Show layout if settings.edited is true and if no onboarding step is saved
|
||||
const isEdited = settings?.edited ?? true;
|
||||
return isEdited ? savedStep === null : false;
|
||||
// Show layout only if onboarding is complete (current_step >= TOTAL_ONBOARDING_STEPS)
|
||||
// This means onboarding will show even if edited=true, as long as it's not complete
|
||||
const onboardingStep = settings?.onboarding?.current_step ?? 0;
|
||||
return onboardingStep >= TOTAL_ONBOARDING_STEPS;
|
||||
});
|
||||
|
||||
// Update currentStep and showLayout when settings change
|
||||
useEffect(() => {
|
||||
if (settings?.onboarding?.current_step !== undefined) {
|
||||
setCurrentStep(settings.onboarding.current_step);
|
||||
// Update showLayout based on whether onboarding is complete
|
||||
setShowLayout(settings.onboarding.current_step >= TOTAL_ONBOARDING_STEPS);
|
||||
}
|
||||
}, [settings?.onboarding?.current_step]);
|
||||
|
||||
// Only fetch conversations on chat page
|
||||
const isOnChatPage = pathname === "/" || pathname === "/chat";
|
||||
const { data: conversations = [], isLoading: isConversationsLoading } =
|
||||
|
|
@ -108,18 +108,18 @@ export function ChatRenderer({
|
|||
}
|
||||
}
|
||||
|
||||
// Try to get the appropriate filter ID
|
||||
// Try to get the appropriate filter ID from settings
|
||||
let filterId: string | null = null;
|
||||
|
||||
if (preferUserDoc) {
|
||||
// Completed full onboarding - prefer user document filter
|
||||
filterId = localStorage.getItem(ONBOARDING_USER_DOC_FILTER_ID_KEY);
|
||||
filterId = settings?.onboarding?.user_doc_filter_id || null;
|
||||
console.log("[FILTER] User doc filter ID:", filterId);
|
||||
}
|
||||
|
||||
// Fall back to OpenRAG docs filter
|
||||
if (!filterId) {
|
||||
filterId = localStorage.getItem(ONBOARDING_OPENRAG_DOCS_FILTER_ID_KEY);
|
||||
filterId = settings?.onboarding?.openrag_docs_filter_id || null;
|
||||
console.log("[FILTER] OpenRAG docs filter ID:", filterId);
|
||||
}
|
||||
|
||||
|
|
@ -149,25 +149,29 @@ export function ChatRenderer({
|
|||
[setConversationFilter]
|
||||
);
|
||||
|
||||
// Save current step to local storage whenever it changes
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined" && !showLayout) {
|
||||
localStorage.setItem(ONBOARDING_STEP_KEY, currentStep.toString());
|
||||
}
|
||||
}, [currentStep, showLayout]);
|
||||
// Note: Current step is now saved to backend via handleStepComplete
|
||||
// No need to save on every change, only on completion
|
||||
|
||||
const updateOnboardingMutation = useUpdateOnboardingStateMutation();
|
||||
|
||||
const handleStepComplete = async () => {
|
||||
if (currentStep < TOTAL_ONBOARDING_STEPS - 1) {
|
||||
setCurrentStep(currentStep + 1);
|
||||
const nextStep = currentStep + 1;
|
||||
setCurrentStep(nextStep);
|
||||
// Save step to backend
|
||||
await updateOnboardingMutation.mutateAsync({ current_step: nextStep });
|
||||
} else {
|
||||
// Onboarding is complete - remove from local storage and show layout
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.removeItem(ONBOARDING_STEP_KEY);
|
||||
localStorage.removeItem(ONBOARDING_ASSISTANT_MESSAGE_KEY);
|
||||
localStorage.removeItem(ONBOARDING_SELECTED_NUDGE_KEY);
|
||||
localStorage.removeItem(ONBOARDING_CARD_STEPS_KEY);
|
||||
localStorage.removeItem(ONBOARDING_UPLOAD_STEPS_KEY);
|
||||
}
|
||||
// Onboarding is complete - set step to TOTAL_ONBOARDING_STEPS to indicate completion
|
||||
// and clear intermediate state in backend
|
||||
await updateOnboardingMutation.mutateAsync({
|
||||
current_step: TOTAL_ONBOARDING_STEPS,
|
||||
assistant_message: null,
|
||||
selected_nudge: null,
|
||||
card_steps: null,
|
||||
upload_steps: null,
|
||||
openrag_docs_filter_id: null,
|
||||
user_doc_filter_id: null,
|
||||
});
|
||||
|
||||
// Mark onboarding as complete in context
|
||||
setOnboardingComplete(true);
|
||||
|
|
@ -180,36 +184,35 @@ export function ChatRenderer({
|
|||
// This will pick up the default filter we just set
|
||||
await startNewConversation();
|
||||
|
||||
// Clean up onboarding filter IDs now that we've set the default
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.removeItem(ONBOARDING_OPENRAG_DOCS_FILTER_ID_KEY);
|
||||
localStorage.removeItem(ONBOARDING_USER_DOC_FILTER_ID_KEY);
|
||||
console.log("[FILTER] Cleaned up onboarding filter IDs");
|
||||
}
|
||||
|
||||
setShowLayout(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleStepBack = () => {
|
||||
const handleStepBack = async () => {
|
||||
if (currentStep > 0) {
|
||||
setCurrentStep(currentStep - 1);
|
||||
const prevStep = currentStep - 1;
|
||||
setCurrentStep(prevStep);
|
||||
// Save step to backend
|
||||
await updateOnboardingMutation.mutateAsync({ current_step: prevStep });
|
||||
}
|
||||
};
|
||||
|
||||
const handleSkipOnboarding = () => {
|
||||
// Skip onboarding by marking it as complete
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.removeItem(ONBOARDING_STEP_KEY);
|
||||
localStorage.removeItem(ONBOARDING_ASSISTANT_MESSAGE_KEY);
|
||||
localStorage.removeItem(ONBOARDING_SELECTED_NUDGE_KEY);
|
||||
localStorage.removeItem(ONBOARDING_CARD_STEPS_KEY);
|
||||
localStorage.removeItem(ONBOARDING_UPLOAD_STEPS_KEY);
|
||||
}
|
||||
const handleSkipOnboarding = async () => {
|
||||
// Skip onboarding by marking it as complete in backend
|
||||
await updateOnboardingMutation.mutateAsync({
|
||||
current_step: TOTAL_ONBOARDING_STEPS,
|
||||
assistant_message: null,
|
||||
selected_nudge: null,
|
||||
card_steps: null,
|
||||
upload_steps: null,
|
||||
openrag_docs_filter_id: null,
|
||||
user_doc_filter_id: null,
|
||||
});
|
||||
|
||||
// Mark onboarding as complete in context
|
||||
setOnboardingComplete(true);
|
||||
// Store the OpenRAG docs filter as default for new conversations
|
||||
storeDefaultFilterForNewConversations(false);
|
||||
await storeDefaultFilterForNewConversations(false);
|
||||
setShowLayout(true);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import {
|
|||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { ONBOARDING_STEP_KEY } from "@/lib/constants";
|
||||
import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery";
|
||||
|
||||
export type EndpointType = "chat" | "langflow";
|
||||
|
|
@ -129,28 +128,15 @@ export function ChatProvider({ children }: ChatProviderProps) {
|
|||
return false;
|
||||
});
|
||||
|
||||
// Sync onboarding completion state with settings.edited and localStorage
|
||||
// Sync onboarding completion state with settings from backend
|
||||
useEffect(() => {
|
||||
const checkOnboarding = () => {
|
||||
if (typeof window !== "undefined") {
|
||||
// Onboarding is complete if settings.edited is true AND step key is null
|
||||
const stepKeyExists = localStorage.getItem(ONBOARDING_STEP_KEY) !== null;
|
||||
const isEdited = settings?.edited === true;
|
||||
// Complete if edited is true and step key doesn't exist (onboarding flow finished)
|
||||
setIsOnboardingComplete(isEdited && !stepKeyExists);
|
||||
}
|
||||
};
|
||||
|
||||
// Check on mount and when settings change
|
||||
checkOnboarding();
|
||||
|
||||
// Listen for storage events (for cross-tab sync)
|
||||
window.addEventListener("storage", checkOnboarding);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("storage", checkOnboarding);
|
||||
};
|
||||
}, [settings?.edited]);
|
||||
const TOTAL_ONBOARDING_STEPS = 4;
|
||||
// Onboarding is complete if current_step >= 4
|
||||
const isComplete =
|
||||
settings?.onboarding?.current_step !== undefined &&
|
||||
settings.onboarding.current_step >= TOTAL_ONBOARDING_STEPS;
|
||||
setIsOnboardingComplete(isComplete);
|
||||
}, [settings?.onboarding?.current_step]);
|
||||
|
||||
const setOnboardingComplete = useCallback((complete: boolean) => {
|
||||
setIsOnboardingComplete(complete);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import {
|
|||
type TaskFileEntry,
|
||||
useGetTasksQuery,
|
||||
} from "@/app/api/queries/useGetTasksQuery";
|
||||
import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery";
|
||||
import { useAuth } from "@/contexts/auth-context";
|
||||
import { ONBOARDING_STEP_KEY } from "@/lib/constants";
|
||||
|
||||
// Task interface is now imported from useGetTasksQuery
|
||||
export type { Task };
|
||||
|
|
@ -90,11 +90,18 @@ export function TaskProvider({ children }: { children: React.ReactNode }) {
|
|||
},
|
||||
});
|
||||
|
||||
// Get settings to check if onboarding is active
|
||||
const { data: settings } = useGetSettingsQuery();
|
||||
|
||||
// Helper function to check if onboarding is active
|
||||
const isOnboardingActive = useCallback(() => {
|
||||
if (typeof window === "undefined") return false;
|
||||
return localStorage.getItem(ONBOARDING_STEP_KEY) !== null;
|
||||
}, []);
|
||||
const TOTAL_ONBOARDING_STEPS = 4;
|
||||
// Onboarding is active if current_step < 4
|
||||
return (
|
||||
settings?.onboarding?.current_step !== undefined &&
|
||||
settings.onboarding.current_step < TOTAL_ONBOARDING_STEPS
|
||||
);
|
||||
}, [settings?.onboarding?.current_step]);
|
||||
|
||||
const refetchSearch = useCallback(() => {
|
||||
queryClient.invalidateQueries({
|
||||
|
|
|
|||
|
|
@ -37,17 +37,6 @@ export const SIDEBAR_WIDTH = 280;
|
|||
export const HEADER_HEIGHT = 54;
|
||||
export const TOTAL_ONBOARDING_STEPS = 4;
|
||||
|
||||
/**
|
||||
* Local Storage Keys
|
||||
*/
|
||||
export const ONBOARDING_STEP_KEY = "onboarding_current_step";
|
||||
export const ONBOARDING_ASSISTANT_MESSAGE_KEY = "onboarding_assistant_message";
|
||||
export const ONBOARDING_SELECTED_NUDGE_KEY = "onboarding_selected_nudge";
|
||||
export const ONBOARDING_CARD_STEPS_KEY = "onboarding_card_steps";
|
||||
export const ONBOARDING_UPLOAD_STEPS_KEY = "onboarding_upload_steps";
|
||||
export const ONBOARDING_OPENRAG_DOCS_FILTER_ID_KEY = "onboarding_openrag_docs_filter_id";
|
||||
export const ONBOARDING_USER_DOC_FILTER_ID_KEY = "onboarding_user_doc_filter_id";
|
||||
|
||||
export const FILES_REGEX =
|
||||
/(?<=I'm uploading a document called ['"])[^'"]+\.[^.]+(?=['"]\. Here is its content:)/;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue