From 2e2efee85bea5c78a6ab563e8d29478fd2e6173e Mon Sep 17 00:00:00 2001 From: kirk1027 Date: Wed, 10 Jan 2024 13:53:52 +0900 Subject: [PATCH] =?UTF-8?q?=E9=96=B2=E8=A6=A7=E3=83=A2=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=82=92=E4=BD=9C=E3=82=8A=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 22 +++++++++++++++++ package.json | 2 ++ src/App.tsx | 2 ++ src/pages/Memo.tsx | 7 ++---- src/pages/MemoList.tsx | 32 +++++++++++++++--------- src/services/ViewMemo.tsx | 51 +++++++++++++++++++++++++++++++++++++++ src/services/check.css | 15 ++++++++++++ tsconfig.json | 2 ++ 8 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 src/services/ViewMemo.tsx create mode 100644 src/services/check.css diff --git a/package-lock.json b/package-lock.json index 3a24c08..4aa9466 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@mui/icons-material": "^5.14.11", "@mui/material": "^5.14.10", "create-vite": "^5.0.0", + "dompurify": "^3.0.8", "firebase": "^10.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -24,6 +25,7 @@ "vite-plugin-svgr": "^4.2.0" }, "devDependencies": { + "@types/dompurify": "^3.0.5", "@types/jest": "^29.5.11", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", @@ -2426,6 +2428,15 @@ "@types/ms": "*" } }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -2586,6 +2597,12 @@ "@testing-library/jest-dom": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true + }, "node_modules/@types/unist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", @@ -3386,6 +3403,11 @@ "csstype": "^3.0.2" } }, + "node_modules/dompurify": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.8.tgz", + "integrity": "sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==" + }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", diff --git a/package.json b/package.json index b65c738..cc45536 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@mui/icons-material": "^5.14.11", "@mui/material": "^5.14.10", "create-vite": "^5.0.0", + "dompurify": "^3.0.8", "firebase": "^10.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -26,6 +27,7 @@ "vite-plugin-svgr": "^4.2.0" }, "devDependencies": { + "@types/dompurify": "^3.0.5", "@types/jest": "^29.5.11", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", diff --git a/src/App.tsx b/src/App.tsx index ad77ad7..08d86cd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import Sidebar from "./pages/Sidebar"; import MenuIcon from "@mui/icons-material/Menu"; import { IconButton } from "@mui/material"; import { useState } from "react"; +import { ViewMemo } from "./services/ViewMemo"; function App() { @@ -31,6 +32,7 @@ function App() { } /> } /> } /> + } /> diff --git a/src/pages/Memo.tsx b/src/pages/Memo.tsx index 81c8c67..a58bab5 100644 --- a/src/pages/Memo.tsx +++ b/src/pages/Memo.tsx @@ -2,7 +2,6 @@ import { Box, Button, Grid, TextField, Typography } from "@mui/material"; import { userAtom } from "../states/userAtom"; import { useRecoilState, useSetRecoilState } from "recoil"; import { saveMemo } from "../services/saveMemo"; - import { messageAtom } from "../states/messageAtom"; import { useNavigate, useParams } from "react-router-dom"; import { searchMemoById } from "../services/searchMemo"; @@ -10,7 +9,7 @@ import { exceptionMessage, successMessage } from "../utils/messages"; import ReactQuill from 'react-quill'; import 'react-quill/dist/quill.snow.css'; import './toolbar.css'; -import React, { useEffect, useState } from 'react';//suzu +import { useEffect, useState } from 'react';//suzu import { WithContext as ReactTags } from 'react-tag-input';//suzu @@ -117,8 +116,6 @@ export function Memo(): JSX.Element { get(); }, [id, loginUser, setMessageAtom]); - - return ( <> @@ -144,7 +141,7 @@ export function Memo(): JSX.Element { Content - { - setSelectedMemoId(memo.id); - setOpenDialog(true); - }} - > - - + <> + {/* 新しい閲覧アイコンボタン */} + memo.id && navigate(`/view/${memo.id}`)} + > + + + { + setSelectedMemoId(memo.id); + setOpenDialog(true); + }} + > + + + } > );})} - + setOpenDialog(false)} diff --git a/src/services/ViewMemo.tsx b/src/services/ViewMemo.tsx new file mode 100644 index 0000000..d02478a --- /dev/null +++ b/src/services/ViewMemo.tsx @@ -0,0 +1,51 @@ +import { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { Box, Typography } from "@mui/material"; +import { searchMemoById } from "../services/searchMemo"; +import { useRecoilValue } from 'recoil'; +import { userAtom } from '../states/userAtom'; +import { Memo } from "../services/memoType"; +import DOMPurify from 'dompurify'; +import 'react-quill/dist/quill.snow.css'; +import './check.css'; + +export function ViewMemo(): JSX.Element { + const { id } = useParams(); + const loginUser = useRecoilValue(userAtom); + const [memo, setMemo] = useState(null); + const safeContent = memo ? DOMPurify.sanitize(memo.content) : ""; + + useEffect(() => { + const fetchMemo = async () => { + if (id && loginUser.userId) { + try { + const fetchedMemo = await searchMemoById(id, loginUser); + if (fetchedMemo) { + setMemo(fetchedMemo); + } else { + setMemo(null); + } + } catch (error) { + console.error("Error fetching memo:", error); + setMemo(null); + } + } + }; + + fetchMemo(); + }, [id, loginUser]); + + if (!memo) { + return Loading...; + } + + return ( + + {memo.title} + +
+ {/* タグや作成日時など、他の情報もここに表示できるよ */} + + + ); +} diff --git a/src/services/check.css b/src/services/check.css new file mode 100644 index 0000000..d2de171 --- /dev/null +++ b/src/services/check.css @@ -0,0 +1,15 @@ +ul[data-checked="true"] li::before { + content: '✔'; /* チェックマーク */ + color: green; /* 色を緑に */ + margin-right: 0.5em; /* 右にマージンを設定 */ + } + + ul[data-checked="false"] li::before { + content: '✘'; /* バツマーク */ + color: red; /* 色を赤に */ + margin-right: 0.5em; /* 右にマージンを設定 */ + } + + + + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index e66aefc..fc6d7d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,8 @@ "module": "ESNext", "skipLibCheck": true, "types": [ "node", "jest", "@testing-library/jest-dom", "vite-plugin-svgr/client"], + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, /* Bundler mode */ "moduleResolution": "node",