From e22265dc93dd8ed3a247d26ddc2d261aeacb8837 Mon Sep 17 00:00:00 2001 From: Akshita Goyal <36129505+gakshita@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:06:36 +0530 Subject: [PATCH] fix: intake refactor (#6698) * fix: refactor * fix: refactor * fix: type * chore: added source data in intake * fix: css --------- Co-authored-by: pablohashescobar --- apiserver/plane/app/serializers/issue.py | 14 +++++ apiserver/plane/app/views/issue/activity.py | 15 ++++-- packages/types/src/inbox.d.ts | 4 +- .../src/issues/activity/issue_activity.d.ts | 7 +++ .../components/editor/rich-text-editor.tsx | 2 +- .../components/issues/issue-details/index.ts | 1 + .../issues/issue-details/issue-creator.tsx | 36 +++++++++++++ .../constants/project/settings/features.tsx | 7 +-- web/ce/store/project-inbox.store.ts | 1 + .../activity/actions/default.tsx | 16 +++++- .../actions/helpers/activity-block.tsx | 7 ++- .../project/settings/features-list.tsx | 5 +- web/core/hooks/store/use-project-inbox.ts | 2 +- .../services/inbox/inbox-issue.service.ts | 26 +--------- web/core/store/inbox/project-inbox.store.ts | 52 ------------------- .../components/issues/issue-details/index.ts | 1 + .../issues/issue-details/issue-creator.tsx | 1 + web/ee/store/project-inbox.store.ts | 1 + 18 files changed, 104 insertions(+), 94 deletions(-) create mode 100644 web/ce/components/issues/issue-details/issue-creator.tsx create mode 100644 web/ce/store/project-inbox.store.ts create mode 100644 web/ee/components/issues/issue-details/issue-creator.tsx create mode 100644 web/ee/store/project-inbox.store.ts diff --git a/apiserver/plane/app/serializers/issue.py b/apiserver/plane/app/serializers/issue.py index b9306a728..8df915c23 100644 --- a/apiserver/plane/app/serializers/issue.py +++ b/apiserver/plane/app/serializers/issue.py @@ -268,6 +268,20 @@ class IssueActivitySerializer(BaseSerializer): issue_detail = IssueFlatSerializer(read_only=True, source="issue") project_detail = ProjectLiteSerializer(read_only=True, source="project") workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace") + source_data = serializers.SerializerMethodField() + + def get_source_data(self, obj): + if ( + hasattr(obj, "issue") + and hasattr(obj.issue, "source_data") + and obj.issue.source_data + ): + return { + "source": obj.issue.source_data[0].source, + "source_email": obj.issue.source_data[0].source_email, + "extra": obj.issue.source_data[0].extra, + } + return None class Meta: model = IssueActivity diff --git a/apiserver/plane/app/views/issue/activity.py b/apiserver/plane/app/views/issue/activity.py index 1b6629e47..91b973f11 100644 --- a/apiserver/plane/app/views/issue/activity.py +++ b/apiserver/plane/app/views/issue/activity.py @@ -14,7 +14,7 @@ from rest_framework import status from .. import BaseAPIView from plane.app.serializers import IssueActivitySerializer, IssueCommentSerializer from plane.app.permissions import ProjectEntityPermission, allow_permission, ROLE -from plane.db.models import IssueActivity, IssueComment, CommentReaction +from plane.db.models import IssueActivity, IssueComment, CommentReaction, IntakeIssue class IssueActivityEndpoint(BaseAPIView): @@ -57,13 +57,22 @@ class IssueActivityEndpoint(BaseAPIView): ) ) ) - issue_activities = IssueActivitySerializer(issue_activities, many=True).data - issue_comments = IssueCommentSerializer(issue_comments, many=True).data if request.GET.get("activity_type", None) == "issue-property": + issue_activities = issue_activities.prefetch_related( + Prefetch( + "issue__issue_intake", + queryset=IntakeIssue.objects.only( + "source_email", "source", "extra" + ), + to_attr="source_data", + ) + ) + issue_activities = IssueActivitySerializer(issue_activities, many=True).data return Response(issue_activities, status=status.HTTP_200_OK) if request.GET.get("activity_type", None) == "issue-comment": + issue_comments = IssueCommentSerializer(issue_comments, many=True).data return Response(issue_comments, status=status.HTTP_200_OK) result_list = sorted( diff --git a/packages/types/src/inbox.d.ts b/packages/types/src/inbox.d.ts index 30ad0120c..69fb01f7c 100644 --- a/packages/types/src/inbox.d.ts +++ b/packages/types/src/inbox.d.ts @@ -66,8 +66,10 @@ export type TInboxIssueWithPagination = TInboxIssuePaginationInfo & { results: TInboxIssue[]; }; +export type TAnchors = { [key: string]: string }; + export type TInboxForm = { - anchor: string; + anchors: TAnchors; id: string; is_in_app_enabled: boolean; is_form_enabled: boolean; diff --git a/packages/types/src/issues/activity/issue_activity.d.ts b/packages/types/src/issues/activity/issue_activity.d.ts index 391d06c12..7eccebdf3 100644 --- a/packages/types/src/issues/activity/issue_activity.d.ts +++ b/packages/types/src/issues/activity/issue_activity.d.ts @@ -30,6 +30,13 @@ export type TIssueActivity = { new_identifier: string | undefined; epoch: number; issue_comment: string | null; + source_data: { + source: "IN_APP" | "FORM" | "EMAIL"; + source_email?: string; + extra: { + username?: string; + }; + }; }; export type TIssueActivityMap = { diff --git a/space/core/components/editor/rich-text-editor.tsx b/space/core/components/editor/rich-text-editor.tsx index 9296b25d2..682036f2a 100644 --- a/space/core/components/editor/rich-text-editor.tsx +++ b/space/core/components/editor/rich-text-editor.tsx @@ -31,7 +31,7 @@ export const RichTextEditor = forwardRef ); }); diff --git a/web/ce/components/issues/issue-details/index.ts b/web/ce/components/issues/issue-details/index.ts index e23fbe531..4125ebf83 100644 --- a/web/ce/components/issues/issue-details/index.ts +++ b/web/ce/components/issues/issue-details/index.ts @@ -3,3 +3,4 @@ export * from "./issue-properties-activity"; export * from "./issue-type-switcher"; export * from "./issue-type-activity"; export * from "./parent-select-root"; +export * from "./issue-creator"; diff --git a/web/ce/components/issues/issue-details/issue-creator.tsx b/web/ce/components/issues/issue-details/issue-creator.tsx new file mode 100644 index 000000000..07e6899d3 --- /dev/null +++ b/web/ce/components/issues/issue-details/issue-creator.tsx @@ -0,0 +1,36 @@ +import { FC } from "react"; +import Link from "next/link"; +// hooks +import { useIssueDetail } from "@/hooks/store"; + +type TIssueUser = { + activityId: string; + customUserName?: string; +}; + +export const IssueCreatorDisplay: FC = (props) => { + const { activityId, customUserName } = props; + // hooks + const { + activity: { getActivityById }, + } = useIssueDetail(); + + const activity = getActivityById(activityId); + + if (!activity) return <>; + + return ( + <> + {customUserName ? ( + {customUserName || "Plane"} + ) : ( + + {activity.actor_detail?.display_name} + + )} + + ); +}; diff --git a/web/ce/constants/project/settings/features.tsx b/web/ce/constants/project/settings/features.tsx index 99e6101d5..8dda34957 100644 --- a/web/ce/constants/project/settings/features.tsx +++ b/web/ce/constants/project/settings/features.tsx @@ -11,12 +11,7 @@ export type TProperties = { icon: ReactNode; isPro: boolean; isEnabled: boolean; - renderChildren?: ( - currentProjectDetails: IProject, - isAdmin: boolean, - handleSubmit: (featureKey: string, featureProperty: string) => Promise, - workspaceSlug: string - ) => ReactNode; + renderChildren?: (currentProjectDetails: IProject, workspaceSlug: string) => ReactNode; }; export type TFeatureList = { [key: string]: TProperties; diff --git a/web/ce/store/project-inbox.store.ts b/web/ce/store/project-inbox.store.ts new file mode 100644 index 000000000..327ff23af --- /dev/null +++ b/web/ce/store/project-inbox.store.ts @@ -0,0 +1 @@ +export * from "@/store/inbox/project-inbox.store"; diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx b/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx index 8099620fe..f137498c2 100644 --- a/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx +++ b/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx @@ -21,13 +21,27 @@ export const IssueDefaultActivity: FC = observer((props) const activity = getActivityById(activityId); if (!activity) return <>; + const source = activity.source_data?.source; + return ( ); }); diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx b/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx index b0981d981..2a9701d34 100644 --- a/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx +++ b/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx @@ -9,6 +9,7 @@ import { useIssueDetail } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; // ui // components +import { IssueCreatorDisplay } from "@/plane-web/components/issues"; import { IssueUser } from "../"; // helpers @@ -41,7 +42,11 @@ export const IssueActivityBlockComponent: FC = (pr {icon ? icon : }
- + {!activity?.field && activity?.verb === "created" ? ( + + ) : ( + + )} {children} = observer((props) => {

{t(featureItem.key)}

{featureItem.isPro && ( - + )}
@@ -103,8 +103,7 @@ export const ProjectFeaturesList: FC = observer((props) => {
{currentProjectDetails?.[featureItem.property as keyof IProject] && - featureItem.renderChildren && - featureItem.renderChildren(currentProjectDetails, isAdmin, handleSubmit, workspaceSlug)} + featureItem.renderChildren?.(currentProjectDetails, workspaceSlug)}
); diff --git a/web/core/hooks/store/use-project-inbox.ts b/web/core/hooks/store/use-project-inbox.ts index 67d4bd074..cdbff2533 100644 --- a/web/core/hooks/store/use-project-inbox.ts +++ b/web/core/hooks/store/use-project-inbox.ts @@ -1,7 +1,7 @@ import { useContext } from "react"; // mobx store import { StoreContext } from "@/lib/store-context"; -import { IProjectInboxStore } from "@/store/inbox/project-inbox.store"; +import { IProjectInboxStore } from "@/plane-web/store/project-inbox.store"; export const useProjectInbox = (): IProjectInboxStore => { const context = useContext(StoreContext); diff --git a/web/core/services/inbox/inbox-issue.service.ts b/web/core/services/inbox/inbox-issue.service.ts index 737065d70..19b62838b 100644 --- a/web/core/services/inbox/inbox-issue.service.ts +++ b/web/core/services/inbox/inbox-issue.service.ts @@ -1,6 +1,6 @@ // types import { TInboxIssue } from "@plane/constants"; -import type { TIssue, TInboxIssueWithPagination, TInboxForm } from "@plane/types"; +import type { TIssue, TInboxIssueWithPagination } from "@plane/types"; import { API_BASE_URL } from "@/helpers/common.helper"; import { APIService } from "@/services/api.service"; // helpers @@ -76,28 +76,4 @@ export class InboxIssueService extends APIService { throw error?.response?.data; }); } - - async retrievePublishForm(workspaceSlug: string, projectId: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/intake-settings/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async updatePublishForm(workspaceSlug: string, projectId: string, data: Partial): Promise { - return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/intake-settings/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async regeneratePublishForm(workspaceSlug: string, projectId: string): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/publish-intake-regenerate/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } } diff --git a/web/core/store/inbox/project-inbox.store.ts b/web/core/store/inbox/project-inbox.store.ts index 55a48b690..996f85d0d 100644 --- a/web/core/store/inbox/project-inbox.store.ts +++ b/web/core/store/inbox/project-inbox.store.ts @@ -11,7 +11,6 @@ import { TInboxIssueSorting, TInboxIssuePaginationInfo, TInboxIssueSortingOrderByQueryParam, - TInboxForm, } from "@plane/types"; // helpers import { EInboxIssueCurrentTab, EInboxIssueStatus, EPastDurationFilters, getCustomDates } from "@/helpers/inbox.helper"; @@ -39,7 +38,6 @@ export interface IProjectInboxStore { inboxIssuePaginationInfo: TInboxIssuePaginationInfo | undefined; inboxIssues: Record; // issue_id -> IInboxIssueStore inboxIssueIds: string[]; - intakeForms: Record; // computed inboxFilters: Partial; // computed project inbox filters inboxSorting: Partial; // computed project inbox sorting @@ -69,9 +67,6 @@ export interface IProjectInboxStore { ) => Promise; fetchInboxPaginationIssues: (workspaceSlug: string, projectId: string) => Promise; fetchInboxIssueById: (workspaceSlug: string, projectId: string, inboxIssueId: string) => Promise; - fetchIntakeForms: (workspaceSlug: string, projectId: string) => Promise; - toggleIntakeForms: (workspaceSlug: string, projectId: string, data: Partial) => Promise; - regenerateIntakeForms: (workspaceSlug: string, projectId: string) => Promise; createInboxIssue: ( workspaceSlug: string, projectId: string, @@ -93,7 +88,6 @@ export class ProjectInboxStore implements IProjectInboxStore { inboxIssuePaginationInfo: TInboxIssuePaginationInfo | undefined = undefined; inboxIssues: Record = {}; inboxIssueIds: string[] = []; - intakeForms: Record = {}; // services inboxIssueService; @@ -108,7 +102,6 @@ export class ProjectInboxStore implements IProjectInboxStore { inboxIssuePaginationInfo: observable, inboxIssues: observable, inboxIssueIds: observable, - intakeForms: observable, // computed inboxFilters: computed, inboxSorting: computed, @@ -316,51 +309,6 @@ export class ProjectInboxStore implements IProjectInboxStore { } }; - fetchIntakeForms = async (workspaceSlug: string, projectId: string) => { - try { - const intakeForms = await this.inboxIssueService.retrievePublishForm(workspaceSlug, projectId); - if (intakeForms) - runInAction(() => { - set(this.intakeForms, projectId, intakeForms); - }); - } catch { - console.error("Error fetching the publish forms"); - } - }; - - toggleIntakeForms = async (workspaceSlug: string, projectId: string, data: Partial) => { - const initialData = this.intakeForms[projectId]; - try { - runInAction(() => { - set(this.intakeForms, projectId, { ...this.intakeForms[projectId], ...data }); - }); - const result = await this.inboxIssueService.updatePublishForm(workspaceSlug, projectId, data); - runInAction(() => { - set(this.intakeForms, projectId, { ...this.intakeForms[projectId], anchor: result?.anchor }); - }); - } catch { - console.error("Error fetching the publish forms"); - runInAction(() => { - set(this.intakeForms, projectId, initialData); - }); - } - }; - regenerateIntakeForms = async (workspaceSlug: string, projectId: string) => { - try { - const form = await this.inboxIssueService.regeneratePublishForm(workspaceSlug, projectId); - if (form) { - runInAction(() => { - set(this.intakeForms, projectId, { - ...this.intakeForms[projectId], - anchor: form?.anchor, - }); - }); - } - } catch { - console.error("Error fetching the publish forms"); - } - }; - /** * @description fetch intake issues with paginated data * @param workspaceSlug diff --git a/web/ee/components/issues/issue-details/index.ts b/web/ee/components/issues/issue-details/index.ts index e23fbe531..4125ebf83 100644 --- a/web/ee/components/issues/issue-details/index.ts +++ b/web/ee/components/issues/issue-details/index.ts @@ -3,3 +3,4 @@ export * from "./issue-properties-activity"; export * from "./issue-type-switcher"; export * from "./issue-type-activity"; export * from "./parent-select-root"; +export * from "./issue-creator"; diff --git a/web/ee/components/issues/issue-details/issue-creator.tsx b/web/ee/components/issues/issue-details/issue-creator.tsx new file mode 100644 index 000000000..a9902b36c --- /dev/null +++ b/web/ee/components/issues/issue-details/issue-creator.tsx @@ -0,0 +1 @@ +export * from "ce/components/issues/issue-details/issue-creator"; diff --git a/web/ee/store/project-inbox.store.ts b/web/ee/store/project-inbox.store.ts new file mode 100644 index 000000000..309e1e51e --- /dev/null +++ b/web/ee/store/project-inbox.store.ts @@ -0,0 +1 @@ +export * from "ce/store/project-inbox.store";