Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions web/components/analytics/custom-analytics/custom-analytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { CustomAnalyticsSelectBar, CustomAnalyticsMainContent, CustomAnalyticsSi
import { IAnalyticsParams } from "@plane/types";
// fetch-keys
import { ANALYTICS } from "constants/fetch-keys";
import { cn } from "helpers/common.helper";
import { useApplication } from "hooks/store";

type Props = {
additionalParams?: Partial<IAnalyticsParams>;
Expand Down Expand Up @@ -46,11 +48,13 @@ export const CustomAnalytics: React.FC<Props> = observer((props) => {
workspaceSlug ? () => analyticsService.getAnalytics(workspaceSlug.toString(), params) : null
);

const { theme: themeStore } = useApplication();

const isProjectLevel = projectId ? true : false;

return (
<div className={`flex flex-col-reverse overflow-hidden ${fullScreen ? "md:grid md:h-full md:grid-cols-4" : ""}`}>
<div className="col-span-3 flex h-full flex-col overflow-hidden">
<div className={cn("relative w-full h-full flex overflow-hidden", isProjectLevel ? "flex-col-reverse" : "")}>
<div className="w-full flex h-full flex-col overflow-hidden">
<CustomAnalyticsSelectBar
control={control}
setValue={setValue}
Expand All @@ -61,16 +65,22 @@ export const CustomAnalytics: React.FC<Props> = observer((props) => {
<CustomAnalyticsMainContent
analytics={analytics}
error={analyticsError}
fullScreen={fullScreen}
params={params}
fullScreen={fullScreen}
/>
</div>
<CustomAnalyticsSidebar
analytics={analytics}
params={params}
fullScreen={fullScreen}
isProjectLevel={isProjectLevel}
/>

<div
className={cn(
"border-l border-custom-border-200 transition-all",
!isProjectLevel
? "absolute right-0 top-0 bottom-0 md:relative flex-shrink-0 h-full max-w-[250px] sm:max-w-full"
: ""
)}
style={themeStore.workspaceAnalyticsSidebarCollapsed ? { right: `-${window?.innerWidth || 0}px` } : {}}
>
<CustomAnalyticsSidebar analytics={analytics} params={params} isProjectLevel={isProjectLevel} />
</div>
</div>
);
});
5 changes: 2 additions & 3 deletions web/components/analytics/custom-analytics/select-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ export const CustomAnalyticsSelectBar: React.FC<Props> = observer((props) => {

return (
<div
className={`grid items-center gap-4 px-5 py-2.5 ${isProjectLevel ? "grid-cols-3" : "grid-cols-2"} ${
fullScreen ? "md:py-5 lg:grid-cols-4" : ""
}`}
className={`grid items-center gap-4 px-5 py-2.5 ${isProjectLevel ? "grid-cols-1 sm:grid-cols-3" : "grid-cols-2"} ${fullScreen ? "md:py-5 lg:grid-cols-4" : ""
}`}
>
{!isProjectLevel && (
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ export const CustomAnalyticsSidebarProjectsList: React.FC<Props> = observer((pro
const { getProjectById } = useProject();

return (
<div className="hidden h-full overflow-hidden md:flex md:flex-col">
<div className="relative flex flex-col gap-4 h-full">
<h4 className="font-medium">Selected Projects</h4>
<div className="mt-4 h-full space-y-6 overflow-y-auto">
<div className="relative space-y-6 overflow-hidden overflow-y-auto">
{projectIds.map((projectId) => {
const project = getProjectById(projectId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
<>
{projectId ? (
cycleDetails ? (
<div className="hidden h-full overflow-y-auto md:block">
<div className="h-full overflow-y-auto">
<h4 className="break-words font-medium">Analytics for {cycleDetails.name}</h4>
<div className="mt-4 space-y-4">
<div className="flex items-center gap-2 text-xs">
Expand All @@ -52,7 +52,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
</div>
</div>
) : moduleDetails ? (
<div className="hidden h-full overflow-y-auto md:block">
<div className="h-full overflow-y-auto">
<h4 className="break-words font-medium">Analytics for {moduleDetails.name}</h4>
<div className="mt-4 space-y-4">
<div className="flex items-center gap-2 text-xs">
Expand All @@ -78,7 +78,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
</div>
</div>
) : (
<div className="hidden h-full overflow-y-auto md:flex md:flex-col">
<div className="h-full overflow-y-auto">
<div className="flex items-center gap-1">
{projectDetails?.emoji ? (
<div className="grid h-6 w-6 flex-shrink-0 place-items-center">{renderEmoji(projectDetails.emoji)}</div>
Expand Down
46 changes: 21 additions & 25 deletions web/components/analytics/custom-analytics/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from "react";
import { useEffect, } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { mutate } from "swr";
Expand All @@ -19,18 +19,18 @@ import { renderFormattedDate } from "helpers/date-time.helper";
import { IAnalyticsParams, IAnalyticsResponse, IExportAnalyticsFormData, IWorkspace } from "@plane/types";
// fetch-keys
import { ANALYTICS } from "constants/fetch-keys";
import { cn } from "helpers/common.helper";

type Props = {
analytics: IAnalyticsResponse | undefined;
params: IAnalyticsParams;
fullScreen: boolean;
isProjectLevel: boolean;
};

const analyticsService = new AnalyticsService();

export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
const { analytics, params, fullScreen, isProjectLevel = false } = props;
const { analytics, params, isProjectLevel = false } = props;
// router
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
Expand Down Expand Up @@ -138,18 +138,14 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {

const selectedProjects = params.project && params.project.length > 0 ? params.project : workspaceProjectIds;


return (
<div
className={`flex items-center justify-between space-y-2 px-5 py-2.5 ${
fullScreen
? "overflow-hidden border-l border-custom-border-200 md:h-full md:flex-col md:items-start md:space-y-4 md:border-l md:border-custom-border-200 md:py-5"
: ""
}`}
<div className={cn("relative h-full flex w-full gap-2 justify-between items-start px-5 py-4 bg-custom-sidebar-background-100", !isProjectLevel ? "flex-col" : "")}
>
<div className="flex flex-wrap items-center gap-2">
<div className="flex items-center gap-1 rounded-md bg-custom-background-80 px-3 py-1 text-xs text-custom-text-200">
<LayersIcon height={14} width={14} />
{analytics ? analytics.total : "..."} Issues
{analytics ? analytics.total : "..."} <div className={cn(isProjectLevel ? "hidden md:block" : "")}>Issues</div>
</div>
{isProjectLevel && (
<div className="flex items-center gap-1 rounded-md bg-custom-background-80 px-3 py-1 text-xs text-custom-text-200">
Expand All @@ -158,36 +154,36 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
(cycleId
? cycleDetails?.created_at
: moduleId
? moduleDetails?.created_at
: projectDetails?.created_at) ?? ""
? moduleDetails?.created_at
: projectDetails?.created_at) ?? ""
)}
</div>
)}
</div>
<div className="h-full w-full overflow-hidden">
{fullScreen ? (
<>
{!isProjectLevel && selectedProjects && selectedProjects.length > 0 && (
<CustomAnalyticsSidebarProjectsList projectIds={selectedProjects} />
)}
<CustomAnalyticsSidebarHeader />
</>
) : null}

<div className={cn("h-full w-full overflow-hidden", isProjectLevel ? "hidden" : "block")}>
<>
{!isProjectLevel && selectedProjects && selectedProjects.length > 0 && (
<CustomAnalyticsSidebarProjectsList projectIds={selectedProjects} />
)}
<CustomAnalyticsSidebarHeader />
</>
</div>
<div className="flex flex-wrap items-center gap-2 justify-self-end">

<div className="flex flex-wrap items-center gap-2 justify-end">
<Button
variant="neutral-primary"
prependIcon={<RefreshCw className="h-3.5 w-3.5" />}
prependIcon={<RefreshCw className="h-3 md:h-3.5 w-3 md:w-3.5" />}
onClick={() => {
if (!workspaceSlug) return;

mutate(ANALYTICS(workspaceSlug.toString(), params));
}}
>
Refresh
<div className={cn(isProjectLevel ? "hidden md:block" : "")}>Refresh</div>
</Button>
<Button variant="primary" prependIcon={<Download className="h-3.5 w-3.5" />} onClick={exportAnalytics}>
Export as CSV
<div className={cn(isProjectLevel ? "hidden md:block" : "")}>Export as CSV</div>
</Button>
</div>
</div>
Expand Down
7 changes: 3 additions & 4 deletions web/components/analytics/project-modal/main-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,15 @@ export const ProjectAnalyticsModalMainContent: React.FC<Props> = observer((props

return (
<Tab.Group as={React.Fragment}>
<Tab.List as="div" className="space-x-2 border-b border-custom-border-200 p-5 pt-0">
<Tab.List as="div" className="flex space-x-2 border-b border-custom-border-200 px-0 md:px-5 py-0 md:py-3">
{ANALYTICS_TABS.map((tab) => (
<Tab
key={tab.key}
className={({ selected }) =>
`rounded-3xl border border-custom-border-200 px-4 py-2 text-xs hover:bg-custom-background-80 ${
selected ? "bg-custom-background-80" : ""
`rounded-0 w-full md:w-max md:rounded-3xl border-b md:border border-custom-border-200 focus:outline-none px-0 md:px-4 py-2 text-xs hover:bg-custom-background-80 ${selected ? "border-custom-primary-100 text-custom-primary-100 md:bg-custom-background-80 md:text-custom-text-200 md:border-custom-border-200" : "border-transparent"
}`
}
onClick={() => {}}
onClick={() => { }}
>
{tab.title}
</Tab>
Expand Down
2 changes: 1 addition & 1 deletion web/components/headers/user-profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
</CustomMenu.MenuItem>
))}
</CustomMenu>
<button className="transition-all block md:hidden" onClick={() => { themStore.toggleProfileSidebar(); console.log(themStore.profileSidebarCollapsed) }}>
<button className="transition-all block md:hidden" onClick={() => { themStore.toggleProfileSidebar() }}>
<PanelRight className={
cn("w-4 h-4 block md:hidden", !themStore.profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")
} />
Expand Down
35 changes: 31 additions & 4 deletions web/components/headers/workspace-analytics.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
import { useRouter } from "next/router";
import { ArrowLeft, BarChart2 } from "lucide-react";
import { BarChart2, PanelRight } from "lucide-react";
// ui
import { Breadcrumbs } from "@plane/ui";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
import { BreadcrumbLink } from "components/common";
import { useApplication } from "hooks/store";
import { observer } from "mobx-react";
import { cn } from "helpers/common.helper";
import { useEffect } from "react";

export const WorkspaceAnalyticsHeader = () => {
export const WorkspaceAnalyticsHeader = observer(() => {
const router = useRouter();
const { analytics_tab } = router.query;

const { theme: themeStore } = useApplication();

useEffect(() => {
const handleToggleWorkspaceAnalyticsSidebar = () => {
if (window && window.innerWidth < 768) {
themeStore.toggleWorkspaceAnalyticsSidebar(true);
}
if (window && themeStore.workspaceAnalyticsSidebarCollapsed && window.innerWidth >= 768) {
themeStore.toggleWorkspaceAnalyticsSidebar(false);
}
};

window.addEventListener("resize", handleToggleWorkspaceAnalyticsSidebar);
handleToggleWorkspaceAnalyticsSidebar();
return () => window.removeEventListener("resize", handleToggleWorkspaceAnalyticsSidebar);
}, [themeStore]);

return (
<>
Expand All @@ -16,7 +38,7 @@ export const WorkspaceAnalyticsHeader = () => {
>
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle />
<div>
<div className="flex items-center justify-between w-full">
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"
Expand All @@ -25,9 +47,14 @@ export const WorkspaceAnalyticsHeader = () => {
}
/>
</Breadcrumbs>
{analytics_tab === 'custom' &&
<button className="block md:hidden" onClick={() => { themeStore.toggleWorkspaceAnalyticsSidebar() }}>
<PanelRight className={cn("w-4 h-4 block md:hidden", !themeStore.workspaceAnalyticsSidebarCollapsed ? "text-custom-primary-100" : "text-custom-text-200")} />
</button>
}
</div>
</div>
</div>
</>
);
};
});
16 changes: 8 additions & 8 deletions web/components/profile/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const ProfileSidebar = observer(() => {
const { workspaceSlug, userId } = router.query;
// store hooks
const { currentUser } = useUser();
const { theme: themStore } = useApplication();
const { theme: themeStore } = useApplication();
const ref = useRef<HTMLDivElement>(null);

const { data: userProjectsData } = useSWR(
Expand All @@ -41,9 +41,9 @@ export const ProfileSidebar = observer(() => {
);

useOutsideClickDetector(ref, () => {
if (themStore.profileSidebarCollapsed === false) {
if (themeStore.profileSidebarCollapsed === false) {
if (window.innerWidth < 768) {
themStore.toggleProfileSidebar();
themeStore.toggleProfileSidebar();
}
}
});
Expand All @@ -62,22 +62,22 @@ export const ProfileSidebar = observer(() => {
useEffect(() => {
const handleToggleProfileSidebar = () => {
if (window && window.innerWidth < 768) {
themStore.toggleProfileSidebar(true);
themeStore.toggleProfileSidebar(true);
}
if (window && themStore.profileSidebarCollapsed && window.innerWidth >= 768) {
themStore.toggleProfileSidebar(false);
if (window && themeStore.profileSidebarCollapsed && window.innerWidth >= 768) {
themeStore.toggleProfileSidebar(false);
}
};

window.addEventListener("resize", handleToggleProfileSidebar);
handleToggleProfileSidebar();
return () => window.removeEventListener("resize", handleToggleProfileSidebar);
}, [themStore]);
}, [themeStore]);

return (
<div
className={`flex-shrink-0 overflow-hidden overflow-y-auto shadow-custom-shadow-sm border-l border-custom-border-100 bg-custom-sidebar-background-100 h-full z-[5] fixed md:relative transition-all w-full md:w-[300px]`}
style={themStore.profileSidebarCollapsed ? { marginLeft: `${window?.innerWidth || 0}px` } : {}}
style={themeStore.profileSidebarCollapsed ? { marginLeft: `${window?.innerWidth || 0}px` } : {}}
>
{userProjectsData ? (
<>
Expand Down
15 changes: 10 additions & 5 deletions web/pages/[workspaceSlug]/analytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import { ANALYTICS_TABS } from "constants/analytics";
import { EUserWorkspaceRoles } from "constants/workspace";
// type
import { NextPageWithLayout } from "lib/types";
import { useRouter } from "next/router";

const AnalyticsPage: NextPageWithLayout = observer(() => {
const router = useRouter()
const { analytics_tab } = router.query
// theme
const { resolvedTheme } = useTheme();
// store hooks
Expand All @@ -38,17 +41,19 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
<>
{workspaceProjectIds && workspaceProjectIds.length > 0 ? (
<div className="flex h-full flex-col overflow-hidden bg-custom-background-100">
<Tab.Group as={Fragment}>
<Tab.List as="div" className="space-x-2 border-b border-custom-border-200 px-5 py-3">
<Tab.Group as={Fragment} defaultIndex={analytics_tab === 'custom' ? 1 : 0}>
<Tab.List as="div" className="flex space-x-2 border-b border-custom-border-200 px-0 md:px-5 py-0 md:py-3">
{ANALYTICS_TABS.map((tab) => (
<Tab
key={tab.key}
className={({ selected }) =>
`rounded-3xl border border-custom-border-200 px-4 py-2 text-xs hover:bg-custom-background-80 ${
selected ? "bg-custom-background-80" : ""
`rounded-0 w-full md:w-max md:rounded-3xl border-b md:border border-custom-border-200 focus:outline-none px-0 md:px-4 py-2 text-xs hover:bg-custom-background-80 ${selected ? "border-custom-primary-100 text-custom-primary-100 md:bg-custom-background-80 md:text-custom-text-200 md:border-custom-border-200" : "border-transparent"
}`
}
onClick={() => {}}
onClick={() => {
router.query.analytics_tab = tab.key
router.push(router)
}}
>
{tab.title}
</Tab>
Expand Down
Loading