mirror of
https://github.com/chartdb/chartdb.git
synced 2026-02-14 07:28:53 -06:00
feat(duplicate table): duplicate table from the canvas and sidebar (#404)
* feat(duplicate table): duplicate table from the canvas and sidebar * feat(duplicate table): underscore instead of space * feat(duplicate table): underscore instead of space
This commit is contained in:
@@ -145,6 +145,7 @@ export const de: LanguageTranslation = {
|
||||
change_schema: 'Schema ändern',
|
||||
add_field: 'Feld hinzufügen',
|
||||
add_index: 'Index hinzufügen',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Tabelle löschen',
|
||||
},
|
||||
},
|
||||
@@ -371,6 +372,7 @@ export const de: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'Tabelle bearbeiten',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Tabelle löschen',
|
||||
},
|
||||
|
||||
|
||||
@@ -144,6 +144,7 @@ export const en = {
|
||||
change_schema: 'Change Schema',
|
||||
add_field: 'Add Field',
|
||||
add_index: 'Add Index',
|
||||
duplicate_table: 'Duplicate Table',
|
||||
delete_table: 'Delete Table',
|
||||
},
|
||||
},
|
||||
@@ -367,6 +368,7 @@ export const en = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'Edit Table',
|
||||
duplicate_table: 'Duplicate Table',
|
||||
delete_table: 'Delete Table',
|
||||
},
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ export const es: LanguageTranslation = {
|
||||
change_schema: 'Cambiar Esquema',
|
||||
add_field: 'Agregar Campo',
|
||||
add_index: 'Agregar Índice',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Eliminar Tabla',
|
||||
},
|
||||
},
|
||||
@@ -371,6 +372,7 @@ export const es: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'Editar Tabla',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Eliminar Tabla',
|
||||
},
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ export const fr: LanguageTranslation = {
|
||||
title: 'Actions de la Table',
|
||||
add_field: 'Ajouter un Champ',
|
||||
add_index: 'Ajouter un Index',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Supprimer la Table',
|
||||
change_schema: 'Changer le Schéma',
|
||||
},
|
||||
@@ -373,6 +374,7 @@ export const fr: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'Éditer la Table',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Supprimer la Table',
|
||||
},
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ export const hi: LanguageTranslation = {
|
||||
change_schema: 'स्कीमा बदलें',
|
||||
add_field: 'फ़ील्ड जोड़ें',
|
||||
add_index: 'सूचकांक जोड़ें',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'तालिका हटाएँ',
|
||||
},
|
||||
},
|
||||
@@ -373,6 +374,7 @@ export const hi: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'तालिका संपादित करें',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'तालिका हटाएँ',
|
||||
},
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ export const ja: LanguageTranslation = {
|
||||
change_schema: 'スキーマを変更',
|
||||
add_field: 'フィールドを追加',
|
||||
add_index: 'インデックスを追加',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'テーブルを削除',
|
||||
},
|
||||
},
|
||||
@@ -375,6 +376,7 @@ export const ja: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'テーブルを編集',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'テーブルを削除',
|
||||
},
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ export const ko_KR: LanguageTranslation = {
|
||||
change_schema: '스키마 변경',
|
||||
add_field: '필드 추가',
|
||||
add_index: '인덱스 추가',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: '테이블 삭제',
|
||||
},
|
||||
},
|
||||
@@ -369,6 +370,7 @@ export const ko_KR: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: '테이블 수정',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: '테이블 삭제',
|
||||
},
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ export const pt_BR: LanguageTranslation = {
|
||||
change_schema: 'Alterar Esquema',
|
||||
add_field: 'Adicionar Campo',
|
||||
add_index: 'Adicionar Índice',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Excluir Tabela',
|
||||
},
|
||||
},
|
||||
@@ -370,6 +371,7 @@ export const pt_BR: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'Editar Tabela',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Excluir Tabela',
|
||||
},
|
||||
|
||||
|
||||
@@ -142,6 +142,7 @@ export const ru: LanguageTranslation = {
|
||||
change_schema: 'Изменить схему',
|
||||
add_field: 'Добавить поле',
|
||||
add_index: 'Добавить индекс',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Удалить таблицу',
|
||||
},
|
||||
},
|
||||
@@ -365,6 +366,7 @@ export const ru: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'Изменить таблицу',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Удалить таблицу',
|
||||
},
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ export const uk: LanguageTranslation = {
|
||||
change_schema: 'Змінити схему',
|
||||
add_field: 'Додати поле',
|
||||
add_index: 'Додати індекс',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Видалити таблицю',
|
||||
},
|
||||
},
|
||||
@@ -370,6 +371,7 @@ export const uk: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: 'Редагувати таблицю',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: 'Видалити таблицю',
|
||||
},
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ export const zh_CN: LanguageTranslation = {
|
||||
change_schema: '更改模式',
|
||||
add_field: '添加字段',
|
||||
add_index: '添加索引',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: '删除表',
|
||||
},
|
||||
},
|
||||
@@ -361,6 +362,7 @@ export const zh_CN: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: '编辑表',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: '删除表',
|
||||
},
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ export const zh_TW: LanguageTranslation = {
|
||||
change_schema: '變更 Schema',
|
||||
add_field: '新增欄位',
|
||||
add_index: '新增索引',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: '刪除表格',
|
||||
},
|
||||
},
|
||||
@@ -360,6 +361,7 @@ export const zh_TW: LanguageTranslation = {
|
||||
|
||||
table_node_context_menu: {
|
||||
edit_table: '編輯表格',
|
||||
duplicate_table: 'Duplicate Table', // TODO: Translate
|
||||
delete_table: '刪除表格',
|
||||
},
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ import {
|
||||
import { useBreakpoint } from '@/hooks/use-breakpoint';
|
||||
import { useChartDB } from '@/hooks/use-chartdb';
|
||||
import { useLayout } from '@/hooks/use-layout';
|
||||
import { cloneTable } from '@/lib/clone';
|
||||
import type { DBTable } from '@/lib/domain/db-table';
|
||||
import { Copy, Pencil, Trash2 } from 'lucide-react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -18,11 +20,21 @@ export interface TableNodeContextMenuProps {
|
||||
export const TableNodeContextMenu: React.FC<
|
||||
React.PropsWithChildren<TableNodeContextMenuProps>
|
||||
> = ({ children, table }) => {
|
||||
const { removeTable, readonly } = useChartDB();
|
||||
const { removeTable, readonly, createTable } = useChartDB();
|
||||
const { openTableFromSidebar } = useLayout();
|
||||
const { t } = useTranslation();
|
||||
const { isMd: isDesktop } = useBreakpoint('md');
|
||||
|
||||
const duplicateTableHandler = useCallback(() => {
|
||||
const clonedTable = cloneTable(table);
|
||||
|
||||
clonedTable.name = `${clonedTable.name}_copy`;
|
||||
clonedTable.x += 30;
|
||||
clonedTable.y += 50;
|
||||
|
||||
createTable(clonedTable);
|
||||
}, [createTable, table]);
|
||||
|
||||
const editTableHandler = useCallback(() => {
|
||||
openTableFromSidebar(table.id);
|
||||
}, [openTableFromSidebar, table.id]);
|
||||
@@ -38,11 +50,26 @@ export const TableNodeContextMenu: React.FC<
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger>{children}</ContextMenuTrigger>
|
||||
<ContextMenuContent>
|
||||
<ContextMenuItem onClick={editTableHandler}>
|
||||
{t('table_node_context_menu.edit_table')}
|
||||
<ContextMenuItem
|
||||
onClick={editTableHandler}
|
||||
className="flex justify-between gap-3"
|
||||
>
|
||||
<span>{t('table_node_context_menu.edit_table')}</span>
|
||||
<Pencil className="size-3.5" />
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem onClick={removeTableHandler}>
|
||||
{t('table_node_context_menu.delete_table')}
|
||||
<ContextMenuItem
|
||||
onClick={duplicateTableHandler}
|
||||
className="flex justify-between gap-3"
|
||||
>
|
||||
<span>{t('table_node_context_menu.duplicate_table')}</span>
|
||||
<Copy className="size-3.5" />
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
onClick={removeTableHandler}
|
||||
className="flex justify-between gap-3"
|
||||
>
|
||||
<span>{t('table_node_context_menu.delete_table')}</span>
|
||||
<Trash2 className="size-3.5 text-red-700" />
|
||||
</ContextMenuItem>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
FileKey2,
|
||||
Check,
|
||||
Group,
|
||||
Copy,
|
||||
} from 'lucide-react';
|
||||
import { ListItemHeaderButton } from '@/pages/editor-page/side-panel/list-item-header-button/list-item-header-button';
|
||||
import type { DBTable } from '@/lib/domain/db-table';
|
||||
@@ -33,6 +34,7 @@ import {
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@/components/tooltip/tooltip';
|
||||
import { cloneTable } from '@/lib/clone';
|
||||
|
||||
export interface TableListItemHeaderProps {
|
||||
table: DBTable;
|
||||
@@ -46,6 +48,7 @@ export const TableListItemHeader: React.FC<TableListItemHeaderProps> = ({
|
||||
removeTable,
|
||||
createIndex,
|
||||
createField,
|
||||
createTable,
|
||||
schemas,
|
||||
filteredSchemas,
|
||||
} = useChartDB();
|
||||
@@ -128,6 +131,20 @@ export const TableListItemHeader: React.FC<TableListItemHeaderProps> = ({
|
||||
});
|
||||
}, [openTableSchemaDialog, table, schemas, updateTableSchema]);
|
||||
|
||||
const duplicateTableHandler = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
||||
e.stopPropagation();
|
||||
const clonedTable = cloneTable(table);
|
||||
|
||||
clonedTable.name = `${clonedTable.name}_copy`;
|
||||
clonedTable.x += 30;
|
||||
clonedTable.y += 50;
|
||||
|
||||
createTable(clonedTable);
|
||||
},
|
||||
[createTable, table]
|
||||
);
|
||||
|
||||
const renderDropDownMenu = useCallback(
|
||||
() => (
|
||||
<DropdownMenu>
|
||||
@@ -189,6 +206,18 @@ export const TableListItemHeader: React.FC<TableListItemHeaderProps> = ({
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
onClick={duplicateTableHandler}
|
||||
className="flex justify-between"
|
||||
>
|
||||
{t(
|
||||
'side_panel.tables_section.table.table_actions.duplicate_table'
|
||||
)}
|
||||
<Copy className="size-3.5" />
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
onClick={deleteTableHandler}
|
||||
@@ -208,6 +237,7 @@ export const TableListItemHeader: React.FC<TableListItemHeaderProps> = ({
|
||||
createField,
|
||||
createIndex,
|
||||
deleteTableHandler,
|
||||
duplicateTableHandler,
|
||||
t,
|
||||
changeSchema,
|
||||
schemas.length,
|
||||
|
||||
Reference in New Issue
Block a user