Merge pull request #744 from Hexastack/feat/duplicate-block-2

feat: duplicate a block 2
This commit is contained in:
Med Marrouchi 2025-02-19 10:47:16 +01:00 committed by GitHub
commit 515139d3bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 57 additions and 4 deletions

View File

@ -113,7 +113,8 @@
"invalid_file_type": "Invalid file type. Please select a file in the supported format.",
"select_category": "Select a flow",
"logout_failed": "Something went wrong during logout",
"duplicate_labels_not_allowed": "Duplicate labels are not allowed"
"duplicate_labels_not_allowed": "Duplicate labels are not allowed",
"duplicate_block_error": "Something went wrong while duplicating block"
},
"menu": {
"terms": "Terms of Use",

View File

@ -113,7 +113,8 @@
"invalid_file_type": "Type de fichier invalide. Veuillez choisir un fichier dans un format pris en charge.",
"select_category": "Sélectionner une catégorie",
"logout_failed": "Une erreur s'est produite lors de la déconnexion",
"duplicate_labels_not_allowed": "Les étiquettes en double ne sont pas autorisées"
"duplicate_labels_not_allowed": "Les étiquettes en double ne sont pas autorisées",
"duplicate_block_error": "Une erreur est survenue lors de la duplication du bloc"
},
"menu": {
"terms": "Conditions d'utilisation",

View File

@ -1,12 +1,12 @@
/*
* Copyright © 2024 Hexastack. All rights reserved.
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { Add, MoveUp } from "@mui/icons-material";
import { Add, ContentCopyRounded, MoveUp } from "@mui/icons-material";
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import FitScreenIcon from "@mui/icons-material/FitScreen";
@ -37,6 +37,7 @@ import { ConfirmDialogBody } from "@/app-components/dialogs";
import { CategoryFormDialog } from "@/components/categories/CategoryFormDialog";
import { BlockMoveFormDialog } from "@/components/visual-editor/BlockMoveFormDialog";
import { isSameEntity } from "@/hooks/crud/helpers";
import { useCreate } from "@/hooks/crud/useCreate";
import { useDeleteFromCache } from "@/hooks/crud/useDelete";
import { useDeleteMany } from "@/hooks/crud/useDeleteMany";
import { useFind } from "@/hooks/crud/useFind";
@ -46,6 +47,7 @@ import { useUpdateMany } from "@/hooks/crud/useUpdateMany";
import useDebouncedUpdate from "@/hooks/useDebouncedUpdate";
import { useDialogs } from "@/hooks/useDialogs";
import { useSearch } from "@/hooks/useSearch";
import { useToast } from "@/hooks/useToast";
import { useTranslate } from "@/hooks/useTranslate";
import { EntityType, Format, QueryType, RouterType } from "@/services/types";
import { IBlock } from "@/types/block.types";
@ -80,6 +82,15 @@ const Diagrams = () => {
const { searchPayload } = useSearch<IBlock>({
$eq: [{ category: selectedCategoryId }],
});
const { toast } = useToast();
const { mutate: duplicateBlock, isLoading: isDuplicatingBlock } = useCreate(
EntityType.BLOCK,
{
onError: () => {
toast.error(t("message.duplicate_block_error"));
},
},
);
const { data: categories } = useFind(
{ entity: EntityType.CATEGORY },
{
@ -172,6 +183,32 @@ const Diagrams = () => {
enabled: !!selectedCategoryId,
},
);
const handleDuplicateBlock = () => {
const block = getBlockFromCache(selectedEntities[0]);
if (!block) {
return;
}
const {
attachedBlock: _attachedBlock,
nextBlocks: _nextBlocks,
previousBlocks: _previousBlocks,
id: _id,
createdAt: _createdAt,
updatedAt: _updatedAt,
position,
...duplicateBlockDto
} = block;
duplicateBlock({
...duplicateBlockDto,
name: `${block.name} (Copy)`,
position: {
x: position.x + 100,
y: position.y + 100,
},
});
};
useEffect(() => {
// Case when categories are already cached
@ -513,6 +550,11 @@ const Diagrams = () => {
);
}
};
const selectedEntities = getSelectedIds();
const shouldDisableDuplicateButton =
selectedEntities.length !== 1 ||
selectedEntities[0]?.length !== 24 ||
isDuplicatingBlock;
return (
<div
@ -672,6 +714,15 @@ const Diagrams = () => {
>
{t("button.move")}
</Button>
<Button
size="small"
variant="contained"
startIcon={<ContentCopyRounded />}
onClick={handleDuplicateBlock}
disabled={shouldDisableDuplicateButton}
>
{t("button.duplicate")}
</Button>
<Button
sx={{}}
size="small"