mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-27 22:13:01 +08:00
feat: Add Openrag feature flag changing starter project name (#10068)
* init default folder change * hide getting started progress * ui testing * add mcp test coverage * [autofix.ci] apply automated fixes * Update to DEFAULT_FOLDER_NAME env var * add new ff for getting started progress --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@ -1287,7 +1287,7 @@
|
||||
"filename": "src/frontend/src/constants/constants.ts",
|
||||
"hashed_secret": "19a2fbd0dd38b4097f419c962342ef5e109eab07",
|
||||
"is_verified": false,
|
||||
"line_number": 734,
|
||||
"line_number": 737,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
@ -1295,7 +1295,7 @@
|
||||
"filename": "src/frontend/src/constants/constants.ts",
|
||||
"hashed_secret": "3806954324550e26ef5de85d007f1746825a073c",
|
||||
"is_verified": false,
|
||||
"line_number": 735,
|
||||
"line_number": 738,
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
@ -1303,7 +1303,7 @@
|
||||
"filename": "src/frontend/src/constants/constants.ts",
|
||||
"hashed_secret": "c04f8fbf55c9096907a982750b1c6b0e4c1dd658",
|
||||
"is_verified": false,
|
||||
"line_number": 1029,
|
||||
"line_number": 913,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
@ -1402,5 +1402,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"generated_at": "2025-06-20T19:21:57Z"
|
||||
"generated_at": "2025-09-30T22:09:16Z"
|
||||
}
|
||||
|
||||
@ -374,6 +374,8 @@ class ConfigResponse(BaseModel):
|
||||
event_delivery: Literal["polling", "streaming", "direct"]
|
||||
webhook_auth_enable: bool
|
||||
voice_mode_available: bool
|
||||
default_folder_name: str
|
||||
hide_getting_started_progress: bool
|
||||
|
||||
@classmethod
|
||||
def from_settings(cls, settings: Settings, auth_settings) -> "ConfigResponse":
|
||||
@ -386,6 +388,10 @@ class ConfigResponse(BaseModel):
|
||||
Returns:
|
||||
ConfigResponse: An instance populated with configuration and feature flag values.
|
||||
"""
|
||||
import os
|
||||
|
||||
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
|
||||
|
||||
return cls(
|
||||
feature_flags=FEATURE_FLAGS,
|
||||
serialization_max_items_length=settings.max_items_length,
|
||||
@ -401,6 +407,8 @@ class ConfigResponse(BaseModel):
|
||||
event_delivery=settings.event_delivery,
|
||||
voice_mode_available=settings.voice_mode_available,
|
||||
webhook_auth_enable=auth_settings.WEBHOOK_AUTH_ENABLE,
|
||||
default_folder_name=DEFAULT_FOLDER_NAME,
|
||||
hide_getting_started_progress=os.getenv("HIDE_GETTING_STARTED_PROGRESS", "").lower() == "true",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -37,7 +37,11 @@ from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from langflow.initial_setup.constants import STARTER_FOLDER_DESCRIPTION, STARTER_FOLDER_NAME
|
||||
from langflow.services.auth.utils import create_super_user
|
||||
from langflow.services.database.models.flow.model import Flow, FlowCreate
|
||||
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
|
||||
from langflow.services.database.models.folder.constants import (
|
||||
DEFAULT_FOLDER_DESCRIPTION,
|
||||
DEFAULT_FOLDER_NAME,
|
||||
LEGACY_FOLDER_NAMES,
|
||||
)
|
||||
from langflow.services.database.models.folder.model import Folder, FolderCreate, FolderRead
|
||||
from langflow.services.deps import get_settings_service, get_storage_service, get_variable_service, session_scope
|
||||
|
||||
@ -1027,6 +1031,9 @@ async def get_or_create_default_folder(session: AsyncSession, user_id: UUID) ->
|
||||
|
||||
Uses an idempotent insertion approach to handle concurrent creation gracefully.
|
||||
|
||||
If the DEFAULT_FOLDER_NAME env var is set to a custom value (e.g., "OpenRAG"), this function
|
||||
will check for legacy folder names and migrate them to avoid duplicates.
|
||||
|
||||
This implementation avoids an external distributed lock and works with both SQLite and PostgreSQL.
|
||||
|
||||
Args:
|
||||
@ -1034,16 +1041,45 @@ async def get_or_create_default_folder(session: AsyncSession, user_id: UUID) ->
|
||||
user_id (UUID): The ID of the user who owns the folder.
|
||||
|
||||
Returns:
|
||||
UUID: The ID of the default folder.
|
||||
FolderRead: The default folder for the user.
|
||||
"""
|
||||
# First, check if the current default folder exists
|
||||
stmt = select(Folder).where(Folder.user_id == user_id, Folder.name == DEFAULT_FOLDER_NAME)
|
||||
result = await session.exec(stmt)
|
||||
folder = result.first()
|
||||
if folder:
|
||||
return FolderRead.model_validate(folder, from_attributes=True)
|
||||
|
||||
# Check if a legacy folder exists and migrate it if the name is different from default
|
||||
if DEFAULT_FOLDER_NAME not in LEGACY_FOLDER_NAMES:
|
||||
for legacy_name in LEGACY_FOLDER_NAMES:
|
||||
if legacy_name == DEFAULT_FOLDER_NAME:
|
||||
continue # Skip if legacy name is the same as current default
|
||||
|
||||
legacy_stmt = select(Folder).where(Folder.user_id == user_id, Folder.name == legacy_name)
|
||||
legacy_result = await session.exec(legacy_stmt)
|
||||
legacy_folder = legacy_result.first()
|
||||
|
||||
if legacy_folder:
|
||||
# Migrate the legacy folder by renaming it
|
||||
await logger.ainfo(
|
||||
f"Migrating legacy folder '{legacy_name}' to '{DEFAULT_FOLDER_NAME}' for user {user_id}"
|
||||
)
|
||||
legacy_folder.name = DEFAULT_FOLDER_NAME
|
||||
legacy_folder.description = DEFAULT_FOLDER_DESCRIPTION
|
||||
session.add(legacy_folder)
|
||||
try:
|
||||
await session.commit()
|
||||
await session.refresh(legacy_folder)
|
||||
return FolderRead.model_validate(legacy_folder, from_attributes=True)
|
||||
except sa.exc.IntegrityError:
|
||||
# If there's a conflict, rollback and proceed to create new folder
|
||||
await session.rollback()
|
||||
break
|
||||
|
||||
# If no existing folder found, create a new one
|
||||
try:
|
||||
folder_obj = Folder(user_id=user_id, name=DEFAULT_FOLDER_NAME)
|
||||
folder_obj = Folder(user_id=user_id, name=DEFAULT_FOLDER_NAME, description=DEFAULT_FOLDER_DESCRIPTION)
|
||||
session.add(folder_obj)
|
||||
await session.commit()
|
||||
await session.refresh(folder_obj)
|
||||
|
||||
@ -1,2 +1,8 @@
|
||||
import os
|
||||
|
||||
DEFAULT_FOLDER_DESCRIPTION = "Manage your own flows. Download and upload projects."
|
||||
DEFAULT_FOLDER_NAME = "Starter Project"
|
||||
# Use DEFAULT_FOLDER_NAME env var, defaulting to "Starter Project" if not set
|
||||
DEFAULT_FOLDER_NAME = os.getenv("DEFAULT_FOLDER_NAME", "Starter Project")
|
||||
|
||||
# Legacy folder names that may exist from previous installations
|
||||
LEGACY_FOLDER_NAMES = ["My Collection", "Starter Project"]
|
||||
|
||||
@ -529,3 +529,209 @@ class TestMultiUserMCPServerAccess:
|
||||
|
||||
response_two = await client.get(f"/api/v2/mcp/servers/{server_name}", headers={"x-api-key": user_two_api_key})
|
||||
assert response_two.json() is None
|
||||
|
||||
|
||||
class TestMCPWithDefaultFolderName:
|
||||
"""Test MCP configuration with different DEFAULT_FOLDER_NAME values."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mcp_finds_default_folder_standard_mode(self, client: AsyncClient): # noqa: ARG002
|
||||
"""Test that MCP finds the correct folder in standard mode (Starter Project)."""
|
||||
user_id = uuid4()
|
||||
project_id = uuid4()
|
||||
flow_id = uuid4()
|
||||
|
||||
async with session_scope() as session:
|
||||
# Create user
|
||||
user = User(id=user_id, username=f"test_default_folder_{user_id}", password="hashed_password") # noqa: S106
|
||||
session.add(user)
|
||||
|
||||
# Create folder with DEFAULT_FOLDER_NAME (should match current setting)
|
||||
folder = Folder(id=project_id, name=DEFAULT_FOLDER_NAME, user_id=user_id, description="Test folder")
|
||||
session.add(folder)
|
||||
|
||||
# Create flow in folder
|
||||
flow = Flow(
|
||||
id=flow_id,
|
||||
name="Test Flow",
|
||||
description="A test flow",
|
||||
folder_id=project_id,
|
||||
user_id=user_id,
|
||||
is_component=False,
|
||||
mcp_enabled=None,
|
||||
)
|
||||
session.add(flow)
|
||||
|
||||
await session.commit()
|
||||
|
||||
try:
|
||||
async with session_scope() as session:
|
||||
from langflow.services.deps import get_settings_service
|
||||
|
||||
settings_service = get_settings_service()
|
||||
original_setting = settings_service.settings.add_projects_to_mcp_servers
|
||||
|
||||
try:
|
||||
settings_service.settings.add_projects_to_mcp_servers = True
|
||||
await auto_configure_starter_projects_mcp(session)
|
||||
|
||||
# Verify folder was found and processed
|
||||
updated_folder = await session.get(Folder, project_id)
|
||||
assert updated_folder is not None
|
||||
assert updated_folder.name == DEFAULT_FOLDER_NAME
|
||||
|
||||
finally:
|
||||
settings_service.settings.add_projects_to_mcp_servers = original_setting
|
||||
|
||||
finally:
|
||||
# Cleanup
|
||||
async with session_scope() as session:
|
||||
flow_to_delete = await session.get(Flow, flow_id)
|
||||
if flow_to_delete:
|
||||
await session.delete(flow_to_delete)
|
||||
folder_to_delete = await session.get(Folder, project_id)
|
||||
if folder_to_delete:
|
||||
await session.delete(folder_to_delete)
|
||||
user_to_delete = await session.get(User, user_id)
|
||||
if user_to_delete:
|
||||
await session.delete(user_to_delete)
|
||||
await session.commit()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mcp_with_legacy_folder_after_migration(self, client: AsyncClient): # noqa: ARG002
|
||||
"""Test that MCP finds migrated folders after setting custom DEFAULT_FOLDER_NAME."""
|
||||
user_id = uuid4()
|
||||
project_id = uuid4()
|
||||
flow_id = uuid4()
|
||||
|
||||
# Only run this test when DEFAULT_FOLDER_NAME is set to custom value (e.g., "OpenRAG")
|
||||
if DEFAULT_FOLDER_NAME in ["Starter Project", "My Collection"]:
|
||||
pytest.skip("Test only applicable when DEFAULT_FOLDER_NAME is set to custom value")
|
||||
|
||||
async with session_scope() as session:
|
||||
# Create user
|
||||
user = User(id=user_id, username=f"test_migrated_{user_id}", password="hashed_password") # noqa: S106
|
||||
session.add(user)
|
||||
|
||||
# Create folder with legacy name that will be migrated
|
||||
legacy_folder = Folder(id=project_id, name="Starter Project", user_id=user_id, description="Legacy folder")
|
||||
session.add(legacy_folder)
|
||||
|
||||
# Create flow in folder
|
||||
flow = Flow(
|
||||
id=flow_id,
|
||||
name="Test Flow in Legacy Folder",
|
||||
description="A test flow",
|
||||
folder_id=project_id,
|
||||
user_id=user_id,
|
||||
is_component=False,
|
||||
mcp_enabled=None,
|
||||
)
|
||||
session.add(flow)
|
||||
|
||||
await session.commit()
|
||||
|
||||
try:
|
||||
# Trigger migration by calling get_or_create_default_folder
|
||||
from langflow.initial_setup.setup import get_or_create_default_folder
|
||||
|
||||
async with session_scope() as session:
|
||||
migrated_folder = await get_or_create_default_folder(session, user_id)
|
||||
assert migrated_folder.name == DEFAULT_FOLDER_NAME
|
||||
assert migrated_folder.id == project_id # Same folder, renamed
|
||||
|
||||
# Now test that MCP can find the migrated folder
|
||||
async with session_scope() as session:
|
||||
from langflow.services.deps import get_settings_service
|
||||
|
||||
settings_service = get_settings_service()
|
||||
original_setting = settings_service.settings.add_projects_to_mcp_servers
|
||||
|
||||
try:
|
||||
settings_service.settings.add_projects_to_mcp_servers = True
|
||||
await auto_configure_starter_projects_mcp(session)
|
||||
|
||||
# Verify MCP found the migrated folder
|
||||
updated_folder = await session.get(Folder, project_id)
|
||||
assert updated_folder is not None
|
||||
assert updated_folder.name == DEFAULT_FOLDER_NAME
|
||||
|
||||
finally:
|
||||
settings_service.settings.add_projects_to_mcp_servers = original_setting
|
||||
|
||||
finally:
|
||||
# Cleanup
|
||||
async with session_scope() as session:
|
||||
flow_to_delete = await session.get(Flow, flow_id)
|
||||
if flow_to_delete:
|
||||
await session.delete(flow_to_delete)
|
||||
folder_to_delete = await session.get(Folder, project_id)
|
||||
if folder_to_delete:
|
||||
await session.delete(folder_to_delete)
|
||||
user_to_delete = await session.get(User, user_id)
|
||||
if user_to_delete:
|
||||
await session.delete(user_to_delete)
|
||||
await session.commit()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mcp_skips_wrong_folder_name(self, client: AsyncClient): # noqa: ARG002
|
||||
"""Test that MCP skips folders that don't match DEFAULT_FOLDER_NAME."""
|
||||
user_id = uuid4()
|
||||
project_id = uuid4()
|
||||
flow_id = uuid4()
|
||||
|
||||
async with session_scope() as session:
|
||||
# Create user
|
||||
user = User(id=user_id, username=f"test_wrong_folder_{user_id}", password="hashed_password") # noqa: S106
|
||||
session.add(user)
|
||||
|
||||
# Create folder with different name
|
||||
folder = Folder(id=project_id, name="Some Other Folder", user_id=user_id, description="Wrong folder")
|
||||
session.add(folder)
|
||||
|
||||
# Create flow in folder
|
||||
flow = Flow(
|
||||
id=flow_id,
|
||||
name="Test Flow",
|
||||
description="A test flow",
|
||||
folder_id=project_id,
|
||||
user_id=user_id,
|
||||
is_component=False,
|
||||
mcp_enabled=None,
|
||||
)
|
||||
session.add(flow)
|
||||
|
||||
await session.commit()
|
||||
|
||||
try:
|
||||
async with session_scope() as session:
|
||||
from langflow.services.deps import get_settings_service
|
||||
|
||||
settings_service = get_settings_service()
|
||||
original_setting = settings_service.settings.add_projects_to_mcp_servers
|
||||
|
||||
try:
|
||||
settings_service.settings.add_projects_to_mcp_servers = True
|
||||
# Should not raise an error, just skip this user
|
||||
await auto_configure_starter_projects_mcp(session)
|
||||
|
||||
# Verify flow was NOT configured (still None or False)
|
||||
updated_flow = await session.get(Flow, flow_id)
|
||||
assert updated_flow.mcp_enabled in [None, False]
|
||||
|
||||
finally:
|
||||
settings_service.settings.add_projects_to_mcp_servers = original_setting
|
||||
|
||||
finally:
|
||||
# Cleanup
|
||||
async with session_scope() as session:
|
||||
flow_to_delete = await session.get(Flow, flow_id)
|
||||
if flow_to_delete:
|
||||
await session.delete(flow_to_delete)
|
||||
folder_to_delete = await session.get(Folder, project_id)
|
||||
if folder_to_delete:
|
||||
await session.delete(folder_to_delete)
|
||||
user_to_delete = await session.get(User, user_id)
|
||||
if user_to_delete:
|
||||
await session.delete(user_to_delete)
|
||||
await session.commit()
|
||||
|
||||
@ -2,7 +2,8 @@ import asyncio
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from langflow.initial_setup.setup import DEFAULT_FOLDER_NAME, get_or_create_default_folder, session_scope
|
||||
from langflow.initial_setup.setup import get_or_create_default_folder, session_scope
|
||||
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
|
||||
from langflow.services.database.models.folder.model import FolderRead
|
||||
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import { SidebarTrigger } from "@/components/ui/sidebar";
|
||||
import { useUpdateUser } from "@/controllers/API/queries/auth";
|
||||
import CustomGetStartedProgress from "@/customization/components/custom-get-started-progress";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
import { useUtilityStore } from "@/stores/utilityStore";
|
||||
import { AddFolderButton } from "./add-folder-button";
|
||||
import { UploadFolderButton } from "./upload-folder-button";
|
||||
|
||||
@ -19,6 +20,9 @@ export const HeaderButtons = ({
|
||||
addNewFolder: () => void;
|
||||
}) => {
|
||||
const userData = useAuthStore((state) => state.userData);
|
||||
const hideGettingStartedProgress = useUtilityStore(
|
||||
(state) => state.hideGettingStartedProgress,
|
||||
);
|
||||
|
||||
const [isDismissedDialog, setIsDismissedDialog] = useState(
|
||||
userData?.optins?.dialog_dismissed,
|
||||
@ -55,7 +59,7 @@ export const HeaderButtons = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isDismissedDialog && userData && (
|
||||
{!hideGettingStartedProgress && !isDismissedDialog && userData && (
|
||||
<>
|
||||
<CustomGetStartedProgress
|
||||
userData={userData!}
|
||||
|
||||
@ -7,8 +7,8 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "@/components/ui/select-custom";
|
||||
import { DEFAULT_FOLDER } from "@/constants/constants";
|
||||
import type { FolderType } from "@/pages/MainPage/entities";
|
||||
import { useUtilityStore } from "@/stores/utilityStore";
|
||||
import { cn } from "@/utils/utils";
|
||||
import { handleSelectChange } from "../helpers/handle-select-change";
|
||||
import { FolderSelectItem } from "./folder-select-item";
|
||||
@ -28,6 +28,7 @@ export const SelectOptions = ({
|
||||
handleSelectFolderToRename: (folder: FolderType) => void;
|
||||
checkPathName: (folderId: string) => boolean;
|
||||
}) => {
|
||||
const defaultFolderName = useUtilityStore((state) => state.defaultFolderName);
|
||||
return (
|
||||
<div>
|
||||
<Select
|
||||
@ -60,7 +61,7 @@ export const SelectOptions = ({
|
||||
</SelectTrigger>
|
||||
</ShadTooltip>
|
||||
<SelectContent align="end" alignOffset={-16} position="popper">
|
||||
{item.name !== DEFAULT_FOLDER && (
|
||||
{item.name !== defaultFolderName && (
|
||||
<SelectItem
|
||||
id="rename-button"
|
||||
value="rename"
|
||||
|
||||
@ -13,7 +13,6 @@ import {
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { DEFAULT_FOLDER } from "@/constants/constants";
|
||||
import { useUpdateUser } from "@/controllers/API/queries/auth";
|
||||
import {
|
||||
usePatchFolders,
|
||||
@ -41,6 +40,7 @@ import type { FolderType } from "../../../../../pages/MainPage/entities";
|
||||
import useAlertStore from "../../../../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../../../../stores/flowsManagerStore";
|
||||
import { useFolderStore } from "../../../../../stores/foldersStore";
|
||||
import { useUtilityStore } from "../../../../../stores/utilityStore";
|
||||
import { handleKeyDown } from "../../../../../utils/reactflowUtils";
|
||||
import { cn } from "../../../../../utils/utils";
|
||||
import useFileDrop from "../../hooks/use-on-file-drop";
|
||||
@ -86,6 +86,7 @@ const SideBarFoldersButtonsComponent = ({
|
||||
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
const defaultFolderName = useUtilityStore((state) => state.defaultFolderName);
|
||||
|
||||
const folderId = useParams().folderId ?? myCollectionId ?? "";
|
||||
|
||||
@ -275,7 +276,7 @@ const SideBarFoldersButtonsComponent = ({
|
||||
};
|
||||
|
||||
const handleDoubleClick = (event, item) => {
|
||||
if (item.name === DEFAULT_FOLDER) {
|
||||
if (item.name === defaultFolderName) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -558,7 +558,10 @@ export const NOUNS: string[] = [
|
||||
*/
|
||||
export const USER_PROJECTS_HEADER = "My Collection";
|
||||
|
||||
// This will be dynamically set based on the RUN_WITH_OPENRAG feature flag
|
||||
// The actual value is determined by the backend configuration
|
||||
export const DEFAULT_FOLDER = "Starter Project";
|
||||
export const OPENRAG_FOLDER = "OpenRAG";
|
||||
|
||||
export const MAX_MCP_SERVER_NAME_LENGTH = 30;
|
||||
|
||||
@ -741,7 +744,7 @@ export const STATUS_INACTIVE = "Execution blocked";
|
||||
export const STATUS_BUILDING = "Building...";
|
||||
export const SAVED_HOVER = "Last saved: ";
|
||||
export const RUN_TIMESTAMP_PREFIX = "Last Run: ";
|
||||
export const STARTER_FOLDER_NAME = "Starter Projects";
|
||||
|
||||
export const PRIORITY_SIDEBAR_ORDER = [
|
||||
"saved_components",
|
||||
"inputs",
|
||||
|
||||
@ -23,6 +23,8 @@ export interface ConfigResponse {
|
||||
event_delivery: EventDeliveryType;
|
||||
webhook_auth_enable: boolean;
|
||||
voice_mode_available: boolean;
|
||||
default_folder_name: string;
|
||||
hide_getting_started_progress: boolean;
|
||||
}
|
||||
|
||||
export const useGetConfig: useQueryFunctionType<undefined, ConfigResponse> = (
|
||||
@ -49,6 +51,12 @@ export const useGetConfig: useQueryFunctionType<undefined, ConfigResponse> = (
|
||||
const setWebhookAuthEnable = useUtilityStore(
|
||||
(state) => state.setWebhookAuthEnable,
|
||||
);
|
||||
const setDefaultFolderName = useUtilityStore(
|
||||
(state) => state.setDefaultFolderName,
|
||||
);
|
||||
const setHideGettingStartedProgress = useUtilityStore(
|
||||
(state) => state.setHideGettingStartedProgress,
|
||||
);
|
||||
|
||||
const { query } = UseRequestProcessor();
|
||||
|
||||
@ -72,6 +80,10 @@ export const useGetConfig: useQueryFunctionType<undefined, ConfigResponse> = (
|
||||
);
|
||||
setEventDelivery(data.event_delivery ?? EventDeliveryType.POLLING);
|
||||
setWebhookAuthEnable(data.webhook_auth_enable ?? true);
|
||||
setDefaultFolderName(data.default_folder_name ?? "Starter Project");
|
||||
setHideGettingStartedProgress(
|
||||
data.hide_getting_started_progress ?? false,
|
||||
);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { DEFAULT_FOLDER } from "@/constants/constants";
|
||||
import type { FolderType } from "@/pages/MainPage/entities";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import { useUtilityStore } from "@/stores/utilityStore";
|
||||
import type { useQueryFunctionType } from "@/types/api";
|
||||
import { api } from "../../api";
|
||||
import { getURL } from "../../helpers/constants";
|
||||
@ -15,6 +15,7 @@ export const useGetFoldersQuery: useQueryFunctionType<
|
||||
|
||||
const setMyCollectionId = useFolderStore((state) => state.setMyCollectionId);
|
||||
const setFolders = useFolderStore((state) => state.setFolders);
|
||||
const defaultFolderName = useUtilityStore((state) => state.defaultFolderName);
|
||||
|
||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||
|
||||
@ -23,7 +24,7 @@ export const useGetFoldersQuery: useQueryFunctionType<
|
||||
const res = await api.get(`${getURL("PROJECTS")}/`);
|
||||
const data = res.data;
|
||||
|
||||
const myCollectionId = data?.find((f) => f.name === DEFAULT_FOLDER)?.id;
|
||||
const myCollectionId = data?.find((f) => f.name === defaultFolderName)?.id;
|
||||
setMyCollectionId(myCollectionId);
|
||||
setFolders(data);
|
||||
|
||||
|
||||
@ -40,6 +40,8 @@ describe("useUtilityStore", () => {
|
||||
currentSessionId: "",
|
||||
eventDelivery: EventDeliveryType.POLLING,
|
||||
webhookAuthEnable: true,
|
||||
defaultFolderName: "Starter Project",
|
||||
hideGettingStartedProgress: false,
|
||||
});
|
||||
});
|
||||
|
||||
@ -61,6 +63,8 @@ describe("useUtilityStore", () => {
|
||||
expect(result.current.currentSessionId).toBe("");
|
||||
expect(result.current.eventDelivery).toBe(EventDeliveryType.POLLING);
|
||||
expect(result.current.webhookAuthEnable).toBe(true);
|
||||
expect(result.current.defaultFolderName).toBe("Starter Project");
|
||||
expect(result.current.hideGettingStartedProgress).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -556,6 +560,75 @@ describe("useUtilityStore", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("setDefaultFolderName", () => {
|
||||
it("should set defaultFolderName", () => {
|
||||
const { result } = renderHook(() => useUtilityStore());
|
||||
|
||||
act(() => {
|
||||
result.current.setDefaultFolderName("OpenRAG");
|
||||
});
|
||||
|
||||
expect(result.current.defaultFolderName).toBe("OpenRAG");
|
||||
});
|
||||
|
||||
it("should change defaultFolderName", () => {
|
||||
const { result } = renderHook(() => useUtilityStore());
|
||||
|
||||
act(() => {
|
||||
result.current.setDefaultFolderName("OpenRAG");
|
||||
});
|
||||
expect(result.current.defaultFolderName).toBe("OpenRAG");
|
||||
|
||||
act(() => {
|
||||
result.current.setDefaultFolderName("My Custom Folder");
|
||||
});
|
||||
expect(result.current.defaultFolderName).toBe("My Custom Folder");
|
||||
});
|
||||
|
||||
it("should handle various folder names", () => {
|
||||
const { result } = renderHook(() => useUtilityStore());
|
||||
|
||||
const folderNames = [
|
||||
"Starter Project",
|
||||
"OpenRAG",
|
||||
"My Collection",
|
||||
"Custom Folder",
|
||||
];
|
||||
folderNames.forEach((folderName) => {
|
||||
act(() => {
|
||||
result.current.setDefaultFolderName(folderName);
|
||||
});
|
||||
expect(result.current.defaultFolderName).toBe(folderName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("setHideGettingStartedProgress", () => {
|
||||
it("should set hideGettingStartedProgress to true", () => {
|
||||
const { result } = renderHook(() => useUtilityStore());
|
||||
|
||||
act(() => {
|
||||
result.current.setHideGettingStartedProgress(true);
|
||||
});
|
||||
|
||||
expect(result.current.hideGettingStartedProgress).toBe(true);
|
||||
});
|
||||
|
||||
it("should toggle hideGettingStartedProgress", () => {
|
||||
const { result } = renderHook(() => useUtilityStore());
|
||||
|
||||
act(() => {
|
||||
result.current.setHideGettingStartedProgress(true);
|
||||
});
|
||||
expect(result.current.hideGettingStartedProgress).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.setHideGettingStartedProgress(false);
|
||||
});
|
||||
expect(result.current.hideGettingStartedProgress).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("state interactions", () => {
|
||||
it("should handle multiple state updates", () => {
|
||||
const { result } = renderHook(() => useUtilityStore());
|
||||
|
||||
@ -51,4 +51,10 @@ export const useUtilityStore = create<UtilityStoreType>((set, get) => ({
|
||||
webhookAuthEnable: true,
|
||||
setWebhookAuthEnable: (webhookAuthEnable: boolean) =>
|
||||
set({ webhookAuthEnable }),
|
||||
defaultFolderName: "Starter Project",
|
||||
setDefaultFolderName: (defaultFolderName: string) =>
|
||||
set({ defaultFolderName }),
|
||||
hideGettingStartedProgress: false,
|
||||
setHideGettingStartedProgress: (hideGettingStartedProgress: boolean) =>
|
||||
set({ hideGettingStartedProgress }),
|
||||
}));
|
||||
|
||||
@ -30,4 +30,8 @@ export type UtilityStoreType = {
|
||||
setSerializationMaxItemsLength: (serializationMaxItemsLength: number) => void;
|
||||
webhookAuthEnable: boolean;
|
||||
setWebhookAuthEnable: (webhookAuthEnable: boolean) => void;
|
||||
defaultFolderName: string;
|
||||
setDefaultFolderName: (defaultFolderName: string) => void;
|
||||
hideGettingStartedProgress: boolean;
|
||||
setHideGettingStartedProgress: (hideGettingStartedProgress: boolean) => void;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user