mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: integrated new endpoints
This commit is contained in:
parent
be03d90c86
commit
1cd31f4705
8
packages/types/src/estimate.d.ts
vendored
8
packages/types/src/estimate.d.ts
vendored
@ -1,4 +1,3 @@
|
|||||||
import { IWorkspace, IProject } from "./";
|
|
||||||
import { EEstimateSystem, EEstimateUpdateStages } from "./enums";
|
import { EEstimateSystem, EEstimateUpdateStages } from "./enums";
|
||||||
|
|
||||||
export interface IEstimatePoint {
|
export interface IEstimatePoint {
|
||||||
@ -27,9 +26,8 @@ export interface IEstimate {
|
|||||||
type: TEstimateSystemKeys | undefined; // categories, points, time
|
type: TEstimateSystemKeys | undefined; // categories, points, time
|
||||||
points: IEstimatePoint[] | undefined;
|
points: IEstimatePoint[] | undefined;
|
||||||
workspace: string | undefined;
|
workspace: string | undefined;
|
||||||
workspace_detail: IWorkspace | undefined;
|
|
||||||
project: string | undefined;
|
project: string | undefined;
|
||||||
project_detail: IProject | undefined;
|
last_used: boolean | undefined;
|
||||||
created_at: Date | undefined;
|
created_at: Date | undefined;
|
||||||
updated_at: Date | undefined;
|
updated_at: Date | undefined;
|
||||||
created_by: string | undefined;
|
created_by: string | undefined;
|
||||||
@ -38,7 +36,9 @@ export interface IEstimate {
|
|||||||
|
|
||||||
export interface IEstimateFormData {
|
export interface IEstimateFormData {
|
||||||
estimate?: {
|
estimate?: {
|
||||||
type: string;
|
name?: string;
|
||||||
|
type?: string;
|
||||||
|
last_used?: boolean;
|
||||||
};
|
};
|
||||||
estimate_points: {
|
estimate_points: {
|
||||||
id?: string | undefined;
|
id?: string | undefined;
|
||||||
|
@ -59,7 +59,9 @@ export const CreateEstimateModal: FC<TCreateEstimateModal> = observer((props) =>
|
|||||||
if (validatedEstimatePoints.length === estimatePoints?.length) {
|
if (validatedEstimatePoints.length === estimatePoints?.length) {
|
||||||
const payload: IEstimateFormData = {
|
const payload: IEstimateFormData = {
|
||||||
estimate: {
|
estimate: {
|
||||||
|
name: ESTIMATE_SYSTEMS[estimateSystem]?.name,
|
||||||
type: estimateSystem,
|
type: estimateSystem,
|
||||||
|
last_used: true,
|
||||||
},
|
},
|
||||||
estimate_points: validatedEstimatePoints,
|
estimate_points: validatedEstimatePoints,
|
||||||
};
|
};
|
||||||
@ -122,6 +124,8 @@ export const CreateEstimateModal: FC<TCreateEstimateModal> = observer((props) =>
|
|||||||
)}
|
)}
|
||||||
{estimatePoints && (
|
{estimatePoints && (
|
||||||
<EstimateCreateStageTwo
|
<EstimateCreateStageTwo
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
estimateSystem={estimateSystem}
|
estimateSystem={estimateSystem}
|
||||||
estimatePoints={estimatePoints}
|
estimatePoints={estimatePoints}
|
||||||
handleEstimatePoints={handleUpdatePoints}
|
handleEstimatePoints={handleUpdatePoints}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
import { Plus } from "lucide-react";
|
import { Plus } from "lucide-react";
|
||||||
import { TEstimatePointsObject } from "@plane/types";
|
import { TEstimatePointsObject } from "@plane/types";
|
||||||
import { Button, Sortable } from "@plane/ui";
|
import { Button, Sortable } from "@plane/ui";
|
||||||
@ -8,13 +9,15 @@ import { EstimatePointItem } from "@/components/estimates";
|
|||||||
import { EEstimateSystem, EEstimateUpdateStages, ESTIMATE_SYSTEMS, maxEstimatesCount } from "@/constants/estimates";
|
import { EEstimateSystem, EEstimateUpdateStages, ESTIMATE_SYSTEMS, maxEstimatesCount } from "@/constants/estimates";
|
||||||
|
|
||||||
type TEstimateCreateStageTwo = {
|
type TEstimateCreateStageTwo = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
estimateSystem: EEstimateSystem;
|
estimateSystem: EEstimateSystem;
|
||||||
estimatePoints: TEstimatePointsObject[];
|
estimatePoints: TEstimatePointsObject[];
|
||||||
handleEstimatePoints: (value: TEstimatePointsObject[]) => void;
|
handleEstimatePoints: (value: TEstimatePointsObject[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EstimateCreateStageTwo: FC<TEstimateCreateStageTwo> = (props) => {
|
export const EstimateCreateStageTwo: FC<TEstimateCreateStageTwo> = observer((props) => {
|
||||||
const { estimateSystem, estimatePoints, handleEstimatePoints } = props;
|
const { workspaceSlug, projectId, estimateSystem, estimatePoints, handleEstimatePoints } = props;
|
||||||
|
|
||||||
const currentEstimateSystem = ESTIMATE_SYSTEMS[estimateSystem] || undefined;
|
const currentEstimateSystem = ESTIMATE_SYSTEMS[estimateSystem] || undefined;
|
||||||
|
|
||||||
@ -22,7 +25,7 @@ export const EstimateCreateStageTwo: FC<TEstimateCreateStageTwo> = (props) => {
|
|||||||
const currentEstimationPoints = estimatePoints;
|
const currentEstimationPoints = estimatePoints;
|
||||||
const newEstimationPoint: TEstimatePointsObject = {
|
const newEstimationPoint: TEstimatePointsObject = {
|
||||||
key: currentEstimationPoints.length + 1,
|
key: currentEstimationPoints.length + 1,
|
||||||
value: "0",
|
value: "",
|
||||||
};
|
};
|
||||||
handleEstimatePoints([...currentEstimationPoints, newEstimationPoint]);
|
handleEstimatePoints([...currentEstimationPoints, newEstimationPoint]);
|
||||||
};
|
};
|
||||||
@ -59,11 +62,15 @@ export const EstimateCreateStageTwo: FC<TEstimateCreateStageTwo> = (props) => {
|
|||||||
data={estimatePoints}
|
data={estimatePoints}
|
||||||
render={(value: TEstimatePointsObject, index: number) => (
|
render={(value: TEstimatePointsObject, index: number) => (
|
||||||
<EstimatePointItem
|
<EstimatePointItem
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
estimateId={undefined}
|
estimateId={undefined}
|
||||||
mode={EEstimateUpdateStages.CREATE}
|
mode={EEstimateUpdateStages.CREATE}
|
||||||
item={value}
|
item={value}
|
||||||
|
estimatePoints={estimatePoints}
|
||||||
editItem={(value: string) => editEstimationPoint(index, value)}
|
editItem={(value: string) => editEstimationPoint(index, value)}
|
||||||
deleteItem={() => deleteEstimationPoint(index)}
|
deleteItem={() => deleteEstimationPoint(index)}
|
||||||
|
handleEstimatePoints={handleEstimatePoints}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
onChange={(data: TEstimatePointsObject[]) => handleEstimatePoints(updatedSortedKeys(data))}
|
onChange={(data: TEstimatePointsObject[]) => handleEstimatePoints(updatedSortedKeys(data))}
|
||||||
@ -77,4 +84,4 @@ export const EstimateCreateStageTwo: FC<TEstimateCreateStageTwo> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -17,5 +17,4 @@ export * from "./create";
|
|||||||
export * from "./update";
|
export * from "./update";
|
||||||
|
|
||||||
// estimate points
|
// estimate points
|
||||||
export * from "./points/estimate-point-item";
|
export * from "./points";
|
||||||
export * from "./points/inline-editable";
|
|
||||||
|
95
web/components/estimates/points/create.tsx
Normal file
95
web/components/estimates/points/create.tsx
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import { FC, useState } from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Check, X } from "lucide-react";
|
||||||
|
import { Spinner } from "@plane/ui";
|
||||||
|
// constants
|
||||||
|
import { EEstimateSystem } from "@/constants/estimates";
|
||||||
|
// hooks
|
||||||
|
import { useEstimate } from "@/hooks/store";
|
||||||
|
|
||||||
|
type TEstimatePointCreate = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
estimateId: string;
|
||||||
|
estimatePointId: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) => {
|
||||||
|
const { workspaceSlug, projectId, estimateId, estimatePointId } = props;
|
||||||
|
// hooks
|
||||||
|
const { asJson: estimate, estimatePointIds, creteEstimatePoint } = useEstimate(estimateId);
|
||||||
|
// states
|
||||||
|
const [loader, setLoader] = useState(false);
|
||||||
|
const [estimateValue, setEstimateValue] = useState("");
|
||||||
|
|
||||||
|
const handleCreate = async () => {
|
||||||
|
if (estimatePointId) {
|
||||||
|
if (!workspaceSlug || !projectId || !projectId || !estimatePointIds) return;
|
||||||
|
try {
|
||||||
|
const estimateType: EEstimateSystem | undefined = estimate?.type;
|
||||||
|
let isEstimateValid = false;
|
||||||
|
if (estimateType && [(EEstimateSystem.TIME, EEstimateSystem.POINTS)].includes(estimateType)) {
|
||||||
|
if (estimateValue && Number(estimateValue) && Number(estimateValue) >= 0) {
|
||||||
|
isEstimateValid = true;
|
||||||
|
}
|
||||||
|
} else if (estimateType && estimateType === EEstimateSystem.CATEGORIES) {
|
||||||
|
if (estimateValue && estimateValue.length > 0) {
|
||||||
|
isEstimateValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEstimateValid) {
|
||||||
|
setLoader(true);
|
||||||
|
const payload = {
|
||||||
|
key: estimatePointIds?.length + 1,
|
||||||
|
value: estimateValue,
|
||||||
|
};
|
||||||
|
await creteEstimatePoint(workspaceSlug, projectId, payload);
|
||||||
|
setLoader(false);
|
||||||
|
handleClose();
|
||||||
|
} else {
|
||||||
|
console.log("please enter a valid estimate value");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setLoader(false);
|
||||||
|
console.log("something went wrong. please try again later");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setEstimateValue("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative flex items-center gap-2">
|
||||||
|
<div className="w-full border border-custom-border-200 rounded">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={estimateValue}
|
||||||
|
onChange={(e) => setEstimateValue(e.target.value)}
|
||||||
|
className="border-none focus:ring-0 focus:border-0 focus:outline-none p-2.5 w-full bg-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{loader ? (
|
||||||
|
<div className="w-6 h-6 flex-shrink-0 relative flex justify-center items-center rota">
|
||||||
|
<Spinner className="w-4 h-4" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||||
|
onClick={handleCreate}
|
||||||
|
>
|
||||||
|
<Check size={14} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
<X size={14} className="text-custom-text-200" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
100
web/components/estimates/points/delete.tsx
Normal file
100
web/components/estimates/points/delete.tsx
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { FC, useEffect, useState } from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Check, X } from "lucide-react";
|
||||||
|
import { Spinner } from "@plane/ui";
|
||||||
|
// constants
|
||||||
|
import { EEstimateSystem } from "@/constants/estimates";
|
||||||
|
// hooks
|
||||||
|
import { useEstimate, useEstimatePoint } from "@/hooks/store";
|
||||||
|
|
||||||
|
type TEstimatePointDelete = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
estimateId: string;
|
||||||
|
estimatePointId: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EstimatePointDelete: FC<TEstimatePointDelete> = observer((props) => {
|
||||||
|
const { workspaceSlug, projectId, estimateId, estimatePointId } = props;
|
||||||
|
// hooks
|
||||||
|
const { asJson: estimate, estimatePointIds } = useEstimate(estimateId);
|
||||||
|
const { asJson: estimatePoint, updateEstimatePoint } = useEstimatePoint(estimateId, estimatePointId);
|
||||||
|
// states
|
||||||
|
const [loader, setLoader] = useState(false);
|
||||||
|
const [estimateValue, setEstimateValue] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (estimateValue === undefined) setEstimateValue(estimatePoint?.value || "");
|
||||||
|
}, [estimateValue, estimatePoint]);
|
||||||
|
|
||||||
|
const handleCreate = async () => {
|
||||||
|
if (estimatePointId) {
|
||||||
|
if (!workspaceSlug || !projectId || !projectId || !estimatePointIds) return;
|
||||||
|
try {
|
||||||
|
const estimateType: EEstimateSystem | undefined = estimate?.type;
|
||||||
|
let isEstimateValid = false;
|
||||||
|
if (estimateType && [(EEstimateSystem.TIME, EEstimateSystem.POINTS)].includes(estimateType)) {
|
||||||
|
if (estimateValue && Number(estimateValue) && Number(estimateValue) >= 0) {
|
||||||
|
isEstimateValid = true;
|
||||||
|
}
|
||||||
|
} else if (estimateType && estimateType === EEstimateSystem.CATEGORIES) {
|
||||||
|
if (estimateValue && estimateValue.length > 0) {
|
||||||
|
isEstimateValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEstimateValid) {
|
||||||
|
setLoader(true);
|
||||||
|
const payload = {
|
||||||
|
key: estimatePointIds?.length + 1,
|
||||||
|
value: estimateValue,
|
||||||
|
};
|
||||||
|
await updateEstimatePoint(workspaceSlug, projectId, payload);
|
||||||
|
setLoader(false);
|
||||||
|
handleClose();
|
||||||
|
} else {
|
||||||
|
console.log("please enter a valid estimate value");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setLoader(false);
|
||||||
|
console.log("something went wrong. please try again later");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setEstimateValue("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative flex items-center gap-2">
|
||||||
|
<div className="w-full border border-custom-border-200 rounded">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={estimateValue}
|
||||||
|
onChange={(e) => setEstimateValue(e.target.value)}
|
||||||
|
className="border-none focus:ring-0 focus:border-0 focus:outline-none p-2.5 w-full bg-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{loader ? (
|
||||||
|
<div className="w-6 h-6 flex-shrink-0 relative flex justify-center items-center rota">
|
||||||
|
<Spinner className="w-4 h-4" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||||
|
onClick={handleCreate}
|
||||||
|
>
|
||||||
|
<Check size={14} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
<X size={14} className="text-custom-text-200" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
29
web/components/estimates/points/edit-root.tsx
Normal file
29
web/components/estimates/points/edit-root.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { FC, useState } from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Draggable } from "@plane/ui";
|
||||||
|
// constants
|
||||||
|
import { EEstimateUpdateStages } from "@/constants/estimates";
|
||||||
|
|
||||||
|
type TEstimatePointEditRoot = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
estimateId: string;
|
||||||
|
mode: EEstimateUpdateStages;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TEstimatePointEditingState = "update" | "delete";
|
||||||
|
|
||||||
|
export const EstimatePointEditRoot: FC<TEstimatePointEditRoot> = observer((props) => {
|
||||||
|
// props
|
||||||
|
const { workspaceSlug, projectId, estimateId, mode } = props;
|
||||||
|
// hooks
|
||||||
|
// states
|
||||||
|
const [editingState, setEditingState] = useState<TEstimatePointEditingState | undefined>(undefined);
|
||||||
|
|
||||||
|
const [estimateEditLoader, setEstimateEditLoader] = useState(false);
|
||||||
|
const [deletedEstimateValue, setDeletedEstimateValue] = useState<string | undefined>(undefined);
|
||||||
|
const [isEstimateEditing, setIsEstimateEditing] = useState(false);
|
||||||
|
const [isEstimateDeleting, setIsEstimateDeleting] = useState(false);
|
||||||
|
|
||||||
|
return <Draggable data={item}></Draggable>;
|
||||||
|
});
|
@ -8,22 +8,37 @@ import { Draggable, Spinner } from "@plane/ui";
|
|||||||
import { EEstimateUpdateStages } from "@/constants/estimates";
|
import { EEstimateUpdateStages } from "@/constants/estimates";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
import { useEstimate } from "@/hooks/store";
|
import { useEstimate, useEstimatePoint } from "@/hooks/store";
|
||||||
|
|
||||||
type TEstimatePointItem = {
|
type TEstimatePointItem = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
estimateId: string | undefined;
|
estimateId: string | undefined;
|
||||||
mode: EEstimateUpdateStages;
|
mode: EEstimateUpdateStages;
|
||||||
item: TEstimatePointsObject;
|
item: TEstimatePointsObject;
|
||||||
|
estimatePoints: TEstimatePointsObject[];
|
||||||
editItem: (value: string) => void;
|
editItem: (value: string) => void;
|
||||||
deleteItem: () => void;
|
deleteItem: () => void;
|
||||||
|
handleEstimatePoints: (value: TEstimatePointsObject[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EstimatePointItem: FC<TEstimatePointItem> = observer((props) => {
|
export const EstimatePointItem: FC<TEstimatePointItem> = observer((props) => {
|
||||||
// props
|
// props
|
||||||
const { estimateId, mode, item, editItem, deleteItem } = props;
|
const {
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
estimateId,
|
||||||
|
mode,
|
||||||
|
item,
|
||||||
|
estimatePoints,
|
||||||
|
editItem,
|
||||||
|
deleteItem,
|
||||||
|
handleEstimatePoints,
|
||||||
|
} = props;
|
||||||
const { id, key, value } = item;
|
const { id, key, value } = item;
|
||||||
// hooks
|
// hooks
|
||||||
const { asJson: estimate, updateEstimate, deleteEstimate } = useEstimate(estimateId);
|
const { asJson: estimate, creteEstimatePoint, deleteEstimatePoint } = useEstimate(estimateId);
|
||||||
|
const { updateEstimatePoint } = useEstimatePoint(estimateId, id);
|
||||||
// ref
|
// ref
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
// states
|
// states
|
||||||
@ -35,7 +50,7 @@ export const EstimatePointItem: FC<TEstimatePointItem> = observer((props) => {
|
|||||||
const [isEstimateDeleting, setIsEstimateDeleting] = useState(false);
|
const [isEstimateDeleting, setIsEstimateDeleting] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (inputValue === undefined || inputValue != value) setInputValue(value);
|
if (value && inputValue === undefined) setInputValue(value);
|
||||||
}, [value, inputValue]);
|
}, [value, inputValue]);
|
||||||
|
|
||||||
const handleCreateEdit = (value: string) => {
|
const handleCreateEdit = (value: string) => {
|
||||||
@ -43,11 +58,26 @@ export const EstimatePointItem: FC<TEstimatePointItem> = observer((props) => {
|
|||||||
editItem(value);
|
editItem(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleNewEstimatePoint = async () => {
|
||||||
|
if (inputValue) {
|
||||||
|
try {
|
||||||
|
setEstimateEditLoader(true);
|
||||||
|
const estimatePoint = await creteEstimatePoint(workspaceSlug, projectId, { key: key, value: inputValue });
|
||||||
|
if (estimatePoint)
|
||||||
|
handleEstimatePoints([...estimatePoints, { id: estimatePoint.id, key: key, value: inputValue }]);
|
||||||
|
setIsEstimateEditing(false);
|
||||||
|
setEstimateEditLoader(false);
|
||||||
|
} catch (error) {
|
||||||
|
setEstimateEditLoader(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleEdit = async () => {
|
const handleEdit = async () => {
|
||||||
if (id) {
|
if (id) {
|
||||||
try {
|
try {
|
||||||
setEstimateEditLoader(true);
|
setEstimateEditLoader(true);
|
||||||
await updateEstimate({ estimate_points: [{ id: id, key: key, value: value }] });
|
await updateEstimatePoint(workspaceSlug, projectId, { key: key, value: inputValue });
|
||||||
setIsEstimateEditing(false);
|
setIsEstimateEditing(false);
|
||||||
setEstimateEditLoader(false);
|
setEstimateEditLoader(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -62,7 +92,7 @@ export const EstimatePointItem: FC<TEstimatePointItem> = observer((props) => {
|
|||||||
if (id) {
|
if (id) {
|
||||||
try {
|
try {
|
||||||
setEstimateEditLoader(true);
|
setEstimateEditLoader(true);
|
||||||
await deleteEstimate(deletedEstimateValue);
|
await deleteEstimatePoint(workspaceSlug, projectId, id, deletedEstimateValue);
|
||||||
setIsEstimateDeleting(false);
|
setIsEstimateDeleting(false);
|
||||||
setEstimateEditLoader(false);
|
setEstimateEditLoader(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -78,24 +108,65 @@ export const EstimatePointItem: FC<TEstimatePointItem> = observer((props) => {
|
|||||||
return (
|
return (
|
||||||
<Draggable data={item}>
|
<Draggable data={item}>
|
||||||
{!id && (
|
{!id && (
|
||||||
<div className="border border-custom-border-200 rounded relative flex items-center px-2.5 gap-2">
|
<>
|
||||||
<div className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer">
|
{mode === EEstimateUpdateStages.CREATE && (
|
||||||
<GripVertical size={14} className="text-custom-text-200" />
|
<div className="border border-custom-border-200 rounded relative flex items-center px-2.5 gap-2">
|
||||||
</div>
|
<div className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer">
|
||||||
<input
|
<GripVertical size={14} className="text-custom-text-200" />
|
||||||
ref={inputRef}
|
</div>
|
||||||
type="text"
|
<input
|
||||||
value={inputValue}
|
ref={inputRef}
|
||||||
onChange={(e) => handleCreateEdit(e.target.value)}
|
type="text"
|
||||||
className="flex-grow border-none bg-transparent focus:ring-0 focus:border-0 focus:outline-none py-2.5 w-full"
|
value={inputValue}
|
||||||
/>
|
onChange={(e) => handleCreateEdit(e.target.value)}
|
||||||
<div
|
className="flex-grow border-none bg-transparent focus:ring-0 focus:border-0 focus:outline-none py-2.5 w-full"
|
||||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
/>
|
||||||
onClick={handleDelete}
|
<div
|
||||||
>
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||||
<Trash2 size={14} className="text-custom-text-200" />
|
onClick={handleDelete}
|
||||||
</div>
|
>
|
||||||
</div>
|
<Trash2 size={14} className="text-custom-text-200" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{mode === EEstimateUpdateStages.EDIT && (
|
||||||
|
<div className="relative flex items-center gap-2">
|
||||||
|
<div className="w-full border border-custom-border-200 rounded">
|
||||||
|
<input
|
||||||
|
ref={inputRef}
|
||||||
|
type="text"
|
||||||
|
value={inputValue}
|
||||||
|
onChange={(e) => setInputValue(e.target.value)}
|
||||||
|
className={cn(
|
||||||
|
"border-none focus:ring-0 focus:border-0 focus:outline-none p-2.5 w-full",
|
||||||
|
isEstimateDeleting ? `bg-custom-background-90` : `bg-transparent`
|
||||||
|
)}
|
||||||
|
disabled={isEstimateDeleting}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{estimateEditLoader ? (
|
||||||
|
<div className="w-6 h-6 flex-shrink-0 relative flex justify-center items-center rota">
|
||||||
|
<Spinner className="w-4 h-4" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||||
|
onClick={handleNewEstimatePoint}
|
||||||
|
>
|
||||||
|
<Check size={14} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||||
|
onClick={handleDelete}
|
||||||
|
>
|
||||||
|
<X size={14} className="text-custom-text-200" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{id && (
|
{id && (
|
||||||
|
8
web/components/estimates/points/index.ts
Normal file
8
web/components/estimates/points/index.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export * from "./estimate-point-item";
|
||||||
|
export * from "./inline-editable";
|
||||||
|
|
||||||
|
export * from "./edit-root";
|
||||||
|
|
||||||
|
export * from "./create";
|
||||||
|
export * from "./update";
|
||||||
|
export * from "./delete";
|
100
web/components/estimates/points/update.tsx
Normal file
100
web/components/estimates/points/update.tsx
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { FC, useEffect, useState } from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Check, X } from "lucide-react";
|
||||||
|
import { Spinner } from "@plane/ui";
|
||||||
|
// constants
|
||||||
|
import { EEstimateSystem } from "@/constants/estimates";
|
||||||
|
// hooks
|
||||||
|
import { useEstimate, useEstimatePoint } from "@/hooks/store";
|
||||||
|
|
||||||
|
type TEstimatePointUpdate = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
estimateId: string;
|
||||||
|
estimatePointId: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EstimatePointUpdate: FC<TEstimatePointUpdate> = observer((props) => {
|
||||||
|
const { workspaceSlug, projectId, estimateId, estimatePointId } = props;
|
||||||
|
// hooks
|
||||||
|
const { asJson: estimate, estimatePointIds } = useEstimate(estimateId);
|
||||||
|
const { asJson: estimatePoint, updateEstimatePoint } = useEstimatePoint(estimateId, estimatePointId);
|
||||||
|
// states
|
||||||
|
const [loader, setLoader] = useState(false);
|
||||||
|
const [estimateValue, setEstimateValue] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (estimateValue === undefined) setEstimateValue(estimatePoint?.value || "");
|
||||||
|
}, [estimateValue, estimatePoint]);
|
||||||
|
|
||||||
|
const handleCreate = async () => {
|
||||||
|
if (estimatePointId) {
|
||||||
|
if (!workspaceSlug || !projectId || !projectId || !estimatePointIds) return;
|
||||||
|
try {
|
||||||
|
const estimateType: EEstimateSystem | undefined = estimate?.type;
|
||||||
|
let isEstimateValid = false;
|
||||||
|
if (estimateType && [(EEstimateSystem.TIME, EEstimateSystem.POINTS)].includes(estimateType)) {
|
||||||
|
if (estimateValue && Number(estimateValue) && Number(estimateValue) >= 0) {
|
||||||
|
isEstimateValid = true;
|
||||||
|
}
|
||||||
|
} else if (estimateType && estimateType === EEstimateSystem.CATEGORIES) {
|
||||||
|
if (estimateValue && estimateValue.length > 0) {
|
||||||
|
isEstimateValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEstimateValid) {
|
||||||
|
setLoader(true);
|
||||||
|
const payload = {
|
||||||
|
key: estimatePointIds?.length + 1,
|
||||||
|
value: estimateValue,
|
||||||
|
};
|
||||||
|
await updateEstimatePoint(workspaceSlug, projectId, payload);
|
||||||
|
setLoader(false);
|
||||||
|
handleClose();
|
||||||
|
} else {
|
||||||
|
console.log("please enter a valid estimate value");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setLoader(false);
|
||||||
|
console.log("something went wrong. please try again later");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setEstimateValue("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative flex items-center gap-2">
|
||||||
|
<div className="w-full border border-custom-border-200 rounded">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={estimateValue}
|
||||||
|
onChange={(e) => setEstimateValue(e.target.value)}
|
||||||
|
className="border-none focus:ring-0 focus:border-0 focus:outline-none p-2.5 w-full bg-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{loader ? (
|
||||||
|
<div className="w-6 h-6 flex-shrink-0 relative flex justify-center items-center rota">
|
||||||
|
<Spinner className="w-4 h-4" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||||
|
onClick={handleCreate}
|
||||||
|
>
|
||||||
|
<Check size={14} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
<X size={14} className="text-custom-text-200" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
@ -1,13 +1,12 @@
|
|||||||
import { FC, useEffect, useMemo, useState } from "react";
|
import { FC, useEffect, useMemo, useState } from "react";
|
||||||
|
import orderBy from "lodash/orderBy";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { ChevronLeft } from "lucide-react";
|
import { ChevronLeft } from "lucide-react";
|
||||||
import { IEstimateFormData, TEstimatePointsObject, TEstimateUpdateStageKeys, TEstimateSystemKeys } from "@plane/types";
|
import { TEstimatePointsObject, TEstimateUpdateStageKeys } from "@plane/types";
|
||||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
import { Button } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { EModalPosition, EModalWidth, ModalCore } from "@/components/core";
|
import { EModalPosition, EModalWidth, ModalCore } from "@/components/core";
|
||||||
import { EstimateUpdateStageOne, EstimateUpdateStageTwo } from "@/components/estimates";
|
import { EstimateUpdateStageOne, EstimateUpdateStageTwo } from "@/components/estimates";
|
||||||
// constants
|
|
||||||
import { EEstimateSystem } from "@/constants/estimates";
|
|
||||||
// hooks
|
// hooks
|
||||||
import {
|
import {
|
||||||
useEstimate,
|
useEstimate,
|
||||||
@ -26,18 +25,19 @@ export const UpdateEstimateModal: FC<TUpdateEstimateModal> = observer((props) =>
|
|||||||
// props
|
// props
|
||||||
const { workspaceSlug, projectId, estimateId, isOpen, handleClose } = props;
|
const { workspaceSlug, projectId, estimateId, isOpen, handleClose } = props;
|
||||||
// hooks
|
// hooks
|
||||||
const { asJson: currentEstimate, updateEstimate } = useEstimate(estimateId);
|
const { asJson: currentEstimate } = useEstimate(estimateId);
|
||||||
// states
|
// states
|
||||||
const [estimateEditType, setEstimateEditType] = useState<TEstimateUpdateStageKeys | undefined>(undefined);
|
const [estimateEditType, setEstimateEditType] = useState<TEstimateUpdateStageKeys | undefined>(undefined);
|
||||||
const [estimatePoints, setEstimatePoints] = useState<TEstimatePointsObject[] | undefined>(undefined);
|
const [estimatePoints, setEstimatePoints] = useState<TEstimatePointsObject[] | undefined>(undefined);
|
||||||
|
|
||||||
const handleEstimateEditType = (type: TEstimateUpdateStageKeys) => {
|
const handleEstimateEditType = (type: TEstimateUpdateStageKeys) => {
|
||||||
if (currentEstimate?.points && currentEstimate?.points.length > 0) {
|
if (currentEstimate?.points && currentEstimate?.points.length > 0) {
|
||||||
const estimateValidatePoints: TEstimatePointsObject[] = [];
|
let estimateValidatePoints: TEstimatePointsObject[] = [];
|
||||||
currentEstimate?.points.map(
|
currentEstimate?.points.map(
|
||||||
(point) =>
|
(point) =>
|
||||||
point.key && point.value && estimateValidatePoints.push({ id: point.id, key: point.key, value: point.value })
|
point.key && point.value && estimateValidatePoints.push({ id: point.id, key: point.key, value: point.value })
|
||||||
);
|
);
|
||||||
|
estimateValidatePoints = orderBy(estimateValidatePoints, ["key"], ["asc"]);
|
||||||
if (estimateValidatePoints.length > 0) {
|
if (estimateValidatePoints.length > 0) {
|
||||||
setEstimateEditType(type);
|
setEstimateEditType(type);
|
||||||
setEstimatePoints(estimateValidatePoints);
|
setEstimatePoints(estimateValidatePoints);
|
||||||
@ -56,57 +56,6 @@ export const UpdateEstimateModal: FC<TUpdateEstimateModal> = observer((props) =>
|
|||||||
|
|
||||||
// derived values
|
// derived values
|
||||||
const renderEstimateStepsCount = useMemo(() => (estimatePoints ? "2" : "1"), [estimatePoints]);
|
const renderEstimateStepsCount = useMemo(() => (estimatePoints ? "2" : "1"), [estimatePoints]);
|
||||||
const isNewEstimatePointsToCreate =
|
|
||||||
(estimatePoints || []).filter((point) => point.id === undefined).length > 0 ? true : false;
|
|
||||||
|
|
||||||
const handleUpdateEstimate = async () => {
|
|
||||||
try {
|
|
||||||
if (!workspaceSlug || !projectId || !estimateId || currentEstimate?.type === undefined) return;
|
|
||||||
|
|
||||||
const currentEstimatePoints = (estimatePoints || []).filter((point) => point.id === undefined);
|
|
||||||
const currentEstimationType: TEstimateSystemKeys = currentEstimate?.type;
|
|
||||||
const validatedEstimatePoints: TEstimatePointsObject[] = [];
|
|
||||||
|
|
||||||
if ([EEstimateSystem.POINTS, EEstimateSystem.TIME].includes(currentEstimationType)) {
|
|
||||||
currentEstimatePoints?.map((estimatePoint) => {
|
|
||||||
if (
|
|
||||||
estimatePoint.value &&
|
|
||||||
((estimatePoint.value != "0" && Number(estimatePoint.value)) || estimatePoint.value === "0")
|
|
||||||
)
|
|
||||||
validatedEstimatePoints.push(estimatePoint);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
currentEstimatePoints?.map((estimatePoint) => {
|
|
||||||
if (estimatePoint.value) validatedEstimatePoints.push(estimatePoint);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validatedEstimatePoints.length === currentEstimatePoints?.length) {
|
|
||||||
const payload: IEstimateFormData = {
|
|
||||||
estimate_points: validatedEstimatePoints,
|
|
||||||
};
|
|
||||||
await updateEstimate(payload);
|
|
||||||
setToast({
|
|
||||||
type: TOAST_TYPE.SUCCESS,
|
|
||||||
title: "Estimate system created",
|
|
||||||
message: "Created and Enabled successfully",
|
|
||||||
});
|
|
||||||
handleClose();
|
|
||||||
} else {
|
|
||||||
setToast({
|
|
||||||
type: TOAST_TYPE.ERROR,
|
|
||||||
title: "Error!",
|
|
||||||
message: "something went wrong",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
setToast({
|
|
||||||
type: TOAST_TYPE.ERROR,
|
|
||||||
title: "Error!",
|
|
||||||
message: "something went wrong",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalCore isOpen={isOpen} handleClose={handleClose} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
<ModalCore isOpen={isOpen} handleClose={handleClose} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
||||||
@ -135,6 +84,8 @@ export const UpdateEstimateModal: FC<TUpdateEstimateModal> = observer((props) =>
|
|||||||
{!estimateEditType && <EstimateUpdateStageOne handleEstimateEditType={handleEstimateEditType} />}
|
{!estimateEditType && <EstimateUpdateStageOne handleEstimateEditType={handleEstimateEditType} />}
|
||||||
{estimateEditType && estimatePoints && (
|
{estimateEditType && estimatePoints && (
|
||||||
<EstimateUpdateStageTwo
|
<EstimateUpdateStageTwo
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
estimate={currentEstimate}
|
estimate={currentEstimate}
|
||||||
estimateEditType={estimateEditType}
|
estimateEditType={estimateEditType}
|
||||||
estimatePoints={estimatePoints}
|
estimatePoints={estimatePoints}
|
||||||
@ -147,11 +98,6 @@ export const UpdateEstimateModal: FC<TUpdateEstimateModal> = observer((props) =>
|
|||||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
{isNewEstimatePointsToCreate && (
|
|
||||||
<Button variant="primary" size="sm" onClick={handleUpdateEstimate}>
|
|
||||||
Update Estimate
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalCore>
|
</ModalCore>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
|
import cloneDeep from "lodash/cloneDeep";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Plus } from "lucide-react";
|
import { Plus } from "lucide-react";
|
||||||
import { IEstimate, TEstimatePointsObject, TEstimateUpdateStageKeys } from "@plane/types";
|
import { IEstimate, TEstimatePointsObject, TEstimateUpdateStageKeys } from "@plane/types";
|
||||||
@ -9,6 +10,8 @@ import { EstimatePointItem } from "@/components/estimates";
|
|||||||
import { EEstimateUpdateStages, maxEstimatesCount } from "@/constants/estimates";
|
import { EEstimateUpdateStages, maxEstimatesCount } from "@/constants/estimates";
|
||||||
|
|
||||||
type TEstimateUpdateStageTwo = {
|
type TEstimateUpdateStageTwo = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
estimate: IEstimate;
|
estimate: IEstimate;
|
||||||
estimateEditType: TEstimateUpdateStageKeys | undefined;
|
estimateEditType: TEstimateUpdateStageKeys | undefined;
|
||||||
estimatePoints: TEstimatePointsObject[];
|
estimatePoints: TEstimatePointsObject[];
|
||||||
@ -16,15 +19,15 @@ type TEstimateUpdateStageTwo = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const EstimateUpdateStageTwo: FC<TEstimateUpdateStageTwo> = observer((props) => {
|
export const EstimateUpdateStageTwo: FC<TEstimateUpdateStageTwo> = observer((props) => {
|
||||||
const { estimate, estimateEditType, estimatePoints, handleEstimatePoints } = props;
|
const { workspaceSlug, projectId, estimate, estimateEditType, estimatePoints, handleEstimatePoints } = props;
|
||||||
|
|
||||||
const currentEstimateSystem = estimate || undefined;
|
const currentEstimateSystem = estimate || undefined;
|
||||||
|
|
||||||
const addNewEstimationPoint = () => {
|
const addNewEstimationPoint = () => {
|
||||||
const currentEstimationPoints = estimatePoints;
|
const currentEstimationPoints = cloneDeep(estimatePoints);
|
||||||
const newEstimationPoint: TEstimatePointsObject = {
|
const newEstimationPoint: TEstimatePointsObject = {
|
||||||
key: currentEstimationPoints.length + 1,
|
key: currentEstimationPoints.length + 1,
|
||||||
value: "0",
|
value: "",
|
||||||
};
|
};
|
||||||
handleEstimatePoints([...currentEstimationPoints, newEstimationPoint]);
|
handleEstimatePoints([...currentEstimationPoints, newEstimationPoint]);
|
||||||
};
|
};
|
||||||
@ -64,11 +67,15 @@ export const EstimateUpdateStageTwo: FC<TEstimateUpdateStageTwo> = observer((pro
|
|||||||
data={estimatePoints}
|
data={estimatePoints}
|
||||||
render={(value: TEstimatePointsObject, index: number) => (
|
render={(value: TEstimatePointsObject, index: number) => (
|
||||||
<EstimatePointItem
|
<EstimatePointItem
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
estimateId={estimate?.id || undefined}
|
estimateId={estimate?.id || undefined}
|
||||||
mode={estimateEditType}
|
mode={estimateEditType}
|
||||||
item={value}
|
item={value}
|
||||||
|
estimatePoints={estimatePoints}
|
||||||
editItem={(value: string) => editEstimationPoint(index, value)}
|
editItem={(value: string) => editEstimationPoint(index, value)}
|
||||||
deleteItem={() => deleteEstimationPoint(index)}
|
deleteItem={() => deleteEstimationPoint(index)}
|
||||||
|
handleEstimatePoints={handleEstimatePoints}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
onChange={(data: TEstimatePointsObject[]) => handleEstimatePoints(updatedSortedKeys(data))}
|
onChange={(data: TEstimatePointsObject[]) => handleEstimatePoints(updatedSortedKeys(data))}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// types
|
// types
|
||||||
import { IEstimate, IEstimateFormData } from "@plane/types";
|
import { IEstimate, IEstimateFormData, IEstimatePoint } from "@plane/types";
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "@/helpers/common.helper";
|
import { API_BASE_URL } from "@/helpers/common.helper";
|
||||||
// services
|
// services
|
||||||
@ -10,7 +10,6 @@ export class EstimateService extends APIService {
|
|||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetching the estimates in workspace level
|
|
||||||
async fetchWorkspaceEstimates(workspaceSlug: string): Promise<IEstimate[] | undefined> {
|
async fetchWorkspaceEstimates(workspaceSlug: string): Promise<IEstimate[] | undefined> {
|
||||||
try {
|
try {
|
||||||
const { data } = await this.get(`/api/workspaces/${workspaceSlug}/estimates/`);
|
const { data } = await this.get(`/api/workspaces/${workspaceSlug}/estimates/`);
|
||||||
@ -61,7 +60,7 @@ export class EstimateService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
estimateId: string,
|
estimateId: string,
|
||||||
payload: IEstimateFormData
|
payload: Partial<IEstimate>
|
||||||
): Promise<IEstimate | undefined> {
|
): Promise<IEstimate | undefined> {
|
||||||
try {
|
try {
|
||||||
const { data } = await this.patch(
|
const { data } = await this.patch(
|
||||||
@ -74,16 +73,51 @@ export class EstimateService extends APIService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createEstimatePoint(
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
estimateId: string,
|
||||||
|
payload: Partial<IEstimatePoint>
|
||||||
|
): Promise<IEstimatePoint | undefined> {
|
||||||
|
try {
|
||||||
|
const { data } = await this.post(
|
||||||
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/estimate-points/`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
return data || undefined;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateEstimatePoint(
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
estimateId: string,
|
||||||
|
estimatePointId: string,
|
||||||
|
payload: Partial<IEstimatePoint>
|
||||||
|
): Promise<IEstimatePoint | undefined> {
|
||||||
|
try {
|
||||||
|
const { data } = await this.post(
|
||||||
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/estimate-points/${estimatePointId}/`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
return data || undefined;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async removeEstimatePoint(
|
async removeEstimatePoint(
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
estimateId: string,
|
estimateId: string,
|
||||||
estimatePointId: string,
|
estimatePointId: string,
|
||||||
payload: { new_estimate_id: string | undefined }
|
params?: { new_estimate_id: string | undefined }
|
||||||
): Promise<any> {
|
): Promise<void> {
|
||||||
return this.patch(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/estimate-point/${estimatePointId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/estimate-points/${estimatePointId}/`,
|
||||||
payload
|
params
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { action, computed, makeObservable, observable } from "mobx";
|
import set from "lodash/set";
|
||||||
import { IEstimateFormData, IEstimate, IEstimatePoint as IEstimatePointType } from "@plane/types";
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||||
|
import { IEstimate, IEstimatePoint as IEstimatePointType } from "@plane/types";
|
||||||
// services
|
// services
|
||||||
import { EstimateService } from "@/services/project/estimate.service";
|
import { EstimateService } from "@/services/project/estimate.service";
|
||||||
// store
|
// store
|
||||||
@ -16,7 +17,11 @@ export interface IEstimatePoint extends IEstimatePointType {
|
|||||||
// computed
|
// computed
|
||||||
asJson: IEstimatePointType;
|
asJson: IEstimatePointType;
|
||||||
// actions
|
// actions
|
||||||
updateEstimatePoint: (payload: IEstimateFormData) => Promise<void>;
|
updateEstimatePoint: (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
payload: Partial<IEstimatePointType>
|
||||||
|
) => Promise<IEstimatePointType | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EstimatePoint implements IEstimatePoint {
|
export class EstimatePoint implements IEstimatePoint {
|
||||||
@ -73,7 +78,6 @@ export class EstimatePoint implements IEstimatePoint {
|
|||||||
this.updated_at = this.data.updated_at;
|
this.updated_at = this.data.updated_at;
|
||||||
this.created_by = this.data.created_by;
|
this.created_by = this.data.created_by;
|
||||||
this.updated_by = this.data.updated_by;
|
this.updated_by = this.data.updated_by;
|
||||||
|
|
||||||
// service
|
// service
|
||||||
this.service = new EstimateService();
|
this.service = new EstimateService();
|
||||||
}
|
}
|
||||||
@ -96,10 +100,36 @@ export class EstimatePoint implements IEstimatePoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
updateEstimatePoint = async (payload: IEstimateFormData) => {
|
/**
|
||||||
|
* @description updating an estimate point
|
||||||
|
* @param { Partial<IEstimatePointType> } payload
|
||||||
|
* @returns { IEstimatePointType | undefined }
|
||||||
|
*/
|
||||||
|
updateEstimatePoint = async (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
payload: Partial<IEstimatePointType>
|
||||||
|
): Promise<IEstimatePointType | undefined> => {
|
||||||
try {
|
try {
|
||||||
const { workspaceSlug, projectId } = this.store.router;
|
if (!this.projectEstimate?.id || !this.id || !payload) return undefined;
|
||||||
if (!workspaceSlug || !projectId || !this.projectEstimate?.id || !this.id || !payload) return undefined;
|
|
||||||
|
const estimatePoint = await this.service.updateEstimatePoint(
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
this.projectEstimate?.id,
|
||||||
|
this.id,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
if (estimatePoint) {
|
||||||
|
runInAction(() => {
|
||||||
|
Object.keys(payload).map((key) => {
|
||||||
|
const estimatePointKey = key as keyof IEstimatePointType;
|
||||||
|
set(this, estimatePointKey, estimatePoint[estimatePointKey]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return estimatePoint;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
import set from "lodash/set";
|
import set from "lodash/set";
|
||||||
import unset from "lodash/unset";
|
import unset from "lodash/unset";
|
||||||
import update from "lodash/update";
|
|
||||||
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||||
import { computedFn } from "mobx-utils";
|
import { computedFn } from "mobx-utils";
|
||||||
import {
|
import { IEstimate as IEstimateType, IEstimatePoint as IEstimatePointType, TEstimateSystemKeys } from "@plane/types";
|
||||||
IEstimate as IEstimateType,
|
|
||||||
IEstimatePoint as IEstimatePointType,
|
|
||||||
IProject,
|
|
||||||
IWorkspace,
|
|
||||||
TEstimateSystemKeys,
|
|
||||||
IEstimateFormData,
|
|
||||||
} from "@plane/types";
|
|
||||||
// services
|
// services
|
||||||
import { EstimateService } from "@/services/project/estimate.service";
|
import { EstimateService } from "@/services/project/estimate.service";
|
||||||
// store
|
// store
|
||||||
@ -31,8 +23,22 @@ export interface IEstimate extends IEstimateType {
|
|||||||
estimatePointIds: string[] | undefined;
|
estimatePointIds: string[] | undefined;
|
||||||
estimatePointById: (estimateId: string) => IEstimatePointType | undefined;
|
estimatePointById: (estimateId: string) => IEstimatePointType | undefined;
|
||||||
// actions
|
// actions
|
||||||
updateEstimate: (payload: IEstimateFormData) => Promise<void>;
|
updateEstimate: (
|
||||||
deleteEstimate: (estimatePointId: string | undefined) => Promise<void>;
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
payload: Partial<IEstimateType>
|
||||||
|
) => Promise<IEstimateType | undefined>;
|
||||||
|
creteEstimatePoint: (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
payload: Partial<IEstimatePointType>
|
||||||
|
) => Promise<IEstimatePointType | undefined>;
|
||||||
|
deleteEstimatePoint: (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
estimatePointId: string,
|
||||||
|
newEstimatePointId: string | undefined
|
||||||
|
) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Estimate implements IEstimate {
|
export class Estimate implements IEstimate {
|
||||||
@ -43,9 +49,8 @@ export class Estimate implements IEstimate {
|
|||||||
type: TEstimateSystemKeys | undefined = undefined;
|
type: TEstimateSystemKeys | undefined = undefined;
|
||||||
points: IEstimatePointType[] | undefined = undefined;
|
points: IEstimatePointType[] | undefined = undefined;
|
||||||
workspace: string | undefined = undefined;
|
workspace: string | undefined = undefined;
|
||||||
workspace_detail: IWorkspace | undefined = undefined;
|
|
||||||
project: string | undefined = undefined;
|
project: string | undefined = undefined;
|
||||||
project_detail: IProject | undefined = undefined;
|
last_used: boolean | undefined = undefined;
|
||||||
created_at: Date | undefined = undefined;
|
created_at: Date | undefined = undefined;
|
||||||
updated_at: Date | undefined = undefined;
|
updated_at: Date | undefined = undefined;
|
||||||
created_by: string | undefined = undefined;
|
created_by: string | undefined = undefined;
|
||||||
@ -68,9 +73,8 @@ export class Estimate implements IEstimate {
|
|||||||
type: observable.ref,
|
type: observable.ref,
|
||||||
points: observable,
|
points: observable,
|
||||||
workspace: observable.ref,
|
workspace: observable.ref,
|
||||||
workspace_detail: observable,
|
|
||||||
project: observable.ref,
|
project: observable.ref,
|
||||||
project_detail: observable,
|
last_used: observable.ref,
|
||||||
created_at: observable.ref,
|
created_at: observable.ref,
|
||||||
updated_at: observable.ref,
|
updated_at: observable.ref,
|
||||||
created_by: observable.ref,
|
created_by: observable.ref,
|
||||||
@ -83,7 +87,8 @@ export class Estimate implements IEstimate {
|
|||||||
estimatePointIds: computed,
|
estimatePointIds: computed,
|
||||||
// actions
|
// actions
|
||||||
updateEstimate: action,
|
updateEstimate: action,
|
||||||
deleteEstimate: action,
|
creteEstimatePoint: action,
|
||||||
|
deleteEstimatePoint: action,
|
||||||
});
|
});
|
||||||
this.id = this.data.id;
|
this.id = this.data.id;
|
||||||
this.name = this.data.name;
|
this.name = this.data.name;
|
||||||
@ -91,14 +96,12 @@ export class Estimate implements IEstimate {
|
|||||||
this.type = this.data.type;
|
this.type = this.data.type;
|
||||||
this.points = this.data.points;
|
this.points = this.data.points;
|
||||||
this.workspace = this.data.workspace;
|
this.workspace = this.data.workspace;
|
||||||
this.workspace_detail = this.data.workspace_detail;
|
|
||||||
this.project = this.data.project;
|
this.project = this.data.project;
|
||||||
this.project_detail = this.data.project_detail;
|
this.last_used = this.data.last_used;
|
||||||
this.created_at = this.data.created_at;
|
this.created_at = this.data.created_at;
|
||||||
this.updated_at = this.data.updated_at;
|
this.updated_at = this.data.updated_at;
|
||||||
this.created_by = this.data.created_by;
|
this.created_by = this.data.created_by;
|
||||||
this.updated_by = this.data.updated_by;
|
this.updated_by = this.data.updated_by;
|
||||||
|
|
||||||
this.data.points?.forEach((estimationPoint) => {
|
this.data.points?.forEach((estimationPoint) => {
|
||||||
if (estimationPoint.id)
|
if (estimationPoint.id)
|
||||||
set(this.estimatePoints, [estimationPoint.id], new EstimatePoint(this.store, this.data, estimationPoint));
|
set(this.estimatePoints, [estimationPoint.id], new EstimatePoint(this.store, this.data, estimationPoint));
|
||||||
@ -116,9 +119,8 @@ export class Estimate implements IEstimate {
|
|||||||
type: this.type,
|
type: this.type,
|
||||||
points: this.points,
|
points: this.points,
|
||||||
workspace: this.workspace,
|
workspace: this.workspace,
|
||||||
workspace_detail: this.workspace_detail,
|
|
||||||
project: this.project,
|
project: this.project,
|
||||||
project_detail: this.project_detail,
|
last_used: this.last_used,
|
||||||
created_at: this.created_at,
|
created_at: this.created_at,
|
||||||
updated_at: this.updated_at,
|
updated_at: this.updated_at,
|
||||||
created_by: this.created_by,
|
created_by: this.created_by,
|
||||||
@ -143,35 +145,95 @@ export class Estimate implements IEstimate {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
updateEstimate = async (payload: IEstimateFormData) => {
|
/**
|
||||||
|
* @description update an estimate
|
||||||
|
* @param { string } workspaceSlug
|
||||||
|
* @param { string } projectId
|
||||||
|
* @param { Partial<IEstimateType> } payload
|
||||||
|
* @returns { IEstimateType | undefined }
|
||||||
|
*/
|
||||||
|
updateEstimate = async (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
payload: Partial<IEstimateType>
|
||||||
|
): Promise<IEstimateType | undefined> => {
|
||||||
try {
|
try {
|
||||||
const { workspaceSlug, projectId } = this.store.router;
|
if (!this.id || !payload) return;
|
||||||
if (!workspaceSlug || !projectId || !this.id || !payload) return;
|
|
||||||
|
|
||||||
await this.service.updateEstimate(workspaceSlug, projectId, this.id, payload);
|
const estimate = await this.service.updateEstimate(workspaceSlug, projectId, this.id, payload);
|
||||||
|
if (estimate) {
|
||||||
|
runInAction(() => {
|
||||||
|
Object.keys(payload).map((key) => {
|
||||||
|
const estimateKey = key as keyof IEstimateType;
|
||||||
|
set(this, estimateKey, estimate[estimateKey]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// runInAction(() => {
|
return estimate;
|
||||||
// this.points = payload.estimate_points;
|
|
||||||
// this.data.points = payload.estimate_points;
|
|
||||||
// });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
deleteEstimate = async (estimatePointId: string | undefined) => {
|
/**
|
||||||
|
* @description create an estimate point
|
||||||
|
* @param { string } workspaceSlug
|
||||||
|
* @param { string } projectId
|
||||||
|
* @param { Partial<IEstimatePointType> } payload
|
||||||
|
* @returns { IEstimatePointType | undefined }
|
||||||
|
*/
|
||||||
|
creteEstimatePoint = async (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
payload: Partial<IEstimatePointType>
|
||||||
|
): Promise<IEstimatePointType | undefined> => {
|
||||||
try {
|
try {
|
||||||
const { workspaceSlug, projectId } = this.store.router;
|
if (!this.id || !payload) return;
|
||||||
if (!workspaceSlug || !projectId || !estimatePointId) return;
|
|
||||||
|
|
||||||
// make delete estimation request
|
const estimatePoint = await this.service.createEstimatePoint(workspaceSlug, projectId, this.id, payload);
|
||||||
|
if (estimatePoint) {
|
||||||
|
runInAction(() => {
|
||||||
|
if (estimatePoint.id) {
|
||||||
|
set(this.estimatePoints, [estimatePoint.id], new EstimatePoint(this.store, this.data, estimatePoint));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description delete an estimate point
|
||||||
|
* @param { string } workspaceSlug
|
||||||
|
* @param { string } projectId
|
||||||
|
* @param { string } estimatePointId
|
||||||
|
* @param { string | undefined } newEstimatePointId
|
||||||
|
* @returns { void }
|
||||||
|
*/
|
||||||
|
deleteEstimatePoint = async (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
estimatePointId: string,
|
||||||
|
newEstimatePointId: string | undefined
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
if (!this.id) return;
|
||||||
|
|
||||||
|
const deleteEstimatePoint = await this.service.removeEstimatePoint(
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
this.id,
|
||||||
|
estimatePointId,
|
||||||
|
newEstimatePointId ? { new_estimate_id: newEstimatePointId } : undefined
|
||||||
|
);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
update(this, "points", (estimationPoints = []) =>
|
|
||||||
estimationPoints.filter((point: IEstimatePointType) => point.id !== estimatePointId)
|
|
||||||
);
|
|
||||||
unset(this.estimatePoints, [estimatePointId]);
|
unset(this.estimatePoints, [estimatePointId]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return deleteEstimatePoint;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import orderBy from "lodash/orderBy";
|
||||||
import set from "lodash/set";
|
import set from "lodash/set";
|
||||||
import sortBy from "lodash/sortBy";
|
|
||||||
import update from "lodash/update";
|
import update from "lodash/update";
|
||||||
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||||
import { computedFn } from "mobx-utils";
|
import { computedFn } from "mobx-utils";
|
||||||
@ -59,7 +59,6 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
// computed
|
// computed
|
||||||
currentActiveEstimateId: computed,
|
currentActiveEstimateId: computed,
|
||||||
archivedEstimateIds: computed,
|
archivedEstimateIds: computed,
|
||||||
projectEstimateIds: computed,
|
|
||||||
// actions
|
// actions
|
||||||
getWorkspaceEstimates: action,
|
getWorkspaceEstimates: action,
|
||||||
getProjectEstimates: action,
|
getProjectEstimates: action,
|
||||||
@ -79,9 +78,10 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
get currentActiveEstimateId(): string | undefined {
|
get currentActiveEstimateId(): string | undefined {
|
||||||
const { projectId } = this.store.router;
|
const { projectId } = this.store.router;
|
||||||
if (!projectId) return undefined;
|
if (!projectId) return undefined;
|
||||||
const projectDetails = this.store.projectRoot.project.getProjectById(projectId);
|
const currentActiveEstimateId = Object.values(this.estimates || {}).find(
|
||||||
if (!projectDetails) return undefined;
|
(p) => p.project === projectId && p.last_used
|
||||||
return projectDetails.estimate ?? undefined;
|
);
|
||||||
|
return currentActiveEstimateId?.id ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,25 +91,15 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
get archivedEstimateIds(): string[] | undefined {
|
get archivedEstimateIds(): string[] | undefined {
|
||||||
const { projectId } = this.store.router;
|
const { projectId } = this.store.router;
|
||||||
if (!projectId) return undefined;
|
if (!projectId) return undefined;
|
||||||
const archivedEstimateIds = Object.values(this.estimates || {})
|
const archivedEstimates = orderBy(
|
||||||
.filter((p) => p.project === projectId && p.id !== this.currentActiveEstimateId)
|
Object.values(this.estimates || {}).filter((p) => p.project === projectId && !p.last_used),
|
||||||
.map((p) => p.id) as string[];
|
["created_at"],
|
||||||
|
"desc"
|
||||||
|
);
|
||||||
|
const archivedEstimateIds = archivedEstimates.map((p) => p.id) as string[];
|
||||||
return archivedEstimateIds ?? undefined;
|
return archivedEstimateIds ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description get all estimate ids for a project
|
|
||||||
* @returns { string[] | undefined }
|
|
||||||
*/
|
|
||||||
get projectEstimateIds(): string[] | undefined {
|
|
||||||
const { projectId } = this.store.router;
|
|
||||||
if (!projectId) return undefined;
|
|
||||||
const projectEstimatesIds = Object.values(this.estimates || {})
|
|
||||||
.filter((p) => p.project === projectId)
|
|
||||||
.map((p) => p.id) as string[];
|
|
||||||
return projectEstimatesIds ?? undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description get estimates are enabled in the project or not
|
* @description get estimates are enabled in the project or not
|
||||||
* @returns { boolean }
|
* @returns { boolean }
|
||||||
@ -145,6 +135,7 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
// actions
|
// actions
|
||||||
/**
|
/**
|
||||||
* @description fetch all estimates for a workspace
|
* @description fetch all estimates for a workspace
|
||||||
|
* @param { string } workspaceSlug
|
||||||
* @returns { IEstimateType[] | undefined }
|
* @returns { IEstimateType[] | undefined }
|
||||||
*/
|
*/
|
||||||
getWorkspaceEstimates = async (
|
getWorkspaceEstimates = async (
|
||||||
@ -153,7 +144,7 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
): Promise<IEstimateType[] | undefined> => {
|
): Promise<IEstimateType[] | undefined> => {
|
||||||
try {
|
try {
|
||||||
this.error = undefined;
|
this.error = undefined;
|
||||||
if (!this.projectEstimateIds) this.loader = loader ? loader : "init-loader";
|
if (Object.keys(this.estimates || {}).length <= 0) this.loader = loader ? loader : "init-loader";
|
||||||
|
|
||||||
const estimates = await this.service.fetchWorkspaceEstimates(workspaceSlug);
|
const estimates = await this.service.fetchWorkspaceEstimates(workspaceSlug);
|
||||||
if (estimates && estimates.length > 0) {
|
if (estimates && estimates.length > 0) {
|
||||||
@ -176,6 +167,8 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description fetch all estimates for a project
|
* @description fetch all estimates for a project
|
||||||
|
* @param { string } workspaceSlug
|
||||||
|
* @param { string } projectId
|
||||||
* @returns { IEstimateType[] | undefined }
|
* @returns { IEstimateType[] | undefined }
|
||||||
*/
|
*/
|
||||||
getProjectEstimates = async (
|
getProjectEstimates = async (
|
||||||
@ -185,7 +178,7 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
): Promise<IEstimateType[] | undefined> => {
|
): Promise<IEstimateType[] | undefined> => {
|
||||||
try {
|
try {
|
||||||
this.error = undefined;
|
this.error = undefined;
|
||||||
if (!this.projectEstimateIds) this.loader = loader ? loader : "init-loader";
|
if (!this.estimateIdsByProjectId(projectId)) this.loader = loader ? loader : "init-loader";
|
||||||
|
|
||||||
const estimates = await this.service.fetchProjectEstimates(workspaceSlug, projectId);
|
const estimates = await this.service.fetchProjectEstimates(workspaceSlug, projectId);
|
||||||
if (estimates && estimates.length > 0) {
|
if (estimates && estimates.length > 0) {
|
||||||
@ -208,6 +201,8 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description update an estimate for a project
|
* @description update an estimate for a project
|
||||||
|
* @param { string } workspaceSlug
|
||||||
|
* @param { string } projectId
|
||||||
* @param { string } estimateId
|
* @param { string } estimateId
|
||||||
* @returns IEstimateType | undefined
|
* @returns IEstimateType | undefined
|
||||||
*/
|
*/
|
||||||
@ -241,7 +236,9 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description create an estimate for a project
|
* @description create an estimate for a project
|
||||||
* @param { Partial<IEstimateType> } payload
|
* @param { string } workspaceSlug
|
||||||
|
* @param { string } projectId
|
||||||
|
* @param { Partial<IEstimateFormData> } payload
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
createEstimate = async (
|
createEstimate = async (
|
||||||
@ -253,21 +250,15 @@ export class ProjectEstimateStore implements IProjectEstimateStore {
|
|||||||
this.error = undefined;
|
this.error = undefined;
|
||||||
|
|
||||||
const estimate = await this.service.createEstimate(workspaceSlug, projectId, payload);
|
const estimate = await this.service.createEstimate(workspaceSlug, projectId, payload);
|
||||||
// FIXME: i am getting different response from the server and once backend changes remove the get request and uncomment the commented code
|
console.log("estimate", estimate);
|
||||||
let estimates = await this.getProjectEstimates(workspaceSlug, projectId, "mutation-loader");
|
if (estimate) {
|
||||||
estimates = sortBy(estimates, "created_at");
|
|
||||||
if (estimates && estimates.length > 0)
|
|
||||||
await this.store.projectRoot.project.updateProject(workspaceSlug, projectId, {
|
await this.store.projectRoot.project.updateProject(workspaceSlug, projectId, {
|
||||||
estimate: estimates[estimates.length - 1].id,
|
estimate: estimate.id,
|
||||||
});
|
});
|
||||||
// if (estimate) {
|
runInAction(() => {
|
||||||
// await this.store.projectRoot.project.updateProject(workspaceSlug, projectId, {
|
if (estimate.id) set(this.estimates, [estimate.id], new Estimate(this.store, estimate));
|
||||||
// estimate: estimate.id,
|
});
|
||||||
// });
|
}
|
||||||
// runInAction(() => {
|
|
||||||
// if (estimate.id) set(this.estimates, [estimate.id], new Estimate(this.store, estimate));
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
return estimate;
|
return estimate;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user