Sudetekešní upravování
This commit is contained in:
@@ -30,7 +30,7 @@ Jestli jste na debian založené distribuci linuxu a nahrávání souborů vám
|
||||
- cd imei
|
||||
- sudo ./imei.sh
|
||||
|
||||
## Vývoj
|
||||
## Vývoj / Roadmap
|
||||
|
||||
Základní funkce jsou již implementované, ale plánujeme přidat i nové
|
||||
|
||||
@@ -55,10 +55,10 @@ Základní funkce jsou již implementované, ale plánujeme přidat i nové
|
||||
- [x] Vlastní stránky
|
||||
- [x] Záznamy
|
||||
- [x] Archiv
|
||||
- [ ] Upravování příspěvků
|
||||
- [ ] Přesouvání příspěvků
|
||||
- [X] Upravování příspěvků
|
||||
- [ ] Více info o IP na IP stránce
|
||||
- [ ] Poznámky k IP adrese
|
||||
- [ ] Přesouvání příspěvků
|
||||
- [ ] Nastavení stránky a správa assetů z UI
|
||||
- [ ] phash
|
||||
- [ ] Přímé zprávy
|
||||
|
||||
@@ -82,8 +82,13 @@ const CreatePostForm = z.object({
|
||||
deletion_code: zRequiredField(zDeletionCode),
|
||||
});
|
||||
|
||||
// Generic
|
||||
const UpdatePostContentForm = z.object({
|
||||
board: zRequiredField(zBoardID),
|
||||
id: zRequiredField(zPostID),
|
||||
content: zRequiredField(z.string()),
|
||||
});
|
||||
|
||||
// Post actions
|
||||
const ZPostActionsForm = z.object({
|
||||
// Common
|
||||
posts: zMultiField(zCompPostID),
|
||||
@@ -131,5 +136,6 @@ export {
|
||||
zCaptcha,
|
||||
zDeletionCode,
|
||||
CreatePostForm,
|
||||
UpdatePostContentForm,
|
||||
ZPostActionsForm,
|
||||
};
|
||||
|
||||
@@ -152,8 +152,15 @@ const PostComponent = ({
|
||||
{canUser(ctx.user, CzchanPerm.VIEW_METADATA) && (
|
||||
<>
|
||||
<b>
|
||||
<a href={`/mod/post-info/${board.id}/${post.id}`}>[M]</a>
|
||||
</b>
|
||||
<a href={`/mod/post_info/${board.id}/${post.id}`}>[I]</a>
|
||||
</b>{" "}
|
||||
</>
|
||||
)}
|
||||
{canUser(ctx.user, CzchanPerm.EDIT_POSTS) && (
|
||||
<>
|
||||
<b>
|
||||
<a href={`/mod/edit/post_content/${board.id}/${post.id}`}>[ED]</a>
|
||||
</b>{" "}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
46
src/web/routes/mod/actions/update_post_content.ts
Normal file
46
src/web/routes/mod/actions/update_post_content.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { readBoard } from "../../../../db/board.js";
|
||||
import { readPost, updatePostContent } from "../../../../db/post.js";
|
||||
import { CzchanError } from "../../../../lib/error.js";
|
||||
import { formatContent } from "../../../../lib/formatting.js";
|
||||
import { czchanLog } from "../../../../lib/log.js";
|
||||
import { canUser, CzchanPerm } from "../../../../lib/permissions.js";
|
||||
import { canonicalPostURL } from "../../../../lib/util.js";
|
||||
import { UpdatePostContentForm } from "../../../../schema/validation/post.js";
|
||||
import type { Request, Response } from "express";
|
||||
import formidable from "formidable";
|
||||
|
||||
export default async (req: Request, res: Response) => {
|
||||
if (!canUser(req.user, CzchanPerm.EDIT_POSTS)) {
|
||||
throw new CzchanError("K tomuto nemáš oprávnění.", 403);
|
||||
}
|
||||
|
||||
const parser = formidable({});
|
||||
const [fields, _] = await parser.parse(req);
|
||||
const { board, id, content } = UpdatePostContentForm.parse(fields);
|
||||
|
||||
const board_ = await readBoard(board);
|
||||
|
||||
if (
|
||||
board_.config.private &&
|
||||
!canUser(req.user, CzchanPerm.VIEW_PRIVATE_BOARDS)
|
||||
) {
|
||||
throw new CzchanError(`K nástěnce /${board_.id}/ nemáš přístup.`, 403);
|
||||
}
|
||||
|
||||
const post = await readPost(board_.id, id);
|
||||
|
||||
const content_unformatted = content;
|
||||
const content_formatted = (await formatContent(req, board_.id, content))
|
||||
.output;
|
||||
|
||||
await updatePostContent(post, content_unformatted, content_formatted);
|
||||
|
||||
await czchanLog(
|
||||
"mod",
|
||||
"info",
|
||||
`Upraven obsah příspěvku: >>>/${board_.id}/${post.id}`,
|
||||
req.user?.username,
|
||||
);
|
||||
|
||||
res.redirect(canonicalPostURL(post));
|
||||
};
|
||||
80
src/web/routes/mod/edit/post_content.tsx
Normal file
80
src/web/routes/mod/edit/post_content.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import { readBoard } from "../../../../db/board.js";
|
||||
import { readPost } from "../../../../db/post.js";
|
||||
import { CzchanError } from "../../../../lib/error.js";
|
||||
import { canUser, CzchanPerm } from "../../../../lib/permissions.js";
|
||||
import { canonicalPostURL } from "../../../../lib/util.js";
|
||||
import type { Board, Post } from "../../../../schema/tables.js";
|
||||
import { zBoardID } from "../../../../schema/validation/common.js";
|
||||
import { zPostID } from "../../../../schema/validation/post.js";
|
||||
import Page from "../../../components/chrome/page.js";
|
||||
import PageBody from "../../../components/chrome/page_body.js";
|
||||
import PageHead from "../../../components/chrome/page_head.js";
|
||||
import { Form, FormButton, FormField } from "../../../components/forms/form.js";
|
||||
import { getCtx, type TemplateCtx } from "../../../ctx.js";
|
||||
import type { PropsWithChildren } from "@kitajs/html";
|
||||
import type { Request, Response } from "express";
|
||||
|
||||
export default async (req: Request, res: Response) => {
|
||||
const ctx = await getCtx(req);
|
||||
|
||||
if (!canUser(ctx.user, CzchanPerm.EDIT_POSTS)) {
|
||||
throw new CzchanError("K tomuto nemáš oprávnění.", 403);
|
||||
}
|
||||
|
||||
const board = await readBoard(zBoardID.parse(req.params.board));
|
||||
|
||||
if (
|
||||
board.config.private &&
|
||||
!canUser(ctx.user, CzchanPerm.VIEW_PRIVATE_BOARDS)
|
||||
) {
|
||||
throw new CzchanError(`K nástěnce /${board.id}/ nemáš přístup.`, 403);
|
||||
}
|
||||
|
||||
const post = await readPost(board.id, zPostID.parse(req.params.id));
|
||||
const html = Template(ctx, board, post);
|
||||
|
||||
res.send(html);
|
||||
};
|
||||
|
||||
const Template = (ctx: TemplateCtx, board: Board, post: Post) => (
|
||||
<Page>
|
||||
<PageHead ctx={ctx} title="Úprava příspěvku" description="" />
|
||||
<PageBody ctx={ctx}>
|
||||
<h1 class="title center">
|
||||
Úprava příspěvku (
|
||||
<a href={canonicalPostURL(post)}>
|
||||
>>>/<span safe>{board.id}</span>/{post.id}
|
||||
</a>
|
||||
)
|
||||
</h1>
|
||||
<UpdateForm ctx={ctx} board={board} post={post} />
|
||||
<hr />
|
||||
</PageBody>
|
||||
</Page>
|
||||
);
|
||||
|
||||
const UpdateForm = ({
|
||||
board,
|
||||
post,
|
||||
}: PropsWithChildren<{ ctx: TemplateCtx; board: Board; post: Post }>) => (
|
||||
<form method="post" action="/mod/actions/update_post_content">
|
||||
<input name="board" type="hidden" value={board.id} />
|
||||
<input name="id" type="hidden" value={post.id.toString()} />
|
||||
<Form center>
|
||||
<FormField
|
||||
label={
|
||||
<>
|
||||
Obsah
|
||||
<br />
|
||||
<small>(max {board.config.max_length})</small>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<textarea name="content" rows="10" cols="35" safe>
|
||||
{post.content_unformatted}
|
||||
</textarea>
|
||||
</FormField>
|
||||
<FormButton submit="Upravit" action="update_post_content" />
|
||||
</Form>
|
||||
</form>
|
||||
);
|
||||
@@ -12,6 +12,7 @@ import modActionNewsActions from "../routes/mod/actions/news_actions.js";
|
||||
import modActionRestrictionActions from "../routes/mod/actions/restriction_actions.js";
|
||||
import modActionUpdateBoardConfig from "../routes/mod/actions/update_board_config.js";
|
||||
import modActionUpdateNewsContent from "../routes/mod/actions/update_news_content.js";
|
||||
import modActionUpdatePostContent from "../routes/mod/actions/update_post_content.js";
|
||||
import modActionUpdateUserPassword from "../routes/mod/actions/update_user_password.js";
|
||||
import modActionUpdateUserPermissions from "../routes/mod/actions/update_user_permissions.js";
|
||||
import modActionUserActions from "../routes/mod/actions/user_actions.js";
|
||||
@@ -20,6 +21,7 @@ import modBans from "../routes/mod/bans.js";
|
||||
import modBoards from "../routes/mod/boards.js";
|
||||
import modEditBoardConfig from "../routes/mod/edit/board_config.js";
|
||||
import modEditNewsContent from "../routes/mod/edit/news_content.js";
|
||||
import modEditPostContent from "../routes/mod/edit/post_content.js";
|
||||
import modEditUserPermissions from "../routes/mod/edit/user_permissions.js";
|
||||
import modFilters from "../routes/mod/filters.js";
|
||||
import modIndex from "../routes/mod/index.js";
|
||||
@@ -50,12 +52,13 @@ const registerModRoutes = (router: Router) => {
|
||||
|
||||
// Mod info
|
||||
router.get("/mod/ip/:ip", e(modIP));
|
||||
router.get("/mod/post-info/:board/:id", e(modPostInfo));
|
||||
router.get("/mod/post_info/:board/:id", e(modPostInfo));
|
||||
|
||||
// Edit pages
|
||||
router.get("/mod/edit/user_permissions/:user", e(modEditUserPermissions));
|
||||
router.get("/mod/edit/board_config/:board", e(modEditBoardConfig));
|
||||
router.get("/mod/edit/news_content/:news", e(modEditNewsContent));
|
||||
router.get("/mod/edit/post_content/:board/:id", e(modEditPostContent));
|
||||
|
||||
// Edit page actions
|
||||
router.post(
|
||||
@@ -70,6 +73,10 @@ const registerModRoutes = (router: Router) => {
|
||||
"/mod/actions/update_news_content",
|
||||
e(modActionUpdateNewsContent),
|
||||
);
|
||||
router.post(
|
||||
"/mod/actions/update_post_content",
|
||||
e(modActionUpdatePostContent),
|
||||
);
|
||||
|
||||
// Action pages
|
||||
router.post("/mod/actions/create_user", e(modActionCreateUser));
|
||||
|
||||
Reference in New Issue
Block a user