mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-03-30 04:31:49 +02:00
Fix connected sources display
This commit is contained in:
parent
824677ca75
commit
f1a5460739
@ -40,6 +40,8 @@ import { ResizableSection } from "@/components/resizable/ResizableSection";
|
|||||||
import { DanswerInitializingLoader } from "@/components/DanswerInitializingLoader";
|
import { DanswerInitializingLoader } from "@/components/DanswerInitializingLoader";
|
||||||
import { ChatIntro } from "./ChatIntro";
|
import { ChatIntro } from "./ChatIntro";
|
||||||
import { HEADER_PADDING } from "@/lib/constants";
|
import { HEADER_PADDING } from "@/lib/constants";
|
||||||
|
import { getSourcesForPersona } from "@/lib/sources";
|
||||||
|
import { computeAvailableFilters } from "@/lib/filters";
|
||||||
|
|
||||||
const MAX_INPUT_HEIGHT = 200;
|
const MAX_INPUT_HEIGHT = 200;
|
||||||
|
|
||||||
@ -164,6 +166,12 @@ export const Chat = ({
|
|||||||
}, [defaultSelectedPersonaId]);
|
}, [defaultSelectedPersonaId]);
|
||||||
|
|
||||||
const filterManager = useFilters();
|
const filterManager = useFilters();
|
||||||
|
const [finalAvailableSources, finalAvailableDocumentSets] =
|
||||||
|
computeAvailableFilters({
|
||||||
|
selectedPersona,
|
||||||
|
availableSources,
|
||||||
|
availableDocumentSets,
|
||||||
|
});
|
||||||
|
|
||||||
// state for cancelling streaming
|
// state for cancelling streaming
|
||||||
const [isCancelled, setIsCancelled] = useState(false);
|
const [isCancelled, setIsCancelled] = useState(false);
|
||||||
@ -461,7 +469,7 @@ export const Chat = ({
|
|||||||
!isFetchingChatMessages &&
|
!isFetchingChatMessages &&
|
||||||
!isStreaming && (
|
!isStreaming && (
|
||||||
<ChatIntro
|
<ChatIntro
|
||||||
availableSources={availableSources}
|
availableSources={finalAvailableSources}
|
||||||
availablePersonas={availablePersonas}
|
availablePersonas={availablePersonas}
|
||||||
selectedPersona={selectedPersona}
|
selectedPersona={selectedPersona}
|
||||||
handlePersonaSelect={(persona) => {
|
handlePersonaSelect={(persona) => {
|
||||||
@ -616,8 +624,8 @@ export const Chat = ({
|
|||||||
) : (
|
) : (
|
||||||
<ChatFilters
|
<ChatFilters
|
||||||
{...filterManager}
|
{...filterManager}
|
||||||
existingSources={availableSources}
|
existingSources={finalAvailableSources}
|
||||||
availableDocumentSets={availableDocumentSets}
|
availableDocumentSets={finalAvailableDocumentSets}
|
||||||
availableTags={availableTags}
|
availableTags={availableTags}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { listSourceMetadata } from "@/lib/sources";
|
import { getSourceMetadataForSources, listSourceMetadata } from "@/lib/sources";
|
||||||
import { ValidSources } from "@/lib/types";
|
import { ValidSources } from "@/lib/types";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Persona } from "../admin/personas/interfaces";
|
import { Persona } from "../admin/personas/interfaces";
|
||||||
@ -8,6 +8,7 @@ import { HoverPopup } from "@/components/HoverPopup";
|
|||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FaRobot } from "react-icons/fa";
|
import { FaRobot } from "react-icons/fa";
|
||||||
|
import { SourceMetadata } from "@/lib/search/interfaces";
|
||||||
|
|
||||||
const MAX_PERSONAS_TO_DISPLAY = 4;
|
const MAX_PERSONAS_TO_DISPLAY = 4;
|
||||||
|
|
||||||
@ -90,10 +91,7 @@ export function ChatIntro({
|
|||||||
const [isAllPersonaOptionVisible, setIsAllPersonaOptionVisible] =
|
const [isAllPersonaOptionVisible, setIsAllPersonaOptionVisible] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
|
||||||
const allSources = listSourceMetadata();
|
const availableSourceMetadata = getSourceMetadataForSources(availableSources);
|
||||||
const availableSourceMetadata = allSources.filter((source) =>
|
|
||||||
availableSources.includes(source.internalName)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -133,29 +131,31 @@ export function ChatIntro({
|
|||||||
<p className="font-bold mb-1 mt-4 text-emphasis">
|
<p className="font-bold mb-1 mt-4 text-emphasis">
|
||||||
Knowledge Sets:{" "}
|
Knowledge Sets:{" "}
|
||||||
</p>
|
</p>
|
||||||
{selectedPersona.document_sets.map((documentSet) => (
|
<div className="flex flex-wrap gap-x-2">
|
||||||
<div key={documentSet.id} className="w-fit">
|
{selectedPersona.document_sets.map((documentSet) => (
|
||||||
<HoverPopup
|
<div key={documentSet.id} className="w-fit">
|
||||||
mainContent={
|
<HoverPopup
|
||||||
<span className="flex w-fit p-1 rounded border border-border text-xs font-medium cursor-default">
|
mainContent={
|
||||||
<div className="mr-1 my-auto">
|
<span className="flex w-fit p-1 rounded border border-border text-xs font-medium cursor-default">
|
||||||
<FiBookmark />
|
<div className="mr-1 my-auto">
|
||||||
|
<FiBookmark />
|
||||||
|
</div>
|
||||||
|
{documentSet.name}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
popupContent={
|
||||||
|
<div className="flex py-1 w-96">
|
||||||
|
<FiInfo className="my-auto mr-2" />
|
||||||
|
<div className="text-sm">
|
||||||
|
{documentSet.description}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{documentSet.name}
|
}
|
||||||
</span>
|
direction="top"
|
||||||
}
|
/>
|
||||||
popupContent={
|
</div>
|
||||||
<div className="flex py-1 w-96">
|
))}
|
||||||
<FiInfo className="my-auto mr-2" />
|
</div>
|
||||||
<div className="text-sm">
|
|
||||||
{documentSet.description}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
direction="top"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{availableSources.length > 0 && (
|
{availableSources.length > 0 && (
|
||||||
|
@ -22,6 +22,7 @@ import { useFilters, useObjectState } from "@/lib/hooks";
|
|||||||
import { questionValidationStreamed } from "@/lib/search/streamingQuestionValidation";
|
import { questionValidationStreamed } from "@/lib/search/streamingQuestionValidation";
|
||||||
import { Persona } from "@/app/admin/personas/interfaces";
|
import { Persona } from "@/app/admin/personas/interfaces";
|
||||||
import { PersonaSelector } from "./PersonaSelector";
|
import { PersonaSelector } from "./PersonaSelector";
|
||||||
|
import { computeAvailableFilters } from "@/lib/filters";
|
||||||
|
|
||||||
const SEARCH_DEFAULT_OVERRIDES_START: SearchDefaultOverrides = {
|
const SEARCH_DEFAULT_OVERRIDES_START: SearchDefaultOverrides = {
|
||||||
forceDisplayQA: false,
|
forceDisplayQA: false,
|
||||||
@ -61,9 +62,6 @@ export const SearchSection = ({
|
|||||||
const [validQuestionResponse, setValidQuestionResponse] =
|
const [validQuestionResponse, setValidQuestionResponse] =
|
||||||
useObjectState<ValidQuestionResponse>(VALID_QUESTION_RESPONSE_DEFAULT);
|
useObjectState<ValidQuestionResponse>(VALID_QUESTION_RESPONSE_DEFAULT);
|
||||||
|
|
||||||
// Filters
|
|
||||||
const filterManager = useFilters();
|
|
||||||
|
|
||||||
// Search Type
|
// Search Type
|
||||||
const [selectedSearchType, setSelectedSearchType] =
|
const [selectedSearchType, setSelectedSearchType] =
|
||||||
useState<SearchType>(defaultSearchType);
|
useState<SearchType>(defaultSearchType);
|
||||||
@ -72,6 +70,18 @@ export const SearchSection = ({
|
|||||||
personas[0]?.id || 0
|
personas[0]?.id || 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
const filterManager = useFilters();
|
||||||
|
const availableSources = connectors.map((connector) => connector.source);
|
||||||
|
const [finalAvailableSources, finalAvailableDocumentSets] =
|
||||||
|
computeAvailableFilters({
|
||||||
|
selectedPersona: personas.find(
|
||||||
|
(persona) => persona.id === selectedPersona
|
||||||
|
),
|
||||||
|
availableSources: availableSources,
|
||||||
|
availableDocumentSets: documentSets,
|
||||||
|
});
|
||||||
|
|
||||||
// Overrides for default behavior that only last a single query
|
// Overrides for default behavior that only last a single query
|
||||||
const [defaultOverrides, setDefaultOverrides] =
|
const [defaultOverrides, setDefaultOverrides] =
|
||||||
useState<SearchDefaultOverrides>(SEARCH_DEFAULT_OVERRIDES_START);
|
useState<SearchDefaultOverrides>(SEARCH_DEFAULT_OVERRIDES_START);
|
||||||
@ -207,8 +217,8 @@ export const SearchSection = ({
|
|||||||
{(connectors.length > 0 || documentSets.length > 0) && (
|
{(connectors.length > 0 || documentSets.length > 0) && (
|
||||||
<SourceSelector
|
<SourceSelector
|
||||||
{...filterManager}
|
{...filterManager}
|
||||||
availableDocumentSets={documentSets}
|
availableDocumentSets={finalAvailableDocumentSets}
|
||||||
existingSources={connectors.map((connector) => connector.source)}
|
existingSources={finalAvailableSources}
|
||||||
availableTags={tags}
|
availableTags={tags}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
32
web/src/lib/filters.ts
Normal file
32
web/src/lib/filters.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { Persona } from "@/app/admin/personas/interfaces";
|
||||||
|
import { DocumentSet, ValidSources } from "./types";
|
||||||
|
import { getSourcesForPersona } from "./sources";
|
||||||
|
|
||||||
|
export function computeAvailableFilters({
|
||||||
|
selectedPersona,
|
||||||
|
availableSources,
|
||||||
|
availableDocumentSets,
|
||||||
|
}: {
|
||||||
|
selectedPersona: Persona | undefined | null;
|
||||||
|
availableSources: ValidSources[];
|
||||||
|
availableDocumentSets: DocumentSet[];
|
||||||
|
}): [ValidSources[], DocumentSet[]] {
|
||||||
|
const finalAvailableSources =
|
||||||
|
selectedPersona && selectedPersona.document_sets.length
|
||||||
|
? getSourcesForPersona(selectedPersona)
|
||||||
|
: availableSources;
|
||||||
|
|
||||||
|
// only display document sets that are available to the persona
|
||||||
|
// in filters
|
||||||
|
const personaDocumentSetIds =
|
||||||
|
selectedPersona && selectedPersona.document_sets.length
|
||||||
|
? selectedPersona.document_sets.map((documentSet) => documentSet.id)
|
||||||
|
: null;
|
||||||
|
const finalAvailableDocumentSets = personaDocumentSetIds
|
||||||
|
? availableDocumentSets.filter((documentSet) =>
|
||||||
|
personaDocumentSetIds.includes(documentSet.id)
|
||||||
|
)
|
||||||
|
: availableDocumentSets;
|
||||||
|
|
||||||
|
return [finalAvailableSources, finalAvailableDocumentSets];
|
||||||
|
}
|
@ -26,6 +26,7 @@ import {
|
|||||||
} from "@/components/icons/icons";
|
} from "@/components/icons/icons";
|
||||||
import { ValidSources } from "./types";
|
import { ValidSources } from "./types";
|
||||||
import { SourceCategory, SourceMetadata } from "./search/interfaces";
|
import { SourceCategory, SourceMetadata } from "./search/interfaces";
|
||||||
|
import { Persona } from "@/app/admin/personas/interfaces";
|
||||||
|
|
||||||
interface PartialSourceMetadata {
|
interface PartialSourceMetadata {
|
||||||
icon: React.FC<{ size?: number; className?: string }>;
|
icon: React.FC<{ size?: number; className?: string }>;
|
||||||
@ -186,3 +187,19 @@ export function listSourceMetadata(): SourceMetadata[] {
|
|||||||
export function getSourceDisplayName(sourceType: ValidSources): string | null {
|
export function getSourceDisplayName(sourceType: ValidSources): string | null {
|
||||||
return getSourceMetadata(sourceType).displayName;
|
return getSourceMetadata(sourceType).displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSourceMetadataForSources(sources: ValidSources[]) {
|
||||||
|
return sources.map((source) => getSourceMetadata(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSourcesForPersona(persona: Persona): ValidSources[] {
|
||||||
|
const personaSources: ValidSources[] = [];
|
||||||
|
persona.document_sets.forEach((documentSet) => {
|
||||||
|
documentSet.cc_pair_descriptors.forEach((ccPair) => {
|
||||||
|
if (!personaSources.includes(ccPair.connector.source)) {
|
||||||
|
personaSources.push(ccPair.connector.source);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return personaSources;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user