diff --git a/app/routes/_layout.archives.edit.$postId.tsx b/app/routes/_layout.archives.edit.$postId.tsx index fc9bf7a9..dc2bfdce 100644 --- a/app/routes/_layout.archives.edit.$postId.tsx +++ b/app/routes/_layout.archives.edit.$postId.tsx @@ -7,10 +7,12 @@ import { H1, H2 } from "~/components/Headings"; import { ClientOnly } from "remix-utils/client-only"; import MarkdownEditor from "~/components/MarkdownEditor.client"; import { useState } from "react"; +// @ts-expect-error : markedの型定義が存在しないため、anyとしている import { marked } from 'marked'; import { getSession, requireUserId } from "~/modules/session.server"; import * as diff from 'diff'; import { createEmbedding } from "~/modules/embedding.server"; +import TagSelectionBox from "~/components/SubmitFormComponents/TagSelectionBox"; export async function loader({ params, request }: LoaderFunctionArgs) { @@ -32,33 +34,22 @@ export async function loader({ params, request }: LoaderFunctionArgs) { - nowEditingInfoが存在し、最終ロック時刻から30分以上経過している場合、編集中でない - それ以外の場合は編集中と判断する。つまりは以下の場合: - nowEditingInfoが存在する - - なおかつ、自分以外のユーザー名が格納されている + - なおかつ、自分以外のユーザーIDが格納されている - なおかつ、lasteHeartBeatAtUTCから30分以内である */ - let isEditing = nowEditingInfo ? new Date().getTime() - nowEditingInfo.lastHeartBeatAtUTC.getTime() <= 1000 * 60 * 30 : false; - - if (nowEditingInfo){ - const userName = await prisma.userProfiles.findUniqueOrThrow({ - select: { userId: true }, - where: { userId }, - }); - if (nowEditingInfo.userId === userName.userId){ - isEditing = false; - } - } + const isEditing = nowEditingInfo && nowEditingInfo.userId !== userId && (new Date().getTime() - new Date(nowEditingInfo.lastHeartBeatAtUTC).getTime()) < 30 * 60 * 1000; if (isEditing && nowEditingInfo){ - // モーダルを表示する:${nowEditingInfo.userName}さんが編集中です。 + // モーダルを表示する:${nowEditingInfo.userId}さんが編集中です。 // 「戻る」を押してredirect(`/archives/${postId}`)する return json({ postData: null, postMarkdown: null, tagNames: null, allTagsForSearch: null, - editingUserName: nowEditingInfo.userId, + userId, postId, isEditing: true, - userName: null, editHistory: null, }); } @@ -70,15 +61,10 @@ export async function loader({ params, request }: LoaderFunctionArgs) { where: { postId: Number(postId) }, }); } - const userName = await prisma.userProfiles.findUniqueOrThrow({ - select: { userId: true }, - where: { userId }, - }); - await prisma.nowEditingPages.create({ data: { postId: Number(postId), - userId: userName.userId, + userId: userId, }, }); @@ -147,8 +133,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) { tagNames, postMarkdown, allTagsForSearch, - userName: userName.userId, - editingUserName:null, + userId, isEditing:false, postId, editHistory, @@ -156,13 +141,16 @@ export async function loader({ params, request }: LoaderFunctionArgs) { } export default function EditPost() { - const { postData, postMarkdown, tagNames, allTagsForSearch, editingUserName, isEditing, postId, userName, editHistory } = useLoaderData(); + const { postData, postMarkdown, tagNames, allTagsForSearch, isEditing, postId, userId, editHistory } = useLoaderData(); + const [markdownContent, setMarkdownContent] = useState(postMarkdown || ""); + const [selectedTags, setSelectedTags] = useState(tagNames); + const navigation = useNavigation(); if (isEditing){ return (
-

{editingUserName}さんが編集中です。

+

{userId}さんが編集中です。

戻る @@ -171,40 +159,26 @@ export default function EditPost() { ); } + if (!postData) { + return
投稿が見つかりません
; + } const { postTitle } = postData; - - const [markdownContent, setMarkdownContent] = useState(postMarkdown); - const [selectedTags, setSelectedTags] = useState(tagNames); - const [tagInputValue, setTagInputValue] = useState(""); - const [tagSearchSuggestions, setTagSearchSuggestions] = useState<{ tagName: string, count: number }[]>([]); const oldTags = tagNames - const handleTagInputChange = (e: React.ChangeEvent) => { - const value = e.target.value; - setTagInputValue(value); - - if (value.length > 0) { - const filteredTagSearchSuggestions = allTagsForSearch.filter((tag) => tag.tagName.includes(value)); - setTagSearchSuggestions(filteredTagSearchSuggestions); - } else { - setTagSearchSuggestions([]); + const handleTagRemove = (tagName: string) => { + if (selectedTags) { + setSelectedTags(selectedTags.filter((tag) => tag !== tagName)); } }; - const handleTagSelect = (tagName: string) => { - if (!selectedTags.includes(tagName)) { - setSelectedTags([...selectedTags, tagName]); - setTagInputValue(""); - setTagSearchSuggestions([]); - } + const handleTagsSelected = (tags: string[]) => { + setSelectedTags(tags); }; - const handleTagRemove = (tagName: string) => { - setSelectedTags(selectedTags.filter((tag) => tag !== tagName)); + const handleMarkdownChange = (value: string | undefined) => { + setMarkdownContent(value || ""); }; - const navigation = useNavigation(); - return ( Loading...
}> {() => ( @@ -226,65 +200,49 @@ export default function EditPost() {

タグを編集する

-
-

変更前:

-
- {oldTags.map( - (tag) => - {tag} - )} -
-
+
+

変更前:

+
+ {oldTags.map((tag) => ( + + {tag} + + ))} +
+
-
- -
- {tagSearchSuggestions.length > 0 && ( -
    - {tagSearchSuggestions.map((tag) => ( -
  • handleTagSelect(tag.tagName)} - > - {tag.tagName} ({tag.count}) -
  • - ))} -
- )} +
-

変更後:

-
- {selectedTags.map((tag) => ( - - - {tag} - - - ))} + + {tag} + + + ))} +
-

本文を編集する

@@ -295,7 +253,6 @@ export default function EditPost() { > 変更を保存する -

編集履歴

@@ -310,43 +267,43 @@ export default function EditPost() { - {editHistory && editHistory.map((edit) => ( - - {edit.postRevisionNumber} - {edit.postEditDateJst.toLocaleString()} - {edit.editorUserId.slice(0,8)} - - {diff.diffChars(edit.postTitleBeforeEdit, edit.postTitleAfterEdit).map((part, index) => { - if (part.added || part.removed) { - const start = Math.max(0, part.value.indexOf(part.value) - 50); - const end = Math.min(part.value.length, part.value.indexOf(part.value) + 50); - const excerpt = part.value.slice(start, end); - return ( - - {excerpt} - - ); - } - return null; - })} - - - {diff.diffLines(edit.postContentBeforeEdit, edit.postContentAfterEdit).map((part, index) => { - if (part.added || part.removed) { - const start = Math.max(0, part.value.indexOf(part.value) - 50); - const end = Math.min(part.value.length, part.value.indexOf(part.value) + 50); - const excerpt = part.value.slice(start, end); - return ( - - {excerpt} - - ); - } - return null; - })} - - - ))} + {editHistory && editHistory.map((edit) => ( + + {edit.postRevisionNumber} + {edit.postEditDateJst.toLocaleString()} + {edit.editorUserId.slice(0,8)} + + {diff.diffChars(edit.postTitleBeforeEdit, edit.postTitleAfterEdit).map((part: diff.Change, index: number) => { + if (part.added || part.removed) { + const start = Math.max(0, part.value.indexOf(part.value) - 50); + const end = Math.min(part.value.length, part.value.indexOf(part.value) + 50); + const excerpt = part.value.slice(start, end); + return ( + + {excerpt} + + ); + } + return null; + })} + + + {diff.diffLines(edit.postContentBeforeEdit, edit.postContentAfterEdit).map((part: diff.Change, index: number) => { + if (part.added || part.removed) { + const start = Math.max(0, part.value.indexOf(part.value) - 50); + const end = Math.min(part.value.length, part.value.indexOf(part.value) + 50); + const excerpt = part.value.slice(start, end); + return ( + + {excerpt} + + ); + } + return null; + })} + + + ))}
diff --git a/app/routes/_layout.signup.tsx b/app/routes/_layout.signup.tsx index fd5651aa..fc412603 100644 --- a/app/routes/_layout.signup.tsx +++ b/app/routes/_layout.signup.tsx @@ -43,7 +43,7 @@ export async function action({ request }: ActionFunctionArgs) { }, }); } catch (error) { - return json({ status: 500, message: "ユーザー登録に失敗しました" }); + throw new Error(`Failed to create user profile: ${error}`); } return redirect("/email"); diff --git a/package-lock.json b/package-lock.json index 6916c184..8132e711 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "@axe-core/playwright": "^4.9.0", "@playwright/test": "^1.42.1", "@remix-run/dev": "^2.8.1", + "@types/diff": "^5.2.0", "@types/marked": "^6.0.0", "@types/node": "^20.11.30", "@types/react": "^18.2.20", @@ -2237,6 +2238,12 @@ "@types/ms": "*" } }, + "node_modules/@types/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-pjJH+02ukgJRW0mViDUA1cdC+wzSgRu0e4cPuogPLAw0i66y62iMP0ZlXoJAmoXrKRZnF3pMDwyKZsgNVlMX4A==", + "dev": true + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", diff --git a/package.json b/package.json index 99d3b3e5..73f3f28c 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "@axe-core/playwright": "^4.9.0", "@playwright/test": "^1.42.1", "@remix-run/dev": "^2.8.1", + "@types/diff": "^5.2.0", "@types/marked": "^6.0.0", "@types/node": "^20.11.30", "@types/react": "^18.2.20",