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

teableio / teable / 8432338670

26 Mar 2024 07:31AM UTC coverage: 26.059% (-0.05%) from 26.106%
8432338670

Pull #493

github

web-flow
Merge 5e65977dd into 98543ea09
Pull Request #493: feat: export csv

2106 of 3377 branches covered (62.36%)

9 of 220 new or added lines in 12 files covered. (4.09%)

1 existing line in 1 file now uncovered.

25609 of 98275 relevant lines covered (26.06%)

5.16 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 { MoreHorizontal, Pencil, Settings, Trash2, Export } from '@teable/icons';
×
2
import { useBase, useTablePermission, useTables } from '@teable/sdk/hooks';
×
3
import type { Table } from '@teable/sdk/model';
×
4
import { ConfirmDialog } from '@teable/ui-lib/base';
×
5
import {
×
6
  DropdownMenu,
×
7
  DropdownMenuContent,
×
8
  DropdownMenuItem,
×
9
  DropdownMenuTrigger,
×
10
} from '@teable/ui-lib/shadcn';
×
11
import Link from 'next/link';
×
12
import { useRouter } from 'next/router';
×
13
import { useTranslation } from 'next-i18next';
×
NEW
14
import React, { useRef, useMemo } from 'react';
×
15
import { tableConfig } from '@/features/i18n/table.config';
×
16
interface ITableOperationProps {
×
17
  className?: string;
×
18
  table: Table;
×
19
  onRename?: () => void;
×
20
}
×
21

×
22
export const TableOperation = (props: ITableOperationProps) => {
×
23
  const { table, className, onRename } = props;
×
24
  const [deleteConfirm, setDeleteConfirm] = React.useState(false);
×
25
  const permission = useTablePermission();
×
26
  const base = useBase();
×
27
  const tables = useTables();
×
28
  const router = useRouter();
×
29
  const { baseId, tableId: routerTableId } = router.query;
×
30
  const { t } = useTranslation(tableConfig.i18nNamespaces);
×
NEW
31
  const iframeRef = useRef<HTMLIFrameElement>(null);
×
32

×
33
  const menuPermission = useMemo(() => {
×
34
    return {
×
35
      deleteTable: permission['table|delete'],
×
36
    };
×
37
  }, [permission]);
×
38

×
39
  const deleteTable = async () => {
×
40
    const tableId = table?.id;
×
41
    if (!tableId) {
×
42
      return;
×
43
    }
×
44
    await base.deleteTable(tableId);
×
45
    const firstTableId = tables.find((t) => t.id !== tableId)?.id;
×
46
    if (routerTableId === tableId) {
×
47
      router.push(
×
48
        firstTableId
×
49
          ? {
×
50
              pathname: '/base/[baseId]/[tableId]',
×
51
              query: { baseId, tableId: firstTableId },
×
52
            }
×
53
          : {
×
54
              pathname: '/base/[baseId]',
×
55
              query: { baseId },
×
56
            }
×
57
      );
×
58
    }
×
59
  };
×
60

×
61
  if (!Object.values(menuPermission).some(Boolean)) {
×
62
    return null;
×
63
  }
×
64

×
65
  return (
×
66
    // eslint-disable-next-line jsx-a11y/no-static-element-interactions
×
67
    <div onMouseDown={(e) => e.stopPropagation()}>
×
68
      {menuPermission.deleteTable && (
×
69
        <DropdownMenu>
×
70
          <DropdownMenuTrigger asChild>
×
71
            <div>
×
72
              <MoreHorizontal className={className} />
×
73
            </div>
×
74
          </DropdownMenuTrigger>
×
75
          <DropdownMenuContent
×
76
            align="end"
×
77
            className="min-w-[160px]"
×
78
            onClick={(e) => e.stopPropagation()}
×
79
          >
×
80
            <DropdownMenuItem onClick={() => onRename?.()}>
×
81
              <Pencil className="mr-2" />
×
82
              {t('table:table.rename')}
×
83
            </DropdownMenuItem>
×
84
            <DropdownMenuItem asChild>
×
85
              <Link
×
86
                href={{
×
87
                  pathname: '/base/[baseId]/[tableId]/design',
×
88
                  query: { baseId, tableId: table.id },
×
89
                }}
×
90
                title={t('table:table.design')}
×
91
              >
×
92
                <Settings className="mr-2" />
×
93
                {t('table:table.design')}
×
94
              </Link>
×
95
            </DropdownMenuItem>
×
NEW
96
            <DropdownMenuItem
×
NEW
97
              onClick={() => {
×
NEW
98
                if (iframeRef.current) {
×
NEW
99
                  iframeRef.current.src = `/api/export/${table.id}`;
×
NEW
100
                }
×
NEW
101
              }}
×
NEW
102
            >
×
NEW
103
              <Export className="mr-2" />
×
NEW
104
              {t('table:import.menu.downAsCsv')}
×
NEW
105
            </DropdownMenuItem>
×
106
            <DropdownMenuItem className="text-destructive" onClick={() => setDeleteConfirm(true)}>
×
107
              <Trash2 className="mr-2" />
×
108
              {t('common:actions.delete')}
×
109
            </DropdownMenuItem>
×
110
          </DropdownMenuContent>
×
111
        </DropdownMenu>
×
112
      )}
×
113
      <ConfirmDialog
×
114
        open={deleteConfirm}
×
115
        onOpenChange={setDeleteConfirm}
×
116
        title={t('table:table.deleteConfirm', { tableName: table?.name })}
×
117
        cancelText={t('common:actions.cancel')}
×
118
        confirmText={t('common:actions.confirm')}
×
119
        content={
×
120
          <div className="space-y-2 text-sm">
×
121
            <p>1. {t('table:table.deleteTip1')}</p>
×
122
            <p>2. {t('table:table.deleteTip2')}</p>
×
123
          </div>
×
124
        }
×
125
        onCancel={() => setDeleteConfirm(false)}
×
126
        onConfirm={deleteTable}
×
127
      />
×
NEW
128
      <iframe ref={iframeRef} title="This for export csv download" style={{ display: 'none' }} />
×
129
    </div>
×
130
  );
×
131
};
×
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