@zeniai/client-epic-state 5.1.44 → 5.1.45-betaDI2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,6 +22,7 @@ export interface TaskPayload {
22
22
  update_time: string | null;
23
23
  company_id?: string;
24
24
  company_name?: string;
25
+ depth?: number | null;
25
26
  group_assignees?: string[];
26
27
  parent_task_id?: string | null;
27
28
  recurring_days_of_week?: string[] | null;
@@ -45,6 +45,14 @@ const mapTaskPayloadToTask = (payload, previousTask) => ({
45
45
  updateTime: payload.update_time != null ? (0, zeniDayJS_1.date)(payload.update_time) : undefined,
46
46
  companyId: payload.company_id,
47
47
  companyName: payload.company_name,
48
+ // `depth` may be absent on partial updates (e.g. pusher-driven task
49
+ // refreshes that don't include it). Preserve the previously-known depth
50
+ // there — otherwise the Redux store's depth flips to undefined and any
51
+ // WC depth-cap gate ("hide Create Subtask at depth 3") re-opens
52
+ // incorrectly. Explicit `null` from the BE still clears it via `??`.
53
+ depth: payload.depth !== undefined
54
+ ? (payload.depth ?? undefined)
55
+ : previousTask?.depth,
48
56
  parentTaskId: payload.parent_task_id ?? undefined,
49
57
  recurringSourceTaskId: payload.recurring_source_task_id != null
50
58
  ? payload.recurring_source_task_id
@@ -23,6 +23,7 @@ export interface Task {
23
23
  type: TaskType;
24
24
  companyId?: ID;
25
25
  companyName?: string;
26
+ depth?: number;
26
27
  dueDate?: ZeniDate;
27
28
  parentTaskId?: ID | null;
28
29
  recurringDaysOfWeek?: DayOfWeek[];
@@ -42,6 +42,14 @@ export const mapTaskPayloadToTask = (payload, previousTask) => ({
42
42
  updateTime: payload.update_time != null ? date(payload.update_time) : undefined,
43
43
  companyId: payload.company_id,
44
44
  companyName: payload.company_name,
45
+ // `depth` may be absent on partial updates (e.g. pusher-driven task
46
+ // refreshes that don't include it). Preserve the previously-known depth
47
+ // there — otherwise the Redux store's depth flips to undefined and any
48
+ // WC depth-cap gate ("hide Create Subtask at depth 3") re-opens
49
+ // incorrectly. Explicit `null` from the BE still clears it via `??`.
50
+ depth: payload.depth !== undefined
51
+ ? (payload.depth ?? undefined)
52
+ : previousTask?.depth,
45
53
  parentTaskId: payload.parent_task_id ?? undefined,
46
54
  recurringSourceTaskId: payload.recurring_source_task_id != null
47
55
  ? payload.recurring_source_task_id
@@ -29,6 +29,7 @@ export const initializeTaskToLocalStoreEpic = (actions$, state$) => actions$.pip
29
29
  timeSpent: task.timeSpent,
30
30
  isPrivate: task.isPrivate,
31
31
  taskGroupId: task.taskGroupIds[0],
32
+ depth: task.depth,
32
33
  };
33
34
  const actions = [
34
35
  saveTaskUpdatesToLocalStore({ taskDetailLocalData, taskId }),
@@ -824,13 +824,38 @@ const getGroupedTaskIds = (tasks) => {
824
824
  ...initialTaskIdsByDueDate,
825
825
  };
826
826
  const taskIdsByTags = {};
827
+ // A task is a "nested subtask" (hidden from the flat top-level list +
828
+ // dropped from the tab count) iff a parent in the same payload claims
829
+ // it via its `subtasks: [...]` array. Match this criterion exactly to
830
+ // WC's `allSubtaskIds` union in TaskManagementPage.tsx — otherwise
831
+ // the tab count and the visible top-level row count disagree
832
+ // whenever the BE emits `parent_task_id` on a subtask but omits it
833
+ // from the parent's `subtasks` array (a real inconsistency this UI
834
+ // sees today).
835
+ //
836
+ // Using `parent_task_id` here would sometimes drop a task from the
837
+ // count that WC still renders as a flat top-level row — that's the
838
+ // bug we're fixing.
839
+ const nestedSubtaskIds = new Set();
827
840
  tasks.forEach((task) => {
828
- taskIds.push(task.task_id);
841
+ (task.subtasks ?? []).forEach((subtaskId) => nestedSubtaskIds.add(subtaskId));
842
+ });
843
+ tasks.forEach((task) => {
844
+ const isNestedSubtask = nestedSubtaskIds.has(task.task_id);
845
+ // Subtasks stay in every groupBy array so the UI can render them
846
+ // nested under their parent (WC's TaskManagementPage builds
847
+ // `subtasksByParentId` from `group.tasks` and then filters them
848
+ // out of top-level rows via `filterOutSubtasks`). Only the flat
849
+ // top-level `taskIds` array — which drives the Active/Completed/…
850
+ // tab counts — must exclude nested subtasks.
829
851
  const priorityKey = toPriorityCodeType(task.priority.code);
830
852
  const statusKey = toTaskStatusCodeType(task.status.code);
831
853
  const assigneeKey = getAssigneesGroupKey(task.assignees);
832
854
  const dueDateKey = getDueDateGroupKey(task.due_date);
833
855
  const tagsKey = getTagsGroupKey(task.tags);
856
+ if (!isNestedSubtask) {
857
+ taskIds.push(task.task_id);
858
+ }
834
859
  taskIdsGroupedByPriority[priorityKey] = [
835
860
  ...taskIdsGroupedByPriority[priorityKey],
836
861
  task.task_id,
@@ -35,6 +35,7 @@ const initializeTaskToLocalStoreEpic = (actions$, state$) => actions$.pipe((0, o
35
35
  timeSpent: task.timeSpent,
36
36
  isPrivate: task.isPrivate,
37
37
  taskGroupId: task.taskGroupIds[0],
38
+ depth: task.depth,
38
39
  };
39
40
  const actions = [
40
41
  (0, taskDetailReducer_1.saveTaskUpdatesToLocalStore)({ taskDetailLocalData, taskId }),
@@ -47,6 +47,7 @@ export interface EditTaskLocalData {
47
47
  tagIds: ID[];
48
48
  timeSpent: string;
49
49
  type: TaskType;
50
+ depth?: number;
50
51
  dueDate?: ZeniDate;
51
52
  isPrivate?: boolean;
52
53
  recurringDaysOfWeek?: DayOfWeek[];
@@ -828,13 +828,38 @@ const getGroupedTaskIds = (tasks) => {
828
828
  ...initialTaskIdsByDueDate,
829
829
  };
830
830
  const taskIdsByTags = {};
831
+ // A task is a "nested subtask" (hidden from the flat top-level list +
832
+ // dropped from the tab count) iff a parent in the same payload claims
833
+ // it via its `subtasks: [...]` array. Match this criterion exactly to
834
+ // WC's `allSubtaskIds` union in TaskManagementPage.tsx — otherwise
835
+ // the tab count and the visible top-level row count disagree
836
+ // whenever the BE emits `parent_task_id` on a subtask but omits it
837
+ // from the parent's `subtasks` array (a real inconsistency this UI
838
+ // sees today).
839
+ //
840
+ // Using `parent_task_id` here would sometimes drop a task from the
841
+ // count that WC still renders as a flat top-level row — that's the
842
+ // bug we're fixing.
843
+ const nestedSubtaskIds = new Set();
831
844
  tasks.forEach((task) => {
832
- taskIds.push(task.task_id);
845
+ (task.subtasks ?? []).forEach((subtaskId) => nestedSubtaskIds.add(subtaskId));
846
+ });
847
+ tasks.forEach((task) => {
848
+ const isNestedSubtask = nestedSubtaskIds.has(task.task_id);
849
+ // Subtasks stay in every groupBy array so the UI can render them
850
+ // nested under their parent (WC's TaskManagementPage builds
851
+ // `subtasksByParentId` from `group.tasks` and then filters them
852
+ // out of top-level rows via `filterOutSubtasks`). Only the flat
853
+ // top-level `taskIds` array — which drives the Active/Completed/…
854
+ // tab counts — must exclude nested subtasks.
833
855
  const priorityKey = (0, taskState_1.toPriorityCodeType)(task.priority.code);
834
856
  const statusKey = (0, taskState_1.toTaskStatusCodeType)(task.status.code);
835
857
  const assigneeKey = getAssigneesGroupKey(task.assignees);
836
858
  const dueDateKey = getDueDateGroupKey(task.due_date);
837
859
  const tagsKey = getTagsGroupKey(task.tags);
860
+ if (!isNestedSubtask) {
861
+ taskIds.push(task.task_id);
862
+ }
838
863
  taskIdsGroupedByPriority[priorityKey] = [
839
864
  ...taskIdsGroupedByPriority[priorityKey],
840
865
  task.task_id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.1.44",
3
+ "version": "5.1.45-betaDI2",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",