Markdwon形式のメモ管理(複数管理 第五回)
「Markdwon形式のメモ管理」の第五回目です。
今回で、Markdwon形式のメモ管理の機能は作り終えたいと思います。
今回はデータの登録、更新について紹介します。
前回の内容は以下を参照してください。
今回の手順は以下のとおりです。
Flaskのapp.py改修
Flaskのapp.pyを改修します。
コードは以下のとおりです。
import os
from flask import Flask, request
from flask_cors import CORS
import pymysql.cursors
import json
RESULT_CODE_SUCESS = 'sucess'
app = Flask(__name__)
CORS(app)
def db_connection():
conn = pymysql.connect(
host='db',
port=3306,
user=os.environ.get('MYSQL_USER'),
password=os.environ.get('MYSQL_PASSWORD'),
db=os.environ.get('MYSQL_DATABASE'),
cursorclass=pymysql.cursors.DictCursor
)
return conn
@app.route("/", methods=["GET"])
def test():
return "Hello World"
RESULT_CODE_SUCESS
@app.route('/mariadb')
def mariadb():
conn = db_connection()
with conn.cursor() as cur:
sql = "SELECT * FROM user"
cur.execute(sql)
results = cur.fetchall()
return results[0]
@app.route('/markdown', methods=["POST"])
def post_markdown():
url = request.json["url"]
title = request.json["title"]
body = request.json["body"]
conn = db_connection()
with conn.cursor() as cur:
cur.execute(
f"INSERT INTO markdown (url, title, body) values('{url}','{title}','{body}')")
conn.commit()
return RESULT_CODE_SUCESS
@app.route('/markdown<path:path>', methods=["PUT"])
def put_markdown(path):
title = request.json["title"]
body = request.json["body"]
conn = db_connection()
with conn.cursor() as cur:
cur.execute(
f"UPDATE markdown SET title = '{title}', body = '{body}' WHERE url = '{path}' ")
conn.commit()
return RESULT_CODE_SUCESS
@app.route('/markdown', methods=["GET"])
def get_markdown():
conn = db_connection()
with conn.cursor() as cur:
cur.execute(f"SELECT * FROM test.markdown")
results = cur.fetchall()
return json.dumps(results, indent=2)
@app.route('/markdown/<path:path>', methods=["GET"])
def get_markdown_url(path):
conn = db_connection()
with conn.cursor() as cur:
cur.execute(f"SELECT * FROM markdown WHERE url = '{path}'")
results = cur.fetchall()
if not results:
return json.dumps({}, indent=2)
return json.dumps(results[0], indent=2)
db_connectionの関数を用意しました。
conn.cursorでwithを使うようにしました。 withは処理終了時にconnを暗黙的にcloseします。
ファイル操作によく使用されます。
post_markdownとput_markdownがメインの処理になります。
それぞれのAPIは以下のようになります。
Markdownデータ登録用API
URL | /markdown |
---|---|
メソッド | POST |
フォーマット | JSON |
パラメータ | {'url': 'test/test1', 'title' : 'TEST', 'body' : '# TEST'} |
Markdownデータ更新用API
URL | /markdown/{url} |
---|---|
メソッド | PUT |
フォーマット | JSON |
パラメータ | {'url': 'test/test1', 'title' : 'TEST', 'body' : '# TEST'} |
更新はurlの内容と一致するデータを更新します。
SubHeaderNavigation改修
サブヘッダーナビゲーションに登録、更新用のボタンを配置します。
import { useEffect } from "react";
import axios from "axios";
import {
BottomNavigation,
BottomNavigationAction,
Box,
TextField,
Toolbar,
Typography,
} from "@mui/material";
import EditIcon from '@mui/icons-material/Edit';
import PageviewIcon from '@mui/icons-material/Pageview';
import SaveIcon from '@mui/icons-material/Save';
export default function SubHeaderNavigation(props) {
const { markdown, setMarkdown, editMode, onClickMode } = props;
const onClickSaveMarkdown = () => {
axios.post(`http://localhost:5000/markdown`, markdown)
.then(res => {
console.log(res.data);
})
};
const onClickUpdateMarkdown = () => {
axios.put(`http://localhost:5000/markdown` + markdown.url, markdown)
.then(res => {
console.log(res.data);
})
};
const onChangeURL = (event) => {
markdown.url = event.target.value;
setMarkdown(
{
url: event.target.value,
title: markdown.title,
body: markdown.body
});
};
const onChangeTitle = (event) => {
setMarkdown(
{
url: markdown.url,
title: event.target.value,
body: markdown.body
});
};
useEffect(() => {
}, [markdown.url, markdown.title]);
return (
<Box>
<Toolbar sx={{ backgroundColor: "#1976d2", display: "flex", justifyContent: "space-between" }}>
{editMode ? <TextField label="URL" value={markdown.url} onChange={onChangeURL}></TextField> : <Typography>{markdown.url}</Typography>}
{editMode ? <TextField label="TITLE" value={markdown.title} onChange={onChangeTitle}></TextField> : <Typography>{markdown.title}</Typography>}
<BottomNavigation showLabels sx={{ backgroundColor: "#1976d2" }}>
{editMode ?
[<BottomNavigationAction label="表示" icon={<PageviewIcon />} onClick={onClickMode} />,
<BottomNavigationAction label="新規登録" icon={<SaveIcon />} onClick={onClickSaveMarkdown} />,
<BottomNavigationAction label="更新" icon={<SaveIcon />} onClick={onClickUpdateMarkdown} />].map((component) => component)
:
<BottomNavigationAction label="編集" icon={<EditIcon />} onClick={onClickMode} />
}
</BottomNavigation>
</Toolbar>
</Box>
);
}
新規登録と更新ボタンを配置しました。
今後見直しは必要ですが、まずは、動作できるものをつくるために簡易的に実装しています。
各ボタンをクリックしたときのAPIの呼び出しも行っています。
こちらも登録、更新成功時のメッセージについて今後検討を行います。
Page1Page改修
Page1Pageを改修します。
こちらは、DBに登録されていないデータを取得したときに、新規登録の編集画面に遷移するような改修になります。
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 => {
if (!Object.keys(res.data).length) {
setMarkdown(
{
url: location.pathname,
title: '',
body: ''
});
setEditMode(true);
} else {
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>
);
}
データ取得APIを使ってデータを取得した際に、データがないときに、useStateのsetMarkdownに空のデータをセットします。
ただし、urlはurlパスをそのまま設定しています。
また、useStateのsetEditModeにtrue(編集モード)を設定します。
・・・略・・・
useEffect(() => {
axios.get("http://localhost:5000/markdown" + location.pathname)
.then(res => {
if (!Object.keys(res.data).length) {
setMarkdown(
{
url: location.pathname,
title: '',
body: ''
});
setEditMode(true);
} else {
setMarkdown(res.data);
}
})
}, [])
・・・略・・・
画面確認
docker-compose upを使って各コンテナを起動します。
docker-compose.ymlファイルがある場所で以下のコマンドを実行します。
docker-compose up
起動したら以下のURLをブラウザに入力します。
http://localhost:3000
以下ブラウザの表示です。
編集画面
テキストを修正することができます。また、登録、更新ボタンを押下できます。
urlが存在しない場合も編集画面が表示されて、urlの入力ができるようになりました。
まとめ
編集画面のデータ登録、更新をおこなえるようにしました。
細かい処理はのこっていますが、Markdownのデータの複数データ管理ができるようになりました。
0 件のコメント:
コメントを投稿
コメントをお待ちしています。