feat: plane analytics (#1029)
* chore: global bar graph component * chore: global pie graph component * chore: global line graph component * chore: removed unnecessary file * chore: refactored global chart components to accept all props * chore: function to convert response to chart data * chore: global calendar graph component added * chore: global scatter plot graph component * feat: analytics boilerplate created * chore: null value for segment and project * chore: clean up file * chore: change project query param key * chore: export, refresh buttons, analytics table * fix: analytics fetch key error * chore: show only integer values in the y-axis * chore: custom x-axis tick values and bar colors * refactor: divide analytics page into granular components * chore: convert analytics page to modal, save analytics modal * fix: build error * fix: modal overflow issues, analytics loading screen * chore: custom tooltip, refactor: graphs folder structure * refactor: folder structure, chore: x-axis tick values for larger data * chore: code cleanup * chore: remove unnecessary files * fix: refresh analytics button on error * feat: scope and demand analytics * refactor: scope and demand and custom analytics folder structure * fix: dynamic import type * chore: minor updates * feat: project, cycle and module level analytics * style: project analytics modal * fix: merge conflicts
This commit is contained in:
parent
d7928f853d
commit
1a534a3c19
45 changed files with 1730 additions and 287 deletions
|
|
@ -19,8 +19,10 @@ import cycleServices from "services/cycles.service";
|
|||
import projectService from "services/project.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { AnalyticsProjectModal } from "components/analytics";
|
||||
// ui
|
||||
import { CustomMenu } from "components/ui";
|
||||
import { CustomMenu, SecondaryButton } from "components/ui";
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
// helpers
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
|
|
@ -37,6 +39,7 @@ import {
|
|||
const SingleCycle: React.FC = () => {
|
||||
const [cycleIssuesListModal, setCycleIssuesListModal] = useState(false);
|
||||
const [cycleSidebar, setCycleSidebar] = useState(true);
|
||||
const [analyticsModal, setAnalyticsModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
|
|
@ -148,6 +151,13 @@ const SingleCycle: React.FC = () => {
|
|||
className={`flex items-center gap-2 ${cycleSidebar ? "mr-[24rem]" : ""} duration-300`}
|
||||
>
|
||||
<IssuesFilterView />
|
||||
<SecondaryButton
|
||||
onClick={() => setAnalyticsModal(true)}
|
||||
className="!py-1.5 font-normal rounded-md text-brand-secondary"
|
||||
outline
|
||||
>
|
||||
Analytics
|
||||
</SecondaryButton>
|
||||
<button
|
||||
type="button"
|
||||
className={`grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-brand-surface-1 ${
|
||||
|
|
@ -160,7 +170,12 @@ const SingleCycle: React.FC = () => {
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<div className={`h-full ${cycleSidebar ? "mr-[24rem]" : ""} duration-300`}>
|
||||
<AnalyticsProjectModal isOpen={analyticsModal} onClose={() => setAnalyticsModal(false)} />
|
||||
<div
|
||||
className={`h-full ${cycleSidebar ? "mr-[24rem]" : ""} ${
|
||||
analyticsModal ? "mr-[50%]" : ""
|
||||
} duration-300`}
|
||||
>
|
||||
<IssuesView
|
||||
type="cycle"
|
||||
openIssuesListModal={openIssuesListModal}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
|
@ -12,8 +14,9 @@ import { IssueViewContextProvider } from "contexts/issue-view.context";
|
|||
import { truncateText } from "helpers/string.helper";
|
||||
// components
|
||||
import { IssuesFilterView, IssuesView } from "components/core";
|
||||
import { AnalyticsProjectModal } from "components/analytics";
|
||||
// ui
|
||||
import { PrimaryButton } from "components/ui";
|
||||
import { PrimaryButton, SecondaryButton } from "components/ui";
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
// icons
|
||||
import { PlusIcon } from "@heroicons/react/24/outline";
|
||||
|
|
@ -23,6 +26,8 @@ import type { NextPage } from "next";
|
|||
import { PROJECT_DETAILS } from "constants/fetch-keys";
|
||||
|
||||
const ProjectIssues: NextPage = () => {
|
||||
const [analyticsModal, setAnalyticsModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
|
|
@ -47,6 +52,13 @@ const ProjectIssues: NextPage = () => {
|
|||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<IssuesFilterView />
|
||||
<SecondaryButton
|
||||
onClick={() => setAnalyticsModal(true)}
|
||||
className="!py-1.5 rounded-md font-normal text-brand-secondary"
|
||||
outline
|
||||
>
|
||||
Analytics
|
||||
</SecondaryButton>
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
|
|
@ -60,6 +72,7 @@ const ProjectIssues: NextPage = () => {
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<AnalyticsProjectModal isOpen={analyticsModal} onClose={() => setAnalyticsModal(false)} />
|
||||
<IssuesView />
|
||||
</ProjectAuthorizationWrapper>
|
||||
</IssueViewContextProvider>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@ import { IssueViewContextProvider } from "contexts/issue-view.context";
|
|||
// components
|
||||
import { ExistingIssuesListModal, IssuesFilterView, IssuesView } from "components/core";
|
||||
import { ModuleDetailsSidebar } from "components/modules";
|
||||
import { AnalyticsProjectModal } from "components/analytics";
|
||||
// ui
|
||||
import { CustomMenu, EmptySpace, EmptySpaceItem, Spinner } from "components/ui";
|
||||
import { CustomMenu, EmptySpace, EmptySpaceItem, SecondaryButton, Spinner } from "components/ui";
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
// helpers
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
|
|
@ -43,6 +44,7 @@ import {
|
|||
const SingleModule: React.FC = () => {
|
||||
const [moduleIssuesListModal, setModuleIssuesListModal] = useState(false);
|
||||
const [moduleSidebar, setModuleSidebar] = useState(true);
|
||||
const [analyticsModal, setAnalyticsModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, moduleId } = router.query;
|
||||
|
|
@ -152,6 +154,13 @@ const SingleModule: React.FC = () => {
|
|||
className={`flex items-center gap-2 ${moduleSidebar ? "mr-[24rem]" : ""} duration-300`}
|
||||
>
|
||||
<IssuesFilterView />
|
||||
<SecondaryButton
|
||||
onClick={() => setAnalyticsModal(true)}
|
||||
className="!py-1.5 font-normal rounded-md text-brand-secondary"
|
||||
outline
|
||||
>
|
||||
Analytics
|
||||
</SecondaryButton>
|
||||
<button
|
||||
type="button"
|
||||
className={`grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-brand-surface-1 ${
|
||||
|
|
@ -164,6 +173,7 @@ const SingleModule: React.FC = () => {
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<AnalyticsProjectModal isOpen={analyticsModal} onClose={() => setAnalyticsModal(false)} />
|
||||
{moduleIssues ? (
|
||||
moduleIssues.length > 0 ? (
|
||||
<div className={`h-full ${moduleSidebar ? "mr-[24rem]" : ""} duration-300`}>
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ const ProjectModules: NextPage = () => {
|
|||
/>
|
||||
)
|
||||
) : (
|
||||
<Loader className="grid grid-cols-3 gap-4">
|
||||
<Loader className="grid grid-cols-3 gap-4 p-8">
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue