add: markdown permission setting
improve: template
This commit is contained in:
62
src/components/Navigations/SideTabs/TemplateTab.js
Normal file
62
src/components/Navigations/SideTabs/TemplateTab.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import React, { useState } from "react";
|
||||
import { useMarkdownTemplates } from "../../../utils/queries/markdown-template-queries";
|
||||
import PermissionGuard from "../../PermissionGuard";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const TemplateTab = () => {
|
||||
const { data: templates, isLoading, error } = useMarkdownTemplates();
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const navigate = useNavigate();
|
||||
|
||||
const filteredTemplates = templates?.filter(template =>
|
||||
template.title.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
|
||||
const handleTemplateClick = (templateId) => {
|
||||
navigate(`/template/edit/${templateId}`);
|
||||
};
|
||||
|
||||
if (isLoading) return <p>Loading...</p>;
|
||||
if (error) return <p>Error loading templates</p>;
|
||||
|
||||
return (
|
||||
<aside className="menu">
|
||||
<div className="control is-expanded">
|
||||
<input
|
||||
className="input is-small"
|
||||
type="text"
|
||||
placeholder="Search templates..."
|
||||
onChange={(e) => setKeyword(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<PermissionGuard rolesRequired={["admin", "creator"]}>
|
||||
<a
|
||||
href="/template/create"
|
||||
className="button is-primary is-small is-fullwidth"
|
||||
style={{ marginBottom: "10px" }}
|
||||
>
|
||||
Create New Template
|
||||
</a>
|
||||
</PermissionGuard>
|
||||
|
||||
{!filteredTemplates || filteredTemplates.length === 0 ? (
|
||||
<p>No templates found</p>
|
||||
) : (
|
||||
<div className="template-list">
|
||||
{filteredTemplates.map(template => (
|
||||
<button
|
||||
key={template.id}
|
||||
className="button is-light is-fullwidth template-button"
|
||||
onClick={() => handleTemplateClick(template.id)}
|
||||
style={{ marginBottom: "5px", textAlign: "left", justifyContent: "flex-start" }}
|
||||
>
|
||||
{template.title}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default TemplateTab;
|
||||
88
src/components/Navigations/SideTabs/TreeTab.js
Normal file
88
src/components/Navigations/SideTabs/TreeTab.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import PermissionGuard from "../../PermissionGuard";
|
||||
import PathNode from "../PathNode";
|
||||
import React from "react";
|
||||
import {useTree} from "../../../utils/queries/tree-queries";
|
||||
import {useDeletePath, useUpdatePath} from "../../../utils/queries/path-queries";
|
||||
|
||||
const TreeTab = () => {
|
||||
const {data: tree, isLoading, error} = useTree();
|
||||
const deletePath = useDeletePath();
|
||||
const updatePath = useUpdatePath();
|
||||
const [keyword, setKeyword] = React.useState("");
|
||||
const handleDelete = (id) => {
|
||||
if (window.confirm("Are you sure you want to delete this path?")){
|
||||
deletePath.mutate(id, {
|
||||
onError: (err) => {
|
||||
alert("Failed to delete path");
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const filterTree = (t, k) => {
|
||||
if(t === undefined)
|
||||
return undefined;
|
||||
if (t.type === "path") {
|
||||
if (t.name.includes(k)) {
|
||||
return { ...t };
|
||||
}
|
||||
const filteredChildren = (t.children || [])
|
||||
.map(c => filterTree(c, k))
|
||||
.filter(Boolean);
|
||||
|
||||
if (filteredChildren.length > 0) {
|
||||
return { ...t, children: filteredChildren };
|
||||
}
|
||||
} else if (t.type === "markdown") {
|
||||
if (t.title.includes(k)) {
|
||||
return { ...t };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const filteredTree = filterTree(tree, keyword);
|
||||
|
||||
const handleSave = (id, newName) => {
|
||||
updatePath.mutate({ id, data: {name: newName }} , {
|
||||
onError: (err) => {
|
||||
alert("Failed to update path");
|
||||
}
|
||||
});
|
||||
};
|
||||
if (isLoading) return <p>Loading...</p>;
|
||||
if (error) return <p>Error loading tree</p>;
|
||||
return (
|
||||
<aside className="menu">
|
||||
|
||||
<div className="control is-expanded">
|
||||
<input
|
||||
className="input is-small"
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
onChange={(e) => setKeyword(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<PermissionGuard rolesRequired={["admin", "creator"]}>
|
||||
<a
|
||||
href="/markdown/create"
|
||||
className="button is-primary is-small"
|
||||
>
|
||||
Create New Markdown
|
||||
</a>
|
||||
</PermissionGuard>
|
||||
{!filteredTree || filteredTree.length === 0 ?
|
||||
<p>No Result</p> :
|
||||
<PathNode
|
||||
key={1}
|
||||
path={filteredTree}
|
||||
isRoot={true}
|
||||
onSave={handleSave}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
}
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default TreeTab;
|
||||
Reference in New Issue
Block a user