gitscope
← marzneshin / Diff · 912d3dc → 912d3dc
Changes 912d3dc..912d3dc
Patch commit
diff --git a/dashboard/src/components/copy-button/index.tsx b/dashboard/src/components/copy-button/index.tsx
index 0f11897..9b75626 100644
--- a/dashboard/src/components/copy-button/index.tsx
+++ b/dashboard/src/components/copy-button/index.tsx
@@ -1,4 +1,4 @@
-import { Button } from '@marzneshin/components';
+import { Button, Tooltip, TooltipContent, TooltipTrigger } from '@marzneshin/components';
import CopyToClipboard from 'react-copy-to-clipboard';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
@@ -11,9 +11,10 @@ interface CopyToClipboardButtonProps {
disabled?: boolean;
successMessage: string;
copyIcon?: LucideIcon;
- copyLabel: string;
- errorLabel: string;
+ copyLabel?: string;
+ errorLabel?: string;
className?: string;
+ tooltipMsg?: string;
}
export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
@@ -22,7 +23,8 @@ export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
successMessage,
copyIcon,
copyLabel,
- errorLabel, className
+ errorLabel, className,
+ tooltipMsg
}) => {
const { t } = useTranslation();
const [copied, setCopied] = useState(false);
@@ -47,14 +49,26 @@ export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
}
};
+ const tooltip = tooltipMsg ? tooltipMsg : (copyLabel ? copyLabel : undefined)
+
const Icon = copied ? CopyCheck : (healthy ? (copyIcon ? copyIcon : ClipboardCopy) : CopyX)
+ const isWithLabel = successMessage && copyLabel && errorLabel
return (
- <CopyToClipboard text={text}>
- <Button className={cn(className, "p-2 flex flex-row items-center gap-2")} disabled={disabled || !healthy} onClick={handleClick}>
- <Icon />
- {t(copied ? successMessage : (healthy ? copyLabel : errorLabel))}
- </Button>
- </CopyToClipboard>
+ <Tooltip>
+ <TooltipTrigger>
+ <CopyToClipboard text={text}>
+ <Button className={cn(className, "p-2 flex flex-row items-center gap-2")} disabled={disabled || !healthy} onClick={handleClick}>
+ <Icon />
+ {isWithLabel && t(copied ? successMessage : (healthy ? copyLabel : errorLabel))}
+ </Button>
+ </CopyToClipboard>
+ </TooltipTrigger>
+ {tooltip &&
+ <TooltipContent>
+ {tooltip}
+ </TooltipContent>
+ }
+ </Tooltip >
);
};
diff --git a/dashboard/src/features/users/dialogs/settings/user-info/qrcode.tsx b/dashboard/src/features/users/dialogs/settings/user-info/qrcode.tsx
index 4ac0416..058f814 100644
--- a/dashboard/src/features/users/dialogs/settings/user-info/qrcode.tsx
+++ b/dashboard/src/features/users/dialogs/settings/user-info/qrcode.tsx
@@ -6,6 +6,7 @@ import { FC } from 'react'
import { Card, CardContent, CardHeader, CardTitle } from '@marzneshin/components';
import { useTranslation } from 'react-i18next';
import { SubscriptionLinkButton } from './subcription-link-button';
+import { getSubscriptionLink } from '@marzneshin/utils';
interface QRCodeProps {
entity: UserType
@@ -14,9 +15,7 @@ interface QRCodeProps {
export const QRCodeSection: FC<QRCodeProps> = (
{ entity }
) => {
- const subscribeQrLink = String(entity.subscription_url).startsWith('/')
- ? window.location.origin + entity.subscription_url
- : String(entity.subscription_url);
+ const subscribeQrLink = getSubscriptionLink(entity.subscription_url);
const { t } = useTranslation()
return (
<Card>
diff --git a/dashboard/src/features/users/dialogs/settings/user-info/subcription-link-button.tsx b/dashboard/src/features/users/dialogs/settings/user-info/subcription-link-button.tsx
index 8f5a077..004369f 100644
--- a/dashboard/src/features/users/dialogs/settings/user-info/subcription-link-button.tsx
+++ b/dashboard/src/features/users/dialogs/settings/user-info/subcription-link-button.tsx
@@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next';
import { CopyToClipboardButton } from '@marzneshin/components';
import { FC } from 'react';
import { SquareCode } from 'lucide-react';
+import { getSubscriptionLink } from '@marzneshin/utils';
interface SubscriptionLinkButtonProps {
subscriptionLink: string;
@@ -12,7 +13,7 @@ export const SubscriptionLinkButton: FC<SubscriptionLinkButtonProps> = ({ subscr
return (
<CopyToClipboardButton
- text={subscriptionLink}
+ text={getSubscriptionLink(subscriptionLink)}
successMessage={t('page.users.settings.subscription_link.copied')}
copyLabel={t('page.users.settings.subscription_link.copy')}
errorLabel={t('page.users.settings.subscription_link.error')}
diff --git a/dashboard/src/features/users/tables/users/columns.tsx b/dashboard/src/features/users/tables/users/columns.tsx
index 5d8af0b..89f11e3 100644
--- a/dashboard/src/features/users/tables/users/columns.tsx
+++ b/dashboard/src/features/users/tables/users/columns.tsx
@@ -3,8 +3,10 @@ import { ColumnDef } from "@tanstack/react-table"
import { UsersStatusBadge, UserType, UsersStatus } from "@marzneshin/features/users"
import { DataTableColumnHeader } from "@marzneshin/components/data-table/column-header"
import i18n from "@marzneshin/features/i18n"
-import { DataTableActionsCell } from "@marzneshin/components"
+import { CopyToClipboardButton, DataTableActionsCell, buttonVariants } from "@marzneshin/components"
import { CircularProgress } from "@nextui-org/progress"
+import { LinkIcon } from "lucide-react"
+import { getSubscriptionLink } from "@marzneshin/utils"
interface ColumnAction {
onDelete: (user: UserType) => void;
@@ -46,6 +48,15 @@ export const columns = (actions: ColumnAction): ColumnDef<UserType>[] => ([
},
{
id: "actions",
- cell: ({ row }) => <DataTableActionsCell {...actions} row={row} />
+ cell: ({ row }) => <div className="flex flex-row gap-2 items-center" onClick={(e) => e.stopPropagation()}>
+ <CopyToClipboardButton
+ text={getSubscriptionLink(row.original.subscription_url)}
+ successMessage={i18n.t('page.users.settings.subscription_link.copied')}
+ copyIcon={LinkIcon}
+ className={buttonVariants({ variant: "ghost", className: "h-8 w-8" })}
+ tooltipMsg={i18n.t('page.users.settings.subscription_link.copy')}
+ />
+ <DataTableActionsCell {...actions} row={row} />
+ </div>
},
]);
diff --git a/dashboard/src/routes/_dashboard.tsx b/dashboard/src/routes/_dashboard.tsx
index dc569c2..e483770 100644
--- a/dashboard/src/routes/_dashboard.tsx
+++ b/dashboard/src/routes/_dashboard.tsx
@@ -5,7 +5,8 @@ import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
- Toaster
+ Toaster,
+ TooltipProvider
} from '@marzneshin/components'
import { NavigationDirectory } from '@marzneshin/components/nav-dir';
import { useAuth } from '@marzneshin/features/auth'
@@ -49,10 +50,12 @@ export const DashboardLayout = () => {
</ResizablePanel>
<ResizableHandle withHandle className="w-[2px]" />
<ResizablePanel>
- <main>
- <Outlet />
- <Toaster position="top-center" />
- </main>
+ <TooltipProvider>
+ <main>
+ <Outlet />
+ <Toaster position="top-center" />
+ </main>
+ </TooltipProvider>
</ResizablePanel>
</ResizablePanelGroup>
) : (
diff --git a/dashboard/src/utils/index.ts b/dashboard/src/utils/index.ts
index d3ce67c..6fca071 100644
--- a/dashboard/src/utils/index.ts
+++ b/dashboard/src/utils/index.ts
@@ -2,3 +2,4 @@ export * from './cn'
export * from './fetch'
export * from './cn'
export * from './query-client'
+export * from './subscription-link'
diff --git a/dashboard/src/utils/subscription-link.ts b/dashboard/src/utils/subscription-link.ts
new file mode 100644
index 0000000..70c6b86
--- /dev/null
+++ b/dashboard/src/utils/subscription-link.ts
@@ -0,0 +1,4 @@
+
+export const getSubscriptionLink = (url: string) => String(url).startsWith('/')
+ ? window.location.origin + url
+ : String(url);