diff --git a/docs/backend/backend_python/openapi.json b/docs/backend/backend_python/openapi.json index 44eb908b1..a29e7c4f1 100644 --- a/docs/backend/backend_python/openapi.json +++ b/docs/backend/backend_python/openapi.json @@ -1117,9 +1117,14 @@ "in": "query", "required": false, "schema": { - "$ref": "#/components/schemas/InputType", + "allOf": [ + { + "$ref": "#/components/schemas/InputType" + } + ], "description": "Choose input type: 'path' or 'base64'", - "default": "path" + "default": "path", + "title": "Input Type" }, "description": "Choose input type: 'path' or 'base64'" } @@ -2199,7 +2204,6 @@ "metadata": { "anyOf": [ { - "additionalProperties": true, "type": "object" }, { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e1e1ddd5f..ab218ecaf 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14476,20 +14476,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx b/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx index 019dd7f43..6f495d505 100644 --- a/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx +++ b/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { setAvatar, setName, @@ -18,23 +18,35 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { avatars } from '@/constants/avatars'; import { AppFeatures } from '@/components/OnboardingSteps/AppFeatures'; +import { RootState } from '@/app/store'; interface AvatarNameSelectionStepProps { stepIndex: number; totalSteps: number; + currentStepDisplayIndex: number; } export const AvatarSelectionStep: React.FC = ({ stepIndex, totalSteps, + currentStepDisplayIndex, }) => { const dispatch = useDispatch(); - const [name, setLocalName] = useState(''); - const [selectedAvatar, setLocalAvatar] = useState(''); + const [name, setLocalName] = useState(localStorage.getItem('name') || ''); + const [selectedAvatar, setLocalAvatar] = useState( + localStorage.getItem('avatar') || '', + ); + const isEditing = useSelector( + (state: RootState) => state.onboarding.isEditing, + ); useEffect(() => { - if (localStorage.getItem('name') && localStorage.getItem('avatar')) { + if ( + localStorage.getItem('name') && + localStorage.getItem('avatar') && + !isEditing + ) { dispatch(markCompleted(stepIndex)); } }, []); @@ -55,7 +67,11 @@ export const AvatarSelectionStep: React.FC = ({ dispatch(markCompleted(stepIndex)); }; - if (localStorage.getItem('name') && localStorage.getItem('avatar')) { + if ( + localStorage.getItem('name') && + localStorage.getItem('avatar') && + !isEditing + ) { return null; } @@ -65,14 +81,18 @@ export const AvatarSelectionStep: React.FC = ({
- Step {stepIndex + 1} of {totalSteps} + Step {currentStepDisplayIndex + 1} of {totalSteps} + + + {Math.round(((currentStepDisplayIndex + 1) / totalSteps) * 100)}% - {Math.round(((stepIndex + 1) / totalSteps) * 100)}%
diff --git a/frontend/src/components/OnboardingSteps/FolderSetupStep.tsx b/frontend/src/components/OnboardingSteps/FolderSetupStep.tsx index e76c1079a..aa5cb7152 100644 --- a/frontend/src/components/OnboardingSteps/FolderSetupStep.tsx +++ b/frontend/src/components/OnboardingSteps/FolderSetupStep.tsx @@ -9,29 +9,34 @@ import { } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { FolderOpen, X, Folder } from 'lucide-react'; -import { useDispatch } from 'react-redux'; -import { AppDispatch } from '@/app/store'; +import { useDispatch, useSelector } from 'react-redux'; +import { AppDispatch, RootState } from '@/app/store'; import { markCompleted, previousStep } from '@/features/onboardingSlice'; import { AppFeatures } from '@/components/OnboardingSteps/AppFeatures'; import { useFolder } from '@/hooks/useFolder'; import { useEffect, useState } from 'react'; - +import { setIsEditing } from '@/features/onboardingSlice'; interface FolderSetupStepProps { stepIndex: number; totalSteps: number; + currentStepDisplayIndex: number; } export function FolderSetupStep({ stepIndex, totalSteps, + currentStepDisplayIndex, }: FolderSetupStepProps) { const dispatch = useDispatch(); // Local state for folders const [folder, setFolder] = useState(''); + const isEditing = useSelector( + (state: RootState) => state.onboarding.isEditing, + ); useEffect(() => { - if (localStorage.getItem('folderChosen') === 'true') { + if (localStorage.getItem('folderChosen') === 'true' && !isEditing) { dispatch(markCompleted(stepIndex)); } }, []); @@ -58,13 +63,16 @@ export function FolderSetupStep({ }; const handleBack = () => { + dispatch(setIsEditing(true)); dispatch(previousStep()); }; - if (localStorage.getItem('folderChosen') === 'true') { + if (localStorage.getItem('folderChosen') === 'true' && !isEditing) { return null; } - const progressPercent = Math.round(((stepIndex + 1) / totalSteps) * 100); + const progressPercent = Math.round( + ((currentStepDisplayIndex + 1) / totalSteps) * 100, + ); return ( <> @@ -72,7 +80,7 @@ export function FolderSetupStep({
- Step {stepIndex + 1} of {totalSteps} + Step {currentStepDisplayIndex + 1} of {totalSteps} {progressPercent}%
diff --git a/frontend/src/components/OnboardingSteps/OnboardingStep.tsx b/frontend/src/components/OnboardingSteps/OnboardingStep.tsx index 07d53a01d..e5d1abf48 100644 --- a/frontend/src/components/OnboardingSteps/OnboardingStep.tsx +++ b/frontend/src/components/OnboardingSteps/OnboardingStep.tsx @@ -44,7 +44,7 @@ export const OnboardingStep: React.FC = ({ return
; } }; - + return (
diff --git a/frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx b/frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx index 33e8bbd5f..fb8c0245a 100644 --- a/frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx +++ b/frontend/src/components/OnboardingSteps/ThemeSelectionStep.tsx @@ -18,20 +18,29 @@ import { Sun, Moon, Monitor } from 'lucide-react'; import { AppFeatures } from '@/components/OnboardingSteps/AppFeatures'; import { useTheme } from '@/contexts/ThemeContext'; + +import { setIsEditing } from '@/features/onboardingSlice'; +import { useSelector } from 'react-redux'; +import { RootState } from '@/app/store'; interface ThemeSelectionStepProps { stepIndex: number; totalSteps: number; + currentStepDisplayIndex: number; } export const ThemeSelectionStep: React.FC = ({ stepIndex, totalSteps, + currentStepDisplayIndex, }) => { const { setTheme, theme } = useTheme(); + const isEditing = useSelector( + (state: RootState) => state.onboarding.isEditing, + ); const dispatch = useDispatch(); useEffect(() => { - if (localStorage.getItem('themeChosen')) { + if (localStorage.getItem('themeChosen') === 'true' && !isEditing) { dispatch(markCompleted(stepIndex)); } }, []); @@ -45,20 +54,23 @@ export const ThemeSelectionStep: React.FC = ({ }; const handleBack = () => { + dispatch(setIsEditing(true)); dispatch(previousStep()); }; - if (localStorage.getItem('themeChosen')) { + if (localStorage.getItem('themeChosen') === 'true' && !isEditing) { return null; } - const progressPercent = Math.round(((stepIndex + 1) / totalSteps) * 100); + const progressPercent = Math.round( + ((currentStepDisplayIndex + 1) / totalSteps) * 100, + ); return ( <>
- Step {stepIndex + 1} of {totalSteps} + Step {currentStepDisplayIndex + 1} of {totalSteps} {progressPercent}%
diff --git a/frontend/src/features/onboardingSlice.ts b/frontend/src/features/onboardingSlice.ts index 541fac94a..6749785c1 100644 --- a/frontend/src/features/onboardingSlice.ts +++ b/frontend/src/features/onboardingSlice.ts @@ -9,6 +9,7 @@ interface OnboardingState { stepStatus: boolean[]; avatar: string | null; name: string; + isEditing: boolean; } const initialState: OnboardingState = { @@ -17,6 +18,7 @@ const initialState: OnboardingState = { stepStatus: STEP_NAMES.map(() => false), avatar: localStorage.getItem('avatar'), name: localStorage.getItem('name') || '', + isEditing: false, }; const onboardingSlice = createSlice({ name: 'onboarding', @@ -28,6 +30,9 @@ const onboardingSlice = createSlice({ setName(state, action: PayloadAction) { state.name = action.payload; }, + setIsEditing(state, action: PayloadAction) { + state.isEditing = action.payload; + }, markCompleted(state, action: PayloadAction) { const stepIndex = action.payload; if (stepIndex >= 0 && stepIndex < state.stepStatus.length) { @@ -51,7 +56,7 @@ const onboardingSlice = createSlice({ }, }); -export const { setAvatar, setName, markCompleted, previousStep } = +export const { setAvatar, setName, setIsEditing, markCompleted, previousStep } = onboardingSlice.actions; export default onboardingSlice.reducer;