Skip to content

Commit

Permalink
Merge pull request #342 from aXenDeveloper/files_delete
Browse files Browse the repository at this point in the history
feat(editor): Add delete files form editor
  • Loading branch information
aXenDeveloper authored May 9, 2024
2 parents 0e5872d + 3aa1841 commit d53604b
Show file tree
Hide file tree
Showing 6 changed files with 323 additions and 229 deletions.
13 changes: 11 additions & 2 deletions frontend/components/editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const Editor = ({
onChange,
value
}: WithLanguage | WithoutLanguage) => {
const { files, uploadFiles } = useUploadFilesHandlerEditor({
const { files, setFiles, uploadFiles } = useUploadFilesHandlerEditor({
value,
allowUploadFiles
});
Expand Down Expand Up @@ -129,7 +129,16 @@ export const Editor = ({

return (
<EditorStateContext.Provider
value={{ files, editor, uploadFiles, allowUploadFiles }}
value={{
files,
editor,
uploadFiles,
allowUploadFiles,
value,
onChange: onChange as (value: TextLanguage[] | string) => void,
selectedLanguage,
setFiles
}}
>
<div
className={cn("border border-input rounded-md shadow-sm", className)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,5 @@ export const useUploadFilesHandlerEditor = ({
);
};

return { uploadFiles, files };
return { uploadFiles, files, setFiles };
};
91 changes: 63 additions & 28 deletions frontend/components/editor/footer/files/item/item.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Plus, Trash2 } from "lucide-react";
import { useTranslations } from "next-intl";
import { toast } from "sonner";
import { findChildren } from "@tiptap/react";
import type { Node } from "@tiptap/pm/model";
import { type JSONContent } from "@tiptap/react";

import { Button } from "@/components/ui/button";
import { cn } from "@/functions/classnames";
Expand All @@ -12,6 +11,7 @@ import { deleteMutationApi } from "./hooks/delete-mutation-api";
import { CONFIG } from "@/config/config";
import type { FileStateEditor } from "@/components/editor/extensions/files/files";
import { useEditorState } from "@/components/editor/hooks/use-editor-state";
import type { TextLanguage } from "@/graphql/hooks";

export interface ItemListFilesFooterEditorProps
extends Omit<FileStateEditor, "file"> {
Expand All @@ -27,7 +27,39 @@ export const ItemListFilesFooterEditor = ({
}: ItemListFilesFooterEditorProps) => {
const t = useTranslations("core.editor.files");
const tCore = useTranslations("core");
const { editor } = useEditorState();
const { editor, onChange, selectedLanguage, setFiles, value } =
useEditorState();

const handleDelete = ({
content,
file_id
}: {
content: string;
file_id: number;
}): string => {
const parseValue: { content: JSONContent[]; type: string } =
JSON.parse(content);

const mapContent = (values: JSONContent[]): JSONContent[] => {
return values.filter(value => {
if (value.type === "files" && value.attrs?.id === file_id) {
return false;
}
if (value.content) {
value.content = mapContent(value.content);
}

return true;
});
};

const valueReturn = {
...parseValue,
content: mapContent(parseValue.content)
};

return JSON.stringify(valueReturn);
};

return (
<>
Expand Down Expand Up @@ -89,32 +121,35 @@ export const ItemListFilesFooterEditor = ({
variant="destructiveGhost"
ariaLabel={tCore("delete")}
onClick={async () => {
const nodes: Node[] = [];
editor.state.tr.doc.descendants(node => {
if (node.type.name === "files" && node.attrs.id === id) {
nodes.push(node);
}
});
// Remove files from the editor
if (Array.isArray(value)) {
const content: TextLanguage[] = value.map(item => ({
language_code: item.language_code,
value: handleDelete({
content: item.value,
file_id: id
})
}));

onChange(content);

const parseContent = JSON.parse(
content.find(item => item.language_code === selectedLanguage)
?.value ?? ""
);

editor.commands.clearContent();
editor.commands.setContent(parseContent);
} else {
const content = handleDelete({
content: value,
file_id: id
});

onChange(content);
}

editor.commands.forEach(
nodes.map(item => item.attrs.id),
(id, { commands, tr }) => {
const item = findChildren(tr.doc, node => {
return node.type.name === "files" && id === node.attrs.id;
})?.[0];

if (!item) {
return true;
}

return commands.deleteRange({
from: item.pos,
to: item.pos + item.node.nodeSize
});
}
);

// setFiles(prev => prev.filter(item => item.id !== id));
setFiles(prev => prev.filter(item => item.id !== id));
const mutation = await deleteMutationApi({
id,
securityKey: data?.security_key
Expand Down
18 changes: 16 additions & 2 deletions frontend/components/editor/hooks/use-editor-state.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
import { createContext, useContext } from "react";
import {
createContext,
useContext,
type Dispatch,
type SetStateAction
} from "react";
import type { Editor } from "@tiptap/react";

import type { FileStateEditor } from "../extensions/files/files";
import type {
UploadFilesHandlerArgs,
UploadFilesHandlerEditorArgs
} from "../extensions/files/hooks/use-upload-files-handler-editor.ts";
import type { TextLanguage } from "@/graphql/hooks";

interface Args extends Omit<UploadFilesHandlerEditorArgs, "value"> {
editor: Editor;
files: FileStateEditor[];
onChange: (value: TextLanguage[] | string) => void;
selectedLanguage: string;
setFiles: Dispatch<SetStateAction<FileStateEditor[]>>;
uploadFiles: (args: UploadFilesHandlerArgs) => Promise<void>;
value: string | TextLanguage[];
}

export const EditorStateContext = createContext<Args>({
files: [],
editor: {} as Editor,
uploadFiles: async () => {}
uploadFiles: async () => {},
value: [],
onChange: () => {},
selectedLanguage: "",
setFiles: () => {}
});

export const useEditorState = () => useContext(EditorStateContext);
28 changes: 14 additions & 14 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@
"@radix-ui/react-toggle": "^1.0.3",
"@radix-ui/react-toggle-group": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@tiptap/extension-code-block-lowlight": "^2.3.1",
"@tiptap/extension-color": "^2.3.1",
"@tiptap/extension-heading": "^2.3.1",
"@tiptap/extension-link": "^2.3.1",
"@tiptap/extension-mention": "^2.3.1",
"@tiptap/extension-text-align": "^2.3.1",
"@tiptap/extension-text-style": "^2.3.1",
"@tiptap/extension-underline": "^2.3.1",
"@tiptap/html": "^2.3.1",
"@tiptap/pm": "^2.3.1",
"@tiptap/react": "^2.3.1",
"@tiptap/starter-kit": "^2.3.1",
"@tiptap/extension-code-block-lowlight": "^2.3.2",
"@tiptap/extension-color": "^2.3.2",
"@tiptap/extension-heading": "^2.3.2",
"@tiptap/extension-link": "^2.3.2",
"@tiptap/extension-mention": "^2.3.2",
"@tiptap/extension-text-align": "^2.3.2",
"@tiptap/extension-text-style": "^2.3.2",
"@tiptap/extension-underline": "^2.3.2",
"@tiptap/html": "^2.3.2",
"@tiptap/pm": "^2.3.2",
"@tiptap/react": "^2.3.2",
"@tiptap/starter-kit": "^2.3.2",
"autoprefixer": "^10.4.19",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
Expand Down Expand Up @@ -81,7 +81,7 @@
"tippy.js": "^6.3.7",
"use-debounce": "^10.0.0",
"vaul": "^0.9.1",
"zod": "^3.23.7"
"zod": "^3.23.8"
},
"devDependencies": {
"@dnd-kit/core": "^6.1.0",
Expand All @@ -101,7 +101,7 @@
"@tanstack/react-table": "^8.16.0",
"@testing-library/react": "^15.0.7",
"@types/lodash": "^4.17.1",
"@types/node": "^20.12.10",
"@types/node": "^20.12.11",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.8.0",
Expand Down
Loading

0 comments on commit d53604b

Please sign in to comment.