From 272f0b5880f08882ab96fbdbd6596e8de00d1438 Mon Sep 17 00:00:00 2001 From: papistacoding Date: Thu, 16 Jan 2025 17:59:54 +0100 Subject: [PATCH 1/6] makinh billing html more pleasent --- .../protected/organization/billing/pricing-plan.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/console/src/components/pages/protected/organization/billing/pricing-plan.tsx b/apps/console/src/components/pages/protected/organization/billing/pricing-plan.tsx index cb9ed8f6..9237173a 100644 --- a/apps/console/src/components/pages/protected/organization/billing/pricing-plan.tsx +++ b/apps/console/src/components/pages/protected/organization/billing/pricing-plan.tsx @@ -61,11 +61,11 @@ const PricingPlan = () => {

Pricing Plan

-

Current Plan

+
-
- -
+
+ +

{productTier ?? 'N/A'}

@@ -78,14 +78,14 @@ const PricingPlan = () => {

{formattedExpiresDate}

-
{/* Features List */}

Features in this plan

-
    +
      {features?.length > 0 ? features.map((feature: string, index: number) => ) :

      No features listed.

      }
From 8fda8144a8a02fb8258752a7a3c5deb0d5d5eef4 Mon Sep 17 00:00:00 2001 From: papistacoding Date: Thu, 16 Jan 2025 19:06:00 +0100 Subject: [PATCH 2/6] actions rendering conditions on org member table --- .../members/actions/member-actions.tsx | 28 +++++++++++++++++-- .../organization/members/members-table.tsx | 4 ++- packages/codegen/query/user.graphql | 1 + packages/codegen/src/schema.ts | 2 ++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/apps/console/src/components/pages/protected/organization/members/actions/member-actions.tsx b/apps/console/src/components/pages/protected/organization/members/actions/member-actions.tsx index 22c4d5c9..a26cfa73 100644 --- a/apps/console/src/components/pages/protected/organization/members/actions/member-actions.tsx +++ b/apps/console/src/components/pages/protected/organization/members/actions/member-actions.tsx @@ -4,7 +4,7 @@ import { MoreHorizontal, Trash2, UserRoundPen } from 'lucide-react' import { useToast } from '@repo/ui/use-toast' import { pageStyles } from '../page.styles' import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from '@repo/ui/dropdown-menu' -import { OrgMembershipRole, useRemoveUserFromOrgMutation, useUpdateUserRoleInOrgMutation } from '@repo/codegen/src/schema' +import { OrgMembershipRole, useGetUserProfileQuery, useRemoveUserFromOrgMutation, useUpdateUserRoleInOrgMutation } from '@repo/codegen/src/schema' import { type UseQueryExecute } from 'urql' import { AlertDialog, @@ -24,18 +24,28 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { z, infer as zInfer } from 'zod' +import { useSession } from 'next-auth/react' +import { useUserHasOrganizationEditPermissions } from '@/lib/authz/utils' type MemberActionsProps = { memberId: string refetchMembers: UseQueryExecute + memberRole: OrgMembershipRole } const ICON_SIZE = 12 -export const MemberActions = ({ memberId: memberId, refetchMembers: refetchMembers }: MemberActionsProps) => { +export const MemberActions = ({ memberId, refetchMembers, memberRole }: MemberActionsProps) => { const { actionIcon, roleRow, buttonRow } = pageStyles() const { toast } = useToast() const [_, deleteMember] = useRemoveUserFromOrgMutation() + const { data: sessionData } = useSession() + const userId = sessionData?.user.userId + + const variables = { userId: userId ?? '' } + const [{ data: userData }] = useGetUserProfileQuery({ variables }) + + const { data, isLoading, error } = useUserHasOrganizationEditPermissions(sessionData) const handleDeleteMember = async () => { const response = await deleteMember({ deleteOrgMembershipId: memberId }) @@ -104,6 +114,20 @@ export const MemberActions = ({ memberId: memberId, refetchMembers: refetchMembe formState: { errors }, } = form + if (memberRole === OrgMembershipRole.OWNER) { + //CANT EDIT OWNER + return null + } + if (memberId === userData?.user.id) { + //CANT EDIT YOURSELF + return null + } + + if (!data.allowed) { + //MEMBERS CANT EDIT ANYONE + return null + } + return ( diff --git a/apps/console/src/components/pages/protected/organization/members/members-table.tsx b/apps/console/src/components/pages/protected/organization/members/members-table.tsx index 1e49868c..a25baf42 100644 --- a/apps/console/src/components/pages/protected/organization/members/members-table.tsx +++ b/apps/console/src/components/pages/protected/organization/members/members-table.tsx @@ -131,7 +131,9 @@ export const MembersTable = ({ setActiveTab }: MembersTableProps) => { { accessorKey: 'id', header: '', - cell: ({ cell }) => , + cell: ({ cell }) => { + return + }, size: 40, }, ] diff --git a/packages/codegen/query/user.graphql b/packages/codegen/query/user.graphql index 8b4217dd..65a5d28e 100644 --- a/packages/codegen/query/user.graphql +++ b/packages/codegen/query/user.graphql @@ -7,6 +7,7 @@ query GetUserProfile($userId: ID!) { email avatarRemoteURL displayName + role avatarFile { presignedURL } diff --git a/packages/codegen/src/schema.ts b/packages/codegen/src/schema.ts index 6c172f43..ae2a513c 100644 --- a/packages/codegen/src/schema.ts +++ b/packages/codegen/src/schema.ts @@ -18408,6 +18408,7 @@ export type GetUserProfileQuery = { displayName: string email: string avatarRemoteURL?: string | null + role?: UserRole | null avatarFile?: { __typename?: 'File'; presignedURL?: string | null } | null setting: { __typename?: 'UserSetting' @@ -19593,6 +19594,7 @@ export const GetUserProfileDocument = gql` email avatarRemoteURL displayName + role avatarFile { presignedURL } From 0cbc53299b472e430b754ae9df2759c2b5156e6c Mon Sep 17 00:00:00 2001 From: papistacoding Date: Thu, 16 Jan 2025 19:09:08 +0100 Subject: [PATCH 3/6] removing extra field --- packages/codegen/query/user.graphql | 1 - packages/codegen/src/schema.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/packages/codegen/query/user.graphql b/packages/codegen/query/user.graphql index 65a5d28e..8b4217dd 100644 --- a/packages/codegen/query/user.graphql +++ b/packages/codegen/query/user.graphql @@ -7,7 +7,6 @@ query GetUserProfile($userId: ID!) { email avatarRemoteURL displayName - role avatarFile { presignedURL } diff --git a/packages/codegen/src/schema.ts b/packages/codegen/src/schema.ts index ae2a513c..6c172f43 100644 --- a/packages/codegen/src/schema.ts +++ b/packages/codegen/src/schema.ts @@ -18408,7 +18408,6 @@ export type GetUserProfileQuery = { displayName: string email: string avatarRemoteURL?: string | null - role?: UserRole | null avatarFile?: { __typename?: 'File'; presignedURL?: string | null } | null setting: { __typename?: 'UserSetting' @@ -19594,7 +19593,6 @@ export const GetUserProfileDocument = gql` email avatarRemoteURL displayName - role avatarFile { presignedURL } From a73fd423efc289e8a04d8628ef0a255be8171ab5 Mon Sep 17 00:00:00 2001 From: papistacoding Date: Thu, 16 Jan 2025 19:13:08 +0100 Subject: [PATCH 4/6] removing email form from org general settings --- .../organization-settings/general-settings/page.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/console/src/app/(protected)/organization-settings/general-settings/page.tsx b/apps/console/src/app/(protected)/organization-settings/general-settings/page.tsx index 692c4928..6dd69301 100644 --- a/apps/console/src/app/(protected)/organization-settings/general-settings/page.tsx +++ b/apps/console/src/app/(protected)/organization-settings/general-settings/page.tsx @@ -1,9 +1,7 @@ import { PageHeading } from '@repo/ui/page-heading' import type { Metadata } from 'next/types' import { OrganizationNameForm } from '@/components/pages/protected/organization/general-settings/organization-name-form' -import { AvatarUpload } from '@/components/shared/avatar-upload/avatar-upload' import { pageStyles } from './page.styles' -import { OrganizationEmailForm } from '@/components/pages/protected/organization/general-settings/organization-email-form' import { OrganizationDelete } from '@/components/pages/protected/organization/general-settings/organization-delete' export const metadata: Metadata = { @@ -17,7 +15,6 @@ const Page: React.FC = () => {
-
From 9537190d977e3738c369d34222dab1c4bf5e791b Mon Sep 17 00:00:00 2001 From: papistacoding Date: Thu, 16 Jan 2025 23:54:53 +0100 Subject: [PATCH 5/6] progress on personal api page --- .../user-settings/developers/page.tsx | 2 +- .../developers/developers-user-page.tsx | 80 ++++++- .../personal-access-token-create-dialog.tsx | 226 ++++++++++++++++++ 3 files changed, 295 insertions(+), 13 deletions(-) create mode 100644 apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx diff --git a/apps/console/src/app/(protected)/user-settings/developers/page.tsx b/apps/console/src/app/(protected)/user-settings/developers/page.tsx index a169f28c..ba8193d1 100644 --- a/apps/console/src/app/(protected)/user-settings/developers/page.tsx +++ b/apps/console/src/app/(protected)/user-settings/developers/page.tsx @@ -9,7 +9,7 @@ export const metadata: Metadata = { const Page: React.FC = () => { return ( <> - + ) diff --git a/apps/console/src/components/pages/protected/developers/developers-user-page.tsx b/apps/console/src/components/pages/protected/developers/developers-user-page.tsx index 71161300..c3068255 100644 --- a/apps/console/src/components/pages/protected/developers/developers-user-page.tsx +++ b/apps/console/src/components/pages/protected/developers/developers-user-page.tsx @@ -1,23 +1,79 @@ 'use client' +import React from 'react' import { pageStyles } from './page.styles' -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@repo/ui/tabs' -import { useState } from 'react' -import { PersonalAccessTokenForm } from './personal-access-token-form' -import { PersonalAccessTokenTable } from './personal-access-tokens-table' +import { Panel, PanelHeader } from '@repo/ui/panel' +import { Button } from '@repo/ui/button' +import { CirclePlusIcon } from 'lucide-react' +import { DataTable } from '@repo/ui/data-table' +import PersonalApiKeyDialog from './personal-access-token-create-dialog' + +interface Token { + name: string + description: string + organizations: string + expires: string +} + +const columns = [ + { + accessorKey: 'name', + header: 'Name', + }, + { + accessorKey: 'description', + header: 'Description', + }, + { + accessorKey: 'organizations', + header: 'Organization(s)', + }, + { + accessorKey: 'expires', + header: 'Expires', + }, + { + accessorKey: 'actions', + header: '', + cell: () => ( + + ), + }, +] + +const data: Token[] = [ + { + name: 'Development', + description: 'Main computer, full Docker', + organizations: 'Meowmeow', + expires: 'Never', + }, + { + name: 'Mobile laptop', + description: 'For writing docs', + organizations: 'Woofwoof', + expires: 'January 7, 2024 1:22 PM', + }, +] const DevelopersPage: React.FC = () => { const { wrapper } = pageStyles() - const defaultTab = 'pat' - const [activeTab, setActiveTab] = useState(defaultTab) return ( - <> -
- - -
- +
+ +
+ + {/* */} + +
+ +
+
) } diff --git a/apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx b/apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx new file mode 100644 index 00000000..ed276b7c --- /dev/null +++ b/apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx @@ -0,0 +1,226 @@ +'use client' + +import React, { useState } from 'react' +import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@repo/ui/dialog' +import { Input } from '@repo/ui/input' +import { Label } from '@repo/ui/label' +import { Button } from '@repo/ui/button' +import { Checkbox } from '@repo/ui/checkbox' +import { CirclePlusIcon } from 'lucide-react' +import { toast } from '@repo/ui/use-toast' +import { useCreatePersonalAccessTokenMutation } from '@repo/codegen/src/schema' +import { useSession } from 'next-auth/react' +import { useOrganization } from '@/hooks/useOrganization' +import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@repo/ui/form' +import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger } from '@repo/ui/dropdown-menu' +import { Avatar, AvatarFallback, AvatarImage } from '@repo/ui/avatar' +import { useForm } from 'react-hook-form' +import { z, infer as zInfer } from 'zod' +import { zodResolver } from '@hookform/resolvers/zod' + +const formSchema = z + .object({ + name: z.string().min(3, { message: 'Token name is required' }), + description: z.string().optional(), + organizationIDs: z.array(z.string()).optional(), + expiryDate: z.date().optional(), + noExpire: z.boolean().optional(), + }) + .refine((data) => data.expiryDate || data.noExpire, { + message: 'Please specify an expiry date or select the Never expires checkbox', + path: ['expiryDate'], + }) + +type FormData = zInfer + +const PersonalApiKeyDialog: React.FC = () => { + const { data: sessionData } = useSession() + const { allOrgs: orgs } = useOrganization() + const [isSubmitting, setIsSubmitting] = useState(false) + const [result, createToken] = useCreatePersonalAccessTokenMutation() + + const form = useForm({ + resolver: zodResolver(formSchema), + defaultValues: { + name: '', + description: '', + expiryDate: undefined, + organizationIDs: [], + noExpire: false, + }, + }) + + const handleSubmit = async (values: FormData) => { + try { + setIsSubmitting(true) + const response = await createToken({ + input: { + name: values.name, + description: values.description, + expiresAt: values.noExpire ? null : values.expiryDate, + ownerID: sessionData?.user.userId, + organizationIDs: values.organizationIDs || [], + }, + }) + + const createdToken = response.data?.createPersonalAccessToken.personalAccessToken.token + + if (response.data && createdToken) { + toast({ + title: 'Token created successfully!', + description: 'Copy your access token now, as you will not be able to see it again.', + variant: 'success', + }) + console.log('Generated Token:', createdToken) // Show this in a modal/dialog if needed + } else { + throw new Error('Failed to create token') + } + } catch (error) { + toast({ + title: 'Error creating API Key!', + description: 'Something went wrong. Please try again.', + variant: 'destructive', + }) + } finally { + setIsSubmitting(false) + } + } + + return ( + { + console.log('first') + }} + > + + + + + + Create new token + +
+ + ( + + Token name* + + + + + + )} + /> + + ( + + Description + + + + + + )} + /> + + ( + + Authorized organization(s) + + + + + + + {Object.entries(orgs).map(([key, value]) => { + const image = value?.node?.avatarFile?.presignedURL ?? value?.node?.avatarRemoteURL + return ( + { + const newValue = checked ? [...(field?.value ?? []), value?.node?.id!] : field?.value?.filter((id) => id !== value?.node?.id) + field.onChange(newValue) + }} + > + + {image && } + {value?.node?.name?.substring(0, 2)} + + {value?.node?.name} + + ) + })} + + + + + + )} + /> + + ( + + Expiration* + + field.onChange(e.target.value ? new Date(e.target.value) : undefined)} + /> + + + + )} + /> + + ( + +
+ field.onChange(checked)} /> + +
+
+ )} + /> + + + + + + +
+
+ ) +} + +export default PersonalApiKeyDialog From aaca8cbcfa50eb0fbabf4a9ec08b14fb1f77a337 Mon Sep 17 00:00:00 2001 From: papistacoding Date: Sat, 18 Jan 2025 02:10:53 +0100 Subject: [PATCH 6/6] progress --- .../developers/actions/pat-actions.tsx | 28 ++++++++- .../developers/developers-user-page.tsx | 59 +------------------ .../personal-access-token-create-dialog.tsx | 47 ++++++++++----- .../personal-access-tokens-table-styles.tsx | 14 +++++ .../personal-access-tokens-table.tsx | 31 ++++++++-- packages/ui/src/data-table/data-table.tsx | 32 +++++++--- 6 files changed, 126 insertions(+), 85 deletions(-) create mode 100644 apps/console/src/components/pages/protected/developers/personal-access-tokens-table-styles.tsx diff --git a/apps/console/src/components/pages/protected/developers/actions/pat-actions.tsx b/apps/console/src/components/pages/protected/developers/actions/pat-actions.tsx index c070513c..06373d6a 100644 --- a/apps/console/src/components/pages/protected/developers/actions/pat-actions.tsx +++ b/apps/console/src/components/pages/protected/developers/actions/pat-actions.tsx @@ -4,6 +4,8 @@ import { MoreHorizontal, Trash2 } from 'lucide-react' import { useToast } from '@repo/ui/use-toast' import { pageStyles } from '../page.styles' import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from '@repo/ui/dropdown-menu' +import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } from '@repo/ui/dialog' +import { Button } from '@repo/ui/button' import { useDeletePersonalAccessTokenMutation } from '@repo/codegen/src/schema' import { type UseQueryExecute } from 'urql' @@ -39,6 +41,7 @@ export const TokenAction = ({ tokenId, refetchTokens }: TokenActionProps) => { }) } } + return ( @@ -46,8 +49,29 @@ export const TokenAction = ({ tokenId, refetchTokens }: TokenActionProps) => { - - Delete token + + + +
+ + Delete token +
+
+ + + Confirm Deletion + Are you sure you want to delete this token? This action cannot be undone. + + + + + + + + +
diff --git a/apps/console/src/components/pages/protected/developers/developers-user-page.tsx b/apps/console/src/components/pages/protected/developers/developers-user-page.tsx index c3068255..7f7d03c9 100644 --- a/apps/console/src/components/pages/protected/developers/developers-user-page.tsx +++ b/apps/console/src/components/pages/protected/developers/developers-user-page.tsx @@ -3,60 +3,8 @@ import React from 'react' import { pageStyles } from './page.styles' import { Panel, PanelHeader } from '@repo/ui/panel' -import { Button } from '@repo/ui/button' -import { CirclePlusIcon } from 'lucide-react' -import { DataTable } from '@repo/ui/data-table' import PersonalApiKeyDialog from './personal-access-token-create-dialog' - -interface Token { - name: string - description: string - organizations: string - expires: string -} - -const columns = [ - { - accessorKey: 'name', - header: 'Name', - }, - { - accessorKey: 'description', - header: 'Description', - }, - { - accessorKey: 'organizations', - header: 'Organization(s)', - }, - { - accessorKey: 'expires', - header: 'Expires', - }, - { - accessorKey: 'actions', - header: '', - cell: () => ( - - ), - }, -] - -const data: Token[] = [ - { - name: 'Development', - description: 'Main computer, full Docker', - organizations: 'Meowmeow', - expires: 'Never', - }, - { - name: 'Mobile laptop', - description: 'For writing docs', - organizations: 'Woofwoof', - expires: 'January 7, 2024 1:22 PM', - }, -] +import { PersonalAccessTokenTable } from './personal-access-tokens-table' const DevelopersPage: React.FC = () => { const { wrapper } = pageStyles() @@ -66,12 +14,9 @@ const DevelopersPage: React.FC = () => {
- {/* */}
- +
) diff --git a/apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx b/apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx index ed276b7c..15224ea4 100644 --- a/apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx +++ b/apps/console/src/components/pages/protected/developers/personal-access-token-create-dialog.tsx @@ -8,7 +8,7 @@ import { Button } from '@repo/ui/button' import { Checkbox } from '@repo/ui/checkbox' import { CirclePlusIcon } from 'lucide-react' import { toast } from '@repo/ui/use-toast' -import { useCreatePersonalAccessTokenMutation } from '@repo/codegen/src/schema' +import { useCreatePersonalAccessTokenMutation, useGetPersonalAccessTokensQuery } from '@repo/codegen/src/schema' import { useSession } from 'next-auth/react' import { useOrganization } from '@/hooks/useOrganization' import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@repo/ui/form' @@ -17,6 +17,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@repo/ui/avatar' import { useForm } from 'react-hook-form' import { z, infer as zInfer } from 'zod' import { zodResolver } from '@hookform/resolvers/zod' +import { UseQueryExecute } from 'urql' const formSchema = z .object({ @@ -33,12 +34,18 @@ const formSchema = z type FormData = zInfer -const PersonalApiKeyDialog: React.FC = () => { +type PersonalApiKeyDialogProps = { + triggerText?: boolean +} + +const PersonalApiKeyDialog = ({ triggerText }: PersonalApiKeyDialogProps) => { const { data: sessionData } = useSession() const { allOrgs: orgs } = useOrganization() const [isSubmitting, setIsSubmitting] = useState(false) const [result, createToken] = useCreatePersonalAccessTokenMutation() + const [{ data, fetching, error }, refetch] = useGetPersonalAccessTokensQuery({ requestPolicy: 'network-only' }) + const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { @@ -71,6 +78,7 @@ const PersonalApiKeyDialog: React.FC = () => { description: 'Copy your access token now, as you will not be able to see it again.', variant: 'success', }) + refetch() console.log('Generated Token:', createdToken) // Show this in a modal/dialog if needed } else { throw new Error('Failed to create token') @@ -93,9 +101,16 @@ const PersonalApiKeyDialog: React.FC = () => { }} > - + {triggerText ? ( +
+

Create token

+

?

+
+ ) : ( + + )}
@@ -183,15 +198,19 @@ const PersonalApiKeyDialog: React.FC = () => { render={({ field }) => ( Expiration* - - field.onChange(e.target.value ? new Date(e.target.value) : undefined)} - /> - - + {!form.watch('noExpire') && ( + <> + + field.onChange(e.target.value ? new Date(e.target.value) : undefined)} + /> + + + + )} )} /> diff --git a/apps/console/src/components/pages/protected/developers/personal-access-tokens-table-styles.tsx b/apps/console/src/components/pages/protected/developers/personal-access-tokens-table-styles.tsx new file mode 100644 index 00000000..89fe9e87 --- /dev/null +++ b/apps/console/src/components/pages/protected/developers/personal-access-tokens-table-styles.tsx @@ -0,0 +1,14 @@ +import { tv, type VariantProps } from 'tailwind-variants' + +const personalAccessTokenTableStyles = tv({ + slots: { + tableRow: 'h-64 text-center', + keyIcon: 'text-accent-primary cursor-pointer text-4xl', + message: ' text-sm mt-5', + createLink: 'text-accent-primary text-sm font-medium mt-2 underline cursor-pointer', + }, +}) + +export type PersonalAccessTokenTableVariants = VariantProps + +export { personalAccessTokenTableStyles } diff --git a/apps/console/src/components/pages/protected/developers/personal-access-tokens-table.tsx b/apps/console/src/components/pages/protected/developers/personal-access-tokens-table.tsx index 70521d13..ffd57ab7 100644 --- a/apps/console/src/components/pages/protected/developers/personal-access-tokens-table.tsx +++ b/apps/console/src/components/pages/protected/developers/personal-access-tokens-table.tsx @@ -6,6 +6,10 @@ import { ColumnDef } from '@tanstack/react-table' import { useSession } from 'next-auth/react' import { format } from 'date-fns' import { TokenAction } from './actions/pat-actions' +import { TableCell, TableRow } from '../../../../../../../packages/ui/src/table/table' +import { KeyRound } from 'lucide-react' +import { personalAccessTokenTableStyles } from './personal-access-tokens-table-styles' +import PersonalApiKeyDialog from './personal-access-token-create-dialog' type TokenNode = { __typename?: 'PersonalAccessToken' | undefined @@ -28,10 +32,9 @@ type TokenEdge = { export const PersonalAccessTokenTable = () => { const { data: session } = useSession() + const { tableRow, keyIcon, message, createLink } = personalAccessTokenTableStyles() - const [{ data, fetching, error }, refetch] = useGetPersonalAccessTokensQuery({ - pause: !session, - }) + const [{ data, fetching, error }, refetch] = useGetPersonalAccessTokensQuery({ requestPolicy: 'network-only' }) if (fetching) return

Loading...

if (error || !data) return null @@ -70,6 +73,24 @@ export const PersonalAccessTokenTable = () => { }, ] - return + console.log('data', data) + + return ( + + +
+ +

No personal access tokens found.

+ +
+
+ + } + /> + ) } -// diff --git a/packages/ui/src/data-table/data-table.tsx b/packages/ui/src/data-table/data-table.tsx index fca54ef5..9d4742b8 100644 --- a/packages/ui/src/data-table/data-table.tsx +++ b/packages/ui/src/data-table/data-table.tsx @@ -15,7 +15,7 @@ import { import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, TableFooter } from '../table/table' import { Button } from '../button/button' -import { useState } from 'react' +import { ReactElement, useState } from 'react' import { Input } from '../input/input' import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger } from '../dropdown-menu/dropdown-menu' import { EyeIcon } from 'lucide-react' @@ -27,9 +27,10 @@ interface DataTableProps { showFilter?: boolean showVisibility?: boolean noResultsText?: string + noDataMarkup?: ReactElement } -export function DataTable({ columns, loading = false, data, showFilter = false, showVisibility = false, noResultsText = 'No results' }: DataTableProps) { +export function DataTable({ columns, loading = false, data, showFilter = false, showVisibility = false, noResultsText = 'No results', noDataMarkup }: DataTableProps) { const [sorting, setSorting] = useState([]) const [columnFilters, setColumnFilters] = useState([]) const [columnVisibility, setColumnVisibility] = useState({}) @@ -118,11 +119,7 @@ export function DataTable({ columns, loading = false, data, showF )) ) : ( - - - {loading ? 'Loading' : noResultsText} - - + )} @@ -144,3 +141,24 @@ export function DataTable({ columns, loading = false, data, showF
) } + +interface NoDataProps { + loading: boolean + colLength: number + noDataMarkup?: ReactElement + noResultsText: string +} + +const NoData = ({ loading, colLength, noDataMarkup, noResultsText }: NoDataProps) => { + if (!loading && noDataMarkup) { + return noDataMarkup + } + + return ( + + + {loading ? 'Loading' : noResultsText} + + + ) +}