Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 158 additions & 60 deletions surfsense_backend/app/tasks/connector_indexers/discord_indexer.py

Large diffs are not rendered by default.

234 changes: 177 additions & 57 deletions surfsense_backend/app/tasks/connector_indexers/slack_indexer.py

Large diffs are not rendered by default.

258 changes: 194 additions & 64 deletions surfsense_backend/app/tasks/connector_indexers/teams_indexer.py

Large diffs are not rendered by default.

9 changes: 1 addition & 8 deletions surfsense_web/app/(home)/login/LocalLoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { trackLoginAttempt, trackLoginFailure, trackLoginSuccess } from "@/lib/p

export function LocalLoginForm() {
const t = useTranslations("auth");
const tCommon = useTranslations("common");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
Expand Down Expand Up @@ -58,12 +57,6 @@ export function LocalLoginForm() {
sessionStorage.setItem("login_success_tracked", "true");
}

// Success toast
toast.success(t("login_success"), {
description: "Redirecting to dashboard",
duration: 2000,
});

// Small delay to show success message
setTimeout(() => {
router.push(`/auth/callback?token=${data.access_token}`);
Expand Down Expand Up @@ -123,7 +116,7 @@ export function LocalLoginForm() {
<form onSubmit={handleSubmit} className="space-y-3 md:space-y-4">
{/* Error Display */}
<AnimatePresence>
{error && error.title && (
{error?.title && (
<motion.div
initial={{ opacity: 0, y: -10, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,42 @@ export function getDocumentTypeIcon(type: string, className?: string): React.Rea
}

export function getDocumentTypeLabel(type: string): string {
return type
.split("_")
.map((word) => word.charAt(0) + word.slice(1).toLowerCase())
.join(" ");
const labelMap: Record<string, string> = {
EXTENSION: "Extension",
CRAWLED_URL: "Web Page",
FILE: "File",
SLACK_CONNECTOR: "Slack",
TEAMS_CONNECTOR: "Microsoft Teams",
NOTION_CONNECTOR: "Notion",
YOUTUBE_VIDEO: "YouTube Video",
GITHUB_CONNECTOR: "GitHub",
LINEAR_CONNECTOR: "Linear",
DISCORD_CONNECTOR: "Discord",
JIRA_CONNECTOR: "Jira",
CONFLUENCE_CONNECTOR: "Confluence",
CLICKUP_CONNECTOR: "ClickUp",
GOOGLE_CALENDAR_CONNECTOR: "Google Calendar",
GOOGLE_GMAIL_CONNECTOR: "Gmail",
GOOGLE_DRIVE_FILE: "Google Drive",
AIRTABLE_CONNECTOR: "Airtable",
LUMA_CONNECTOR: "Luma",
ELASTICSEARCH_CONNECTOR: "Elasticsearch",
BOOKSTACK_CONNECTOR: "BookStack",
CIRCLEBACK: "Circleback",
OBSIDIAN_CONNECTOR: "Obsidian",
SURFSENSE_DOCS: "SurfSense Docs",
NOTE: "Note",
COMPOSIO_GOOGLE_DRIVE_CONNECTOR: "Composio Google Drive",
COMPOSIO_GMAIL_CONNECTOR: "Composio Gmail",
COMPOSIO_GOOGLE_CALENDAR_CONNECTOR: "Composio Google Calendar",
};
return (
labelMap[type] ||
type
.split("_")
.map((word) => word.charAt(0) + word.slice(1).toLowerCase())
.join(" ")
);
}

export function DocumentTypeChip({ type, className }: { type: string; className?: string }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
Clock,
FileText,
FileX,
Loader2,
Network,
Plus,
User,
Expand Down Expand Up @@ -354,11 +353,11 @@ export function DocumentsTableShell({
<Skeleton className="h-4 w-4 rounded" />
</div>
</TableHead>
<TableHead className="w-[35%] max-w-0 border-r border-border/40">
<TableHead className="w-[40%] max-w-0 border-r border-border/40">
<Skeleton className="h-3 w-20" />
</TableHead>
{columnVisibility.document_type && (
<TableHead className="w-[20%] min-w-[120px] max-w-[200px] border-r border-border/40">
<TableHead className="w-[15%] min-w-[100px] max-w-[170px] border-r border-border/40">
<Skeleton className="h-3 w-14" />
</TableHead>
)}
Expand Down Expand Up @@ -396,11 +395,11 @@ export function DocumentsTableShell({
<Skeleton className="h-4 w-4 rounded" />
</div>
</TableCell>
<TableCell className="w-[35%] py-2.5 max-w-0 border-r border-border/40">
<TableCell className="w-[40%] py-2.5 max-w-0 border-r border-border/40">
<Skeleton className="h-4" style={{ width: `${widthPercent}%` }} />
</TableCell>
{columnVisibility.document_type && (
<TableCell className="w-[20%] min-w-[120px] max-w-[200px] py-2.5 border-r border-border/40 overflow-hidden">
<TableCell className="w-[15%] min-w-[100px] max-w-[170px] py-2.5 border-r border-border/40 overflow-hidden">
<Skeleton className="h-5 w-24 rounded" />
</TableCell>
)}
Expand Down Expand Up @@ -499,7 +498,7 @@ export function DocumentsTableShell({
/>
</div>
</TableHead>
<TableHead className="w-[35%] border-r border-border/40">
<TableHead className="w-[40%] border-r border-border/40">
<SortableHeader
sortKey="title"
currentSortKey={sortKey}
Expand All @@ -511,7 +510,7 @@ export function DocumentsTableShell({
</SortableHeader>
</TableHead>
{columnVisibility.document_type && (
<TableHead className="w-[20%] min-w-[120px] max-w-[200px] border-r border-border/40">
<TableHead className="w-[15%] min-w-[100px] max-w-[170px] border-r border-border/40">
<SortableHeader
sortKey="document_type"
currentSortKey={sortKey}
Expand Down Expand Up @@ -594,7 +593,7 @@ export function DocumentsTableShell({
/>
</div>
</TableCell>
<TableCell className="w-[35%] py-2.5 max-w-0 border-r border-border/40">
<TableCell className="w-[40%] py-2.5 max-w-0 border-r border-border/40">
<button
type="button"
className="block w-full text-left text-sm text-foreground hover:text-foreground transition-colors cursor-pointer bg-transparent border-0 p-0 truncate"
Expand Down Expand Up @@ -624,7 +623,7 @@ export function DocumentsTableShell({
</button>
</TableCell>
{columnVisibility.document_type && (
<TableCell className="w-[20%] min-w-[120px] max-w-[200px] py-2.5 border-r border-border/40 overflow-hidden">
<TableCell className="w-[15%] min-w-[100px] max-w-[170px] py-2.5 border-r border-border/40 overflow-hidden">
<DocumentTypeChip type={doc.document_type} />
</TableCell>
)}
Expand Down Expand Up @@ -773,7 +772,7 @@ export function DocumentsTableShell({
<div className="mt-4">
{viewingLoading ? (
<div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
<Spinner size="lg" className="text-muted-foreground" />
</div>
) : (
<MarkdownViewer content={viewingContent} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,16 @@ export function RowActions({
const isBeingProcessed =
document.status?.state === "pending" || document.status?.state === "processing";

// FILE documents that failed processing cannot be edited
const isFileFailed = document.document_type === "FILE" && document.status?.state === "failed";

// SURFSENSE_DOCS are system-managed and should not show delete at all
const shouldShowDelete = !NON_DELETABLE_DOCUMENT_TYPES.includes(
document.document_type as (typeof NON_DELETABLE_DOCUMENT_TYPES)[number]
);

// Edit and Delete are disabled while processing
const isEditDisabled = isBeingProcessed;
// Edit is disabled while processing OR for failed FILE documents
const isEditDisabled = isBeingProcessed || isFileFailed;
const isDeleteDisabled = isBeingProcessed;

const handleDelete = async () => {
Expand Down Expand Up @@ -208,7 +211,8 @@ export function RowActions({
<AlertDialogHeader>
<AlertDialogTitle>Delete document?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete this document from your search space.
This action cannot be undone. This will permanently delete this document from your
search space.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import { IconCalendar, IconMailFilled } from "@tabler/icons-react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Check, ExternalLink, Gift, Loader2, Mail, Star } from "lucide-react";
import { Check, ExternalLink, Gift, Mail, Star } from "lucide-react";
import { motion } from "motion/react";
import Link from "next/link";
import { useEffect } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { Card, CardContent } from "@/components/ui/card";
import {
Dialog,
Expand Down Expand Up @@ -144,7 +145,7 @@ export default function MorePagesPage() {
className="gap-1"
>
{completeMutation.isPending ? (
<Loader2 className="h-3 w-3 animate-spin" />
<Spinner size="xs" />
) : (
<>
Go
Expand Down
5 changes: 3 additions & 2 deletions surfsense_web/components/UserDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use client";

import { BadgeCheck, Loader2, LogOut } from "lucide-react";
import { BadgeCheck, LogOut } from "lucide-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import {
DropdownMenu,
DropdownMenuContent,
Expand Down Expand Up @@ -98,7 +99,7 @@ export function UserDropdown({
disabled={isLoggingOut}
>
{isLoggingOut ? (
<Loader2 className="mr-2 h-3.5 w-3.5 md:h-4 md:w-4 animate-spin" />
<Spinner size="sm" className="mr-2" />
) : (
<LogOut className="mr-2 h-3.5 w-3.5 md:h-4 md:w-4" />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,12 @@ export const IndexingConfigurationView: FC<IndexingConfigurationViewProps> = ({
<div className="flex flex-col">
<span className="text-xl sm:text-2xl font-semibold tracking-tight text-wrap whitespace-normal wrap-break-word">
{getConnectorTypeDisplay(connector?.connector_type || "")} Connected !
</span>{" "}
<span className="text-xl sm:text-xl font-semibold text-muted-foreground tracking-tight text-wrap whitespace-normal wrap-break-word">
{getConnectorDisplayName(connector?.name || "")}
</span>
{connector?.name?.includes(" - ") && (
<span className="text-xl sm:text-xl font-semibold text-muted-foreground tracking-tight text-wrap whitespace-normal wrap-break-word">
{getConnectorDisplayName(connector.name)}
</span>
)}
</div>
<p className="text-xs sm:text-base text-muted-foreground mt-1">
Configure when to start syncing your data
Expand Down
4 changes: 2 additions & 2 deletions surfsense_web/components/assistant-ui/thread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
ChevronRightIcon,
CopyIcon,
DownloadIcon,
Loader2,
RefreshCwIcon,
SquareIcon,
} from "lucide-react";
Expand Down Expand Up @@ -61,6 +60,7 @@ import {
} from "@/components/new-chat/document-mention-picker";
import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import type { Document } from "@/contracts/types/document.types";
import { useCommentsElectric } from "@/hooks/use-comments-electric";
import { cn } from "@/lib/utils";
Expand Down Expand Up @@ -542,7 +542,7 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
{/* Show processing indicator when attachments are being processed */}
{hasProcessingAttachments && (
<div className="flex items-center gap-1.5 text-muted-foreground text-xs">
<Loader2 className="size-3 animate-spin" />
<Spinner size="xs" />
<span>Processing...</span>
</div>
)}
Expand Down
5 changes: 3 additions & 2 deletions surfsense_web/components/json-metadata-viewer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { FileJson, Loader2 } from "lucide-react";
import { FileJson } from "lucide-react";
import React from "react";
import { defaultStyles, JsonView } from "react-json-view-lite";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import {
Dialog,
DialogContent,
Expand Down Expand Up @@ -58,7 +59,7 @@ export function JsonMetadataViewer({
<div className="mt-2 sm:mt-4 p-2 sm:p-4 bg-muted/30 rounded-md text-xs sm:text-sm">
{loading ? (
<div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
<Spinner size="lg" className="text-muted-foreground" />
</div>
) : (
<JsonView data={jsonData} style={defaultStyles} />
Expand Down
17 changes: 4 additions & 13 deletions surfsense_web/components/layout/ui/sidebar/SidebarUserProfile.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
"use client";

import {
Check,
ChevronUp,
Languages,
Laptop,
Loader2,
LogOut,
Moon,
Settings,
Sun,
} from "lucide-react";
import { Check, ChevronUp, Languages, Laptop, LogOut, Moon, Settings, Sun } from "lucide-react";
import { useTranslations } from "next-intl";
import { useState } from "react";
import {
Expand All @@ -27,6 +17,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { useLocaleContext } from "@/contexts/LocaleContext";
import { Spinner } from "@/components/ui/spinner";
import { cn } from "@/lib/utils";
import type { User } from "../../types/layout.types";

Expand Down Expand Up @@ -266,7 +257,7 @@ export function SidebarUserProfile({

<DropdownMenuItem onClick={handleLogout} disabled={isLoggingOut}>
{isLoggingOut ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
<Spinner size="sm" className="mr-2" />
) : (
<LogOut className="mr-2 h-4 w-4" />
)}
Expand Down Expand Up @@ -388,7 +379,7 @@ export function SidebarUserProfile({

<DropdownMenuItem onClick={handleLogout} disabled={isLoggingOut}>
{isLoggingOut ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
<Spinner size="sm" className="mr-2" />
) : (
<LogOut className="mr-2 h-4 w-4" />
)}
Expand Down
14 changes: 10 additions & 4 deletions surfsense_web/components/public-chat/public-chat-footer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use client";

import { Copy, Loader2 } from "lucide-react";
import { Copy } from "lucide-react";
import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { publicChatApiService } from "@/lib/apis/public-chat-api.service";
import { getBearerToken } from "@/lib/auth-utils";

Expand Down Expand Up @@ -61,9 +62,14 @@ export function PublicChatFooter({ shareToken }: PublicChatFooterProps) {
};

return (
<div className="mx-auto flex max-w-(--thread-max-width) items-center justify-center px-4 py-4">
<Button size="lg" onClick={handleCopyAndContinue} disabled={isCloning} className="gap-2">
{isCloning ? <Loader2 className="size-4 animate-spin" /> : <Copy className="size-4" />}
<div className="fixed bottom-6 left-1/2 z-50 -translate-x-1/2">
<Button
size="lg"
onClick={handleCopyAndContinue}
disabled={isCloning}
className="gap-2 rounded-full px-6 shadow-lg transition-all duration-200 hover:scale-[1.02] hover:shadow-xl hover:brightness-110 hover:bg-primary"
>
{isCloning ? <Spinner size="sm" /> : <Copy className="size-4" />}
Copy and continue this chat
</Button>
</div>
Expand Down
4 changes: 2 additions & 2 deletions surfsense_web/components/public-chat/public-chat-view.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { Loader2 } from "lucide-react";
import { Navbar } from "@/components/homepage/navbar";
import { Spinner } from "@/components/ui/spinner";
import { DisplayImageToolUI } from "@/components/tool-ui/display-image";
import { GeneratePodcastToolUI } from "@/components/tool-ui/generate-podcast";
import { LinkPreviewToolUI } from "@/components/tool-ui/link-preview";
Expand All @@ -26,7 +26,7 @@ export function PublicChatView({ shareToken }: PublicChatViewProps) {
<main className="min-h-screen bg-linear-to-b from-gray-50 to-gray-100 text-gray-900 dark:from-black dark:to-gray-900 dark:text-white overflow-x-hidden">
<Navbar />
<div className="flex h-screen items-center justify-center">
<Loader2 className="size-8 animate-spin text-muted-foreground" />
<Spinner size="lg" className="text-muted-foreground" />
</div>
</main>
);
Expand Down
Loading
Loading