mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-27 20:38:32 +02:00
Small fixes + adding 'Powered by Danswer'
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
from fastapi import Response
|
||||||
from fastapi import UploadFile
|
from fastapi import UploadFile
|
||||||
from fastapi.responses import StreamingResponse
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from danswer.auth.users import current_admin_user
|
from danswer.auth.users import current_admin_user
|
||||||
@@ -43,7 +43,7 @@ def upload_logo(
|
|||||||
db_session: Session = Depends(get_session),
|
db_session: Session = Depends(get_session),
|
||||||
_: User | None = Depends(current_admin_user),
|
_: User | None = Depends(current_admin_user),
|
||||||
) -> None:
|
) -> None:
|
||||||
if (
|
if not file.filename or (
|
||||||
not file.filename.endswith(".png")
|
not file.filename.endswith(".png")
|
||||||
and not file.filename.endswith(".jpg")
|
and not file.filename.endswith(".jpg")
|
||||||
and not file.filename.endswith(".jpeg")
|
and not file.filename.endswith(".jpeg")
|
||||||
@@ -59,7 +59,9 @@ def upload_logo(
|
|||||||
|
|
||||||
|
|
||||||
@basic_router.get("/logo")
|
@basic_router.get("/logo")
|
||||||
def fetch_logo(db_session: Session = Depends(get_session)) -> StreamingResponse:
|
def fetch_logo(db_session: Session = Depends(get_session)) -> Response:
|
||||||
file_store = get_default_file_store(db_session)
|
file_store = get_default_file_store(db_session)
|
||||||
file_io = file_store.read_file(_LOGO_FILENAME, mode="b")
|
file_io = file_store.read_file(_LOGO_FILENAME, mode="b")
|
||||||
return StreamingResponse(content=file_io, media_type="image/jpeg")
|
# NOTE: specifying "image/jpeg" here, but it still works for pngs
|
||||||
|
# TODO: do this properly
|
||||||
|
return Response(content=file_io.read(), media_type="image/jpeg")
|
||||||
|
@@ -4,10 +4,6 @@ export interface Settings {
|
|||||||
default_page: "search" | "chat";
|
default_page: "search" | "chat";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ColorConfig {
|
|
||||||
primary: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EnterpriseSettings {
|
export interface EnterpriseSettings {
|
||||||
application_name: string | null;
|
application_name: string | null;
|
||||||
use_custom_logo: boolean;
|
use_custom_logo: boolean;
|
||||||
@@ -16,7 +12,6 @@ export interface EnterpriseSettings {
|
|||||||
custom_header_content: string | null;
|
custom_header_content: string | null;
|
||||||
custom_popup_header: string | null;
|
custom_popup_header: string | null;
|
||||||
custom_popup_content: string | null;
|
custom_popup_content: string | null;
|
||||||
color_config: ColorConfig | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CombinedSettings {
|
export interface CombinedSettings {
|
||||||
|
@@ -50,14 +50,10 @@ export function WhitelabelingForm() {
|
|||||||
initialValues={{
|
initialValues={{
|
||||||
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,
|
||||||
color_config: enterpriseSettings?.color_config || null,
|
|
||||||
}}
|
}}
|
||||||
validationSchema={Yup.object().shape({
|
validationSchema={Yup.object().shape({
|
||||||
application_name: Yup.string(),
|
application_name: Yup.string(),
|
||||||
use_custom_logo: Yup.boolean().required(),
|
use_custom_logo: Yup.boolean().required(),
|
||||||
color_config: Yup.object().shape({
|
|
||||||
primary: Yup.string(),
|
|
||||||
}),
|
|
||||||
})}
|
})}
|
||||||
onSubmit={async (values, formikHelpers) => {
|
onSubmit={async (values, formikHelpers) => {
|
||||||
formikHelpers.setSubmitting(true);
|
formikHelpers.setSubmitting(true);
|
||||||
@@ -67,6 +63,7 @@ export function WhitelabelingForm() {
|
|||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", selectedFile);
|
formData.append("file", selectedFile);
|
||||||
|
setSelectedFile(null);
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
"/api/admin/enterprise-settings/logo",
|
"/api/admin/enterprise-settings/logo",
|
||||||
{
|
{
|
||||||
@@ -80,7 +77,6 @@ export function WhitelabelingForm() {
|
|||||||
formikHelpers.setSubmitting(false);
|
formikHelpers.setSubmitting(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSelectedFile(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
formikHelpers.setValues(values);
|
formikHelpers.setValues(values);
|
||||||
@@ -103,7 +99,7 @@ export function WhitelabelingForm() {
|
|||||||
<div className="mt-3">
|
<div className="mt-3">
|
||||||
<SubLabel>Current Custom Logo: </SubLabel>
|
<SubLabel>Current Custom Logo: </SubLabel>
|
||||||
<img
|
<img
|
||||||
src="/api/enterprise-settings/logo"
|
src={"/api/enterprise-settings/logo?u=" + Date.now()}
|
||||||
alt="logo"
|
alt="logo"
|
||||||
style={{ objectFit: "contain" }}
|
style={{ objectFit: "contain" }}
|
||||||
className="w-32 h-32 mb-10 mt-4"
|
className="w-32 h-32 mb-10 mt-4"
|
||||||
|
@@ -32,11 +32,11 @@ export function Logo({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ height, width }} className={`relative ${className}`}>
|
<div style={{ height, width }} className={`relative ${className}`}>
|
||||||
<Image
|
{/* TODO: figure out how to use Next Image here */}
|
||||||
|
<img
|
||||||
src="/api/enterprise-settings/logo"
|
src="/api/enterprise-settings/logo"
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
fill
|
style={{ objectFit: "contain", height, width }}
|
||||||
style={{ objectFit: "contain" }}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -12,6 +12,10 @@ import { SettingsContext } from "../settings/SettingsProvider";
|
|||||||
import { UserDropdown } from "../UserDropdown";
|
import { UserDropdown } from "../UserDropdown";
|
||||||
import { Logo } from "../Logo";
|
import { Logo } from "../Logo";
|
||||||
|
|
||||||
|
function HeaderTitle({ children }: { children: JSX.Element | string }) {
|
||||||
|
return <h1 className="flex text-2xl text-strong font-bold">{children}</h1>;
|
||||||
|
}
|
||||||
|
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
user: User | null;
|
user: User | null;
|
||||||
}
|
}
|
||||||
@@ -28,19 +32,29 @@ export function Header({ user }: HeaderProps) {
|
|||||||
<HeaderWrapper>
|
<HeaderWrapper>
|
||||||
<div className="flex h-full">
|
<div className="flex h-full">
|
||||||
<Link
|
<Link
|
||||||
className="py-4"
|
className="py-3 flex flex-col"
|
||||||
href={
|
href={
|
||||||
settings && settings.default_page === "chat" ? "/chat" : "/search"
|
settings && settings.default_page === "chat" ? "/chat" : "/search"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex my-auto">
|
||||||
<div className="mr-1">
|
<div className="mr-1 my-auto">
|
||||||
<Logo />
|
<Logo />
|
||||||
</div>
|
</div>
|
||||||
<h1 className="flex text-2xl text-strong font-bold my-auto">
|
<div className="my-auto">
|
||||||
{(enterpriseSettings && enterpriseSettings.application_name) ||
|
{enterpriseSettings && enterpriseSettings.application_name ? (
|
||||||
"Danswer"}
|
<div>
|
||||||
</h1>
|
<HeaderTitle>
|
||||||
|
{enterpriseSettings.application_name}
|
||||||
|
</HeaderTitle>
|
||||||
|
<p className="text-xs text-subtle -mt-1.5">
|
||||||
|
Powered by Danswer
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<HeaderTitle>Danswer</HeaderTitle>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user