• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

teableio / teable / 10062884181

23 Jul 2024 04:40PM UTC coverage: 17.778% (-64.7%) from 82.436%
10062884181

push

github

web-flow
refactor: react query (#752)

1384 of 2805 branches covered (49.34%)

0 of 285 new or added lines in 58 files covered. (0.0%)

14014 of 78827 relevant lines covered (17.78%)

1.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/apps/nextjs-app/src/features/app/components/collaborator-manage/space/InviteLink.tsx
1
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
×
2
import type { SpaceRole } from '@teable/core';
×
3
import { Copy, X } from '@teable/icons';
×
4
import {
×
5
  deleteSpaceInvitationLink,
×
6
  listSpaceInvitationLink,
×
7
  updateSpaceInvitationLink,
×
8
} from '@teable/openapi';
×
9
import { useSpaceRoleStatic, useLanDayjs } from '@teable/sdk/hooks';
×
10
import {
×
11
  Button,
×
12
  Input,
×
13
  Tooltip,
×
14
  TooltipContent,
×
15
  TooltipProvider,
×
16
  TooltipTrigger,
×
17
  useToast,
×
18
} from '@teable/ui-lib';
×
19
import { map } from 'lodash';
×
20
import { useTranslation } from 'next-i18next';
×
21
import { useMemo } from 'react';
×
22
import { RoleSelect } from './RoleSelect';
×
23
import { getRolesWithLowerPermissions } from './utils';
×
24

×
25
interface IInviteLink {
×
26
  spaceId: string;
×
27
  role: SpaceRole;
×
28
}
×
29

×
30
export const InviteLink: React.FC<IInviteLink> = (props) => {
×
31
  const { spaceId, role } = props;
×
32
  const queryClient = useQueryClient();
×
33
  const { toast } = useToast();
×
34
  const { t } = useTranslation('common');
×
35
  const dayjs = useLanDayjs();
×
36

×
37
  const linkList = useQuery({
×
38
    queryKey: ['invite-link-list', spaceId],
×
NEW
39
    queryFn: ({ queryKey }) => listSpaceInvitationLink(queryKey[1]).then((res) => res.data),
×
NEW
40
  }).data;
×
41

×
42
  const { mutate: updateInviteLink, isLoading: updateInviteLinkLoading } = useMutation({
×
43
    mutationFn: updateSpaceInvitationLink,
×
44
    onSuccess: () => {
×
45
      queryClient.invalidateQueries({ queryKey: ['invite-link-list'] });
×
46
    },
×
47
  });
×
48

×
49
  const { mutate: deleteInviteLink, isLoading: deleteInviteLinkLoading } = useMutation({
×
50
    mutationFn: deleteSpaceInvitationLink,
×
51
    onSuccess: () => {
×
52
      queryClient.invalidateQueries({ queryKey: ['invite-link-list'] });
×
53
    },
×
54
  });
×
55

×
56
  const copyInviteUrl = async (url: string) => {
×
57
    await navigator.clipboard.writeText(url);
×
58
    toast({ title: t('invite.dialog.linkCopySuccess') });
×
59
  };
×
60

×
61
  const spaceRoleStatic = useSpaceRoleStatic();
×
62
  const filterRoles = useMemo(
×
63
    () => map(getRolesWithLowerPermissions(role, spaceRoleStatic), 'role'),
×
64
    [role, spaceRoleStatic]
×
65
  );
×
66

×
67
  if (!linkList?.length) {
×
68
    return <></>;
×
69
  }
×
70

×
71
  return (
×
72
    <div>
×
73
      <div className="mb-3 text-sm text-muted-foreground">{t('invite.dialog.linkTitle')}</div>
×
74
      <div className="space-y-3">
×
75
        {linkList.map(({ invitationId, inviteUrl, createdTime, role }) => (
×
76
          <div key={invitationId} className="relative flex items-center gap-3 pr-7">
×
77
            <div className="flex flex-1 items-center gap-2">
×
78
              <Input className="h-8 flex-1" value={inviteUrl} readOnly />
×
79
              <Copy
×
80
                onClick={() => copyInviteUrl(inviteUrl)}
×
81
                className="size-4 cursor-pointer text-muted-foreground opacity-70 hover:opacity-100"
×
82
              />
×
83
            </div>
×
84
            <div className="text-xs text-muted-foreground">
×
85
              {t('invite.dialog.linkCreatedTime', { createdTime: dayjs(createdTime).fromNow() })}
×
86
            </div>
×
87
            <RoleSelect
×
88
              value={role}
×
89
              disabled={updateInviteLinkLoading}
×
90
              filterRoles={filterRoles}
×
91
              onChange={(role) =>
×
92
                updateInviteLink({ spaceId, invitationId, updateSpaceInvitationLinkRo: { role } })
×
93
              }
×
94
            />
×
95
            <TooltipProvider>
×
96
              <Tooltip>
×
97
                <TooltipTrigger asChild>
×
98
                  <Button
×
99
                    className="absolute right-0 h-auto p-0 hover:bg-inherit"
×
100
                    size="sm"
×
101
                    variant="ghost"
×
102
                    disabled={deleteInviteLinkLoading}
×
103
                    onClick={() => deleteInviteLink({ spaceId, invitationId })}
×
104
                  >
×
105
                    <X className="size-4 cursor-pointer text-muted-foreground opacity-70 hover:opacity-100" />
×
106
                  </Button>
×
107
                </TooltipTrigger>
×
108
                <TooltipContent>
×
109
                  <p>{t('invite.dialog.linkRemove')}</p>
×
110
                </TooltipContent>
×
111
              </Tooltip>
×
112
            </TooltipProvider>
×
113
          </div>
×
114
        ))}
×
115
      </div>
×
116
    </div>
×
117
  );
×
118
};
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc