forked from github/plane
chore: Removing 'description_html' from Issue List (#3623)
* chore: removed issue description from issue list * fix: issue description handling on peekoverview --------- Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
parent
963d26ccda
commit
0fb43c6fc5
@ -68,6 +68,7 @@ from .issue import (
|
|||||||
IssueRelationSerializer,
|
IssueRelationSerializer,
|
||||||
RelatedIssueSerializer,
|
RelatedIssueSerializer,
|
||||||
IssuePublicSerializer,
|
IssuePublicSerializer,
|
||||||
|
IssueDetailSerializer,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .module import (
|
from .module import (
|
||||||
|
@ -586,7 +586,6 @@ class IssueSerializer(DynamicBaseSerializer):
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"state_id",
|
"state_id",
|
||||||
"description_html",
|
|
||||||
"sort_order",
|
"sort_order",
|
||||||
"completed_at",
|
"completed_at",
|
||||||
"estimate_point",
|
"estimate_point",
|
||||||
@ -618,6 +617,13 @@ class IssueSerializer(DynamicBaseSerializer):
|
|||||||
return [module for module in obj.issue_module.values_list("module_id", flat=True)]
|
return [module for module in obj.issue_module.values_list("module_id", flat=True)]
|
||||||
|
|
||||||
|
|
||||||
|
class IssueDetailSerializer(IssueSerializer):
|
||||||
|
description_html = serializers.CharField()
|
||||||
|
|
||||||
|
class Meta(IssueSerializer.Meta):
|
||||||
|
fields = IssueSerializer.Meta.fields + ['description_html']
|
||||||
|
|
||||||
|
|
||||||
class IssueLiteSerializer(DynamicBaseSerializer):
|
class IssueLiteSerializer(DynamicBaseSerializer):
|
||||||
workspace_detail = WorkspaceLiteSerializer(
|
workspace_detail = WorkspaceLiteSerializer(
|
||||||
read_only=True, source="workspace"
|
read_only=True, source="workspace"
|
||||||
|
@ -50,6 +50,7 @@ from plane.app.serializers import (
|
|||||||
CommentReactionSerializer,
|
CommentReactionSerializer,
|
||||||
IssueRelationSerializer,
|
IssueRelationSerializer,
|
||||||
RelatedIssueSerializer,
|
RelatedIssueSerializer,
|
||||||
|
IssueDetailSerializer,
|
||||||
)
|
)
|
||||||
from plane.app.permissions import (
|
from plane.app.permissions import (
|
||||||
ProjectEntityPermission,
|
ProjectEntityPermission,
|
||||||
@ -267,7 +268,7 @@ class IssueViewSet(WebhookMixin, BaseViewSet):
|
|||||||
def retrieve(self, request, slug, project_id, pk=None):
|
def retrieve(self, request, slug, project_id, pk=None):
|
||||||
issue = self.get_queryset().filter(pk=pk).first()
|
issue = self.get_queryset().filter(pk=pk).first()
|
||||||
return Response(
|
return Response(
|
||||||
IssueSerializer(
|
IssueDetailSerializer(
|
||||||
issue, fields=self.fields, expand=self.expand
|
issue, fields=self.fields, expand=self.expand
|
||||||
).data,
|
).data,
|
||||||
status=status.HTTP_200_OK,
|
status=status.HTTP_200_OK,
|
||||||
|
@ -4,7 +4,7 @@ import { Controller, useForm } from "react-hook-form";
|
|||||||
import useReloadConfirmations from "hooks/use-reload-confirmation";
|
import useReloadConfirmations from "hooks/use-reload-confirmation";
|
||||||
import debounce from "lodash/debounce";
|
import debounce from "lodash/debounce";
|
||||||
// components
|
// components
|
||||||
import { TextArea } from "@plane/ui";
|
import { Loader, TextArea } from "@plane/ui";
|
||||||
import { RichReadOnlyEditor, RichTextEditor } from "@plane/rich-text-editor";
|
import { RichReadOnlyEditor, RichTextEditor } from "@plane/rich-text-editor";
|
||||||
// types
|
// types
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
@ -12,6 +12,8 @@ import { TIssueOperations } from "./issue-detail";
|
|||||||
// services
|
// services
|
||||||
import { FileService } from "services/file.service";
|
import { FileService } from "services/file.service";
|
||||||
import { useMention, useWorkspace } from "hooks/store";
|
import { useMention, useWorkspace } from "hooks/store";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { isNil } from "lodash";
|
||||||
|
|
||||||
export interface IssueDescriptionFormValues {
|
export interface IssueDescriptionFormValues {
|
||||||
name: string;
|
name: string;
|
||||||
@ -36,7 +38,7 @@ export interface IssueDetailsProps {
|
|||||||
|
|
||||||
const fileService = new FileService();
|
const fileService = new FileService();
|
||||||
|
|
||||||
export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
|
export const IssueDescriptionForm: FC<IssueDetailsProps> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, issueId, issue, issueOperations, disabled, isSubmitting, setIsSubmitting } = props;
|
const { workspaceSlug, projectId, issueId, issue, issueOperations, disabled, isSubmitting, setIsSubmitting } = props;
|
||||||
const workspaceStore = useWorkspace();
|
const workspaceStore = useWorkspace();
|
||||||
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug)?.id as string;
|
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug)?.id as string;
|
||||||
@ -71,12 +73,20 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
|
|||||||
// editor rerendering on every save
|
// editor rerendering on every save
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (issue.id) {
|
if (issue.id) {
|
||||||
setLocalIssueDescription({ id: issue.id, description_html: issue.description_html });
|
|
||||||
setLocalTitleValue(issue.name);
|
setLocalTitleValue(issue.name);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [issue.id]); // TODO: verify the exhaustive-deps warning
|
}, [issue.id]); // TODO: verify the exhaustive-deps warning
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (issue.description_html) {
|
||||||
|
setLocalIssueDescription((state) => {
|
||||||
|
if (!isNil(state.description_html)) return state;
|
||||||
|
return { id: issue.id, description_html: issue.description_html };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [issue.description_html]);
|
||||||
|
|
||||||
const handleDescriptionFormSubmit = useCallback(
|
const handleDescriptionFormSubmit = useCallback(
|
||||||
async (formData: Partial<TIssue>) => {
|
async (formData: Partial<TIssue>) => {
|
||||||
if (!formData?.name || formData?.name.length === 0 || formData?.name.length > 255) return;
|
if (!formData?.name || formData?.name.length === 0 || formData?.name.length > 255) return;
|
||||||
@ -167,6 +177,7 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<span>{errors.name ? errors.name.message : null}</span>
|
<span>{errors.name ? errors.name.message : null}</span>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
{issue.description_html ? (
|
||||||
<Controller
|
<Controller
|
||||||
name="description_html"
|
name="description_html"
|
||||||
control={control}
|
control={control}
|
||||||
@ -202,7 +213,12 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<Loader>
|
||||||
|
<Loader.Item height="150px" />
|
||||||
|
</Loader>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -4,6 +4,7 @@ import { useIssueDetail, useProject, useUser } from "hooks/store";
|
|||||||
// components
|
// components
|
||||||
import { IssueDescriptionForm, TIssueOperations } from "components/issues";
|
import { IssueDescriptionForm, TIssueOperations } from "components/issues";
|
||||||
import { IssueReaction } from "../issue-detail/reactions";
|
import { IssueReaction } from "../issue-detail/reactions";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
interface IPeekOverviewIssueDetails {
|
interface IPeekOverviewIssueDetails {
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
@ -15,7 +16,7 @@ interface IPeekOverviewIssueDetails {
|
|||||||
setIsSubmitting: (value: "submitting" | "submitted" | "saved") => void;
|
setIsSubmitting: (value: "submitting" | "submitted" | "saved") => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) => {
|
export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, issueId, issueOperations, disabled, isSubmitting, setIsSubmitting } = props;
|
const { workspaceSlug, projectId, issueId, issueOperations, disabled, isSubmitting, setIsSubmitting } = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { getProjectById } = useProject();
|
const { getProjectById } = useProject();
|
||||||
@ -23,6 +24,7 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
|
|||||||
const {
|
const {
|
||||||
issue: { getIssueById },
|
issue: { getIssueById },
|
||||||
} = useIssueDetail();
|
} = useIssueDetail();
|
||||||
|
|
||||||
// derived values
|
// derived values
|
||||||
const issue = getIssueById(issueId);
|
const issue = getIssueById(issueId);
|
||||||
if (!issue) return <></>;
|
if (!issue) return <></>;
|
||||||
@ -53,4 +55,4 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -4,6 +4,7 @@ import { IssueArchiveService, IssueService } from "services/issue";
|
|||||||
// types
|
// types
|
||||||
import { IIssueDetail } from "./root.store";
|
import { IIssueDetail } from "./root.store";
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
|
import { computedFn } from "mobx-utils";
|
||||||
|
|
||||||
export interface IIssueStoreActions {
|
export interface IIssueStoreActions {
|
||||||
// actions
|
// actions
|
||||||
@ -44,10 +45,10 @@ export class IssueStore implements IIssueStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// helper methods
|
// helper methods
|
||||||
getIssueById = (issueId: string) => {
|
getIssueById = computedFn((issueId: string) => {
|
||||||
if (!issueId) return undefined;
|
if (!issueId) return undefined;
|
||||||
return this.rootIssueDetailStore.rootIssueStore.issues.getIssueById(issueId) ?? undefined;
|
return this.rootIssueDetailStore.rootIssueStore.issues.getIssueById(issueId) ?? undefined;
|
||||||
};
|
});
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
fetchIssue = async (workspaceSlug: string, projectId: string, issueId: string, isArchived = false) => {
|
fetchIssue = async (workspaceSlug: string, projectId: string, issueId: string, isArchived = false) => {
|
||||||
@ -63,12 +64,12 @@ export class IssueStore implements IIssueStore {
|
|||||||
|
|
||||||
if (!issue) throw new Error("Issue not found");
|
if (!issue) throw new Error("Issue not found");
|
||||||
|
|
||||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([issue]);
|
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([issue], true);
|
||||||
|
|
||||||
// store handlers from issue detail
|
// store handlers from issue detail
|
||||||
// parent
|
// parent
|
||||||
if (issue && issue?.parent && issue?.parent?.id)
|
if (issue && issue?.parent && issue?.parent?.id)
|
||||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([issue?.parent]);
|
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([issue.parent]);
|
||||||
// assignees
|
// assignees
|
||||||
// labels
|
// labels
|
||||||
// state
|
// state
|
||||||
|
@ -10,7 +10,7 @@ export type IIssueStore = {
|
|||||||
// observables
|
// observables
|
||||||
issuesMap: Record<string, TIssue>; // Record defines issue_id as key and TIssue as value
|
issuesMap: Record<string, TIssue>; // Record defines issue_id as key and TIssue as value
|
||||||
// actions
|
// actions
|
||||||
addIssue(issues: TIssue[]): void;
|
addIssue(issues: TIssue[], shouldReplace?: boolean): void;
|
||||||
updateIssue(issueId: string, issue: Partial<TIssue>): void;
|
updateIssue(issueId: string, issue: Partial<TIssue>): void;
|
||||||
removeIssue(issueId: string): void;
|
removeIssue(issueId: string): void;
|
||||||
// helper methods
|
// helper methods
|
||||||
@ -39,11 +39,11 @@ export class IssueStore implements IIssueStore {
|
|||||||
* @param {TIssue[]} issues
|
* @param {TIssue[]} issues
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
addIssue = (issues: TIssue[]) => {
|
addIssue = (issues: TIssue[], shouldReplace = false) => {
|
||||||
if (issues && issues.length <= 0) return;
|
if (issues && issues.length <= 0) return;
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
issues.forEach((issue) => {
|
issues.forEach((issue) => {
|
||||||
if (!this.issuesMap[issue.id]) set(this.issuesMap, issue.id, issue);
|
if (!this.issuesMap[issue.id] || shouldReplace) set(this.issuesMap, issue.id, issue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user