Markdwon形式のメモ管理(複数管理 第三回)

データ管理

「Markdwon形式のメモ管理」の第三回目です。

前回は、ホームページでMarkdownのデータを複数取得し、その中から選択したMarkdownのデータを表示するページを作成しました。

今回は表示のページで表示と編集(エディット)を切り替えて画面を表示できるようにします。

前回の内容は以下を参照してください。

Markdwon形式のメモ管理(複数管理 第ニ回)

今回の手順は以下のとおりです。

Page1Page改修

Page1Pageを改修します。

表示とエディットで分けていたページを一つにします。

Material-UI(MUI)のテーマThemeProviderをテンプレートから移動しました。

このためデータ取得用のAPIをこのファイルに移動します。

また、表示用と編集用のモードの管理と、Markdownのデータを保持をuseStateを使います。

モードによってテンプレートの切り替えを行います。

    
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import axios from "axios";

import { createTheme, ThemeProvider } from "@mui/material";

import MarkDownTemplate from "../template/MarkdownTemplate";
import EditTemplate from "../template/EditTemplate";

export default function Page1Page() {

  const darkTheme = createTheme({
    palette: {
      mode: "dark",
      primary: {
        main: "#1976d2"
      }
    }
  });

  const [markdown, setMarkdown] = useState([]);
  const [editMode, setEditMode] = useState(false);

  const location = useLocation();

  useEffect(() => {
    axios.get("http://localhost:5000/markdown" + location.pathname)
      .then(res => {
        setMarkdown(res.data);
      })
  }, [])

  const onClickMode = () => { setEditMode(!editMode) }

  console.log('MODE' + editMode);
  return (
    <ThemeProvider theme={darkTheme}>
      {editMode ?
        <EditTemplate markdown={markdown} setMarkdown={setMarkdown} editMode={editMode} onClickMode={onClickMode} /> :
        <MarkDownTemplate markdown={markdown} setMarkdown={setMarkdown} editMode={editMode} onClickMode={onClickMode} />}
    </ThemeProvider>
  );
}
    
  

MarkdownTemplate改修

MarkdownTemplate改修を改修します。

    
import ReactMarkdown from "react-markdown";
import remarkGfm from 'remark-gfm';

import {
  AppBar,
  Box,
  Container,
  Drawer,
} from "@mui/material";

import HeaderNavigation from "../organisms/HeaderNavigation";
import SubHeaderNavigation from "../organisms/SubHeaderNavigation";

export default function MarkDownTemplate(props) {
  const {markdown, setMarkdown, editMode, onClickMode} = props;
  return (
    <Box
      sx={{
        display: "flex",
        flexDirection: "column",
        height: "100vh"
      }}
    >
      <HeaderNavigation />
      <SubHeaderNavigation markdown={markdown} setMarkdown={setMarkdown} editMode={editMode} onClickMode={onClickMode} />
      <Drawer></Drawer>
      <Box component="main" >
        <Box
          sx={{
            display: "flex",
            flexDirection: "row"
          }}
        >
          <Container maxWidth="xl">
            <ReactMarkdown remarkPlugins={[remarkGfm]} styled={{ width: "100%" }}>{markdown.body}</ReactMarkdown>
          </Container >
        </Box>
      </Box>
    </Box>
  );
}
    
  

SubHeaderNavigationの部品を新しく作成しました。

propsを引数で受け取ることで呼出し側(親コンポーネント)から引数を受け取ります。

サブナビゲーションの部品化

サブナビゲーションの部品化します。

ファイル作成

「organisms」配下に「HeaderNavigation」ファイルをを作成します。

    
project/
  web/
    Dockerfile
    src/
      react-project/
        src/
          organisms/
         ┃ ┣ HeaderNavigation.js
         ┃ ┗ SubHeaderNavigation.js
          pages/
         ┃ ┣ HomePage.js
         ┃ ┣ Page1Page.js
         ┃ ┗ P1ge2Page.js
          template/
         ┃ ┗ HomeTemplate.js
         ┃ ┗ MarkdownTemplate.js
         ┃ ┗ EditTemplate.js
          component/
          App.js
    
  

以上でディレクトリとファイルの作成は終了です。

SubHeaderNavigationのコーディング

  1. import axios from "axios";
  2. import {
  3. BottomNavigation,
  4. BottomNavigationAction,
  5. Box,
  6. Toolbar,
  7. } from "@mui/material";
  8. import EditIcon from '@mui/icons-material/Edit';
  9. import PageviewIcon from '@mui/icons-material/Pageview';
  10. export default function SubHeaderNavigation(props) {
  11. const { markdown, setMarkdown, editMode, onClickMode } = props;
  12. return (
  13. <Box>
  14. <Toolbar sx={{ backgroundColor: "#1976d2", display: "flex", justifyContent: "space-between" }}>
  15. <BottomNavigation showLabels sx={{ backgroundColor: "#1976d2" }}>
  16. {editMode ?
  17. <BottomNavigationAction label="表示" icon={<PageviewIcon />}} />
  18. :
  19. <BottomNavigationAction label="編集" icon={<EditIcon />}} />
  20. }
  21. </BottomNavigation>
  22. </Toolbar>
  23. </Box>
  24. );
  25. }

HeaderNavigationにあったページ1とページ2のアイコンボタンを移動して、表示と編集ボタンにしました。editMode(表示と編集を管理するモード)のステータスを見ながら切り替えるようにしました。

ボタンはMUIのBottomNavigationとBottomNavigationActionをつかいます。

BottomNavigationについては以下を参照してください。

BottomNavigationActionについては以下を参照してください。

以上がSubHeaderNavigationのコーディングです。

HeaderNavigationの改修

ヘッダーナビゲーションの改修内容です。

不要な記述の削除とページ2とページ2のリンクとアイコンを削除しました。

  1. import { useNavigate } from "react-router-dom"
  2. import {
  3. AppBar,
  4. BottomNavigation,
  5. BottomNavigationAction,
  6. Toolbar,
  7. Typography
  8. } from "@mui/material";
  9. import HomeIcon from '@mui/icons-material/Home';
  10. export default function HeaderNavigation() {
  11. const navigate = useNavigate();
  12. const onClickHome = () => { navigate('/') };
  13. return (
  14. <AppBar position="relative" >
  15. <Toolbar sx={{ display: "flex", justifyContent: "space-between" }}>
  16. <Typography component="div" >Markdown</Typography>
  17. <BottomNavigation showLabels>
  18. <BottomNavigationAction label="ホーム" icon={<HomeIcon />} onClick={onClickHome} />
  19. </BottomNavigation>
  20. </Toolbar>
  21. </AppBar>
  22. );
  23. }

EditTemplateの改修

EditTemplateの改修内容です。

親コンポーネントで渡されるporpsの追加をします。

今回は表示画面を中心に説明するため一時的にエディット部分はコメントアウトをします。

  1. import {
  2. AppBar,
  3. Box,
  4. createTheme,
  5. ThemeProvider,
  6. Toolbar,
  7. Container,
  8. Button
  9. } from "@mui/material";
  10. import { useState, useEffect } from "react";
  11. import ReactMarkdown from "react-markdown";
  12. import remarkGfm from 'remark-gfm';
  13. import axios from 'axios';
  14. import HeaderNavigation from "../organisms/HeaderNavigation";
  15. import EditMarkdown from "../organisms/EditMarkdown";
  16. import SaveIcon from '@mui/icons-material/Save';
  17. export default function EditTemplate(props) {
  18. const { markdown, setMarkdown, editMode, onClickMode } = props;
  19. /*
  20. const darkTheme = createTheme({
  21. palette: {
  22. mode: "dark",
  23. primary: {
  24. main: "#1976d2"
  25. }
  26. }
  27. });
  28. const [text, setText] = useState("");
  29. const onChangeText = (event) => setText(event.target.value);
  30. useEffect(() => {
  31. axios.get('http://localhost:5000/markdown')
  32. .then(res => {
  33. setText(res.data.body)
  34. })
  35. }, [])
  36. const onClickText = () => {
  37. const markdown = {
  38. body: text
  39. };
  40. axios.post(`http://localhost:5000/markdown`, markdown)
  41. .then(res => {
  42. console.log(res.data);
  43. })
  44. };
  45. return (
  46. <ThemeProvider theme={darkTheme}>
  47. <Box
  48. sx={{
  49. display: "flex",
  50. flexDirection: "column",
  51. height: "100vh"
  52. }}
  53. >
  54. <AppBar position="relative" >
  55. <HeaderNavigation />
  56. </AppBar>
  57. <Box >
  58. <Toolbar sx={{ backgroundColor: "#1976d2" }}>サブヘッダ</Toolbar>
  59. </Box>
  60. <Box component="main" >
  61. <Box
  62. sx={{
  63. display: "flex",
  64. flexDirection: "row"
  65. }}
  66. >
  67. <Box
  68. sx={{
  69. height: "100vh",
  70. width: "50%",
  71. backgroundColor: "#121212"
  72. }}
  73. >
  74. <Container >
  75. <Button variant="contained" onClick={onClickText} startIcon={<SaveIcon />}>保存</Button>
  76. <br />
  77. <EditMarkdown text={text} onChangeText={onChangeText} />
  78. </Container >
  79. </Box>
  80. <Box sx={{ width: "50%" }}>
  81. <Container >
  82. <ReactMarkdown remarkPlugins={[remarkGfm]}>{text}</ReactMarkdown>
  83. </Container >
  84. </Box>
  85. </Box>
  86. </Box>
  87. </Box>
  88. </ThemeProvider>
  89. );
  90. */
  91. return (<>TEST</>)
  92. }

HomeTemplateの改修

Homeテンプレートの改修内容です。

直接コーディングしていたサブナビゲーション部分を削除します。

最初はホーム画面にもサブナビゲーションを配置することを考えていましたが不要になり削除しました。

  1. import { useState, useEffect } from "react";
  2. import {
  3. Box,
  4. Container,
  5. createTheme,
  6. ThemeProvider,
  7. } from "@mui/material";
  8. import axios from 'axios';
  9. import HeaderNavigation from "../organisms/HeaderNavigation";
  10. import { Link } from "react-router-dom";
  11. export default function HomeTemplate() {
  12. const darkTheme = createTheme({
  13. palette: {
  14. mode: "dark",
  15. primary: {
  16. main: "#1976d2"
  17. }
  18. }
  19. });
  20. const [text, setText] = useState([]);
  21. useEffect(() => {
  22. axios.get('http://localhost:5000/markdown')
  23. .then(res => setText(res.data))
  24. }, [])
  25. return (
  26. <ThemeProvider theme={darkTheme}>
  27. <Box
  28. sx={{
  29. display: "flex",
  30. flexDirection: "column",
  31. height: "100vh"
  32. }}
  33. >
  34. <HeaderNavigation />
  35. <Box component="main" >
  36. <Container maxWidth="xl" sx={{ display: "flex", flexDirection: "column" }}>
  37. {text.map((markdown) => {
  38. return (
  39. <Link key={markdown.url} to={markdown.url}>
  40. {markdown.title}
  41. </Link>
  42. )
  43. })}
  44. </Container >
  45. </Box>
  46. </Box>
  47. </ThemeProvider>
  48. );
  49. }

画面確認

docker-compose upを使って各コンテナを起動します。

docker-compose.ymlファイルがある場所で以下のコマンドを実行します。

  1. docker-compose up

起動したら以下のURLをブラウザに入力します。

http://localhost:3000

以下ブラウザの表示です。

ホームページの画面です。ページ1とページ2のアイコンを削除しました。

また、サブナビゲーションを削除しています。

markdown-homepage

表示画面

編集ボタンを表示するようにしています。

markdown-view

まとめ

表示のページで表示と編集(エディット)を切り替える対応を行いました。

次回は編集画面について紹介します。

コメント

0 件のコメント:

コメントを投稿

コメントをお待ちしています。