[WEB-4109] chore: remove analytics duration filter (#7073)

* chore: remove analytics duration filter

* removed subtitle from title and date_filter from service call

* chore: removed the date filter

* bottom text of insight trend card

* chore: changed issue manager

* fix: limited items in table

* fix: removed unnecessary props from data-table

---------

Co-authored-by: JayashTripathy <jayashtripathy371@gmail.com>
Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
This commit is contained in:
Aaryan Khandelwal 2025-05-16 19:16:30 +05:30 committed by GitHub
parent 084cc75726
commit ba158d5d6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 46 additions and 35 deletions

View file

@ -1,9 +1,10 @@
from rest_framework.response import Response
from rest_framework import status
from typing import Dict, List, Any
from datetime import timedelta
from django.db.models import QuerySet, Q, Count
from django.http import HttpRequest
from django.db.models.functions import TruncMonth
from django.utils import timezone
from plane.app.views.base import BaseAPIView
from plane.app.permissions import ROLE, allow_permission
@ -15,14 +16,10 @@ from plane.db.models import (
Module,
IssueView,
ProjectPage,
Workspace
)
from django.db.models import (
Q,
Count,
)
from plane.utils.build_chart import build_analytics_chart
from datetime import timedelta
from plane.bgtasks.analytic_plot_export import export_analytics_to_csv_email
from plane.utils.date_utils import (
get_analytics_filters,
@ -125,7 +122,7 @@ class AdvanceAnalyticsEndpoint(AdvanceAnalyticsBaseView):
def get_work_items_stats(self) -> Dict[str, Dict[str, int]]:
base_queryset = Issue.objects.filter(**self.filters["base_filters"])
base_queryset = Issue.issue_objects.filter(**self.filters["base_filters"])
return {
"total_work_items": self.get_filtered_counts(base_queryset),
@ -263,6 +260,7 @@ class AdvanceAnalyticsChartEndpoint(AdvanceAnalyticsBaseView):
"assignees", "labels", "issue_module__module", "issue_cycle__cycle"
)
)
# Apply date range filter if available
if self.filters["chart_period_range"]:
start_date, end_date = self.filters["chart_period_range"]
@ -270,41 +268,54 @@ class AdvanceAnalyticsChartEndpoint(AdvanceAnalyticsBaseView):
created_at__date__gte=start_date, created_at__date__lte=end_date
)
# Get daily stats with optimized query
daily_stats = (
queryset.values("created_at__date")
# Annotate by month and count
monthly_stats = (
queryset.annotate(month=TruncMonth("created_at"))
.values("month")
.annotate(
created_count=Count("id"),
completed_count=Count("id", filter=Q(completed_at__isnull=False)),
)
.order_by("created_at__date")
.order_by("month")
)
# Create a dictionary of existing stats with summed counts
# Create dictionary of month -> counts
stats_dict = {
stat["created_at__date"].strftime("%Y-%m-%d"): {
stat["month"].strftime("%Y-%m-%d"): {
"created_count": stat["created_count"],
"completed_count": stat["completed_count"],
}
for stat in daily_stats
for stat in monthly_stats
}
# Generate data for all days in the range
# Generate monthly data (ensure months with 0 count are included)
data = []
current_date = start_date
while current_date <= end_date:
date_str = current_date.strftime("%Y-%m-%d")
workspace = Workspace.objects.get(slug=self._workspace_slug)
start_date = workspace.created_at.date().replace(day=1)
# include the current date at the end
end_date = timezone.now().date()
last_month = end_date.replace(day=1)
current_month = start_date
while current_month <= last_month:
date_str = current_month.strftime("%Y-%m-%d")
stats = stats_dict.get(date_str, {"created_count": 0, "completed_count": 0})
data.append(
{
"key": date_str,
"name": date_str,
"count": stats["created_count"] + stats["completed_count"],
"count": stats[
"created_count"
], # <- Total created issues in that month
"completed_issues": stats["completed_count"],
"created_issues": stats["created_count"],
}
)
current_date += timedelta(days=1)
# Move to next month
if current_month.month == 12:
current_month = current_month.replace(year=current_month.year + 1, month=1)
else:
current_month = current_month.replace(month=current_month.month + 1)
schema = {
"completed_issues": "completed_issues",

View file

@ -129,7 +129,7 @@ def get_chart_period_range(
"last_3_months": (today - timedelta(days=90), today),
}
return period_ranges.get(date_filter, period_ranges["last_7_days"])
return period_ranges.get(date_filter, None)
def get_analytics_filters(
@ -165,6 +165,8 @@ def get_analytics_filters(
"workspace__slug": slug,
"project__project_projectmember__member": user,
"project__project_projectmember__is_active": True,
"project__deleted_at__isnull": True,
"project__archived_at__isnull": True,
}
# Project filters
@ -172,6 +174,8 @@ def get_analytics_filters(
"workspace__slug": slug,
"project_projectmember__member": user,
"project_projectmember__is_active": True,
"project__deleted_at__isnull": True,
"project__archived_at__isnull": True,
}
# Add project IDs to filters if provided

View file

@ -19,14 +19,14 @@ const AnalyticsFilterActions = observer(() => {
}}
projectIds={workspaceProjectIds}
/>
<DurationDropdown
{/* <DurationDropdown
buttonVariant="border-with-text"
value={selectedDuration}
onChange={(val) => {
updateSelectedDuration(val);
}}
dropdownArrow
/>
/> */}
</div>
);
});

View file

@ -17,7 +17,7 @@ const AnalyticsSectionWrapper: React.FC<Props> = (props) => {
{title && (
<div className="flex items-center gap-2 ">
<h1 className={"text-lg font-medium"}>{title}</h1>
{subtitle && <p className="text-lg text-custom-text-300"> {subtitle}</p>}
{/* {subtitle && <p className="text-lg text-custom-text-300"> • {subtitle}</p>} */}
</div>
)}
{actions}

View file

@ -30,12 +30,12 @@ const InsightCard = (props: InsightCardProps) => {
{!isLoading ? (
<div className="flex flex-col gap-1">
<div className="text-2xl font-bold text-custom-text-100">{count}</div>
{percentage && (
{/* {percentage && (
<div className="flex gap-1 text-xs text-custom-text-300">
<TrendPiece percentage={percentage} size="xs" />
{versus && <div>vs {versus}</div>}
</div>
)}
)} */}
</div>
) : (
<Loader.Item height="50px" width="100%" />

View file

@ -51,14 +51,10 @@ export function DataTable<TData, TValue>({ columns, data, searchPlaceholder, act
rowSelection,
columnFilters,
},
enableRowSelection: true,
onRowSelectionChange: setRowSelection,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
onColumnVisibilityChange: setColumnVisibility,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),

View file

@ -34,7 +34,7 @@ const ProjectInsights = observer(() => {
`radar-chart-${workspaceSlug}-${selectedDuration}-${selectedProjects}`,
() =>
analyticsV2Service.getAdvanceAnalyticsCharts<TChartData<string, string>[]>(workspaceSlug, "projects", {
date_filter: selectedDuration,
// date_filter: selectedDuration,
...(selectedProjects?.length > 0 && { project_ids: selectedProjects?.join(",") }),
})
);

View file

@ -26,7 +26,7 @@ const TotalInsights: React.FC<{ analyticsType: TAnalyticsTabsV2Base; peekView?:
`total-insights-${analyticsType}-${selectedDuration}-${selectedProjects}`,
() =>
analyticsV2Service.getAdvanceAnalytics<IAnalyticsResponseV2>(workspaceSlug, analyticsType, {
date_filter: selectedDuration,
// date_filter: selectedDuration,
...(selectedProjects?.length > 0 ? { project_ids: selectedProjects.join(",") } : {}),
})
);

View file

@ -28,7 +28,7 @@ const CreatedVsResolved = observer(() => {
`created-vs-resolved-${workspaceSlug}-${selectedDuration}-${selectedProjects}`,
() =>
analyticsV2Service.getAdvanceAnalyticsCharts<IChartResponseV2>(workspaceSlug, "work-items", {
date_filter: selectedDuration,
// date_filter: selectedDuration,
...(selectedProjects?.length > 0 && { project_ids: selectedProjects?.join(",") }),
})
);

View file

@ -57,7 +57,7 @@ const PriorityChart = observer((props: Props) => {
`customized-insights-chart-${workspaceSlug}-${selectedDuration}-${selectedProjects}-${props.x_axis}-${props.y_axis}-${props.group_by}`,
() =>
analyticsV2Service.getAdvanceAnalyticsCharts<TChart>(workspaceSlug, "custom-work-items", {
date_filter: selectedDuration,
// date_filter: selectedDuration,
...(selectedProjects?.length > 0 && { project_ids: selectedProjects?.join(",") }),
...props,
})

View file

@ -30,7 +30,7 @@ const WorkItemsInsightTable = observer(() => {
`insights-table-work-items-${workspaceSlug}-${selectedDuration}-${selectedProjects}`,
() =>
analyticsV2Service.getAdvanceAnalyticsStats<WorkItemInsightColumns[]>(workspaceSlug, "work-items", {
date_filter: selectedDuration,
// date_filter: selectedDuration,
...(selectedProjects?.length > 0 ? { project_ids: selectedProjects.join(",") } : {}),
})
);