diff --git a/apps/api/plane/db/models/asset.py b/apps/api/plane/db/models/asset.py index 55efff7f41d..e04cf4119ff 100644 --- a/apps/api/plane/db/models/asset.py +++ b/apps/api/plane/db/models/asset.py @@ -44,6 +44,7 @@ class EntityTypeContext(models.TextChoices): PROJECT_COVER = "PROJECT_COVER" DRAFT_ISSUE_ATTACHMENT = "DRAFT_ISSUE_ATTACHMENT" DRAFT_ISSUE_DESCRIPTION = "DRAFT_ISSUE_DESCRIPTION" + MODULE_DESCRIPTION = "MODULE_DESCRIPTION" attributes = models.JSONField(default=dict) asset = models.FileField(upload_to=get_upload_path, max_length=800) @@ -97,6 +98,7 @@ def asset_url(self): self.EntityTypeContext.COMMENT_DESCRIPTION, self.EntityTypeContext.PAGE_DESCRIPTION, self.EntityTypeContext.DRAFT_ISSUE_DESCRIPTION, + self.EntityTypeContext.MODULE_DESCRIPTION, ]: return f"/api/assets/v2/workspaces/{self.workspace.slug}/projects/{self.project_id}/{self.id}/" diff --git a/apps/web/core/components/modules/analytics-sidebar/root.tsx b/apps/web/core/components/modules/analytics-sidebar/root.tsx index d5844e6a0eb..bb64b5144b8 100644 --- a/apps/web/core/components/modules/analytics-sidebar/root.tsx +++ b/apps/web/core/components/modules/analytics-sidebar/root.tsx @@ -4,7 +4,7 @@ * See the LICENSE file for details. */ -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Controller, useForm } from "react-hook-form"; @@ -23,14 +23,17 @@ import { ChevronRightIcon, } from "@plane/propel/icons"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; -import type { ILinkDetails, IModule, ModuleLink } from "@plane/types"; +import type { ILinkDetails, IModule, ModuleLink, TModuleStatus, TNameDescriptionLoader } from "@plane/types"; +import { EFileAssetType } from "@plane/types"; // plane ui -import { Loader, CustomSelect, TextArea } from "@plane/ui"; +import { Loader, CustomSelect } from "@plane/ui"; // components // helpers -import { getDate, renderFormattedPayloadDate } from "@plane/utils"; +import { getDate, getModuleDescriptionInitialValue, renderFormattedPayloadDate } from "@plane/utils"; import { DateRangeDropdown } from "@/components/dropdowns/date-range"; import { MemberDropdown } from "@/components/dropdowns/member/dropdown"; +import { DescriptionInput } from "@/components/editor/rich-text/description-input"; +import { NameDescriptionUpdateStatus } from "@/components/issues/issue-update-status"; import { CreateUpdateModuleLinkModal, ModuleAnalyticsProgress, ModuleLinksList } from "@/components/modules"; // hooks import { useProjectEstimates } from "@/hooks/store/estimates"; @@ -57,6 +60,7 @@ export const ModuleAnalyticsSidebar = observer(function ModuleAnalyticsSidebar(p // states const [moduleLinkModal, setModuleLinkModal] = useState(false); const [selectedLinkToUpdate, setSelectedLinkToUpdate] = useState(null); + const [isSubmittingDescription, setIsSubmittingDescription] = useState("saved"); // router const { workspaceSlug, projectId } = useParams(); @@ -71,7 +75,9 @@ export const ModuleAnalyticsSidebar = observer(function ModuleAnalyticsSidebar(p const moduleDetails = getModuleById(moduleId); const areEstimateEnabled = projectId && areEstimateEnabledByProjectId(projectId.toString()); const estimateType = areEstimateEnabled && currentActiveEstimateId && estimateById(currentActiveEstimateId); - const isEstimatePointValid = estimateType && estimateType?.type == EEstimateSystem.POINTS ? true : false; + const isEstimatePointValid = !!(estimateType && estimateType?.type == EEstimateSystem.POINTS); + // the editor is uncontrolled, so only recompute its starting content when the description actually changes + const descriptionInitialValue = useMemo(() => getModuleDescriptionInitialValue(moduleDetails), [moduleDetails]); const { reset, control } = useForm({ defaultValues, @@ -215,8 +221,8 @@ export const ModuleAnalyticsSidebar = observer(function ModuleAnalyticsSidebar(p } value={value} - onChange={(value: any) => { - submitChanges({ status: value }); + onChange={(selectedStatus: TModuleStatus) => { + submitChanges({ status: selectedStatus }); }} disabled={!isEditingAllowed || isArchived} > @@ -235,14 +241,27 @@ export const ModuleAnalyticsSidebar = observer(function ModuleAnalyticsSidebar(p

{moduleDetails.name}

- {moduleDetails.description && ( -