add: tree / search
This commit is contained in:
@@ -3,23 +3,15 @@ import PathNode from "./PathNode";
|
||||
import "./SideNavigation.css";
|
||||
import {useDeletePath, usePaths, useUpdatePath} from "../../utils/path-queries";
|
||||
import React from 'react';
|
||||
import {useSearchMarkdown} from "../../utils/markdown-queries";
|
||||
import MarkdownNode from "./MarkdownNode";
|
||||
import {useTree} from "../../utils/tree-queries";
|
||||
|
||||
const SideNavigation = () => {
|
||||
const {data: paths, isLoading, error } = usePaths(1);
|
||||
const {data: tree, isLoading, error} = useTree();
|
||||
const deletePath = useDeletePath();
|
||||
const updatePath = useUpdatePath();
|
||||
const [searchTerm, setSearchTerm] = React.useState("");
|
||||
const [keyword, setKeyword] = React.useState("");
|
||||
const [searchMode, setSearchMode] = React.useState(false);
|
||||
|
||||
const {data: searchResults, isLoading: isSearching} = useSearchMarkdown(keyword, {
|
||||
enabled: searchMode && !!searchMode,
|
||||
});
|
||||
const sortedPaths = paths
|
||||
? paths.slice().sort((a, b) => a.order.localeCompare(b.order))
|
||||
: [];
|
||||
const handleDelete = (id) => {
|
||||
if (window.confirm("Are you sure you want to delete this path?")){
|
||||
deletePath.mutate(id, {
|
||||
@@ -30,13 +22,30 @@ const SideNavigation = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
setSearchMode(true);
|
||||
setKeyword(searchTerm);
|
||||
}
|
||||
const exitSearch = () => {
|
||||
setSearchMode(false);
|
||||
}
|
||||
|
||||
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 }} , {
|
||||
@@ -45,55 +54,17 @@ const SideNavigation = () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
if(!searchMode && isLoading){
|
||||
return <aside className="menu"><p>Loading...</p></aside>;
|
||||
}
|
||||
if(searchMode && isSearching){
|
||||
return <aside className="menu"><p>Loading...</p></aside>;
|
||||
}
|
||||
if(error){
|
||||
return <aside className="menu"><p>Error...</p></aside>;
|
||||
}
|
||||
|
||||
|
||||
if (isLoading) return <aside className="menu"><p>Loading...</p></aside>;
|
||||
if (error) return <aside className="menu"><p>Error loading tree</p></aside>;
|
||||
return (
|
||||
<aside className="menu">
|
||||
<div className="field has-addons mb-2">
|
||||
<div className="control is-expanded">
|
||||
<input
|
||||
className="input is-small"
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="control">
|
||||
<button
|
||||
className="button is-small is-info"
|
||||
onClick={handleSearch}
|
||||
disabled={!searchTerm.trim()}
|
||||
type="button"
|
||||
>
|
||||
<span className="icon">
|
||||
<i className="fa fa-search"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{searchMode && (
|
||||
<div className="control">
|
||||
<button
|
||||
className="button is-small is-danger"
|
||||
onClick={exitSearch}
|
||||
type="button"
|
||||
>
|
||||
<span className="icon">
|
||||
<i className={"fa fa-window-close"}></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<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
|
||||
@@ -103,29 +74,17 @@ const SideNavigation = () => {
|
||||
Create New Markdown
|
||||
</a>
|
||||
</PermissionGuard>
|
||||
{searchMode ? (
|
||||
<ul>
|
||||
{searchResults.map((markdown, i) => (
|
||||
<MarkdownNode
|
||||
markdown={markdown}
|
||||
handleMoveMarkdown={() => {}}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<ul className="menu-list">
|
||||
{isLoading && <p>Loading...</p>}
|
||||
{sortedPaths.map((path) => (
|
||||
<PathNode
|
||||
key={path.id}
|
||||
path={path}
|
||||
isRoot={false}
|
||||
onSave={handleSave}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{!filteredTree || filteredTree.length === 0 ?
|
||||
<p>No Result</p> :
|
||||
<PathNode
|
||||
key={1}
|
||||
path={filteredTree}
|
||||
isRoot={true}
|
||||
onSave={handleSave}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
}
|
||||
|
||||
|
||||
</aside>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user