markdown editor

This commit is contained in:
h z
2024-12-04 16:53:35 +00:00
parent 55ddd17bf0
commit 413896c54b
9 changed files with 155 additions and 24 deletions

View File

@@ -0,0 +1,97 @@
import React, {useContext, useEffect, useState} from "react";
import {AuthContext} from "../../AuthProvider";
import {useNavigate, useParams} from "react-router-dom";
import {fetchWithCache} from "../../utils/fetchWithCache";
const MarkdownEditor = () => {
const {roles} = useContext(AuthContext);
const navigate = useNavigate();
const {id} = useParams()
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [path, setPath] = useState("");
useEffect(() => {
if(id){
fetchWithCache(`/api/markdown/${id}`)
.then((data) => {
setTitle(data.title);
setContent(data.content);
setPath(data.path);
})
.catch((err) => {console.error("failed to load markdown", err)});
}
}, [id]);
const handleSave = () => {
const url = id ? `/api/markdown/${id}` : "/api/markdown";
const method = id ? "PUT" : "POST";
fetch (url, {
method,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("accessToken")}`,
},
body: JSON.stringify({title, content, path}),
})
.then((res) => {
if (res.ok) {
navigate("/");
}else {
return res.json().then((data) => {
throw new Error(data.error || "Failed to save markdown");
})
}
})
.catch((err) => {console.error("failed to load markdown", err)});
};
const hasPermission = roles.includes("admin") || roles.includes("creator");
if(! hasPermission)
return (
<div> Can not crete(Permission Denied)</div>
);
return (
<div>
<h2>{id ? "Edit Markdown" : "Create Markdown"}</h2>
<form>
<div>
<label>
Title:
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</label>
</div>
<div>
<label>
Path:
<input
type="text"
value={path}
onChange={(e) => setPath(e.target.value)}
/>
</label>
</div>
<div>
<label>
Content:
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
/>
</label>
</div>
<button type="button" onClick={handleSave}>
Save
</button>
</form>
</div>
);
}
export default MarkdownEditor;

View File

@@ -3,7 +3,7 @@
import React, {useContext} from "react";
import { Link } from "react-router-dom";
import "./MainNavigation.css";
import {AuthContext} from "../AuthProvider";
import {AuthContext} from "../../AuthProvider";
const MainNavigation = () => {
const { user, login, logout } = useContext(AuthContext);

View File

@@ -3,7 +3,8 @@
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import "./SideNavigation.css";
import {fetchWithCache} from "../utils/fetchWithCache";
import {fetchWithCache} from "../../utils/fetchWithCache";
import PermissionGuard from "../PermissionGuard";
const SideNavigation = () => {
const [markdowns, setMarkdowns] = useState([]);
@@ -40,6 +41,12 @@ const SideNavigation = () => {
function renderTree(node, basePath = "") {
return (
<ul>
<li>
<PermissionGuard rolesRequired={["admin", "creator"]} >
<Link to="/markdown/create">Create New Markdown</Link>
</PermissionGuard>
</li>
{Object.entries(node).map(([key, value]) => {
if (value.markdown) {
return (
@@ -63,7 +70,7 @@ const SideNavigation = () => {
return (
<nav className="side-navigation">
<h3>Markdown Directory</h3>
<h3>Markdown Directory</h3>
{tree ? renderTree(tree) : <p>Loading...</p>}
</nav>
);

View File

@@ -0,0 +1,15 @@
import {useContext} from "react";
import {AuthContext} from "../AuthProvider";
const PermissionGuard = ({rolesRequired, children}) => {
const { roles = [] } = useContext(AuthContext);
const hasPermission = rolesRequired.some((role) => roles.includes(role));
if (!hasPermission) {
console.log("F");
return null;
}
return children;
}
export default PermissionGuard;