forked from github/plane
Merge branch 'preview' of github.com:makeplane/plane into develop
This commit is contained in:
commit
41a3cb708c
@ -10,6 +10,8 @@ import { CustomAnalyticsSelectBar, CustomAnalyticsMainContent, CustomAnalyticsSi
|
|||||||
import { IAnalyticsParams } from "@plane/types";
|
import { IAnalyticsParams } from "@plane/types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { ANALYTICS } from "constants/fetch-keys";
|
import { ANALYTICS } from "constants/fetch-keys";
|
||||||
|
import { cn } from "helpers/common.helper";
|
||||||
|
import { useApplication } from "hooks/store";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
additionalParams?: Partial<IAnalyticsParams>;
|
additionalParams?: Partial<IAnalyticsParams>;
|
||||||
@ -46,11 +48,13 @@ export const CustomAnalytics: React.FC<Props> = observer((props) => {
|
|||||||
workspaceSlug ? () => analyticsService.getAnalytics(workspaceSlug.toString(), params) : null
|
workspaceSlug ? () => analyticsService.getAnalytics(workspaceSlug.toString(), params) : null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { theme: themeStore } = useApplication();
|
||||||
|
|
||||||
const isProjectLevel = projectId ? true : false;
|
const isProjectLevel = projectId ? true : false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`flex flex-col-reverse overflow-hidden ${fullScreen ? "md:grid md:h-full md:grid-cols-4" : ""}`}>
|
<div className={cn("relative w-full h-full flex overflow-hidden", isProjectLevel ? "flex-col-reverse" : "")}>
|
||||||
<div className="col-span-3 flex h-full flex-col overflow-hidden">
|
<div className="w-full flex h-full flex-col overflow-hidden">
|
||||||
<CustomAnalyticsSelectBar
|
<CustomAnalyticsSelectBar
|
||||||
control={control}
|
control={control}
|
||||||
setValue={setValue}
|
setValue={setValue}
|
||||||
@ -61,16 +65,22 @@ export const CustomAnalytics: React.FC<Props> = observer((props) => {
|
|||||||
<CustomAnalyticsMainContent
|
<CustomAnalyticsMainContent
|
||||||
analytics={analytics}
|
analytics={analytics}
|
||||||
error={analyticsError}
|
error={analyticsError}
|
||||||
fullScreen={fullScreen}
|
|
||||||
params={params}
|
params={params}
|
||||||
|
fullScreen={fullScreen}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<CustomAnalyticsSidebar
|
|
||||||
analytics={analytics}
|
<div
|
||||||
params={params}
|
className={cn(
|
||||||
fullScreen={fullScreen}
|
"border-l border-custom-border-200 transition-all",
|
||||||
isProjectLevel={isProjectLevel}
|
!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>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -22,9 +22,8 @@ export const CustomAnalyticsSelectBar: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`grid items-center gap-4 px-5 py-2.5 ${isProjectLevel ? "grid-cols-3" : "grid-cols-2"} ${
|
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" : ""
|
||||||
fullScreen ? "md:py-5 lg:grid-cols-4" : ""
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{!isProjectLevel && (
|
{!isProjectLevel && (
|
||||||
<div>
|
<div>
|
||||||
|
@ -17,9 +17,9 @@ export const CustomAnalyticsSidebarProjectsList: React.FC<Props> = observer((pro
|
|||||||
const { getProjectById } = useProject();
|
const { getProjectById } = useProject();
|
||||||
|
|
||||||
return (
|
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>
|
<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) => {
|
{projectIds.map((projectId) => {
|
||||||
const project = getProjectById(projectId);
|
const project = getProjectById(projectId);
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
|
|||||||
<>
|
<>
|
||||||
{projectId ? (
|
{projectId ? (
|
||||||
cycleDetails ? (
|
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>
|
<h4 className="break-words font-medium">Analytics for {cycleDetails.name}</h4>
|
||||||
<div className="mt-4 space-y-4">
|
<div className="mt-4 space-y-4">
|
||||||
<div className="flex items-center gap-2 text-xs">
|
<div className="flex items-center gap-2 text-xs">
|
||||||
@ -52,7 +52,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : moduleDetails ? (
|
) : 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>
|
<h4 className="break-words font-medium">Analytics for {moduleDetails.name}</h4>
|
||||||
<div className="mt-4 space-y-4">
|
<div className="mt-4 space-y-4">
|
||||||
<div className="flex items-center gap-2 text-xs">
|
<div className="flex items-center gap-2 text-xs">
|
||||||
@ -78,7 +78,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
|
|||||||
</div>
|
</div>
|
||||||
</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">
|
<div className="flex items-center gap-1">
|
||||||
{projectDetails?.emoji ? (
|
{projectDetails?.emoji ? (
|
||||||
<div className="grid h-6 w-6 flex-shrink-0 place-items-center">{renderEmoji(projectDetails.emoji)}</div>
|
<div className="grid h-6 w-6 flex-shrink-0 place-items-center">{renderEmoji(projectDetails.emoji)}</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect, } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
@ -19,18 +19,18 @@ import { renderFormattedDate } from "helpers/date-time.helper";
|
|||||||
import { IAnalyticsParams, IAnalyticsResponse, IExportAnalyticsFormData, IWorkspace } from "@plane/types";
|
import { IAnalyticsParams, IAnalyticsResponse, IExportAnalyticsFormData, IWorkspace } from "@plane/types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { ANALYTICS } from "constants/fetch-keys";
|
import { ANALYTICS } from "constants/fetch-keys";
|
||||||
|
import { cn } from "helpers/common.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
analytics: IAnalyticsResponse | undefined;
|
analytics: IAnalyticsResponse | undefined;
|
||||||
params: IAnalyticsParams;
|
params: IAnalyticsParams;
|
||||||
fullScreen: boolean;
|
|
||||||
isProjectLevel: boolean;
|
isProjectLevel: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const analyticsService = new AnalyticsService();
|
const analyticsService = new AnalyticsService();
|
||||||
|
|
||||||
export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
|
export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
|
||||||
const { analytics, params, fullScreen, isProjectLevel = false } = props;
|
const { analytics, params, isProjectLevel = false } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||||
@ -138,18 +138,14 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const selectedProjects = params.project && params.project.length > 0 ? params.project : workspaceProjectIds;
|
const selectedProjects = params.project && params.project.length > 0 ? params.project : workspaceProjectIds;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<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" : "")}
|
||||||
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="flex flex-wrap items-center gap-2">
|
<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">
|
<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} />
|
<LayersIcon height={14} width={14} />
|
||||||
{analytics ? analytics.total : "..."} Issues
|
{analytics ? analytics.total : "..."} <div className={cn(isProjectLevel ? "hidden md:block" : "")}>Issues</div>
|
||||||
</div>
|
</div>
|
||||||
{isProjectLevel && (
|
{isProjectLevel && (
|
||||||
<div className="flex items-center gap-1 rounded-md bg-custom-background-80 px-3 py-1 text-xs text-custom-text-200">
|
<div className="flex items-center gap-1 rounded-md bg-custom-background-80 px-3 py-1 text-xs text-custom-text-200">
|
||||||
@ -158,36 +154,36 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
(cycleId
|
(cycleId
|
||||||
? cycleDetails?.created_at
|
? cycleDetails?.created_at
|
||||||
: moduleId
|
: moduleId
|
||||||
? moduleDetails?.created_at
|
? moduleDetails?.created_at
|
||||||
: projectDetails?.created_at) ?? ""
|
: projectDetails?.created_at) ?? ""
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-full overflow-hidden">
|
|
||||||
{fullScreen ? (
|
<div className={cn("h-full w-full overflow-hidden", isProjectLevel ? "hidden" : "block")}>
|
||||||
<>
|
<>
|
||||||
{!isProjectLevel && selectedProjects && selectedProjects.length > 0 && (
|
{!isProjectLevel && selectedProjects && selectedProjects.length > 0 && (
|
||||||
<CustomAnalyticsSidebarProjectsList projectIds={selectedProjects} />
|
<CustomAnalyticsSidebarProjectsList projectIds={selectedProjects} />
|
||||||
)}
|
)}
|
||||||
<CustomAnalyticsSidebarHeader />
|
<CustomAnalyticsSidebarHeader />
|
||||||
</>
|
</>
|
||||||
) : null}
|
|
||||||
</div>
|
</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
|
<Button
|
||||||
variant="neutral-primary"
|
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={() => {
|
onClick={() => {
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
mutate(ANALYTICS(workspaceSlug.toString(), params));
|
mutate(ANALYTICS(workspaceSlug.toString(), params));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Refresh
|
<div className={cn(isProjectLevel ? "hidden md:block" : "")}>Refresh</div>
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="primary" prependIcon={<Download className="h-3.5 w-3.5" />} onClick={exportAnalytics}>
|
<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>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,16 +20,15 @@ export const ProjectAnalyticsModalMainContent: React.FC<Props> = observer((props
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Group as={React.Fragment}>
|
<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) => (
|
{ANALYTICS_TABS.map((tab) => (
|
||||||
<Tab
|
<Tab
|
||||||
key={tab.key}
|
key={tab.key}
|
||||||
className={({ selected }) =>
|
className={({ selected }) =>
|
||||||
`rounded-3xl border border-custom-border-200 px-4 py-2 text-xs hover: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"
|
||||||
selected ? "bg-custom-background-80" : ""
|
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
onClick={() => {}}
|
onClick={() => { }}
|
||||||
>
|
>
|
||||||
{tab.title}
|
{tab.title}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -64,7 +64,7 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
|||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
))}
|
))}
|
||||||
</CustomMenu>
|
</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={
|
<PanelRight className={
|
||||||
cn("w-4 h-4 block md:hidden", !themStore.profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")
|
cn("w-4 h-4 block md:hidden", !themStore.profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")
|
||||||
} />
|
} />
|
||||||
|
@ -1,13 +1,35 @@
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { ArrowLeft, BarChart2 } from "lucide-react";
|
import { BarChart2, PanelRight } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs } from "@plane/ui";
|
import { Breadcrumbs } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
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";
|
||||||
|
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 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 (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -16,7 +38,7 @@ export const WorkspaceAnalyticsHeader = () => {
|
|||||||
>
|
>
|
||||||
<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 className="flex items-center justify-between w-full">
|
||||||
<Breadcrumbs>
|
<Breadcrumbs>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
@ -25,9 +47,14 @@ export const WorkspaceAnalyticsHeader = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -30,7 +30,7 @@ export const ProfileSidebar = observer(() => {
|
|||||||
const { workspaceSlug, userId } = router.query;
|
const { workspaceSlug, userId } = router.query;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { currentUser } = useUser();
|
const { currentUser } = useUser();
|
||||||
const { theme: themStore } = useApplication();
|
const { theme: themeStore } = useApplication();
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const { data: userProjectsData } = useSWR(
|
const { data: userProjectsData } = useSWR(
|
||||||
@ -41,9 +41,9 @@ export const ProfileSidebar = observer(() => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useOutsideClickDetector(ref, () => {
|
useOutsideClickDetector(ref, () => {
|
||||||
if (themStore.profileSidebarCollapsed === false) {
|
if (themeStore.profileSidebarCollapsed === false) {
|
||||||
if (window.innerWidth < 768) {
|
if (window.innerWidth < 768) {
|
||||||
themStore.toggleProfileSidebar();
|
themeStore.toggleProfileSidebar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -62,22 +62,22 @@ export const ProfileSidebar = observer(() => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleToggleProfileSidebar = () => {
|
const handleToggleProfileSidebar = () => {
|
||||||
if (window && window.innerWidth < 768) {
|
if (window && window.innerWidth < 768) {
|
||||||
themStore.toggleProfileSidebar(true);
|
themeStore.toggleProfileSidebar(true);
|
||||||
}
|
}
|
||||||
if (window && themStore.profileSidebarCollapsed && window.innerWidth >= 768) {
|
if (window && themeStore.profileSidebarCollapsed && window.innerWidth >= 768) {
|
||||||
themStore.toggleProfileSidebar(false);
|
themeStore.toggleProfileSidebar(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("resize", handleToggleProfileSidebar);
|
window.addEventListener("resize", handleToggleProfileSidebar);
|
||||||
handleToggleProfileSidebar();
|
handleToggleProfileSidebar();
|
||||||
return () => window.removeEventListener("resize", handleToggleProfileSidebar);
|
return () => window.removeEventListener("resize", handleToggleProfileSidebar);
|
||||||
}, [themStore]);
|
}, [themeStore]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<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]`}
|
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 ? (
|
{userProjectsData ? (
|
||||||
<>
|
<>
|
||||||
|
@ -15,8 +15,11 @@ import { ANALYTICS_TABS } from "constants/analytics";
|
|||||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
// type
|
// type
|
||||||
import { NextPageWithLayout } from "lib/types";
|
import { NextPageWithLayout } from "lib/types";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
const AnalyticsPage: NextPageWithLayout = observer(() => {
|
const AnalyticsPage: NextPageWithLayout = observer(() => {
|
||||||
|
const router = useRouter()
|
||||||
|
const { analytics_tab } = router.query
|
||||||
// theme
|
// theme
|
||||||
const { resolvedTheme } = useTheme();
|
const { resolvedTheme } = useTheme();
|
||||||
// store hooks
|
// store hooks
|
||||||
@ -38,17 +41,19 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
|
|||||||
<>
|
<>
|
||||||
{workspaceProjectIds && workspaceProjectIds.length > 0 ? (
|
{workspaceProjectIds && workspaceProjectIds.length > 0 ? (
|
||||||
<div className="flex h-full flex-col overflow-hidden bg-custom-background-100">
|
<div className="flex h-full flex-col overflow-hidden bg-custom-background-100">
|
||||||
<Tab.Group as={Fragment}>
|
<Tab.Group as={Fragment} defaultIndex={analytics_tab === 'custom' ? 1 : 0}>
|
||||||
<Tab.List as="div" className="space-x-2 border-b border-custom-border-200 px-5 py-3">
|
<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) => (
|
{ANALYTICS_TABS.map((tab) => (
|
||||||
<Tab
|
<Tab
|
||||||
key={tab.key}
|
key={tab.key}
|
||||||
className={({ selected }) =>
|
className={({ selected }) =>
|
||||||
`rounded-3xl border border-custom-border-200 px-4 py-2 text-xs hover: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"
|
||||||
selected ? "bg-custom-background-80" : ""
|
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
onClick={() => {}}
|
onClick={() => {
|
||||||
|
router.query.analytics_tab = tab.key
|
||||||
|
router.push(router)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{tab.title}
|
{tab.title}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -8,10 +8,12 @@ export interface IThemeStore {
|
|||||||
theme: string | null;
|
theme: string | null;
|
||||||
sidebarCollapsed: boolean | undefined;
|
sidebarCollapsed: boolean | undefined;
|
||||||
profileSidebarCollapsed: boolean | undefined;
|
profileSidebarCollapsed: boolean | undefined;
|
||||||
|
workspaceAnalyticsSidebarCollapsed: boolean | undefined;
|
||||||
// actions
|
// actions
|
||||||
toggleSidebar: (collapsed?: boolean) => void;
|
toggleSidebar: (collapsed?: boolean) => void;
|
||||||
setTheme: (theme: any) => void;
|
setTheme: (theme: any) => void;
|
||||||
toggleProfileSidebar: (collapsed?: boolean) => void;
|
toggleProfileSidebar: (collapsed?: boolean) => void;
|
||||||
|
toggleWorkspaceAnalyticsSidebar: (collapsed?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ThemeStore implements IThemeStore {
|
export class ThemeStore implements IThemeStore {
|
||||||
@ -19,6 +21,7 @@ export class ThemeStore implements IThemeStore {
|
|||||||
sidebarCollapsed: boolean | undefined = undefined;
|
sidebarCollapsed: boolean | undefined = undefined;
|
||||||
theme: string | null = null;
|
theme: string | null = null;
|
||||||
profileSidebarCollapsed: boolean | undefined = undefined;
|
profileSidebarCollapsed: boolean | undefined = undefined;
|
||||||
|
workspaceAnalyticsSidebarCollapsed: boolean | undefined = undefined;
|
||||||
// root store
|
// root store
|
||||||
rootStore;
|
rootStore;
|
||||||
|
|
||||||
@ -28,10 +31,12 @@ export class ThemeStore implements IThemeStore {
|
|||||||
sidebarCollapsed: observable.ref,
|
sidebarCollapsed: observable.ref,
|
||||||
theme: observable.ref,
|
theme: observable.ref,
|
||||||
profileSidebarCollapsed: observable.ref,
|
profileSidebarCollapsed: observable.ref,
|
||||||
|
workspaceAnalyticsSidebarCollapsed: observable.ref,
|
||||||
// action
|
// action
|
||||||
toggleSidebar: action,
|
toggleSidebar: action,
|
||||||
setTheme: action,
|
setTheme: action,
|
||||||
toggleProfileSidebar: action,
|
toggleProfileSidebar: action,
|
||||||
|
toggleWorkspaceAnalyticsSidebar: action
|
||||||
// computed
|
// computed
|
||||||
});
|
});
|
||||||
// root store
|
// root store
|
||||||
@ -64,6 +69,19 @@ export class ThemeStore implements IThemeStore {
|
|||||||
localStorage.setItem("profile_sidebar_collapsed", this.profileSidebarCollapsed.toString());
|
localStorage.setItem("profile_sidebar_collapsed", this.profileSidebarCollapsed.toString());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the profile sidebar collapsed state
|
||||||
|
* @param collapsed
|
||||||
|
*/
|
||||||
|
toggleWorkspaceAnalyticsSidebar = (collapsed?: boolean) => {
|
||||||
|
if (collapsed === undefined) {
|
||||||
|
this.workspaceAnalyticsSidebarCollapsed = !this.workspaceAnalyticsSidebarCollapsed;
|
||||||
|
} else {
|
||||||
|
this.workspaceAnalyticsSidebarCollapsed = collapsed;
|
||||||
|
}
|
||||||
|
localStorage.setItem("workspace_analytics_sidebar_collapsed", this.workspaceAnalyticsSidebarCollapsed.toString());
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the user theme and applies it to the platform
|
* Sets the user theme and applies it to the platform
|
||||||
* @param _theme
|
* @param _theme
|
||||||
|
Loading…
Reference in New Issue
Block a user