[WEB-926] fix: issue description component update handled in peek overview, issue detail, and inbox issues (#4159)

* fix: issue description mutation

* fix: implemented same issue description logic for issue detail and inbox issue description

* fix: fixed parent issue title dissapearing while loading the issue detail page

* chore: code cleanup

* chore: handled exception when issue in not available in issue detail in issue store

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
guru_sainath 2024-04-10 14:58:46 +05:30 committed by GitHub
parent c80638090f
commit d0cb00f28a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 51 additions and 56 deletions

View File

@ -2,7 +2,7 @@ import { Dispatch, SetStateAction, useEffect, useMemo } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { TIssue } from "@plane/types";
import { Loader, TOAST_TYPE, setToast } from "@plane/ui";
import { TOAST_TYPE, setToast } from "@plane/ui";
// components
import { InboxIssueProperties } from "@/components/inbox/content";
import {
@ -13,7 +13,7 @@ import {
TIssueOperations,
} from "@/components/issues";
// hooks
import { useEventTracker, useProjectInbox, useUser } from "@/hooks/store";
import { useEventTracker, useUser } from "@/hooks/store";
import useReloadConfirmations from "@/hooks/use-reload-confirmation";
// store types
import { IInboxIssueStore } from "@/store/inbox/inbox-issue.store";
@ -32,7 +32,6 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId, inboxIssue, is_editable, isSubmitting, setIsSubmitting } = props;
// hooks
const { currentUser } = useUser();
const { isLoading } = useProjectInbox();
const { setShowAlert } = useReloadConfirmations(isSubmitting === "submitting");
const { captureIssueEvent } = useEventTracker();
@ -131,22 +130,16 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
value={issue.name}
/>
{isLoading ? (
<Loader className="h-[150px] space-y-2 overflow-hidden rounded-md border border-custom-border-200 p-2 py-2">
<Loader.Item width="100%" height="132px" />
</Loader>
) : (
<IssueDescriptionInput
workspaceSlug={workspaceSlug}
projectId={issue.project_id}
issueId={issue.id}
value={issueDescription}
initialValue={issueDescription}
disabled={!is_editable}
issueOperations={issueOperations}
setIsSubmitting={(value) => setIsSubmitting(value)}
/>
)}
<IssueDescriptionInput
workspaceSlug={workspaceSlug}
projectId={issue.project_id}
issueId={issue.id}
value={issueDescription}
initialValue={issueDescription}
disabled={!is_editable}
issueOperations={issueOperations}
setIsSubmitting={(value) => setIsSubmitting(value)}
/>
{currentUser && (
<IssueReaction

View File

@ -25,6 +25,7 @@ export type IssueDescriptionInputProps = {
export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = (props) => {
const { workspaceSlug, projectId, issueId, value, initialValue, disabled, issueOperations, setIsSubmitting } = props;
// states
const [localIssueId, setLocalIssueId] = useState(issueId);
const [descriptionHTML, setDescriptionHTML] = useState(value);
// store hooks
const { mentionHighlights, mentionSuggestions } = useMention();
@ -35,8 +36,14 @@ export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = (props) =>
const workspaceId = getWorkspaceBySlug(workspaceSlug)?.id as string;
useEffect(() => {
setDescriptionHTML(value);
}, [value]);
if (issueId !== localIssueId) {
setDescriptionHTML(undefined);
setLocalIssueId(issueId);
} else {
setDescriptionHTML(value);
}
return () => setDescriptionHTML(undefined);
}, [issueId, localIssueId, value]);
useEffect(() => {
if (debouncedValue && debouncedValue !== value) {

View File

@ -28,7 +28,6 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId, issueId, issueOperations, is_editable } = props;
// states
const [isSubmitting, setIsSubmitting] = useState<"submitting" | "submitted" | "saved">("saved");
const [issueDescription, setIssueDescription] = useState<string | undefined>(undefined);
// hooks
const { currentUser } = useUser();
const { projectStates } = useProjectState();
@ -53,16 +52,12 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
const currentIssueState = projectStates?.find((s) => s.id === issue.state_id);
useEffect(() => {
setIssueDescription(
issue.description_html !== undefined || issue.description_html !== null
? issue.description_html != ""
? issue.description_html
: "<p></p>"
: undefined
);
return () => setIssueDescription(undefined);
}, [issue.description_html]);
const issueDescription =
issue.description_html !== undefined || issue.description_html !== null
? issue.description_html != ""
? issue.description_html
: "<p></p>"
: undefined;
return (
<>
@ -99,18 +94,16 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
value={issue.name}
/>
{issue?.description_html === issueDescription && (
<IssueDescriptionInput
workspaceSlug={workspaceSlug}
projectId={issue.project_id}
issueId={issue.id}
value={issueDescription}
initialValue={issueDescription}
disabled={!is_editable}
issueOperations={issueOperations}
setIsSubmitting={(value) => setIsSubmitting(value)}
/>
)}
<IssueDescriptionInput
workspaceSlug={workspaceSlug}
projectId={issue.project_id}
issueId={issue.id}
value={issueDescription}
initialValue={issueDescription}
disabled={!is_editable}
issueOperations={issueOperations}
setIsSubmitting={(value) => setIsSubmitting(value)}
/>
{currentUser && (
<IssueReaction

View File

@ -1,4 +1,5 @@
import { FC } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { MinusCircle } from "lucide-react";
import { TIssue } from "@plane/types";
@ -19,7 +20,7 @@ export type TIssueParentDetail = {
issueOperations: TIssueOperations;
};
export const IssueParentDetail: FC<TIssueParentDetail> = (props) => {
export const IssueParentDetail: FC<TIssueParentDetail> = observer((props) => {
const { workspaceSlug, projectId, issueId, issue, issueOperations } = props;
// hooks
const { issueMap } = useIssues();
@ -68,4 +69,4 @@ export const IssueParentDetail: FC<TIssueParentDetail> = (props) => {
</div>
</>
);
};
});

View File

@ -66,7 +66,6 @@ export class IssueStore implements IIssueStore {
};
let issue: TIssue;
let issuePayload: TIssue;
if (issueType === "ARCHIVED")
issue = await this.issueArchiveService.retrieveArchivedIssue(workspaceSlug, projectId, issueId, query);
@ -76,7 +75,7 @@ export class IssueStore implements IIssueStore {
if (!issue) throw new Error("Issue not found");
issuePayload = {
const issuePayload: TIssue = {
id: issue?.id,
sequence_id: issue?.sequence_id,
name: issue?.name,
@ -110,8 +109,10 @@ export class IssueStore implements IIssueStore {
// store handlers from issue detail
// parent
if (issue && issue?.parent && issue?.parent?.id)
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([issue.parent]);
if (issue && issue?.parent && issue?.parent?.id) {
const parentIssue = await this.issueService.retrieve(workspaceSlug, projectId, issue?.parent?.id);
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([parentIssue]);
}
// assignees
// labels
// state
@ -184,7 +185,7 @@ export class IssueStore implements IIssueStore {
};
addModulesToIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
const _module = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.addModulesToIssue(
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.addModulesToIssue(
workspaceSlug,
projectId,
issueId,
@ -192,28 +193,28 @@ export class IssueStore implements IIssueStore {
);
if (moduleIds && moduleIds.length > 0)
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
return _module;
return currentModule;
};
removeModulesFromIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
const _module = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.removeModulesFromIssue(
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.removeModulesFromIssue(
workspaceSlug,
projectId,
issueId,
moduleIds
);
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
return _module;
return currentModule;
};
removeIssueFromModule = async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => {
const _module = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.removeIssueFromModule(
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.removeIssueFromModule(
workspaceSlug,
projectId,
moduleId,
issueId
);
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
return _module;
return currentModule;
};
}