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

teableio / teable / 8387437936

22 Mar 2024 08:21AM UTC coverage: 28.019% (-0.2%) from 28.222%
8387437936

Pull #484

github

web-flow
Merge dba36f5dd into a06c6afb1
Pull Request #484: feat: support increment import

2099 of 3218 branches covered (65.23%)

24 of 732 new or added lines in 18 files covered. (3.28%)

49 existing lines in 6 files now uncovered.

25815 of 92133 relevant lines covered (28.02%)

5.52 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-list/TableOperation.tsx
NEW
1
import { SUPPORTEDTYPE } from '@teable/core';
×
NEW
2
import {
×
NEW
3
  MoreHorizontal,
×
NEW
4
  Pencil,
×
NEW
5
  Settings,
×
NEW
6
  Trash2,
×
NEW
7
  Import,
×
NEW
8
  FileCsv,
×
NEW
9
  FileExcel,
×
NEW
10
} from '@teable/icons';
×
11
import { useBase, useTablePermission, useTables } from '@teable/sdk/hooks';
×
12
import type { Table } from '@teable/sdk/model';
×
13
import { ConfirmDialog } from '@teable/ui-lib/base';
×
14
import {
×
15
  DropdownMenu,
×
16
  DropdownMenuContent,
×
17
  DropdownMenuItem,
×
18
  DropdownMenuTrigger,
×
NEW
19
  DropdownMenuSub,
×
NEW
20
  DropdownMenuPortal,
×
NEW
21
  DropdownMenuSubContent,
×
NEW
22
  DropdownMenuSubTrigger,
×
23
} from '@teable/ui-lib/shadcn';
×
24
import Link from 'next/link';
×
25
import { useRouter } from 'next/router';
×
26
import { useTranslation } from 'next-i18next';
×
NEW
27
import React, { useMemo, useState } from 'react';
×
28
import { tableConfig } from '@/features/i18n/table.config';
×
NEW
29
import { TableImport } from '../import-table';
×
30

×
31
interface ITableOperationProps {
×
32
  className?: string;
×
33
  table: Table;
×
34
  onRename?: () => void;
×
35
}
×
36

×
37
export const TableOperation = (props: ITableOperationProps) => {
×
38
  const { table, className, onRename } = props;
×
NEW
39
  const [deleteConfirm, setDeleteConfirm] = useState(false);
×
NEW
40
  const [importVisible, setImportVisible] = useState(false);
×
NEW
41
  const [importType, setImportType] = useState(SUPPORTEDTYPE.CSV);
×
42
  const permission = useTablePermission();
×
43
  const base = useBase();
×
44
  const tables = useTables();
×
45
  const router = useRouter();
×
46
  const { baseId, tableId: routerTableId } = router.query;
×
47
  const { t } = useTranslation(tableConfig.i18nNamespaces);
×
48

×
49
  const menuPermission = useMemo(() => {
×
50
    return {
×
51
      deleteTable: permission['table|delete'],
×
52
    };
×
53
  }, [permission]);
×
54

×
55
  const deleteTable = async () => {
×
56
    const tableId = table?.id;
×
57
    if (!tableId) {
×
58
      return;
×
59
    }
×
60
    await base.deleteTable(tableId);
×
61
    const firstTableId = tables.find((t) => t.id !== tableId)?.id;
×
62
    if (routerTableId === tableId) {
×
63
      router.push(
×
64
        firstTableId
×
65
          ? {
×
66
              pathname: '/base/[baseId]/[tableId]',
×
67
              query: { baseId, tableId: firstTableId },
×
68
            }
×
69
          : {
×
70
              pathname: '/base/[baseId]',
×
71
              query: { baseId },
×
72
            }
×
73
      );
×
74
    }
×
75
  };
×
76

×
77
  if (!Object.values(menuPermission).some(Boolean)) {
×
78
    return null;
×
79
  }
×
80

×
81
  return (
×
82
    // eslint-disable-next-line jsx-a11y/no-static-element-interactions
×
83
    <div onMouseDown={(e) => e.stopPropagation()}>
×
84
      {menuPermission.deleteTable && (
×
85
        <DropdownMenu>
×
86
          <DropdownMenuTrigger asChild>
×
87
            <div>
×
88
              <MoreHorizontal className={className} />
×
89
            </div>
×
90
          </DropdownMenuTrigger>
×
91
          <DropdownMenuContent
×
92
            align="end"
×
93
            className="min-w-[160px]"
×
94
            onClick={(e) => e.stopPropagation()}
×
95
          >
×
96
            <DropdownMenuItem onClick={() => onRename?.()}>
×
97
              <Pencil className="mr-2" />
×
98
              {t('table:table.rename')}
×
99
            </DropdownMenuItem>
×
100
            <DropdownMenuItem asChild>
×
101
              <Link
×
102
                href={{
×
103
                  pathname: '/base/[baseId]/[tableId]/design',
×
104
                  query: { baseId, tableId: table.id },
×
105
                }}
×
106
                title={t('table:table.design')}
×
107
              >
×
108
                <Settings className="mr-2" />
×
109
                {t('table:table.design')}
×
110
              </Link>
×
111
            </DropdownMenuItem>
×
NEW
112
            <DropdownMenuSub>
×
NEW
113
              <DropdownMenuSubTrigger>
×
NEW
114
                <Import className="mr-2" />
×
NEW
115
                <span>{t('table:import.menu.importData')}</span>
×
NEW
116
              </DropdownMenuSubTrigger>
×
NEW
117
              <DropdownMenuPortal>
×
NEW
118
                <DropdownMenuSubContent>
×
NEW
119
                  <DropdownMenuItem
×
NEW
120
                    onClick={() => {
×
NEW
121
                      setImportVisible(true);
×
NEW
122
                      setImportType(SUPPORTEDTYPE.CSV);
×
NEW
123
                    }}
×
NEW
124
                  >
×
NEW
125
                    <FileCsv className="mr-2 size-4" />
×
NEW
126
                    <span>{t('table:import.menu.csvFile')}</span>
×
NEW
127
                  </DropdownMenuItem>
×
NEW
128
                  <DropdownMenuItem
×
NEW
129
                    onClick={() => {
×
NEW
130
                      setImportVisible(true);
×
NEW
131
                      setImportType(SUPPORTEDTYPE.EXCEL);
×
NEW
132
                    }}
×
NEW
133
                  >
×
NEW
134
                    <FileExcel className="mr-2 size-4" />
×
NEW
135
                    <span>{t('table:import.menu.excelFile')}</span>
×
NEW
136
                  </DropdownMenuItem>
×
NEW
137
                </DropdownMenuSubContent>
×
NEW
138
              </DropdownMenuPortal>
×
NEW
139
            </DropdownMenuSub>
×
140
            <DropdownMenuItem className="text-destructive" onClick={() => setDeleteConfirm(true)}>
×
141
              <Trash2 className="mr-2" />
×
142
              {t('common:actions.delete')}
×
143
            </DropdownMenuItem>
×
144
          </DropdownMenuContent>
×
145
        </DropdownMenu>
×
146
      )}
×
NEW
147

×
NEW
148
      {importVisible && (
×
NEW
149
        <TableImport
×
NEW
150
          open={importVisible}
×
NEW
151
          tableId={table.id}
×
NEW
152
          fileType={importType}
×
NEW
153
          onOpenChange={(open: boolean) => setImportVisible(open)}
×
NEW
154
        ></TableImport>
×
NEW
155
      )}
×
NEW
156

×
157
      <ConfirmDialog
×
158
        open={deleteConfirm}
×
159
        onOpenChange={setDeleteConfirm}
×
160
        title={t('table:table.deleteConfirm', { tableName: table?.name })}
×
161
        cancelText={t('common:actions.cancel')}
×
162
        confirmText={t('common:actions.confirm')}
×
163
        content={
×
164
          <div className="space-y-2 text-sm">
×
165
            <p>1. {t('table:table.deleteTip1')}</p>
×
166
            <p>2. {t('table:table.deleteTip2')}</p>
×
167
          </div>
×
168
        }
×
169
        onCancel={() => setDeleteConfirm(false)}
×
170
        onConfirm={deleteTable}
×
171
      />
×
172
    </div>
×
173
  );
×
174
};
×
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