[WEB-2126] chore: guest and viewer role permission (#5347)

* chore: user store code refactor

* chore: general unauthorized screen asset added

* chore: workspace setting sidebar options updated for guest and viewer

* chore: NotAuthorizedView component code updated

* chore: project setting layout code refactor

* chore: workspace setting members and exports page permission validation added

* chore: workspace members and exports settings page improvement

* chore: project invite modal updated

* chore: workspace setting unauthorized access empty state

* chore: workspace setting unauthorized access empty state

* chore: project settings sidebar permission updated

* fix: project settings user role permission updated

* chore: app sidebar role permission validation updated

* chore: app sidebar role permission validation

* chore: disabled page empty state validation

* chore: app sidebar add project improvement

* chore: guest role changes

* fix: user favorite

* chore: changed pages permission

* chore: guest role changes

* fix: app sidebar project item permission

* fix: project setting empty state flicker

* fix: workspace setting empty state flicker

* chore: granted notification permission to viewer

* chore: project invite and edit validation updated

* chore: favorite validation added for guest and viewer role

* chore: create view validation updated

* chore: views permission changes

* chore: create view empty state validation updated

* chore: created ENUM for permissions

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com>
This commit is contained in:
Anmol Singh Bhatia 2024-08-16 16:35:05 +05:30 committed by GitHub
parent d60e988ca1
commit 0a1c656865
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
62 changed files with 957 additions and 590 deletions

View file

@ -45,7 +45,7 @@ import { EUserProjectRoles } from "@/constants/project";
// helpers
import { cn } from "@/helpers/common.helper";
// hooks
import { useAppTheme, useEventTracker, useProject } from "@/hooks/store";
import { useAppTheme, useEventTracker, useProject, useUser } from "@/hooks/store";
import useOutsideClickDetector from "@/hooks/use-outside-click-detector";
import { usePlatformOS } from "@/hooks/use-platform-os";
// constants
@ -70,31 +70,37 @@ const navigation = (workspaceSlug: string, projectId: string) => [
name: "Issues",
href: `/${workspaceSlug}/projects/${projectId}/issues`,
Icon: LayersIcon,
access: EUserProjectRoles.GUEST,
},
{
name: "Cycles",
href: `/${workspaceSlug}/projects/${projectId}/cycles`,
Icon: ContrastIcon,
access: EUserProjectRoles.VIEWER,
},
{
name: "Modules",
href: `/${workspaceSlug}/projects/${projectId}/modules`,
Icon: DiceIcon,
access: EUserProjectRoles.VIEWER,
},
{
name: "Views",
href: `/${workspaceSlug}/projects/${projectId}/views`,
Icon: Layers,
access: EUserProjectRoles.GUEST,
},
{
name: "Pages",
href: `/${workspaceSlug}/projects/${projectId}/pages`,
Icon: FileText,
access: EUserProjectRoles.VIEWER,
},
{
name: "Intake",
href: `/${workspaceSlug}/projects/${projectId}/inbox`,
Icon: Intake,
access: EUserProjectRoles.GUEST,
},
];
@ -106,6 +112,9 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
const { setTrackElement } = useEventTracker();
const { addProjectToFavorites, removeProjectFromFavorites, getProjectById } = useProject();
const { isMobile } = usePlatformOS();
const {
membership: { currentWorkspaceAllProjectsRole },
} = useUser();
// states
const [leaveProjectModalOpen, setLeaveProjectModal] = useState(false);
const [publishModalOpen, setPublishModal] = useState(false);
@ -378,16 +387,20 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
customButtonClassName="grid place-items-center"
placement="bottom-start"
>
<CustomMenu.MenuItem onClick={project.is_favorite ? handleRemoveFromFavorites : handleAddToFavorites}>
<span className="flex items-center justify-start gap-2">
<Star
className={cn("h-3.5 w-3.5 ", {
"fill-yellow-500 stroke-yellow-500": project.is_favorite,
})}
/>
<span>{project.is_favorite ? "Remove from favorites" : "Add to favorites"}</span>
</span>
</CustomMenu.MenuItem>
{!isViewerOrGuest && (
<CustomMenu.MenuItem
onClick={project.is_favorite ? handleRemoveFromFavorites : handleAddToFavorites}
>
<span className="flex items-center justify-start gap-2">
<Star
className={cn("h-3.5 w-3.5 ", {
"fill-yellow-500 stroke-yellow-500": project.is_favorite,
})}
/>
<span>{project.is_favorite ? "Remove from favorites" : "Add to favorites"}</span>
</span>
</CustomMenu.MenuItem>
)}
{/* publish project settings */}
{isAdmin && (
@ -400,14 +413,16 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
</div>
</CustomMenu.MenuItem>
)}
<CustomMenu.MenuItem>
<Link href={`/${workspaceSlug}/projects/${project?.id}/draft-issues/`}>
<div className="flex items-center justify-start gap-2">
<PenSquare className="h-3.5 w-3.5 stroke-[1.5] text-custom-text-300" />
<span>Draft issues</span>
</div>
</Link>
</CustomMenu.MenuItem>
{!isViewerOrGuest && (
<CustomMenu.MenuItem>
<Link href={`/${workspaceSlug}/projects/${project?.id}/draft-issues/`}>
<div className="flex items-center justify-start gap-2">
<PenSquare className="h-3.5 w-3.5 stroke-[1.5] text-custom-text-300" />
<span>Draft issues</span>
</div>
</Link>
</CustomMenu.MenuItem>
)}
<CustomMenu.MenuItem onClick={handleCopyText}>
<span className="flex items-center justify-start gap-2">
<LinkIcon className="h-3.5 w-3.5 stroke-[1.5]" />
@ -482,31 +497,37 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
(item.name === "Intake" && !project.inbox_view)
)
return;
const currentRole = currentWorkspaceAllProjectsRole
? currentWorkspaceAllProjectsRole[projectId]
: undefined;
return (
<Tooltip
key={item.name}
isMobile={isMobile}
tooltipContent={`${project?.name}: ${item.name}`}
position="right"
className="ml-2"
disabled={!isSidebarCollapsed}
>
<Link key={item.name} href={item.href} onClick={handleProjectClick}>
<SidebarNavItem
<>
{currentRole >= item.access && (
<Tooltip
key={item.name}
className={`pl-[18px] ${isSidebarCollapsed ? "p-0 size-7 justify-center mx-auto" : ""}`}
isActive={pathname.includes(item.href)}
isMobile={isMobile}
tooltipContent={`${project?.name}: ${item.name}`}
position="right"
className="ml-2"
disabled={!isSidebarCollapsed}
>
<div className="flex items-center gap-1.5 py-[1px]">
<item.Icon
className={`flex-shrink-0 size-4 ${item.name === "Intake" ? "stroke-1" : "stroke-[1.5]"}`}
/>
{!isSidebarCollapsed && <span className="text-xs font-medium">{item.name}</span>}
</div>
</SidebarNavItem>
</Link>
</Tooltip>
<Link key={item.name} href={item.href} onClick={handleProjectClick}>
<SidebarNavItem
key={item.name}
className={`pl-[18px] ${isSidebarCollapsed ? "p-0 size-7 justify-center mx-auto" : ""}`}
isActive={pathname.includes(item.href)}
>
<div className="flex items-center gap-1.5 py-[1px]">
<item.Icon
className={`flex-shrink-0 size-4 ${item.name === "Intake" ? "stroke-1" : "stroke-[1.5]"}`}
/>
{!isSidebarCollapsed && <span className="text-xs font-medium">{item.name}</span>}
</div>
</SidebarNavItem>
</Link>
</Tooltip>
)}
</>
);
})}
</Disclosure.Panel>

View file

@ -263,7 +263,6 @@ export const SidebarProjectsList: FC = observer(() => {
toggleCreateProjectModal(true);
}}
>
<Plus className="flex-shrink-0 size-4" />
{!isCollapsed && "Add project"}
</button>
)}