mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-23 19:05:16 +02:00
refactor: update alert components across various files to use a consistent structure and styling
This commit is contained in:
parent
e0ecea61f8
commit
b7a6e3af3d
34 changed files with 372 additions and 619 deletions
|
|
@ -218,13 +218,13 @@ export function AgentPermissionsContent() {
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
return (
|
return (
|
||||||
<div className="rounded-lg border border-dashed border-destructive/40 p-8 text-center">
|
<Alert variant="destructive">
|
||||||
<AlertTriangle className="mx-auto size-8 text-destructive/60" />
|
<AlertTriangle />
|
||||||
<p className="mt-2 text-sm text-destructive">Failed to load rules</p>
|
<AlertTitle>Failed to load rules</AlertTitle>
|
||||||
<p className="text-xs text-muted-foreground">
|
<AlertDescription>
|
||||||
{error instanceof Error ? error.message : "Unknown error."}
|
{error instanceof Error ? error.message : "Unknown error."}
|
||||||
</p>
|
</AlertDescription>
|
||||||
</div>
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { AlertTriangle, Copy, Globe, Sparkles } from "lucide-react";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { copyPromptMutationAtom } from "@/atoms/prompts/prompts-mutation.atoms";
|
import { copyPromptMutationAtom } from "@/atoms/prompts/prompts-mutation.atoms";
|
||||||
import { publicPromptsAtom } from "@/atoms/prompts/prompts-query.atoms";
|
import { publicPromptsAtom } from "@/atoms/prompts/prompts-query.atoms";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Spinner } from "@/components/ui/spinner";
|
import { Spinner } from "@/components/ui/spinner";
|
||||||
|
|
||||||
|
|
@ -44,11 +45,11 @@ export function CommunityPromptsContent() {
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
return (
|
return (
|
||||||
<div className="rounded-lg border border-dashed border-destructive/40 p-8 text-center">
|
<Alert variant="destructive">
|
||||||
<AlertTriangle className="mx-auto size-8 text-destructive/60" />
|
<AlertTriangle />
|
||||||
<p className="mt-2 text-sm text-destructive">Failed to load community prompts</p>
|
<AlertTitle>Failed to load community prompts</AlertTitle>
|
||||||
<p className="text-xs text-muted-foreground">Please try refreshing the page.</p>
|
<AlertDescription>Please try refreshing the page.</AlertDescription>
|
||||||
</div>
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -177,9 +177,9 @@ export function MemoryContent() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
<p>
|
<p>
|
||||||
SurfSense uses this personal memory to personalize your responses across all
|
SurfSense uses this personal memory to personalize your responses across all
|
||||||
conversations.
|
conversations.
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import {
|
||||||
AlertDialogHeader,
|
AlertDialogHeader,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
} from "@/components/ui/alert-dialog";
|
} from "@/components/ui/alert-dialog";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
|
@ -133,11 +134,11 @@ export function PromptsContent() {
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
return (
|
return (
|
||||||
<div className="rounded-lg border border-dashed border-destructive/40 p-8 text-center">
|
<Alert variant="destructive">
|
||||||
<AlertTriangle className="mx-auto size-8 text-destructive/60" />
|
<AlertTriangle />
|
||||||
<p className="mt-2 text-sm text-destructive">Failed to load prompts</p>
|
<AlertTitle>Failed to load prompts</AlertTitle>
|
||||||
<p className="text-xs text-muted-foreground">Please try refreshing the page.</p>
|
<AlertDescription>Please try refreshing the page.</AlertDescription>
|
||||||
</div>
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -380,14 +380,12 @@ export const ConnectorIndicator = forwardRef<ConnectorIndicatorHandle, Connector
|
||||||
<div className="px-4 sm:px-12 py-4 sm:py-8 pb-12 sm:pb-16">
|
<div className="px-4 sm:px-12 py-4 sm:py-8 pb-12 sm:pb-16">
|
||||||
{/* LLM Configuration Warning */}
|
{/* LLM Configuration Warning */}
|
||||||
{!llmConfigLoading && !hasDocumentSummaryLLM && (
|
{!llmConfigLoading && !hasDocumentSummaryLLM && (
|
||||||
<Alert
|
<div className="mb-6">
|
||||||
variant="destructive"
|
<Alert variant="destructive">
|
||||||
className="mb-6 bg-muted/50 rounded-xl border-destructive/30"
|
<AlertTriangle />
|
||||||
>
|
|
||||||
<AlertTriangle className="h-4 w-4" />
|
|
||||||
<AlertTitle>LLM Configuration Required</AlertTitle>
|
<AlertTitle>LLM Configuration Required</AlertTitle>
|
||||||
<AlertDescription className="mt-2">
|
<AlertDescription>
|
||||||
<p className="mb-3">
|
<p>
|
||||||
{isAutoMode && !hasGlobalConfigs
|
{isAutoMode && !hasGlobalConfigs
|
||||||
? "Auto mode requires a global LLM configuration. Please add one in Settings"
|
? "Auto mode requires a global LLM configuration. Please add one in Settings"
|
||||||
: "A Document Summary LLM is required to process uploads, configure one in Settings"}
|
: "A Document Summary LLM is required to process uploads, configure one in Settings"}
|
||||||
|
|
@ -407,6 +405,7 @@ export const ConnectorIndicator = forwardRef<ConnectorIndicatorHandle, Connector
|
||||||
</Button>
|
</Button>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<TabsContent value="all" className="m-0">
|
<TabsContent value="all" className="m-0">
|
||||||
|
|
|
||||||
|
|
@ -70,12 +70,13 @@ export const BaiduSearchApiConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSu
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">API Key Required</AlertTitle>
|
<AlertTitle>API Key Required</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
You'll need a Baidu AppBuilder API key to use this connector. You can get one by signing
|
<p>
|
||||||
up at{" "}
|
You'll need a Baidu AppBuilder API key to use this connector. You can get one by
|
||||||
|
signing up at{" "}
|
||||||
<a
|
<a
|
||||||
href="https://qianfan.cloud.baidu.com/"
|
href="https://qianfan.cloud.baidu.com/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
@ -84,6 +85,7 @@ export const BaiduSearchApiConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSu
|
||||||
>
|
>
|
||||||
qianfan.cloud.baidu.com
|
qianfan.cloud.baidu.com
|
||||||
</a>
|
</a>
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,10 +96,10 @@ export const BookStackConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitt
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">API Token Required</AlertTitle>
|
<AlertTitle>API Token Required</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
You'll need a BookStack API Token to use this connector. You can create one from your
|
You'll need a BookStack API Token to use this connector. You can create one from your
|
||||||
BookStack instance settings.
|
BookStack instance settings.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
|
|
|
||||||
|
|
@ -172,10 +172,10 @@ export const ElasticsearchConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSub
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">API Key Required</AlertTitle>
|
<AlertTitle>API Key Required</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
Enter your Elasticsearch cluster endpoint URL and authentication credentials to connect.
|
Enter your Elasticsearch cluster endpoint URL and authentication credentials to connect.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
@ -428,10 +428,10 @@ export const ElasticsearchConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSub
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20">
|
<Alert>
|
||||||
<Info className="h-3 w-3 sm:h-4 sm:w-4" />
|
<Info />
|
||||||
<AlertTitle className="text-[10px] sm:text-xs">Index Selection Tips</AlertTitle>
|
<AlertTitle>Index Selection Tips</AlertTitle>
|
||||||
<AlertDescription className="text-[9px] sm:text-[10px] mt-2">
|
<AlertDescription>
|
||||||
<ul className="list-disc pl-4 space-y-1">
|
<ul className="list-disc pl-4 space-y-1">
|
||||||
<li>Use wildcards like "logs-*" to match multiple indices</li>
|
<li>Use wildcards like "logs-*" to match multiple indices</li>
|
||||||
<li>Separate multiple indices with commas</li>
|
<li>Separate multiple indices with commas</li>
|
||||||
|
|
@ -643,231 +643,6 @@ export const ElasticsearchConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSub
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Documentation Section */}
|
|
||||||
<Accordion
|
|
||||||
type="single"
|
|
||||||
collapsible
|
|
||||||
className="w-full border border-border rounded-xl bg-slate-400/5 dark:bg-white/5"
|
|
||||||
>
|
|
||||||
<AccordionItem value="documentation" className="border-0">
|
|
||||||
<AccordionTrigger className="text-sm sm:text-base font-medium px-3 sm:px-6 no-underline hover:no-underline">
|
|
||||||
Documentation
|
|
||||||
</AccordionTrigger>
|
|
||||||
<AccordionContent className="px-3 sm:px-6 pb-3 sm:pb-6 space-y-6">
|
|
||||||
<div>
|
|
||||||
<h3 className="text-sm sm:text-base font-semibold mb-2">How it works</h3>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground">
|
|
||||||
The Elasticsearch connector allows you to search and retrieve documents from your
|
|
||||||
Elasticsearch cluster. Configure connection details, select specific indices, and
|
|
||||||
set search parameters to make your existing data searchable within SurfSense.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<h3 className="text-sm sm:text-base font-semibold mb-2">Connection Setup</h3>
|
|
||||||
<div className="space-y-4 sm:space-y-6">
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">
|
|
||||||
Step 1: Get your Elasticsearch endpoint
|
|
||||||
</h4>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground mb-3">
|
|
||||||
You'll need the endpoint URL for your Elasticsearch cluster. This typically
|
|
||||||
looks like:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc pl-5 space-y-1 text-[10px] sm:text-xs text-muted-foreground mb-4">
|
|
||||||
<li>
|
|
||||||
Cloud:{" "}
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded">
|
|
||||||
https://your-cluster.es.region.aws.com:443
|
|
||||||
</code>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Self-hosted:{" "}
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded">
|
|
||||||
https://elasticsearch.example.com:9200
|
|
||||||
</code>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">
|
|
||||||
Step 2: Configure authentication
|
|
||||||
</h4>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground mb-3">
|
|
||||||
Elasticsearch requires authentication. You can use either:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc pl-5 space-y-2 text-[10px] sm:text-xs text-muted-foreground mb-4">
|
|
||||||
<li>
|
|
||||||
<strong>API Key:</strong> A base64-encoded API key. You can create one in
|
|
||||||
Elasticsearch by running:
|
|
||||||
<pre className="bg-muted p-2 rounded mt-1 text-[9px] overflow-x-auto">
|
|
||||||
<code>POST /_security/api_key</code>
|
|
||||||
</pre>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Username & Password:</strong> Basic authentication using your
|
|
||||||
Elasticsearch username and password.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">
|
|
||||||
Step 3: Select indices
|
|
||||||
</h4>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground mb-3">
|
|
||||||
Specify which indices to search. You can:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc pl-5 space-y-1 text-[10px] sm:text-xs text-muted-foreground">
|
|
||||||
<li>
|
|
||||||
Use wildcards: <code className="bg-muted px-1 py-0.5 rounded">logs-*</code>{" "}
|
|
||||||
to match multiple indices
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
List specific indices:{" "}
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded">
|
|
||||||
logs-2024, documents-2024
|
|
||||||
</code>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Leave empty to search all accessible indices (not recommended for
|
|
||||||
performance)
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<h3 className="text-sm sm:text-base font-semibold mb-2">Advanced Configuration</h3>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">Search Query</h4>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground mb-2">
|
|
||||||
The default query used for searches. Use{" "}
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded">*</code> to match all
|
|
||||||
documents, or specify a more complex Elasticsearch query.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">Search Fields</h4>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground mb-2">
|
|
||||||
Limit searches to specific fields for better performance. Common fields
|
|
||||||
include:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc pl-5 space-y-1 text-[10px] sm:text-xs text-muted-foreground">
|
|
||||||
<li>
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded">title</code> - Document
|
|
||||||
titles
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded">content</code> - Main content
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded">description</code> -
|
|
||||||
Descriptions
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground mt-2">
|
|
||||||
Leave empty to search all fields in your documents.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">Maximum Documents</h4>
|
|
||||||
<p className="text-[10px] sm:text-xs text-muted-foreground">
|
|
||||||
Set a limit on the number of documents retrieved per search (1-10,000). This
|
|
||||||
helps control response times and resource usage. Leave empty to use
|
|
||||||
Elasticsearch's default limit.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<h3 className="text-sm sm:text-base font-semibold mb-2">Troubleshooting</h3>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">Connection Issues</h4>
|
|
||||||
<ul className="list-disc pl-5 space-y-2 text-[10px] sm:text-xs text-muted-foreground">
|
|
||||||
<li>
|
|
||||||
<strong>Invalid URL:</strong> Ensure your endpoint URL includes the protocol
|
|
||||||
(https://) and port number if required.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>SSL/TLS Errors:</strong> Verify that your cluster uses HTTPS and the
|
|
||||||
certificate is valid. Self-signed certificates may require additional
|
|
||||||
configuration.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Connection Timeout:</strong> Check your network connectivity and
|
|
||||||
firewall settings. Ensure the Elasticsearch cluster is accessible from
|
|
||||||
SurfSense servers.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">
|
|
||||||
Authentication Issues
|
|
||||||
</h4>
|
|
||||||
<ul className="list-disc pl-5 space-y-2 text-[10px] sm:text-xs text-muted-foreground">
|
|
||||||
<li>
|
|
||||||
<strong>Invalid Credentials:</strong> Double-check your username/password or
|
|
||||||
API key. API keys must be base64-encoded.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Permission Denied:</strong> Ensure your API key or user account has
|
|
||||||
read permissions for the indices you want to search.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>API Key Format:</strong> Elasticsearch API keys are typically
|
|
||||||
base64-encoded strings. Make sure you're using the full key value.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 className="text-[10px] sm:text-xs font-medium mb-2">Search Issues</h4>
|
|
||||||
<ul className="list-disc pl-5 space-y-2 text-[10px] sm:text-xs text-muted-foreground">
|
|
||||||
<li>
|
|
||||||
<strong>No Results:</strong> Verify that your index selection matches
|
|
||||||
existing indices. Use wildcards carefully.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Slow Searches:</strong> Limit the number of indices or use specific
|
|
||||||
index names instead of wildcards. Reduce the maximum documents limit.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Field Not Found:</strong> Ensure the search fields you specify
|
|
||||||
actually exist in your Elasticsearch documents.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 mt-4">
|
|
||||||
<Info className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
||||||
<AlertTitle className="text-[10px] sm:text-xs">Need More Help?</AlertTitle>
|
|
||||||
<AlertDescription className="text-[9px] sm:text-[10px]">
|
|
||||||
If you continue to experience issues, check your Elasticsearch cluster logs
|
|
||||||
and ensure your cluster version is compatible. For Elasticsearch Cloud
|
|
||||||
deployments, verify your access policies and IP allowlists.
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AccordionContent>
|
|
||||||
</AccordionItem>
|
|
||||||
</Accordion>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -105,11 +105,13 @@ export const GithubConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitting
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">Personal Access Token (Optional)</AlertTitle>
|
<AlertTitle>Personal Access Token (Optional)</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
A GitHub PAT is only required for private repositories. Public repos work without a token.{" "}
|
<p>
|
||||||
|
A GitHub PAT is only required for private repositories. Public repos work without a
|
||||||
|
token.{" "}
|
||||||
<a
|
<a
|
||||||
href="https://github.com/settings/tokens/new?description=surfsense&scopes=repo"
|
href="https://github.com/settings/tokens/new?description=surfsense&scopes=repo"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
@ -118,7 +120,8 @@ export const GithubConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitting
|
||||||
>
|
>
|
||||||
Get your token
|
Get your token
|
||||||
<ExternalLink className="h-3 w-3 sm:h-4 sm:w-4" />
|
<ExternalLink className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||||
</a>{" "}
|
</a>
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,11 @@ export const LinkupApiConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitt
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">API Key Required</AlertTitle>
|
<AlertTitle>API Key Required</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You'll need a Linkup API key to use this connector. You can get one by signing up at{" "}
|
You'll need a Linkup API key to use this connector. You can get one by signing up at{" "}
|
||||||
<a
|
<a
|
||||||
href="https://linkup.so"
|
href="https://linkup.so"
|
||||||
|
|
@ -83,6 +84,7 @@ export const LinkupApiConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitt
|
||||||
>
|
>
|
||||||
linkup.so
|
linkup.so
|
||||||
</a>
|
</a>
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,11 @@ export const LumaConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitting }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">API Key Required</AlertTitle>
|
<AlertTitle>API Key Required</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You'll need a Luma API Key to use this connector. You can create one from{" "}
|
You'll need a Luma API Key to use this connector. You can create one from{" "}
|
||||||
<a
|
<a
|
||||||
href="https://lu.ma/api"
|
href="https://lu.ma/api"
|
||||||
|
|
@ -101,6 +102,7 @@ export const LumaConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitting }
|
||||||
>
|
>
|
||||||
Luma API Settings
|
Luma API Settings
|
||||||
</a>
|
</a>
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,17 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Check, Copy, Info } from "lucide-react";
|
import { Check, Copy, Info } from "lucide-react";
|
||||||
import { type FC, useCallback, useRef, useState } from "react";
|
import type { FC } from "react";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||||
import { useApiKey } from "@/hooks/use-api-key";
|
import { useApiKey } from "@/hooks/use-api-key";
|
||||||
import { copyToClipboard as copyToClipboardUtil } from "@/lib/utils";
|
|
||||||
import { getConnectorBenefits } from "../connector-benefits";
|
import { getConnectorBenefits } from "../connector-benefits";
|
||||||
import type { ConnectFormProps } from "../index";
|
import type { ConnectFormProps } from "../index";
|
||||||
|
|
||||||
const PLUGIN_RELEASES_URL =
|
const PLUGIN_RELEASES_URL =
|
||||||
"https://github.com/MODSetter/SurfSense/releases?q=obsidian&expanded=true";
|
"https://github.com/MODSetter/SurfSense/releases?q=obsidian&expanded=true";
|
||||||
|
|
||||||
const BACKEND_URL = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL ?? "https://surfsense.com";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obsidian connect form for the plugin-only architecture.
|
* Obsidian connect form for the plugin-only architecture.
|
||||||
*
|
*
|
||||||
|
|
@ -30,16 +27,6 @@ const BACKEND_URL = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL ?? "https://surf
|
||||||
*/
|
*/
|
||||||
export const ObsidianConnectForm: FC<ConnectFormProps> = ({ onBack }) => {
|
export const ObsidianConnectForm: FC<ConnectFormProps> = ({ onBack }) => {
|
||||||
const { apiKey, isLoading, copied, copyToClipboard } = useApiKey();
|
const { apiKey, isLoading, copied, copyToClipboard } = useApiKey();
|
||||||
const [copiedUrl, setCopiedUrl] = useState(false);
|
|
||||||
const urlCopyTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
|
||||||
|
|
||||||
const copyServerUrl = useCallback(async () => {
|
|
||||||
const ok = await copyToClipboardUtil(BACKEND_URL);
|
|
||||||
if (!ok) return;
|
|
||||||
setCopiedUrl(true);
|
|
||||||
if (urlCopyTimerRef.current) clearTimeout(urlCopyTimerRef.current);
|
|
||||||
urlCopyTimerRef.current = setTimeout(() => setCopiedUrl(false), 2000);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -52,10 +39,10 @@ export const ObsidianConnectForm: FC<ConnectFormProps> = ({ onBack }) => {
|
||||||
that just closes the dialog (see component-level docstring). */}
|
that just closes the dialog (see component-level docstring). */}
|
||||||
<form id="obsidian-connect-form" onSubmit={handleSubmit} />
|
<form id="obsidian-connect-form" onSubmit={handleSubmit} />
|
||||||
|
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0 text-purple-500" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">Plugin-based sync</AlertTitle>
|
<AlertTitle>Plugin-based sync</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
SurfSense now syncs Obsidian via an official plugin that runs inside Obsidian itself.
|
SurfSense now syncs Obsidian via an official plugin that runs inside Obsidian itself.
|
||||||
Works on desktop and mobile, in cloud and self-hosted deployments.
|
Works on desktop and mobile, in cloud and self-hosted deployments.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
|
|
|
||||||
|
|
@ -123,10 +123,11 @@ export const SearxngConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmittin
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">SearxNG Instance Required</AlertTitle>
|
<AlertTitle>SearxNG Instance Required</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You need access to a running SearxNG instance. Refer to the{" "}
|
You need access to a running SearxNG instance. Refer to the{" "}
|
||||||
<a
|
<a
|
||||||
href="https://docs.searxng.org/admin/installation-docker.html"
|
href="https://docs.searxng.org/admin/installation-docker.html"
|
||||||
|
|
@ -137,6 +138,7 @@ export const SearxngConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmittin
|
||||||
SearxNG installation guide
|
SearxNG installation guide
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
for setup instructions. If your instance requires an API key, include it below.
|
for setup instructions. If your instance requires an API key, include it below.
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,11 @@ export const TavilyApiConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitt
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-6">
|
<div className="space-y-6 pb-6">
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">API Key Required</AlertTitle>
|
<AlertTitle>API Key Required</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You'll need a Tavily API key to use this connector. You can get one by signing up at{" "}
|
You'll need a Tavily API key to use this connector. You can get one by signing up at{" "}
|
||||||
<a
|
<a
|
||||||
href="https://tavily.com"
|
href="https://tavily.com"
|
||||||
|
|
@ -83,6 +84,7 @@ export const TavilyApiConnectForm: FC<ConnectFormProps> = ({ onSubmit, isSubmitt
|
||||||
>
|
>
|
||||||
tavily.com
|
tavily.com
|
||||||
</a>
|
</a>
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -166,10 +166,10 @@ export const CirclebackConfig: FC<CirclebackConfigProps> = ({ connector, onNameC
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{webhookInfo && (
|
{webhookInfo && (
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20">
|
<Alert>
|
||||||
<Info className="h-3 w-3 sm:h-4 sm:w-4" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">Configuration Instructions</AlertTitle>
|
<AlertTitle>Configuration Instructions</AlertTitle>
|
||||||
<AlertDescription className="text-[10px] sm:text-xs mt-1">
|
<AlertDescription>
|
||||||
Configure this URL in Circleback Settings → Automations → Create automation → Send
|
Configure this URL in Circleback Settings → Automations → Create automation → Send
|
||||||
webhook request. The webhook will automatically send meeting notes, transcripts, and
|
webhook request. The webhook will automatically send meeting notes, transcripts, and
|
||||||
action items to this search space.
|
action items to this search space.
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
import { Info, KeyRound } from "lucide-react";
|
import { Info, KeyRound } from "lucide-react";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import type { ConnectorConfigProps } from "../index";
|
import type { ConnectorConfigProps } from "../index";
|
||||||
|
|
@ -47,21 +48,17 @@ export const ClickUpConfig: FC<ClickUpConfigProps> = ({
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* OAuth Info */}
|
{/* OAuth Info */}
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertTitle>Connected via OAuth</AlertTitle>
|
||||||
</div>
|
<AlertDescription>
|
||||||
<div className="text-xs sm:text-sm">
|
<p>
|
||||||
<p className="font-medium text-xs sm:text-sm">Connected via OAuth</p>
|
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
Workspace:{" "}
|
Workspace:{" "}
|
||||||
<code className="bg-muted px-1 py-0.5 rounded text-inherit">{workspaceName}</code>
|
<code className="bg-muted px-1 py-0.5 rounded text-inherit">{workspaceName}</code>
|
||||||
</p>
|
</p>
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
<p>To update your connection, reconnect this connector.</p>
|
||||||
To update your connection, reconnect this connector.
|
</AlertDescription>
|
||||||
</p>
|
</Alert>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
import { Info, KeyRound } from "lucide-react";
|
import { Info, KeyRound } from "lucide-react";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import type { ConnectorConfigProps } from "../index";
|
import type { ConnectorConfigProps } from "../index";
|
||||||
|
|
@ -72,23 +73,17 @@ export const ConfluenceConfig: FC<ConfluenceConfigProps> = ({
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* OAuth Info */}
|
{/* OAuth Info */}
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertTitle>Connected via OAuth</AlertTitle>
|
||||||
</div>
|
<AlertDescription>
|
||||||
<div className="text-xs sm:text-sm">
|
<p>This connector is authenticated using OAuth 2.0. Your Confluence instance is:</p>
|
||||||
<p className="font-medium text-xs sm:text-sm">Connected via OAuth</p>
|
<p>
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
This connector is authenticated using OAuth 2.0. Your Confluence instance is:
|
|
||||||
</p>
|
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded text-inherit">{siteUrl}</code>
|
<code className="bg-muted px-1 py-0.5 rounded text-inherit">{siteUrl}</code>
|
||||||
</p>
|
</p>
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
<p>To update your connection, reconnect this connector.</p>
|
||||||
To update your connection, reconnect this connector.
|
</AlertDescription>
|
||||||
</p>
|
</Alert>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { AlertCircle, CheckCircle2, Hash, Info, Megaphone, RefreshCw } from "lucide-react";
|
import { AlertCircle, CheckCircle2, Hash, Info, Megaphone, RefreshCw } from "lucide-react";
|
||||||
import { type FC, useCallback, useEffect, useState } from "react";
|
import { type FC, useCallback, useEffect, useState } from "react";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Spinner } from "@/components/ui/spinner";
|
import { Spinner } from "@/components/ui/spinner";
|
||||||
import { connectorsApiService, type DiscordChannel } from "@/lib/apis/connectors-api.service";
|
import { connectorsApiService, type DiscordChannel } from "@/lib/apis/connectors-api.service";
|
||||||
|
|
@ -73,17 +74,14 @@ export const DiscordConfig: FC<DiscordConfigProps> = ({ connector }) => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Info box */}
|
{/* Info box */}
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertTitle>Grant Channel Permissions</AlertTitle>
|
||||||
</div>
|
<AlertDescription>
|
||||||
<div className="text-xs sm:text-sm">
|
The bot needs "Read Message History" permission to access channels. Ask a server
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
admin to grant this permission for channels shown below.
|
||||||
The bot needs "Read Message History" permission to access channels. Ask a
|
</AlertDescription>
|
||||||
server admin to grant this permission for channels shown below.
|
</Alert>
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Channels Section */}
|
{/* Channels Section */}
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
import { Info, KeyRound } from "lucide-react";
|
import { Info, KeyRound } from "lucide-react";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import type { ConnectorConfigProps } from "../index";
|
import type { ConnectorConfigProps } from "../index";
|
||||||
|
|
@ -65,23 +66,17 @@ export const JiraConfig: FC<JiraConfigProps> = ({ connector, onConfigChange, onN
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* OAuth Info */}
|
{/* OAuth Info */}
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertTitle>Connected via OAuth</AlertTitle>
|
||||||
</div>
|
<AlertDescription>
|
||||||
<div className="text-xs sm:text-sm">
|
<p>This connector is authenticated using OAuth 2.0. Your Jira instance is:</p>
|
||||||
<p className="font-medium text-xs sm:text-sm">Connected via OAuth</p>
|
<p>
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
This connector is authenticated using OAuth 2.0. Your Jira instance is:
|
|
||||||
</p>
|
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
<code className="bg-muted px-1 py-0.5 rounded text-inherit">{baseUrl}</code>
|
<code className="bg-muted px-1 py-0.5 rounded text-inherit">{baseUrl}</code>
|
||||||
</p>
|
</p>
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
<p>To update your connection, reconnect this connector.</p>
|
||||||
To update your connection, reconnect this connector.
|
</AlertDescription>
|
||||||
</p>
|
</Alert>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,10 @@ export const ObsidianConfig: FC<ConnectorConfigProps> = ({ connector }) => {
|
||||||
const LegacyBanner: FC = () => {
|
const LegacyBanner: FC = () => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<Alert className="border-amber-500/40 bg-amber-500/10">
|
<Alert>
|
||||||
<AlertTriangle className="size-4 shrink-0 text-amber-500" />
|
<AlertTriangle />
|
||||||
<AlertTitle className="text-xs sm:text-sm">
|
<AlertTitle>Sync stopped, install the plugin to migrate</AlertTitle>
|
||||||
Sync stopped, install the plugin to migrate
|
<AlertDescription>
|
||||||
</AlertTitle>
|
|
||||||
<AlertDescription className="text-[11px] sm:text-xs leading-relaxed">
|
|
||||||
This Obsidian connector used the legacy server-path scanner, which has been removed. The
|
This Obsidian connector used the legacy server-path scanner, which has been removed. The
|
||||||
notes already indexed remain searchable, but they no longer reflect changes made in your
|
notes already indexed remain searchable, but they no longer reflect changes made in your
|
||||||
vault.
|
vault.
|
||||||
|
|
@ -124,10 +122,10 @@ const PluginStats: FC<{ config: Record<string, unknown> }> = ({ config }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Alert className="border-emerald-500/30 bg-emerald-500/10">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0 text-emerald-500" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">Plugin connected</AlertTitle>
|
<AlertTitle>Plugin connected</AlertTitle>
|
||||||
<AlertDescription className="text-[11px] sm:text-xs">
|
<AlertDescription>
|
||||||
Your notes stay synced automatically. To stop syncing, disable or uninstall the plugin in
|
Your notes stay synced automatically. To stop syncing, disable or uninstall the plugin in
|
||||||
Obsidian, or delete this connector.
|
Obsidian, or delete this connector.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
|
|
@ -152,11 +150,11 @@ const PluginStats: FC<{ config: Record<string, unknown> }> = ({ config }) => {
|
||||||
|
|
||||||
const UnknownConnectorState: FC = () => (
|
const UnknownConnectorState: FC = () => (
|
||||||
<Alert>
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertTitle className="text-xs sm:text-sm">Unrecognized config</AlertTitle>
|
<AlertTitle>Unrecognized config</AlertTitle>
|
||||||
<AlertDescription className="text-[11px] sm:text-xs">
|
<AlertDescription>
|
||||||
This connector has neither plugin metadata nor a legacy marker. It may predate migration — you
|
This connector is missing plugin metadata and may predate the Obsidian plugin migration. You
|
||||||
can safely delete it and re-install the SurfSense Obsidian plugin to resume syncing.
|
can safely delete it and reinstall the SurfSense Obsidian plugin to resume syncing.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { AlertCircle, CheckCircle2, Hash, Info, Lock, RefreshCw } from "lucide-react";
|
import { AlertCircle, CheckCircle2, Hash, Info, Lock, RefreshCw } from "lucide-react";
|
||||||
import { type FC, useCallback, useEffect, useState } from "react";
|
import { type FC, useCallback, useEffect, useState } from "react";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Spinner } from "@/components/ui/spinner";
|
import { Spinner } from "@/components/ui/spinner";
|
||||||
import { connectorsApiService, type SlackChannel } from "@/lib/apis/connectors-api.service";
|
import { connectorsApiService, type SlackChannel } from "@/lib/apis/connectors-api.service";
|
||||||
|
|
@ -74,20 +75,18 @@ export const SlackConfig: FC<SlackConfigProps> = ({ connector }) => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Info box */}
|
{/* Info box */}
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertTitle>Add Bot to Channels</AlertTitle>
|
||||||
</div>
|
<AlertDescription>
|
||||||
<div className="text-xs sm:text-sm">
|
<p>
|
||||||
<p className="font-medium text-xs sm:text-sm">Add Bot to Channels</p>
|
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
Before indexing, add the SurfSense bot to each channel you want to index. The bot can
|
Before indexing, add the SurfSense bot to each channel you want to index. The bot can
|
||||||
only access messages from channels it's been added to. Type{" "}
|
only access messages from channels it's been added to. Type{" "}
|
||||||
<code className="bg-muted px-1 py-0.5 rounded text-[9px]">/invite @SurfSense</code> in
|
<code className="bg-muted px-1 py-0.5 rounded text-[9px]">/invite @SurfSense</code>{" "}
|
||||||
any channel to add it.
|
in any channel to add it.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</AlertDescription>
|
||||||
</div>
|
</Alert>
|
||||||
|
|
||||||
{/* Channels Section */}
|
{/* Channels Section */}
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { Info } from "lucide-react";
|
import { Info } from "lucide-react";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import type { ConnectorConfigProps } from "../index";
|
import type { ConnectorConfigProps } from "../index";
|
||||||
|
|
||||||
export interface TeamsConfigProps extends ConnectorConfigProps {
|
export interface TeamsConfigProps extends ConnectorConfigProps {
|
||||||
|
|
@ -11,19 +12,17 @@ export interface TeamsConfigProps extends ConnectorConfigProps {
|
||||||
export const TeamsConfig: FC<TeamsConfigProps> = () => {
|
export const TeamsConfig: FC<TeamsConfigProps> = () => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertTitle>Microsoft Teams Access</AlertTitle>
|
||||||
</div>
|
<AlertDescription>
|
||||||
<div className="text-xs sm:text-sm">
|
<p>
|
||||||
<p className="font-medium text-xs sm:text-sm">Microsoft Teams Access</p>
|
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
Your agent can search and read messages from Teams channels you have access to, and send
|
Your agent can search and read messages from Teams channels you have access to, and send
|
||||||
messages on your behalf. Make sure you're a member of the teams you want to interact
|
messages on your behalf. Make sure you're a member of the teams you want to
|
||||||
with.
|
interact with.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</AlertDescription>
|
||||||
</div>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -52,13 +52,13 @@ export const WebcrawlerConfig: FC<ConnectorConfigProps> = ({ connector, onConfig
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Chat tip */}
|
{/* Chat tip */}
|
||||||
<div className="flex items-start gap-3 rounded-lg border border-blue-200/50 bg-blue-50/50 dark:border-blue-500/20 dark:bg-blue-950/20 p-3 text-xs sm:text-sm">
|
<Alert>
|
||||||
<Info className="size-4 mt-0.5 shrink-0 text-blue-600 dark:text-blue-400" />
|
<Info />
|
||||||
<p className="text-muted-foreground">
|
<AlertDescription>
|
||||||
Want a quick answer from a webpage without indexing it? Just paste the URL directly into
|
Want a quick answer from a webpage without indexing it? Just paste the URL directly into
|
||||||
the chat instead.
|
the chat instead.
|
||||||
</p>
|
</AlertDescription>
|
||||||
</div>
|
</Alert>
|
||||||
|
|
||||||
{/* API Key Field */}
|
{/* API Key Field */}
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|
@ -116,9 +116,9 @@ export const WebcrawlerConfig: FC<ConnectorConfigProps> = ({ connector, onConfig
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Info Alert */}
|
{/* Info Alert */}
|
||||||
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3">
|
<Alert>
|
||||||
<Info className="size-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-[10px] sm:text-xs">
|
<AlertDescription>
|
||||||
Configuration is saved when you start indexing. You can update these settings anytime from
|
Configuration is saved when you start indexing. You can update these settings anytime from
|
||||||
the connector management page.
|
the connector management page.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { ArrowLeft, Info, RefreshCw } from "lucide-react";
|
||||||
import { type FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { type FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||||
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Spinner } from "@/components/ui/spinner";
|
import { Spinner } from "@/components/ui/spinner";
|
||||||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||||
|
|
@ -350,20 +351,12 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
|
||||||
|
|
||||||
{/* Info box - hidden for live connectors */}
|
{/* Info box - hidden for live connectors */}
|
||||||
{connector.is_indexable && !isLive && (
|
{connector.is_indexable && !isLive && (
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertDescription>
|
||||||
</div>
|
You can continue using SurfSense while we sync your data. Check inbox for updates.
|
||||||
<div className="text-xs sm:text-sm">
|
</AlertDescription>
|
||||||
<p className="font-medium text-xs sm:text-sm">
|
</Alert>
|
||||||
Re-indexing runs in the background
|
|
||||||
</p>
|
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
You can continue using SurfSense while we sync your data. Check inbox for
|
|
||||||
updates.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { ArrowLeft, Check, Info } from "lucide-react";
|
import { ArrowLeft, Check, Info } from "lucide-react";
|
||||||
import { type FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { type FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Spinner } from "@/components/ui/spinner";
|
import { Spinner } from "@/components/ui/spinner";
|
||||||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||||
|
|
@ -230,18 +231,12 @@ export const IndexingConfigurationView: FC<IndexingConfigurationViewProps> = ({
|
||||||
|
|
||||||
{/* Info box - hidden for live connectors */}
|
{/* Info box - hidden for live connectors */}
|
||||||
{connector?.is_indexable && !isLive && (
|
{connector?.is_indexable && !isLive && (
|
||||||
<div className="rounded-xl border border-border bg-primary/5 p-4 flex items-start gap-3">
|
<Alert>
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 shrink-0 mt-0.5">
|
<Info />
|
||||||
<Info className="size-4" />
|
<AlertDescription>
|
||||||
</div>
|
You can continue using SurfSense while we sync your data. Check inbox for updates.
|
||||||
<div className="text-xs sm:text-sm">
|
</AlertDescription>
|
||||||
<p className="font-medium text-xs sm:text-sm">Indexing runs in the background</p>
|
</Alert>
|
||||||
<p className="text-muted-foreground mt-1 text-[10px] sm:text-sm">
|
|
||||||
You can continue using SurfSense while we sync your data. Check inbox for
|
|
||||||
updates.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { useTranslations } from "next-intl";
|
||||||
import { type FC, useCallback, useState } from "react";
|
import { type FC, useCallback, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { createDocumentMutationAtom } from "@/atoms/documents/document-mutation.atoms";
|
import { createDocumentMutationAtom } from "@/atoms/documents/document-mutation.atoms";
|
||||||
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Spinner } from "@/components/ui/spinner";
|
import { Spinner } from "@/components/ui/spinner";
|
||||||
|
|
@ -279,10 +280,10 @@ export const YouTubeCrawlerView: FC<YouTubeCrawlerViewProps> = ({ searchSpaceId,
|
||||||
|
|
||||||
{error && <div className="text-sm text-red-500 mt-2">{error}</div>}
|
{error && <div className="text-sm text-red-500 mt-2">{error}</div>}
|
||||||
|
|
||||||
<div className="flex items-start gap-3 rounded-lg border border-blue-200/50 bg-blue-50/50 dark:border-blue-500/20 dark:bg-blue-950/20 p-4 text-sm">
|
<Alert>
|
||||||
<Info className="size-4 mt-0.5 shrink-0 text-blue-600 dark:text-blue-400" />
|
<Info />
|
||||||
<p className="text-muted-foreground">{t("chat_tip")}</p>
|
<AlertDescription>{t("chat_tip")}</AlertDescription>
|
||||||
</div>
|
</Alert>
|
||||||
|
|
||||||
<div className="bg-muted/50 rounded-lg p-4 text-sm">
|
<div className="bg-muted/50 rounded-lg p-4 text-sm">
|
||||||
<h4 className="font-medium mb-2">{t("tips_title")}</h4>
|
<h4 className="font-medium mb-2">{t("tips_title")}</h4>
|
||||||
|
|
|
||||||
|
|
@ -147,14 +147,12 @@ const DocumentUploadPopupContent: FC<{
|
||||||
|
|
||||||
<div className="px-4 sm:px-6 pb-4 sm:pb-6">
|
<div className="px-4 sm:px-6 pb-4 sm:pb-6">
|
||||||
{!isLoading && !hasDocumentSummaryLLM ? (
|
{!isLoading && !hasDocumentSummaryLLM ? (
|
||||||
<Alert
|
<div className="mb-4">
|
||||||
variant="destructive"
|
<Alert variant="destructive">
|
||||||
className="mb-4 bg-muted/50 rounded-xl border-destructive/30"
|
<AlertTriangle />
|
||||||
>
|
|
||||||
<AlertTriangle className="h-4 w-4" />
|
|
||||||
<AlertTitle>LLM Configuration Required</AlertTitle>
|
<AlertTitle>LLM Configuration Required</AlertTitle>
|
||||||
<AlertDescription className="mt-2">
|
<AlertDescription>
|
||||||
<p className="mb-3">
|
<p>
|
||||||
{isAutoMode && !hasGlobalConfigs
|
{isAutoMode && !hasGlobalConfigs
|
||||||
? "Auto mode requires a global LLM configuration. Please add one in Settings"
|
? "Auto mode requires a global LLM configuration. Please add one in Settings"
|
||||||
: "A Document Summary LLM is required to process uploads, configure one in Settings"}
|
: "A Document Summary LLM is required to process uploads, configure one in Settings"}
|
||||||
|
|
@ -172,6 +170,7 @@ const DocumentUploadPopupContent: FC<{
|
||||||
</Button>
|
</Button>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<DocumentUploadTab searchSpaceId={searchSpaceId} onSuccess={handleSuccess} />
|
<DocumentUploadTab searchSpaceId={searchSpaceId} onSuccess={handleSuccess} />
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,8 @@ export function PublicChatSnapshotsManager({
|
||||||
// Permission denied
|
// Permission denied
|
||||||
if (!canView) {
|
if (!canView) {
|
||||||
return (
|
return (
|
||||||
<Alert variant="destructive">
|
<Alert>
|
||||||
<Info className="h-4 w-4" />
|
<Info />
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
You don't have permission to view public chat links in this search space.
|
You don't have permission to view public chat links in this search space.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
|
|
@ -141,9 +141,9 @@ export function PublicChatSnapshotsManager({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 md:space-y-5">
|
<div className="space-y-4 md:space-y-5">
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
Public chat links allow anyone with the URL to view a snapshot of a chat. These links do
|
Public chat links allow anyone with the URL to view a snapshot of a chat. These links do
|
||||||
not update when the original chat changes.
|
not update when the original chat changes.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
|
|
|
||||||
|
|
@ -152,26 +152,30 @@ export function AgentModelManager({ searchSpaceId }: AgentModelManagerProps) {
|
||||||
{/* Read-only / Limited permissions notice */}
|
{/* Read-only / Limited permissions notice */}
|
||||||
{access && !isLoading && isReadOnly && (
|
{access && !isLoading && isReadOnly && (
|
||||||
<div>
|
<div>
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
You have <span className="font-medium">read-only</span> access to LLM configurations.
|
<p>
|
||||||
Contact a space owner to request additional permissions.
|
You have <span className="font-medium">read-only</span> access to LLM
|
||||||
|
configurations. Contact a space owner to request additional permissions.
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{access && !isLoading && !isReadOnly && (!canCreate || !canUpdate || !canDelete) && (
|
{access && !isLoading && !isReadOnly && (!canCreate || !canUpdate || !canDelete) && (
|
||||||
<div>
|
<div>
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You can{" "}
|
You can{" "}
|
||||||
{[canCreate && "create", canUpdate && "edit", canDelete && "delete"]
|
{[canCreate && "create", canUpdate && "edit", canDelete && "delete"]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(" and ")}{" "}
|
.join(" and ")}{" "}
|
||||||
configurations
|
configurations
|
||||||
{!canDelete && ", but cannot delete them"}.
|
{!canDelete && ", but cannot delete them"}.
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -179,9 +183,9 @@ export function AgentModelManager({ searchSpaceId }: AgentModelManagerProps) {
|
||||||
|
|
||||||
{/* Global Configs Info */}
|
{/* Global Configs Info */}
|
||||||
{globalConfigs.length > 0 && (
|
{globalConfigs.length > 0 && (
|
||||||
<Alert className="bg-muted/50 py-3">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
<p>
|
<p>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{globalConfigs.length} global {globalConfigs.length === 1 ? "model" : "models"}
|
{globalConfigs.length} global {globalConfigs.length === 1 ? "model" : "models"}
|
||||||
|
|
|
||||||
|
|
@ -135,11 +135,9 @@ export function GeneralSettingsManager({ searchSpaceId }: GeneralSettingsManager
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 md:space-y-6">
|
<div className="space-y-4 md:space-y-6">
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>Update your search space name and description.</AlertDescription>
|
||||||
Update your search space name and description.
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
<form onSubmit={onSubmit} className="space-y-6">
|
<form onSubmit={onSubmit} className="space-y-6">
|
||||||
|
|
|
||||||
|
|
@ -153,26 +153,30 @@ export function ImageModelManager({ searchSpaceId }: ImageModelManagerProps) {
|
||||||
{/* Read-only / Limited permissions notice */}
|
{/* Read-only / Limited permissions notice */}
|
||||||
{access && !isLoading && isReadOnly && (
|
{access && !isLoading && isReadOnly && (
|
||||||
<div>
|
<div>
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You have <span className="font-medium">read-only</span> access to image generation
|
You have <span className="font-medium">read-only</span> access to image generation
|
||||||
configurations. Contact a space owner to request additional permissions.
|
configurations. Contact a space owner to request additional permissions.
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{access && !isLoading && !isReadOnly && (!canCreate || !canDelete) && (
|
{access && !isLoading && !isReadOnly && (!canCreate || !canDelete) && (
|
||||||
<div>
|
<div>
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You can{" "}
|
You can{" "}
|
||||||
{[canCreate && "create and edit", canDelete && "delete"]
|
{[canCreate && "create and edit", canDelete && "delete"]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(" and ")}{" "}
|
.join(" and ")}{" "}
|
||||||
image model configurations
|
image model configurations
|
||||||
{!canDelete && ", but cannot delete them"}.
|
{!canDelete && ", but cannot delete them"}.
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -180,9 +184,9 @@ export function ImageModelManager({ searchSpaceId }: ImageModelManagerProps) {
|
||||||
|
|
||||||
{/* Global info */}
|
{/* Global info */}
|
||||||
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length > 0 && (
|
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length > 0 && (
|
||||||
<Alert className="bg-muted/50 py-3">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
<p>
|
<p>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length}{" "}
|
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length}{" "}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { useQuery } from "@tanstack/react-query";
|
||||||
import { AlertTriangle, Info } from "lucide-react";
|
import { AlertTriangle, Info } from "lucide-react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
|
@ -102,21 +102,19 @@ export function PromptConfigManager({ searchSpaceId }: PromptConfigManagerProps)
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 md:space-y-6">
|
<div className="space-y-4 md:space-y-6">
|
||||||
{/* Work in Progress Notice */}
|
{/* Work in Progress Notice */}
|
||||||
<Alert
|
<Alert>
|
||||||
variant="default"
|
<AlertTriangle />
|
||||||
className="bg-amber-50 dark:bg-amber-950/30 border-amber-300 dark:border-amber-700 py-3 md:py-4"
|
<AlertTitle>Work in Progress</AlertTitle>
|
||||||
>
|
<AlertDescription>
|
||||||
<AlertTriangle className="h-3 w-3 md:h-4 md:w-4 text-amber-600 dark:text-amber-500 shrink-0" />
|
This functionality is currently under development and not yet connected to the backend.
|
||||||
<AlertDescription className="text-amber-800 dark:text-amber-300 text-xs md:text-sm">
|
Your instructions will be saved but won't affect AI behavior until the feature is fully
|
||||||
<span className="font-semibold">Work in Progress:</span> This functionality is currently
|
implemented.
|
||||||
under development and not yet connected to the backend. Your instructions will be saved
|
|
||||||
but won't affect AI behavior until the feature is fully implemented.
|
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
System instructions apply to all AI interactions in this search space. They guide how the
|
System instructions apply to all AI interactions in this search space. They guide how the
|
||||||
AI responds, its tone, focus areas, and behavior patterns.
|
AI responds, its tone, focus areas, and behavior patterns.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
|
|
@ -167,9 +165,9 @@ export function PromptConfigManager({ searchSpaceId }: PromptConfigManagerProps)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{customInstructions.trim().length === 0 && (
|
{customInstructions.trim().length === 0 && (
|
||||||
<Alert className="py-2 md:py-3">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
No system instructions are currently set. The AI will use default behavior.
|
No system instructions are currently set. The AI will use default behavior.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
|
||||||
|
|
@ -183,9 +183,9 @@ export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
<p>
|
<p>
|
||||||
SurfSense uses this shared memory to provide team-wide context across all conversations
|
SurfSense uses this shared memory to provide team-wide context across all conversations
|
||||||
in this search space.
|
in this search space.
|
||||||
|
|
|
||||||
|
|
@ -155,35 +155,39 @@ export function VisionModelManager({ searchSpaceId }: VisionModelManagerProps) {
|
||||||
|
|
||||||
{access && !isLoading && isReadOnly && (
|
{access && !isLoading && isReadOnly && (
|
||||||
<div>
|
<div>
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You have <span className="font-medium">read-only</span> access to vision model
|
You have <span className="font-medium">read-only</span> access to vision model
|
||||||
configurations. Contact a space owner to request additional permissions.
|
configurations. Contact a space owner to request additional permissions.
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{access && !isLoading && !isReadOnly && (!canCreate || !canDelete) && (
|
{access && !isLoading && !isReadOnly && (!canCreate || !canDelete) && (
|
||||||
<div>
|
<div>
|
||||||
<Alert className="bg-muted/50 py-3 md:py-4">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
|
<p>
|
||||||
You can{" "}
|
You can{" "}
|
||||||
{[canCreate && "create and edit", canDelete && "delete"]
|
{[canCreate && "create and edit", canDelete && "delete"]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(" and ")}{" "}
|
.join(" and ")}{" "}
|
||||||
vision model configurations
|
vision model configurations
|
||||||
{!canDelete && ", but cannot delete them"}.
|
{!canDelete && ", but cannot delete them"}.
|
||||||
|
</p>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length > 0 && (
|
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length > 0 && (
|
||||||
<Alert className="bg-muted/50 py-3">
|
<Alert>
|
||||||
<Info className="h-3 w-3 md:h-4 md:w-4 shrink-0" />
|
<Info />
|
||||||
<AlertDescription className="text-xs md:text-sm">
|
<AlertDescription>
|
||||||
<p>
|
<p>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length}{" "}
|
{globalConfigs.filter((g) => !("is_auto_mode" in g && g.is_auto_mode)).length}{" "}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue