mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
Merge pull request #1902 from makeplane/sync/ce-ee
Sync: Community Changes
This commit is contained in:
2
packages/types/src/issues.d.ts
vendored
2
packages/types/src/issues.d.ts
vendored
@@ -216,7 +216,7 @@ export type GroupByColumnTypes =
|
||||
export interface IGroupByColumn {
|
||||
id: string;
|
||||
name: string;
|
||||
icon: ReactElement | undefined;
|
||||
icon?: ReactElement | undefined;
|
||||
payload: Partial<TIssue>;
|
||||
isDropDisabled?: boolean;
|
||||
dropErrorMessage?: string;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ContentWrapper } from "@plane/ui";
|
||||
import RenderIfVisible from "@/components/core/render-if-visible-HOC";
|
||||
import { KanbanColumnLoader } from "@/components/ui";
|
||||
// hooks
|
||||
import { useCycle, useKanbanView, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
|
||||
import { useKanbanView } from "@/hooks/store";
|
||||
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
||||
// types
|
||||
// parent components
|
||||
@@ -87,30 +87,16 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
dropErrorMessage,
|
||||
subGroupIndex = 0,
|
||||
} = props;
|
||||
|
||||
// store hooks
|
||||
const storeType = useIssueStoreType();
|
||||
|
||||
const member = useMember();
|
||||
const project = useProject();
|
||||
const label = useLabel();
|
||||
const cycle = useCycle();
|
||||
const moduleInfo = useModule();
|
||||
const projectState = useProjectState();
|
||||
const issueKanBanView = useKanbanView();
|
||||
|
||||
// derived values
|
||||
const isDragDisabled = !issueKanBanView?.getCanUserDragDrop(group_by, sub_group_by);
|
||||
|
||||
const list = getGroupByColumns(
|
||||
group_by as GroupByColumnTypes,
|
||||
project,
|
||||
cycle,
|
||||
moduleInfo,
|
||||
label,
|
||||
projectState,
|
||||
member,
|
||||
true,
|
||||
isWorkspaceLevel(storeType)
|
||||
);
|
||||
const list = getGroupByColumns({
|
||||
groupBy: group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
});
|
||||
|
||||
if (!list) return null;
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
// UI
|
||||
import { Row } from "@plane/ui";
|
||||
// hooks
|
||||
import { useCycle, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
|
||||
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
||||
// components
|
||||
import { TRenderQuickActions } from "../list/list-view-types";
|
||||
@@ -262,38 +261,19 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
quickAddCallback,
|
||||
scrollableContainerRef,
|
||||
} = props;
|
||||
|
||||
// store hooks
|
||||
const storeType = useIssueStoreType();
|
||||
|
||||
const member = useMember();
|
||||
const project = useProject();
|
||||
const label = useLabel();
|
||||
const cycle = useCycle();
|
||||
const projectModule = useModule();
|
||||
const projectState = useProjectState();
|
||||
|
||||
const groupByList = getGroupByColumns(
|
||||
group_by as GroupByColumnTypes,
|
||||
project,
|
||||
cycle,
|
||||
projectModule,
|
||||
label,
|
||||
projectState,
|
||||
member,
|
||||
true,
|
||||
isWorkspaceLevel(storeType)
|
||||
);
|
||||
const subGroupByList = getGroupByColumns(
|
||||
sub_group_by as GroupByColumnTypes,
|
||||
project,
|
||||
cycle,
|
||||
projectModule,
|
||||
label,
|
||||
projectState,
|
||||
member,
|
||||
true,
|
||||
isWorkspaceLevel(storeType)
|
||||
);
|
||||
// derived values
|
||||
const groupByList = getGroupByColumns({
|
||||
groupBy: group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
});
|
||||
const subGroupByList = getGroupByColumns({
|
||||
groupBy: sub_group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
});
|
||||
|
||||
if (!groupByList || !subGroupByList) return null;
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ import {
|
||||
} from "@plane/types";
|
||||
// components
|
||||
import { MultipleSelectGroup } from "@/components/core";
|
||||
|
||||
// hooks
|
||||
import { useCycle, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
|
||||
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
||||
// plane web components
|
||||
import { IssueBulkOperationsRoot } from "@/plane-web/components/issues";
|
||||
@@ -75,29 +73,16 @@ export const List: React.FC<IList> = observer((props) => {
|
||||
} = props;
|
||||
|
||||
const storeType = useIssueStoreType();
|
||||
// store hooks
|
||||
const member = useMember();
|
||||
const project = useProject();
|
||||
const label = useLabel();
|
||||
const projectState = useProjectState();
|
||||
const cycle = useCycle();
|
||||
const projectModule = useModule();
|
||||
// plane web hooks
|
||||
const isBulkOperationsEnabled = useBulkOperationStatus();
|
||||
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const groups = getGroupByColumns(
|
||||
group_by as GroupByColumnTypes,
|
||||
project,
|
||||
cycle,
|
||||
projectModule,
|
||||
label,
|
||||
projectState,
|
||||
member,
|
||||
true,
|
||||
isWorkspaceLevel(storeType)
|
||||
);
|
||||
const groups = getGroupByColumns({
|
||||
groupBy: group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
});
|
||||
|
||||
// Enable Auto Scroll for Main Kanban
|
||||
useEffect(() => {
|
||||
|
||||
@@ -36,13 +36,8 @@ import { STATE_GROUPS } from "@/constants/state";
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
// store
|
||||
import { ICycleStore } from "@/store/cycle.store";
|
||||
import { store } from "@/lib/store-context";
|
||||
import { ISSUE_FILTER_DEFAULT_DATA } from "@/store/issue/helpers/base-issues.store";
|
||||
import { ILabelStore } from "@/store/label.store";
|
||||
import { IMemberRootStore } from "@/store/member";
|
||||
import { IModuleStore } from "@/store/module.store";
|
||||
import { IProjectStore } from "@/store/project/project.store";
|
||||
import { IStateStore } from "@/store/state.store";
|
||||
|
||||
export const HIGHLIGHT_CLASS = "highlight";
|
||||
export const HIGHLIGHT_WITH_LINE = "highlight-with-line";
|
||||
@@ -65,51 +60,61 @@ export type IssueUpdates = {
|
||||
export const isWorkspaceLevel = (type: EIssuesStoreType) =>
|
||||
[EIssuesStoreType.PROFILE, EIssuesStoreType.GLOBAL].includes(type) ? true : false;
|
||||
|
||||
export const getGroupByColumns = (
|
||||
groupBy: GroupByColumnTypes | null,
|
||||
project: IProjectStore,
|
||||
cycle: ICycleStore,
|
||||
module: IModuleStore,
|
||||
label: ILabelStore,
|
||||
projectState: IStateStore,
|
||||
member: IMemberRootStore,
|
||||
includeNone?: boolean,
|
||||
isWorkspaceLevel?: boolean
|
||||
): IGroupByColumn[] | undefined => {
|
||||
switch (groupBy) {
|
||||
case "project":
|
||||
return getProjectColumns(project);
|
||||
case "cycle":
|
||||
return getCycleColumns(project, cycle);
|
||||
case "module":
|
||||
return getModuleColumns(project, module);
|
||||
case "state":
|
||||
return getStateColumns(projectState);
|
||||
case "state_detail.group":
|
||||
return getStateGroupColumns();
|
||||
case "priority":
|
||||
return getPriorityColumns();
|
||||
case "labels":
|
||||
return getLabelsColumns(label, isWorkspaceLevel) as any;
|
||||
case "assignees":
|
||||
return getAssigneeColumns(member) as any;
|
||||
case "created_by":
|
||||
return getCreatedByColumns(member) as any;
|
||||
default:
|
||||
if (includeNone) return [{ id: `All Issues`, name: `All Issues`, payload: {}, icon: undefined }];
|
||||
}
|
||||
type TGetGroupByColumns = {
|
||||
groupBy: GroupByColumnTypes | null;
|
||||
includeNone: boolean;
|
||||
isWorkspaceLevel: boolean;
|
||||
};
|
||||
|
||||
const getProjectColumns = (project: IProjectStore): IGroupByColumn[] | undefined => {
|
||||
const { workspaceProjectIds: projectIds, projectMap } = project;
|
||||
// NOTE: Type of groupBy is different compared to what's being passed from the components.
|
||||
// We are using `as` to typecast it to the expected type.
|
||||
// It can break the includeNone logic if not handled properly.
|
||||
export const getGroupByColumns = ({
|
||||
groupBy,
|
||||
includeNone,
|
||||
isWorkspaceLevel,
|
||||
}: TGetGroupByColumns): IGroupByColumn[] | undefined => {
|
||||
// If no groupBy is specified and includeNone is true, return "All Issues" group
|
||||
if (!groupBy && includeNone) {
|
||||
return [
|
||||
{
|
||||
id: "All Issues",
|
||||
name: "All Issues",
|
||||
payload: {},
|
||||
icon: undefined,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Return undefined if no valid groupBy
|
||||
if (!groupBy) return undefined;
|
||||
|
||||
// Map of group by options to their corresponding column getter functions
|
||||
const groupByColumnMap: Record<GroupByColumnTypes, () => IGroupByColumn[] | undefined> = {
|
||||
project: getProjectColumns,
|
||||
cycle: getCycleColumns,
|
||||
module: getModuleColumns,
|
||||
state: getStateColumns,
|
||||
"state_detail.group": getStateGroupColumns,
|
||||
priority: getPriorityColumns,
|
||||
labels: () => getLabelsColumns(isWorkspaceLevel),
|
||||
assignees: getAssigneeColumns,
|
||||
created_by: getCreatedByColumns,
|
||||
};
|
||||
|
||||
// Get and return the columns for the specified group by option
|
||||
return groupByColumnMap[groupBy]?.();
|
||||
};
|
||||
|
||||
const getProjectColumns = (): IGroupByColumn[] | undefined => {
|
||||
const { joinedProjectIds: projectIds, projectMap } = store.projectRoot.project;
|
||||
// Return undefined if no project ids
|
||||
if (!projectIds) return;
|
||||
|
||||
// Map project ids to project columns
|
||||
return projectIds
|
||||
.filter((projectId) => !!projectMap[projectId])
|
||||
.map((projectId) => {
|
||||
.map((projectId: string) => {
|
||||
const project = projectMap[projectId];
|
||||
|
||||
if (!project) return;
|
||||
return {
|
||||
id: project.id,
|
||||
name: project.name,
|
||||
@@ -120,78 +125,71 @@ const getProjectColumns = (project: IProjectStore): IGroupByColumn[] | undefined
|
||||
),
|
||||
payload: { project_id: project.id },
|
||||
};
|
||||
}) as any;
|
||||
})
|
||||
.filter((column) => column !== undefined) as IGroupByColumn[];
|
||||
};
|
||||
|
||||
const getCycleColumns = (projectStore: IProjectStore, cycleStore: ICycleStore): IGroupByColumn[] | undefined => {
|
||||
const { currentProjectDetails } = projectStore;
|
||||
const { getProjectCycleIds, getCycleById } = cycleStore;
|
||||
|
||||
const getCycleColumns = (): IGroupByColumn[] | undefined => {
|
||||
const { currentProjectDetails } = store.projectRoot.project;
|
||||
// Check for the current project details
|
||||
if (!currentProjectDetails || !currentProjectDetails?.id) return;
|
||||
|
||||
const cycleIds = currentProjectDetails?.id ? getProjectCycleIds(currentProjectDetails?.id) : undefined;
|
||||
if (!cycleIds) return;
|
||||
|
||||
const cycles = [];
|
||||
|
||||
cycleIds.map((cycleId) => {
|
||||
const cycle = getCycleById(cycleId);
|
||||
if (cycle) {
|
||||
const cycleStatus = cycle.status ? (cycle.status.toLocaleLowerCase() as TCycleGroups) : "draft";
|
||||
const isDropDisabled = cycleStatus === "completed";
|
||||
cycles.push({
|
||||
id: cycle.id,
|
||||
name: cycle.name,
|
||||
icon: <CycleGroupIcon cycleGroup={cycleStatus as TCycleGroups} className="h-3.5 w-3.5" />,
|
||||
payload: { cycle_id: cycle.id },
|
||||
isDropDisabled,
|
||||
dropErrorMessage: isDropDisabled ? "Issue cannot be moved to completed cycles" : undefined,
|
||||
});
|
||||
}
|
||||
const { getProjectCycleDetails } = store.cycle;
|
||||
// Get the cycle details for the current project
|
||||
const cycleDetails = currentProjectDetails?.id ? getProjectCycleDetails(currentProjectDetails?.id) : undefined;
|
||||
// Map the cycle details to the group by columns
|
||||
const cycles: IGroupByColumn[] = [];
|
||||
cycleDetails?.map((cycle) => {
|
||||
const cycleStatus = cycle.status ? (cycle.status.toLocaleLowerCase() as TCycleGroups) : "draft";
|
||||
const isDropDisabled = cycleStatus === "completed";
|
||||
cycles.push({
|
||||
id: cycle.id,
|
||||
name: cycle.name,
|
||||
icon: <CycleGroupIcon cycleGroup={cycleStatus as TCycleGroups} className="h-3.5 w-3.5" />,
|
||||
payload: { cycle_id: cycle.id },
|
||||
isDropDisabled,
|
||||
dropErrorMessage: isDropDisabled ? "Issue cannot be moved to completed cycles" : undefined,
|
||||
});
|
||||
});
|
||||
cycles.push({
|
||||
id: "None",
|
||||
name: "None",
|
||||
icon: <ContrastIcon className="h-3.5 w-3.5" />,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
return cycles as any;
|
||||
return cycles;
|
||||
};
|
||||
|
||||
const getModuleColumns = (projectStore: IProjectStore, moduleStore: IModuleStore): IGroupByColumn[] | undefined => {
|
||||
const { currentProjectDetails } = projectStore;
|
||||
const { getProjectModuleIds, getModuleById } = moduleStore;
|
||||
|
||||
const getModuleColumns = (): IGroupByColumn[] | undefined => {
|
||||
// get current project details
|
||||
const { currentProjectDetails } = store.projectRoot.project;
|
||||
if (!currentProjectDetails || !currentProjectDetails?.id) return;
|
||||
|
||||
const moduleIds = currentProjectDetails?.id ? getProjectModuleIds(currentProjectDetails?.id) : undefined;
|
||||
if (!moduleIds) return;
|
||||
|
||||
const modules = [];
|
||||
|
||||
moduleIds.map((moduleId) => {
|
||||
const moduleInfo = getModuleById(moduleId);
|
||||
if (moduleInfo)
|
||||
modules.push({
|
||||
id: moduleInfo.id,
|
||||
name: moduleInfo.name,
|
||||
icon: <DiceIcon className="h-3.5 w-3.5" />,
|
||||
payload: { module_ids: [moduleInfo.id] },
|
||||
});
|
||||
}) as any;
|
||||
// get project module ids and module details
|
||||
const { getProjectModuleDetails } = store.module;
|
||||
// get module details
|
||||
const moduleDetails = currentProjectDetails?.id ? getProjectModuleDetails(currentProjectDetails?.id) : undefined;
|
||||
// map module details to group by columns
|
||||
const modules: IGroupByColumn[] = [];
|
||||
moduleDetails?.map((module) => {
|
||||
modules.push({
|
||||
id: module.id,
|
||||
name: module.name,
|
||||
icon: <DiceIcon className="h-3.5 w-3.5" />,
|
||||
payload: { module_ids: [module.id] },
|
||||
});
|
||||
});
|
||||
modules.push({
|
||||
id: "None",
|
||||
name: "None",
|
||||
icon: <DiceIcon className="h-3.5 w-3.5" />,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
return modules as any;
|
||||
return modules;
|
||||
};
|
||||
|
||||
const getStateColumns = (projectState: IStateStore): IGroupByColumn[] | undefined => {
|
||||
const { projectStates } = projectState;
|
||||
const getStateColumns = (): IGroupByColumn[] | undefined => {
|
||||
const { projectStates } = store.state;
|
||||
if (!projectStates) return;
|
||||
|
||||
// map project states to group by columns
|
||||
return projectStates.map((state) => ({
|
||||
id: state.id,
|
||||
name: state.name,
|
||||
@@ -201,12 +199,12 @@ const getStateColumns = (projectState: IStateStore): IGroupByColumn[] | undefine
|
||||
</div>
|
||||
),
|
||||
payload: { state_id: state.id },
|
||||
})) as any;
|
||||
}));
|
||||
};
|
||||
|
||||
const getStateGroupColumns = () => {
|
||||
const getStateGroupColumns = (): IGroupByColumn[] => {
|
||||
const stateGroups = STATE_GROUPS;
|
||||
|
||||
// map state groups to group by columns
|
||||
return Object.values(stateGroups).map((stateGroup) => ({
|
||||
id: stateGroup.key,
|
||||
name: stateGroup.label,
|
||||
@@ -219,9 +217,9 @@ const getStateGroupColumns = () => {
|
||||
}));
|
||||
};
|
||||
|
||||
const getPriorityColumns = () => {
|
||||
const getPriorityColumns = (): IGroupByColumn[] => {
|
||||
const priorities = ISSUE_PRIORITIES;
|
||||
|
||||
// map priorities to group by columns
|
||||
return priorities.map((priority) => ({
|
||||
id: priority.key,
|
||||
name: priority.title,
|
||||
@@ -230,14 +228,14 @@ const getPriorityColumns = () => {
|
||||
}));
|
||||
};
|
||||
|
||||
const getLabelsColumns = (label: ILabelStore, isWorkspaceLevel: boolean = false) => {
|
||||
const { workspaceLabels, projectLabels } = label;
|
||||
|
||||
const getLabelsColumns = (isWorkspaceLevel: boolean = false): IGroupByColumn[] => {
|
||||
const { workspaceLabels, projectLabels } = store.label;
|
||||
// map labels to group by columns
|
||||
const labels = [
|
||||
...(isWorkspaceLevel ? workspaceLabels || [] : projectLabels || []),
|
||||
{ id: "None", name: "None", color: "#666" },
|
||||
];
|
||||
|
||||
// map labels to group by columns
|
||||
return labels.map((label) => ({
|
||||
id: label.id,
|
||||
name: label.name,
|
||||
@@ -248,15 +246,14 @@ const getLabelsColumns = (label: ILabelStore, isWorkspaceLevel: boolean = false)
|
||||
}));
|
||||
};
|
||||
|
||||
const getAssigneeColumns = (member: IMemberRootStore) => {
|
||||
const getAssigneeColumns = (): IGroupByColumn[] | undefined => {
|
||||
const {
|
||||
project: { projectMemberIds },
|
||||
getUserDetails,
|
||||
} = member;
|
||||
|
||||
} = store.memberRoot;
|
||||
if (!projectMemberIds) return;
|
||||
|
||||
const assigneeColumns: any = projectMemberIds.map((memberId) => {
|
||||
// Map project member ids to group by assignee columns
|
||||
const assigneeColumns: IGroupByColumn[] = projectMemberIds.map((memberId) => {
|
||||
const member = getUserDetails(memberId);
|
||||
return {
|
||||
id: memberId,
|
||||
@@ -265,20 +262,17 @@ const getAssigneeColumns = (member: IMemberRootStore) => {
|
||||
payload: { assignee_ids: [memberId] },
|
||||
};
|
||||
});
|
||||
|
||||
assigneeColumns.push({ id: "None", name: "None", icon: <Avatar size="md" />, payload: {} });
|
||||
|
||||
return assigneeColumns;
|
||||
};
|
||||
|
||||
const getCreatedByColumns = (member: IMemberRootStore) => {
|
||||
const getCreatedByColumns = (): IGroupByColumn[] | undefined => {
|
||||
const {
|
||||
project: { projectMemberIds },
|
||||
getUserDetails,
|
||||
} = member;
|
||||
|
||||
} = store.memberRoot;
|
||||
if (!projectMemberIds) return;
|
||||
|
||||
// Map project member ids to group by created by columns
|
||||
return projectMemberIds.map((memberId) => {
|
||||
const member = getUserDetails(memberId);
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isFuture, isPast, isToday } from "date-fns";
|
||||
import { isPast, isToday } from "date-fns";
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
import set from "lodash/set";
|
||||
import sortBy from "lodash/sortBy";
|
||||
@@ -7,16 +7,14 @@ import { computedFn } from "mobx-utils";
|
||||
// types
|
||||
import {
|
||||
ICycle,
|
||||
CycleDateCheckData,
|
||||
TCyclePlotType,
|
||||
TProgressSnapshot,
|
||||
TCycleEstimateDistribution,
|
||||
TCycleDistribution,
|
||||
TCycleEstimateType,
|
||||
TCycleProgress,
|
||||
} from "@plane/types";
|
||||
// helpers
|
||||
import { orderCycles, shouldFilterCycle, formatActiveCycle } from "@/helpers/cycle.helper";
|
||||
import { orderCycles, shouldFilterCycle } from "@/helpers/cycle.helper";
|
||||
import { getDate } from "@/helpers/date-time.helper";
|
||||
import { DistributionUpdates, updateDistribution } from "@/helpers/distribution-update.helper";
|
||||
// services
|
||||
@@ -42,21 +40,18 @@ export interface ICycleStore {
|
||||
// computed
|
||||
currentProjectCycleIds: string[] | null;
|
||||
currentProjectCompletedCycleIds: string[] | null;
|
||||
currentProjectUpcomingCycleIds: string[] | null;
|
||||
currentProjectIncompleteCycleIds: string[] | null;
|
||||
currentProjectDraftCycleIds: string[] | null;
|
||||
currentProjectActiveCycleId: string | null;
|
||||
currentProjectArchivedCycleIds: string[] | null;
|
||||
currentProjectActiveCycle: ICycle | null;
|
||||
|
||||
// computed actions
|
||||
getActiveCycleProgress: (cycleId?: string) => { cycle: ICycle; isBurnDown: boolean; isTypeIssue: boolean } | null;
|
||||
getFilteredCycleIds: (projectId: string, sortByManual: boolean) => string[] | null;
|
||||
getFilteredCompletedCycleIds: (projectId: string) => string[] | null;
|
||||
getFilteredArchivedCycleIds: (projectId: string) => string[] | null;
|
||||
getCycleById: (cycleId: string) => ICycle | null;
|
||||
getCycleNameById: (cycleId: string) => string | undefined;
|
||||
getActiveCycleById: (cycleId: string) => ICycle | null;
|
||||
getProjectCycleDetails: (projectId: string) => ICycle[] | null;
|
||||
getProjectCycleIds: (projectId: string) => string[] | null;
|
||||
getPlotTypeByCycleId: (cycleId: string) => TCyclePlotType;
|
||||
getEstimateTypeByCycleId: (cycleId: string) => TCycleEstimateType;
|
||||
@@ -64,7 +59,6 @@ export interface ICycleStore {
|
||||
|
||||
// actions
|
||||
updateCycleDistribution: (distributionUpdates: DistributionUpdates, cycleId: string) => void;
|
||||
validateDate: (workspaceSlug: string, projectId: string, payload: CycleDateCheckData) => Promise<any>;
|
||||
setPlotType: (cycleId: string, plotType: TCyclePlotType) => void;
|
||||
setEstimateType: (cycleId: string, estimateType: TCycleEstimateType) => void;
|
||||
updateWorkspaceUserActiveCycleCount: (workspaceSlug: string, increment: number) => void;
|
||||
@@ -131,15 +125,12 @@ export class CycleStore implements ICycleStore {
|
||||
// computed
|
||||
currentProjectCycleIds: computed,
|
||||
currentProjectCompletedCycleIds: computed,
|
||||
currentProjectUpcomingCycleIds: computed,
|
||||
currentProjectIncompleteCycleIds: computed,
|
||||
currentProjectDraftCycleIds: computed,
|
||||
currentProjectActiveCycleId: computed,
|
||||
currentProjectArchivedCycleIds: computed,
|
||||
currentProjectActiveCycle: computed,
|
||||
|
||||
// actions
|
||||
setPlotType: action,
|
||||
setEstimateType: action,
|
||||
fetchWorkspaceCycles: action,
|
||||
fetchAllCycles: action,
|
||||
@@ -197,22 +188,6 @@ export class CycleStore implements ICycleStore {
|
||||
return completedCycleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all upcoming cycle ids for a project
|
||||
*/
|
||||
get currentProjectUpcomingCycleIds() {
|
||||
const projectId = this.rootStore.router.projectId;
|
||||
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||
let upcomingCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
|
||||
const startDate = getDate(c.start_date);
|
||||
const isStartDateUpcoming = startDate && isFuture(startDate);
|
||||
return c.project_id === projectId && isStartDateUpcoming && !c?.archived_at;
|
||||
});
|
||||
upcomingCycles = sortBy(upcomingCycles, [(c) => c.sort_order]);
|
||||
const upcomingCycleIds = upcomingCycles.map((c) => c.id);
|
||||
return upcomingCycleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all incomplete cycle ids for a project
|
||||
*/
|
||||
@@ -229,20 +204,6 @@ export class CycleStore implements ICycleStore {
|
||||
return incompleteCycleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all draft cycle ids for a project
|
||||
*/
|
||||
get currentProjectDraftCycleIds() {
|
||||
const projectId = this.rootStore.router.projectId;
|
||||
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||
let draftCycles = Object.values(this.cycleMap ?? {}).filter(
|
||||
(c) => c.project_id === projectId && !c.start_date && !c.end_date && !c?.archived_at
|
||||
);
|
||||
draftCycles = sortBy(draftCycles, [(c) => c.sort_order]);
|
||||
const draftCycleIds = draftCycles.map((c) => c.id);
|
||||
return draftCycleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns active cycle id for a project
|
||||
*/
|
||||
@@ -287,19 +248,6 @@ export class CycleStore implements ICycleStore {
|
||||
} else return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* returns active cycle progress for a project
|
||||
*/
|
||||
getActiveCycleProgress = computedFn((cycleId?: string) => {
|
||||
const cycle = cycleId ? this.cycleMap[cycleId] : this.currentProjectActiveCycle;
|
||||
if (!cycle) return null;
|
||||
|
||||
const isTypeIssue = this.getEstimateTypeByCycleId(cycle.id) === "issues";
|
||||
const isBurnDown = this.getPlotTypeByCycleId(cycle.id) === "burndown";
|
||||
|
||||
return { cycle, isTypeIssue, isBurnDown };
|
||||
});
|
||||
|
||||
/**
|
||||
* @description returns filtered cycle ids based on display filters and filters
|
||||
* @param {TCycleDisplayFilters} displayFilters
|
||||
@@ -381,37 +329,28 @@ export class CycleStore implements ICycleStore {
|
||||
getCycleNameById = computedFn((cycleId: string): string => this.cycleMap?.[cycleId]?.name);
|
||||
|
||||
/**
|
||||
* @description returns active cycle details by cycle id
|
||||
* @param cycleId
|
||||
* @returns
|
||||
* @description returns list of cycle details of the project id passed as argument
|
||||
* @param projectId
|
||||
*/
|
||||
getActiveCycleById = computedFn((cycleId: string): ICycle | null =>
|
||||
this.activeCycleIdMap?.[cycleId] && this.cycleMap?.[cycleId] ? this.cycleMap?.[cycleId] : null
|
||||
);
|
||||
getProjectCycleDetails = computedFn((projectId: string): ICycle[] | null => {
|
||||
if (!this.fetchedMap[projectId]) return null;
|
||||
|
||||
let cycles = Object.values(this.cycleMap ?? {}).filter((c) => c.project_id === projectId && !c?.archived_at);
|
||||
cycles = sortBy(cycles, [(c) => c.sort_order]);
|
||||
return cycles || null;
|
||||
});
|
||||
|
||||
/**
|
||||
* @description returns list of cycle ids of the project id passed as argument
|
||||
* @param projectId
|
||||
*/
|
||||
getProjectCycleIds = computedFn((projectId: string): string[] | null => {
|
||||
if (!this.fetchedMap[projectId]) return null;
|
||||
|
||||
let cycles = Object.values(this.cycleMap ?? {}).filter((c) => c.project_id === projectId && !c?.archived_at);
|
||||
cycles = sortBy(cycles, [(c) => c.sort_order]);
|
||||
const cycles = this.getProjectCycleDetails(projectId);
|
||||
if (!cycles) return null;
|
||||
const cycleIds = cycles.map((c) => c.id);
|
||||
return cycleIds || null;
|
||||
});
|
||||
|
||||
/**
|
||||
* @description validates cycle dates
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param payload
|
||||
* @returns
|
||||
*/
|
||||
validateDate = async (workspaceSlug: string, projectId: string, payload: CycleDateCheckData) =>
|
||||
await this.cycleService.cycleDateCheck(workspaceSlug, projectId, payload);
|
||||
|
||||
/**
|
||||
* @description gets the plot type for the cycle store
|
||||
* @param {TCyclePlotType} plotType
|
||||
@@ -482,14 +421,16 @@ export class CycleStore implements ICycleStore {
|
||||
runInAction(() => {
|
||||
response.forEach((cycle) => {
|
||||
set(this.cycleMap, [cycle.id], cycle);
|
||||
cycle.status?.toLowerCase() === "current" && set(this.activeCycleIdMap, [cycle.id], true);
|
||||
if (cycle.status?.toLowerCase() === "current") {
|
||||
set(this.activeCycleIdMap, [cycle.id], true);
|
||||
}
|
||||
});
|
||||
set(this.fetchedMap, projectId, true);
|
||||
this.loader = false;
|
||||
});
|
||||
return response;
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
this.loader = false;
|
||||
return undefined;
|
||||
}
|
||||
@@ -562,6 +503,7 @@ export class CycleStore implements ICycleStore {
|
||||
* @param cycleId
|
||||
* @returns
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
fetchActiveCycleProgressPro = action(async (workspaceSlug: string, projectId: string, cycleId: string) => {});
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,7 @@ export interface IModuleStore {
|
||||
getFilteredArchivedModuleIds: (projectId: string) => string[] | null;
|
||||
getModuleById: (moduleId: string) => IModule | null;
|
||||
getModuleNameById: (moduleId: string) => string;
|
||||
getProjectModuleDetails: (projectId: string) => IModule[] | null;
|
||||
getProjectModuleIds: (projectId: string) => string[] | null;
|
||||
getPlotTypeByModuleId: (moduleId: string) => TModulePlotType;
|
||||
// actions
|
||||
@@ -210,15 +211,24 @@ export class ModulesStore implements IModuleStore {
|
||||
*/
|
||||
getModuleNameById = computedFn((moduleId: string) => this.moduleMap?.[moduleId]?.name);
|
||||
|
||||
/**
|
||||
* @description returns list of module details of the project id passed as argument
|
||||
* @param projectId
|
||||
*/
|
||||
getProjectModuleDetails = computedFn((projectId: string) => {
|
||||
if (!this.fetchedMap[projectId]) return null;
|
||||
let projectModules = Object.values(this.moduleMap).filter((m) => m.project_id === projectId && !m.archived_at);
|
||||
projectModules = sortBy(projectModules, [(m) => m.sort_order]);
|
||||
return projectModules;
|
||||
});
|
||||
|
||||
/**
|
||||
* @description returns list of module ids of the project id passed as argument
|
||||
* @param projectId
|
||||
*/
|
||||
getProjectModuleIds = computedFn((projectId: string) => {
|
||||
if (!this.fetchedMap[projectId]) return null;
|
||||
|
||||
let projectModules = Object.values(this.moduleMap).filter((m) => m.project_id === projectId && !m.archived_at);
|
||||
projectModules = sortBy(projectModules, [(m) => m.sort_order]);
|
||||
const projectModules = this.getProjectModuleDetails(projectId);
|
||||
if (!projectModules) return null;
|
||||
const projectModuleIds = projectModules.map((m) => m.id);
|
||||
return projectModuleIds;
|
||||
});
|
||||
@@ -282,7 +292,7 @@ export class ModulesStore implements IModuleStore {
|
||||
});
|
||||
return response;
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
this.loader = false;
|
||||
return undefined;
|
||||
}
|
||||
@@ -308,7 +318,7 @@ export class ModulesStore implements IModuleStore {
|
||||
});
|
||||
return projectModules;
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
this.loader = false;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user