fix: merge conflicts resolved

This commit is contained in:
sriram veeraghanta 2024-02-12 13:14:00 +05:30
commit 3eb819c4ae
17 changed files with 312 additions and 242 deletions

View File

@ -1,6 +1,6 @@
# base requirements # base requirements
Django==4.2.7 Django==4.2.10
psycopg==3.1.12 psycopg==3.1.12
djangorestframework==3.14.0 djangorestframework==3.14.0
redis==4.6.0 redis==4.6.0
@ -30,7 +30,7 @@ openpyxl==3.1.2
beautifulsoup4==4.12.2 beautifulsoup4==4.12.2
dj-database-url==2.1.0 dj-database-url==2.1.0
posthog==3.0.2 posthog==3.0.2
cryptography==41.0.6 cryptography==42.0.0
lxml==4.9.3 lxml==4.9.3
boto3==1.28.40 boto3==1.28.40

View File

@ -1,35 +1,73 @@
import * as React from "react"; import * as React from "react";
// icons
import { ChevronRight } from "lucide-react"; import { ChevronRight } from "lucide-react";
type BreadcrumbsProps = { type BreadcrumbsProps = {
children: any; children: React.ReactNode;
onBack?: () => void;
}; };
const Breadcrumbs = ({ children }: BreadcrumbsProps) => ( const Breadcrumbs = ({ children, onBack }: BreadcrumbsProps) => {
<div className="flex items-center space-x-2"> const [isSmallScreen, setIsSmallScreen] = React.useState(false);
{React.Children.map(children, (child, index) => (
<div key={index} className="flex items-center gap-2.5"> React.useEffect(() => {
{child} const handleResize = () => {
{index !== React.Children.count(children) - 1 && ( setIsSmallScreen(window.innerWidth <= 640); // Adjust this value as per your requirement
<ChevronRight className="h-3.5 w-3.5 flex-shrink-0 text-custom-text-400" aria-hidden="true" /> };
)}
</div> window.addEventListener("resize", handleResize);
))} handleResize(); // Call it initially to set the correct state
</div> return () => window.removeEventListener("resize", handleResize);
); }, []);
const childrenArray = React.Children.toArray(children);
return (
<div className="flex items-center space-x-2 overflow-hidden">
{!isSmallScreen && (
<>
{childrenArray.map((child, index) => (
<React.Fragment key={index}>
{index > 0 && !isSmallScreen && (
<div className="flex items-center gap-2.5">
<ChevronRight
className="h-3.5 w-3.5 flex-shrink-0 text-custom-text-400"
aria-hidden="true"
/>
</div>
)}
<div className={`flex items-center gap-2.5 ${isSmallScreen && index > 0 ? 'hidden sm:flex' : 'flex'}`}>
{child}
</div>
</React.Fragment>
))}
</>
)}
{isSmallScreen && childrenArray.length > 1 && (
<>
<div className="flex items-center gap-2.5">
{onBack && <span onClick={onBack} className="text-custom-text-200">...</span>}
<ChevronRight className="h-3.5 w-3.5 flex-shrink-0 text-custom-text-400" aria-hidden="true" />
</div>
<div className="flex items-center gap-2.5">{childrenArray[childrenArray.length - 1]}</div>
</>
)}
{isSmallScreen && childrenArray.length === 1 && childrenArray}
</div>
);
};
type Props = { type Props = {
type?: "text" | "component"; type?: "text" | "component";
component?: React.ReactNode; component?: React.ReactNode;
link?: JSX.Element; link?: JSX.Element;
}; };
const BreadcrumbItem: React.FC<Props> = (props) => { const BreadcrumbItem: React.FC<Props> = (props) => {
const { type = "text", component, link } = props; const { type = "text", component, link } = props;
return <>{type != "text" ? <div className="flex items-center space-x-2">{component}</div> : link}</>; return <>{type !== "text" ? <div className="flex items-center space-x-2">{component}</div> : link}</>;
}; };
Breadcrumbs.BreadcrumbItem = BreadcrumbItem; Breadcrumbs.BreadcrumbItem = BreadcrumbItem;
export { Breadcrumbs, BreadcrumbItem }; export { Breadcrumbs, BreadcrumbItem };

View File

@ -38,7 +38,7 @@ export const CyclePeekOverview: React.FC<Props> = observer(({ projectId, workspa
{peekCycle && ( {peekCycle && (
<div <div
ref={ref} ref={ref}
className="flex h-full w-[24rem] flex-shrink-0 flex-col gap-3.5 overflow-y-auto border-l border-custom-border-100 bg-custom-sidebar-background-100 px-6 py-3.5 duration-300" className="flex h-full w-full max-w-[24rem] flex-shrink-0 flex-col gap-3.5 overflow-y-auto border-l border-custom-border-100 bg-custom-sidebar-background-100 px-6 py-3.5 duration-300 fixed md:relative right-0 z-[9]"
style={{ style={{
boxShadow: boxShadow:
"0px 1px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 4px 0px rgba(16, 24, 40, 0.06), 0px 1px 8px -1px rgba(16, 24, 40, 0.06)", "0px 1px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 4px 0px rgba(16, 24, 40, 0.06), 0px 1px 8px -1px rgba(16, 24, 40, 0.06)",

View File

@ -69,8 +69,8 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
? cycleTotalIssues === 0 ? cycleTotalIssues === 0
? "0 Issue" ? "0 Issue"
: cycleTotalIssues === cycleDetails.completed_issues : cycleTotalIssues === cycleDetails.completed_issues
? `${cycleTotalIssues} Issue${cycleTotalIssues > 1 ? "s" : ""}` ? `${cycleTotalIssues} Issue${cycleTotalIssues > 1 ? "s" : ""}`
: `${cycleDetails.completed_issues}/${cycleTotalIssues} Issues` : `${cycleDetails.completed_issues}/${cycleTotalIssues} Issues`
: "0 Issue"; : "0 Issue";
const handleCopyText = (e: MouseEvent<HTMLButtonElement>) => { const handleCopyText = (e: MouseEvent<HTMLButtonElement>) => {
@ -175,7 +175,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
/> />
<Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycleDetails.id}`}> <Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycleDetails.id}`}>
<div className="flex h-44 w-full min-w-[250px] flex-col justify-between rounded border border-custom-border-100 bg-custom-background-100 p-4 text-sm hover:shadow-md"> <div className="flex h-44 w-full flex-col justify-between rounded border border-custom-border-100 bg-custom-background-100 p-4 text-sm hover:shadow-md">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-3 truncate"> <div className="flex items-center gap-3 truncate">
<span className="flex-shrink-0"> <span className="flex-shrink-0">
@ -253,7 +253,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
) : ( ) : (
<span className="text-xs text-custom-text-400">No due date</span> <span className="text-xs text-custom-text-400">No due date</span>
)} )}
<div className="z-10 flex items-center gap-1.5"> <div className="z-[5] flex items-center gap-1.5">
{isEditingAllowed && {isEditingAllowed &&
(cycleDetails.is_favorite ? ( (cycleDetails.is_favorite ? (
<button type="button" onClick={handleRemoveFromFavorites}> <button type="button" onClick={handleRemoveFromFavorites}>

View File

@ -204,7 +204,7 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
</Tooltip> </Tooltip>
</div> </div>
<button onClick={openCycleOverview} className="invisible z-10 flex-shrink-0 group-hover:visible"> <button onClick={openCycleOverview} className="flex-shrink-0 z-[5] invisible group-hover:visible">
<Info className="h-4 w-4 text-custom-text-400" /> <Info className="h-4 w-4 text-custom-text-400" />
</button> </button>
</div> </div>

View File

@ -100,7 +100,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
}); });
}) })
.catch((_) => { .catch(() => {
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_UPDATED, eventName: CYCLE_UPDATED,
payload: { payload: {

View File

@ -153,7 +153,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
<div className="flex justify-between border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div className="flex justify-between border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle />
<Breadcrumbs> <Breadcrumbs onBack={router.back}>
<Breadcrumbs.BreadcrumbItem <Breadcrumbs.BreadcrumbItem
type="text" type="text"
link={ link={
@ -196,7 +196,9 @@ export const CycleIssuesHeader: React.FC = observer(() => {
label={ label={
<> <>
<ContrastIcon className="h-3 w-3" /> <ContrastIcon className="h-3 w-3" />
{cycleDetails?.name && truncateText(cycleDetails.name, 40)} <div className=" w-auto max-w-[70px] sm:max-w-[200px] inline-block truncate line-clamp-1 overflow-hidden whitespace-nowrap">
{cycleDetails?.name && cycleDetails.name}
</div>
</> </>
} }
className="ml-1.5 flex-shrink-0" className="ml-1.5 flex-shrink-0"

View File

@ -50,7 +50,7 @@ export const CyclesHeader: FC = observer(() => {
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap"> <div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle />
<div> <div>
<Breadcrumbs> <Breadcrumbs onBack={router.back}>
<Breadcrumbs.BreadcrumbItem <Breadcrumbs.BreadcrumbItem
type="text" type="text"
link={ link={
@ -89,7 +89,7 @@ export const CyclesHeader: FC = observer(() => {
toggleCreateCycleModal(true); toggleCreateCycleModal(true);
}} }}
> >
Add Cycle <div className="hidden sm:block">Add</div> Cycle
</Button> </Button>
</div> </div>
)} )}

View File

@ -21,7 +21,7 @@ import { ProjectAnalyticsModal } from "components/analytics";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
import { BreadcrumbLink } from "components/common"; import { BreadcrumbLink } from "components/common";
// ui // ui
import { Breadcrumbs, Button, CustomMenu, DiceIcon } from "@plane/ui"; import { Breadcrumbs, Button, CustomMenu, DiceIcon, LayersIcon } from "@plane/ui";
// icons // icons
import { ArrowRight, PanelRight, Plus } from "lucide-react"; import { ArrowRight, PanelRight, Plus } from "lucide-react";
// helpers // helpers
@ -156,7 +156,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
<div className="flex justify-between border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div className="flex justify-between border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle />
<Breadcrumbs> <Breadcrumbs onBack={router.back}>
<Breadcrumbs.BreadcrumbItem <Breadcrumbs.BreadcrumbItem
type="text" type="text"
link={ link={
@ -199,7 +199,9 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
label={ label={
<> <>
<DiceIcon className="h-3 w-3" /> <DiceIcon className="h-3 w-3" />
{moduleDetails?.name && truncateText(moduleDetails.name, 40)} <div className="w-auto max-w-[70px] sm:max-w-[200px] inline-block truncate line-clamp-1 overflow-hidden whitespace-nowrap">
{moduleDetails?.name && moduleDetails.name}
</div>
</> </>
} }
className="ml-1.5 flex-shrink-0" className="ml-1.5 flex-shrink-0"
@ -251,6 +253,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
Analytics Analytics
</Button> </Button>
<Button <Button
className="hidden sm:flex"
onClick={() => { onClick={() => {
setTrackElement("Module issues page"); setTrackElement("Module issues page");
toggleCreateIssueModal(true, EIssuesStoreType.MODULE); toggleCreateIssueModal(true, EIssuesStoreType.MODULE);
@ -258,7 +261,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
size="sm" size="sm"
prependIcon={<Plus />} prependIcon={<Plus />}
> >
<span className="hidden md:block">Add</span> Issue Add Issue
</Button> </Button>
</> </>
)} )}

View File

@ -1,11 +1,11 @@
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Plus } from "lucide-react"; import { GanttChartSquare, LayoutGrid, List, Plus } from "lucide-react";
// hooks // hooks
import { useApplication, useEventTracker, useProject, useUser } from "hooks/store"; import { useApplication, useEventTracker, useProject, useUser } from "hooks/store";
import useLocalStorage from "hooks/use-local-storage"; import useLocalStorage from "hooks/use-local-storage";
// ui // ui
import { Breadcrumbs, Button, Tooltip, DiceIcon } from "@plane/ui"; import { Breadcrumbs, Button, Tooltip, DiceIcon, CustomMenu } from "@plane/ui";
// helper // helper
import { renderEmoji } from "helpers/emoji.helper"; import { renderEmoji } from "helpers/emoji.helper";
// constants // constants
@ -31,75 +31,101 @@ export const ModulesListHeader: React.FC = observer(() => {
const canUserCreateModule = const canUserCreateModule =
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole); currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
return ( return (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4"> <div>
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap"> <div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<SidebarHamburgerToggle /> <div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<div> <SidebarHamburgerToggle />
<Breadcrumbs> <div>
<Breadcrumbs.BreadcrumbItem <Breadcrumbs onBack={router.back}>
type="text" <Breadcrumbs.BreadcrumbItem
link={ type="text"
<BreadcrumbLink link={
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} <BreadcrumbLink
label={currentProjectDetails?.name ?? "Project"} href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`}
icon={ label={currentProjectDetails?.name ?? "Project"}
currentProjectDetails?.emoji ? ( icon={
renderEmoji(currentProjectDetails.emoji) currentProjectDetails?.emoji ? (
) : currentProjectDetails?.icon_prop ? ( renderEmoji(currentProjectDetails.emoji)
renderEmoji(currentProjectDetails.icon_prop) ) : currentProjectDetails?.icon_prop ? (
) : ( renderEmoji(currentProjectDetails.icon_prop)
<span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded bg-gray-700 uppercase text-white"> ) : (
{currentProjectDetails?.name.charAt(0)} <span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded bg-gray-700 uppercase text-white">
</span> {currentProjectDetails?.name.charAt(0)}
) </span>
} )
/> }
} />
/> }
<Breadcrumbs.BreadcrumbItem />
type="text" <Breadcrumbs.BreadcrumbItem
link={<BreadcrumbLink label="Modules" icon={<DiceIcon className="h-4 w-4 text-custom-text-300" />} />} type="text"
/> link={<BreadcrumbLink label="Modules" icon={<DiceIcon className="h-4 w-4 text-custom-text-300" />} />}
</Breadcrumbs> />
</Breadcrumbs>
</div>
</div>
<div className="flex items-center gap-2">
<div className="items-center gap-1 rounded bg-custom-background-80 p-1 hidden md:flex">
{MODULE_VIEW_LAYOUTS.map((layout) => (
<Tooltip key={layout.key} tooltipContent={layout.title}>
<button
type="button"
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${modulesView == layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : ""
}`}
onClick={() => setModulesView(layout.key)}
>
<layout.icon
strokeWidth={2}
className={`h-3.5 w-3.5 ${modulesView == layout.key ? "text-custom-text-100" : "text-custom-text-200"
}`}
/>
</button>
</Tooltip>
))}
</div>
{canUserCreateModule && (
<Button
variant="primary"
size="sm"
prependIcon={<Plus />}
onClick={() => {
setTrackElement("Modules page");
commandPaletteStore.toggleCreateModuleModal(true);
}}
>
<div className="hidden sm:block">Add</div> Module
</Button>
)}
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex justify-center md:hidden">
<div className="flex items-center gap-1 rounded bg-custom-background-80 p-1"> <CustomMenu
maxHeight={"md"}
className="flex flex-grow justify-center text-custom-text-200 text-sm py-2 border-b border-custom-border-200 bg-custom-sidebar-background-100"
// placement="bottom-start"
customButton={
<span className="flex items-center gap-2">
{modulesView === 'gantt_chart' ? <GanttChartSquare className="w-3 h-3" /> : modulesView === 'grid' ? <LayoutGrid className="w-3 h-3" /> : <List className="w-3 h-3" />}
<span className="flex flex-grow justify-center text-custom-text-200 text-sm">Layout</span>
</span>
}
customButtonClassName="flex flex-grow justify-center items-center text-custom-text-200 text-sm"
closeOnSelect
>
{MODULE_VIEW_LAYOUTS.map((layout) => ( {MODULE_VIEW_LAYOUTS.map((layout) => (
<Tooltip key={layout.key} tooltipContent={layout.title}> <CustomMenu.MenuItem
<button onClick={() => setModulesView(layout.key)}
type="button" className="flex items-center gap-2"
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${ >
modulesView == layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : "" <layout.icon className="w-3 h-3" />
}`} <div className="text-custom-text-300">{layout.title}</div>
onClick={() => setModulesView(layout.key)} </CustomMenu.MenuItem>
>
<layout.icon
strokeWidth={2}
className={`h-3.5 w-3.5 ${
modulesView == layout.key ? "text-custom-text-100" : "text-custom-text-200"
}`}
/>
</button>
</Tooltip>
))} ))}
</div> </CustomMenu>
{canUserCreateModule && (
<Button
variant="primary"
size="sm"
prependIcon={<Plus />}
onClick={() => {
setTrackElement("Modules page");
commandPaletteStore.toggleCreateModuleModal(true);
}}
>
Add Module
</Button>
)}
</div> </div>
</div> </div>
); );
}); });

View File

@ -2,7 +2,7 @@ import { useCallback, useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Briefcase, Circle, ExternalLink, Plus } from "lucide-react"; import { Briefcase, Circle, ExternalLink, Plus, Inbox } from "lucide-react";
// hooks // hooks
import { import {
useApplication, useApplication,
@ -120,35 +120,35 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap"> <div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle />
<div> <div>
<Breadcrumbs> <Breadcrumbs onBack={() => router.back()}>
<Breadcrumbs.BreadcrumbItem <Breadcrumbs.BreadcrumbItem
type="text" type="text"
link={ link={
<BreadcrumbLink <BreadcrumbLink
href={`/${workspaceSlug}/projects`} href={`/${workspaceSlug}/projects`}
label={currentProjectDetails?.name ?? "Project"} label={currentProjectDetails?.name ?? "Project"}
icon={ icon={
currentProjectDetails ? ( currentProjectDetails ? (
currentProjectDetails?.emoji ? ( currentProjectDetails?.emoji ? (
<span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded uppercase">
{renderEmoji(currentProjectDetails.emoji)}
</span>
) : currentProjectDetails?.icon_prop ? (
<div className="grid h-7 w-7 flex-shrink-0 place-items-center">
{renderEmoji(currentProjectDetails.icon_prop)}
</div>
) : (
<span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded bg-gray-700 uppercase text-white">
{currentProjectDetails?.name.charAt(0)}
</span>
)
) : (
<span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded uppercase"> <span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded uppercase">
<Briefcase className="h-4 w-4" /> {renderEmoji(currentProjectDetails.emoji)}
</span>
) : currentProjectDetails?.icon_prop ? (
<div className="grid h-7 w-7 flex-shrink-0 place-items-center">
{renderEmoji(currentProjectDetails.icon_prop)}
</div>
) : (
<span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded bg-gray-700 uppercase text-white">
{currentProjectDetails?.name.charAt(0)}
</span> </span>
) )
} ) : (
/> <span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded uppercase">
<Briefcase className="h-4 w-4" />
</span>
)
}
/>
} }
/> />
@ -202,18 +202,19 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
</FiltersDropdown> </FiltersDropdown>
</div> </div>
{currentProjectDetails?.inbox_view && inboxDetails && ( {currentProjectDetails?.inbox_view && inboxDetails && (
<Link href={`/${workspaceSlug}/projects/${projectId}/inbox/${inboxDetails?.id}`}> <Link href={`/${workspaceSlug}/projects/${projectId}/inbox/${inboxDetails?.id}`}>
<span> <span className="hidden md:block" >
<Button variant="neutral-primary" size="sm" className="relative"> <Button variant="neutral-primary" size="sm" className="relative">
Inbox Inbox
{inboxDetails?.pending_issue_count > 0 && ( {inboxDetails?.pending_issue_count > 0 && (
<span className="absolute -right-1.5 -top-1.5 h-4 w-4 rounded-full border border-custom-sidebar-border-200 bg-custom-sidebar-background-80 text-custom-text-100"> <span className="absolute -right-1.5 -top-1.5 h-4 w-4 rounded-full border border-custom-sidebar-border-200 bg-custom-sidebar-background-80 text-custom-text-100">
{inboxDetails?.pending_issue_count} {inboxDetails?.pending_issue_count}
</span> </span>
)} )}
</Button> </Button>
</span> </span>
</Link> <Inbox className="w-4 h-4 mr-2 text-custom-text-200" />
</Link>
)} )}
{canUserCreateIssue && ( {canUserCreateIssue && (
<> <>
@ -228,7 +229,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
size="sm" size="sm"
prependIcon={<Plus />} prependIcon={<Plus />}
> >
Add Issue <div className="hidden sm:block">Add</div> Issue
</Button> </Button>
</> </>
)} )}

View File

@ -36,7 +36,7 @@ export const ProjectSettingHeader: FC<IProjectSettingHeader> = observer((props)
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap"> <div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<div> <div>
<div className="z-50"> <div className="z-50">
<Breadcrumbs> <Breadcrumbs onBack={router.back}>
<Breadcrumbs.BreadcrumbItem <Breadcrumbs.BreadcrumbItem
type="text" type="text"
link={ link={

View File

@ -56,7 +56,7 @@ export const ProjectsHeader = observer(() => {
}} }}
className="items-center" className="items-center"
> >
Add Project <div className="hidden sm:block">Add</div> Project
</Button> </Button>
)} )}
</div> </div>

View File

@ -147,8 +147,8 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
? !moduleTotalIssues || moduleTotalIssues === 0 ? !moduleTotalIssues || moduleTotalIssues === 0
? "0 Issue" ? "0 Issue"
: moduleTotalIssues === moduleDetails.completed_issues : moduleTotalIssues === moduleDetails.completed_issues
? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}` ? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}`
: `${moduleDetails.completed_issues}/${moduleTotalIssues} Issues` : `${moduleDetails.completed_issues}/${moduleTotalIssues} Issues`
: "0 Issue"; : "0 Issue";
return ( return (
@ -164,7 +164,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
)} )}
<DeleteModuleModal data={moduleDetails} isOpen={deleteModal} onClose={() => setDeleteModal(false)} /> <DeleteModuleModal data={moduleDetails} isOpen={deleteModal} onClose={() => setDeleteModal(false)} />
<Link href={`/${workspaceSlug}/projects/${moduleDetails.project}/modules/${moduleDetails.id}`}> <Link href={`/${workspaceSlug}/projects/${moduleDetails.project}/modules/${moduleDetails.id}`}>
<div className="flex h-44 w-full min-w-[250px] flex-col justify-between rounded border border-custom-border-100 bg-custom-background-100 p-4 text-sm hover:shadow-md"> <div className="flex h-44 w-full flex-col justify-between rounded border border-custom-border-100 bg-custom-background-100 p-4 text-sm hover:shadow-md">
<div> <div>
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<Tooltip tooltipContent={moduleDetails.name} position="top"> <Tooltip tooltipContent={moduleDetails.name} position="top">
@ -240,7 +240,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
<span className="text-xs text-custom-text-400">No due date</span> <span className="text-xs text-custom-text-400">No due date</span>
)} )}
<div className="z-10 flex items-center gap-1.5"> <div className="z-[5] flex items-center gap-1.5">
{isEditingAllowed && {isEditingAllowed &&
(moduleDetails.is_favorite ? ( (moduleDetails.is_favorite ? (
<button type="button" onClick={handleRemoveFromFavorites}> <button type="button" onClick={handleRemoveFromFavorites}>

View File

@ -154,38 +154,37 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
)} )}
<DeleteModuleModal data={moduleDetails} isOpen={deleteModal} onClose={() => setDeleteModal(false)} /> <DeleteModuleModal data={moduleDetails} isOpen={deleteModal} onClose={() => setDeleteModal(false)} />
<Link href={`/${workspaceSlug}/projects/${moduleDetails.project}/modules/${moduleDetails.id}`}> <Link href={`/${workspaceSlug}/projects/${moduleDetails.project}/modules/${moduleDetails.id}`}>
<div className="group flex h-16 w-full items-center justify-between gap-5 border-b border-custom-border-100 bg-custom-background-100 px-5 py-6 text-sm hover:bg-custom-background-90"> <div className="group flex w-full items-center justify-between gap-5 border-b border-custom-border-100 bg-custom-background-100 flex-col sm:flex-row px-5 py-6 text-sm hover:bg-custom-background-90">
<div className="flex w-full items-center gap-3 truncate"> <div className="relative flex w-full items-center gap-3 justify-between overflow-hidden">
<div className="flex items-center gap-4 truncate"> <div className="relative w-full flex items-center gap-3 overflow-hidden">
<span className="flex-shrink-0"> <div className="flex items-center gap-4 truncate">
<CircularProgressIndicator size={38} percentage={progress}> <span className="flex-shrink-0">
{completedModuleCheck ? ( <CircularProgressIndicator size={38} percentage={progress}>
progress === 100 ? ( {completedModuleCheck ? (
progress === 100 ? (
<Check className="h-3 w-3 stroke-[2] text-custom-primary-100" />
) : (
<span className="text-sm text-custom-primary-100">{`!`}</span>
)
) : progress === 100 ? (
<Check className="h-3 w-3 stroke-[2] text-custom-primary-100" /> <Check className="h-3 w-3 stroke-[2] text-custom-primary-100" />
) : ( ) : (
<span className="text-sm text-custom-primary-100">{`!`}</span> <span className="text-xs text-custom-text-300">{`${progress}%`}</span>
) )}
) : progress === 100 ? ( </CircularProgressIndicator>
<Check className="h-3 w-3 stroke-[2] text-custom-primary-100" /> </span>
) : ( <Tooltip tooltipContent={moduleDetails.name} position="top">
<span className="text-xs text-custom-text-300">{`${progress}%`}</span> <span className="truncate text-base font-medium">{moduleDetails.name}</span>
)} </Tooltip>
</CircularProgressIndicator> </div>
</span> <button onClick={openModuleOverview} className="z-[5] hidden flex-shrink-0 group-hover:flex">
<Tooltip tooltipContent={moduleDetails.name} position="top"> <Info className="h-4 w-4 text-custom-text-400" />
<span className="truncate text-base font-medium">{moduleDetails.name}</span> </button>
</Tooltip>
</div> </div>
<button onClick={openModuleOverview} className="z-10 hidden flex-shrink-0 group-hover:flex"> <div className="flex items-center justify-center flex-shrink-0">
<Info className="h-4 w-4 text-custom-text-400" />
</button>
</div>
<div className="flex w-full items-center justify-end gap-2.5 md:w-auto md:flex-shrink-0 ">
<div className="flex items-center justify-center">
{moduleStatus && ( {moduleStatus && (
<span <span
className="flex h-6 w-20 items-center justify-center rounded-sm text-center text-xs" className="flex h-6 w-20 items-center justify-center rounded-sm text-center text-xs flex-shrink-0"
style={{ style={{
color: moduleStatus.color, color: moduleStatus.color,
backgroundColor: `${moduleStatus.color}20`, backgroundColor: `${moduleStatus.color}20`,
@ -195,64 +194,70 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
</span> </span>
)} )}
</div> </div>
</div>
{renderDate && ( <div className="flex w-full sm:w-auto relative overflow-hidden items-center gap-2.5 justify-between sm:justify-end sm:flex-shrink-0 ">
<span className="flex w-40 items-center justify-center gap-2 text-xs text-custom-text-300"> <div className="text-xs text-custom-text-300">
{renderFormattedDate(startDate) ?? "_ _"} - {renderFormattedDate(endDate) ?? "_ _"} {renderDate && (
</span> <span className=" text-xs text-custom-text-300">
)} {renderFormattedDate(startDate) ?? "_ _"} - {renderFormattedDate(endDate) ?? "_ _"}
<Tooltip tooltipContent={`${moduleDetails.members_detail.length} Members`}>
<div className="flex w-16 cursor-default items-center justify-center gap-1">
{moduleDetails.members_detail.length > 0 ? (
<AvatarGroup showTooltip={false}>
{moduleDetails.members_detail.map((member) => (
<Avatar key={member.id} name={member.display_name} src={member.avatar} />
))}
</AvatarGroup>
) : (
<span className="flex h-5 w-5 items-end justify-center rounded-full border border-dashed border-custom-text-400 bg-custom-background-80">
<User2 className="h-4 w-4 text-custom-text-400" />
</span>
)}
</div>
</Tooltip>
{isEditingAllowed &&
(moduleDetails.is_favorite ? (
<button type="button" onClick={handleRemoveFromFavorites} className="z-[1]">
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
</button>
) : (
<button type="button" onClick={handleAddToFavorites} className="z-[1]">
<Star className="h-3.5 w-3.5 text-custom-text-300" />
</button>
))}
<CustomMenu verticalEllipsis buttonClassName="z-[1]">
{isEditingAllowed && (
<>
<CustomMenu.MenuItem onClick={handleEditModule}>
<span className="flex items-center justify-start gap-2">
<Pencil className="h-3 w-3" />
<span>Edit module</span>
</span>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem onClick={handleDeleteModule}>
<span className="flex items-center justify-start gap-2">
<Trash2 className="h-3 w-3" />
<span>Delete module</span>
</span>
</CustomMenu.MenuItem>
</>
)}
<CustomMenu.MenuItem onClick={handleCopyText}>
<span className="flex items-center justify-start gap-2">
<LinkIcon className="h-3 w-3" />
<span>Copy module link</span>
</span> </span>
</CustomMenu.MenuItem> )}
</CustomMenu> </div>
<div className="flex-shrink-0 relative flex items-center gap-3">
<Tooltip tooltipContent={`${moduleDetails.members_detail.length} Members`}>
<div className="flex w-10 cursor-default items-center justify-center gap-1">
{moduleDetails.members_detail.length > 0 ? (
<AvatarGroup showTooltip={false}>
{moduleDetails.members_detail.map((member) => (
<Avatar key={member.id} name={member.display_name} src={member.avatar} />
))}
</AvatarGroup>
) : (
<span className="flex h-5 w-5 items-end justify-center rounded-full border border-dashed border-custom-text-400 bg-custom-background-80">
<User2 className="h-4 w-4 text-custom-text-400" />
</span>
)}
</div>
</Tooltip>
{isEditingAllowed &&
(moduleDetails.is_favorite ? (
<button type="button" onClick={handleRemoveFromFavorites} className="z-[1]">
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
</button>
) : (
<button type="button" onClick={handleAddToFavorites} className="z-[1]">
<Star className="h-3.5 w-3.5 text-custom-text-300" />
</button>
))}
<CustomMenu verticalEllipsis buttonClassName="z-[1]">
{isEditingAllowed && (
<>
<CustomMenu.MenuItem onClick={handleEditModule}>
<span className="flex items-center justify-start gap-2">
<Pencil className="h-3 w-3" />
<span>Edit module</span>
</span>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem onClick={handleDeleteModule}>
<span className="flex items-center justify-start gap-2">
<Trash2 className="h-3 w-3" />
<span>Delete module</span>
</span>
</CustomMenu.MenuItem>
</>
)}
<CustomMenu.MenuItem onClick={handleCopyText}>
<span className="flex items-center justify-start gap-2">
<LinkIcon className="h-3 w-3" />
<span>Copy module link</span>
</span>
</CustomMenu.MenuItem>
</CustomMenu>
</div>
</div> </div>
</div> </div>
</Link> </Link>

View File

@ -39,7 +39,7 @@ export const ModulePeekOverview: React.FC<Props> = observer(({ projectId, worksp
{peekModule && ( {peekModule && (
<div <div
ref={ref} ref={ref}
className="flex h-full w-[24rem] flex-shrink-0 flex-col gap-3.5 overflow-y-auto border-l border-custom-border-100 bg-custom-sidebar-background-100 px-6 py-3.5 duration-300" className="flex h-full w-full max-w-[24rem] flex-shrink-0 flex-col gap-3.5 overflow-y-auto border-l border-custom-border-100 bg-custom-sidebar-background-100 px-6 py-3.5 duration-300 absolute md:relative right-0 z-[9]"
style={{ style={{
boxShadow: boxShadow:
"0px 1px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 4px 0px rgba(16, 24, 40, 0.06), 0px 1px 8px -1px rgba(16, 24, 40, 0.06)", "0px 1px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 4px 0px rgba(16, 24, 40, 0.06), 0px 1px 8px -1px rgba(16, 24, 40, 0.06)",

View File

@ -323,9 +323,8 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
<CustomSelect <CustomSelect
customButton={ customButton={
<span <span
className={`flex h-6 w-20 items-center justify-center rounded-sm text-center text-xs ${ className={`flex h-6 w-20 items-center justify-center rounded-sm text-center text-xs ${isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed"
isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed" }`}
}`}
style={{ style={{
color: moduleStatus ? moduleStatus.color : "#a3a3a2", color: moduleStatus ? moduleStatus.color : "#a3a3a2",
backgroundColor: moduleStatus ? `${moduleStatus.color}20` : "#a3a3a220", backgroundColor: moduleStatus ? `${moduleStatus.color}20` : "#a3a3a220",
@ -374,15 +373,13 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
<> <>
<Popover.Button <Popover.Button
ref={startDateButtonRef} ref={startDateButtonRef}
className={`w-full cursor-pointer rounded-sm text-sm font-medium text-custom-text-300 hover:bg-custom-background-80 ${ className={`w-full cursor-pointer rounded-sm text-sm font-medium text-custom-text-300 hover:bg-custom-background-80 ${isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed"
isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed" }`}
}`}
disabled={!isEditingAllowed} disabled={!isEditingAllowed}
> >
<span <span
className={`group flex w-full items-center justify-between gap-2 px-1.5 py-1 text-sm ${ className={`group flex w-full items-center justify-between gap-2 px-1.5 py-1 text-sm ${watch("start_date") ? "" : "text-custom-text-400"
watch("start_date") ? "" : "text-custom-text-400" }`}
}`}
> >
{renderFormattedDate(startDate) ?? "No date selected"} {renderFormattedDate(startDate) ?? "No date selected"}
</span> </span>
@ -430,15 +427,13 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
<> <>
<Popover.Button <Popover.Button
ref={endDateButtonRef} ref={endDateButtonRef}
className={`w-full cursor-pointer rounded-sm text-sm font-medium text-custom-text-300 hover:bg-custom-background-80 ${ className={`w-full cursor-pointer rounded-sm text-sm font-medium text-custom-text-300 hover:bg-custom-background-80 ${isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed"
isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed" }`}
}`}
disabled={!isEditingAllowed} disabled={!isEditingAllowed}
> >
<span <span
className={`group flex w-full items-center justify-between gap-2 px-1.5 py-1 text-sm ${ className={`group flex w-full items-center justify-between gap-2 px-1.5 py-1 text-sm ${watch("target_date") ? "" : "text-custom-text-400"
watch("target_date") ? "" : "text-custom-text-400" }`}
}`}
> >
{renderFormattedDate(endDate) ?? "No date selected"} {renderFormattedDate(endDate) ?? "No date selected"}
</span> </span>
@ -596,7 +591,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
</div> </div>
</div> </div>
</div> </div>
<div className="relative h-40 w-80"> <div className="relative h-40 w-full max-w-80">
<ProgressChart <ProgressChart
distribution={moduleDetails.distribution?.completion_chart ?? {}} distribution={moduleDetails.distribution?.completion_chart ?? {}}
startDate={moduleDetails.start_date} startDate={moduleDetails.start_date}