mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-05-07 10:20:32 +02:00
Linting (#2704)
* effect cleanup * remove unused imports * remove unne * remove unnecessary packages * k * temp * minor
This commit is contained in:
parent
150dcc2883
commit
1900a390d8
@ -283,6 +283,7 @@ class DefaultMultiLLM(LLM):
|
|||||||
_convert_message_to_dict(msg) if isinstance(msg, BaseMessage) else msg
|
_convert_message_to_dict(msg) if isinstance(msg, BaseMessage) else msg
|
||||||
for msg in prompt
|
for msg in prompt
|
||||||
]
|
]
|
||||||
|
|
||||||
elif isinstance(prompt, str):
|
elif isinstance(prompt, str):
|
||||||
prompt = [_convert_message_to_dict(HumanMessage(content=prompt))]
|
prompt = [_convert_message_to_dict(HumanMessage(content=prompt))]
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "next/core-web-vitals"
|
"extends": "next/core-web-vitals",
|
||||||
|
"rules": {
|
||||||
|
"@next/next/no-img-element": "off"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { SourceCategory, SourceMetadata } from "@/lib/search/interfaces";
|
|||||||
import { listSourceMetadata } from "@/lib/sources";
|
import { listSourceMetadata } from "@/lib/sources";
|
||||||
import { Title, Text, Button } from "@tremor/react";
|
import { Title, Text, Button } from "@tremor/react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
|
||||||
function SourceTile({
|
function SourceTile({
|
||||||
sourceMetadata,
|
sourceMetadata,
|
||||||
@ -49,7 +49,8 @@ export default function Page() {
|
|||||||
searchInputRef.current.focus();
|
searchInputRef.current.focus();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
const filterSources = (sources: SourceMetadata[]) => {
|
const filterSources = useCallback(
|
||||||
|
(sources: SourceMetadata[]) => {
|
||||||
if (!searchTerm) return sources;
|
if (!searchTerm) return sources;
|
||||||
const lowerSearchTerm = searchTerm.toLowerCase();
|
const lowerSearchTerm = searchTerm.toLowerCase();
|
||||||
return sources.filter(
|
return sources.filter(
|
||||||
@ -57,7 +58,9 @@ export default function Page() {
|
|||||||
source.displayName.toLowerCase().includes(lowerSearchTerm) ||
|
source.displayName.toLowerCase().includes(lowerSearchTerm) ||
|
||||||
source.category.toLowerCase().includes(lowerSearchTerm)
|
source.category.toLowerCase().includes(lowerSearchTerm)
|
||||||
);
|
);
|
||||||
};
|
},
|
||||||
|
[searchTerm]
|
||||||
|
);
|
||||||
|
|
||||||
const categorizedSources = useMemo(() => {
|
const categorizedSources = useMemo(() => {
|
||||||
const filtered = filterSources(sources);
|
const filtered = filterSources(sources);
|
||||||
|
@ -132,7 +132,7 @@ export function AssistantEditor({
|
|||||||
if (defaultIconShape === null) {
|
if (defaultIconShape === null) {
|
||||||
setDefaultIconShape(generateRandomIconShape().encodedGrid);
|
setDefaultIconShape(generateRandomIconShape().encodedGrid);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [defaultIconShape]);
|
||||||
|
|
||||||
const [isIconDropdownOpen, setIsIconDropdownOpen] = useState(false);
|
const [isIconDropdownOpen, setIsIconDropdownOpen] = useState(false);
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ export function AssistantEditor({
|
|||||||
existingPersona.num_chunks === 0
|
existingPersona.num_chunks === 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [isUpdate, existingPrompt]);
|
}, [isUpdate, existingPrompt, existingPersona?.num_chunks]);
|
||||||
|
|
||||||
const defaultProvider = llmProviders.find(
|
const defaultProvider = llmProviders.find(
|
||||||
(llmProvider) => llmProvider.is_default_provider
|
(llmProvider) => llmProvider.is_default_provider
|
||||||
@ -888,7 +888,7 @@ export function AssistantEditor({
|
|||||||
values.document_set_ids.indexOf(
|
values.document_set_ids.indexOf(
|
||||||
documentSet.id
|
documentSet.id
|
||||||
);
|
);
|
||||||
let isSelected = ind !== -1;
|
const isSelected = ind !== -1;
|
||||||
return (
|
return (
|
||||||
<DocumentSetSelectable
|
<DocumentSetSelectable
|
||||||
key={documentSet.id}
|
key={documentSet.id}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { Button } from "@tremor/react";
|
|
||||||
import React, { ReactNode, useState } from "react";
|
import React, { ReactNode, useState } from "react";
|
||||||
import { FiSettings } from "react-icons/fi";
|
import { FiSettings } from "react-icons/fi";
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { Persona } from "./interfaces";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { CustomCheckbox } from "@/components/CustomCheckbox";
|
import { CustomCheckbox } from "@/components/CustomCheckbox";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { useState, useMemo, useEffect } from "react";
|
import { useState, useMemo } from "react";
|
||||||
import { UniqueIdentifier } from "@dnd-kit/core";
|
import { UniqueIdentifier } from "@dnd-kit/core";
|
||||||
import { DraggableTable } from "@/components/table/DraggableTable";
|
import { DraggableTable } from "@/components/table/DraggableTable";
|
||||||
import {
|
import {
|
||||||
@ -15,8 +15,6 @@ import {
|
|||||||
} from "./lib";
|
} from "./lib";
|
||||||
import { FiEdit2 } from "react-icons/fi";
|
import { FiEdit2 } from "react-icons/fi";
|
||||||
import { TrashIcon } from "@/components/icons/icons";
|
import { TrashIcon } from "@/components/icons/icons";
|
||||||
import { getCurrentUser } from "@/lib/user";
|
|
||||||
import { UserRole, User } from "@/lib/types";
|
|
||||||
import { useUser } from "@/components/user/UserProvider";
|
import { useUser } from "@/components/user/UserProvider";
|
||||||
|
|
||||||
function PersonaTypeDisplay({ persona }: { persona: Persona }) {
|
function PersonaTypeDisplay({ persona }: { persona: Persona }) {
|
||||||
@ -51,9 +49,9 @@ export function PersonasTable({
|
|||||||
|
|
||||||
const { isLoadingUser, isAdmin } = useUser();
|
const { isLoadingUser, isAdmin } = useUser();
|
||||||
|
|
||||||
const editablePersonaIds = new Set(
|
const editablePersonaIds = useMemo(() => {
|
||||||
editablePersonas.map((p) => p.id.toString())
|
return new Set(editablePersonas.map((p) => p.id.toString()));
|
||||||
);
|
}, [editablePersonas]);
|
||||||
|
|
||||||
const sortedPersonas = useMemo(() => {
|
const sortedPersonas = useMemo(() => {
|
||||||
const editable = editablePersonas.sort(personaComparator);
|
const editable = editablePersonas.sort(personaComparator);
|
||||||
|
@ -276,7 +276,7 @@ export function buildFinalPrompt(
|
|||||||
taskPrompt: string,
|
taskPrompt: string,
|
||||||
retrievalDisabled: boolean
|
retrievalDisabled: boolean
|
||||||
) {
|
) {
|
||||||
let queryString = Object.entries({
|
const queryString = Object.entries({
|
||||||
system_prompt: systemPrompt,
|
system_prompt: systemPrompt,
|
||||||
task_prompt: taskPrompt,
|
task_prompt: taskPrompt,
|
||||||
retrieval_disabled: retrievalDisabled,
|
retrieval_disabled: retrievalDisabled,
|
||||||
|
@ -5,7 +5,7 @@ import { Divider, Text, Title } from "@tremor/react";
|
|||||||
import { fetchSS } from "@/lib/utilsSS";
|
import { fetchSS } from "@/lib/utilsSS";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { Persona } from "./interfaces";
|
import { Persona } from "./interfaces";
|
||||||
import { AssistantsIcon, RobotIcon } from "@/components/icons/icons";
|
import { AssistantsIcon } from "@/components/icons/icons";
|
||||||
import { AdminPageTitle } from "@/components/admin/Title";
|
import { AdminPageTitle } from "@/components/admin/Title";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
|
@ -20,7 +20,6 @@ import { Button, Card, Divider } from "@tremor/react";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { Persona } from "../assistants/interfaces";
|
import { Persona } from "../assistants/interfaces";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import MultiSelectDropdown from "@/components/MultiSelectDropdown";
|
|
||||||
import { AdvancedOptionsToggle } from "@/components/AdvancedOptionsToggle";
|
import { AdvancedOptionsToggle } from "@/components/AdvancedOptionsToggle";
|
||||||
import { DocumentSetSelectable } from "@/components/documentSet/DocumentSetSelectable";
|
import { DocumentSetSelectable } from "@/components/documentSet/DocumentSetSelectable";
|
||||||
import CollapsibleSection from "../assistants/CollapsibleSection";
|
import CollapsibleSection from "../assistants/CollapsibleSection";
|
||||||
@ -229,7 +228,7 @@ export const SlackBotCreationForm = ({
|
|||||||
const ind = values.document_sets.indexOf(
|
const ind = values.document_sets.indexOf(
|
||||||
documentSet.id
|
documentSet.id
|
||||||
);
|
);
|
||||||
let isSelected = ind !== -1;
|
const isSelected = ind !== -1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DocumentSetSelectable
|
<DocumentSetSelectable
|
||||||
|
@ -3,9 +3,8 @@ import { CPUIcon } from "@/components/icons/icons";
|
|||||||
import { SlackBotCreationForm } from "../SlackBotConfigCreationForm";
|
import { SlackBotCreationForm } from "../SlackBotConfigCreationForm";
|
||||||
import { fetchSS } from "@/lib/utilsSS";
|
import { fetchSS } from "@/lib/utilsSS";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { DocumentSet, StandardAnswerCategory } from "@/lib/types";
|
import { DocumentSet } from "@/lib/types";
|
||||||
import { BackButton } from "@/components/BackButton";
|
import { BackButton } from "@/components/BackButton";
|
||||||
import { Text } from "@tremor/react";
|
|
||||||
import {
|
import {
|
||||||
FetchAssistantsResponse,
|
FetchAssistantsResponse,
|
||||||
fetchAssistantsSS,
|
fetchAssistantsSS,
|
||||||
|
@ -2,12 +2,7 @@
|
|||||||
|
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import { PageSelector } from "@/components/PageSelector";
|
import { PageSelector } from "@/components/PageSelector";
|
||||||
import {
|
import { EditIcon, SlackIcon, TrashIcon } from "@/components/icons/icons";
|
||||||
CPUIcon,
|
|
||||||
EditIcon,
|
|
||||||
SlackIcon,
|
|
||||||
TrashIcon,
|
|
||||||
} from "@/components/icons/icons";
|
|
||||||
import { SlackBotConfig } from "@/lib/types";
|
import { SlackBotConfig } from "@/lib/types";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useSlackBotConfigs, useSlackBotTokens } from "./hooks";
|
import { useSlackBotConfigs, useSlackBotTokens } from "./hooks";
|
||||||
@ -26,12 +21,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import {
|
import { FiArrowUpRight, FiChevronDown, FiChevronUp } from "react-icons/fi";
|
||||||
FiArrowUpRight,
|
|
||||||
FiChevronDown,
|
|
||||||
FiChevronUp,
|
|
||||||
FiSlack,
|
|
||||||
} from "react-icons/fi";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { InstantSSRAutoRefresh } from "@/components/SSRAutoRefresh";
|
import { InstantSSRAutoRefresh } from "@/components/SSRAutoRefresh";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
@ -223,6 +213,7 @@ const Main = () => {
|
|||||||
className="text-blue-500"
|
className="text-blue-500"
|
||||||
href="https://docs.danswer.dev/slack_bot_setup"
|
href="https://docs.danswer.dev/slack_bot_setup"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
guide{" "}
|
guide{" "}
|
||||||
</a>
|
</a>
|
||||||
|
@ -220,6 +220,7 @@ export function CustomLLMProviderUpdateForm({
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://docs.litellm.ai/docs/providers"
|
href="https://docs.litellm.ai/docs/providers"
|
||||||
className="text-link"
|
className="text-link"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
https://docs.litellm.ai/docs/providers
|
https://docs.litellm.ai/docs/providers
|
||||||
</a>
|
</a>
|
||||||
@ -373,6 +374,7 @@ export function CustomLLMProviderUpdateForm({
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://models.litellm.ai/"
|
href="https://models.litellm.ai/"
|
||||||
className="text-link"
|
className="text-link"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
here
|
here
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { AdminPageTitle } from "@/components/admin/Title";
|
import { AdminPageTitle } from "@/components/admin/Title";
|
||||||
import { FiCpu } from "react-icons/fi";
|
|
||||||
import { LLMConfiguration } from "./LLMConfiguration";
|
import { LLMConfiguration } from "./LLMConfiguration";
|
||||||
import { CpuIcon } from "@/components/icons/icons";
|
import { CpuIcon } from "@/components/icons/icons";
|
||||||
|
|
||||||
|
@ -63,13 +63,16 @@ export default function UpgradingPage({
|
|||||||
}
|
}
|
||||||
setIsCancelling(false);
|
setIsCancelling(false);
|
||||||
};
|
};
|
||||||
const statusOrder: Record<ValidStatuses, number> = {
|
const statusOrder: Record<ValidStatuses, number> = useMemo(
|
||||||
|
() => ({
|
||||||
failed: 0,
|
failed: 0,
|
||||||
completed_with_errors: 1,
|
completed_with_errors: 1,
|
||||||
not_started: 2,
|
not_started: 2,
|
||||||
in_progress: 3,
|
in_progress: 3,
|
||||||
success: 4,
|
success: 4,
|
||||||
};
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const sortedReindexingProgress = useMemo(() => {
|
const sortedReindexingProgress = useMemo(() => {
|
||||||
return [...(ongoingReIndexingStatus || [])].sort((a, b) => {
|
return [...(ongoingReIndexingStatus || [])].sort((a, b) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useRef } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableHead,
|
TableHead,
|
||||||
@ -10,9 +10,8 @@ import {
|
|||||||
TableCell,
|
TableCell,
|
||||||
Text,
|
Text,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { CCPairFullInfo } from "./types";
|
import { CCPairFullInfo, PaginatedIndexAttempts } from "./types";
|
||||||
import { IndexAttemptStatus } from "@/components/Status";
|
import { IndexAttemptStatus } from "@/components/Status";
|
||||||
import { useState } from "react";
|
|
||||||
import { PageSelector } from "@/components/PageSelector";
|
import { PageSelector } from "@/components/PageSelector";
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import { buildCCPairInfoUrl } from "./lib";
|
import { buildCCPairInfoUrl } from "./lib";
|
||||||
@ -22,7 +21,6 @@ import { ErrorCallout } from "@/components/ErrorCallout";
|
|||||||
import { InfoIcon, SearchIcon } from "@/components/icons/icons";
|
import { InfoIcon, SearchIcon } from "@/components/icons/icons";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import ExceptionTraceModal from "@/components/modals/ExceptionTraceModal";
|
import ExceptionTraceModal from "@/components/modals/ExceptionTraceModal";
|
||||||
import { PaginatedIndexAttempts } from "./types";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { Tooltip } from "@/components/tooltip/Tooltip";
|
import { Tooltip } from "@/components/tooltip/Tooltip";
|
||||||
|
|
||||||
@ -61,11 +59,16 @@ export function IndexingAttemptsTable({ ccPair }: { ccPair: CCPairFullInfo }) {
|
|||||||
// we use it to avoid duplicate requests
|
// we use it to avoid duplicate requests
|
||||||
const ongoingRequestsRef = useRef<Set<number>>(new Set());
|
const ongoingRequestsRef = useRef<Set<number>>(new Set());
|
||||||
|
|
||||||
const batchRetrievalUrlBuilder = (batchNum: number) =>
|
const batchRetrievalUrlBuilder = useCallback(
|
||||||
`${buildCCPairInfoUrl(ccPair.id)}/index-attempts?page=${batchNum}&page_size=${BATCH_SIZE * NUM_IN_PAGE}`;
|
(batchNum: number) => {
|
||||||
|
return `${buildCCPairInfoUrl(ccPair.id)}/index-attempts?page=${batchNum}&page_size=${BATCH_SIZE * NUM_IN_PAGE}`;
|
||||||
|
},
|
||||||
|
[ccPair.id]
|
||||||
|
);
|
||||||
|
|
||||||
// This fetches and caches the data for a given batch number
|
// This fetches and caches the data for a given batch number
|
||||||
const fetchBatchData = async (batchNum: number) => {
|
const fetchBatchData = useCallback(
|
||||||
|
async (batchNum: number) => {
|
||||||
if (ongoingRequestsRef.current.has(batchNum)) return;
|
if (ongoingRequestsRef.current.has(batchNum)) return;
|
||||||
ongoingRequestsRef.current.add(batchNum);
|
ongoingRequestsRef.current.add(batchNum);
|
||||||
|
|
||||||
@ -101,7 +104,14 @@ export function IndexingAttemptsTable({ ccPair }: { ccPair: CCPairFullInfo }) {
|
|||||||
} finally {
|
} finally {
|
||||||
ongoingRequestsRef.current.delete(batchNum);
|
ongoingRequestsRef.current.delete(batchNum);
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[
|
||||||
|
ongoingRequestsRef,
|
||||||
|
setCachedBatches,
|
||||||
|
setCurrentPageError,
|
||||||
|
batchRetrievalUrlBuilder,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
// This fetches and caches the data for the current batch and the next and previous batches
|
// This fetches and caches the data for the current batch and the next and previous batches
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { CCPairFullInfo, ConnectorCredentialPairStatus } from "./types";
|
|
||||||
import { CCPairStatus } from "@/components/Status";
|
|
||||||
import { BackButton } from "@/components/BackButton";
|
import { BackButton } from "@/components/BackButton";
|
||||||
import { Button, Divider, Title } from "@tremor/react";
|
|
||||||
import { IndexingAttemptsTable } from "./IndexingAttemptsTable";
|
|
||||||
import { AdvancedConfigDisplay, ConfigDisplay } from "./ConfigDisplay";
|
|
||||||
import { ModifyStatusButtonCluster } from "./ModifyStatusButtonCluster";
|
|
||||||
import { DeletionButton } from "./DeletionButton";
|
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { ReIndexButton } from "./ReIndexButton";
|
|
||||||
import { ValidSources } from "@/lib/types";
|
|
||||||
import useSWR, { mutate } from "swr";
|
|
||||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import CredentialSection from "@/components/credentials/CredentialSection";
|
|
||||||
import { buildCCPairInfoUrl } from "./lib";
|
|
||||||
import { SourceIcon } from "@/components/SourceIcon";
|
import { SourceIcon } from "@/components/SourceIcon";
|
||||||
import { credentialTemplates } from "@/lib/connectors/credentials";
|
import { CCPairStatus } from "@/components/Status";
|
||||||
import { useEffect, useRef, useState } from "react";
|
|
||||||
import { CheckmarkIcon, EditIcon, XIcon } from "@/components/icons/icons";
|
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
|
import CredentialSection from "@/components/credentials/CredentialSection";
|
||||||
|
import { CheckmarkIcon, EditIcon, XIcon } from "@/components/icons/icons";
|
||||||
import { updateConnectorCredentialPairName } from "@/lib/connector";
|
import { updateConnectorCredentialPairName } from "@/lib/connector";
|
||||||
import DeletionErrorStatus from "./DeletionErrorStatus";
|
import { credentialTemplates } from "@/lib/connectors/credentials";
|
||||||
|
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||||
|
import { ValidSources } from "@/lib/types";
|
||||||
|
import { Button, Divider, Title } from "@tremor/react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
import useSWR, { mutate } from "swr";
|
||||||
|
import { AdvancedConfigDisplay, ConfigDisplay } from "./ConfigDisplay";
|
||||||
|
import { DeletionButton } from "./DeletionButton";
|
||||||
|
import DeletionErrorStatus from "./DeletionErrorStatus";
|
||||||
|
import { IndexingAttemptsTable } from "./IndexingAttemptsTable";
|
||||||
|
import { ModifyStatusButtonCluster } from "./ModifyStatusButtonCluster";
|
||||||
|
import { ReIndexButton } from "./ReIndexButton";
|
||||||
|
import { buildCCPairInfoUrl } from "./lib";
|
||||||
|
import { CCPairFullInfo, ConnectorCredentialPairStatus } from "./types";
|
||||||
|
|
||||||
// since the uploaded files are cleaned up after some period of time
|
// since the uploaded files are cleaned up after some period of time
|
||||||
// re-indexing will not work for the file connector. Also, it would not
|
// re-indexing will not work for the file connector. Also, it would not
|
||||||
@ -49,7 +49,7 @@ function Main({ ccPairId }: { ccPairId: number }) {
|
|||||||
|
|
||||||
const { popup, setPopup } = usePopup();
|
const { popup, setPopup } = usePopup();
|
||||||
|
|
||||||
const finishConnectorDeletion = () => {
|
const finishConnectorDeletion = useCallback(() => {
|
||||||
setPopup({
|
setPopup({
|
||||||
message: "Connector deleted successfully",
|
message: "Connector deleted successfully",
|
||||||
type: "success",
|
type: "success",
|
||||||
@ -57,7 +57,7 @@ function Main({ ccPairId }: { ccPairId: number }) {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
router.push("/admin/indexing/status");
|
router.push("/admin/indexing/status");
|
||||||
}, 2000);
|
}, 2000);
|
||||||
};
|
}, [router, setPopup]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isEditing && inputRef.current) {
|
if (isEditing && inputRef.current) {
|
||||||
@ -80,7 +80,14 @@ function Main({ ccPairId }: { ccPairId: number }) {
|
|||||||
) {
|
) {
|
||||||
finishConnectorDeletion();
|
finishConnectorDeletion();
|
||||||
}
|
}
|
||||||
}, [isLoading, ccPair, error, hasLoadedOnce, router]);
|
}, [
|
||||||
|
isLoading,
|
||||||
|
ccPair,
|
||||||
|
error,
|
||||||
|
hasLoadedOnce,
|
||||||
|
router,
|
||||||
|
finishConnectorDeletion,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setEditableName(e.target.value);
|
setEditableName(e.target.value);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FetchError, errorHandlingFetcher } from "@/lib/fetcher";
|
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
||||||
|
|
||||||
@ -29,6 +29,8 @@ import {
|
|||||||
defaultPruneFreqDays,
|
defaultPruneFreqDays,
|
||||||
defaultRefreshFreqMinutes,
|
defaultRefreshFreqMinutes,
|
||||||
isLoadState,
|
isLoadState,
|
||||||
|
Connector,
|
||||||
|
ConnectorBase,
|
||||||
} from "@/lib/connectors/connectors";
|
} from "@/lib/connectors/connectors";
|
||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import GDriveMain from "./pages/gdrive/GoogleDrivePage";
|
import GDriveMain from "./pages/gdrive/GoogleDrivePage";
|
||||||
@ -47,7 +49,6 @@ export interface AdvancedConfig {
|
|||||||
pruneFreq: number;
|
pruneFreq: number;
|
||||||
indexingStart: string;
|
indexingStart: string;
|
||||||
}
|
}
|
||||||
import { Connector, ConnectorBase } from "@/lib/connectors/connectors";
|
|
||||||
|
|
||||||
const BASE_CONNECTOR_URL = "/api/manage/admin/connector";
|
const BASE_CONNECTOR_URL = "/api/manage/admin/connector";
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { ConfigurableSources, ValidSources } from "@/lib/types";
|
import { ConfigurableSources } from "@/lib/types";
|
||||||
import AddConnector from "./AddConnectorPage";
|
import AddConnector from "./AddConnectorPage";
|
||||||
import { FormProvider } from "@/components/context/FormContext";
|
import { FormProvider } from "@/components/context/FormContext";
|
||||||
import Sidebar from "./Sidebar";
|
import Sidebar from "./Sidebar";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useFormContext } from "@/components/context/FormContext";
|
import { useFormContext } from "@/components/context/FormContext";
|
||||||
import { HeaderTitle } from "@/components/header/HeaderTitle";
|
import { HeaderTitle } from "@/components/header/HeaderTitle";
|
||||||
|
|
||||||
import { BackIcon, SettingsIcon } from "@/components/icons/icons";
|
import { SettingsIcon } from "@/components/icons/icons";
|
||||||
import { Logo } from "@/components/Logo";
|
import { Logo } from "@/components/Logo";
|
||||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||||
import { credentialTemplates } from "@/lib/connectors/credentials";
|
import { credentialTemplates } from "@/lib/connectors/credentials";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { SubLabel } from "@/components/admin/connectors/Field";
|
import { SubLabel } from "@/components/admin/connectors/Field";
|
||||||
import { Field, useFormikContext } from "formik";
|
import { Field } from "formik";
|
||||||
|
|
||||||
export default function NumberInput({
|
export default function NumberInput({
|
||||||
label,
|
label,
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
import CredentialSubText from "@/components/credentials/CredentialFields";
|
import CredentialSubText from "@/components/credentials/CredentialFields";
|
||||||
import {
|
import { StringWithDescription } from "@/lib/connectors/connectors";
|
||||||
ListOption,
|
|
||||||
SelectOption,
|
|
||||||
StringWithDescription,
|
|
||||||
} from "@/lib/connectors/connectors";
|
|
||||||
import { Field } from "formik";
|
import { Field } from "formik";
|
||||||
|
|
||||||
export default function SelectInput({
|
export default function SelectInput({
|
||||||
|
@ -10,15 +10,13 @@ import { GOOGLE_DRIVE_AUTH_IS_ADMIN_COOKIE_NAME } from "@/lib/constants";
|
|||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { TextFormField } from "@/components/admin/connectors/Field";
|
import { TextFormField } from "@/components/admin/connectors/Field";
|
||||||
import { Form, Formik } from "formik";
|
import { Form, Formik } from "formik";
|
||||||
import { Card } from "@tremor/react";
|
import { Button as TremorButton } from "@tremor/react";
|
||||||
import {
|
import {
|
||||||
Credential,
|
Credential,
|
||||||
GoogleDriveCredentialJson,
|
GoogleDriveCredentialJson,
|
||||||
GoogleDriveServiceAccountCredentialJson,
|
GoogleDriveServiceAccountCredentialJson,
|
||||||
} from "@/lib/connectors/credentials";
|
} from "@/lib/connectors/credentials";
|
||||||
|
|
||||||
import { Button as TremorButton } from "@tremor/react";
|
|
||||||
|
|
||||||
type GoogleDriveCredentialJsonTypes = "authorized_user" | "service_account";
|
type GoogleDriveCredentialJsonTypes = "authorized_user" | "service_account";
|
||||||
|
|
||||||
export const DriveJsonUpload = ({
|
export const DriveJsonUpload = ({
|
||||||
@ -285,6 +283,7 @@ export const DriveJsonUploadSection = ({
|
|||||||
className="text-link"
|
className="text-link"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://docs.danswer.dev/connectors/google_drive#authorization"
|
href="https://docs.danswer.dev/connectors/google_drive#authorization"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
here
|
here
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { FetchError, errorHandlingFetcher } from "@/lib/fetcher";
|
import { FetchError, errorHandlingFetcher } from "@/lib/fetcher";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { LoadingAnimation } from "@/components/Loading";
|
import { LoadingAnimation } from "@/components/Loading";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { ConnectorIndexingStatus } from "@/lib/types";
|
import { ConnectorIndexingStatus } from "@/lib/types";
|
||||||
import { usePublicCredentials } from "@/lib/hooks";
|
import {
|
||||||
|
usePublicCredentials,
|
||||||
|
useConnectorCredentialIndexingStatus,
|
||||||
|
} from "@/lib/hooks";
|
||||||
import { Title } from "@tremor/react";
|
import { Title } from "@tremor/react";
|
||||||
import { DriveJsonUploadSection, DriveOAuthSection } from "./Credential";
|
import { DriveJsonUploadSection, DriveOAuthSection } from "./Credential";
|
||||||
import {
|
import {
|
||||||
@ -18,7 +20,6 @@ import {
|
|||||||
} from "@/lib/connectors/credentials";
|
} from "@/lib/connectors/credentials";
|
||||||
import { GoogleDriveConfig } from "@/lib/connectors/connectors";
|
import { GoogleDriveConfig } from "@/lib/connectors/connectors";
|
||||||
import { useUser } from "@/components/user/UserProvider";
|
import { useUser } from "@/components/user/UserProvider";
|
||||||
import { useConnectorCredentialIndexingStatus } from "@/lib/hooks";
|
|
||||||
|
|
||||||
const GDriveMain = ({}: {}) => {
|
const GDriveMain = ({}: {}) => {
|
||||||
const { isLoadingUser, isAdmin } = useUser();
|
const { isLoadingUser, isAdmin } = useUser();
|
||||||
|
@ -271,6 +271,7 @@ export const GmailJsonUploadSection = ({
|
|||||||
className="text-link"
|
className="text-link"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://docs.danswer.dev/connectors/gmail#authorization"
|
href="https://docs.danswer.dev/connectors/gmail#authorization"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
here
|
here
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
|
@ -5,20 +5,19 @@ import { errorHandlingFetcher } from "@/lib/fetcher";
|
|||||||
import { LoadingAnimation } from "@/components/Loading";
|
import { LoadingAnimation } from "@/components/Loading";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { ConnectorIndexingStatus } from "@/lib/types";
|
import { ConnectorIndexingStatus } from "@/lib/types";
|
||||||
import { getCurrentUser } from "@/lib/user";
|
|
||||||
import { User, UserRole } from "@/lib/types";
|
|
||||||
import {
|
import {
|
||||||
Credential,
|
Credential,
|
||||||
GmailCredentialJson,
|
GmailCredentialJson,
|
||||||
GmailServiceAccountCredentialJson,
|
GmailServiceAccountCredentialJson,
|
||||||
} from "@/lib/connectors/credentials";
|
} from "@/lib/connectors/credentials";
|
||||||
import { GmailOAuthSection, GmailJsonUploadSection } from "./Credential";
|
import { GmailOAuthSection, GmailJsonUploadSection } from "./Credential";
|
||||||
import { usePublicCredentials } from "@/lib/hooks";
|
import {
|
||||||
|
usePublicCredentials,
|
||||||
|
useConnectorCredentialIndexingStatus,
|
||||||
|
} from "@/lib/hooks";
|
||||||
import { Title } from "@tremor/react";
|
import { Title } from "@tremor/react";
|
||||||
import { GmailConfig } from "@/lib/connectors/connectors";
|
import { GmailConfig } from "@/lib/connectors/connectors";
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
import { useUser } from "@/components/user/UserProvider";
|
import { useUser } from "@/components/user/UserProvider";
|
||||||
import { useConnectorCredentialIndexingStatus } from "@/lib/hooks";
|
|
||||||
|
|
||||||
export const GmailMain = () => {
|
export const GmailMain = () => {
|
||||||
const { isLoadingUser, isAdmin } = useUser();
|
const { isLoadingUser, isAdmin } = useUser();
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { adminSearch } from "./lib";
|
import { adminSearch } from "./lib";
|
||||||
import { MagnifyingGlass } from "@phosphor-icons/react";
|
import { MagnifyingGlass } from "@phosphor-icons/react";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { DanswerDocument } from "@/lib/search/interfaces";
|
import { DanswerDocument } from "@/lib/search/interfaces";
|
||||||
import { buildDocumentSummaryDisplay } from "@/components/search/DocumentDisplay";
|
import { buildDocumentSummaryDisplay } from "@/components/search/DocumentDisplay";
|
||||||
import { CustomCheckbox } from "@/components/CustomCheckbox";
|
import { CustomCheckbox } from "@/components/CustomCheckbox";
|
||||||
@ -121,7 +121,8 @@ export function Explorer({
|
|||||||
|
|
||||||
const filterManager = useFilters();
|
const filterManager = useFilters();
|
||||||
|
|
||||||
const onSearch = async (query: string) => {
|
const onSearch = useCallback(
|
||||||
|
async (query: string) => {
|
||||||
const filters = buildFilters(
|
const filters = buildFilters(
|
||||||
filterManager.selectedSources,
|
filterManager.selectedSources,
|
||||||
filterManager.selectedDocumentSets,
|
filterManager.selectedDocumentSets,
|
||||||
@ -133,7 +134,14 @@ export function Explorer({
|
|||||||
setResults((await results.json()).documents);
|
setResults((await results.json()).documents);
|
||||||
}
|
}
|
||||||
setTimeoutId(null);
|
setTimeoutId(null);
|
||||||
};
|
},
|
||||||
|
[
|
||||||
|
filterManager.selectedDocumentSets,
|
||||||
|
filterManager.selectedSources,
|
||||||
|
filterManager.timeRange,
|
||||||
|
filterManager.selectedTags,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (timeoutId !== null) {
|
if (timeoutId !== null) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { BasicTable } from "@/components/admin/connectors/BasicTable";
|
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
|
@ -177,7 +177,7 @@ export const DocumentSetCreationForm = ({
|
|||||||
const ind = props.values.cc_pair_ids.indexOf(
|
const ind = props.values.cc_pair_ids.indexOf(
|
||||||
ccPair.cc_pair_id
|
ccPair.cc_pair_id
|
||||||
);
|
);
|
||||||
let isSelected = ind !== -1;
|
const isSelected = ind !== -1;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={`${ccPair.connector.id}-${ccPair.credential.id}`}
|
key={`${ccPair.connector.id}-${ccPair.credential.id}`}
|
||||||
@ -291,7 +291,7 @@ export const DocumentSetCreationForm = ({
|
|||||||
const ind = props.values.cc_pair_ids.indexOf(
|
const ind = props.values.cc_pair_ids.indexOf(
|
||||||
ccPair.cc_pair_id
|
ccPair.cc_pair_id
|
||||||
);
|
);
|
||||||
let isSelected = ind !== -1;
|
const isSelected = ind !== -1;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={`${ccPair.connector.id}-${ccPair.credential.id}`}
|
key={`${ccPair.connector.id}-${ccPair.credential.id}`}
|
||||||
|
@ -13,7 +13,6 @@ import { Card } from "@tremor/react";
|
|||||||
import { BackButton } from "@/components/BackButton";
|
import { BackButton } from "@/components/BackButton";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { UserGroup } from "@/lib/types";
|
|
||||||
import { refreshDocumentSets } from "../hooks";
|
import { refreshDocumentSets } from "../hooks";
|
||||||
|
|
||||||
function Main() {
|
function Main() {
|
||||||
|
@ -13,18 +13,17 @@ import {
|
|||||||
Title,
|
Title,
|
||||||
Divider,
|
Divider,
|
||||||
Badge,
|
Badge,
|
||||||
|
Button,
|
||||||
|
Text,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { useConnectorCredentialIndexingStatus } from "@/lib/hooks";
|
import { useConnectorCredentialIndexingStatus } from "@/lib/hooks";
|
||||||
import { ConnectorIndexingStatus, DocumentSet } from "@/lib/types";
|
import { ConnectorIndexingStatus, DocumentSet } from "@/lib/types";
|
||||||
import { useState, useEffect } from "react";
|
import { useState } from "react";
|
||||||
import { getCurrentUser } from "@/lib/user";
|
|
||||||
import { User, UserRole } from "@/lib/types";
|
|
||||||
import { useDocumentSets } from "./hooks";
|
import { useDocumentSets } from "./hooks";
|
||||||
import { ConnectorTitle } from "@/components/admin/connectors/ConnectorTitle";
|
import { ConnectorTitle } from "@/components/admin/connectors/ConnectorTitle";
|
||||||
import { deleteDocumentSet } from "./lib";
|
import { deleteDocumentSet } from "./lib";
|
||||||
import { PopupSpec, usePopup } from "@/components/admin/connectors/Popup";
|
import { PopupSpec, usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { AdminPageTitle } from "@/components/admin/Title";
|
import { AdminPageTitle } from "@/components/admin/Title";
|
||||||
import { Button, Text } from "@tremor/react";
|
|
||||||
import {
|
import {
|
||||||
FiAlertTriangle,
|
FiAlertTriangle,
|
||||||
FiCheckCircle,
|
FiCheckCircle,
|
||||||
|
@ -6,7 +6,6 @@ import { Dispatch, SetStateAction, useState } from "react";
|
|||||||
import {
|
import {
|
||||||
CloudEmbeddingProvider,
|
CloudEmbeddingProvider,
|
||||||
CloudEmbeddingModel,
|
CloudEmbeddingModel,
|
||||||
AVAILABLE_CLOUD_PROVIDERS,
|
|
||||||
AVAILABLE_MODELS,
|
AVAILABLE_MODELS,
|
||||||
INVALID_OLD_MODEL,
|
INVALID_OLD_MODEL,
|
||||||
HostedEmbeddingModel,
|
HostedEmbeddingModel,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useRef, useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import { Button, Text, Callout, Subtitle, Divider } from "@tremor/react";
|
import { Button, Text, Callout, Subtitle, Divider } from "@tremor/react";
|
||||||
import { Label, TextFormField } from "@/components/admin/connectors/Field";
|
import { Label } from "@/components/admin/connectors/Field";
|
||||||
import { CloudEmbeddingProvider } from "../../../../components/embedding/interfaces";
|
import { CloudEmbeddingProvider } from "../../../../components/embedding/interfaces";
|
||||||
import {
|
import {
|
||||||
EMBEDDING_PROVIDERS_ADMIN_URL,
|
EMBEDDING_PROVIDERS_ADMIN_URL,
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import { Button, Text, Callout } from "@tremor/react";
|
import { Button, Text, Callout } from "@tremor/react";
|
||||||
import {
|
import { HostedEmbeddingModel } from "../../../../components/embedding/interfaces";
|
||||||
EmbeddingModelDescriptor,
|
|
||||||
HostedEmbeddingModel,
|
|
||||||
} from "../../../../components/embedding/interfaces";
|
|
||||||
|
|
||||||
export function ModelSelectionConfirmationModal({
|
export function ModelSelectionConfirmationModal({
|
||||||
selectedModel,
|
selectedModel,
|
||||||
|
@ -167,6 +167,7 @@ export function ProviderCreationModal({
|
|||||||
className="cursor-pointer underline"
|
className="cursor-pointer underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href={selectedProvider.docsLink}
|
href={selectedProvider.docsLink}
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
here
|
here
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
@ -175,6 +176,7 @@ export function ProviderCreationModal({
|
|||||||
className="cursor-pointer underline"
|
className="cursor-pointer underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href={selectedProvider.apiLink}
|
href={selectedProvider.apiLink}
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
{isProxy ? "API URL" : "API KEY"}
|
{isProxy ? "API URL" : "API KEY"}
|
||||||
</a>
|
</a>
|
||||||
@ -223,6 +225,7 @@ export function ProviderCreationModal({
|
|||||||
href={selectedProvider.apiLink}
|
href={selectedProvider.apiLink}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="underline cursor-pointer"
|
className="underline cursor-pointer"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
Learn more here
|
Learn more here
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { Dispatch, forwardRef, SetStateAction } from "react";
|
import React, { forwardRef } from "react";
|
||||||
import { Formik, Form, FormikProps, FieldArray, Field } from "formik";
|
import { Formik, Form, FormikProps, FieldArray, Field } from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import CredentialSubText from "@/components/credentials/CredentialFields";
|
|
||||||
import { TrashIcon } from "@/components/icons/icons";
|
import { TrashIcon } from "@/components/icons/icons";
|
||||||
import { FaPlus } from "react-icons/fa";
|
import { FaPlus } from "react-icons/fa";
|
||||||
import { AdvancedSearchConfiguration } from "../interfaces";
|
import { AdvancedSearchConfiguration } from "../interfaces";
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Button, Card, Text, Title } from "@tremor/react";
|
import { Card, Text, Title } from "@tremor/react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CloudEmbeddingProvider,
|
CloudEmbeddingProvider,
|
||||||
@ -56,7 +56,7 @@ export default function CloudEmbeddingPage({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let providers: CloudEmbeddingProviderFull[] = AVAILABLE_CLOUD_PROVIDERS.map(
|
const providers: CloudEmbeddingProviderFull[] = AVAILABLE_CLOUD_PROVIDERS.map(
|
||||||
(model) => ({
|
(model) => ({
|
||||||
...model,
|
...model,
|
||||||
configured:
|
configured:
|
||||||
|
@ -165,7 +165,7 @@ export default function EmbeddingForm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updateSearch = async () => {
|
const updateSearch = async () => {
|
||||||
let values: SavedSearchSettings = {
|
const values: SavedSearchSettings = {
|
||||||
...rerankingDetails,
|
...rerankingDetails,
|
||||||
...advancedEmbeddingDetails,
|
...advancedEmbeddingDetails,
|
||||||
provider_type:
|
provider_type:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { Button, Card, Text } from "@tremor/react";
|
import { Button, Card, Text, Title } from "@tremor/react";
|
||||||
import { ModelSelector } from "../../../../components/embedding/ModelSelector";
|
import { ModelSelector } from "../../../../components/embedding/ModelSelector";
|
||||||
import {
|
import {
|
||||||
AVAILABLE_MODELS,
|
AVAILABLE_MODELS,
|
||||||
@ -8,7 +8,6 @@ import {
|
|||||||
} from "../../../../components/embedding/interfaces";
|
} from "../../../../components/embedding/interfaces";
|
||||||
import { CustomModelForm } from "../../../../components/embedding/CustomModelForm";
|
import { CustomModelForm } from "../../../../components/embedding/CustomModelForm";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Title } from "@tremor/react";
|
|
||||||
export default function OpenEmbeddingPage({
|
export default function OpenEmbeddingPage({
|
||||||
onSelectOpenSource,
|
onSelectOpenSource,
|
||||||
selectedProvider,
|
selectedProvider,
|
||||||
@ -34,7 +33,12 @@ export default function OpenEmbeddingPage({
|
|||||||
|
|
||||||
<Text className="mt-6">
|
<Text className="mt-6">
|
||||||
Alternatively, (if you know what you're doing) you can specify a{" "}
|
Alternatively, (if you know what you're doing) you can specify a{" "}
|
||||||
<a target="_blank" href="https://www.sbert.net/" className="text-link">
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://www.sbert.net/"
|
||||||
|
className="text-link"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
SentenceTransformers
|
SentenceTransformers
|
||||||
</a>
|
</a>
|
||||||
-compatible model of your choice below. The rough list of supported
|
-compatible model of your choice below. The rough list of supported
|
||||||
@ -43,6 +47,7 @@ export default function OpenEmbeddingPage({
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://huggingface.co/models?library=sentence-transformers&sort=trending"
|
href="https://huggingface.co/models?library=sentence-transformers&sort=trending"
|
||||||
className="text-link"
|
className="text-link"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
here
|
here
|
||||||
</a>
|
</a>
|
||||||
|
@ -4,7 +4,6 @@ import { BackButton } from "@/components/BackButton";
|
|||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||||
import { ValidSources } from "@/lib/types";
|
|
||||||
import { Title } from "@tremor/react";
|
import { Title } from "@tremor/react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { IndexAttemptErrorsTable } from "./IndexAttemptErrorsTable";
|
import { IndexAttemptErrorsTable } from "./IndexAttemptErrorsTable";
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import useSWR from "swr";
|
|
||||||
|
|
||||||
import { LoadingAnimation } from "@/components/Loading";
|
import { LoadingAnimation } from "@/components/Loading";
|
||||||
import { NotebookIcon } from "@/components/icons/icons";
|
import { NotebookIcon } from "@/components/icons/icons";
|
||||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
|
||||||
import { ConnectorIndexingStatus } from "@/lib/types";
|
|
||||||
import { CCPairIndexingStatusTable } from "./CCPairIndexingStatusTable";
|
import { CCPairIndexingStatusTable } from "./CCPairIndexingStatusTable";
|
||||||
import { AdminPageTitle } from "@/components/admin/Title";
|
import { AdminPageTitle } from "@/components/admin/Title";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Formik, Form, Field, ErrorMessage } from "formik";
|
import { Formik, Form } from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { ModalWrapper } from "@/components/modals/ModalWrapper";
|
import { ModalWrapper } from "@/components/modals/ModalWrapper";
|
||||||
import { Button, Textarea, TextInput } from "@tremor/react";
|
import { Button } from "@tremor/react";
|
||||||
|
|
||||||
import { BookstackIcon } from "@/components/icons/icons";
|
import { BookstackIcon } from "@/components/icons/icons";
|
||||||
import { AddPromptModalProps } from "../interfaces";
|
import { AddPromptModalProps } from "../interfaces";
|
||||||
|
@ -16,7 +16,6 @@ import { FilterDropdown } from "@/components/search/filtering/FilterDropdown";
|
|||||||
import { FiTag } from "react-icons/fi";
|
import { FiTag } from "react-icons/fi";
|
||||||
import { PageSelector } from "@/components/PageSelector";
|
import { PageSelector } from "@/components/PageSelector";
|
||||||
import { InputPrompt } from "./interfaces";
|
import { InputPrompt } from "./interfaces";
|
||||||
import { Modal } from "@/components/Modal";
|
|
||||||
import { DeleteEntityModal } from "@/components/modals/DeleteEntityModal";
|
import { DeleteEntityModal } from "@/components/modals/DeleteEntityModal";
|
||||||
|
|
||||||
const CategoryBubble = ({
|
const CategoryBubble = ({
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
import { Label, SubLabel } from "@/components/admin/connectors/Field";
|
import { Label, SubLabel } from "@/components/admin/connectors/Field";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { Title } from "@tremor/react";
|
import { Title, Button } from "@tremor/react";
|
||||||
import { Settings } from "./interfaces";
|
import { Settings } from "./interfaces";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { DefaultDropdown, Option } from "@/components/Dropdown";
|
import { DefaultDropdown, Option } from "@/components/Dropdown";
|
||||||
import { useContext } from "react";
|
import React, { useContext, useState, useEffect } from "react";
|
||||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||||
import { Button } from "@tremor/react";
|
|
||||||
|
|
||||||
function Checkbox({
|
function Checkbox({
|
||||||
label,
|
label,
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FiGlobe, FiShield, FiUser, FiUsers } from "react-icons/fi";
|
import { FiGlobe, FiUser, FiUsers } from "react-icons/fi";
|
||||||
import {
|
import {
|
||||||
insertGlobalTokenRateLimit,
|
insertGlobalTokenRateLimit,
|
||||||
insertGroupTokenRateLimit,
|
insertGroupTokenRateLimit,
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { MethodSpec, ToolSnapshot } from "@/lib/tools/interfaces";
|
import { MethodSpec, ToolSnapshot } from "@/lib/tools/interfaces";
|
||||||
import { TextFormField } from "@/components/admin/connectors/Field";
|
import { TextFormField } from "@/components/admin/connectors/Field";
|
||||||
import { Button, Divider, Text } from "@tremor/react";
|
import { Button, Divider } from "@tremor/react";
|
||||||
import {
|
import {
|
||||||
createCustomTool,
|
createCustomTool,
|
||||||
updateCustomTool,
|
updateCustomTool,
|
||||||
@ -64,9 +64,9 @@ function ToolForm({
|
|||||||
const [definitionError, setDefinitionError] = definitionErrorState;
|
const [definitionError, setDefinitionError] = definitionErrorState;
|
||||||
const [methodSpecs, setMethodSpecs] = methodSpecsState;
|
const [methodSpecs, setMethodSpecs] = methodSpecsState;
|
||||||
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
|
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
|
||||||
|
|
||||||
const debouncedValidateDefinition = useCallback(
|
const debouncedValidateDefinition = useCallback(
|
||||||
debounce(async (definition: string) => {
|
(definition: string) => {
|
||||||
|
const validateDefinition = async () => {
|
||||||
try {
|
try {
|
||||||
const parsedDefinition = parseJsonWithTrailingCommas(definition);
|
const parsedDefinition = parseJsonWithTrailingCommas(definition);
|
||||||
const response = await validateToolDefinition({
|
const response = await validateToolDefinition({
|
||||||
@ -84,8 +84,11 @@ function ToolForm({
|
|||||||
setMethodSpecs(null);
|
setMethodSpecs(null);
|
||||||
setDefinitionError("Invalid JSON format");
|
setDefinitionError("Invalid JSON format");
|
||||||
}
|
}
|
||||||
}, 300),
|
};
|
||||||
[]
|
|
||||||
|
debounce(validateDefinition, 300)();
|
||||||
|
},
|
||||||
|
[setMethodSpecs, setDefinitionError]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Text,
|
|
||||||
Table,
|
Table,
|
||||||
TableHead,
|
TableHead,
|
||||||
TableRow,
|
TableRow,
|
||||||
|
@ -3,7 +3,6 @@ import { Card, Text, Title } from "@tremor/react";
|
|||||||
import { ToolEditor } from "@/app/admin/tools/ToolEditor";
|
import { ToolEditor } from "@/app/admin/tools/ToolEditor";
|
||||||
import { fetchToolByIdSS } from "@/lib/tools/fetchTools";
|
import { fetchToolByIdSS } from "@/lib/tools/fetchTools";
|
||||||
import { DeleteToolButton } from "./DeleteToolButton";
|
import { DeleteToolButton } from "./DeleteToolButton";
|
||||||
import { FiTool } from "react-icons/fi";
|
|
||||||
import { AdminPageTitle } from "@/components/admin/Title";
|
import { AdminPageTitle } from "@/components/admin/Title";
|
||||||
import { BackButton } from "@/components/BackButton";
|
import { BackButton } from "@/components/BackButton";
|
||||||
import { ToolIcon } from "@/components/icons/icons";
|
import { ToolIcon } from "@/components/icons/icons";
|
||||||
|
@ -5,7 +5,6 @@ import { BackButton } from "@/components/BackButton";
|
|||||||
import { AdminPageTitle } from "@/components/admin/Title";
|
import { AdminPageTitle } from "@/components/admin/Title";
|
||||||
import { ToolIcon } from "@/components/icons/icons";
|
import { ToolIcon } from "@/components/icons/icons";
|
||||||
import { Card } from "@tremor/react";
|
import { Card } from "@tremor/react";
|
||||||
import { FiTool } from "react-icons/fi";
|
|
||||||
|
|
||||||
export default function NewToolPage() {
|
export default function NewToolPage() {
|
||||||
return (
|
return (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ToolsTable } from "./ToolsTable";
|
import { ToolsTable } from "./ToolsTable";
|
||||||
import { ToolSnapshot } from "@/lib/tools/interfaces";
|
import { ToolSnapshot } from "@/lib/tools/interfaces";
|
||||||
import { FiPlusSquare, FiTool } from "react-icons/fi";
|
import { FiPlusSquare } from "react-icons/fi";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Divider, Text, Title } from "@tremor/react";
|
import { Divider, Text, Title } from "@tremor/react";
|
||||||
import { fetchSS } from "@/lib/utilsSS";
|
import { fetchSS } from "@/lib/utilsSS";
|
||||||
|
@ -12,7 +12,6 @@ import { AdminPageTitle } from "@/components/admin/Title";
|
|||||||
import { usePopup, PopupSpec } from "@/components/admin/connectors/Popup";
|
import { usePopup, PopupSpec } from "@/components/admin/connectors/Popup";
|
||||||
import { UsersIcon } from "@/components/icons/icons";
|
import { UsersIcon } from "@/components/icons/icons";
|
||||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||||
import { type User, UserStatus } from "@/lib/types";
|
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { HidableSection } from "@/app/admin/assistants/HidableSection";
|
import { HidableSection } from "@/app/admin/assistants/HidableSection";
|
||||||
|
@ -6,7 +6,14 @@ import { Folder } from "@/app/chat/folders/interfaces";
|
|||||||
import { User } from "@/lib/types";
|
import { User } from "@/lib/types";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { SIDEBAR_TOGGLED_COOKIE_NAME } from "@/components/resizable/constants";
|
import { SIDEBAR_TOGGLED_COOKIE_NAME } from "@/components/resizable/constants";
|
||||||
import { ReactNode, useContext, useEffect, useRef, useState } from "react";
|
import {
|
||||||
|
ReactNode,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
import { useSidebarVisibility } from "@/components/chat_search/hooks";
|
import { useSidebarVisibility } from "@/components/chat_search/hooks";
|
||||||
import FunctionalHeader from "@/components/chat_search/Header";
|
import FunctionalHeader from "@/components/chat_search/Header";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
@ -54,7 +61,7 @@ export default function SidebarWrapper<T extends object>({
|
|||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleSidebar = () => {
|
const toggleSidebar = useCallback(() => {
|
||||||
Cookies.set(
|
Cookies.set(
|
||||||
SIDEBAR_TOGGLED_COOKIE_NAME,
|
SIDEBAR_TOGGLED_COOKIE_NAME,
|
||||||
String(!toggledSidebar).toLocaleLowerCase()
|
String(!toggledSidebar).toLocaleLowerCase()
|
||||||
@ -63,7 +70,7 @@ export default function SidebarWrapper<T extends object>({
|
|||||||
path: "/",
|
path: "/",
|
||||||
};
|
};
|
||||||
setToggledSidebar((toggledSidebar) => !toggledSidebar);
|
setToggledSidebar((toggledSidebar) => !toggledSidebar);
|
||||||
};
|
}, [toggledSidebar]);
|
||||||
|
|
||||||
const sidebarElementRef = useRef<HTMLDivElement>(null);
|
const sidebarElementRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import { Persona } from "@/app/admin/assistants/interfaces";
|
|||||||
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||||
import { User } from "@/lib/types";
|
import { User } from "@/lib/types";
|
||||||
import { Button } from "@tremor/react";
|
import { Button } from "@tremor/react";
|
||||||
import Link from "next/link";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FiList, FiMinus, FiPlus } from "react-icons/fi";
|
import { FiList, FiMinus, FiPlus } from "react-icons/fi";
|
||||||
import { AssistantsPageTitle } from "../AssistantsPageTitle";
|
import { AssistantsPageTitle } from "../AssistantsPageTitle";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import { MinimalUserSnapshot, User } from "@/lib/types";
|
import { MinimalUserSnapshot, User } from "@/lib/types";
|
||||||
import { Button, Divider, Text } from "@tremor/react";
|
import { Button } from "@tremor/react";
|
||||||
import { FiPlus, FiX } from "react-icons/fi";
|
import { FiPlus, FiX } from "react-icons/fi";
|
||||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||||
import { SearchMultiSelectDropdown } from "@/components/Dropdown";
|
import { SearchMultiSelectDropdown } from "@/components/Dropdown";
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, {
|
import React, { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||||
Dispatch,
|
|
||||||
ReactNode,
|
|
||||||
SetStateAction,
|
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
} from "react";
|
|
||||||
import { MinimalUserSnapshot, User } from "@/lib/types";
|
import { MinimalUserSnapshot, User } from "@/lib/types";
|
||||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||||
import { Button, Divider, Text } from "@tremor/react";
|
import { Button, Divider } from "@tremor/react";
|
||||||
import {
|
import {
|
||||||
FiEdit2,
|
FiEdit2,
|
||||||
FiList,
|
FiList,
|
||||||
@ -51,8 +45,8 @@ import {
|
|||||||
SortableContext,
|
SortableContext,
|
||||||
sortableKeyboardCoordinates,
|
sortableKeyboardCoordinates,
|
||||||
verticalListSortingStrategy,
|
verticalListSortingStrategy,
|
||||||
|
useSortable,
|
||||||
} from "@dnd-kit/sortable";
|
} from "@dnd-kit/sortable";
|
||||||
import { useSortable } from "@dnd-kit/sortable";
|
|
||||||
|
|
||||||
import { DragHandle } from "@/components/table/DragHandle";
|
import { DragHandle } from "@/components/table/DragHandle";
|
||||||
import {
|
import {
|
||||||
|
@ -5,7 +5,6 @@ import { Folder } from "@/app/chat/folders/interfaces";
|
|||||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||||
import { User } from "@/lib/types";
|
import { User } from "@/lib/types";
|
||||||
|
|
||||||
import { InstantSSRAutoRefresh } from "@/components/SSRAutoRefresh";
|
|
||||||
import { AssistantsPageTitle } from "../AssistantsPageTitle";
|
import { AssistantsPageTitle } from "../AssistantsPageTitle";
|
||||||
import { useInputPrompts } from "@/app/admin/prompt-library/hooks";
|
import { useInputPrompts } from "@/app/admin/prompt-library/hooks";
|
||||||
import { PromptSection } from "@/app/admin/prompt-library/promptSection";
|
import { PromptSection } from "@/app/admin/prompt-library/promptSection";
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React from "react";
|
import React, { useContext } from "react";
|
||||||
import { useContext } from "react";
|
|
||||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||||
|
|
||||||
export const LoginText = () => {
|
export const LoginText = () => {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import { useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { Text } from "@tremor/react";
|
import { Text } from "@tremor/react";
|
||||||
import { RequestNewVerificationEmail } from "../waiting-on-verification/RequestNewVerificationEmail";
|
import { RequestNewVerificationEmail } from "../waiting-on-verification/RequestNewVerificationEmail";
|
||||||
import { User } from "@/lib/types";
|
import { User } from "@/lib/types";
|
||||||
@ -14,7 +14,7 @@ export function Verify({ user }: { user: User | null }) {
|
|||||||
|
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
async function verify() {
|
const verify = useCallback(async () => {
|
||||||
const token = searchParams.get("token");
|
const token = searchParams.get("token");
|
||||||
if (!token) {
|
if (!token) {
|
||||||
setError(
|
setError(
|
||||||
@ -39,11 +39,11 @@ export function Verify({ user }: { user: User | null }) {
|
|||||||
`Failed to verify your email - ${errorDetail}. Please try requesting a new verification email.`
|
`Failed to verify your email - ${errorDetail}. Please try requesting a new verification email.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}, [searchParams, router]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
verify();
|
verify();
|
||||||
}, []);
|
}, [verify]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
|
@ -123,7 +123,7 @@ export function ChatPage({
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
let {
|
const {
|
||||||
chatSessions,
|
chatSessions,
|
||||||
availableSources,
|
availableSources,
|
||||||
availableDocumentSets,
|
availableDocumentSets,
|
||||||
@ -243,7 +243,8 @@ export function ChatPage({
|
|||||||
destructureValue(user?.preferences.default_model)
|
destructureValue(user?.preferences.default_model)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [liveAssistant]);
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [liveAssistant, llmProviders, user?.preferences.default_model]);
|
||||||
|
|
||||||
const stopGenerating = () => {
|
const stopGenerating = () => {
|
||||||
const currentSession = currentSessionId();
|
const currentSession = currentSessionId();
|
||||||
@ -436,6 +437,7 @@ export function ChatPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialSessionFetch();
|
initialSessionFetch();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [existingChatSessionId]);
|
}, [existingChatSessionId]);
|
||||||
|
|
||||||
const [message, setMessage] = useState(
|
const [message, setMessage] = useState(
|
||||||
@ -696,7 +698,7 @@ export function ChatPage({
|
|||||||
finalAssistants.find((persona) => persona.id === defaultAssistantId)
|
finalAssistants.find((persona) => persona.id === defaultAssistantId)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [defaultAssistantId]);
|
}, [defaultAssistantId, finalAssistants, messageHistory.length]);
|
||||||
|
|
||||||
const [
|
const [
|
||||||
selectedDocuments,
|
selectedDocuments,
|
||||||
@ -772,7 +774,7 @@ export function ChatPage({
|
|||||||
const handleInputResize = () => {
|
const handleInputResize = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (inputRef.current && lastMessageRef.current) {
|
if (inputRef.current && lastMessageRef.current) {
|
||||||
let newHeight: number =
|
const newHeight: number =
|
||||||
inputRef.current?.getBoundingClientRect().height!;
|
inputRef.current?.getBoundingClientRect().height!;
|
||||||
const heightDifference = newHeight - previousHeight.current;
|
const heightDifference = newHeight - previousHeight.current;
|
||||||
if (
|
if (
|
||||||
@ -984,7 +986,7 @@ export function ChatPage({
|
|||||||
setAlternativeGeneratingAssistant(alternativeAssistantOverride);
|
setAlternativeGeneratingAssistant(alternativeAssistantOverride);
|
||||||
clientScrollToBottom();
|
clientScrollToBottom();
|
||||||
let currChatSessionId: number;
|
let currChatSessionId: number;
|
||||||
let isNewSession = chatSessionIdRef.current === null;
|
const isNewSession = chatSessionIdRef.current === null;
|
||||||
const searchParamBasedChatSessionName =
|
const searchParamBasedChatSessionName =
|
||||||
searchParams.get(SEARCH_PARAM_NAMES.TITLE) || null;
|
searchParams.get(SEARCH_PARAM_NAMES.TITLE) || null;
|
||||||
|
|
||||||
@ -1067,7 +1069,7 @@ export function ChatPage({
|
|||||||
|
|
||||||
let answer = "";
|
let answer = "";
|
||||||
|
|
||||||
let stopReason: StreamStopReason | null = null;
|
const stopReason: StreamStopReason | null = null;
|
||||||
let query: string | null = null;
|
let query: string | null = null;
|
||||||
let retrievalType: RetrievalType =
|
let retrievalType: RetrievalType =
|
||||||
selectedDocuments.length > 0
|
selectedDocuments.length > 0
|
||||||
@ -1668,17 +1670,22 @@ export function ChatPage({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initializeVisibleRange();
|
initializeVisibleRange();
|
||||||
}, [router, messageHistory, chatSessionIdRef.current]);
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [router, messageHistory]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
|
const scrollableDiv = scrollableDivRef.current;
|
||||||
|
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
updateVisibleRangeBasedOnScroll();
|
updateVisibleRangeBasedOnScroll();
|
||||||
};
|
};
|
||||||
scrollableDivRef.current?.addEventListener("scroll", handleScroll);
|
|
||||||
|
scrollableDiv?.addEventListener("scroll", handleScroll);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
scrollableDivRef.current?.removeEventListener("scroll", handleScroll);
|
scrollableDiv?.removeEventListener("scroll", handleScroll);
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [messageHistory]);
|
}, [messageHistory]);
|
||||||
|
|
||||||
const currentVisibleRange = visibleRange.get(currentSessionId()) || {
|
const currentVisibleRange = visibleRange.get(currentSessionId()) || {
|
||||||
@ -1728,6 +1735,7 @@ export function ChatPage({
|
|||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("keydown", handleKeyDown);
|
window.removeEventListener("keydown", handleKeyDown);
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [router]);
|
}, [router]);
|
||||||
const [sharedChatSession, setSharedChatSession] =
|
const [sharedChatSession, setSharedChatSession] =
|
||||||
useState<ChatSession | null>();
|
useState<ChatSession | null>();
|
||||||
|
@ -17,7 +17,7 @@ export function ChatPopup() {
|
|||||||
setCompletedFlow(
|
setCompletedFlow(
|
||||||
localStorage.getItem(ALL_USERS_INITIAL_POPUP_FLOW_COMPLETED) === "true"
|
localStorage.getItem(ALL_USERS_INITIAL_POPUP_FLOW_COMPLETED) === "true"
|
||||||
);
|
);
|
||||||
});
|
}, []);
|
||||||
|
|
||||||
const settings = useContext(SettingsContext);
|
const settings = useContext(SettingsContext);
|
||||||
const enterpriseSettings = settings?.enterpriseSettings;
|
const enterpriseSettings = settings?.enterpriseSettings;
|
||||||
|
@ -14,7 +14,6 @@ import { destructureValue, getFinalLLM, structureValue } from "@/lib/llm/utils";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Hoverable } from "@/components/Hoverable";
|
import { Hoverable } from "@/components/Hoverable";
|
||||||
import { Popover } from "@/components/popover/Popover";
|
import { Popover } from "@/components/popover/Popover";
|
||||||
import { FiStar } from "react-icons/fi";
|
|
||||||
import { StarFeedback } from "@/components/icons/icons";
|
import { StarFeedback } from "@/components/icons/icons";
|
||||||
import { IconType } from "react-icons";
|
import { IconType } from "react-icons";
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ export function ChatDocumentDisplay({
|
|||||||
"rounded-lg flex font-bold flex-shrink truncate" +
|
"rounded-lg flex font-bold flex-shrink truncate" +
|
||||||
(document.link ? "" : "pointer-events-none")
|
(document.link ? "" : "pointer-events-none")
|
||||||
}
|
}
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
{isInternet ? (
|
{isInternet ? (
|
||||||
<InternetSearchIcon url={document.link} />
|
<InternetSearchIcon url={document.link} />
|
||||||
|
@ -3,7 +3,7 @@ import { Divider, Text } from "@tremor/react";
|
|||||||
import { ChatDocumentDisplay } from "./ChatDocumentDisplay";
|
import { ChatDocumentDisplay } from "./ChatDocumentDisplay";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { removeDuplicateDocs } from "@/lib/documentUtils";
|
import { removeDuplicateDocs } from "@/lib/documentUtils";
|
||||||
import { Message, RetrievalType } from "../interfaces";
|
import { Message } from "../interfaces";
|
||||||
import { ForwardedRef, forwardRef } from "react";
|
import { ForwardedRef, forwardRef } from "react";
|
||||||
|
|
||||||
interface DocumentSidebarProps {
|
interface DocumentSidebarProps {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { ChatFileType, FileDescriptor } from "../interfaces";
|
import { FileDescriptor } from "../interfaces";
|
||||||
|
|
||||||
import { FiX, FiLoader, FiFileText } from "react-icons/fi";
|
import { FiX, FiLoader, FiFileText } from "react-icons/fi";
|
||||||
import { InputBarPreviewImage } from "./images/InputBarPreviewImage";
|
import { InputBarPreviewImage } from "./images/InputBarPreviewImage";
|
||||||
|
@ -30,6 +30,7 @@ export function InputBarPreviewImage({ fileId }: { fileId: string }) {
|
|||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
alt="preview"
|
||||||
onClick={() => setFullImageShowing(true)}
|
onClick={() => setFullImageShowing(true)}
|
||||||
className="h-8 w-8 object-cover rounded-lg bg-background cursor-pointer"
|
className="h-8 w-8 object-cover rounded-lg bg-background cursor-pointer"
|
||||||
src={buildImgUrl(fileId)}
|
src={buildImgUrl(fileId)}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { useState, useEffect, FC } from "react";
|
|
||||||
|
|
||||||
// Function to create a new folder
|
// Function to create a new folder
|
||||||
export async function createFolder(folderName: string): Promise<number> {
|
export async function createFolder(folderName: string): Promise<number> {
|
||||||
const response = await fetch("/api/folder", {
|
const response = await fetch("/api/folder", {
|
||||||
|
@ -98,7 +98,7 @@ export function ChatInputBar({
|
|||||||
MAX_INPUT_HEIGHT
|
MAX_INPUT_HEIGHT
|
||||||
)}px`;
|
)}px`;
|
||||||
}
|
}
|
||||||
}, [message]);
|
}, [message, textAreaRef]);
|
||||||
|
|
||||||
const handlePaste = (event: React.ClipboardEvent) => {
|
const handlePaste = (event: React.ClipboardEvent) => {
|
||||||
const items = event.clipboardData?.items;
|
const items = event.clipboardData?.items;
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import {
|
import { ChevronDownIcon, IconProps } from "@/components/icons/icons";
|
||||||
ChevronDownIcon,
|
|
||||||
ChevronRightIcon,
|
|
||||||
IconProps,
|
|
||||||
} from "@/components/icons/icons";
|
|
||||||
|
|
||||||
interface ChatInputOptionProps {
|
interface ChatInputOptionProps {
|
||||||
name?: string;
|
name?: string;
|
||||||
|
@ -4,16 +4,9 @@ import {
|
|||||||
Filters,
|
Filters,
|
||||||
StreamStopInfo,
|
StreamStopInfo,
|
||||||
} from "@/lib/search/interfaces";
|
} from "@/lib/search/interfaces";
|
||||||
import { handleSSEStream, handleStream } from "@/lib/search/streamingUtils";
|
import { handleSSEStream } from "@/lib/search/streamingUtils";
|
||||||
import { ChatState, FeedbackType } from "./types";
|
import { ChatState, FeedbackType } from "./types";
|
||||||
import {
|
import { MutableRefObject, RefObject, useEffect, useRef } from "react";
|
||||||
Dispatch,
|
|
||||||
MutableRefObject,
|
|
||||||
RefObject,
|
|
||||||
SetStateAction,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
} from "react";
|
|
||||||
import {
|
import {
|
||||||
BackendMessage,
|
BackendMessage,
|
||||||
ChatSession,
|
ChatSession,
|
||||||
@ -664,7 +657,7 @@ export async function useScrollonStream({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (chatState != "input" && scrollableDivRef && scrollableDivRef.current) {
|
if (chatState != "input" && scrollableDivRef && scrollableDivRef.current) {
|
||||||
let newHeight: number = scrollableDivRef.current?.scrollTop!;
|
const newHeight: number = scrollableDivRef.current?.scrollTop!;
|
||||||
const heightDifference = newHeight - previousScroll.current;
|
const heightDifference = newHeight - previousScroll.current;
|
||||||
previousScroll.current = newHeight;
|
previousScroll.current = newHeight;
|
||||||
|
|
||||||
@ -729,5 +722,5 @@ export async function useScrollonStream({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [chatState]);
|
}, [chatState, distance, scrollDist, scrollableDivRef]);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { EmphasizedClickable } from "@/components/BasicClickable";
|
import { EmphasizedClickable } from "@/components/BasicClickable";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { FiBook, FiPlayCircle } from "react-icons/fi";
|
import { FiPlayCircle } from "react-icons/fi";
|
||||||
|
|
||||||
export function ContinueGenerating({
|
export function ContinueGenerating({
|
||||||
handleContinueGenerating,
|
handleContinueGenerating,
|
||||||
|
@ -202,7 +202,7 @@ export const AIMessage = ({
|
|||||||
|
|
||||||
const selectedDocumentIds =
|
const selectedDocumentIds =
|
||||||
selectedDocuments?.map((document) => document.document_id) || [];
|
selectedDocuments?.map((document) => document.document_id) || [];
|
||||||
let citedDocumentIds: string[] = [];
|
const citedDocumentIds: string[] = [];
|
||||||
|
|
||||||
citedDocuments?.forEach((doc) => {
|
citedDocuments?.forEach((doc) => {
|
||||||
citedDocumentIds.push(doc[1].document_id);
|
citedDocumentIds.push(doc[1].document_id);
|
||||||
@ -272,7 +272,7 @@ export const AIMessage = ({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[messageId, content]
|
[finalContent]
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderedMarkdown = useMemo(() => {
|
const renderedMarkdown = useMemo(() => {
|
||||||
@ -286,7 +286,7 @@ export const AIMessage = ({
|
|||||||
{finalContent as string}
|
{finalContent as string}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
);
|
);
|
||||||
}, [finalContent]);
|
}, [finalContent, markdownComponents]);
|
||||||
|
|
||||||
const includeMessageSwitcher =
|
const includeMessageSwitcher =
|
||||||
currentMessageInd !== undefined &&
|
currentMessageInd !== undefined &&
|
||||||
@ -412,6 +412,7 @@ export const AIMessage = ({
|
|||||||
href={doc.link || undefined}
|
href={doc.link || undefined}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="text-sm flex w-full pt-1 gap-x-1.5 overflow-hidden justify-between font-semibold text-text-700"
|
className="text-sm flex w-full pt-1 gap-x-1.5 overflow-hidden justify-between font-semibold text-text-700"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
<Citation link={doc.link} index={ind + 1} />
|
<Citation link={doc.link} index={ind + 1} />
|
||||||
<p className="shrink truncate ellipsis break-all">
|
<p className="shrink truncate ellipsis break-all">
|
||||||
@ -670,7 +671,7 @@ export const HumanMessage = ({
|
|||||||
if (!isEditing) {
|
if (!isEditing) {
|
||||||
setEditedContent(content);
|
setEditedContent(content);
|
||||||
}
|
}
|
||||||
}, [content]);
|
}, [content, isEditing]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (textareaRef.current) {
|
if (textareaRef.current) {
|
||||||
|
@ -83,7 +83,7 @@ export function SearchSummary({
|
|||||||
if (!isEditing) {
|
if (!isEditing) {
|
||||||
setFinalQuery(query);
|
setFinalQuery(query);
|
||||||
}
|
}
|
||||||
}, [query]);
|
}, [query, isEditing]);
|
||||||
|
|
||||||
const searchingForDisplay = (
|
const searchingForDisplay = (
|
||||||
<div className={`flex p-1 rounded ${isOverflowed && "cursor-default"}`}>
|
<div className={`flex p-1 rounded ${isOverflowed && "cursor-default"}`}>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { EmphasizedClickable } from "@/components/BasicClickable";
|
import { EmphasizedClickable } from "@/components/BasicClickable";
|
||||||
import { FiArchive, FiBook, FiSearch } from "react-icons/fi";
|
import { FiBook } from "react-icons/fi";
|
||||||
|
|
||||||
function ForceSearchButton({
|
function ForceSearchButton({
|
||||||
messageId,
|
messageId,
|
||||||
|
@ -2,13 +2,8 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FeedbackType } from "../types";
|
import { FeedbackType } from "../types";
|
||||||
import { FiThumbsDown, FiThumbsUp } from "react-icons/fi";
|
|
||||||
import { ModalWrapper } from "@/components/modals/ModalWrapper";
|
import { ModalWrapper } from "@/components/modals/ModalWrapper";
|
||||||
import {
|
import { FilledLikeIcon } from "@/components/icons/icons";
|
||||||
DislikeFeedbackIcon,
|
|
||||||
FilledLikeIcon,
|
|
||||||
LikeFeedbackIcon,
|
|
||||||
} from "@/components/icons/icons";
|
|
||||||
|
|
||||||
const predefinedPositiveFeedbackOptions =
|
const predefinedPositiveFeedbackOptions =
|
||||||
process.env.NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS?.split(",") ||
|
process.env.NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS?.split(",") ||
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Dispatch, SetStateAction, useState, useEffect, useRef } from "react";
|
import { Dispatch, SetStateAction, useEffect, useRef } from "react";
|
||||||
import { ModalWrapper } from "@/components/modals/ModalWrapper";
|
import { ModalWrapper } from "@/components/modals/ModalWrapper";
|
||||||
import { Badge, Text } from "@tremor/react";
|
import { Text } from "@tremor/react";
|
||||||
import { getDisplayNameForModel, LlmOverride } from "@/lib/hooks";
|
import { getDisplayNameForModel, LlmOverride } from "@/lib/hooks";
|
||||||
import { LLMProviderDescriptor } from "@/app/admin/configuration/llm/interfaces";
|
import { LLMProviderDescriptor } from "@/app/admin/configuration/llm/interfaces";
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { ModalWrapper } from "@/components/modals/ModalWrapper";
|
|||||||
import { Button, Callout, Divider, Text } from "@tremor/react";
|
import { Button, Callout, Divider, Text } from "@tremor/react";
|
||||||
import { Spinner } from "@/components/Spinner";
|
import { Spinner } from "@/components/Spinner";
|
||||||
import { ChatSessionSharedStatus } from "../interfaces";
|
import { ChatSessionSharedStatus } from "../interfaces";
|
||||||
import { FiCopy, FiX } from "react-icons/fi";
|
import { FiCopy } from "react-icons/fi";
|
||||||
import { CopyButton } from "@/components/CopyButton";
|
import { CopyButton } from "@/components/CopyButton";
|
||||||
|
|
||||||
function buildShareLink(chatSessionId: number) {
|
function buildShareLink(chatSessionId: number) {
|
||||||
@ -82,6 +82,7 @@ export function ShareChatSessionModal({
|
|||||||
href={shareLink}
|
href={shareLink}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="underline text-link mt-1 ml-1 text-sm my-auto"
|
className="underline text-link mt-1 ml-1 text-sm my-auto"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
{shareLink}
|
{shareLink}
|
||||||
</a>
|
</a>
|
||||||
|
@ -19,7 +19,6 @@ import { getFinalLLM } from "@/lib/llm/utils";
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { updateUserAssistantList } from "@/lib/assistants/updateAssistantPreferences";
|
import { updateUserAssistantList } from "@/lib/assistants/updateAssistantPreferences";
|
||||||
import { DraggableAssistantCard } from "@/components/assistants/AssistantCards";
|
import { DraggableAssistantCard } from "@/components/assistants/AssistantCards";
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
|
|
||||||
export function AssistantsTab({
|
export function AssistantsTab({
|
||||||
selectedAssistant,
|
selectedAssistant,
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import { useChatContext } from "@/components/context/ChatContext";
|
import { useChatContext } from "@/components/context/ChatContext";
|
||||||
import { getDisplayNameForModel, LlmOverrideManager } from "@/lib/hooks";
|
import { LlmOverrideManager } from "@/lib/hooks";
|
||||||
import React, { forwardRef, useCallback, useState } from "react";
|
import React, { forwardRef, useCallback, useState } from "react";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import { Text } from "@tremor/react";
|
import { Text } from "@tremor/react";
|
||||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||||
import {
|
import { destructureValue } from "@/lib/llm/utils";
|
||||||
checkLLMSupportsImageInput,
|
|
||||||
destructureValue,
|
|
||||||
structureValue,
|
|
||||||
} from "@/lib/llm/utils";
|
|
||||||
import { updateModelOverrideForChatSession } from "../../lib";
|
import { updateModelOverrideForChatSession } from "../../lib";
|
||||||
import { GearIcon } from "@/components/icons/icons";
|
import { GearIcon } from "@/components/icons/icons";
|
||||||
import { LlmList } from "@/components/llm/LLMList";
|
import { LlmList } from "@/components/llm/LLMList";
|
||||||
@ -44,12 +40,14 @@ export const LlmTab = forwardRef<HTMLDivElement, LlmTabProps>(
|
|||||||
const [localTemperature, setLocalTemperature] = useState<number>(
|
const [localTemperature, setLocalTemperature] = useState<number>(
|
||||||
temperature || 0
|
temperature || 0
|
||||||
);
|
);
|
||||||
|
|
||||||
const debouncedSetTemperature = useCallback(
|
const debouncedSetTemperature = useCallback(
|
||||||
debounce((value) => {
|
(value: number) => {
|
||||||
|
const debouncedFunction = debounce((value: number) => {
|
||||||
setTemperature(value);
|
setTemperature(value);
|
||||||
}, 300),
|
}, 300);
|
||||||
[]
|
return debouncedFunction(value);
|
||||||
|
},
|
||||||
|
[setTemperature]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleTemperatureChange = (value: number) => {
|
const handleTemperatureChange = (value: number) => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { BasicClickable } from "@/components/BasicClickable";
|
import { BasicClickable } from "@/components/BasicClickable";
|
||||||
import { ControlledPopup, DefaultDropdownElement } from "@/components/Dropdown";
|
import { ControlledPopup, DefaultDropdownElement } from "@/components/Dropdown";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FiCpu, FiFilter, FiSearch } from "react-icons/fi";
|
import { FiCpu, FiSearch } from "react-icons/fi";
|
||||||
|
|
||||||
export const QA = "Question Answering";
|
export const QA = "Question Answering";
|
||||||
export const SEARCH = "Search Only";
|
export const SEARCH = "Search Only";
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { BasicClickable } from "@/components/BasicClickable";
|
import { BasicClickable } from "@/components/BasicClickable";
|
||||||
import { DanswerDocument } from "@/lib/search/interfaces";
|
import { DanswerDocument } from "@/lib/search/interfaces";
|
||||||
import { useState } from "react";
|
import { FiBook } from "react-icons/fi";
|
||||||
import { FiBook, FiFilter } from "react-icons/fi";
|
|
||||||
|
|
||||||
export function SelectedDocuments({
|
export function SelectedDocuments({
|
||||||
selectedDocuments,
|
selectedDocuments,
|
||||||
|
@ -5,8 +5,6 @@ import { WelcomeModal } from "@/components/initialSetup/welcome/WelcomeModalWrap
|
|||||||
import { ChatProvider } from "@/components/context/ChatContext";
|
import { ChatProvider } from "@/components/context/ChatContext";
|
||||||
import { fetchChatData } from "@/lib/chat/fetchChatData";
|
import { fetchChatData } from "@/lib/chat/fetchChatData";
|
||||||
import WrappedChat from "./WrappedChat";
|
import WrappedChat from "./WrappedChat";
|
||||||
import { ProviderContextProvider } from "@/components/chat_search/ProviderContext";
|
|
||||||
import { orderAssistantsForUser } from "@/lib/assistants/utils";
|
|
||||||
|
|
||||||
export default async function Page({
|
export default async function Page({
|
||||||
searchParams,
|
searchParams,
|
||||||
|
@ -3,11 +3,7 @@
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { ChatSession } from "../interfaces";
|
import { ChatSession } from "../interfaces";
|
||||||
import { useState, useEffect, useContext } from "react";
|
import { useState, useEffect, useContext } from "react";
|
||||||
import {
|
import { getChatRetentionInfo, renameChatSession } from "../lib";
|
||||||
deleteChatSession,
|
|
||||||
getChatRetentionInfo,
|
|
||||||
renameChatSession,
|
|
||||||
} from "../lib";
|
|
||||||
import { BasicSelectable } from "@/components/BasicClickable";
|
import { BasicSelectable } from "@/components/BasicClickable";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {
|
import {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FiEdit, FiFolderPlus } from "react-icons/fi";
|
import { FiEdit, FiFolderPlus } from "react-icons/fi";
|
||||||
import { ForwardedRef, forwardRef, useContext, useState } from "react";
|
import React, { ForwardedRef, forwardRef, useContext, useState } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { ChatSession } from "../interfaces";
|
import { ChatSession } from "../interfaces";
|
||||||
@ -11,7 +11,6 @@ import { createFolder } from "../folders/FolderManagement";
|
|||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import {
|
import {
|
||||||
AssistantsIconSkeleton,
|
AssistantsIconSkeleton,
|
||||||
ClosedBookIcon,
|
ClosedBookIcon,
|
||||||
|
@ -7,7 +7,7 @@ import { Folder } from "../folders/interfaces";
|
|||||||
import { CHAT_SESSION_ID_KEY, FOLDER_ID_KEY } from "@/lib/drag/constants";
|
import { CHAT_SESSION_ID_KEY, FOLDER_ID_KEY } from "@/lib/drag/constants";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import { pageType } from "./types";
|
import { pageType } from "./types";
|
||||||
|
|
||||||
export function PagesTab({
|
export function PagesTab({
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
} from "@/components/admin/connectors/Field";
|
} from "@/components/admin/connectors/Field";
|
||||||
import { createApiKey, updateApiKey } from "./lib";
|
import { createApiKey, updateApiKey } from "./lib";
|
||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import { XIcon } from "@/components/icons/icons";
|
|
||||||
import { Button, Divider, Text } from "@tremor/react";
|
import { Button, Divider, Text } from "@tremor/react";
|
||||||
import { UserRole } from "@/lib/types";
|
import { UserRole } from "@/lib/types";
|
||||||
import { APIKey } from "./types";
|
import { APIKey } from "./types";
|
||||||
|
@ -16,10 +16,10 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
|
Table,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Table } from "@tremor/react";
|
|
||||||
import { DeleteButton } from "@/components/DeleteButton";
|
import { DeleteButton } from "@/components/DeleteButton";
|
||||||
import { FiCopy, FiEdit2, FiRefreshCw, FiX } from "react-icons/fi";
|
import { FiCopy, FiEdit2, FiRefreshCw, FiX } from "react-icons/fi";
|
||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
|
@ -19,7 +19,7 @@ export const ConnectorEditor = ({
|
|||||||
.filter((ccPair) => !(ccPair.access_type === "public"))
|
.filter((ccPair) => !(ccPair.access_type === "public"))
|
||||||
.map((ccPair) => {
|
.map((ccPair) => {
|
||||||
const ind = selectedCCPairIds.indexOf(ccPair.cc_pair_id);
|
const ind = selectedCCPairIds.indexOf(ccPair.cc_pair_id);
|
||||||
let isSelected = ind !== -1;
|
const isSelected = ind !== -1;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={`${ccPair.connector.id}-${ccPair.credential.id}`}
|
key={`${ccPair.connector.id}-${ccPair.credential.id}`}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { User } from "@/lib/types";
|
import { User } from "@/lib/types";
|
||||||
import { useState } from "react";
|
|
||||||
import { FiPlus, FiX } from "react-icons/fi";
|
import { FiPlus, FiX } from "react-icons/fi";
|
||||||
import { SearchMultiSelectDropdown } from "@/components/Dropdown";
|
import { SearchMultiSelectDropdown } from "@/components/Dropdown";
|
||||||
import { UsersIcon } from "@/components/icons/icons";
|
import { UsersIcon } from "@/components/icons/icons";
|
||||||
|
@ -3,12 +3,10 @@ import * as Yup from "yup";
|
|||||||
import { PopupSpec } from "@/components/admin/connectors/Popup";
|
import { PopupSpec } from "@/components/admin/connectors/Popup";
|
||||||
import { ConnectorIndexingStatus, User, UserGroup } from "@/lib/types";
|
import { ConnectorIndexingStatus, User, UserGroup } from "@/lib/types";
|
||||||
import { TextFormField } from "@/components/admin/connectors/Field";
|
import { TextFormField } from "@/components/admin/connectors/Field";
|
||||||
import { ConnectorTitle } from "@/components/admin/connectors/ConnectorTitle";
|
|
||||||
import { createUserGroup } from "./lib";
|
import { createUserGroup } from "./lib";
|
||||||
import { UserEditor } from "./UserEditor";
|
import { UserEditor } from "./UserEditor";
|
||||||
import { ConnectorEditor } from "./ConnectorEditor";
|
import { ConnectorEditor } from "./ConnectorEditor";
|
||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import { XIcon } from "@/components/icons/icons";
|
|
||||||
import { Button, Divider } from "@tremor/react";
|
import { Button, Divider } from "@tremor/react";
|
||||||
|
|
||||||
interface UserGroupCreationFormProps {
|
interface UserGroupCreationFormProps {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Button } from "@/components/Button";
|
import { Button } from "@/components/Button";
|
||||||
import { SearchMultiSelectDropdown } from "@/components/Dropdown";
|
import { SearchMultiSelectDropdown } from "@/components/Dropdown";
|
||||||
import { Modal } from "@/components/Modal";
|
import { Modal } from "@/components/Modal";
|
||||||
import { UsersIcon } from "@/components/icons/icons";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FiPlus, FiX } from "react-icons/fi";
|
import { FiPlus, FiX } from "react-icons/fi";
|
||||||
import { updateUserGroup } from "./lib";
|
import { updateUserGroup } from "./lib";
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { GroupsIcon } from "@/components/icons/icons";
|
import { GroupsIcon } from "@/components/icons/icons";
|
||||||
import { GroupDisplay } from "./GroupDisplay";
|
import { GroupDisplay } from "./GroupDisplay";
|
||||||
import { FiAlertCircle, FiChevronLeft } from "react-icons/fi";
|
|
||||||
import { useSpecificUserGroup } from "./hook";
|
import { useSpecificUserGroup } from "./hook";
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import { useConnectorCredentialIndexingStatus, useUsers } from "@/lib/hooks";
|
import { useConnectorCredentialIndexingStatus, useUsers } from "@/lib/hooks";
|
||||||
|
@ -4,9 +4,7 @@ import { GroupsIcon } from "@/components/icons/icons";
|
|||||||
import { UserGroupsTable } from "./UserGroupsTable";
|
import { UserGroupsTable } from "./UserGroupsTable";
|
||||||
import { UserGroupCreationForm } from "./UserGroupCreationForm";
|
import { UserGroupCreationForm } from "./UserGroupCreationForm";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import { useState, useEffect } from "react";
|
import { useState } from "react";
|
||||||
import { getCurrentUser } from "@/lib/user";
|
|
||||||
import { User, UserRole } from "@/lib/types";
|
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import {
|
import {
|
||||||
useConnectorCredentialIndexingStatus,
|
useConnectorCredentialIndexingStatus,
|
||||||
|
@ -9,9 +9,10 @@ import {
|
|||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
Text,
|
Text,
|
||||||
|
Divider,
|
||||||
|
Select,
|
||||||
|
SelectItem,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { Divider } from "@tremor/react";
|
|
||||||
import { Select, SelectItem } from "@tremor/react";
|
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import { ChatSessionMinimal } from "../usage/types";
|
import { ChatSessionMinimal } from "../usage/types";
|
||||||
import { timestampToReadableDate } from "@/lib/dateUtils";
|
import { timestampToReadableDate } from "@/lib/dateUtils";
|
||||||
|
@ -30,7 +30,12 @@ function MessageDisplay({ message }: { message: MessageSnapshot }) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{document.link ? (
|
{document.link ? (
|
||||||
<a href={document.link} target="_blank" className="text-link">
|
<a
|
||||||
|
href={document.link}
|
||||||
|
target="_blank"
|
||||||
|
className="text-link"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
{document.semantic_identifier}
|
{document.semantic_identifier}
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
|
@ -16,9 +16,9 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
|
Button,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { Button } from "@tremor/react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { UsageReport } from "./types";
|
import { UsageReport } from "./types";
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
@ -36,7 +36,7 @@ function GenerateReportInput() {
|
|||||||
const [errorOccurred, setErrorOccurred] = useState<Error | null>(null);
|
const [errorOccurred, setErrorOccurred] = useState<Error | null>(null);
|
||||||
|
|
||||||
const download = (bytes: Blob) => {
|
const download = (bytes: Blob) => {
|
||||||
let elm = document.createElement("a");
|
const elm = document.createElement("a");
|
||||||
elm.href = URL.createObjectURL(bytes);
|
elm.href = URL.createObjectURL(bytes);
|
||||||
elm.setAttribute("download", "usage_reports.zip");
|
elm.setAttribute("download", "usage_reports.zip");
|
||||||
elm.click();
|
elm.click();
|
||||||
|
@ -4,7 +4,6 @@ import { DateRangeSelector } from "../DateRangeSelector";
|
|||||||
import { DanswerBotChart } from "./DanswerBotChart";
|
import { DanswerBotChart } from "./DanswerBotChart";
|
||||||
import { FeedbackChart } from "./FeedbackChart";
|
import { FeedbackChart } from "./FeedbackChart";
|
||||||
import { QueryPerformanceChart } from "./QueryPerformanceChart";
|
import { QueryPerformanceChart } from "./QueryPerformanceChart";
|
||||||
import { BarChartIcon } from "@/components/icons/icons";
|
|
||||||
import { useTimeRange } from "../lib";
|
import { useTimeRange } from "../lib";
|
||||||
import { AdminPageTitle } from "@/components/admin/Title";
|
import { AdminPageTitle } from "@/components/admin/Title";
|
||||||
import { FiActivity } from "react-icons/fi";
|
import { FiActivity } from "react-icons/fi";
|
||||||
|
@ -3,7 +3,6 @@ import { StandardAnswerCreationForm } from "@/app/ee/admin/standard-answer/Stand
|
|||||||
import { fetchSS } from "@/lib/utilsSS";
|
import { fetchSS } from "@/lib/utilsSS";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { BackButton } from "@/components/BackButton";
|
import { BackButton } from "@/components/BackButton";
|
||||||
import { Text } from "@tremor/react";
|
|
||||||
import { ClipboardIcon } from "@/components/icons/icons";
|
import { ClipboardIcon } from "@/components/icons/icons";
|
||||||
import { StandardAnswer, StandardAnswerCategory } from "@/lib/types";
|
import { StandardAnswer, StandardAnswerCategory } from "@/lib/types";
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ import { StandardAnswerCreationForm } from "@/app/ee/admin/standard-answer/Stand
|
|||||||
import { fetchSS } from "@/lib/utilsSS";
|
import { fetchSS } from "@/lib/utilsSS";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { BackButton } from "@/components/BackButton";
|
import { BackButton } from "@/components/BackButton";
|
||||||
import { Text } from "@tremor/react";
|
|
||||||
import { ClipboardIcon } from "@/components/icons/icons";
|
import { ClipboardIcon } from "@/components/icons/icons";
|
||||||
import { StandardAnswerCategory } from "@/lib/types";
|
import { StandardAnswerCategory } from "@/lib/types";
|
||||||
|
|
||||||
|
@ -6,12 +6,10 @@ import { PopupSpec, usePopup } from "@/components/admin/connectors/Popup";
|
|||||||
import { useStandardAnswers, useStandardAnswerCategories } from "./hooks";
|
import { useStandardAnswers, useStandardAnswerCategories } from "./hooks";
|
||||||
import { ThreeDotsLoader } from "@/components/Loading";
|
import { ThreeDotsLoader } from "@/components/Loading";
|
||||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||||
import { Button, Divider, Text } from "@tremor/react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { StandardAnswer, StandardAnswerCategory } from "@/lib/types";
|
|
||||||
import { MagnifyingGlass } from "@phosphor-icons/react";
|
|
||||||
import { useState } from "react";
|
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
|
Divider,
|
||||||
|
Text,
|
||||||
Table,
|
Table,
|
||||||
TableHead,
|
TableHead,
|
||||||
TableRow,
|
TableRow,
|
||||||
@ -19,12 +17,15 @@ import {
|
|||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { StandardAnswer, StandardAnswerCategory } from "@/lib/types";
|
||||||
|
import { MagnifyingGlass } from "@phosphor-icons/react";
|
||||||
|
import { useState } from "react";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
import { deleteStandardAnswer } from "./lib";
|
import { deleteStandardAnswer } from "./lib";
|
||||||
import { FilterDropdown } from "@/components/search/filtering/FilterDropdown";
|
import { FilterDropdown } from "@/components/search/filtering/FilterDropdown";
|
||||||
import { FiTag } from "react-icons/fi";
|
import { FiTag } from "react-icons/fi";
|
||||||
import { SelectedBubble } from "@/components/search/filtering/Filters";
|
|
||||||
import { PageSelector } from "@/components/PageSelector";
|
import { PageSelector } from "@/components/PageSelector";
|
||||||
import { CustomCheckbox } from "@/components/CustomCheckbox";
|
import { CustomCheckbox } from "@/components/CustomCheckbox";
|
||||||
|
|
||||||
|
@ -61,7 +61,11 @@ export function ImageUpload({
|
|||||||
{tmpImageUrl && (
|
{tmpImageUrl && (
|
||||||
<div className="mt-4 mb-8">
|
<div className="mt-4 mb-8">
|
||||||
<SubLabel>Uploaded Image:</SubLabel>
|
<SubLabel>Uploaded Image:</SubLabel>
|
||||||
<img src={tmpImageUrl} className="mt-4 max-w-xs max-h-64" />
|
<img
|
||||||
|
alt="Uploaded Image"
|
||||||
|
src={tmpImageUrl}
|
||||||
|
className="mt-4 max-w-xs max-h-64"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
@ -6,12 +6,11 @@ import {
|
|||||||
} from "@/components/settings/lib";
|
} from "@/components/settings/lib";
|
||||||
import {
|
import {
|
||||||
CUSTOM_ANALYTICS_ENABLED,
|
CUSTOM_ANALYTICS_ENABLED,
|
||||||
EE_ENABLED,
|
|
||||||
SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED,
|
SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED,
|
||||||
} from "@/lib/constants";
|
} from "@/lib/constants";
|
||||||
import { SettingsProvider } from "@/components/settings/SettingsProvider";
|
import { SettingsProvider } from "@/components/settings/SettingsProvider";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
import { buildClientUrl, fetchSS } from "@/lib/utilsSS";
|
import { buildClientUrl } from "@/lib/utilsSS";
|
||||||
import { Inter } from "next/font/google";
|
import { Inter } from "next/font/google";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { EnterpriseSettings } from "./admin/settings/interfaces";
|
import { EnterpriseSettings } from "./admin/settings/interfaces";
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user