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

teableio / teable / 10280217705

07 Aug 2024 07:43AM UTC coverage: 17.548% (-0.2%) from 17.734%
10280217705

Pull #793

github

web-flow
Merge 1d187fdaf into 6131ee284
Pull Request #793: feat: record history

1387 of 2823 branches covered (49.13%)

6 of 1033 new or added lines in 43 files covered. (0.58%)

34 existing lines in 5 files now uncovered.

14088 of 80281 relevant lines covered (17.55%)

1.74 hits per line

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

0.0
/apps/nextjs-app/src/features/app/blocks/table/table-header/TableHeader.tsx
NEW
1
import { HelpCircle, History, MoreHorizontal, Settings, UserPlus } from '@teable/icons';
×
NEW
2
import { RecordHistory } from '@teable/sdk/components/expand-record/RecordHistory';
×
NEW
3
import { useBase, useBasePermission, useTableId } from '@teable/sdk/hooks';
×
NEW
4
import {
×
NEW
5
  Button,
×
NEW
6
  cn,
×
NEW
7
  Dialog,
×
NEW
8
  DialogContent,
×
NEW
9
  DialogHeader,
×
NEW
10
  DialogTitle,
×
NEW
11
  DialogTrigger,
×
NEW
12
  Popover,
×
NEW
13
  PopoverContent,
×
NEW
14
  PopoverTrigger,
×
NEW
15
  Sheet,
×
NEW
16
  SheetContent,
×
NEW
17
  SheetHeader,
×
NEW
18
  SheetTrigger,
×
NEW
19
} from '@teable/ui-lib/shadcn';
×
20
import Link from 'next/link';
×
NEW
21
import { useRouter } from 'next/router';
×
22
import { useTranslation } from 'next-i18next';
×
23
import { SpaceCollaboratorModalTrigger } from '@/features/app/components/collaborator-manage/space/SpaceCollaboratorModalTrigger';
×
24
import { tableConfig } from '@/features/i18n/table.config';
×
25
import { ExpandViewList } from '../../view/list/ExpandViewList';
×
26
import { ViewList } from '../../view/list/ViewList';
×
27

×
28
import { AddView } from './AddView';
×
29
import { Collaborators } from './Collaborators';
×
30
import { TableInfo } from './TableInfo';
×
31

×
32
const RightList = ({
×
33
  className,
×
34
  buttonClassName,
×
35
}: {
×
36
  className?: string;
×
37
  buttonClassName?: string;
×
38
}) => {
×
NEW
39
  const router = useRouter();
×
40
  const base = useBase();
×
41
  const tableId = useTableId();
×
42
  const { t } = useTranslation(tableConfig.i18nNamespaces);
×
NEW
43
  const basePermission = useBasePermission();
×
NEW
44

×
NEW
45
  const onRecordClick = (recordId: string) => {
×
NEW
46
    router.push(
×
NEW
47
      {
×
NEW
48
        pathname: router.pathname,
×
NEW
49
        query: { ...router.query, recordId },
×
NEW
50
      },
×
NEW
51
      undefined,
×
NEW
52
      {
×
NEW
53
        shallow: true,
×
NEW
54
      }
×
NEW
55
    );
×
NEW
56
  };
×
NEW
57

×
58
  return (
×
59
    <div className={cn('flex', className)}>
×
60
      <Collaborators className="flex" />
×
61
      <div className="flex">
×
NEW
62
        {basePermission?.['record_history|read'] && (
×
NEW
63
          <Dialog>
×
NEW
64
            <DialogTrigger asChild>
×
NEW
65
              <Button
×
NEW
66
                variant="ghost"
×
NEW
67
                size="xs"
×
NEW
68
                className={cn('flex', buttonClassName)}
×
NEW
69
                title={t('table:table.tableRecordHistory')}
×
NEW
70
              >
×
NEW
71
                <History className="size-4" />
×
NEW
72
              </Button>
×
NEW
73
            </DialogTrigger>
×
NEW
74
            <DialogContent className="flex h-[90%] max-w-4xl flex-col gap-0 p-0">
×
NEW
75
              <DialogHeader className="border-b p-4">
×
NEW
76
                <DialogTitle>{t('table:table.tableRecordHistory')}</DialogTitle>
×
NEW
77
              </DialogHeader>
×
NEW
78
              <RecordHistory onRecordClick={onRecordClick} />
×
NEW
79
            </DialogContent>
×
NEW
80
          </Dialog>
×
NEW
81
        )}
×
NEW
82

×
83
        <Button asChild variant="ghost" size="xs" className={cn('flex', buttonClassName)}>
×
84
          <Link
×
85
            href={{
×
86
              pathname: '/base/[baseId]/[tableId]/design',
×
87
              query: { baseId: base.id, tableId },
×
88
            }}
×
NEW
89
            title={t('table:table.design')}
×
90
          >
×
91
            <Settings className="size-4" />
×
92
          </Link>
×
93
        </Button>
×
94
        <Button asChild variant="ghost" size="xs" className={cn('flex', buttonClassName)}>
×
95
          <a href={t('help.mainLink')} title={t('help.title')} target="_blank" rel="noreferrer">
×
96
            <HelpCircle className="size-4" />
×
97
          </a>
×
98
        </Button>
×
99
      </div>
×
100
      <SpaceCollaboratorModalTrigger
×
101
        space={{
×
102
          name: base.name,
×
103
          role: base.role,
×
104
          id: base.spaceId,
×
105
        }}
×
106
      >
×
107
        <Button variant="default" size="xs" className="flex">
×
108
          <UserPlus className="size-4" />{' '}
×
109
          <span className="hidden @md/view-header:inline">{t('space:action.invite')}</span>
×
110
        </Button>
×
111
      </SpaceCollaboratorModalTrigger>
×
112
    </div>
×
113
  );
×
114
};
×
115

×
116
const RightMenu = ({ className }: { className?: string }) => {
×
NEW
117
  const router = useRouter();
×
118
  const base = useBase();
×
119
  const tableId = useTableId();
×
NEW
120
  const basePermission = useBasePermission();
×
121
  const { t } = useTranslation(tableConfig.i18nNamespaces);
×
NEW
122

×
NEW
123
  // eslint-disable-next-line sonarjs/no-identical-functions
×
NEW
124
  const onRecordClick = (recordId: string) => {
×
NEW
125
    router.push(
×
NEW
126
      {
×
NEW
127
        pathname: router.pathname,
×
NEW
128
        query: { ...router.query, recordId },
×
NEW
129
      },
×
NEW
130
      undefined,
×
NEW
131
      {
×
NEW
132
        shallow: true,
×
NEW
133
      }
×
NEW
134
    );
×
NEW
135
  };
×
NEW
136

×
137
  return (
×
138
    <Popover>
×
139
      <PopoverTrigger asChild>
×
140
        <Button
×
141
          variant={'ghost'}
×
142
          size={'xs'}
×
143
          className={cn('font-normal shrink-0 truncate', className)}
×
144
        >
×
145
          <MoreHorizontal className="size-4" />
×
146
        </Button>
×
147
      </PopoverTrigger>
×
148
      <PopoverContent side="bottom" align="start" className="w-32 p-0">
×
149
        <div className="flex flex-col">
×
150
          <Collaborators className="flex p-2" />
×
151
          <SpaceCollaboratorModalTrigger
×
152
            space={{
×
153
              name: base.name,
×
154
              role: base.role,
×
155
              id: base.spaceId,
×
156
            }}
×
157
          >
×
158
            <Button variant="ghost" size="xs" className="flex justify-start">
×
159
              <UserPlus className="size-4" /> {t('space:action.invite')}
×
160
            </Button>
×
161
          </SpaceCollaboratorModalTrigger>
×
NEW
162
          {basePermission?.['record_history|read'] && (
×
NEW
163
            <Sheet modal={true}>
×
NEW
164
              <SheetTrigger asChild>
×
NEW
165
                <Button size="xs" variant="ghost" className="flex justify-start">
×
NEW
166
                  <History className="size-4" />
×
NEW
167
                  {t('table:table.tableRecordHistory')}
×
NEW
168
                </Button>
×
NEW
169
              </SheetTrigger>
×
NEW
170
              <SheetContent
×
NEW
171
                className="h-5/6 overflow-hidden rounded-t-lg p-0"
×
NEW
172
                side="bottom"
×
NEW
173
                closeable={false}
×
NEW
174
              >
×
NEW
175
                <SheetHeader className="h-16 justify-center border-b text-2xl">
×
NEW
176
                  {t('table:table.tableRecordHistory')}
×
NEW
177
                </SheetHeader>
×
NEW
178
                <RecordHistory onRecordClick={onRecordClick} />
×
NEW
179
              </SheetContent>
×
NEW
180
            </Sheet>
×
NEW
181
          )}
×
182
          <Button asChild variant="ghost" size="xs" className="flex justify-start">
×
183
            <Link
×
184
              href={{
×
185
                pathname: '/base/[baseId]/[tableId]/design',
×
186
                query: { baseId: base.id, tableId },
×
187
              }}
×
188
              title={t('table:table.design')}
×
189
            >
×
190
              <Settings className="size-4" /> {t('table:table.design')}
×
191
            </Link>
×
192
          </Button>
×
193
          <Button asChild variant="ghost" size="xs" className="flex justify-start">
×
194
            <a href={t('help.mainLink')} title={t('help.title')} target="_blank" rel="noreferrer">
×
195
              <HelpCircle className="size-4" /> {t('help.title')}
×
196
            </a>
×
197
          </Button>
×
198
        </div>
×
199
      </PopoverContent>
×
200
    </Popover>
×
201
  );
×
202
};
×
203

×
204
export const TableHeader: React.FC = () => {
×
205
  return (
×
206
    <div className="z-10 flex h-[42px] shrink-0 flex-row items-center gap-2 px-4 @container/view-header">
×
207
      <TableInfo className="shrink-0 grow-0" />
×
208
      <ExpandViewList />
×
209
      <div className="flex h-full items-center gap-2 overflow-x-auto">
×
210
        <ViewList />
×
211
      </div>
×
212
      <AddView />
×
213
      <div className="grow basis-0"></div>
×
214
      <RightList className="hidden gap-2 @sm/view-header:flex" />
×
215
      <RightMenu className="flex @sm/view-header:hidden" />
×
216
    </div>
×
217
  );
×
218
};
×
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