diff --git a/apiserver/plane/app/serializers/__init__.py b/apiserver/plane/app/serializers/__init__.py index 094328fff..60c292336 100644 --- a/apiserver/plane/app/serializers/__init__.py +++ b/apiserver/plane/app/serializers/__init__.py @@ -104,6 +104,7 @@ from .estimate import ( EstimateSerializer, EstimatePointSerializer, EstimateReadSerializer, + WorkspaceEstimateSerializer, ) from .inbox import ( diff --git a/apiserver/plane/app/serializers/estimate.py b/apiserver/plane/app/serializers/estimate.py index a563c6956..675390080 100644 --- a/apiserver/plane/app/serializers/estimate.py +++ b/apiserver/plane/app/serializers/estimate.py @@ -61,3 +61,18 @@ class EstimateReadSerializer(BaseSerializer): "name", "description", ] + + +class WorkspaceEstimateSerializer(BaseSerializer): + points = EstimatePointSerializer(read_only=True, many=True) + + class Meta: + model = Estimate + fields = "__all__" + read_only_fields = [ + "points", + "name", + "description", + ] + + diff --git a/apiserver/plane/app/serializers/issue.py b/apiserver/plane/app/serializers/issue.py index 0b3b666ce..4f1767ccb 100644 --- a/apiserver/plane/app/serializers/issue.py +++ b/apiserver/plane/app/serializers/issue.py @@ -259,14 +259,17 @@ class IssuePropertySerializer(BaseSerializer): class LabelSerializer(BaseSerializer): - workspace_detail = WorkspaceLiteSerializer( - source="workspace", read_only=True - ) - project_detail = ProjectLiteSerializer(source="project", read_only=True) - class Meta: model = Label - fields = "__all__" + fields = [ + "parent", + "name", + "color", + "id", + "project_id", + "workspace_id", + "sort_order", + ] read_only_fields = [ "workspace", "project", @@ -295,8 +298,12 @@ class IssueLabelSerializer(BaseSerializer): class IssueRelationSerializer(BaseSerializer): id = serializers.UUIDField(source="related_issue.id", read_only=True) - project_id = serializers.PrimaryKeyRelatedField(source="related_issue.project_id", read_only=True) - sequence_id = serializers.IntegerField(source="related_issue.sequence_id", read_only=True) + project_id = serializers.PrimaryKeyRelatedField( + source="related_issue.project_id", read_only=True + ) + sequence_id = serializers.IntegerField( + source="related_issue.sequence_id", read_only=True + ) relation_type = serializers.CharField(read_only=True) class Meta: @@ -315,8 +322,12 @@ class IssueRelationSerializer(BaseSerializer): class RelatedIssueSerializer(BaseSerializer): id = serializers.UUIDField(source="issue.id", read_only=True) - project_id = serializers.PrimaryKeyRelatedField(source="issue.project_id", read_only=True) - sequence_id = serializers.IntegerField(source="issue.sequence_id", read_only=True) + project_id = serializers.PrimaryKeyRelatedField( + source="issue.project_id", read_only=True + ) + sequence_id = serializers.IntegerField( + source="issue.sequence_id", read_only=True + ) relation_type = serializers.CharField(read_only=True) class Meta: diff --git a/apiserver/plane/app/serializers/state.py b/apiserver/plane/app/serializers/state.py index 25dded62d..773d8e461 100644 --- a/apiserver/plane/app/serializers/state.py +++ b/apiserver/plane/app/serializers/state.py @@ -8,7 +8,17 @@ from plane.db.models import State class StateSerializer(BaseSerializer): class Meta: model = State - fields = "__all__" + fields = [ + "id", + "project_id", + "workspace_id", + "name", + "color", + "group", + "default", + "description", + "sequence", + ] read_only_fields = [ "workspace", "project", diff --git a/apiserver/plane/app/urls/workspace.py b/apiserver/plane/app/urls/workspace.py index d2d8f5c06..7e64e586a 100644 --- a/apiserver/plane/app/urls/workspace.py +++ b/apiserver/plane/app/urls/workspace.py @@ -20,6 +20,8 @@ from plane.app.views import ( WorkspaceLabelsEndpoint, WorkspaceProjectMemberEndpoint, WorkspaceUserPropertiesEndpoint, + WorkspaceStatesEndpoint, + WorkspaceEstimatesEndpoint, ) @@ -207,4 +209,14 @@ urlpatterns = [ WorkspaceUserPropertiesEndpoint.as_view(), name="workspace-user-filters", ), + path( + "workspaces//states/", + WorkspaceStatesEndpoint.as_view(), + name="workspace-state", + ), + path( + "workspaces//estimates/", + WorkspaceEstimatesEndpoint.as_view(), + name="workspace-estimate", + ), ] diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py index d3c4f4baf..9c71e29ab 100644 --- a/apiserver/plane/app/views/__init__.py +++ b/apiserver/plane/app/views/__init__.py @@ -47,6 +47,8 @@ from .workspace import ( WorkspaceLabelsEndpoint, WorkspaceProjectMemberEndpoint, WorkspaceUserPropertiesEndpoint, + WorkspaceStatesEndpoint, + WorkspaceEstimatesEndpoint, ) from .state import StateViewSet from .view import ( diff --git a/apiserver/plane/app/views/issue.py b/apiserver/plane/app/views/issue.py index ec8b4da5e..0d27b806d 100644 --- a/apiserver/plane/app/views/issue.py +++ b/apiserver/plane/app/views/issue.py @@ -83,6 +83,7 @@ from plane.utils.grouper import group_results from plane.utils.issue_filters import issue_filters from collections import defaultdict + class IssueViewSet(WebhookMixin, BaseViewSet): def get_serializer_class(self): return ( @@ -821,7 +822,9 @@ class SubIssuesEndpoint(BaseAPIView): _ = Issue.objects.bulk_update(sub_issues, ["parent"], batch_size=10) - updated_sub_issues = Issue.issue_objects.filter(id__in=sub_issue_ids).annotate(state_group=F("state__group")) + updated_sub_issues = Issue.issue_objects.filter( + id__in=sub_issue_ids + ).annotate(state_group=F("state__group")) # Track the issue _ = [ @@ -836,7 +839,7 @@ class SubIssuesEndpoint(BaseAPIView): ) for sub_issue_id in sub_issue_ids ] - + # create's a dict with state group name with their respective issue id's result = defaultdict(list) for sub_issue in updated_sub_issues: @@ -853,7 +856,6 @@ class SubIssuesEndpoint(BaseAPIView): }, status=status.HTTP_200_OK, ) - class IssueLinkViewSet(BaseViewSet): diff --git a/apiserver/plane/app/views/state.py b/apiserver/plane/app/views/state.py index 9c83cf006..242061e18 100644 --- a/apiserver/plane/app/views/state.py +++ b/apiserver/plane/app/views/state.py @@ -9,9 +9,12 @@ from rest_framework.response import Response from rest_framework import status # Module imports -from . import BaseViewSet +from . import BaseViewSet, BaseAPIView from plane.app.serializers import StateSerializer -from plane.app.permissions import ProjectEntityPermission +from plane.app.permissions import ( + ProjectEntityPermission, + WorkspaceEntityPermission, +) from plane.db.models import State, Issue @@ -22,9 +25,6 @@ class StateViewSet(BaseViewSet): ProjectEntityPermission, ] - def perform_create(self, serializer): - serializer.save(project_id=self.kwargs.get("project_id")) - def get_queryset(self): return self.filter_queryset( super() diff --git a/apiserver/plane/app/views/workspace.py b/apiserver/plane/app/views/workspace.py index ec878bcb0..159fbcb08 100644 --- a/apiserver/plane/app/views/workspace.py +++ b/apiserver/plane/app/views/workspace.py @@ -46,10 +46,14 @@ from plane.app.serializers import ( WorkspaceMemberMeSerializer, ProjectMemberRoleSerializer, WorkspaceUserPropertiesSerializer, + WorkspaceEstimateSerializer, + StateSerializer, + LabelSerializer, ) from plane.app.views.base import BaseAPIView from . import BaseViewSet from plane.db.models import ( + State, User, Workspace, WorkspaceMemberInvite, @@ -67,6 +71,8 @@ from plane.db.models import ( CycleIssue, IssueReaction, WorkspaceUserProperties, + Estimate, + EstimatePoint, ) from plane.app.permissions import ( WorkSpaceBasePermission, @@ -1358,7 +1364,9 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView): .values("count") ) .annotate( - sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id")) + sub_issues_count=Issue.issue_objects.filter( + parent=OuterRef("id") + ) .order_by() .annotate(count=Func(F("id"), function="Count")) .values("count") @@ -1441,10 +1449,46 @@ class WorkspaceLabelsEndpoint(BaseAPIView): labels = Label.objects.filter( workspace__slug=slug, project__project_projectmember__member=request.user, - ).values( - "parent", "name", "color", "id", "project_id", "workspace__slug" ) - return Response(labels, status=status.HTTP_200_OK) + serializer = LabelSerializer(labels, many=True).data + return Response(serializer, status=status.HTTP_200_OK) + + +class WorkspaceStatesEndpoint(BaseAPIView): + permission_classes = [ + WorkspaceEntityPermission, + ] + + def get(self, request, slug): + states = State.objects.filter( + workspace__slug=slug, + project__project_projectmember__member=request.user, + ) + serializer = StateSerializer(states, many=True).data + return Response(serializer, status=status.HTTP_200_OK) + + +class WorkspaceEstimatesEndpoint(BaseAPIView): + permission_classes = [ + WorkspaceEntityPermission, + ] + + def get(self, request, slug): + estimate_ids = Project.objects.filter( + workspace__slug=slug, estimate__isnull=False + ).values_list("estimate_id", flat=True) + estimates = Estimate.objects.filter( + pk__in=estimate_ids + ).prefetch_related( + Prefetch( + "points", + queryset=EstimatePoint.objects.select_related( + "estimate", "workspace", "project" + ), + ) + ) + serializer = WorkspaceEstimateSerializer(estimates, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) class WorkspaceUserPropertiesEndpoint(BaseAPIView): diff --git a/packages/types/src/issues.d.ts b/packages/types/src/issues.d.ts index da6db8062..c54943f90 100644 --- a/packages/types/src/issues.d.ts +++ b/packages/types/src/issues.d.ts @@ -109,17 +109,10 @@ export type IssuePriorities = { export interface IIssueLabel { id: string; - created_at: Date; - updated_at: Date; name: string; - description: string; color: string; - created_by: string; - updated_by: string; - project: string; - project_detail: IProjectLite; - workspace: string; - workspace_detail: IWorkspaceLite; + project_id: string; + workspace_id: string; parent: string | null; sort_order: number; } diff --git a/packages/types/src/state.d.ts b/packages/types/src/state.d.ts index 822b99f17..120b216da 100644 --- a/packages/types/src/state.d.ts +++ b/packages/types/src/state.d.ts @@ -5,20 +5,13 @@ export type TStateGroups = "backlog" | "unstarted" | "started" | "completed" | " export interface IState { readonly id: string; color: string; - readonly created_at: Date; - readonly created_by: string; default: boolean; description: string; group: TStateGroups; name: string; - project: string; - readonly project_detail: IProjectLite; + project_id: string; sequence: number; - readonly slug: string; - readonly updated_at: Date; - readonly updated_by: string; - workspace: string; - workspace_detail: IWorkspaceLite; + workspace_id: string; } export interface IStateLite { diff --git a/web/components/core/activity.tsx b/web/components/core/activity.tsx index 99396dda2..e49205459 100644 --- a/web/components/core/activity.tsx +++ b/web/components/core/activity.tsx @@ -72,9 +72,7 @@ const UserLink = ({ activity }: { activity: IIssueActivity }) => { const LabelPill = observer(({ labelId, workspaceSlug }: { labelId: string; workspaceSlug: string }) => { // store hooks - const { - workspace: { workspaceLabels, fetchWorkspaceLabels }, - } = useLabel(); + const { workspaceLabels, fetchWorkspaceLabels } = useLabel(); useEffect(() => { if (!workspaceLabels) fetchWorkspaceLabels(workspaceSlug); diff --git a/web/components/dropdowns/estimate.tsx b/web/components/dropdowns/estimate.tsx index 9138b2bea..241a695fa 100644 --- a/web/components/dropdowns/estimate.tsx +++ b/web/components/dropdowns/estimate.tsx @@ -158,17 +158,12 @@ export const EstimateDropdown: React.FC = observer((props) => { const filteredOptions = query === "" ? options : options?.filter((o) => o.query.toLowerCase().includes(query.toLowerCase())); - // fetch cycles of the project if not already present in the store - useEffect(() => { - if (!workspaceSlug) return; - - if (!activeEstimate) fetchProjectEstimates(workspaceSlug, projectId); - }, [activeEstimate, fetchProjectEstimates, projectId, workspaceSlug]); - - const selectedEstimate = value !== null ? getEstimatePointValue(value) : null; + const selectedEstimate = value !== null ? getEstimatePointValue(value, projectId) : null; const openDropdown = () => { setIsOpen(true); + + if (!activeEstimate && workspaceSlug) fetchProjectEstimates(workspaceSlug, projectId); if (referenceElement) referenceElement.focus(); }; const closeDropdown = () => setIsOpen(false); diff --git a/web/components/dropdowns/member/project-member.tsx b/web/components/dropdowns/member/project-member.tsx index 1e6856274..581978d9d 100644 --- a/web/components/dropdowns/member/project-member.tsx +++ b/web/components/dropdowns/member/project-member.tsx @@ -93,14 +93,10 @@ export const ProjectMemberDropdown: React.FC = observer((props) => { }; if (multiple) comboboxProps.multiple = true; - useEffect(() => { - if (!workspaceSlug) return; - - if (!projectMemberIds) fetchProjectMembers(workspaceSlug, projectId); - }, [fetchProjectMembers, projectId, projectMemberIds, workspaceSlug]); - const openDropdown = () => { setIsOpen(true); + + if (!projectMemberIds && workspaceSlug) fetchProjectMembers(workspaceSlug, projectId); if (referenceElement) referenceElement.focus(); }; const closeDropdown = () => setIsOpen(false); diff --git a/web/components/dropdowns/state.tsx b/web/components/dropdowns/state.tsx index ba48af4bd..25073901a 100644 --- a/web/components/dropdowns/state.tsx +++ b/web/components/dropdowns/state.tsx @@ -142,17 +142,12 @@ export const StateDropdown: React.FC = observer((props) => { const filteredOptions = query === "" ? options : options?.filter((o) => o.query.toLowerCase().includes(query.toLowerCase())); - // fetch states of the project if not already present in the store - useEffect(() => { - if (!workspaceSlug) return; - - if (!statesList) fetchProjectStates(workspaceSlug, projectId); - }, [fetchProjectStates, projectId, statesList, workspaceSlug]); const selectedState = getStateById(value); const openDropdown = () => { setIsOpen(true); + if (!statesList && workspaceSlug) fetchProjectStates(workspaceSlug, projectId); if (referenceElement) referenceElement.focus(); }; const closeDropdown = () => setIsOpen(false); diff --git a/web/components/headers/cycle-issues.tsx b/web/components/headers/cycle-issues.tsx index a616e4470..f97be5244 100644 --- a/web/components/headers/cycle-issues.tsx +++ b/web/components/headers/cycle-issues.tsx @@ -75,9 +75,7 @@ export const CycleIssuesHeader: React.FC = observer(() => { } = useUser(); const { currentProjectDetails } = useProject(); const { projectStates } = useProjectState(); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { project: { projectMemberIds }, } = useMember(); diff --git a/web/components/headers/global-issues.tsx b/web/components/headers/global-issues.tsx index aa9a32bc9..b6aeda154 100644 --- a/web/components/headers/global-issues.tsx +++ b/web/components/headers/global-issues.tsx @@ -45,9 +45,7 @@ export const GlobalIssuesHeader: React.FC = observer((props) => { const { membership: { currentWorkspaceRole }, } = useUser(); - const { - workspace: { workspaceLabels }, - } = useLabel(); + const { workspaceLabels } = useLabel(); const { workspace: { workspaceMemberIds }, } = useMember(); diff --git a/web/components/headers/module-issues.tsx b/web/components/headers/module-issues.tsx index 9cfc9c1b3..3b60e69ab 100644 --- a/web/components/headers/module-issues.tsx +++ b/web/components/headers/module-issues.tsx @@ -77,9 +77,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => { membership: { currentProjectRole }, } = useUser(); const { currentProjectDetails } = useProject(); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { projectStates } = useProjectState(); const { project: { projectMemberIds }, diff --git a/web/components/headers/project-archived-issues.tsx b/web/components/headers/project-archived-issues.tsx index e20687ec0..76eaa2eb6 100644 --- a/web/components/headers/project-archived-issues.tsx +++ b/web/components/headers/project-archived-issues.tsx @@ -25,9 +25,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => { } = useIssues(EIssuesStoreType.ARCHIVED); const { currentProjectDetails } = useProject(); const { projectStates } = useProjectState(); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { project: { projectMemberIds }, } = useMember(); diff --git a/web/components/headers/project-draft-issues.tsx b/web/components/headers/project-draft-issues.tsx index dcbfbe0a4..16a6b7691 100644 --- a/web/components/headers/project-draft-issues.tsx +++ b/web/components/headers/project-draft-issues.tsx @@ -22,9 +22,7 @@ export const ProjectDraftIssueHeader: FC = observer(() => { } = useIssues(EIssuesStoreType.DRAFT); const { currentProjectDetails } = useProject(); const { projectStates } = useProjectState(); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { project: { projectMemberIds }, } = useMember(); diff --git a/web/components/headers/project-issues.tsx b/web/components/headers/project-issues.tsx index e79022570..c756b4410 100644 --- a/web/components/headers/project-issues.tsx +++ b/web/components/headers/project-issues.tsx @@ -42,9 +42,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => { } = useUser(); const { currentProjectDetails } = useProject(); const { projectStates } = useProjectState(); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const activeLayout = issueFilters?.displayFilters?.layout; diff --git a/web/components/headers/project-view-issues.tsx b/web/components/headers/project-view-issues.tsx index 48e38491b..14d3996b1 100644 --- a/web/components/headers/project-view-issues.tsx +++ b/web/components/headers/project-view-issues.tsx @@ -49,9 +49,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { const { currentProjectDetails } = useProject(); const { projectViewIds, getViewById } = useProjectView(); const { projectStates } = useProjectState(); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { project: { projectMemberIds }, } = useMember(); diff --git a/web/components/issues/issue-detail/label/root.tsx b/web/components/issues/issue-detail/label/root.tsx index 93e303f61..2ef9bec6e 100644 --- a/web/components/issues/issue-detail/label/root.tsx +++ b/web/components/issues/issue-detail/label/root.tsx @@ -24,9 +24,7 @@ export const IssueLabel: FC = observer((props) => { const { workspaceSlug, projectId, issueId, disabled = false } = props; // hooks const { updateIssue } = useIssueDetail(); - const { - project: { createLabel }, - } = useLabel(); + const { createLabel } = useLabel(); const { setToastAlert } = useToast(); const labelOperations: TLabelOperations = useMemo( diff --git a/web/components/issues/issue-detail/label/select/label-select.tsx b/web/components/issues/issue-detail/label/select/label-select.tsx index c553ef333..4af089d5e 100644 --- a/web/components/issues/issue-detail/label/select/label-select.tsx +++ b/web/components/issues/issue-detail/label/select/label-select.tsx @@ -20,9 +20,7 @@ export const IssueLabelSelect: React.FC = observer((props) => const { issue: { getIssueById }, } = useIssueDetail(); - const { - project: { fetchProjectLabels, projectLabels }, - } = useLabel(); + const { fetchProjectLabels, getProjectLabels } = useLabel(); // states const [referenceElement, setReferenceElement] = useState(null); const [popperElement, setPopperElement] = useState(null); @@ -30,10 +28,12 @@ export const IssueLabelSelect: React.FC = observer((props) => const [query, setQuery] = useState(""); const issue = getIssueById(issueId); + const projectLabels = getProjectLabels(projectId); const fetchLabels = () => { setIsLoading(true); - if (workspaceSlug && projectId) fetchProjectLabels(workspaceSlug, projectId).then(() => setIsLoading(false)); + if (!projectLabels && workspaceSlug && projectId) + fetchProjectLabels(workspaceSlug, projectId).then(() => setIsLoading(false)); }; const options = (projectLabels ?? []).map((label) => ({ diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx index b09bc7628..227dc025b 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx @@ -17,9 +17,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => { const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.ARCHIVED); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { projectStates } = useProjectState(); // derived values const userFilters = issueFilters?.filters; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx index f402c9807..827382da7 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx @@ -21,9 +21,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.CYCLE); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { projectStates } = useProjectState(); // derived values const userFilters = issueFilters?.filters; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx index f650c0bd5..e9024afeb 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx @@ -16,9 +16,7 @@ export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => { const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.DRAFT); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { projectStates } = useProjectState(); // derived values const userFilters = issueFilters?.filters; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx index 4d8ad5196..0dae3c8bd 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx @@ -25,9 +25,7 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => { const { issuesFilter: { filters, updateFilters }, } = useIssues(EIssuesStoreType.GLOBAL); - const { - workspace: { workspaceLabels }, - } = useLabel(); + const { workspaceLabels } = useLabel(); const { globalViewMap, updateGlobalView } = useGlobalView(); const { membership: { currentWorkspaceRole }, diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx index a9a7832c6..b823a4bd1 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx @@ -20,9 +20,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => { const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.MODULE); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { projectStates } = useProjectState(); // derived values const userFilters = issueFilters?.filters; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx index 0c45c025e..7b483ef98 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx @@ -7,19 +7,20 @@ import { AppliedFiltersList } from "components/issues"; // types import { IIssueFilterOptions } from "@plane/types"; import { EIssueFilterType, EIssuesStoreType } from "constants/issue"; +import { useWorskspaceIssueProperties } from "hooks/use-worskspace-issue-properties"; export const ProfileIssuesAppliedFiltersRoot: React.FC = observer(() => { // router const router = useRouter(); const { workspaceSlug, userId } = router.query; + //swr hook for fetching issue properties + useWorskspaceIssueProperties(workspaceSlug); // store hooks const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.PROFILE); - const { - workspace: { workspaceLabels }, - } = useLabel(); + const { workspaceLabels } = useLabel(); // derived values const userFilters = issueFilters?.filters; diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx index 98ecf50b4..68b5e6727 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx @@ -19,9 +19,7 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => { projectId: string; }; // store hooks - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.PROJECT); diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx index c10de461a..0768064ec 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx @@ -23,9 +23,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.PROJECT_VIEW); - const { - project: { projectLabels }, - } = useLabel(); + const { projectLabels } = useLabel(); const { projectStates } = useProjectState(); const { viewMap, updateView } = useProjectView(); // derived values diff --git a/web/components/issues/issue-layouts/kanban/default.tsx b/web/components/issues/issue-layouts/kanban/default.tsx index 5b5dc3ead..48aa445c3 100644 --- a/web/components/issues/issue-layouts/kanban/default.tsx +++ b/web/components/issues/issue-layouts/kanban/default.tsx @@ -71,10 +71,10 @@ const GroupByKanBan: React.FC = observer((props) => { const member = useMember(); const project = useProject(); - const projectLabel = useLabel(); + const label = useLabel(); const projectState = useProjectState(); - const list = getGroupByColumns(group_by as GroupByColumnTypes, project, projectLabel, projectState, member); + const list = getGroupByColumns(group_by as GroupByColumnTypes, project, label, projectState, member); if (!list) return null; diff --git a/web/components/issues/issue-layouts/kanban/swimlanes.tsx b/web/components/issues/issue-layouts/kanban/swimlanes.tsx index 33126d17b..1b9f27828 100644 --- a/web/components/issues/issue-layouts/kanban/swimlanes.tsx +++ b/web/components/issues/issue-layouts/kanban/swimlanes.tsx @@ -208,17 +208,11 @@ export const KanBanSwimLanes: React.FC = observer((props) => { const member = useMember(); const project = useProject(); - const projectLabel = useLabel(); + const label = useLabel(); const projectState = useProjectState(); - const groupByList = getGroupByColumns(group_by as GroupByColumnTypes, project, projectLabel, projectState, member); - const subGroupByList = getGroupByColumns( - sub_group_by as GroupByColumnTypes, - project, - projectLabel, - projectState, - member - ); + const groupByList = getGroupByColumns(group_by as GroupByColumnTypes, project, label, projectState, member); + const subGroupByList = getGroupByColumns(sub_group_by as GroupByColumnTypes, project, label, projectState, member); if (!groupByList || !subGroupByList) return null; diff --git a/web/components/issues/issue-layouts/list/default.tsx b/web/components/issues/issue-layouts/list/default.tsx index df9103817..95e31b758 100644 --- a/web/components/issues/issue-layouts/list/default.tsx +++ b/web/components/issues/issue-layouts/list/default.tsx @@ -59,10 +59,10 @@ const GroupByList: React.FC = (props) => { // store hooks const member = useMember(); const project = useProject(); - const projectLabel = useLabel(); + const label = useLabel(); const projectState = useProjectState(); - const list = getGroupByColumns(group_by as GroupByColumnTypes, project, projectLabel, projectState, member, true); + const list = getGroupByColumns(group_by as GroupByColumnTypes, project, label, projectState, member, true); if (!list) return null; diff --git a/web/components/issues/issue-layouts/properties/labels.tsx b/web/components/issues/issue-layouts/properties/labels.tsx index 67295af0f..0a33ed886 100644 --- a/web/components/issues/issue-layouts/properties/labels.tsx +++ b/web/components/issues/issue-layouts/properties/labels.tsx @@ -53,13 +53,15 @@ export const IssuePropertyLabels: React.FC = observer((pro const { router: { workspaceSlug }, } = useApplication(); - const { - project: { fetchProjectLabels, projectLabels: storeLabels }, - } = useLabel(); + const { fetchProjectLabels, getProjectLabels } = useLabel(); - const fetchLabels = () => { - setIsLoading(true); - if (workspaceSlug && projectId) fetchProjectLabels(workspaceSlug, projectId).then(() => setIsLoading(false)); + const storeLabels = getProjectLabels(projectId); + + const openDropDown = () => { + if (!storeLabels && workspaceSlug && projectId) { + setIsLoading(true); + fetchProjectLabels(workspaceSlug, projectId).then(() => setIsLoading(false)); + } }; const { styles, attributes } = usePopper(referenceElement, popperElement, { @@ -182,7 +184,7 @@ export const IssuePropertyLabels: React.FC = observer((pro ? "cursor-pointer" : "cursor-pointer hover:bg-custom-background-80" } ${buttonClassName}`} - onClick={() => !storeLabels && fetchLabels()} + onClick={openDropDown} > {label} {!hideDropdownArrow && !disabled &&