@tuturuuu/ui 0.8.0 → 0.10.0

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.
Files changed (245) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/biome.json +1 -1
  3. package/package.json +74 -71
  4. package/src/components/ui/accordion.tsx +1 -1
  5. package/src/components/ui/breadcrumb.tsx +1 -1
  6. package/src/components/ui/calendar-app/calendar-page-shell.tsx +4 -0
  7. package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +239 -33
  8. package/src/components/ui/calendar-app/components/load-smart-scheduling-tasks.tsx +143 -0
  9. package/src/components/ui/calendar-app/components/priority-view.tsx +10 -3
  10. package/src/components/ui/calendar-app/components/tasks-sidebar.tsx +4 -116
  11. package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +67 -2
  12. package/src/components/ui/calendar.tsx +1 -1
  13. package/src/components/ui/carousel.tsx +1 -1
  14. package/src/components/ui/chat/chat-agent-details-external-thread-panel.test.tsx +1 -1
  15. package/src/components/ui/chat/chat-agent-details-external-thread-panel.tsx +1 -1
  16. package/src/components/ui/chat/chat-agent-details-operations-panel.test.tsx +1 -1
  17. package/src/components/ui/chat/chat-agent-details-operations-panel.tsx +1 -1
  18. package/src/components/ui/chat/chat-agent-details-setup-panel.tsx +1 -1
  19. package/src/components/ui/chat/chat-agent-details-sidebar.test.tsx +1 -1
  20. package/src/components/ui/chat/chat-agent-details-sidebar.tsx +2 -2
  21. package/src/components/ui/chat/chat-agent-details-utils.test.ts +1 -1
  22. package/src/components/ui/chat/chat-agent-details-utils.tsx +1 -1
  23. package/src/components/ui/chat/chat-agent-details-zalo-personal-panel.tsx +2 -2
  24. package/src/components/ui/checkbox.tsx +1 -1
  25. package/src/components/ui/color-picker.tsx +1 -1
  26. package/src/components/ui/command.tsx +1 -1
  27. package/src/components/ui/context-menu.tsx +5 -1
  28. package/src/components/ui/custom/__tests__/settings-dialog-search.test.ts +78 -0
  29. package/src/components/ui/custom/__tests__/settings-dialog-shell-compile-graph.test.ts +76 -0
  30. package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +3 -0
  31. package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +46 -1
  32. package/src/components/ui/custom/combobox.test.tsx +195 -0
  33. package/src/components/ui/custom/combobox.tsx +273 -156
  34. package/src/components/ui/custom/education/modules/youtube/delete-link-button.tsx +5 -13
  35. package/src/components/ui/custom/facebook-mockup/facebook-mockup.tsx +7 -1
  36. package/src/components/ui/custom/facebook-mockup/form.tsx +1 -1
  37. package/src/components/ui/custom/facebook-mockup/image-upload-field.tsx +1 -1
  38. package/src/components/ui/custom/facebook-mockup/preview.tsx +1 -1
  39. package/src/components/ui/custom/nav-link.test.tsx +165 -0
  40. package/src/components/ui/custom/nav-link.tsx +69 -11
  41. package/src/components/ui/custom/navigation.tsx +1 -0
  42. package/src/components/ui/custom/settings/task-settings.tsx +104 -0
  43. package/src/components/ui/custom/settings-dialog-search-loader.d.ts +5 -0
  44. package/src/components/ui/custom/settings-dialog-search-loader.js +3 -0
  45. package/src/components/ui/custom/settings-dialog-search.ts +75 -0
  46. package/src/components/ui/custom/settings-dialog-shell.tsx +65 -28
  47. package/src/components/ui/custom/theme-toggle.tsx +1 -1
  48. package/src/components/ui/custom/workspace-select-helpers.ts +23 -0
  49. package/src/components/ui/custom/workspace-select.tsx +25 -19
  50. package/src/components/ui/dialog.test.tsx +52 -0
  51. package/src/components/ui/dialog.tsx +6 -2
  52. package/src/components/ui/dropdown-menu.tsx +5 -1
  53. package/src/components/ui/finance/debts/debt-loan-form.tsx +12 -5
  54. package/src/components/ui/finance/debts/debt-loan-summary.tsx +3 -2
  55. package/src/components/ui/finance/debts/debts-page.test.tsx +54 -5
  56. package/src/components/ui/finance/debts/debts-page.tsx +15 -2
  57. package/src/components/ui/finance/invoices/components/subscription-group-selector.tsx +3 -5
  58. package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +25 -5
  59. package/src/components/ui/finance/invoices/new-invoice-page.tsx +7 -2
  60. package/src/components/ui/finance/invoices/standard-invoice.tsx +4 -2
  61. package/src/components/ui/finance/invoices/subscription-invoice.tsx +4 -2
  62. package/src/components/ui/finance/invoices/utils.ts +3 -1
  63. package/src/components/ui/finance/transactions/form-content-dialog.tsx +3 -0
  64. package/src/components/ui/finance/transactions/form-types.ts +1 -0
  65. package/src/components/ui/finance/transactions/form.tsx +2 -0
  66. package/src/components/ui/finance/transactions/infinite-transactions-list.tsx +2 -0
  67. package/src/components/ui/finance/transactions/period-charts/category-breakdown-dialog.tsx +1 -1
  68. package/src/components/ui/finance/transactions/transaction-edit-dialog.tsx +1 -4
  69. package/src/components/ui/finance/transactions/transactions-create-summary.tsx +3 -0
  70. package/src/components/ui/finance/transactions/transactions-page.tsx +4 -1
  71. package/src/components/ui/finance/wallets/form.test.tsx +51 -3
  72. package/src/components/ui/finance/wallets/form.tsx +15 -4
  73. package/src/components/ui/finance/wallets/walletId/wallet-details-actions.tsx +4 -0
  74. package/src/components/ui/finance/wallets/walletId/wallet-details-page.tsx +4 -2
  75. package/src/components/ui/finance/wallets/wallets-data-table.tsx +1 -0
  76. package/src/components/ui/finance/wallets/wallets-page.tsx +5 -2
  77. package/src/components/ui/input-otp.tsx +1 -1
  78. package/src/components/ui/legacy/calendar/all-day-event-bar.tsx +28 -39
  79. package/src/components/ui/legacy/calendar/calendar-cell.tsx +2 -0
  80. package/src/components/ui/legacy/calendar/calendar-content.tsx +10 -6
  81. package/src/components/ui/legacy/calendar/calendar-header.tsx +23 -3
  82. package/src/components/ui/legacy/calendar/calendar-loading-skeleton.tsx +135 -0
  83. package/src/components/ui/legacy/calendar/calendar-matrix.tsx +175 -237
  84. package/src/components/ui/legacy/calendar/event-card.test.tsx +177 -0
  85. package/src/components/ui/legacy/calendar/event-card.tsx +220 -131
  86. package/src/components/ui/legacy/calendar/event-modal.tsx +17 -17
  87. package/src/components/ui/legacy/calendar/event-provider-display.tsx +69 -0
  88. package/src/components/ui/legacy/calendar/smart-calendar.test.tsx +86 -4
  89. package/src/components/ui/legacy/calendar/smart-calendar.tsx +32 -2
  90. package/src/components/ui/legacy/meet/create-plan-dialog.tsx +19 -10
  91. package/src/components/ui/navigation-menu.tsx +1 -1
  92. package/src/components/ui/pagination.tsx +1 -1
  93. package/src/components/ui/radio-group.tsx +1 -1
  94. package/src/components/ui/select.tsx +5 -1
  95. package/src/components/ui/sheet.tsx +1 -1
  96. package/src/components/ui/sidebar.tsx +1 -1
  97. package/src/components/ui/storefront/cart-popover.tsx +61 -0
  98. package/src/components/ui/storefront/cart-summary-parts.tsx +290 -0
  99. package/src/components/ui/storefront/cart-summary.tsx +93 -154
  100. package/src/components/ui/storefront/checkout-overlay.tsx +4 -5
  101. package/src/components/ui/storefront/listing-card.tsx +1 -1
  102. package/src/components/ui/storefront/merch-sections.tsx +70 -0
  103. package/src/components/ui/storefront/product-detail.tsx +1 -1
  104. package/src/components/ui/storefront/storefront-surface.test.tsx +106 -11
  105. package/src/components/ui/storefront/storefront-surface.tsx +101 -166
  106. package/src/components/ui/storefront/types.ts +4 -0
  107. package/src/components/ui/storefront/utils.ts +6 -0
  108. package/src/components/ui/text-editor/__tests__/extensions.test.ts +123 -0
  109. package/src/components/ui/text-editor/background-color-extension.ts +62 -0
  110. package/src/components/ui/text-editor/color-controls.tsx +284 -0
  111. package/src/components/ui/text-editor/editor.tsx +69 -14
  112. package/src/components/ui/text-editor/extensions.ts +8 -2
  113. package/src/components/ui/text-editor/highlight-extension.ts +22 -0
  114. package/src/components/ui/text-editor/tool-bar.tsx +9 -16
  115. package/src/components/ui/toast.tsx +1 -1
  116. package/src/components/ui/tu-do/boards/__tests__/board-share-dialog.test.tsx +286 -0
  117. package/src/components/ui/tu-do/boards/__tests__/task-board-form.test.tsx +12 -0
  118. package/src/components/ui/tu-do/boards/board-public-link-section.tsx +231 -0
  119. package/src/components/ui/tu-do/boards/board-share-dialog.tsx +15 -226
  120. package/src/components/ui/tu-do/boards/board-share-settings-panel.tsx +351 -0
  121. package/src/components/ui/tu-do/boards/boardId/board-column.tsx +121 -39
  122. package/src/components/ui/tu-do/boards/boardId/enhanced-task-list.tsx +7 -0
  123. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-clear-delete.ts +2 -0
  124. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-move.ts +5 -0
  125. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-updates.ts +3 -0
  126. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operation-types.ts +3 -3
  127. package/src/components/ui/tu-do/boards/boardId/kanban/data/kanban-deadline-query.ts +50 -2
  128. package/src/components/ui/tu-do/boards/boardId/kanban/data/use-bulk-resources.ts +59 -5
  129. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/__tests__/column-reorder.test.ts +17 -0
  130. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/column-reorder.ts +4 -1
  131. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/drag-preview.tsx +20 -1
  132. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-cache.ts +38 -9
  133. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-order.ts +2 -8
  134. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-sort-key.ts +47 -0
  135. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +81 -30
  136. package/src/components/ui/tu-do/boards/boardId/kanban/planner/__tests__/kanban-planner-island.test.tsx +380 -0
  137. package/src/components/ui/tu-do/boards/boardId/kanban/planner/kanban-planner-dialog.tsx +204 -0
  138. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-digest-panel.tsx +61 -0
  139. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-item-strip.tsx +54 -0
  140. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-plan-toolbar.tsx +251 -0
  141. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-scope-badge.tsx +27 -0
  142. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-section.tsx +58 -0
  143. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-share-dialog.tsx +238 -0
  144. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-target-controls.tsx +143 -0
  145. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-utils.ts +65 -0
  146. package/src/components/ui/tu-do/boards/boardId/kanban/planner/use-kanban-planner-state.ts +234 -0
  147. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +642 -5
  148. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +224 -15
  149. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-deadline-panels.tsx +535 -53
  150. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-skeleton.tsx +101 -33
  151. package/src/components/ui/tu-do/boards/boardId/kanban.tsx +235 -113
  152. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.test.tsx +50 -5
  153. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +12 -2
  154. package/src/components/ui/tu-do/boards/boardId/task-card/measured-task-card.tsx +10 -1
  155. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.ts +3 -0
  156. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +20 -0
  157. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +10 -0
  158. package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +271 -36
  159. package/src/components/ui/tu-do/boards/boardId/task-filter.test.tsx +152 -0
  160. package/src/components/ui/tu-do/boards/boardId/task-filter.tsx +555 -545
  161. package/src/components/ui/tu-do/boards/boardId/task-list.tsx +22 -0
  162. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-grid.tsx +9 -0
  163. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-task-row.tsx +9 -0
  164. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-toolbar.tsx +9 -0
  165. package/src/components/ui/tu-do/boards/boardId/timeline-board.tsx +35 -3
  166. package/src/components/ui/tu-do/boards/form.tsx +1 -1
  167. package/src/components/ui/tu-do/boards/share-section.tsx +100 -0
  168. package/src/components/ui/tu-do/drafts/draft-convert-dialog.tsx +10 -12
  169. package/src/components/ui/tu-do/drafts/drafts-page.tsx +33 -16
  170. package/src/components/ui/tu-do/hooks/__tests__/useTaskLabelManagement.test.tsx +48 -0
  171. package/src/components/ui/tu-do/hooks/__tests__/useTaskProjectManagement.test.tsx +144 -0
  172. package/src/components/ui/tu-do/hooks/useTaskDialog.ts +7 -0
  173. package/src/components/ui/tu-do/hooks/useTaskLabelManagement.ts +115 -106
  174. package/src/components/ui/tu-do/hooks/useTaskProjectManagement.ts +115 -122
  175. package/src/components/ui/tu-do/initiatives/task-initiatives-client.tsx +56 -88
  176. package/src/components/ui/tu-do/my-tasks/my-tasks-content.tsx +26 -2
  177. package/src/components/ui/tu-do/my-tasks/use-my-tasks-state.ts +55 -8
  178. package/src/components/ui/tu-do/notes/note-edit-dialog.tsx +1 -4
  179. package/src/components/ui/tu-do/progress/task-progress-import-panel.tsx +60 -0
  180. package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +156 -0
  181. package/src/components/ui/tu-do/progress/task-progress-page.tsx +348 -0
  182. package/src/components/ui/tu-do/progress/task-progress-panels.tsx +301 -0
  183. package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +26 -0
  184. package/src/components/ui/tu-do/shared/__tests__/assignee-select.test.tsx +81 -10
  185. package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +141 -1
  186. package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +377 -36
  187. package/src/components/ui/tu-do/shared/__tests__/board-switcher.test.tsx +374 -0
  188. package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +419 -5
  189. package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +38 -0
  190. package/src/components/ui/tu-do/shared/__tests__/task-cache-patches.test.ts +147 -0
  191. package/src/components/ui/tu-do/shared/__tests__/task-legacy-route-recovery.test.tsx +16 -0
  192. package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +3 -0
  193. package/src/components/ui/tu-do/shared/assignee-select.tsx +77 -26
  194. package/src/components/ui/tu-do/shared/board-client.tsx +15 -10
  195. package/src/components/ui/tu-do/shared/board-config-storage.ts +7 -1
  196. package/src/components/ui/tu-do/shared/board-header.tsx +471 -975
  197. package/src/components/ui/tu-do/shared/board-layout-settings.tsx +165 -136
  198. package/src/components/ui/tu-do/shared/board-switcher.tsx +244 -220
  199. package/src/components/ui/tu-do/shared/board-user-presence-avatars.tsx +18 -12
  200. package/src/components/ui/tu-do/shared/board-views.tsx +577 -85
  201. package/src/components/ui/tu-do/shared/list-view.tsx +246 -2
  202. package/src/components/ui/tu-do/shared/recycle-bin-panel.tsx +142 -94
  203. package/src/components/ui/tu-do/shared/special-task-list-pins.ts +51 -0
  204. package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +28 -0
  205. package/src/components/ui/tu-do/shared/task-cache-patches.ts +394 -0
  206. package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +21 -1
  207. package/src/components/ui/tu-do/shared/task-edit-dialog/components/quick-settings-popover.tsx +5 -1
  208. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +25 -2
  209. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-list-selector.tsx +7 -1
  210. package/src/components/ui/tu-do/shared/task-edit-dialog/field-diff-viewer.tsx +3 -2
  211. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-data.ts +79 -10
  212. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +76 -77
  213. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.test.tsx +63 -0
  214. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.ts +78 -69
  215. package/src/components/ui/tu-do/shared/task-edit-dialog/personal-overrides-section.tsx +28 -8
  216. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/dependencies-section.tsx +14 -3
  217. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/parent-section.tsx +6 -1
  218. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/related-section.tsx +6 -1
  219. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/subtasks-section.tsx +6 -1
  220. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/types/task-relationships.types.ts +8 -0
  221. package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.test.tsx +91 -0
  222. package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.tsx +123 -78
  223. package/src/components/ui/tu-do/shared/task-edit-dialog/task-activity-section.tsx +7 -1
  224. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +8 -1
  225. package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.test.tsx +150 -0
  226. package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.tsx +61 -35
  227. package/src/components/ui/tu-do/shared/task-edit-dialog/task-relationships-properties.tsx +44 -2
  228. package/src/components/ui/tu-do/shared/task-edit-dialog/task-snapshot-dialog.tsx +8 -3
  229. package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +11 -1
  230. package/src/components/ui/tu-do/shared/task-legacy-route-recovery.tsx +2 -9
  231. package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +11 -0
  232. package/src/components/ui/tu-do/shared/use-progressive-board-loader.ts +2 -0
  233. package/src/declarations.d.ts +1 -0
  234. package/src/hooks/__tests__/use-calendar-readonly.test.tsx +322 -2
  235. package/src/hooks/__tests__/use-calendar-sync.test.tsx +446 -0
  236. package/src/hooks/__tests__/useBoardPresence.test.tsx +191 -0
  237. package/src/hooks/__tests__/useBoardRealtime.test.tsx +24 -144
  238. package/src/hooks/use-calendar-sync.tsx +247 -243
  239. package/src/hooks/use-calendar.tsx +323 -138
  240. package/src/hooks/use-task-actions.ts +24 -0
  241. package/src/hooks/use-user-workspace-config.ts +75 -0
  242. package/src/hooks/use-workspace-currency.ts +8 -3
  243. package/src/hooks/useBoardPresence.ts +364 -0
  244. package/src/hooks/useBoardRealtimeEventHandler.ts +45 -90
  245. package/src/lib/workspace-actions.ts +2 -6
@@ -0,0 +1,150 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import '@testing-library/jest-dom';
6
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
7
+ import { fireEvent, render, screen } from '@testing-library/react';
8
+ import type { TaskList } from '@tuturuuu/types/primitives/TaskList';
9
+ import { describe, expect, it, vi } from 'vitest';
10
+ import { TaskPropertiesSection } from './task-properties-section';
11
+
12
+ vi.mock('next-intl', () => ({
13
+ useTranslations: () => (key: string) => key,
14
+ }));
15
+
16
+ vi.mock('@tuturuuu/ui/date-time-picker', () => ({
17
+ DateTimePicker: () => <button type="button">date-time-picker</button>,
18
+ }));
19
+
20
+ vi.mock('@tuturuuu/ui/hooks/use-calendar-preferences', () => ({
21
+ useCalendarPreferences: () => ({
22
+ weekStartsOn: 1,
23
+ timezone: 'UTC',
24
+ timeFormat: '24h',
25
+ }),
26
+ }));
27
+
28
+ function renderTaskPropertiesSection() {
29
+ const props = {
30
+ wsId: 'ws-1',
31
+ boardId: 'board-1',
32
+ taskId: 'task-1',
33
+ priority: null,
34
+ startDate: undefined,
35
+ endDate: undefined,
36
+ estimationPoints: null,
37
+ selectedLabels: [],
38
+ selectedProjects: [],
39
+ selectedListId: 'list-1',
40
+ selectedAssignees: [],
41
+ isLoading: false,
42
+ isPersonalWorkspace: false,
43
+ canUseBoardAssignees: true,
44
+ isCreateMode: false,
45
+ totalDuration: null,
46
+ isSplittable: false,
47
+ minSplitDurationMinutes: null,
48
+ maxSplitDurationMinutes: null,
49
+ calendarHours: null,
50
+ autoSchedule: false,
51
+ savedSchedulingSettings: undefined,
52
+ scheduledEvents: [],
53
+ availableLists: [
54
+ {
55
+ id: 'list-1',
56
+ board_id: 'board-1',
57
+ name: 'To Do',
58
+ status: 'not_started',
59
+ color: 'GRAY',
60
+ position: 0,
61
+ archived: false,
62
+ deleted: false,
63
+ created_at: '2026-01-01T00:00:00.000Z',
64
+ creator_id: 'user-1',
65
+ },
66
+ ] satisfies TaskList[],
67
+ availableLabels: [
68
+ {
69
+ id: 'label-1',
70
+ name: 'Bug',
71
+ color: '#ef4444',
72
+ created_at: '2026-01-01T00:00:00.000Z',
73
+ },
74
+ ],
75
+ taskProjects: [],
76
+ workspaceMembers: [
77
+ {
78
+ id: 'user-1',
79
+ user_id: 'user-1',
80
+ display_name: 'Taylor',
81
+ email: 'taylor@example.com',
82
+ },
83
+ ],
84
+ boardConfig: {},
85
+ onPriorityChange: vi.fn(),
86
+ onStartDateChange: vi.fn(),
87
+ onEndDateChange: vi.fn(),
88
+ onEstimationChange: vi.fn(),
89
+ onLabelToggle: vi.fn(),
90
+ onProjectToggle: vi.fn(),
91
+ onListChange: vi.fn(),
92
+ onAssigneeToggle: vi.fn(),
93
+ onQuickDueDate: vi.fn(),
94
+ onShowNewLabelDialog: vi.fn(),
95
+ onShowNewProjectDialog: vi.fn(),
96
+ onShowEstimationConfigDialog: vi.fn(),
97
+ onTotalDurationChange: vi.fn(),
98
+ onIsSplittableChange: vi.fn(),
99
+ onMinSplitDurationChange: vi.fn(),
100
+ onMaxSplitDurationChange: vi.fn(),
101
+ onCalendarHoursChange: vi.fn(),
102
+ onAutoScheduleChange: vi.fn(),
103
+ onSaveSchedulingSettings: vi.fn().mockResolvedValue(true),
104
+ schedulingSaving: false,
105
+ disabled: false,
106
+ isDraftMode: false,
107
+ variant: 'compact' as const,
108
+ };
109
+
110
+ const queryClient = new QueryClient({
111
+ defaultOptions: {
112
+ queries: { retry: false },
113
+ mutations: { retry: false },
114
+ },
115
+ });
116
+
117
+ render(
118
+ <QueryClientProvider client={queryClient}>
119
+ <TaskPropertiesSection {...props} />
120
+ </QueryClientProvider>
121
+ );
122
+
123
+ return props;
124
+ }
125
+
126
+ describe('TaskPropertiesSection', () => {
127
+ it('keeps only one property popover open at a time', () => {
128
+ renderTaskPropertiesSection();
129
+
130
+ fireEvent.click(screen.getByLabelText('common.priority'));
131
+ expect(screen.getByText('tasks.priority_critical')).toBeInTheDocument();
132
+
133
+ fireEvent.click(screen.getByLabelText('common.labels'));
134
+ expect(
135
+ screen.queryByText('tasks.priority_critical')
136
+ ).not.toBeInTheDocument();
137
+ expect(
138
+ screen.getByPlaceholderText('common.search_labels')
139
+ ).toBeInTheDocument();
140
+
141
+ fireEvent.click(screen.getByLabelText('common.list_name_to_do'));
142
+ expect(
143
+ screen.queryByPlaceholderText('common.search_labels')
144
+ ).not.toBeInTheDocument();
145
+ expect(screen.getByLabelText('common.list_name_to_do')).toHaveAttribute(
146
+ 'aria-expanded',
147
+ 'true'
148
+ );
149
+ });
150
+ });
@@ -102,6 +102,7 @@ interface TaskPropertiesSectionProps {
102
102
  selectedAssignees: any[];
103
103
  isLoading: boolean;
104
104
  isPersonalWorkspace: boolean;
105
+ canUseBoardAssignees?: boolean;
105
106
  isCreateMode: boolean;
106
107
  // Scheduling state
107
108
  totalDuration: number | null;
@@ -151,6 +152,16 @@ interface TaskPropertiesSectionProps {
151
152
  variant?: 'default' | 'compact';
152
153
  }
153
154
 
155
+ type TaskPropertyPopoverId =
156
+ | 'priority'
157
+ | 'list'
158
+ | 'dates'
159
+ | 'estimation'
160
+ | 'labels'
161
+ | 'projects'
162
+ | 'assignees'
163
+ | 'scheduling';
164
+
154
165
  function TaskPropertyPopoverTrigger({
155
166
  children,
156
167
  compact,
@@ -320,6 +331,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
320
331
  selectedAssignees,
321
332
  isLoading,
322
333
  isPersonalWorkspace,
334
+ canUseBoardAssignees = !isPersonalWorkspace,
323
335
  isCreateMode,
324
336
  // Scheduling state
325
337
  totalDuration,
@@ -399,17 +411,27 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
399
411
  const { weekStartsOn, timezone, timeFormat } = useCalendarPreferences();
400
412
 
401
413
  const [isMetadataExpanded, setIsMetadataExpanded] = useState(false);
402
- const [isPriorityPopoverOpen, setIsPriorityPopoverOpen] = useState(false);
403
- const [isDueDatePopoverOpen, setIsDueDatePopoverOpen] = useState(false);
404
- const [isEstimationPopoverOpen, setIsEstimationPopoverOpen] = useState(false);
405
- const [isLabelsPopoverOpen, setIsLabelsPopoverOpen] = useState(false);
406
- const [isProjectsPopoverOpen, setIsProjectsPopoverOpen] = useState(false);
407
- const [isAssigneesPopoverOpen, setIsAssigneesPopoverOpen] = useState(false);
408
- const [isSchedulingPopoverOpen, setIsSchedulingPopoverOpen] = useState(false);
414
+ const [activePopover, setActivePopover] =
415
+ useState<TaskPropertyPopoverId | null>(null);
409
416
  const [labelSearchQuery, setLabelSearchQuery] = useState('');
410
417
  const [projectSearchQuery, setProjectSearchQuery] = useState('');
411
418
  const [assigneeSearchQuery, setAssigneeSearchQuery] = useState('');
412
419
 
420
+ const isPopoverOpen = useCallback(
421
+ (popoverId: TaskPropertyPopoverId) => activePopover === popoverId,
422
+ [activePopover]
423
+ );
424
+
425
+ const setPopoverOpen = useCallback(
426
+ (popoverId: TaskPropertyPopoverId, open: boolean) => {
427
+ setActivePopover((currentPopover) => {
428
+ if (open) return popoverId;
429
+ return currentPopover === popoverId ? null : currentPopover;
430
+ });
431
+ },
432
+ []
433
+ );
434
+
413
435
  const unselectedAvailableLabels = useMemo(
414
436
  () =>
415
437
  availableLabels.filter(
@@ -551,7 +573,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
551
573
  if (success) {
552
574
  // Update local saved state to reflect the successful save
553
575
  setLastSavedSettings(settings);
554
- setIsSchedulingPopoverOpen(false);
576
+ setPopoverOpen('scheduling', false);
555
577
  }
556
578
  }, [
557
579
  totalDuration,
@@ -561,6 +583,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
561
583
  calendarHours,
562
584
  autoSchedule,
563
585
  onSaveSchedulingSettings,
586
+ setPopoverOpen,
564
587
  ]);
565
588
 
566
589
  // Handle clear and save scheduling settings
@@ -585,7 +608,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
585
608
  const success = await onSaveSchedulingSettings(clearedSettings);
586
609
  if (success) {
587
610
  setLastSavedSettings(clearedSettings);
588
- setIsSchedulingPopoverOpen(false);
611
+ setPopoverOpen('scheduling', false);
589
612
  }
590
613
  }, [
591
614
  onTotalDurationChange,
@@ -595,6 +618,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
595
618
  onCalendarHoursChange,
596
619
  onAutoScheduleChange,
597
620
  onSaveSchedulingSettings,
621
+ setPopoverOpen,
598
622
  ]);
599
623
 
600
624
  // Note: Manual scheduling removed - handled by Smart Schedule button in Calendar
@@ -813,7 +837,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
813
837
  })}
814
838
  </Badge>
815
839
  )}
816
- {selectedAssignees.length > 0 && !isPersonalWorkspace && (
840
+ {selectedAssignees.length > 0 && canUseBoardAssignees && (
817
841
  <Badge
818
842
  variant="secondary"
819
843
  className="h-5 shrink-0 gap-1 border border-dynamic-cyan/30 bg-dynamic-cyan/15 px-2 font-medium text-[10px] text-dynamic-cyan"
@@ -869,8 +893,8 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
869
893
  >
870
894
  {/* Priority Badge */}
871
895
  <Popover
872
- open={isPriorityPopoverOpen}
873
- onOpenChange={setIsPriorityPopoverOpen}
896
+ open={isPopoverOpen('priority')}
897
+ onOpenChange={(open) => setPopoverOpen('priority', open)}
874
898
  >
875
899
  <TaskPropertyPopoverTrigger
876
900
  compact={isCompact}
@@ -937,7 +961,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
937
961
  type="button"
938
962
  onClick={() => {
939
963
  onPriorityChange(opt.value as TaskPriority);
940
- setIsPriorityPopoverOpen(false);
964
+ setPopoverOpen('priority', false);
941
965
  }}
942
966
  className={cn(
943
967
  'flex w-full items-center gap-2.5 rounded-md px-2 py-2 text-left text-sm transition-colors hover:bg-muted',
@@ -959,7 +983,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
959
983
  label={t('ws-task-boards.dialog.clear_priority')}
960
984
  onClick={() => {
961
985
  onPriorityChange(null);
962
- setIsPriorityPopoverOpen(false);
986
+ setPopoverOpen('priority', false);
963
987
  }}
964
988
  />
965
989
  )}
@@ -974,13 +998,15 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
974
998
  availableLists={availableLists}
975
999
  disabled={disabled}
976
1000
  compact={isCompact}
1001
+ open={isPopoverOpen('list')}
1002
+ onOpenChange={(open) => setPopoverOpen('list', open)}
977
1003
  onListChange={onListChange}
978
1004
  />
979
1005
 
980
1006
  {/* Dates Badge */}
981
1007
  <Popover
982
- open={isDueDatePopoverOpen}
983
- onOpenChange={setIsDueDatePopoverOpen}
1008
+ open={isPopoverOpen('dates')}
1009
+ onOpenChange={(open) => setPopoverOpen('dates', open)}
984
1010
  >
985
1011
  <TaskPropertyPopoverTrigger
986
1012
  compact={isCompact}
@@ -1126,8 +1152,8 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1126
1152
 
1127
1153
  {/* Estimation Points Badge */}
1128
1154
  <Popover
1129
- open={isEstimationPopoverOpen}
1130
- onOpenChange={setIsEstimationPopoverOpen}
1155
+ open={isPopoverOpen('estimation')}
1156
+ onOpenChange={(open) => setPopoverOpen('estimation', open)}
1131
1157
  >
1132
1158
  <TaskPropertyPopoverTrigger
1133
1159
  compact={isCompact}
@@ -1175,7 +1201,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1175
1201
  actionLabel={t('common.configure')}
1176
1202
  ActionIcon={Pen}
1177
1203
  onAction={() => {
1178
- setIsEstimationPopoverOpen(false);
1204
+ setPopoverOpen('estimation', false);
1179
1205
  onShowEstimationConfigDialog();
1180
1206
  }}
1181
1207
  />
@@ -1187,7 +1213,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1187
1213
  type="button"
1188
1214
  onClick={() => {
1189
1215
  onEstimationChange(idx);
1190
- setIsEstimationPopoverOpen(false);
1216
+ setPopoverOpen('estimation', false);
1191
1217
  }}
1192
1218
  className={cn(
1193
1219
  'flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-sm transition-colors hover:bg-muted',
@@ -1211,7 +1237,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1211
1237
  label={t('ws-task-boards.dialog.clear_estimate')}
1212
1238
  onClick={() => {
1213
1239
  onEstimationChange(null);
1214
- setIsEstimationPopoverOpen(false);
1240
+ setPopoverOpen('estimation', false);
1215
1241
  }}
1216
1242
  />
1217
1243
  )}
@@ -1222,9 +1248,9 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1222
1248
 
1223
1249
  {/* Labels Badge */}
1224
1250
  <Popover
1225
- open={isLabelsPopoverOpen}
1251
+ open={isPopoverOpen('labels')}
1226
1252
  onOpenChange={(open) => {
1227
- setIsLabelsPopoverOpen(open);
1253
+ setPopoverOpen('labels', open);
1228
1254
  if (!open) setLabelSearchQuery('');
1229
1255
  }}
1230
1256
  >
@@ -1274,7 +1300,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1274
1300
  actionLabel={t('ws-task-boards.dialog.create_label')}
1275
1301
  ActionIcon={Plus}
1276
1302
  onAction={() => {
1277
- setIsLabelsPopoverOpen(false);
1303
+ setPopoverOpen('labels', false);
1278
1304
  onShowNewLabelDialog();
1279
1305
  }}
1280
1306
  />
@@ -1355,7 +1381,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1355
1381
  size="sm"
1356
1382
  variant="ghost"
1357
1383
  onClick={() => {
1358
- setIsLabelsPopoverOpen(false);
1384
+ setPopoverOpen('labels', false);
1359
1385
  onShowNewLabelDialog();
1360
1386
  }}
1361
1387
  className="h-8 w-full justify-start"
@@ -1372,9 +1398,9 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1372
1398
  {/* Projects Badge — not available for drafts */}
1373
1399
  {!isDraftMode && (
1374
1400
  <Popover
1375
- open={isProjectsPopoverOpen}
1401
+ open={isPopoverOpen('projects')}
1376
1402
  onOpenChange={(open) => {
1377
- setIsProjectsPopoverOpen(open);
1403
+ setPopoverOpen('projects', open);
1378
1404
  if (!open) setProjectSearchQuery('');
1379
1405
  }}
1380
1406
  >
@@ -1424,7 +1450,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1424
1450
  actionLabel={t('ws-task-boards.dialog.create_project')}
1425
1451
  ActionIcon={Plus}
1426
1452
  onAction={() => {
1427
- setIsProjectsPopoverOpen(false);
1453
+ setPopoverOpen('projects', false);
1428
1454
  onShowNewProjectDialog();
1429
1455
  }}
1430
1456
  />
@@ -1494,7 +1520,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1494
1520
  size="sm"
1495
1521
  variant="ghost"
1496
1522
  onClick={() => {
1497
- setIsProjectsPopoverOpen(false);
1523
+ setPopoverOpen('projects', false);
1498
1524
  onShowNewProjectDialog();
1499
1525
  }}
1500
1526
  className="h-8 w-full justify-start"
@@ -1510,11 +1536,11 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1510
1536
  )}
1511
1537
 
1512
1538
  {/* Assignees Badge */}
1513
- {!isPersonalWorkspace && (
1539
+ {canUseBoardAssignees && (
1514
1540
  <Popover
1515
- open={isAssigneesPopoverOpen}
1541
+ open={isPopoverOpen('assignees')}
1516
1542
  onOpenChange={(open) => {
1517
- setIsAssigneesPopoverOpen(open);
1543
+ setPopoverOpen('assignees', open);
1518
1544
  if (!open) setAssigneeSearchQuery('');
1519
1545
  }}
1520
1546
  >
@@ -1643,8 +1669,8 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
1643
1669
  {/* Scheduling Badge — not available for drafts */}
1644
1670
  {!isDraftMode && (
1645
1671
  <Popover
1646
- open={isSchedulingPopoverOpen}
1647
- onOpenChange={setIsSchedulingPopoverOpen}
1672
+ open={isPopoverOpen('scheduling')}
1673
+ onOpenChange={(open) => setPopoverOpen('scheduling', open)}
1648
1674
  >
1649
1675
  <TaskPropertyPopoverTrigger
1650
1676
  compact={isCompact}
@@ -2006,7 +2032,7 @@ export function TaskPropertiesSection(props: TaskPropertiesSectionProps) {
2006
2032
  label={t('ws-task-boards.dialog.clear_duration')}
2007
2033
  onClick={() => {
2008
2034
  onTotalDurationChange(null);
2009
- setIsSchedulingPopoverOpen(false);
2035
+ setPopoverOpen('scheduling', false);
2010
2036
  }}
2011
2037
  />
2012
2038
  )}
@@ -22,6 +22,8 @@ import type {
22
22
  TaskRelationshipsPropertiesProps,
23
23
  } from './relationships/types/task-relationships.types';
24
24
 
25
+ type RelationshipSearchPopoverId = RelationshipTab;
26
+
25
27
  export function TaskRelationshipsProperties({
26
28
  wsId,
27
29
  taskId,
@@ -59,6 +61,24 @@ export function TaskRelationshipsProperties({
59
61
  const [activeTab, setActiveTab] = React.useState<RelationshipTab>(
60
62
  initialActiveTab ?? 'parent'
61
63
  );
64
+ const [activeSearchPopover, setActiveSearchPopover] =
65
+ React.useState<RelationshipSearchPopoverId | null>(null);
66
+
67
+ const isSearchPopoverOpen = React.useCallback(
68
+ (popoverId: RelationshipSearchPopoverId) =>
69
+ activeSearchPopover === popoverId,
70
+ [activeSearchPopover]
71
+ );
72
+
73
+ const setSearchPopoverOpen = React.useCallback(
74
+ (popoverId: RelationshipSearchPopoverId, open: boolean) => {
75
+ setActiveSearchPopover((currentPopover) => {
76
+ if (open) return popoverId;
77
+ return currentPopover === popoverId ? null : currentPopover;
78
+ });
79
+ },
80
+ []
81
+ );
62
82
 
63
83
  // Tab configuration
64
84
  const tabs = React.useMemo(
@@ -111,7 +131,10 @@ export function TaskRelationshipsProperties({
111
131
  {/* Header with toggle button */}
112
132
  <button
113
133
  type="button"
114
- onClick={() => setIsExpanded(!isExpanded)}
134
+ onClick={() => {
135
+ setIsExpanded((current) => !current);
136
+ setActiveSearchPopover(null);
137
+ }}
115
138
  className="flex w-full items-center justify-between px-4 py-3 text-left transition-colors hover:bg-background/40 md:px-8"
116
139
  >
117
140
  <div className="flex min-w-0 flex-1 items-center gap-2">
@@ -185,7 +208,10 @@ export function TaskRelationshipsProperties({
185
208
  <TabButton
186
209
  key={tab.id}
187
210
  active={activeTab === tab.id}
188
- onClick={() => setActiveTab(tab.id)}
211
+ onClick={() => {
212
+ setActiveTab(tab.id);
213
+ setActiveSearchPopover(null);
214
+ }}
189
215
  icon={tab.icon}
190
216
  label={tab.label}
191
217
  count={tab.count}
@@ -208,6 +234,10 @@ export function TaskRelationshipsProperties({
208
234
  onRemoveParent={onRemoveParent}
209
235
  onNavigateToTask={onNavigateToTask}
210
236
  onAddParentTask={onAddParentTask}
237
+ searchOpen={isSearchPopoverOpen('parent')}
238
+ onSearchOpenChange={(open) =>
239
+ setSearchPopoverOpen('parent', open)
240
+ }
211
241
  disabled={disabled}
212
242
  />
213
243
  )}
@@ -224,6 +254,10 @@ export function TaskRelationshipsProperties({
224
254
  onAddSubtask={onAddSubtask}
225
255
  onAddExistingAsSubtask={onAddExistingAsSubtask}
226
256
  isSaving={isSaving}
257
+ searchOpen={isSearchPopoverOpen('subtasks')}
258
+ onSearchOpenChange={(open) =>
259
+ setSearchPopoverOpen('subtasks', open)
260
+ }
227
261
  disabled={disabled}
228
262
  />
229
263
  )}
@@ -244,6 +278,10 @@ export function TaskRelationshipsProperties({
244
278
  onNavigateToTask={onNavigateToTask}
245
279
  onAddBlockingTaskDialog={onAddBlockingTaskDialog}
246
280
  onAddBlockedByTaskDialog={onAddBlockedByTaskDialog}
281
+ searchOpen={isSearchPopoverOpen('dependencies')}
282
+ onSearchOpenChange={(open) =>
283
+ setSearchPopoverOpen('dependencies', open)
284
+ }
247
285
  disabled={disabled}
248
286
  />
249
287
  )}
@@ -259,6 +297,10 @@ export function TaskRelationshipsProperties({
259
297
  onRemoveRelated={onRemoveRelatedTask}
260
298
  onNavigateToTask={onNavigateToTask}
261
299
  onAddRelatedTaskDialog={onAddRelatedTaskDialog}
300
+ searchOpen={isSearchPopoverOpen('related')}
301
+ onSearchOpenChange={(open) =>
302
+ setSearchPopoverOpen('related', open)
303
+ }
262
304
  disabled={disabled}
263
305
  />
264
306
  )}
@@ -29,15 +29,20 @@ interface TaskSnapshotDialogProps {
29
29
  onClose: () => void;
30
30
  onRevertSuccess?: () => void;
31
31
  locale?: string;
32
- t?: (key: string, options?: { defaultValue?: string }) => string;
32
+ t?: (
33
+ key: string,
34
+ options?: { count?: number; defaultValue?: string }
35
+ ) => string;
33
36
  /** Estimation type for displaying points */
34
37
  estimationType?: EstimationType;
35
38
  /** When true, disables the revert functionality (feature not stable) */
36
39
  revertDisabled?: boolean;
37
40
  }
38
41
 
39
- const defaultT = (key: string, opts?: { defaultValue?: string }) =>
40
- opts?.defaultValue || key;
42
+ const defaultT = (
43
+ key: string,
44
+ opts?: { count?: number; defaultValue?: string }
45
+ ) => opts?.defaultValue || key;
41
46
 
42
47
  export function TaskSnapshotDialog({
43
48
  wsId,
@@ -123,6 +123,8 @@ import { TaskShareDialog } from './task-share-dialog';
123
123
  import type { TaskFilters } from './types';
124
124
  import { UnsavedChangesWarningDialog } from './unsaved-changes-warning-dialog';
125
125
 
126
+ type AssigneeMemberSource = 'workspace' | 'board' | 'workspace-and-board';
127
+
126
128
  export {
127
129
  type DialogHeaderInfo,
128
130
  getTaskDialogHeaderInfo,
@@ -149,6 +151,8 @@ export interface TaskEditDialogProps {
149
151
  taskLoadError?: boolean;
150
152
  taskHydrationVersion?: number;
151
153
  isPersonalWorkspace?: boolean;
154
+ canUseBoardAssignees?: boolean;
155
+ assigneeMemberSource?: AssigneeMemberSource;
152
156
  parentTaskId?: string;
153
157
  parentTaskName?: string;
154
158
  pendingRelationship?: PendingRelationship;
@@ -189,6 +193,8 @@ export function TaskEditDialog({
189
193
  taskLoadError = false,
190
194
  taskHydrationVersion = 0,
191
195
  isPersonalWorkspace = false,
196
+ canUseBoardAssignees,
197
+ assigneeMemberSource,
192
198
  parentTaskId,
193
199
  parentTaskName,
194
200
  pendingRelationship,
@@ -494,6 +500,8 @@ export function TaskEditDialog({
494
500
  isOpen,
495
501
  propAvailableLists,
496
502
  taskSearchQuery,
503
+ canUseBoardAssignees: canUseBoardAssignees ?? !isPersonalWorkspace,
504
+ assigneeMemberSource,
497
505
  sharedContext,
498
506
  });
499
507
  const currentList = availableLists?.find(
@@ -2166,6 +2174,7 @@ export function TaskEditDialog({
2166
2174
  selectedAssignees={formState.selectedAssignees}
2167
2175
  isLoading={isLoading}
2168
2176
  isPersonalWorkspace={isPersonalWorkspace}
2177
+ canUseBoardAssignees={canUseBoardAssignees ?? !isPersonalWorkspace}
2169
2178
  totalDuration={formState.totalDuration}
2170
2179
  isSplittable={formState.isSplittable}
2171
2180
  minSplitDurationMinutes={formState.minSplitDurationMinutes}
@@ -2258,10 +2267,11 @@ export function TaskEditDialog({
2258
2267
  <Dialog open={isOpen} onOpenChange={handleDialogOpenChange} modal={true}>
2259
2268
  <DialogContent
2260
2269
  showCloseButton={false}
2270
+ presentation={showCompactDialog ? 'default' : 'fullscreen'}
2261
2271
  className={
2262
2272
  showCompactDialog
2263
2273
  ? 'w-[min(calc(100vw-2rem),30rem)] max-w-[30rem] gap-0 overflow-visible rounded-lg border p-0 shadow-xl'
2264
- : 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-out-to-bottom-2 data-[state=open]:slide-in-from-bottom-2 inset-0! top-0! left-0! flex h-screen max-h-screen w-screen max-w-none! translate-x-0! translate-y-0! gap-0 rounded-none! border-0 p-0'
2274
+ : undefined
2265
2275
  }
2266
2276
  onContextMenu={(e) => {
2267
2277
  if (shouldPreserveNativeContextMenu(e.target)) {
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
3
  import { useQuery } from '@tanstack/react-query';
4
- import { Loader2 } from '@tuturuuu/icons';
5
4
  import { getWorkspaceTask } from '@tuturuuu/internal-api/tasks';
6
5
  import { useRouter } from 'next/navigation';
7
6
  import { useTranslations } from 'next-intl';
8
7
  import { useEffect } from 'react';
8
+ import { TaskBoardLoadingState } from './task-board-loading-state';
9
9
  import { buildWorkspaceTaskUrl } from './task-url';
10
10
 
11
11
  interface TaskLegacyRouteRecoveryProps {
@@ -61,12 +61,5 @@ export function TaskLegacyRouteRecovery({
61
61
  );
62
62
  }
63
63
 
64
- return (
65
- <div className="flex min-h-[40vh] items-center justify-center p-6">
66
- <div className="flex items-center gap-3 text-muted-foreground">
67
- <Loader2 className="h-5 w-5 animate-spin" />
68
- <span>{t('loading')}</span>
69
- </div>
70
- </div>
71
- );
64
+ return <TaskBoardLoadingState />;
72
65
  }
@@ -41,6 +41,7 @@ import {
41
41
  TaskSchedulingMenu,
42
42
  } from '../boards/boardId/menus';
43
43
  import { useTaskDialog } from '../hooks/useTaskDialog';
44
+ import type { TaskAssigneeMemberSource } from '../providers/task-dialog-provider';
44
45
  import { useTasksHref } from '../tasks-route-context';
45
46
 
46
47
  interface TaskRowActionsMenuProps {
@@ -49,6 +50,8 @@ interface TaskRowActionsMenuProps {
49
50
  workspaceId: string;
50
51
  lists: TaskList[];
51
52
  isPersonalWorkspace?: boolean;
53
+ canUseBoardAssignees?: boolean;
54
+ assigneeMemberSource?: TaskAssigneeMemberSource;
52
55
  onUpdate: () => void;
53
56
  open?: boolean;
54
57
  onOpenChange?: (open: boolean) => void;
@@ -78,6 +81,8 @@ export function TaskRowActionsMenu({
78
81
  workspaceId,
79
82
  lists,
80
83
  isPersonalWorkspace = false,
84
+ canUseBoardAssignees,
85
+ assigneeMemberSource,
81
86
  onUpdate,
82
87
  open,
83
88
  onOpenChange,
@@ -171,6 +176,12 @@ export function TaskRowActionsMenu({
171
176
  taskWorkspacePersonal: task.source_workspace_id
172
177
  ? false
173
178
  : isPersonalWorkspace,
179
+ canUseBoardAssignees:
180
+ canUseBoardAssignees ??
181
+ (task.source_workspace_id ? true : !isPersonalWorkspace),
182
+ assigneeMemberSource: task.source_workspace_id
183
+ ? 'workspace'
184
+ : assigneeMemberSource,
174
185
  }
175
186
  );
176
187
  setMenuOpen(false);