From 32359d2dff031b1e2a19c4406be879bdf7a817f6 Mon Sep 17 00:00:00 2001 From: pablodanswer Date: Tue, 3 Sep 2024 12:24:50 -0700 Subject: [PATCH] Add user dropdown seed-able list (#2308) * add user dropdown seedable list * minor cleanup * fix build issue * minor type update * remove log * quick update to divider logic (squash) * tiny icon updates --- .../server/enterprise_settings/models.py | 12 +++++ web/src/app/admin/settings/interfaces.ts | 9 ++++ web/src/app/chat/message/Messages.tsx | 3 +- .../admin/whitelabeling/WhitelabelingForm.tsx | 1 + web/src/components/UserDropdown.tsx | 35 +++++++++++++-- .../admin/connectors/AdminSidebar.tsx | 4 +- web/src/components/icons/DynamicFaIcon.tsx | 44 +++++++++++++++++++ 7 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 web/src/components/icons/DynamicFaIcon.tsx diff --git a/backend/ee/danswer/server/enterprise_settings/models.py b/backend/ee/danswer/server/enterprise_settings/models.py index b4cf91a4a3e..b5f8165f541 100644 --- a/backend/ee/danswer/server/enterprise_settings/models.py +++ b/backend/ee/danswer/server/enterprise_settings/models.py @@ -1,4 +1,13 @@ +from typing import List + from pydantic import BaseModel +from pydantic import Field + + +class NavigationItem(BaseModel): + link: str + icon: str + title: str class EnterpriseSettings(BaseModel): @@ -10,6 +19,9 @@ class EnterpriseSettings(BaseModel): use_custom_logo: bool = False use_custom_logotype: bool = False + # custom navigation + custom_nav_items: List[NavigationItem] = Field(default_factory=list) + # custom Chat components two_lines_for_chat_header: bool | None = None custom_lower_disclaimer_content: str | None = None diff --git a/web/src/app/admin/settings/interfaces.ts b/web/src/app/admin/settings/interfaces.ts index 5c3f7a72564..1986da9ab53 100644 --- a/web/src/app/admin/settings/interfaces.ts +++ b/web/src/app/admin/settings/interfaces.ts @@ -15,11 +15,20 @@ export interface Notification { first_shown: string; } +export interface NavigationItem { + link: string; + icon: string; + title: string; +} + export interface EnterpriseSettings { application_name: string | null; use_custom_logo: boolean; use_custom_logotype: boolean; + // custom navigation + custom_nav_items: NavigationItem[]; + // custom Chat components custom_lower_disclaimer_content: string | null; custom_header_content: string | null; diff --git a/web/src/app/chat/message/Messages.tsx b/web/src/app/chat/message/Messages.tsx index ff177c6a6ee..8cb51fee144 100644 --- a/web/src/app/chat/message/Messages.tsx +++ b/web/src/app/chat/message/Messages.tsx @@ -64,8 +64,6 @@ import { SettingsContext } from "@/components/settings/SettingsProvider"; import GeneratingImageDisplay from "../tools/GeneratingImageDisplay"; import RegenerateOption from "../RegenerateOption"; import { LlmOverride } from "@/lib/hooks"; -import ExceptionTraceModal from "@/components/modals/ExceptionTraceModal"; -import { EmphasizedClickable } from "@/components/BasicClickable"; import { ContinueGenerating } from "./ContinueMessage"; const TOOLS_WITH_CUSTOM_HANDLING = [ @@ -742,6 +740,7 @@ export const HumanMessage = ({
+
{isEditing ? ( diff --git a/web/src/app/ee/admin/whitelabeling/WhitelabelingForm.tsx b/web/src/app/ee/admin/whitelabeling/WhitelabelingForm.tsx index 9195d9362d0..814e37058aa 100644 --- a/web/src/app/ee/admin/whitelabeling/WhitelabelingForm.tsx +++ b/web/src/app/ee/admin/whitelabeling/WhitelabelingForm.tsx @@ -64,6 +64,7 @@ export function WhitelabelingForm() { custom_popup_content: enterpriseSettings?.custom_popup_content || "", custom_lower_disclaimer_content: enterpriseSettings?.custom_lower_disclaimer_content || "", + custom_nav_items: enterpriseSettings?.custom_nav_items || [], }} validationSchema={Yup.object().shape({ application_name: Yup.string().nullable(), diff --git a/web/src/components/UserDropdown.tsx b/web/src/components/UserDropdown.tsx index 22baa391d9c..3bc18b5241b 100644 --- a/web/src/components/UserDropdown.tsx +++ b/web/src/components/UserDropdown.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useRef, useContext } from "react"; +import { useState, useRef, useContext, useEffect } from "react"; import { FiLogOut } from "react-icons/fi"; import Link from "next/link"; import { useRouter } from "next/navigation"; @@ -15,6 +15,8 @@ import { UsersIcon, } from "./icons/icons"; import { pageType } from "@/app/chat/sessionSidebar/types"; +import { NavigationItem } from "@/app/admin/settings/interfaces"; +import DynamicFaIcon, { preloadIcons } from "./icons/DynamicFaIcon"; interface DropdownOptionProps { href?: string; @@ -55,6 +57,14 @@ export function UserDropdown({ const router = useRouter(); const combinedSettings = useContext(SettingsContext); + const customNavItems: NavigationItem[] = + combinedSettings?.enterpriseSettings?.custom_nav_items || []; + + useEffect(() => { + const iconNames = customNavItems.map((item) => item.icon); + preloadIcons(iconNames); + }, [customNavItems]); + if (!combinedSettings) { return null; } @@ -126,6 +136,20 @@ export function UserDropdown({ overscroll-contain `} > + {customNavItems.map((item, i) => ( + + } + label={item.title} + /> + ))} + {showAdminPanel ? ( - )} + {showLogout && + (showCuratorPanel || + showAdminPanel || + customNavItems.length > 0) && ( +
+ )} {showLogout && (
-