@tuturuuu/ui 0.1.0 → 0.3.1
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.
- package/CHANGELOG.md +71 -0
- package/package.json +82 -70
- package/src/components/ui/__tests__/avatar.test.tsx +8 -5
- package/src/components/ui/calendar-app/components/calendar-connections-compact.tsx +414 -0
- package/src/components/ui/calendar-app/components/calendar-connections-manager.tsx +5 -1
- package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +529 -0
- package/src/components/ui/calendar-app/components/calendar-connections-unified.tsx +26 -1429
- package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +711 -0
- package/src/components/ui/chart.test.tsx +29 -0
- package/src/components/ui/chart.tsx +12 -3
- package/src/components/ui/chat/chat-agent-details-external-thread-panel.test.tsx +43 -13
- package/src/components/ui/chat/chat-agent-details-external-thread-panel.tsx +138 -74
- package/src/components/ui/chat/chat-agent-details-operations-panel.test.tsx +70 -0
- package/src/components/ui/chat/chat-agent-details-operations-panel.tsx +60 -1
- package/src/components/ui/chat/chat-agent-details-sidebar.tsx +13 -5
- package/src/components/ui/chat/chat-sidebar-panel.test.tsx +110 -0
- package/src/components/ui/chat/chat-sidebar-panel.tsx +13 -3
- package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +24 -1
- package/src/components/ui/custom/__tests__/tuturuuu-logo.test.ts +12 -3
- package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +39 -0
- package/src/components/ui/custom/common-footer.tsx +16 -1
- package/src/components/ui/custom/production-indicator.tsx +1 -1
- package/src/components/ui/custom/settings/sidebar-settings.tsx +1 -1
- package/src/components/ui/custom/settings/task-settings.tsx +18 -0
- package/src/components/ui/custom/settings-dialog-shell.tsx +38 -23
- package/src/components/ui/custom/sidebar-context-compile-graph.test.ts +60 -0
- package/src/components/ui/custom/sidebar-context.tsx +61 -61
- package/src/components/ui/custom/sidebar-remote-behavior-bridge.tsx +123 -0
- package/src/components/ui/custom/tuturuuu-logo-urls.ts +6 -0
- package/src/components/ui/custom/tuturuuu-logo.tsx +25 -7
- package/src/components/ui/custom/workspace-select-helpers.ts +20 -0
- package/src/components/ui/custom/workspace-select.tsx +33 -12
- package/src/components/ui/finance/invoices/components/invoice-checkout-summary.tsx +7 -1
- package/src/components/ui/finance/invoices/components/invoice-payment-settings.tsx +3 -0
- package/src/components/ui/finance/invoices/components/invoice-products-permission-warning.tsx +58 -0
- package/src/components/ui/finance/invoices/components/subscription-group-selector.tsx +12 -20
- package/src/components/ui/finance/invoices/hooks/use-subscription-auto-selection.ts +10 -9
- package/src/components/ui/finance/invoices/hooks/use-subscription-invoice-content.ts +10 -5
- package/src/components/ui/finance/invoices/hooks.ts +75 -20
- package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +137 -0
- package/src/components/ui/finance/invoices/new-invoice-page.tsx +86 -37
- package/src/components/ui/finance/invoices/product-selection.test.tsx +8 -26
- package/src/components/ui/finance/invoices/product-selection.tsx +2 -10
- package/src/components/ui/finance/invoices/standard-invoice.tsx +88 -26
- package/src/components/ui/finance/invoices/subscription-invoice.tsx +154 -46
- package/src/components/ui/finance/invoices/utils.test.ts +50 -0
- package/src/components/ui/finance/invoices/utils.ts +75 -17
- package/src/components/ui/finance/shared/finance-display-amount.tsx +3 -1
- package/src/components/ui/finance/shared/finance-permission-warning-dialog.test.tsx +34 -0
- package/src/components/ui/finance/shared/finance-permission-warning-dialog.tsx +157 -0
- package/src/components/ui/finance/transactions/form-basic-tab.tsx +8 -0
- package/src/components/ui/finance/transactions/form-more-tab.tsx +8 -0
- package/src/components/ui/finance/transactions/form-types.ts +2 -0
- package/src/components/ui/finance/transactions/form.test.tsx +43 -0
- package/src/components/ui/finance/transactions/form.tsx +60 -0
- package/src/components/ui/finance/transactions/infinite-transactions-list.tsx +27 -0
- package/src/components/ui/finance/transactions/transactions-create-summary.tsx +13 -1
- package/src/components/ui/finance/transactions/transactions-infinite-page.tsx +4 -0
- package/src/components/ui/finance/transactions/transactions-page.tsx +23 -1
- package/src/components/ui/finance/wallets/walletId/wallet-details-actions.tsx +4 -0
- package/src/components/ui/finance/wallets/walletId/wallet-details-page.tsx +5 -0
- package/src/components/ui/legacy/calendar/calendar-content.tsx +9 -1
- package/src/components/ui/legacy/calendar/event-modal.tsx +146 -2
- package/src/components/ui/legacy/calendar/event-preview-popover.tsx +200 -0
- package/src/components/ui/legacy/calendar/smart-calendar.test.tsx +76 -0
- package/src/components/ui/legacy/calendar/smart-calendar.tsx +13 -1
- package/src/components/ui/legacy/meet/page.test.ts +180 -0
- package/src/components/ui/legacy/meet/page.tsx +87 -39
- package/src/components/ui/legacy/meet/planId/page.tsx +10 -4
- package/src/components/ui/text-editor/__tests__/task-mention-chip.test.tsx +203 -6
- package/src/components/ui/text-editor/task-mention-chip.tsx +29 -7
- package/src/components/ui/tu-do/boards/boardId/board-column.tsx +79 -25
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/__tests__/bulk-mutations-external-workspaces.test.tsx +392 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-actions-island.test.tsx +57 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-actions-island.tsx +106 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-clear-delete.ts +106 -161
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-relations-assignees.ts +96 -150
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-relations-labels.ts +63 -79
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-relations-projects.ts +64 -83
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-updates.ts +115 -155
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operation-utils.ts +319 -2
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operations.ts +8 -1
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +63 -37
- package/src/components/ui/tu-do/boards/boardId/kanban/kanban-column-collapse.ts +16 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +46 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +5 -3
- package/src/components/ui/tu-do/boards/boardId/kanban.tsx +19 -7
- package/src/components/ui/tu-do/boards/boardId/menus/__tests__/task-menus.test.tsx +181 -2
- package/src/components/ui/tu-do/boards/boardId/menus/index.ts +1 -0
- package/src/components/ui/tu-do/boards/boardId/menus/task-scheduling-menu.tsx +463 -0
- package/src/components/ui/tu-do/boards/boardId/menus/task-scheduling-utils.ts +109 -0
- package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +4 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/TaskCardCheckbox.tsx +6 -3
- package/src/components/ui/tu-do/boards/boardId/task-card/TaskCardDates.tsx +26 -9
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-checkbox-style.ts +39 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.test.ts +43 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.ts +33 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-completion-checkbox-visibility.test.ts +31 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-completion-checkbox-visibility.ts +9 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-identifier-row.test.tsx +124 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-identifier-row.tsx +88 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +151 -76
- package/src/components/ui/tu-do/boards/boardId/task-card/task-scheduling-badge.tsx +174 -0
- package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +34 -13
- package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +54 -1
- package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +158 -0
- package/src/components/ui/tu-do/shared/__tests__/task-dialog-manager.test.tsx +5 -2
- package/src/components/ui/tu-do/shared/board-client.tsx +12 -2
- package/src/components/ui/tu-do/shared/board-views.tsx +195 -328
- package/src/components/ui/tu-do/shared/list-view.tsx +18 -8
- package/src/components/ui/tu-do/shared/task-due-date-visibility.test.ts +72 -0
- package/src/components/ui/tu-do/shared/task-due-date-visibility.ts +38 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/__tests__/use-task-realtime-sync.test.tsx +37 -9
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +6 -3
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-realtime-sync.ts +89 -70
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-save.ts +2 -2
- package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +33 -0
- package/src/hooks/__tests__/use-calendar-readonly.test.tsx +74 -3
- package/src/hooks/__tests__/use-task-actions.test.tsx +118 -0
- package/src/hooks/__tests__/use-user-config.test.tsx +65 -0
- package/src/hooks/__tests__/use-workspace-presence.test.tsx +1 -1
- package/src/hooks/use-calendar-sync.tsx +22 -277
- package/src/hooks/use-calendar.tsx +95 -525
- package/src/hooks/use-task-actions.ts +43 -117
- package/src/hooks/use-user-config.ts +1 -1
- package/src/hooks/use-workspace-config.ts +6 -2
- package/src/hooks/use-workspace-presence.ts +1 -1
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-actions-bar.tsx +0 -94
|
@@ -94,6 +94,24 @@ export function useTaskActions({
|
|
|
94
94
|
return resolveWorkspaceIdForTask(task);
|
|
95
95
|
}, [resolveWorkspaceIdForTask, task]);
|
|
96
96
|
|
|
97
|
+
const getEffectiveTaskIds = useCallback(
|
|
98
|
+
(taskRecord?: Task) => {
|
|
99
|
+
if (!taskRecord) return [];
|
|
100
|
+
|
|
101
|
+
if (
|
|
102
|
+
isMultiSelectMode &&
|
|
103
|
+
selectedTasks &&
|
|
104
|
+
selectedTasks.size > 1 &&
|
|
105
|
+
selectedTasks.has(taskRecord.id)
|
|
106
|
+
) {
|
|
107
|
+
return Array.from(selectedTasks);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return [taskRecord.id];
|
|
111
|
+
},
|
|
112
|
+
[isMultiSelectMode, selectedTasks]
|
|
113
|
+
);
|
|
114
|
+
|
|
97
115
|
const getExternalMoveOptions = useCallback((targetList: TaskList) => {
|
|
98
116
|
const options: {
|
|
99
117
|
sourceStatus?: TaskBoardStatus;
|
|
@@ -389,13 +407,8 @@ export function useTaskActions({
|
|
|
389
407
|
|
|
390
408
|
setIsLoading(true);
|
|
391
409
|
|
|
392
|
-
|
|
393
|
-
const shouldBulkMove =
|
|
394
|
-
isMultiSelectMode &&
|
|
395
|
-
selectedTasks &&
|
|
396
|
-
selectedTasks.size > 1 &&
|
|
397
|
-
selectedTasks.has(task.id);
|
|
398
|
-
const tasksToMove = shouldBulkMove ? Array.from(selectedTasks) : [task.id];
|
|
410
|
+
const tasksToMove = getEffectiveTaskIds(task);
|
|
411
|
+
const shouldBulkMove = tasksToMove.length > 1;
|
|
399
412
|
|
|
400
413
|
// Store previous state for rollback
|
|
401
414
|
const previousTasks = queryClient.getQueryData<Task[]>(['tasks', boardId]);
|
|
@@ -515,8 +528,7 @@ export function useTaskActions({
|
|
|
515
528
|
task?.id,
|
|
516
529
|
setIsLoading,
|
|
517
530
|
setMenuOpen,
|
|
518
|
-
|
|
519
|
-
selectedTasks,
|
|
531
|
+
getEffectiveTaskIds,
|
|
520
532
|
queryClient,
|
|
521
533
|
boardId,
|
|
522
534
|
task,
|
|
@@ -531,13 +543,8 @@ export function useTaskActions({
|
|
|
531
543
|
|
|
532
544
|
setIsLoading(true);
|
|
533
545
|
|
|
534
|
-
|
|
535
|
-
const shouldBulkMove =
|
|
536
|
-
isMultiSelectMode &&
|
|
537
|
-
selectedTasks &&
|
|
538
|
-
selectedTasks.size > 1 &&
|
|
539
|
-
selectedTasks.has(task.id);
|
|
540
|
-
const tasksToMove = shouldBulkMove ? Array.from(selectedTasks) : [task.id];
|
|
546
|
+
const tasksToMove = getEffectiveTaskIds(task);
|
|
547
|
+
const shouldBulkMove = tasksToMove.length > 1;
|
|
541
548
|
|
|
542
549
|
// Store previous state for rollback
|
|
543
550
|
const previousTasks = queryClient.getQueryData<Task[]>(['tasks', boardId]);
|
|
@@ -649,8 +656,7 @@ export function useTaskActions({
|
|
|
649
656
|
task?.id,
|
|
650
657
|
setIsLoading,
|
|
651
658
|
setMenuOpen,
|
|
652
|
-
|
|
653
|
-
selectedTasks,
|
|
659
|
+
getEffectiveTaskIds,
|
|
654
660
|
queryClient,
|
|
655
661
|
boardId,
|
|
656
662
|
task,
|
|
@@ -664,15 +670,7 @@ export function useTaskActions({
|
|
|
664
670
|
if (!task) return;
|
|
665
671
|
setIsLoading(true);
|
|
666
672
|
|
|
667
|
-
|
|
668
|
-
const shouldBulkDelete =
|
|
669
|
-
isMultiSelectMode &&
|
|
670
|
-
selectedTasks &&
|
|
671
|
-
selectedTasks.size > 1 &&
|
|
672
|
-
selectedTasks.has(task.id);
|
|
673
|
-
const tasksToDelete = shouldBulkDelete
|
|
674
|
-
? Array.from(selectedTasks)
|
|
675
|
-
: [task.id];
|
|
673
|
+
const tasksToDelete = getEffectiveTaskIds(task);
|
|
676
674
|
|
|
677
675
|
const now = new Date().toISOString();
|
|
678
676
|
|
|
@@ -777,8 +775,7 @@ export function useTaskActions({
|
|
|
777
775
|
task?.id,
|
|
778
776
|
setIsLoading,
|
|
779
777
|
setDeleteDialogOpen,
|
|
780
|
-
|
|
781
|
-
selectedTasks,
|
|
778
|
+
getEffectiveTaskIds,
|
|
782
779
|
queryClient,
|
|
783
780
|
boardId,
|
|
784
781
|
task,
|
|
@@ -923,15 +920,8 @@ export function useTaskActions({
|
|
|
923
920
|
|
|
924
921
|
setIsLoading(true);
|
|
925
922
|
|
|
926
|
-
|
|
927
|
-
const shouldBulkMove =
|
|
928
|
-
isMultiSelectMode &&
|
|
929
|
-
selectedTasks &&
|
|
930
|
-
selectedTasks.size > 1 &&
|
|
931
|
-
selectedTasks.has(task.id);
|
|
932
|
-
const tasksToMove = shouldBulkMove
|
|
933
|
-
? Array.from(selectedTasks)
|
|
934
|
-
: [task.id];
|
|
923
|
+
const tasksToMove = getEffectiveTaskIds(task);
|
|
924
|
+
const shouldBulkMove = tasksToMove.length > 1;
|
|
935
925
|
|
|
936
926
|
// Store previous state for rollback
|
|
937
927
|
const previousTasks = queryClient.getQueryData<Task[]>([
|
|
@@ -1127,8 +1117,7 @@ export function useTaskActions({
|
|
|
1127
1117
|
availableLists,
|
|
1128
1118
|
setIsLoading,
|
|
1129
1119
|
setMenuOpen,
|
|
1130
|
-
|
|
1131
|
-
selectedTasks,
|
|
1120
|
+
getEffectiveTaskIds,
|
|
1132
1121
|
queryClient,
|
|
1133
1122
|
boardId,
|
|
1134
1123
|
task,
|
|
@@ -1150,15 +1139,7 @@ export function useTaskActions({
|
|
|
1150
1139
|
newDate = target.toISOString();
|
|
1151
1140
|
}
|
|
1152
1141
|
|
|
1153
|
-
|
|
1154
|
-
const shouldBulkUpdate =
|
|
1155
|
-
isMultiSelectMode &&
|
|
1156
|
-
selectedTasks &&
|
|
1157
|
-
selectedTasks.size > 1 &&
|
|
1158
|
-
selectedTasks.has(task.id);
|
|
1159
|
-
const tasksToUpdate = shouldBulkUpdate
|
|
1160
|
-
? Array.from(selectedTasks)
|
|
1161
|
-
: [task.id];
|
|
1142
|
+
const tasksToUpdate = getEffectiveTaskIds(task);
|
|
1162
1143
|
|
|
1163
1144
|
setIsLoading(true);
|
|
1164
1145
|
|
|
@@ -1260,8 +1241,7 @@ export function useTaskActions({
|
|
|
1260
1241
|
task?.id,
|
|
1261
1242
|
setIsLoading,
|
|
1262
1243
|
getWorkspaceId,
|
|
1263
|
-
|
|
1264
|
-
selectedTasks,
|
|
1244
|
+
getEffectiveTaskIds,
|
|
1265
1245
|
queryClient,
|
|
1266
1246
|
boardId,
|
|
1267
1247
|
task,
|
|
@@ -1274,26 +1254,7 @@ export function useTaskActions({
|
|
|
1274
1254
|
if (!task) return;
|
|
1275
1255
|
if (newPriority === task.priority && !isMultiSelectMode) return;
|
|
1276
1256
|
|
|
1277
|
-
|
|
1278
|
-
const shouldBulkUpdate =
|
|
1279
|
-
isMultiSelectMode &&
|
|
1280
|
-
selectedTasks &&
|
|
1281
|
-
selectedTasks.size > 1 &&
|
|
1282
|
-
selectedTasks.has(task.id);
|
|
1283
|
-
const tasksToUpdate = shouldBulkUpdate
|
|
1284
|
-
? Array.from(selectedTasks)
|
|
1285
|
-
: [task.id];
|
|
1286
|
-
|
|
1287
|
-
console.log('🎯 handlePriorityChange called:', {
|
|
1288
|
-
taskId: task.id,
|
|
1289
|
-
newPriority,
|
|
1290
|
-
isMultiSelectMode,
|
|
1291
|
-
selectedTasksSize: selectedTasks?.size,
|
|
1292
|
-
selectedTasksArray: Array.from(selectedTasks || []),
|
|
1293
|
-
shouldBulkUpdate,
|
|
1294
|
-
tasksToUpdate,
|
|
1295
|
-
tasksToUpdateCount: tasksToUpdate.length,
|
|
1296
|
-
});
|
|
1257
|
+
const tasksToUpdate = getEffectiveTaskIds(task);
|
|
1297
1258
|
|
|
1298
1259
|
setIsLoading(true);
|
|
1299
1260
|
|
|
@@ -1318,12 +1279,6 @@ export function useTaskActions({
|
|
|
1318
1279
|
const succeededTaskIds: string[] = [];
|
|
1319
1280
|
const workspaceId = await getWorkspaceId();
|
|
1320
1281
|
|
|
1321
|
-
console.log('🔄 Executing sequential API updates:', {
|
|
1322
|
-
tasksToUpdate,
|
|
1323
|
-
count: tasksToUpdate.length,
|
|
1324
|
-
priority: newPriority,
|
|
1325
|
-
});
|
|
1326
|
-
|
|
1327
1282
|
for (const taskId of tasksToUpdate) {
|
|
1328
1283
|
try {
|
|
1329
1284
|
await updateWorkspaceTask(workspaceId, taskId, {
|
|
@@ -1338,11 +1293,6 @@ export function useTaskActions({
|
|
|
1338
1293
|
}
|
|
1339
1294
|
}
|
|
1340
1295
|
|
|
1341
|
-
console.log('✅ Sequential update result:', {
|
|
1342
|
-
successCount: succeededTaskIds.length,
|
|
1343
|
-
totalTasks: tasksToUpdate.length,
|
|
1344
|
-
});
|
|
1345
|
-
|
|
1346
1296
|
if (succeededTaskIds.length === 0) {
|
|
1347
1297
|
throw new Error('Failed to update any tasks');
|
|
1348
1298
|
}
|
|
@@ -1392,7 +1342,7 @@ export function useTaskActions({
|
|
|
1392
1342
|
|
|
1393
1343
|
// Don't auto-clear selection - let user manually clear with "Clear" button
|
|
1394
1344
|
} catch (error) {
|
|
1395
|
-
console.error('
|
|
1345
|
+
console.error('Failed to update priority:', error);
|
|
1396
1346
|
// Rollback on error
|
|
1397
1347
|
if (previousTasks) {
|
|
1398
1348
|
queryClient.setQueryData(['tasks', boardId], previousTasks);
|
|
@@ -1409,12 +1359,12 @@ export function useTaskActions({
|
|
|
1409
1359
|
task?.priority,
|
|
1410
1360
|
setIsLoading,
|
|
1411
1361
|
getWorkspaceId,
|
|
1412
|
-
|
|
1413
|
-
selectedTasks,
|
|
1362
|
+
getEffectiveTaskIds,
|
|
1414
1363
|
queryClient,
|
|
1415
1364
|
boardId,
|
|
1416
1365
|
task,
|
|
1417
1366
|
broadcast,
|
|
1367
|
+
isMultiSelectMode,
|
|
1418
1368
|
]
|
|
1419
1369
|
);
|
|
1420
1370
|
|
|
@@ -1423,20 +1373,11 @@ export function useTaskActions({
|
|
|
1423
1373
|
if (!task) return;
|
|
1424
1374
|
if (points === task.estimation_points && !isMultiSelectMode) return;
|
|
1425
1375
|
|
|
1426
|
-
// Check if we're in multi-select mode and have multiple tasks selected
|
|
1427
|
-
const shouldBulkUpdate =
|
|
1428
|
-
isMultiSelectMode &&
|
|
1429
|
-
selectedTasks &&
|
|
1430
|
-
selectedTasks.size > 1 &&
|
|
1431
|
-
selectedTasks.has(task.id);
|
|
1432
|
-
|
|
1433
1376
|
// Get current tasks from cache to filter out ones that already have the target value
|
|
1434
1377
|
const currentTasks = queryClient.getQueryData<Task[]>(['tasks', boardId]);
|
|
1435
1378
|
|
|
1436
1379
|
// Filter tasks that actually need updating (don't already have the target estimation)
|
|
1437
|
-
const candidateTasks =
|
|
1438
|
-
? Array.from(selectedTasks)
|
|
1439
|
-
: [task.id];
|
|
1380
|
+
const candidateTasks = getEffectiveTaskIds(task);
|
|
1440
1381
|
|
|
1441
1382
|
const tasksToUpdate = currentTasks
|
|
1442
1383
|
? candidateTasks.filter((taskId) => {
|
|
@@ -1556,7 +1497,7 @@ export function useTaskActions({
|
|
|
1556
1497
|
setEstimationSaving,
|
|
1557
1498
|
getWorkspaceId,
|
|
1558
1499
|
isMultiSelectMode,
|
|
1559
|
-
|
|
1500
|
+
getEffectiveTaskIds,
|
|
1560
1501
|
queryClient,
|
|
1561
1502
|
boardId,
|
|
1562
1503
|
task,
|
|
@@ -1587,12 +1528,7 @@ export function useTaskActions({
|
|
|
1587
1528
|
setIsLoading(true);
|
|
1588
1529
|
setCustomDateDialogOpen?.(false); // Close dialog immediately when date is selected
|
|
1589
1530
|
|
|
1590
|
-
|
|
1591
|
-
const shouldBulkUpdate =
|
|
1592
|
-
isMultiSelectMode &&
|
|
1593
|
-
selectedTasks &&
|
|
1594
|
-
selectedTasks.size > 1 &&
|
|
1595
|
-
selectedTasks.has(task.id);
|
|
1531
|
+
const shouldBulkUpdate = getEffectiveTaskIds(task).length > 1;
|
|
1596
1532
|
|
|
1597
1533
|
if (shouldBulkUpdate && bulkUpdateCustomDueDate) {
|
|
1598
1534
|
// Use the centralized bulk update function from useBulkOperations
|
|
@@ -1655,8 +1591,7 @@ export function useTaskActions({
|
|
|
1655
1591
|
getWorkspaceId,
|
|
1656
1592
|
setIsLoading,
|
|
1657
1593
|
setCustomDateDialogOpen,
|
|
1658
|
-
|
|
1659
|
-
selectedTasks,
|
|
1594
|
+
getEffectiveTaskIds,
|
|
1660
1595
|
bulkUpdateCustomDueDate,
|
|
1661
1596
|
task,
|
|
1662
1597
|
queryClient,
|
|
@@ -1676,16 +1611,8 @@ export function useTaskActions({
|
|
|
1676
1611
|
task)
|
|
1677
1612
|
: task;
|
|
1678
1613
|
|
|
1679
|
-
|
|
1680
|
-
const shouldBulkUpdate =
|
|
1681
|
-
isMultiSelectMode &&
|
|
1682
|
-
selectedTasks &&
|
|
1683
|
-
selectedTasks.size > 1 &&
|
|
1684
|
-
selectedTasks.has(currentTask.id);
|
|
1685
|
-
|
|
1686
|
-
const tasksToUpdate = shouldBulkUpdate
|
|
1687
|
-
? Array.from(selectedTasks)
|
|
1688
|
-
: [currentTask.id];
|
|
1614
|
+
const tasksToUpdate = getEffectiveTaskIds(currentTask);
|
|
1615
|
+
const shouldBulkUpdate = tasksToUpdate.length > 1;
|
|
1689
1616
|
|
|
1690
1617
|
setIsLoading(true);
|
|
1691
1618
|
|
|
@@ -1703,7 +1630,7 @@ export function useTaskActions({
|
|
|
1703
1630
|
|
|
1704
1631
|
if (shouldBulkUpdate && previousTasks) {
|
|
1705
1632
|
const selectedTasksData = previousTasks.filter((t) =>
|
|
1706
|
-
|
|
1633
|
+
tasksToUpdate.includes(t.id)
|
|
1707
1634
|
);
|
|
1708
1635
|
// Only mark as active (to remove) if ALL selected tasks have the assignee
|
|
1709
1636
|
active = selectedTasksData.every((t) =>
|
|
@@ -1891,8 +1818,7 @@ export function useTaskActions({
|
|
|
1891
1818
|
boardId,
|
|
1892
1819
|
queryClient,
|
|
1893
1820
|
setIsLoading,
|
|
1894
|
-
|
|
1895
|
-
selectedTasks,
|
|
1821
|
+
getEffectiveTaskIds,
|
|
1896
1822
|
broadcast,
|
|
1897
1823
|
getWorkspaceId,
|
|
1898
1824
|
]
|
|
@@ -89,7 +89,7 @@ export function useUserBooleanConfig(
|
|
|
89
89
|
);
|
|
90
90
|
const updateConfig = useUpdateUserConfig();
|
|
91
91
|
|
|
92
|
-
const value = rawValue === 'true';
|
|
92
|
+
const value = rawValue === undefined ? defaultValue : rawValue === 'true';
|
|
93
93
|
|
|
94
94
|
const setValue = (newValue: boolean) => {
|
|
95
95
|
updateConfig.mutate({ configId, value: newValue ? 'true' : 'false' });
|
|
@@ -28,7 +28,10 @@ export const useWorkspaceConfig = <T>(
|
|
|
28
28
|
});
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
export const useWorkspaceConfigs = (
|
|
31
|
+
export const useWorkspaceConfigs = (
|
|
32
|
+
wsId: string,
|
|
33
|
+
configIds: readonly string[]
|
|
34
|
+
) => {
|
|
32
35
|
return useQuery({
|
|
33
36
|
queryKey: ['workspace-configs', wsId, configIds],
|
|
34
37
|
queryFn: async () => {
|
|
@@ -43,7 +46,8 @@ export const useWorkspaceConfigs = (wsId: string, configIds: string[]) => {
|
|
|
43
46
|
return data ?? {};
|
|
44
47
|
},
|
|
45
48
|
enabled: !!wsId && configIds.length > 0,
|
|
46
|
-
staleTime:
|
|
49
|
+
staleTime: 5 * 60_000,
|
|
47
50
|
placeholderData: (previousData) => previousData,
|
|
51
|
+
refetchOnWindowFocus: false,
|
|
48
52
|
});
|
|
49
53
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { getCurrentUserProfile } from '@tuturuuu/internal-api';
|
|
3
|
+
import { getCurrentUserProfile } from '@tuturuuu/internal-api/users';
|
|
4
4
|
import { createClient } from '@tuturuuu/supabase/next/client';
|
|
5
5
|
import type { RealtimePresenceState } from '@tuturuuu/supabase/next/realtime';
|
|
6
6
|
import type { User } from '@tuturuuu/types/primitives/User';
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { ArrowRightLeft, Check, MoreHorizontal } from '@tuturuuu/icons';
|
|
4
|
-
import { Badge } from '@tuturuuu/ui/badge';
|
|
5
|
-
import { Button } from '@tuturuuu/ui/button';
|
|
6
|
-
import { DropdownMenu, DropdownMenuTrigger } from '@tuturuuu/ui/dropdown-menu';
|
|
7
|
-
import { useTranslations } from 'next-intl';
|
|
8
|
-
import { BulkActionsMenu } from './bulk-actions-menu';
|
|
9
|
-
|
|
10
|
-
interface BulkActionsBarProps {
|
|
11
|
-
selectedCount: number;
|
|
12
|
-
isMultiSelectMode: boolean;
|
|
13
|
-
bulkWorking: boolean;
|
|
14
|
-
modKey: string;
|
|
15
|
-
onClearSelection: () => void;
|
|
16
|
-
onOpenBoardSelector: () => void;
|
|
17
|
-
menuProps: React.ComponentProps<typeof BulkActionsMenu>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function BulkActionsBar({
|
|
21
|
-
selectedCount,
|
|
22
|
-
isMultiSelectMode,
|
|
23
|
-
bulkWorking,
|
|
24
|
-
modKey,
|
|
25
|
-
onClearSelection,
|
|
26
|
-
onOpenBoardSelector,
|
|
27
|
-
menuProps,
|
|
28
|
-
}: BulkActionsBarProps) {
|
|
29
|
-
const t = useTranslations();
|
|
30
|
-
const tc = useTranslations('common');
|
|
31
|
-
|
|
32
|
-
if (!isMultiSelectMode) return null;
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<div className="flex flex-wrap items-center justify-between gap-3 border-b bg-linear-to-r from-primary/5 via-primary/3 to-transparent px-4 py-3 shadow-sm">
|
|
36
|
-
<div className="flex flex-wrap items-center gap-3 text-xs md:text-sm">
|
|
37
|
-
<div className="flex items-center gap-2 rounded-full bg-primary/10 px-3 py-1 ring-1 ring-primary/20">
|
|
38
|
-
<Check className="h-3.5 w-3.5 text-primary" />
|
|
39
|
-
<span className="font-semibold text-primary">
|
|
40
|
-
{selectedCount}{' '}
|
|
41
|
-
{selectedCount === 1 ? tc('task') : tc('tasks_plural')}
|
|
42
|
-
</span>
|
|
43
|
-
</div>
|
|
44
|
-
<span className="hidden text-muted-foreground text-xs sm:inline">
|
|
45
|
-
{tc('selection_instruction', { modKey })}
|
|
46
|
-
</span>
|
|
47
|
-
{bulkWorking && (
|
|
48
|
-
<Badge
|
|
49
|
-
variant="outline"
|
|
50
|
-
className="animate-pulse border-dynamic-blue/40 text-[10px]"
|
|
51
|
-
>
|
|
52
|
-
{t('common.working')}
|
|
53
|
-
</Badge>
|
|
54
|
-
)}
|
|
55
|
-
</div>
|
|
56
|
-
<div className="flex flex-wrap items-center gap-2">
|
|
57
|
-
<DropdownMenu>
|
|
58
|
-
<DropdownMenuTrigger asChild>
|
|
59
|
-
<Button
|
|
60
|
-
variant="outline"
|
|
61
|
-
size="sm"
|
|
62
|
-
className="h-6 px-2 text-xs"
|
|
63
|
-
disabled={bulkWorking}
|
|
64
|
-
>
|
|
65
|
-
<MoreHorizontal className="mr-1 h-3 w-3" />{' '}
|
|
66
|
-
{t('common.bulk_actions')}
|
|
67
|
-
</Button>
|
|
68
|
-
</DropdownMenuTrigger>
|
|
69
|
-
<BulkActionsMenu {...menuProps} />
|
|
70
|
-
</DropdownMenu>
|
|
71
|
-
|
|
72
|
-
<Button
|
|
73
|
-
variant="outline"
|
|
74
|
-
size="sm"
|
|
75
|
-
onClick={onOpenBoardSelector}
|
|
76
|
-
className="h-6 px-2 text-xs"
|
|
77
|
-
disabled={selectedCount === 0 || bulkWorking}
|
|
78
|
-
>
|
|
79
|
-
<ArrowRightLeft className="mr-1 h-3 w-3" />
|
|
80
|
-
{t('common.move')}
|
|
81
|
-
</Button>
|
|
82
|
-
<Button
|
|
83
|
-
variant="ghost"
|
|
84
|
-
size="sm"
|
|
85
|
-
onClick={onClearSelection}
|
|
86
|
-
className="h-6 px-2 text-xs"
|
|
87
|
-
disabled={bulkWorking}
|
|
88
|
-
>
|
|
89
|
-
{t('common.clear')}
|
|
90
|
-
</Button>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
);
|
|
94
|
-
}
|