diff --git a/apiserver/plane/app/views/estimate/base.py b/apiserver/plane/app/views/estimate/base.py index 77557e2b4..1705e5567 100644 --- a/apiserver/plane/app/views/estimate/base.py +++ b/apiserver/plane/app/views/estimate/base.py @@ -62,8 +62,9 @@ class BulkEstimatePointEndpoint(BaseViewSet): path="/api/workspaces/:slug/estimates/", url_params=True, user=False ) def create(self, request, slug, project_id): - estimate_name = request.data.get("name", generate_random_name()) - last_used = request.data.get("last_used", False) + estimate = request.data.get('estimate') + estimate_name = estimate.get("name", generate_random_name()) + last_used = estimate.get("last_used", False) estimate = Estimate.objects.create( name=estimate_name, project_id=project_id, last_used=last_used ) diff --git a/web/components/estimates/create/stage-two.tsx b/web/components/estimates/create/stage-two.tsx index ab703a3d0..ec5f67aa3 100644 --- a/web/components/estimates/create/stage-two.tsx +++ b/web/components/estimates/create/stage-two.tsx @@ -46,6 +46,12 @@ export const EstimateCreateStageTwo: FC = observer((pro handleEstimatePoints(newEstimationPoints); }; + const replaceEstimateItem = (index: number, value: TEstimatePointsObject) => { + const newEstimationPoints = estimatePoints; + newEstimationPoints[index] = value; + handleEstimatePoints(newEstimationPoints); + }; + const updatedSortedKeys = (updatedEstimatePoints: TEstimatePointsObject[]) => { const sortedEstimatePoints = updatedEstimatePoints.map((item, index) => ({ ...item, @@ -67,10 +73,9 @@ export const EstimateCreateStageTwo: FC = observer((pro estimateId={undefined} mode={EEstimateUpdateStages.CREATE} item={value} - estimatePoints={estimatePoints} editItem={(value: string) => editEstimationPoint(index, value)} + replaceEstimateItem={(value: TEstimatePointsObject) => replaceEstimateItem(index, value)} deleteItem={() => deleteEstimationPoint(index)} - handleEstimatePoints={handleEstimatePoints} /> )} onChange={(data: TEstimatePointsObject[]) => handleEstimatePoints(updatedSortedKeys(data))} diff --git a/web/components/estimates/points/estimate-point-item.tsx b/web/components/estimates/points/estimate-point-item.tsx index 899352d21..5b622c8a8 100644 --- a/web/components/estimates/points/estimate-point-item.tsx +++ b/web/components/estimates/points/estimate-point-item.tsx @@ -16,25 +16,14 @@ type TEstimatePointItem = { estimateId: string | undefined; mode: EEstimateUpdateStages; item: TEstimatePointsObject; - estimatePoints: TEstimatePointsObject[]; editItem: (value: string) => void; + replaceEstimateItem: (value: TEstimatePointsObject) => void; deleteItem: () => void; - handleEstimatePoints: (value: TEstimatePointsObject[]) => void; }; export const EstimatePointItem: FC = observer((props) => { // props - const { - workspaceSlug, - projectId, - estimateId, - mode, - item, - estimatePoints, - editItem, - deleteItem, - handleEstimatePoints, - } = props; + const { workspaceSlug, projectId, estimateId, mode, item, editItem, replaceEstimateItem, deleteItem } = props; const { id, key, value } = item; // hooks const { asJson: estimate, creteEstimatePoint, deleteEstimatePoint } = useEstimate(estimateId); @@ -63,8 +52,9 @@ export const EstimatePointItem: FC = observer((props) => { try { setEstimateEditLoader(true); const estimatePoint = await creteEstimatePoint(workspaceSlug, projectId, { key: key, value: inputValue }); - if (estimatePoint) - handleEstimatePoints([...estimatePoints, { id: estimatePoint.id, key: key, value: inputValue }]); + if (estimatePoint && estimatePoint.key && estimatePoint.value) { + replaceEstimateItem({ id: estimatePoint.id, key: estimatePoint.key, value: estimatePoint.value }); + } setIsEstimateEditing(false); setEstimateEditLoader(false); } catch (error) { @@ -77,7 +67,11 @@ export const EstimatePointItem: FC = observer((props) => { if (id) { try { setEstimateEditLoader(true); - await updateEstimatePoint(workspaceSlug, projectId, { key: key, value: inputValue }); + const estimatePoint = await updateEstimatePoint(workspaceSlug, projectId, { + key: key, + value: inputValue || "", + }); + if (estimatePoint) if (estimatePoint) editItem(inputValue || ""); setIsEstimateEditing(false); setEstimateEditLoader(false); } catch (error) { @@ -93,6 +87,7 @@ export const EstimatePointItem: FC = observer((props) => { try { setEstimateEditLoader(true); await deleteEstimatePoint(workspaceSlug, projectId, id, deletedEstimateValue); + deleteItem(); setIsEstimateDeleting(false); setEstimateEditLoader(false); } catch (error) { diff --git a/web/components/estimates/update/stage-two.tsx b/web/components/estimates/update/stage-two.tsx index df58c51ab..9cf754b80 100644 --- a/web/components/estimates/update/stage-two.tsx +++ b/web/components/estimates/update/stage-two.tsx @@ -8,6 +8,7 @@ import { Button, Sortable } from "@plane/ui"; import { EstimatePointItem } from "@/components/estimates"; // constants import { EEstimateUpdateStages, maxEstimatesCount } from "@/constants/estimates"; +import { useEstimate } from "@/hooks/store"; type TEstimateUpdateStageTwo = { workspaceSlug: string; @@ -20,6 +21,8 @@ type TEstimateUpdateStageTwo = { export const EstimateUpdateStageTwo: FC = observer((props) => { const { workspaceSlug, projectId, estimate, estimateEditType, estimatePoints, handleEstimatePoints } = props; + // hooks + const { updateEstimate: updateEstimateRequest } = useEstimate(estimate?.id); const currentEstimateSystem = estimate || undefined; @@ -39,7 +42,7 @@ export const EstimateUpdateStageTwo: FC = observer((pro }; const deleteEstimationPoint = (index: number) => { - let newEstimationPoints = estimatePoints; + let newEstimationPoints = cloneDeep(estimatePoints); newEstimationPoints.splice(index, 1); newEstimationPoints = newEstimationPoints.map((item, index) => ({ ...item, @@ -48,12 +51,25 @@ export const EstimateUpdateStageTwo: FC = observer((pro handleEstimatePoints(newEstimationPoints); }; + const replaceEstimateItem = (index: number, value: TEstimatePointsObject) => { + const newEstimationPoints = cloneDeep(estimatePoints); + newEstimationPoints[index].id = value.id; + newEstimationPoints[index].key = value.key; + newEstimationPoints[index].value = value.value; + handleEstimatePoints(newEstimationPoints); + }; + const updatedSortedKeys = (updatedEstimatePoints: TEstimatePointsObject[]) => { - const sortedEstimatePoints = updatedEstimatePoints.map((item, index) => ({ - ...item, - key: index + 1, - })) as TEstimatePointsObject[]; - return sortedEstimatePoints; + try { + const sortedEstimatePoints = cloneDeep(updatedEstimatePoints).map((item, index) => ({ + ...item, + key: index + 1, + })) as TEstimatePointsObject[]; + handleEstimatePoints(sortedEstimatePoints); + updateEstimateRequest(workspaceSlug, projectId, { estimate_points: sortedEstimatePoints }); + } catch (error) { + console.log(error); + } }; if (!estimateEditType) return <>; @@ -72,13 +88,12 @@ export const EstimateUpdateStageTwo: FC = observer((pro estimateId={estimate?.id || undefined} mode={estimateEditType} item={value} - estimatePoints={estimatePoints} editItem={(value: string) => editEstimationPoint(index, value)} + replaceEstimateItem={(value: TEstimatePointsObject) => replaceEstimateItem(index, value)} deleteItem={() => deleteEstimationPoint(index)} - handleEstimatePoints={handleEstimatePoints} /> )} - onChange={(data: TEstimatePointsObject[]) => handleEstimatePoints(updatedSortedKeys(data))} + onChange={(data: TEstimatePointsObject[]) => updatedSortedKeys(data)} keyExtractor={(item: TEstimatePointsObject) => item?.id?.toString() || item.value.toString()} /> {estimateEditType === EEstimateUpdateStages.EDIT && ( diff --git a/web/services/project/estimate.service.ts b/web/services/project/estimate.service.ts index 02ee78e47..1b35d7ff7 100644 --- a/web/services/project/estimate.service.ts +++ b/web/services/project/estimate.service.ts @@ -60,7 +60,7 @@ export class EstimateService extends APIService { workspaceSlug: string, projectId: string, estimateId: string, - payload: Partial + payload: Partial ): Promise { try { const { data } = await this.patch( @@ -98,7 +98,7 @@ export class EstimateService extends APIService { payload: Partial ): Promise { try { - const { data } = await this.post( + const { data } = await this.patch( `/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/estimate-points/${estimatePointId}/`, payload ); diff --git a/web/store/estimates/estimate.ts b/web/store/estimates/estimate.ts index ad304d01b..e2580a5a9 100644 --- a/web/store/estimates/estimate.ts +++ b/web/store/estimates/estimate.ts @@ -2,7 +2,12 @@ import set from "lodash/set"; import unset from "lodash/unset"; import { action, computed, makeObservable, observable, runInAction } from "mobx"; import { computedFn } from "mobx-utils"; -import { IEstimate as IEstimateType, IEstimatePoint as IEstimatePointType, TEstimateSystemKeys } from "@plane/types"; +import { + IEstimate as IEstimateType, + IEstimatePoint as IEstimatePointType, + TEstimateSystemKeys, + IEstimateFormData, +} from "@plane/types"; // services import { EstimateService } from "@/services/project/estimate.service"; // store @@ -26,7 +31,7 @@ export interface IEstimate extends IEstimateType { updateEstimate: ( workspaceSlug: string, projectId: string, - payload: Partial + payload: Partial ) => Promise; creteEstimatePoint: ( workspaceSlug: string, @@ -149,13 +154,13 @@ export class Estimate implements IEstimate { * @description update an estimate * @param { string } workspaceSlug * @param { string } projectId - * @param { Partial } payload + * @param { Partial } payload * @returns { IEstimateType | undefined } */ updateEstimate = async ( workspaceSlug: string, projectId: string, - payload: Partial + payload: Partial ): Promise => { try { if (!this.id || !payload) return;