mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-06-19 12:30:55 +02:00
Admin default (#4032)
* clean up * minor cleanup * building * update agnetic message look * k * fix alembic history
This commit is contained in:
parent
630bdf71a3
commit
9635522de8
@ -0,0 +1,31 @@
|
|||||||
|
"""nullable preferences
|
||||||
|
|
||||||
|
Revision ID: b388730a2899
|
||||||
|
Revises: 1a03d2c2856b
|
||||||
|
Create Date: 2025-02-17 18:49:22.643902
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "b388730a2899"
|
||||||
|
down_revision = "1a03d2c2856b"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
op.alter_column("user", "temperature_override_enabled", nullable=True)
|
||||||
|
op.alter_column("user", "auto_scroll", nullable=True)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# Ensure no null values before making columns non-nullable
|
||||||
|
op.execute(
|
||||||
|
'UPDATE "user" SET temperature_override_enabled = false WHERE temperature_override_enabled IS NULL'
|
||||||
|
)
|
||||||
|
op.execute('UPDATE "user" SET auto_scroll = false WHERE auto_scroll IS NULL')
|
||||||
|
|
||||||
|
op.alter_column("user", "temperature_override_enabled", nullable=False)
|
||||||
|
op.alter_column("user", "auto_scroll", nullable=False)
|
@ -148,11 +148,12 @@ class User(SQLAlchemyBaseUserTableUUID, Base):
|
|||||||
putting here for simpicity
|
putting here for simpicity
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# if specified, controls the assistants that are shown to the user + their order
|
temperature_override_enabled: Mapped[bool | None] = mapped_column(
|
||||||
# if not specified, all assistants are shown
|
Boolean, default=None
|
||||||
temperature_override_enabled: Mapped[bool] = mapped_column(Boolean, default=False)
|
)
|
||||||
auto_scroll: Mapped[bool] = mapped_column(Boolean, default=True)
|
auto_scroll: Mapped[bool | None] = mapped_column(Boolean, default=None)
|
||||||
shortcut_enabled: Mapped[bool] = mapped_column(Boolean, default=False)
|
shortcut_enabled: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||||
|
|
||||||
chosen_assistants: Mapped[list[int] | None] = mapped_column(
|
chosen_assistants: Mapped[list[int] | None] = mapped_column(
|
||||||
postgresql.JSONB(), nullable=True, default=None
|
postgresql.JSONB(), nullable=True, default=None
|
||||||
)
|
)
|
||||||
|
@ -45,9 +45,11 @@ class UserPreferences(BaseModel):
|
|||||||
hidden_assistants: list[int] = []
|
hidden_assistants: list[int] = []
|
||||||
visible_assistants: list[int] = []
|
visible_assistants: list[int] = []
|
||||||
default_model: str | None = None
|
default_model: str | None = None
|
||||||
auto_scroll: bool | None = None
|
|
||||||
pinned_assistants: list[int] | None = None
|
pinned_assistants: list[int] | None = None
|
||||||
shortcut_enabled: bool | None = None
|
shortcut_enabled: bool | None = None
|
||||||
|
|
||||||
|
# These will default to workspace settings on the frontend if not set
|
||||||
|
auto_scroll: bool | None = None
|
||||||
temperature_override_enabled: bool | None = None
|
temperature_override_enabled: bool | None = None
|
||||||
|
|
||||||
|
|
||||||
@ -86,12 +88,12 @@ class UserInfo(BaseModel):
|
|||||||
preferences=(
|
preferences=(
|
||||||
UserPreferences(
|
UserPreferences(
|
||||||
shortcut_enabled=user.shortcut_enabled,
|
shortcut_enabled=user.shortcut_enabled,
|
||||||
auto_scroll=user.auto_scroll,
|
|
||||||
chosen_assistants=user.chosen_assistants,
|
chosen_assistants=user.chosen_assistants,
|
||||||
default_model=user.default_model,
|
default_model=user.default_model,
|
||||||
hidden_assistants=user.hidden_assistants,
|
hidden_assistants=user.hidden_assistants,
|
||||||
pinned_assistants=user.pinned_assistants,
|
pinned_assistants=user.pinned_assistants,
|
||||||
visible_assistants=user.visible_assistants,
|
visible_assistants=user.visible_assistants,
|
||||||
|
auto_scroll=user.auto_scroll,
|
||||||
temperature_override_enabled=user.temperature_override_enabled,
|
temperature_override_enabled=user.temperature_override_enabled,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -46,7 +46,9 @@ class Settings(BaseModel):
|
|||||||
application_status: ApplicationStatus = ApplicationStatus.ACTIVE
|
application_status: ApplicationStatus = ApplicationStatus.ACTIVE
|
||||||
anonymous_user_enabled: bool | None = None
|
anonymous_user_enabled: bool | None = None
|
||||||
pro_search_disabled: bool | None = None
|
pro_search_disabled: bool | None = None
|
||||||
auto_scroll: bool | None = None
|
|
||||||
|
temperature_override_enabled: bool = False
|
||||||
|
auto_scroll: bool = False
|
||||||
|
|
||||||
|
|
||||||
class UserSettings(Settings):
|
class UserSettings(Settings):
|
||||||
|
@ -213,12 +213,23 @@ export function SettingsForm() {
|
|||||||
<Title className="mb-4">Workspace Settings</Title>
|
<Title className="mb-4">Workspace Settings</Title>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Auto-scroll"
|
label="Auto-scroll"
|
||||||
sublabel="If set, the chat window will automatically scroll to the bottom as new lines of text are generated by the AI model."
|
sublabel="If set, the chat window will automatically scroll to the bottom as new lines of text are generated by the AI model. This can be overridden by individual user settings."
|
||||||
checked={settings.auto_scroll}
|
checked={settings.auto_scroll}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
handleToggleSettingsField("auto_scroll", e.target.checked)
|
handleToggleSettingsField("auto_scroll", e.target.checked)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label="Override default temperature"
|
||||||
|
sublabel="If set, users will be able to override the default temperature for each assistant."
|
||||||
|
checked={settings.temperature_override_enabled}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleToggleSettingsField(
|
||||||
|
"temperature_override_enabled",
|
||||||
|
e.target.checked
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Anonymous Users"
|
label="Anonymous Users"
|
||||||
sublabel="If set, users will not be required to sign in to use Onyx."
|
sublabel="If set, users will not be required to sign in to use Onyx."
|
||||||
|
@ -13,6 +13,7 @@ export interface Settings {
|
|||||||
pro_search_disabled: boolean | null;
|
pro_search_disabled: boolean | null;
|
||||||
application_status: ApplicationStatus;
|
application_status: ApplicationStatus;
|
||||||
auto_scroll: boolean;
|
auto_scroll: boolean;
|
||||||
|
temperature_override_enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NotificationType {
|
export enum NotificationType {
|
||||||
@ -54,7 +55,6 @@ export interface EnterpriseSettings {
|
|||||||
custom_popup_header: string | null;
|
custom_popup_header: string | null;
|
||||||
custom_popup_content: string | null;
|
custom_popup_content: string | null;
|
||||||
enable_consent_screen: boolean | null;
|
enable_consent_screen: boolean | null;
|
||||||
auto_scroll: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CombinedSettings {
|
export interface CombinedSettings {
|
||||||
|
@ -1870,9 +1870,7 @@ export function ChatPage({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const autoScrollEnabled =
|
const autoScrollEnabled =
|
||||||
user?.preferences?.auto_scroll == null
|
(user?.preferences?.auto_scroll && !agenticGenerating) ?? false;
|
||||||
? settings?.enterpriseSettings?.auto_scroll || false
|
|
||||||
: user?.preferences?.auto_scroll! && !agenticGenerating;
|
|
||||||
|
|
||||||
useScrollonStream({
|
useScrollonStream({
|
||||||
chatState: currentSessionChatState,
|
chatState: currentSessionChatState,
|
||||||
|
@ -537,7 +537,6 @@ export const AgenticMessage = ({
|
|||||||
{includeMessageSwitcher && (
|
{includeMessageSwitcher && (
|
||||||
<div className="-mx-1 mr-auto">
|
<div className="-mx-1 mr-auto">
|
||||||
<MessageSwitcher
|
<MessageSwitcher
|
||||||
disableForStreaming={!isComplete}
|
|
||||||
currentPage={currentMessageInd + 1}
|
currentPage={currentMessageInd + 1}
|
||||||
totalPages={otherMessagesCanSwitchTo.length}
|
totalPages={otherMessagesCanSwitchTo.length}
|
||||||
handlePrevious={() => {
|
handlePrevious={() => {
|
||||||
@ -624,7 +623,6 @@ export const AgenticMessage = ({
|
|||||||
{includeMessageSwitcher && (
|
{includeMessageSwitcher && (
|
||||||
<div className="-mx-1 mr-auto">
|
<div className="-mx-1 mr-auto">
|
||||||
<MessageSwitcher
|
<MessageSwitcher
|
||||||
disableForStreaming={!isComplete}
|
|
||||||
currentPage={currentMessageInd + 1}
|
currentPage={currentMessageInd + 1}
|
||||||
totalPages={otherMessagesCanSwitchTo.length}
|
totalPages={otherMessagesCanSwitchTo.length}
|
||||||
handlePrevious={() => {
|
handlePrevious={() => {
|
||||||
@ -703,52 +701,27 @@ function MessageSwitcher({
|
|||||||
totalPages,
|
totalPages,
|
||||||
handlePrevious,
|
handlePrevious,
|
||||||
handleNext,
|
handleNext,
|
||||||
disableForStreaming,
|
|
||||||
}: {
|
}: {
|
||||||
currentPage: number;
|
currentPage: number;
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
handlePrevious: () => void;
|
handlePrevious: () => void;
|
||||||
handleNext: () => void;
|
handleNext: () => void;
|
||||||
disableForStreaming?: boolean;
|
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center text-sm space-x-0.5">
|
<div className="flex items-center text-sm space-x-0.5">
|
||||||
<TooltipProvider>
|
<Hoverable
|
||||||
<Tooltip>
|
icon={FiChevronLeft}
|
||||||
<TooltipTrigger asChild>
|
onClick={currentPage === 1 ? undefined : handlePrevious}
|
||||||
<div>
|
/>
|
||||||
<Hoverable
|
|
||||||
icon={FiChevronLeft}
|
|
||||||
onClick={currentPage === 1 ? undefined : handlePrevious}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
{disableForStreaming ? "Disabled" : "Previous"}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
|
|
||||||
<span className="text-text-darker select-none">
|
<span className="text-text-darker select-none">
|
||||||
{currentPage} / {totalPages}
|
{currentPage} / {totalPages}
|
||||||
{disableForStreaming ? "Complete" : "Generating"}
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<TooltipProvider>
|
<Hoverable
|
||||||
<Tooltip>
|
icon={FiChevronRight}
|
||||||
<TooltipTrigger asChild>
|
onClick={currentPage === totalPages ? undefined : handleNext}
|
||||||
<div>
|
/>
|
||||||
<Hoverable
|
|
||||||
icon={FiChevronRight}
|
|
||||||
onClick={currentPage === totalPages ? undefined : handleNext}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
{disableForStreaming ? "Disabled" : "Next"}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -154,11 +154,9 @@ export function UserSettingsModal({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const defaultProvider = llmProviders.find(
|
|
||||||
(llmProvider) => llmProvider.is_default_provider
|
|
||||||
);
|
|
||||||
const settings = useContext(SettingsContext);
|
const settings = useContext(SettingsContext);
|
||||||
const autoScroll = settings?.enterpriseSettings?.auto_scroll;
|
const autoScroll = settings?.settings?.auto_scroll;
|
||||||
|
|
||||||
const checked =
|
const checked =
|
||||||
user?.preferences?.auto_scroll === null
|
user?.preferences?.auto_scroll === null
|
||||||
|
@ -55,7 +55,7 @@ export function WhitelabelingForm() {
|
|||||||
<div>
|
<div>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={{
|
||||||
auto_scroll: enterpriseSettings?.auto_scroll || false,
|
auto_scroll: settings?.settings?.auto_scroll || false,
|
||||||
application_name: enterpriseSettings?.application_name || null,
|
application_name: enterpriseSettings?.application_name || null,
|
||||||
use_custom_logo: enterpriseSettings?.use_custom_logo || false,
|
use_custom_logo: enterpriseSettings?.use_custom_logo || false,
|
||||||
use_custom_logotype: enterpriseSettings?.use_custom_logotype || false,
|
use_custom_logotype: enterpriseSettings?.use_custom_logotype || false,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
"use client";
|
||||||
import { CombinedSettings } from "@/app/admin/settings/interfaces";
|
import { CombinedSettings } from "@/app/admin/settings/interfaces";
|
||||||
import { UserProvider } from "../user/UserProvider";
|
import { UserProvider } from "../user/UserProvider";
|
||||||
import { ProviderContextProvider } from "../chat/ProviderContext";
|
import { ProviderContextProvider } from "../chat/ProviderContext";
|
||||||
@ -27,9 +28,9 @@ export const AppProvider = ({
|
|||||||
hasImageCompatibleModel,
|
hasImageCompatibleModel,
|
||||||
}: AppProviderProps) => {
|
}: AppProviderProps) => {
|
||||||
return (
|
return (
|
||||||
<UserProvider user={user}>
|
<SettingsProvider settings={settings}>
|
||||||
<ProviderContextProvider>
|
<UserProvider settings={settings} user={user}>
|
||||||
<SettingsProvider settings={settings}>
|
<ProviderContextProvider>
|
||||||
<AssistantsProvider
|
<AssistantsProvider
|
||||||
initialAssistants={assistants}
|
initialAssistants={assistants}
|
||||||
hasAnyConnectors={hasAnyConnectors}
|
hasAnyConnectors={hasAnyConnectors}
|
||||||
@ -37,8 +38,8 @@ export const AppProvider = ({
|
|||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</AssistantsProvider>
|
</AssistantsProvider>
|
||||||
</SettingsProvider>
|
</ProviderContextProvider>
|
||||||
</ProviderContextProvider>
|
</UserProvider>
|
||||||
</UserProvider>
|
</SettingsProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -52,6 +52,7 @@ export async function fetchSettingsSS(): Promise<CombinedSettings | null> {
|
|||||||
needs_reindexing: false,
|
needs_reindexing: false,
|
||||||
anonymous_user_enabled: false,
|
anonymous_user_enabled: false,
|
||||||
pro_search_disabled: false,
|
pro_search_disabled: false,
|
||||||
|
temperature_override_enabled: true,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -4,6 +4,8 @@ import React, { createContext, useContext, useState, useEffect } from "react";
|
|||||||
import { User, UserRole } from "@/lib/types";
|
import { User, UserRole } from "@/lib/types";
|
||||||
import { getCurrentUser } from "@/lib/user";
|
import { getCurrentUser } from "@/lib/user";
|
||||||
import { usePostHog } from "posthog-js/react";
|
import { usePostHog } from "posthog-js/react";
|
||||||
|
import { CombinedSettings } from "@/app/admin/settings/interfaces";
|
||||||
|
import { SettingsContext } from "../settings/SettingsProvider";
|
||||||
|
|
||||||
interface UserContextType {
|
interface UserContextType {
|
||||||
user: User | null;
|
user: User | null;
|
||||||
@ -26,14 +28,47 @@ const UserContext = createContext<UserContextType | undefined>(undefined);
|
|||||||
export function UserProvider({
|
export function UserProvider({
|
||||||
children,
|
children,
|
||||||
user,
|
user,
|
||||||
|
settings,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
user: User | null;
|
user: User | null;
|
||||||
|
settings: CombinedSettings;
|
||||||
}) {
|
}) {
|
||||||
const [upToDateUser, setUpToDateUser] = useState<User | null>(user);
|
const updatedSettings = useContext(SettingsContext);
|
||||||
|
|
||||||
const posthog = usePostHog();
|
const posthog = usePostHog();
|
||||||
|
|
||||||
|
// For auto_scroll and temperature_override_enabled:
|
||||||
|
// - If user has a preference set, use that
|
||||||
|
// - Otherwise, use the workspace setting if available
|
||||||
|
function mergeUserPreferences(
|
||||||
|
currentUser: User | null,
|
||||||
|
currentSettings: CombinedSettings | null
|
||||||
|
): User | null {
|
||||||
|
if (!currentUser) return null;
|
||||||
|
return {
|
||||||
|
...currentUser,
|
||||||
|
preferences: {
|
||||||
|
...currentUser.preferences,
|
||||||
|
auto_scroll:
|
||||||
|
currentUser.preferences?.auto_scroll ??
|
||||||
|
currentSettings?.settings?.auto_scroll ??
|
||||||
|
false,
|
||||||
|
temperature_override_enabled:
|
||||||
|
currentUser.preferences?.temperature_override_enabled ??
|
||||||
|
currentSettings?.settings?.temperature_override_enabled ??
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const [upToDateUser, setUpToDateUser] = useState<User | null>(
|
||||||
|
mergeUserPreferences(user, settings)
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setUpToDateUser(mergeUserPreferences(user, updatedSettings));
|
||||||
|
}, [user, updatedSettings]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!posthog) return;
|
if (!posthog) return;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user