problem solved

This commit is contained in:
Andreas 2024-07-07 01:15:40 +02:00
parent dc66da7d00
commit 365e2e3982
2 changed files with 221 additions and 288 deletions

View File

@ -6,6 +6,7 @@ import { Attributes, where } from "@sequelize/core";
import { getCookieAuth, userIsAdmin } from '../../actions';
import { ActionResult } from '../../ActionResult';
import { PostAttributesWithBuckets } from '@/models';
import { inspect } from 'util';
export async function deletePost(postID: number): Promise<ActionResult<boolean>> {
await dbSync;
@ -30,7 +31,7 @@ export type GetPostsAttributes = {
export async function getPostsWithBucketsAndProject(): Promise<ActionResult<GetPostsAttributes[]>> {
await dbSync;
if(! await userIsAdmin()) return {error:"Unauthorized, not fetching Posts."}
const posts = await Post.findAll({
const posts:Post[] = await Post.findAll({
include: [
{association: Post.associations.buckets, include: Bucket.associations.attachments},
{association: Post.associations.user},
@ -38,22 +39,7 @@ export async function getPostsWithBucketsAndProject(): Promise<ActionResult<GetP
nest: false
});
return {result:JSON.parse(JSON.stringify(posts.map((e:Post)=>{
return {
id: e.id,
title: e.title,
content: e.content,
description: e.description,
buckets: e.buckets ? e.buckets : [],
user: e.user,
project: {
id: e.project_id,
name: e.project ? e.project.name : "",
readableIdentifier: e.project ? e.project.readableIdentifier : "",
posts: e.project ? e.project.posts : []
},
createdAt: e.createdAt,
updatedAt: e.updatedAt
} as GetPostsAttributes
return inspect(e)
})))};
}

View File

@ -1,296 +1,243 @@
import { GetPostsAttributes } from "@/app/lib/actions/entityManagement/post/postActions";
import { GetPostsAttributes } from "@/app/lib/actions/entitymanagement/post/postActions";
import { Post, Project, Bucket, PostBucket, Attachment } from "@/models";
import { Attributes } from "@sequelize/core";
import { UUID } from "crypto";
import { EntityEditorTextArea } from '../input/EntityEditorTextArea';
import { EntityEditorTextArea } from "../input/EntityEditorTextArea";
import { ChangeEvent, ChangeEventHandler, MouseEventHandler, useState } from "react";
import {
ChangeEventHandler,
MouseEventHandler,
useState,
} from "react";
import {
Accordion,
AccordionBody,
AccordionHeader,
AccordionItem,
Accordion,
AccordionBody,
AccordionHeader,
AccordionItem,
} from "react-bootstrap";
export type PostTableCallbacks = {
savePost: (p: Partial<Attributes<Post>>) => void;
refetch: () => any;
closeEditor: () => any;
uploadAttachment: () => any;
savePost: (p: Partial<Attributes<Post>>) => void;
refetch: () => any;
closeEditor: () => any;
uploadAttachment: () => any;
};
export type EditorState = {
isEditorOpen: boolean;
editorPost: GetPostsAttributes;
isEditorOpen: boolean;
editorPost: GetPostsAttributes;
};
export type EditorProps = {
editorPost: GetPostsAttributes;
projectList: {
id: number;
readableIdentifier: string;
}[];
callbacks: PostTableCallbacks;
editorPost: GetPostsAttributes;
projectList: {
id: number;
readableIdentifier: string;
}[];
callbacks: PostTableCallbacks;
};
export default function PostEditor({
editorPost,
projectList,
callbacks,
editorPost,
projectList,
callbacks,
}: EditorProps) {
// Setup State Hooks
let [postContentState, setPostContentState] = useState(editorPost.content);
let [postTitleState, setPostTitleState] = useState(editorPost.title);
let [postProjectIDState, setPostProjectIDState] = useState(
editorPost.project.id
);
// Setup State Hooks
let [postContentState, setPostContentState] = useState(editorPost.content);
let [postTitleState, setPostTitleState] = useState(editorPost.title);
let [postProjectIDState, setPostProjectIDState] = useState(
editorPost.project.id
);
// Handle changing the selected project using the dropdown select
const projectSelectionChange: ChangeEventHandler<HTMLSelectElement> = (e) =>
setPostProjectIDState(parseInt(e.target.value));
// Handle clicking the save button
const onClickSaveButton: MouseEventHandler<HTMLButtonElement> = (e) => {
callbacks?.savePost({
id: editorPost?.id as number,
content: postContentState as string,
title: postTitleState as string,
project_id: postProjectIDState,
});
};
const onClickCancelButton: MouseEventHandler<HTMLButtonElement> = (e) => {
callbacks?.closeEditor();
};
// Handle changing the selected project using the dropdown select
const projectSelectionChange: ChangeEventHandler<HTMLSelectElement> = (e) =>
setPostProjectIDState(parseInt(e.target.value));
// Handle clicking the save button
const onClickSaveButton: MouseEventHandler<HTMLButtonElement> = (e) => {
callbacks?.savePost({
id: editorPost?.id as number,
content: postContentState as string,
title: postTitleState as string,
project_id: postProjectIDState,
});
};
const onClickCancelButton: MouseEventHandler<HTMLButtonElement> = (e) => {
callbacks?.closeEditor();
};
return (
<>
<form className="bg-light w-[100%] h-content p-1">
<h1 key="heading-editpost" className="m-2">
Edit Post
</h1>
<h2 key="label-title" className="m-2">
Title
</h2>
<input
key="input-title"
value={postTitleState}
onChange={(e) => setPostTitleState(e.target.value)}
type="text"
className="m-2"
/>
<h2 key="label-content" className="m-2">
Content
</h2>
<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>
<select
key="input-project"
onChange={projectSelectionChange}
name="projects"
id="projects"
defaultValue={editorPost?.project?.id}
placeholder={editorPost?.project?.name}
value={postProjectIDState}
className="m-2"
>
<option key="projectSelectionOpt-0" value={0}>
unassigned
</option>
{projectList?.map((p) => (
<option
key={`projectSelectionOpt-${p.id}`}
value={p.id}
>
{p.readableIdentifier}
</option>
))}
</select>
<h2 key="label-attachments">Attachments</h2>
<table key="table-buckets" className="table table-striped">
<thead>
<tr>
<td>Buckets</td>
</tr>
</thead>
<tbody>
{editorPost?.buckets ? (
(() => {
let bucketMap: Map<
UUID,
Attributes<Bucket>
> = new Map(
editorPost.buckets.map((b) => [
b.id as UUID,
b,
])
);
let bucketList = [
...editorPost.buckets.map((b) => b.id),
];
return bucketList.map((e) => {
return (
<>
<tr
key={`bucketAccordionRow-${bucketList
.indexOf(e)
.toString()}`}
>
<Accordion>
<AccordionItem
eventKey={bucketList
.indexOf(e)
.toString()}
>
<AccordionHeader>
{e}
</AccordionHeader>
<AccordionBody>
<ul>
<li>
<input
type="file"
className="btn btn-success"
onChange={(
e
) => {
for (
let index = 0;
index <
((
e
.target
.files as FileList
)
.length as number);
index++
) {
const element =
(
e
.target
.files as FileList
)[
index
];
const fReader =
new FileReader();
fReader.readAsDataURL(
element
);
fReader.onloadend =
(
event
) => {
console.log(
event
.target
?.result
);
};
}
}}
/>
</li>
{(() => {
const bucket =
bucketMap.get(
e as UUID
);
return bucket &&
bucket.attachments ? (
bucket.attachments.map(
(
attachment
) => (
<li
key={`listItem-file-${attachment.filename}`}
>
{
attachment.filename
}
</li>
)
)
) : (
<></>
);
})()}
</ul>
</AccordionBody>
</AccordionItem>
</Accordion>
</tr>
</>
);
});
})()
) : (
<></>
)}
</tbody>
</table>
<button type="button" className="m-2 btn btn-primary">
Preview
</button>
<button
type="button"
className="m-2 btn btn-success"
onClick={onClickSaveButton}
>
Save
</button>
<button
type="button"
className="m-2 btn btn-danger"
onClick={onClickCancelButton}
>
Cancel
</button>
</form>
</>
);
return (
<>
<form className="bg-light w-[100%] h-content p-1">
<h1 key="heading-editpost" className="m-2">
Edit Post
</h1>
<h2 key="label-title" className="m-2">
Title
</h2>
<input
key="input-title"
value={postTitleState}
onChange={(e) => setPostTitleState(e.target.value)}
type="text"
className="m-2"
/>
<h2 key="label-content" className="m-2">
Content
</h2>
<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>
<select
key="input-project"
onChange={projectSelectionChange}
name="projects"
id="projects"
defaultValue={editorPost?.project?.id}
placeholder={editorPost?.project?.name}
value={postProjectIDState}
className="m-2"
>
<option key="projectSelectionOpt-0" value={0}>
unassigned
</option>
{projectList?.map((p) => (
<option key={`projectSelectionOpt-${p.id}`} value={p.id}>
{p.readableIdentifier}
</option>
))}
</select>
<h2 key="label-attachments">Attachments</h2>
<table key="table-buckets" className="table table-striped">
<thead>
<tr>
<td>Buckets</td>
</tr>
</thead>
<tbody>
{editorPost?.buckets ? (
(() => {
let bucketMap: Map<UUID, Attributes<Bucket>> = new Map(
editorPost.buckets.map((b) => [b.id as UUID, b])
);
let bucketList:UUID[] = [...editorPost.buckets.map((b) => b.id)];
return bucketList.map((bucketID,i) => {
return (
<>
<tr
key={i}
>
<Accordion>
<AccordionItem
eventKey={bucketList.indexOf(bucketID).toString()}
>
<AccordionHeader>{bucketID}</AccordionHeader>
<AccordionBody>
<ul>
<li>
<input
type="file"
className="btn btn-success"
onChange={onFileInputChange()}
/>
</li>
{(() => {
const bucket: Attributes<Bucket> | undefined = bucketMap.get(bucketID);
return bucket && bucket.attachments && (
bucket.attachments.map((attachment) => (
<li
key={`listItem-file-${attachment.filename}`}
>
{attachment.filename}
</li>
))
);
})()}
</ul>
</AccordionBody>
</AccordionItem>
</Accordion>
</tr>
</>
);
});
})()
) : (
<></>
)}
</tbody>
</table>
<button type="button" className="m-2 btn btn-primary">
Preview
</button>
<button
type="button"
className="m-2 btn btn-success"
onClick={onClickSaveButton}
>
Save
</button>
<button
type="button"
className="m-2 btn btn-danger"
onClick={onClickCancelButton}
>
Cancel
</button>
</form>
</>
);
}
type EditorRendererProps = {
editorPost: GetPostsAttributes;
headings: string[];
editorState: EditorState;
editorControls: any;
callbacks: any;
projects: any;
editorPost: GetPostsAttributes;
headings: string[];
editorState: EditorState;
editorControls: any;
callbacks: any;
projects: any;
};
export function EditorRenderer({
editorPost,
headings,
editorState,
callbacks,
projects,
}: EditorRendererProps) {
return editorState.isEditorOpen &&
editorState.editorPost &&
editorState.editorPost.id == editorPost.id ? (
<tr>
<th scope="row" colSpan={headings.length}>
<PostEditor
callbacks={callbacks}
editorPost={editorState.editorPost}
projectList={projects}
/>
</th>
</tr>
) : (
""
);
function onFileInputChange(): ChangeEventHandler<HTMLInputElement> {
return (e: ChangeEvent<HTMLInputElement>) => {
for (let index = 0; index <
((e.target.files as FileList)
.length as number); index++) {
const element = (
e.target.files as FileList
)[index];
const fReader = new FileReader();
fReader.readAsDataURL(element);
fReader.onloadend = (event) => {
console.log(event.target?.result);
};
}
};
}
export function EditorRenderer({
editorPost,
headings,
editorState,
callbacks,
projects,
}: EditorRendererProps) {
return editorState.isEditorOpen &&
editorState.editorPost &&
editorState.editorPost.id == editorPost.id ? (
<tr>
<th scope="row" colSpan={headings.length}>
<PostEditor
callbacks={callbacks}
editorPost={editorState.editorPost}
projectList={projects}
/>
</th>
</tr>
) : (
""
);
}