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:
Aaryan Khandelwal 2023-05-11 17:38:46 +05:30 committed by GitHub
parent d7928f853d
commit 1a534a3c19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 1730 additions and 287 deletions

View file

@ -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}

View file

@ -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>

View file

@ -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`}>

View file

@ -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" />