[WEB-1177] fix: sub-issues count mutation. (#4516)

* [WEB-1177] fix: sub-issues count mutation.

* chore: refactor sub_issues_count mutation logic.

* fix: build errors.
This commit is contained in:
Prateek Shourya 2024-05-21 17:14:41 +05:30 committed by GitHub
parent 8a960e269f
commit 709cd9dd6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 44 additions and 25 deletions

View File

@ -67,8 +67,9 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
!getIsIssuePeeked(issue.id) && !getIsIssuePeeked(issue.id) &&
setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id, nestingLevel: nestingLevel }); setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id, nestingLevel: nestingLevel });
const issue = issuesMap[issueId]; const issue = issuesMap[issueId];
const subIssues = subIssuesStore.subIssuesByIssueId(issueId); const subIssuesCount = issue.sub_issues_count;
const { isMobile } = usePlatformOS(); const { isMobile } = usePlatformOS();
useEffect(() => { useEffect(() => {
@ -97,8 +98,6 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
const canEditIssueProperties = canEditProperties(issue.project_id); const canEditIssueProperties = canEditProperties(issue.project_id);
const projectIdentifier = getProjectIdentifierById(issue.project_id); const projectIdentifier = getProjectIdentifierById(issue.project_id);
// if sub issues have been fetched for the issue, use that for count or use issue's sub_issues_count
const subIssuesCount = subIssues ? subIssues.length : issue.sub_issues_count;
const paddingLeft = `${spacingLeft}px`; const paddingLeft = `${spacingLeft}px`;

View File

@ -2,10 +2,13 @@ import { useCallback, useMemo } from "react";
import xor from "lodash/xor"; import xor from "lodash/xor";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
// icons
import { CalendarCheck2, CalendarClock, Layers, Link, Paperclip } from "lucide-react"; import { CalendarCheck2, CalendarClock, Layers, Link, Paperclip } from "lucide-react";
// types
import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types"; import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types";
// hooks // ui
import { Tooltip } from "@plane/ui"; import { Tooltip } from "@plane/ui";
// components
import { import {
DateDropdown, DateDropdown,
EstimateDropdown, EstimateDropdown,
@ -15,23 +18,19 @@ import {
CycleDropdown, CycleDropdown,
StateDropdown, StateDropdown,
} from "@/components/dropdowns"; } from "@/components/dropdowns";
// helpers
// types
// constants // constants
import { ISSUE_UPDATED } from "@/constants/event-tracker"; import { ISSUE_UPDATED } from "@/constants/event-tracker";
import { EIssuesStoreType } from "@/constants/issue"; import { EIssuesStoreType } from "@/constants/issue";
// helpers
import { cn } from "@/helpers/common.helper"; import { cn } from "@/helpers/common.helper";
import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper"; import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper"; import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper";
// hooks
import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState, useProject } from "@/hooks/store"; import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState, useProject } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os"; import { usePlatformOS } from "@/hooks/use-platform-os";
// components // local components
import { IssuePropertyLabels } from "../properties/labels"; import { IssuePropertyLabels } from "../properties/labels";
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC"; import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
// helpers
// types
// constants
export interface IIssueProperties { export interface IIssueProperties {
issue: TIssue; issue: TIssue;
@ -64,6 +63,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
const currentLayout = `${activeLayout} layout`; const currentLayout = `${activeLayout} layout`;
// derived values // derived values
const stateDetails = getStateById(issue.state_id); const stateDetails = getStateById(issue.state_id);
const subIssueCount = issue.sub_issues_count;
const issueOperations = useMemo( const issueOperations = useMemo(
() => ({ () => ({
@ -414,24 +414,24 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
<WithDisplayPropertiesHOC <WithDisplayPropertiesHOC
displayProperties={displayProperties} displayProperties={displayProperties}
displayPropertyKey="sub_issue_count" displayPropertyKey="sub_issue_count"
shouldRenderProperty={(properties) => !!properties.sub_issue_count && !!issue.sub_issues_count} shouldRenderProperty={(properties) => !!properties.sub_issue_count && !!subIssueCount}
> >
<Tooltip tooltipHeading="Sub-issues" tooltipContent={`${issue.sub_issues_count}`} isMobile={isMobile}> <Tooltip tooltipHeading="Sub-issues" tooltipContent={`${subIssueCount}`} isMobile={isMobile}>
<div <div
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
if (issue.sub_issues_count) redirectToIssueDetail(); if (subIssueCount) redirectToIssueDetail();
}} }}
className={cn( className={cn(
"flex h-5 flex-shrink-0 items-center justify-center gap-2 overflow-hidden rounded border-[0.5px] border-custom-border-300 px-2.5 py-1", "flex h-5 flex-shrink-0 items-center justify-center gap-2 overflow-hidden rounded border-[0.5px] border-custom-border-300 px-2.5 py-1",
{ {
"hover:bg-custom-background-80 cursor-pointer": issue.sub_issues_count, "hover:bg-custom-background-80 cursor-pointer": subIssueCount,
} }
)} )}
> >
<Layers className="h-3 w-3 flex-shrink-0" strokeWidth={2} /> <Layers className="h-3 w-3 flex-shrink-0" strokeWidth={2} />
<div className="text-xs">{issue.sub_issues_count}</div> <div className="text-xs">{subIssueCount}</div>
</div> </div>
</Tooltip> </Tooltip>
</WithDisplayPropertiesHOC> </WithDisplayPropertiesHOC>

View File

@ -18,6 +18,8 @@ export const SpreadsheetSubIssueColumn: React.FC<Props> = observer((props: Props
const router = useRouter(); const router = useRouter();
// hooks // hooks
const { workspaceSlug } = useAppRouter(); const { workspaceSlug } = useAppRouter();
// derived values
const subIssueCount = issue.sub_issues_count;
const redirectToIssueDetail = () => { const redirectToIssueDetail = () => {
router.push({ router.push({
@ -30,15 +32,15 @@ export const SpreadsheetSubIssueColumn: React.FC<Props> = observer((props: Props
return ( return (
<div <div
onClick={issue?.sub_issues_count ? redirectToIssueDetail : () => {}} onClick={subIssueCount ? redirectToIssueDetail : () => {}}
className={cn( className={cn(
"flex h-11 w-full items-center border-b-[0.5px] border-custom-border-200 px-2.5 py-1 text-xs hover:bg-custom-background-80", "flex h-11 w-full items-center border-b-[0.5px] border-custom-border-200 px-2.5 py-1 text-xs hover:bg-custom-background-80",
{ {
"cursor-pointer": issue?.sub_issues_count, "cursor-pointer": subIssueCount,
} }
)} )}
> >
{issue?.sub_issues_count} {issue?.sub_issues_count === 1 ? "sub-issue" : "sub-issues"} {subIssueCount} {subIssueCount === 1 ? "sub-issue" : "sub-issues"}
</div> </div>
); );
}); });

View File

@ -170,7 +170,6 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
const { subIssues: subIssuesStore, issue } = useIssueDetail(); const { subIssues: subIssuesStore, issue } = useIssueDetail();
const issueDetail = issue.getIssueById(issueId); const issueDetail = issue.getIssueById(issueId);
const subIssues = subIssuesStore.subIssuesByIssueId(issueId);
const paddingLeft = `${spacingLeft}px`; const paddingLeft = `${spacingLeft}px`;
@ -204,8 +203,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
}; };
const disableUserActions = !canEditProperties(issueDetail.project_id); const disableUserActions = !canEditProperties(issueDetail.project_id);
// if sub issues have been fetched for the issue, use that for count or use issue's sub_issues_count const subIssuesCount = issueDetail.sub_issues_count;
const subIssuesCount = subIssues ? subIssues.length : issueDetail.sub_issues_count;
return ( return (
<> <>

View File

@ -59,6 +59,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
undefined; undefined;
const subIssueHelpers = subIssueHelpersByIssueId(parentIssueId); const subIssueHelpers = subIssueHelpersByIssueId(parentIssueId);
const subIssueCount = issue?.sub_issues_count || 0;
const handleIssuePeekOverview = (issue: TIssue) => const handleIssuePeekOverview = (issue: TIssue) =>
workspaceSlug && workspaceSlug &&
@ -77,7 +78,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
style={{ paddingLeft: `${spacingLeft}px` }} style={{ paddingLeft: `${spacingLeft}px` }}
> >
<div className="h-[22px] w-[22px] flex-shrink-0"> <div className="h-[22px] w-[22px] flex-shrink-0">
{issue?.sub_issues_count > 0 && ( {subIssueCount > 0 && (
<> <>
{subIssueHelpers.preview_loader.includes(issue.id) ? ( {subIssueHelpers.preview_loader.includes(issue.id) ? (
<div className="flex h-full w-full cursor-not-allowed items-center justify-center rounded-sm bg-custom-background-80 transition-all"> <div className="flex h-full w-full cursor-not-allowed items-center justify-center rounded-sm bg-custom-background-80 transition-all">
@ -205,7 +206,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
</div> </div>
)} )}
{subIssueHelpers.issue_visibility.includes(issueId) && issue.sub_issues_count && issue.sub_issues_count > 0 && ( {subIssueHelpers.issue_visibility.includes(issueId) && subIssueCount > 0 && (
<IssueList <IssueList
workspaceSlug={workspaceSlug} workspaceSlug={workspaceSlug}
projectId={issue.project_id} projectId={issue.project_id}

View File

@ -174,6 +174,13 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
this.rootIssueDetailStore.rootIssueStore.issues.addIssue(subIssues); this.rootIssueDetailStore.rootIssueStore.issues.addIssue(subIssues);
// update sub-issues_count of the parent issue
set(
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
[parentIssueId, "sub_issues_count"],
this.subIssues[parentIssueId].length
);
return; return;
} catch (error) { } catch (error) {
throw error; throw error;
@ -270,6 +277,12 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
runInAction(() => { runInAction(() => {
pull(this.subIssues[parentIssueId], issueId); pull(this.subIssues[parentIssueId], issueId);
// update sub-issues_count of the parent issue
set(
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
[parentIssueId, "sub_issues_count"],
this.subIssues[parentIssueId].length
);
}); });
return; return;
@ -301,6 +314,12 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
runInAction(() => { runInAction(() => {
pull(this.subIssues[parentIssueId], issueId); pull(this.subIssues[parentIssueId], issueId);
// update sub-issues_count of the parent issue
set(
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
[parentIssueId, "sub_issues_count"],
this.subIssues[parentIssueId].length
);
}); });
return; return;