👔(app-impress) save the templates editor automatically

On almost each change in the code editor,
the template is saved automatically.
It will restore as well the editor when we arrive
on the template editor page.
This commit is contained in:
Anthony LC
2024-04-16 16:55:59 +02:00
committed by Anthony LC
parent 3aaa3e179d
commit e13ecdd38d
5 changed files with 129 additions and 3 deletions

View File

@@ -0,0 +1,39 @@
import { useMutation } from '@tanstack/react-query';
import { APIError, errorCauses, fetchAPI } from '@/api';
import { Template } from '../types';
type UpdateTemplateProps = Pick<Template, 'code_editor' | 'id'>;
export const updateTemplateCodeEditor = async ({
code_editor,
id,
}: UpdateTemplateProps): Promise<Template> => {
const response = await fetchAPI(`templates/${id}/`, {
method: 'PATCH',
body: JSON.stringify({
code_editor,
}),
});
if (!response.ok) {
throw new APIError(
'Failed to update the template',
await errorCauses(response),
);
}
return response.json() as Promise<Template>;
};
export function useUpdateTemplateCodeEditor(
onSuccess?: (data: Template) => void,
) {
return useMutation<Template, APIError, UpdateTemplateProps>({
mutationFn: updateTemplateCodeEditor,
onSuccess: (data) => {
onSuccess?.(data);
},
});
}

View File

@@ -2,6 +2,7 @@ import GjsEditor from '@grapesjs/react';
import grapesjs, { Editor, ProjectData } from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';
import pluginBlocksBasic from 'grapesjs-blocks-basic';
import { useEffect, useState } from 'react';
import { Card, Text } from '@/components';
@@ -13,7 +14,44 @@ interface TemplateEditorProps {
}
export const TemplateEditor = ({ template }: TemplateEditorProps) => {
const onEditor = (editor: Editor) => {};
const { mutate: updateCodeEditor } = useUpdateTemplateCodeEditor();
const [editor, setEditor] = useState<Editor>();
useEffect(() => {
if (!editor?.loadProjectData) {
return;
}
editor.loadProjectData(template.code_editor);
}, [template.code_editor, editor]);
useEffect(() => {
editor?.Storage.add('remote', {
load() {
return Promise.resolve(template.code_editor);
},
store(data: ProjectData) {
updateCodeEditor({
code_editor: data,
id: template.id,
});
return Promise.resolve();
},
});
}, [editor, template.code_editor, template.id, updateCodeEditor]);
const onEditor = (editor: Editor) => {
setEditor(editor);
editor?.Storage.add('remote', {
load() {
return Promise.resolve(template.code_editor);
},
store() {
return Promise.resolve();
},
});
};
return (
<>
@@ -24,7 +62,9 @@ export const TemplateEditor = ({ template }: TemplateEditorProps) => {
<GjsEditor
grapesjs={grapesjs}
options={{
storageManager: false,
storageManager: {
type: 'remote',
},
}}
plugins={[(editor) => pluginBlocksBasic(editor, {})]}
onEditor={onEditor}

View File

@@ -1,3 +1,5 @@
import { ProjectData } from 'grapesjs';
export enum Role {
MEMBER = 'member',
ADMIN = 'administrator',
@@ -27,5 +29,6 @@ export interface Template {
update: boolean;
};
accesses: Access[];
code_editor: ProjectData;
title: string;
}

View File

@@ -26,7 +26,18 @@ interface TemplateProps {
}
const Template = ({ id }: TemplateProps) => {
const { data: template, isLoading, isError, error } = useTemplate({ id });
const {
data: template,
isLoading,
isError,
error,
} = useTemplate(
{ id },
{
queryKey: ['template', { id }],
staleTime: 0,
},
);
const navigate = useNavigate();
if (isError && error) {