Compare commits
No commits in common. "0b8a444b39440241e4449eec7eb525e45ca56a92" and "97d47b339aa67a40b9c9c7369087eaafbbd198f1" have entirely different histories.
0b8a444b39
...
97d47b339a
@ -2,44 +2,15 @@
|
|||||||
|
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { AbstractApi } from '@/app/api/abstract-api';
|
import Tiptap from '../../../components/Tiptap'
|
||||||
import { Website, WebsiteSerializer } from '@/app/lib/website';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import Tiptap from '../../../components/Tiptap';
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
|
|
||||||
const [website, setWebsite] = useState<Website>()
|
|
||||||
const api = new AbstractApi<Website>();
|
|
||||||
const serializer = new WebsiteSerializer();
|
|
||||||
|
|
||||||
const [timeoutId, setTimeoutId] = useState<NodeJS.Timeout | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
api.get(serializer, undefined, (loadedWebsite) => {
|
|
||||||
setWebsite(loadedWebsite);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const updateWebsite = (newContent: string) => {
|
|
||||||
// Debounce API update: send after 500ms of no further changes
|
|
||||||
if (timeoutId) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeoutId(
|
|
||||||
setTimeout(() => {
|
|
||||||
api.update(serializer, new Website('', newContent), () => { });
|
|
||||||
}, 500)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border rounded-lg p-4">
|
<div className="border rounded-lg p-4">
|
||||||
<Tiptap
|
<Tiptap
|
||||||
key={website?.content ?? 'empty'}
|
content="<p>Hello World! 🌎️</p>"
|
||||||
content={website?.content || ''}
|
onUpdate={(newContent) => console.log(newContent)}
|
||||||
onUpdate={updateWebsite}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { getCsrfToken, getSlug } from '@/app/lib/utils';
|
|||||||
export interface Api<T extends Entity> {
|
export interface Api<T extends Entity> {
|
||||||
getAll(serializable: Serializable<T>, callback: (objets: T[]) => void): void;
|
getAll(serializable: Serializable<T>, callback: (objets: T[]) => void): void;
|
||||||
get(serializable: Serializable<T>, id: string, callback: (object: T) => void): void;
|
get(serializable: Serializable<T>, id: string, callback: (object: T) => void): void;
|
||||||
getSingleton(serializable: Serializable<T>, callback: (object: T) => void): void;
|
|
||||||
create(serializable: Serializable<T>, object: T, callback: (object: T) => void): void;
|
create(serializable: Serializable<T>, object: T, callback: (object: T) => void): void;
|
||||||
update(serializable: Serializable<T>, object: T, callback: () => void): void;
|
update(serializable: Serializable<T>, object: T, callback: () => void): void;
|
||||||
destroy(serializable: Serializable<T>, object: T, callback: () => void): void;
|
destroy(serializable: Serializable<T>, object: T, callback: () => void): void;
|
||||||
@ -31,9 +30,8 @@ export class AbstractApi<T extends Entity> implements Api<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get(serializable: Serializable<T>, id: (string | undefined), callback: (object: T) => void): void {
|
get(serializable: Serializable<T>, id: string, callback: (object: T) => void): void {
|
||||||
const endpoint = id ? `/api/${getSlug()}/${serializable.apiPath()}/${id}` : `/api/${getSlug()}/${serializable.apiPath()}`;
|
fetch(`/api/${getSlug()}/${serializable.apiPath()}/${id}`)
|
||||||
fetch(endpoint)
|
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
callback(serializable.fromJson(data));
|
callback(serializable.fromJson(data));
|
||||||
@ -43,9 +41,7 @@ export class AbstractApi<T extends Entity> implements Api<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(serializable: Serializable<T>, object: T, callback: () => void): void {
|
update(serializable: Serializable<T>, object: T, callback: () => void): void {
|
||||||
const endpoint = object.id ? `/api/${getSlug()}/${serializable.apiPath()}/${object.id}` : `/api/${getSlug()}/${serializable.apiPath()}`;
|
fetch(`/api/${getSlug()}/${serializable.apiPath()}/${object.id}`, {
|
||||||
|
|
||||||
fetch(endpoint, {
|
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: serializable.toJson(object),
|
body: serializable.toJson(object),
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@ -13,7 +13,6 @@ const Tiptap = ({ content, onUpdate }: { content: string, onUpdate: (newContent:
|
|||||||
onUpdate({ editor }) {
|
onUpdate({ editor }) {
|
||||||
onUpdate(editor.getHTML());
|
onUpdate(editor.getHTML());
|
||||||
},
|
},
|
||||||
immediatelyRender: false,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return <EditorContent editor={editor} />
|
return <EditorContent editor={editor} />
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
/* Copyright (C) 2024-2025 LibreWeddingPlanner contributors*/
|
|
||||||
|
|
||||||
import { Serializable } from "../api/abstract-api";
|
|
||||||
import { Entity } from "./definitions";
|
|
||||||
|
|
||||||
|
|
||||||
export class Website implements Entity {
|
|
||||||
id?: string;
|
|
||||||
content?: string;
|
|
||||||
|
|
||||||
constructor(id: string, content: string) {
|
|
||||||
this.id = id;
|
|
||||||
this.content = content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class WebsiteSerializer implements Serializable<Website> {
|
|
||||||
fromJson(data: any): Website {
|
|
||||||
return new Website("", data.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
toJson(website: Website): string {
|
|
||||||
return JSON.stringify({ website: { content: website.content } });
|
|
||||||
}
|
|
||||||
|
|
||||||
apiPath(): string {
|
|
||||||
return 'website';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user