Refactoring and reworking dbsetup route

This commit is contained in:
2024-06-28 08:03:58 +02:00
parent c076918d05
commit 665da4be29
18 changed files with 390 additions and 162 deletions

View File

@@ -2,6 +2,7 @@ import { GetPostsAttributes } from "@/app/lib/actions/entityManagement/postActio
import { Post, Project, Bucket, PostBucket, Attachment } from "@/models";
import { Attributes } from "@sequelize/core";
import { UUID } from "crypto";
import { EntityEditorTextArea } from '../input/EntityEditorTextArea';
import {
ChangeEventHandler,
MouseEventHandler,
@@ -49,23 +50,6 @@ export default function PostEditor({
let [postProjectIDState, setPostProjectIDState] = useState(
editorPost.project.id
);
let textbox: any = useRef(undefined);
// Autosize the text area
function textAreaAutoSize(
textbox: MutableRefObject<HTMLTextAreaElement>
): void {
if (!textbox.current || !textbox.current.style) return;
textbox.current.style.height = "fit-content";
textbox.current.style.height = `${textbox.current.scrollHeight}px`;
}
useLayoutEffect(() => textAreaAutoSize(textbox));
// Handle user input on the text area by updating state and autosizing the textfield
const onTextAreaChange: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
setPostContentState(e.target.value); // Update State
textAreaAutoSize(textbox); // Autosize the text area
};
// Handle changing the selected project using the dropdown select
const projectSelectionChange: ChangeEventHandler<HTMLSelectElement> = (e) =>
@@ -102,14 +86,14 @@ export default function PostEditor({
<h2 key="label-content" className="m-2">
Content
</h2>
<textarea
key="input-content"
onChange={onTextAreaChange}
ref={textbox}
value={postContentState}
style={{ height: "100%" }}
className="w-[100%] min-h-auto h-content align-top text-start text-base line-clamp-6 m-2"
/>
<EntityEditorTextArea
contentHook={{
state: postContentState,
setState: setPostContentState
}}
className={ "w-[100%] min-h-auto h-content align-top text-start text-base line-clamp-6 m-2" }
>
</EntityEditorTextArea>
<h2 key="label-project" className="m-2">
Project
</h2>

View File

@@ -1,38 +1,28 @@
"use client";
import React, { ReactNode } from "react";
import React from "react";
import EntityManagementTable from "../EntityManagementTable";
import toast from "react-hot-toast";
import { EditorRenderer, EditorState, PostTableCallbacks } from "./PostEditor";
import { Attributes } from "@sequelize/core";
import { useState } from "react";
import { Project, Post, Bucket } from "@/models";
import { ActionResult } from "@/app/lib/actions/ActionResult";
import { Attributes, InferAttributes } from "@sequelize/core";
import { Project, Post, Bucket, User, PostAttributesWithBuckets } from "@/models";
import { handleActionResult } from "@/app/lib/actions/clientActionHandler";
import {
getPostsWithBucketsAndProject,
GetPostsAttributes,
PostServerActions,
} from "@/app/lib/actions/entityManagement/postActions";
import { PostViewProps } from "@/views/admin/ClientPostView";
import { aifa } from "@/util/Utils";
import { StateHook } from "../../../util/types/StateHook";
export type PostTableServerActions = {
deletePost: (id: number) => Promise<ActionResult<boolean>>;
getPosts: () => Promise<ActionResult<GetPostsAttributes[]>>;
getProjects: () => Promise<ActionResult<Attributes<Project>[]>>;
savePost: (
data: Partial<Attributes<Post>>
) => Promise<ActionResult<Attributes<Post>[]>>;
// uploadAttachment: ()=> Promise<ActionResult<any>>
};
export type PostTableStateProps = {
posts:StateHook<GetPostsAttributes[]>,
editor:StateHook<EditorState>
}
type PostTableProps = {
children?: ReactNode;
headings: Array<string>;
posts: GetPostsAttributes[];
projects: Attributes<Project>[];
actions: PostTableServerActions;
};
export type PostTableProps = PostViewProps & {state:PostTableStateProps};
const aifa = (a: ReactNode, b: ReactNode) => (a ? a : b);
export default function PostTable({
children,
@@ -40,26 +30,20 @@ export default function PostTable({
posts,
projects,
actions,
state,
}: PostTableProps) {
// Init editor state. Make sure it is not opened by default
const initEditorState: EditorState = {
isEditorOpen: false,
editorPost: posts[0],
};
// Set up required state hooks
const [postsState, setPostsState] = useState(posts);
const [editorState, setEditorState] = useState(initEditorState);
// Define editor controls
const editorControls = {
closeEditor: () => {
setEditorState({
state.editor.setState({
isEditorOpen: false,
editorPost: posts[0],
});
},
showEditor: (entry: GetPostsAttributes) => {
setEditorState({
state.editor.setState({
isEditorOpen: true,
editorPost: entry,
});
@@ -72,8 +56,8 @@ export default function PostTable({
actions.deletePost(entry.id).then((actionResult) => {
const result = handleActionResult(actionResult);
if (!result) return;
postsState.splice(postsState.indexOf(entry), 1);
setPostsState([...postsState]);
state.posts.state.splice(state.posts.state.indexOf(entry), 1);
state.posts.setState([...state.posts.state]);
toast.success("Removed Post:" + entry.id);
});
},
@@ -86,7 +70,7 @@ export default function PostTable({
getPostsServerActionResult
);
// Set Posts state
if (result) setPostsState(result);
if (result) state.posts.setState(result);
});
},
savePost: (e: Partial<Attributes<Post>>) => {
@@ -101,26 +85,19 @@ export default function PostTable({
.then(getPostsWithBucketsAndProject)
.then((res) => {
const result = handleActionResult(res);
if (result) setPostsState(result);
if (result) state.posts.setState(result);
})
.then(editorControls.closeEditor)
.then(postActions.refetch);
},
};
const callbacks: PostTableCallbacks = {
savePost: postActions.savePost,
closeEditor: editorControls.closeEditor,
refetch: postActions.refetch,
uploadAttachment: () => {},
};
return (
<EntityManagementTable
entityName="Post"
headings={headings}
>
{postsState.map((post: GetPostsAttributes) => (
{state.posts.state.map((post: GetPostsAttributes) => (
<React.Fragment key={`postrow-${post.id}`}>
<tr>
<th key={`rowheading-post-${post.id}`} scope="row">
@@ -177,8 +154,13 @@ export default function PostTable({
headings={headings}
editorPost={post}
editorControls={editorControls}
editorState={editorState}
callbacks={callbacks}
editorState={state.editor.state}
callbacks={{
savePost: postActions.savePost,
closeEditor: editorControls.closeEditor,
refetch: postActions.refetch,
uploadAttachment: () => {},
}}
projects={projects}
/>
</React.Fragment>

View File

@@ -0,0 +1,34 @@
'use client'
import { useRef, MutableRefObject, useLayoutEffect, ChangeEventHandler, useState } from "react";
import { StateHook } from '../../../util/types/StateHook';
export function EntityEditorTextArea({contentHook, className}: {contentHook:StateHook<string>, className:string}){
let textbox: any = useRef(undefined);
// Autosize the text area
function textAreaAutoSize(
textbox: MutableRefObject<HTMLTextAreaElement>
): void {
if (!textbox.current || !textbox.current.style) return;
textbox.current.style.height = "fit-content";
textbox.current.style.height = `${textbox.current.scrollHeight}px`;
}
useLayoutEffect(() => textAreaAutoSize(textbox));
// Handle user input on the text area by updating state and autosizing the textfield
const onTextAreaChange: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
contentHook?.setState(e.target.value); // Update State
textAreaAutoSize(textbox); // Autosize the text area
};
return <textarea
key="input-content"
onChange={onTextAreaChange}
ref={textbox}
value={contentHook?.state}
style={{ height: "100%" }}
className={className}
/>
}