fix: favorite improvements (#5307)
This commit is contained in:
parent
07574b4222
commit
a93dfc1b8d
4 changed files with 218 additions and 193 deletions
|
|
@ -111,6 +111,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
const [publishModalOpen, setPublishModal] = useState(false);
|
const [publishModalOpen, setPublishModal] = useState(false);
|
||||||
const [isMenuActive, setIsMenuActive] = useState(false);
|
const [isMenuActive, setIsMenuActive] = useState(false);
|
||||||
const [isDragging, setIsDragging] = useState(false);
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
|
const [isProjectListOpen, setIsProjectListOpen] = useState(false);
|
||||||
const [instruction, setInstruction] = useState<"DRAG_OVER" | "DRAG_BELOW" | undefined>(undefined);
|
const [instruction, setInstruction] = useState<"DRAG_OVER" | "DRAG_BELOW" | undefined>(undefined);
|
||||||
// refs
|
// refs
|
||||||
const actionSectionRef = useRef<HTMLDivElement | null>(null);
|
const actionSectionRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
@ -266,12 +267,15 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
|
|
||||||
if (!project) return null;
|
if (!project) return null;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (URLProjectId === project.id) setIsProjectListOpen(true);
|
||||||
|
}, [URLProjectId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PublishProjectModal isOpen={publishModalOpen} project={project} onClose={() => setPublishModal(false)} />
|
<PublishProjectModal isOpen={publishModalOpen} project={project} onClose={() => setPublishModal(false)} />
|
||||||
<LeaveProjectModal project={project} isOpen={leaveProjectModalOpen} onClose={() => setLeaveProjectModal(false)} />
|
<LeaveProjectModal project={project} isOpen={leaveProjectModalOpen} onClose={() => setLeaveProjectModal(false)} />
|
||||||
<Disclosure key={`${project.id}_${URLProjectId}`} ref={projectRef} defaultOpen={URLProjectId === project.id}>
|
<Disclosure key={`${project.id}_${URLProjectId}`} ref={projectRef} defaultOpen={isProjectListOpen}>
|
||||||
{({ open }) => (
|
|
||||||
<div
|
<div
|
||||||
id={`sidebar-${projectId}-${projectListType}`}
|
id={`sidebar-${projectId}-${projectListType}`}
|
||||||
className={cn("relative", {
|
className={cn("relative", {
|
||||||
|
|
@ -319,7 +323,11 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
"justify-center": isSidebarCollapsed,
|
"justify-center": isSidebarCollapsed,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Disclosure.Button as="button" className="size-8 aspect-square flex-shrink-0 grid place-items-center">
|
<Disclosure.Button
|
||||||
|
as="button"
|
||||||
|
className="size-8 aspect-square flex-shrink-0 grid place-items-center"
|
||||||
|
onClick={() => setIsProjectListOpen(!isProjectListOpen)}
|
||||||
|
>
|
||||||
<div className="size-4 grid place-items-center flex-shrink-0">
|
<div className="size-4 grid place-items-center flex-shrink-0">
|
||||||
<Logo logo={project.logo_props} size={16} />
|
<Logo logo={project.logo_props} size={16} />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -340,6 +348,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
className={cn("flex-grow flex items-center gap-1.5 text-left select-none w-full", {
|
className={cn("flex-grow flex items-center gap-1.5 text-left select-none w-full", {
|
||||||
"justify-center": isSidebarCollapsed,
|
"justify-center": isSidebarCollapsed,
|
||||||
})}
|
})}
|
||||||
|
onClick={() => setIsProjectListOpen(!isProjectListOpen)}
|
||||||
>
|
>
|
||||||
<div className="size-4 grid place-items-center flex-shrink-0">
|
<div className="size-4 grid place-items-center flex-shrink-0">
|
||||||
<Logo logo={project.logo_props} size={16} />
|
<Logo logo={project.logo_props} size={16} />
|
||||||
|
|
@ -367,9 +376,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
customButtonClassName="grid place-items-center"
|
customButtonClassName="grid place-items-center"
|
||||||
placement="bottom-start"
|
placement="bottom-start"
|
||||||
>
|
>
|
||||||
<CustomMenu.MenuItem
|
<CustomMenu.MenuItem onClick={project.is_favorite ? handleRemoveFromFavorites : handleAddToFavorites}>
|
||||||
onClick={project.is_favorite ? handleRemoveFromFavorites : handleAddToFavorites}
|
|
||||||
>
|
|
||||||
<span className="flex items-center justify-start gap-2">
|
<span className="flex items-center justify-start gap-2">
|
||||||
<Star
|
<Star
|
||||||
className={cn("h-3.5 w-3.5 ", {
|
className={cn("h-3.5 w-3.5 ", {
|
||||||
|
|
@ -442,10 +449,11 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
"inline-block": isMenuActive,
|
"inline-block": isMenuActive,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
onClick={() => setIsProjectListOpen(!isProjectListOpen)}
|
||||||
>
|
>
|
||||||
<ChevronRight
|
<ChevronRight
|
||||||
className={cn("size-4 flex-shrink-0 text-custom-sidebar-text-400 transition-transform", {
|
className={cn("size-4 flex-shrink-0 text-custom-sidebar-text-400 transition-transform", {
|
||||||
"rotate-90": open,
|
"rotate-90": isProjectListOpen,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Disclosure.Button>
|
</Disclosure.Button>
|
||||||
|
|
@ -453,6 +461,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Transition
|
<Transition
|
||||||
|
show={isProjectListOpen}
|
||||||
enter="transition duration-100 ease-out"
|
enter="transition duration-100 ease-out"
|
||||||
enterFrom="transform scale-95 opacity-0"
|
enterFrom="transform scale-95 opacity-0"
|
||||||
enterTo="transform scale-100 opacity-100"
|
enterTo="transform scale-100 opacity-100"
|
||||||
|
|
@ -460,6 +469,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
leaveFrom="transform scale-100 opacity-100"
|
leaveFrom="transform scale-100 opacity-100"
|
||||||
leaveTo="transform scale-95 opacity-0"
|
leaveTo="transform scale-95 opacity-0"
|
||||||
>
|
>
|
||||||
|
{isProjectListOpen && (
|
||||||
<Disclosure.Panel as="div" className="flex flex-col gap-0.5 mt-1">
|
<Disclosure.Panel as="div" className="flex flex-col gap-0.5 mt-1">
|
||||||
{navigation(workspaceSlug?.toString(), project?.id).map((item) => {
|
{navigation(workspaceSlug?.toString(), project?.id).map((item) => {
|
||||||
if (
|
if (
|
||||||
|
|
@ -498,10 +508,10 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Disclosure.Panel>
|
</Disclosure.Panel>
|
||||||
|
)}
|
||||||
</Transition>
|
</Transition>
|
||||||
{isLastChild && <DropIndicator isVisible={instruction === "DRAG_BELOW"} />}
|
{isLastChild && <DropIndicator isVisible={instruction === "DRAG_BELOW"} />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</Disclosure>
|
</Disclosure>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { useState, FC, useRef, useEffect } from "react";
|
||||||
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
||||||
import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
|
import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams, usePathname } from "next/navigation";
|
||||||
import { Briefcase, ChevronRight, Plus } from "lucide-react";
|
import { Briefcase, ChevronRight, Plus } from "lucide-react";
|
||||||
import { Disclosure, Transition } from "@headlessui/react";
|
import { Disclosure, Transition } from "@headlessui/react";
|
||||||
// types
|
// types
|
||||||
|
|
@ -43,6 +43,8 @@ export const SidebarProjectsList: FC = observer(() => {
|
||||||
const { getProjectById, joinedProjectIds: joinedProjects, updateProjectView } = useProject();
|
const { getProjectById, joinedProjectIds: joinedProjects, updateProjectView } = useProject();
|
||||||
// router params
|
// router params
|
||||||
const { workspaceSlug } = useParams();
|
const { workspaceSlug } = useParams();
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
|
|
@ -127,7 +129,12 @@ export const SidebarProjectsList: FC = observer(() => {
|
||||||
setIsAllProjectsListOpen(isOpen);
|
setIsAllProjectsListOpen(isOpen);
|
||||||
localStorage.setItem("isAllProjectsListOpen", isOpen.toString());
|
localStorage.setItem("isAllProjectsListOpen", isOpen.toString());
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (pathname.includes("projects")) {
|
||||||
|
setIsAllProjectsListOpen(true);
|
||||||
|
localStorage.setItem("isAllProjectsListOpen", "true");
|
||||||
|
}
|
||||||
|
}, [pathname]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{workspaceSlug && (
|
{workspaceSlug && (
|
||||||
|
|
|
||||||
|
|
@ -399,6 +399,9 @@ export class FavoriteStore implements IFavoriteStore {
|
||||||
*/
|
*/
|
||||||
fetchFavorite = async (workspaceSlug: string) => {
|
fetchFavorite = async (workspaceSlug: string) => {
|
||||||
try {
|
try {
|
||||||
|
this.favoriteIds = [];
|
||||||
|
this.favoriteMap = {};
|
||||||
|
this.entityMap = {};
|
||||||
const favorites = await this.favoriteService.getFavorites(workspaceSlug);
|
const favorites = await this.favoriteService.getFavorites(workspaceSlug);
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
favorites.forEach((favorite) => {
|
favorites.forEach((favorite) => {
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||||
};
|
};
|
||||||
// service
|
// service
|
||||||
service: ProjectPageService;
|
service: ProjectPageService;
|
||||||
|
rootStore: CoreRootStore;
|
||||||
|
|
||||||
constructor(private store: CoreRootStore) {
|
constructor(private store: CoreRootStore) {
|
||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
|
|
@ -70,6 +71,7 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||||
createPage: action,
|
createPage: action,
|
||||||
removePage: action,
|
removePage: action,
|
||||||
});
|
});
|
||||||
|
this.rootStore = store;
|
||||||
// service
|
// service
|
||||||
this.service = new ProjectPageService();
|
this.service = new ProjectPageService();
|
||||||
// initialize display filters of the current project
|
// initialize display filters of the current project
|
||||||
|
|
@ -257,7 +259,10 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||||
if (!workspaceSlug || !projectId || !pageId) return undefined;
|
if (!workspaceSlug || !projectId || !pageId) return undefined;
|
||||||
|
|
||||||
await this.service.remove(workspaceSlug, projectId, pageId);
|
await this.service.remove(workspaceSlug, projectId, pageId);
|
||||||
runInAction(() => unset(this.data, [pageId]));
|
runInAction(() => {
|
||||||
|
unset(this.data, [pageId]);
|
||||||
|
this.rootStore.favorite.removeFavoriteFromStore(pageId);
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = undefined;
|
this.loader = undefined;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue