* fix tree root element ref
* fix tree node toggle bug
* fix tree node reparenting on the backend
* highlight active home menu on the sidebar
This commit is contained in:
Philipinho
2024-05-20 01:08:31 +01:00
parent 6287f41ef6
commit b06a78b6ec
8 changed files with 85 additions and 42 deletions

View File

@ -85,3 +85,8 @@
color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0));
}
}
.activeButton {
background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6));
color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0));
}

View File

@ -20,25 +20,28 @@ import React from "react";
import { useAtom } from "jotai";
import { SearchSpotlight } from "@/features/search/search-spotlight";
import { treeApiAtom } from "@/features/page/tree/atoms/tree-api-atom";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import SpaceContent from "@/features/page/tree/components/space-content.tsx";
import clsx from "clsx";
import APP_ROUTE from "@/lib/app-route.ts";
interface PrimaryMenuItem {
icon: React.ElementType;
label: string;
path?: string;
onClick?: () => void;
}
const primaryMenu: PrimaryMenuItem[] = [
{ icon: IconHome, label: "Home" },
{ icon: IconHome, label: "Home", path: "/home" },
{ icon: IconSearch, label: "Search" },
{ icon: IconSettings, label: "Settings" },
// { icon: IconFilePlus, label: 'New Page' },
];
export function Navbar() {
const [tree] = useAtom(treeApiAtom);
const navigate = useNavigate();
const location = useLocation();
const handleMenuItemClick = (label: string) => {
if (label === "Home") {
@ -61,7 +64,12 @@ export function Navbar() {
const primaryMenuItems = primaryMenu.map((menuItem) => (
<UnstyledButton
key={menuItem.label}
className={classes.menu}
className={clsx(
classes.menu,
location.pathname.toLowerCase() === menuItem?.path
? classes.activeButton
: "",
)}
onClick={() => handleMenuItemClick(menuItem.label)}
>
<div className={classes.menuItemInner}>

View File

@ -8,7 +8,7 @@ import {
useUpdatePageMutation,
} from "@/features/page/queries/page-query.ts";
import React, { useEffect, useRef } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import classes from "@/features/page/tree/styles/tree.module.css";
import { ActionIcon, Menu, rem, Text } from "@mantine/core";
import {
@ -45,6 +45,7 @@ import { useQueryEmit } from "@/features/websocket/use-query-emit.ts";
import { buildPageSlug } from "@/features/page/page.utils.ts";
import { notifications } from "@mantine/notifications";
import { modals } from "@mantine/modals";
import APP_ROUTE from "@/lib/app-route.ts";
interface SpaceTreeProps {
spaceId: string;
@ -72,6 +73,7 @@ export default function SpaceTree({ spaceId }: SpaceTreeProps) {
const mergedRef = useMergedRef(rootElement, sizeRef);
const isDataLoaded = useRef(false);
const { data: currentPage } = usePageQuery(slugId);
const location = useLocation();
useEffect(() => {
if (hasNextPage && !isFetching) {
@ -166,7 +168,7 @@ export default function SpaceTree({ spaceId }: SpaceTreeProps) {
if (currentPage) {
setTimeout(() => {
treeApiRef.current?.select(currentPage.id, { align: "auto" });
}, 200);
}, 100);
}
}, [currentPage?.id]);
@ -175,35 +177,38 @@ export default function SpaceTree({ spaceId }: SpaceTreeProps) {
// @ts-ignore
setTreeApi(treeApiRef.current);
}
}, []);
}, [treeApiRef.current]);
useEffect(() => {
if (openTreeNodes) {
treeApiRef.current.state.nodes.open.unfiltered = openTreeNodes;
if (location.pathname === APP_ROUTE.HOME && treeApiRef.current) {
treeApiRef.current.deselectAll();
}
}, []);
}, [location.pathname]);
return (
<div ref={mergedRef} className={classes.treeContainer}>
<Tree
data={data}
{...controllers}
width={width}
height={height}
ref={treeApiRef}
openByDefault={false}
disableMultiSelection={true}
className={classes.tree}
rowClassName={classes.row}
rowHeight={30}
overscanCount={10}
dndRootElement={rootElement.current}
onToggle={() => {
setOpenTreeNodes(treeApiRef.current.openState);
}}
>
{Node}
</Tree>
{rootElement.current && (
<Tree
data={data}
{...controllers}
width={width}
height={height}
ref={treeApiRef}
openByDefault={false}
disableMultiSelection={true}
className={classes.tree}
rowClassName={classes.row}
rowHeight={30}
overscanCount={10}
dndRootElement={rootElement.current}
onToggle={() => {
setOpenTreeNodes(treeApiRef.current.openState);
}}
initialOpenState={openTreeNodes}
>
{Node}
</Tree>
)}
</div>
);
}
@ -288,10 +293,16 @@ function Node({ node, style, dragHandle, tree }: NodeRendererProps<any>) {
}, 50);
};
if (node.willReceiveDrop && node.isClosed) {
if (
node.willReceiveDrop &&
node.isClosed &&
(node.children.length > 0 || node.data.hasChildren)
) {
handleLoadChildren(node);
setTimeout(() => {
if (node.state.willReceiveDrop) node.open();
if (node.state.willReceiveDrop) {
node.open();
}
}, 650);
}

View File

@ -124,6 +124,25 @@ export function useTreeMutation<T>(spaceId: string) {
changes: { position: newPosition } as any,
});
const previousParent = args.dragNodes[0].parent;
if (
previousParent.id !== args.parentId &&
previousParent.id !== "__REACT_ARBORIST_INTERNAL_ROOT__"
) {
// if the page was moved to another parent,
// check if the previous still has children
// if no children left, change 'hasChildren' to false, to make the page toggle arrows work properly
const childrenCount = previousParent.children.filter(
(child) => child.id !== draggedNodeId,
).length;
if (childrenCount === 0) {
tree.update({
id: previousParent.id,
changes: { ...previousParent.data, hasChildren: false } as any,
});
}
}
setData(tree.data);
const payload: IMovePage = {

View File

@ -1,6 +1,6 @@
import axios, { AxiosInstance } from "axios";
import Cookies from "js-cookie";
import Routes from "@/lib/routes";
import Routes from "@/lib/app-route.ts";
const baseUrl = import.meta.env.DEV ? "http://localhost:3000" : "";
const api: AxiosInstance = axios.create({

View File

@ -0,0 +1,9 @@
const APP_ROUTE = {
HOME: "/home",
AUTH: {
LOGIN: "/login",
SIGNUP: "/signup",
},
};
export default APP_ROUTE;

View File

@ -1,9 +0,0 @@
const ROUTES = {
HOME: '/home',
AUTH: {
LOGIN: '/login',
SIGNUP: '/signup',
},
};
export default ROUTES;

View File

@ -184,7 +184,7 @@ export class PageService {
throw new BadRequestException('Invalid move position');
}
let parentPageId: string;
let parentPageId = null;
if (movedPage.parentPageId === dto.parentPageId) {
parentPageId = undefined;
} else {