feat: update Google Drive connector UI and authentication handling

This commit is contained in:
Anish Sarkar 2026-03-20 13:39:28 +05:30
parent 75f0975674
commit a27c10a5f5
10 changed files with 29 additions and 48 deletions

View file

@ -5,7 +5,6 @@ import {
AlertTriangleIcon,
CornerDownLeftIcon,
FileIcon,
Loader2Icon,
Pen,
RefreshCwIcon,
} from "lucide-react";
@ -22,7 +21,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { PlateEditor } from "@/components/editor/plate-editor";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
import { authenticatedFetch } from "@/lib/auth-utils";
import { useSetAtom } from "jotai";
import { openHitlEditPanelAtom } from "@/atoms/chat/hitl-edit-panel.atom";
@ -436,11 +435,7 @@ function InsufficientPermissionsCard({ result }: { result: InsufficientPermissio
<div className="px-5 py-4 space-y-3">
<p className="text-sm text-muted-foreground">{result.message}</p>
<Button size="sm" className="rounded-lg" onClick={handleReauth} disabled={loading}>
{loading ? (
<Loader2Icon className="size-4 animate-spin" />
) : (
<RefreshCwIcon className="size-4" />
)}
<RefreshCwIcon className={`size-4 ${loading ? "animate-spin" : ""}`} />
Re-authenticate Google Drive
</Button>
</div>
@ -517,9 +512,8 @@ export const CreateGoogleDriveFileToolUI = makeAssistantToolUI<
render: function CreateGoogleDriveFileUI({ args, result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Preparing Google Drive file...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Preparing Google Drive file..." size="sm" />
</div>
);
}

View file

@ -5,7 +5,6 @@ import {
AlertTriangleIcon,
CornerDownLeftIcon,
InfoIcon,
Loader2Icon,
RefreshCwIcon,
TriangleAlertIcon,
} from "lucide-react";
@ -13,7 +12,7 @@ import { useParams } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
import { authenticatedFetch } from "@/lib/auth-utils";
interface GoogleDriveAccount {
@ -368,11 +367,7 @@ function InsufficientPermissionsCard({ result }: { result: InsufficientPermissio
<div className="px-5 py-4 space-y-3">
<p className="text-sm text-muted-foreground">{result.message}</p>
<Button size="sm" className="rounded-lg" onClick={handleReauth} disabled={loading}>
{loading ? (
<Loader2Icon className="size-4 animate-spin" />
) : (
<RefreshCwIcon className="size-4" />
)}
<RefreshCwIcon className={`size-4 ${loading ? "animate-spin" : ""}`} />
Re-authenticate Google Drive
</Button>
</div>
@ -466,9 +461,8 @@ export const DeleteGoogleDriveFileToolUI = makeAssistantToolUI<
render: function DeleteGoogleDriveFileUI({ result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Looking up file in Google Drive...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Looking up file in Google Drive..." size="sm" />
</div>
);
}

View file

@ -12,7 +12,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { PlateEditor } from "@/components/editor/plate-editor";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
import { useSetAtom } from "jotai";
import { openHitlEditPanelAtom } from "@/atoms/chat/hitl-edit-panel.atom";
@ -571,9 +571,8 @@ export const CreateLinearIssueToolUI = makeAssistantToolUI<
render: function CreateLinearIssueUI({ args, result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Preparing Linear issue...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Preparing Linear issue..." size="sm" />
</div>
);
}

View file

@ -4,7 +4,7 @@ import { makeAssistantToolUI } from "@assistant-ui/react";
import { CornerDownLeftIcon, TriangleAlertIcon } from "lucide-react";
import { useCallback, useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
interface InterruptResult {
__interrupt__: true;
@ -367,9 +367,8 @@ export const DeleteLinearIssueToolUI = makeAssistantToolUI<
render: function DeleteLinearIssueUI({ result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Preparing Linear issue deletion...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Preparing Linear issue deletion..." size="sm" />
</div>
);
}

View file

@ -13,7 +13,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { PlateEditor } from "@/components/editor/plate-editor";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
import { openHitlEditPanelAtom } from "@/atoms/chat/hitl-edit-panel.atom";
interface LinearLabel {
@ -709,9 +709,8 @@ export const UpdateLinearIssueToolUI = makeAssistantToolUI<
render: function UpdateLinearIssueUI({ result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Preparing Linear issue update...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Preparing Linear issue update..." size="sm" />
</div>
);
}

View file

@ -13,7 +13,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { PlateEditor } from "@/components/editor/plate-editor";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
import { openHitlEditPanelAtom } from "@/atoms/chat/hitl-edit-panel.atom";
interface InterruptResult {
@ -444,9 +444,8 @@ export const CreateNotionPageToolUI = makeAssistantToolUI<
render: function CreateNotionPageUI({ args, result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Preparing Notion page...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Preparing Notion page..." size="sm" />
</div>
);
}

View file

@ -4,7 +4,7 @@ import { makeAssistantToolUI } from "@assistant-ui/react";
import { CornerDownLeftIcon, TriangleAlertIcon } from "lucide-react";
import { useCallback, useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
interface InterruptResult {
__interrupt__: true;
@ -383,9 +383,8 @@ export const DeleteNotionPageToolUI = makeAssistantToolUI<
render: function DeleteNotionPageUI({ result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Deleting Notion page...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Deleting Notion page..." size="sm" />
</div>
);
}

View file

@ -6,7 +6,7 @@ import { CornerDownLeftIcon, Pen } from "lucide-react";
import { useCallback, useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import { PlateEditor } from "@/components/editor/plate-editor";
import { Spinner } from "@/components/ui/spinner";
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
import { openHitlEditPanelAtom } from "@/atoms/chat/hitl-edit-panel.atom";
interface InterruptResult {
@ -390,9 +390,8 @@ export const UpdateNotionPageToolUI = makeAssistantToolUI<
render: function UpdateNotionPageUI({ args, result, status }) {
if (status.type === "running") {
return (
<div className="my-4 flex max-w-lg items-center gap-3 rounded-2xl border bg-muted/30 px-5 py-4">
<Spinner size="sm" className="text-muted-foreground" />
<p className="text-sm text-muted-foreground">Updating Notion page...</p>
<div className="my-4 max-w-lg rounded-2xl border bg-muted/30 px-5 py-4">
<TextShimmerLoader text="Updating Notion page..." size="sm" />
</div>
);
}