// // Copyright (c) 2025 rustmailer.com (https://rustmailer.com) // // This file is part of the Bichon Email Archiving Project // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { get_oauth2_tokens } from '@/api/oauth2/api' import { useQuery } from '@tanstack/react-query' import { Card, CardContent } from '@/components/ui/card' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' import { TableSkeleton } from '@/components/table-skeleton' import { useTranslation } from 'react-i18next' import { FileIcon } from 'lucide-react' import { format, formatDistanceToNow } from 'date-fns' import LongText from '@/components/long-text' import { useCallback } from 'react' import { IconCopy } from '@tabler/icons-react' import { toast } from '@/hooks/use-toast' import { ToastAction } from '@/components/ui/toast' import { useNavigate } from '@tanstack/react-router' import { dateFnsLocaleMap } from '@/lib/utils' import { enUS } from 'date-fns/locale' import { AccountModel } from '@/api/account/api' interface Props { currentRow: AccountModel open: boolean onOpenChange: (open: boolean) => void } export function OAuth2TokensDialog({ currentRow, open, onOpenChange }: Props) { const { t, i18n } = useTranslation() const locale = dateFnsLocaleMap[i18n.language.toLowerCase()] ?? enUS; const navigate = useNavigate() const { data: oauth2Tokens, isLoading } = useQuery({ queryKey: ['oauth2-tokens', currentRow.id], queryFn: () => get_oauth2_tokens(currentRow.id), enabled: open && !!currentRow.id, retry: 0, refetchOnWindowFocus: false, refetchOnMount: false, }) const onCopy = useCallback(async (access: boolean, token: string) => { try { await navigator.clipboard.writeText(token); if (access) { toast({ title: t('common.ok'), description: t('accounts.accessTokenCopiedToClipboard'), }); } else { toast({ title: t('common.ok'), description: t('accounts.refreshTokenCopiedToClipboard'), }); } } catch (err) { toast({ variant: "destructive", title: t('settings.failedToCopyText'), description: (err as Error).message, action: {t('common.tryAgain')}, }); } }, []); return ( { onOpenChange(state) }} > {t('accounts.oauth2Tokens')} {t('accounts.detailsOfTheOAuth2TokensForTheAccount')} {isLoading ? ( ) : oauth2Tokens ? ( {t('accounts.field')} {t('accounts.value')} {t('common.actions')} {t('oauth2.id')} {oauth2Tokens.oauth2_id} {t('accessTokens.token')} {oauth2Tokens.access_token} {t('accounts.refreshToken')} {oauth2Tokens.refresh_token} {t('settings.createdAt')} {format(new Date(oauth2Tokens.created_at), 'yyyy-MM-dd HH:mm:ss')} {t('settings.updatedAt')} {formatDistanceToNow(new Date(oauth2Tokens.updated_at), { addSuffix: true, locale })}
) : (

{t('accounts.noOAuth2Tokens')}

{t('accounts.theAccountHasNotCompletedTheAuthorizationProcess')} navigate({ to: '/oauth2' })} className="ml-1 text-blue-500 underline cursor-pointer">{t('accounts.clickHere')} {t('accounts.toAuthorizeTheAccount')}

)}
) }