@tuturuuu/ui 0.2.0 → 0.3.2

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 (129) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/package.json +79 -67
  3. package/src/components/ui/__tests__/avatar.test.tsx +8 -5
  4. package/src/components/ui/calendar-app/components/calendar-connections-compact.tsx +414 -0
  5. package/src/components/ui/calendar-app/components/calendar-connections-manager.tsx +5 -1
  6. package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +529 -0
  7. package/src/components/ui/calendar-app/components/calendar-connections-unified.tsx +26 -1429
  8. package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +711 -0
  9. package/src/components/ui/chart.test.tsx +29 -0
  10. package/src/components/ui/chart.tsx +12 -3
  11. package/src/components/ui/chat/chat-agent-details-operations-panel.test.tsx +396 -2
  12. package/src/components/ui/chat/chat-agent-details-operations-panel.tsx +36 -8
  13. package/src/components/ui/chat/chat-agent-details-setup-panel.tsx +14 -0
  14. package/src/components/ui/chat/chat-agent-details-sidebar.test.tsx +5 -0
  15. package/src/components/ui/chat/chat-agent-details-sidebar.tsx +21 -7
  16. package/src/components/ui/chat/chat-agent-details-utils.test.ts +73 -0
  17. package/src/components/ui/chat/chat-agent-details-utils.tsx +100 -26
  18. package/src/components/ui/chat/chat-agent-details-zalo-personal-panel.tsx +517 -0
  19. package/src/components/ui/chat/chat-workspace.tsx +31 -1
  20. package/src/components/ui/chat/hooks-messages.test.tsx +45 -1
  21. package/src/components/ui/chat/hooks-messages.ts +1 -1
  22. package/src/components/ui/chat/hooks-realtime.ts +13 -16
  23. package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +24 -1
  24. package/src/components/ui/custom/__tests__/tuturuuu-logo.test.ts +12 -3
  25. package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +39 -0
  26. package/src/components/ui/custom/common-footer.tsx +16 -1
  27. package/src/components/ui/custom/production-indicator.tsx +1 -1
  28. package/src/components/ui/custom/settings/sidebar-settings.tsx +1 -1
  29. package/src/components/ui/custom/settings/task-settings.tsx +18 -0
  30. package/src/components/ui/custom/settings-dialog-shell.tsx +38 -23
  31. package/src/components/ui/custom/sidebar-context-compile-graph.test.ts +60 -0
  32. package/src/components/ui/custom/sidebar-context.tsx +61 -61
  33. package/src/components/ui/custom/sidebar-remote-behavior-bridge.tsx +123 -0
  34. package/src/components/ui/custom/tuturuuu-logo-urls.ts +6 -0
  35. package/src/components/ui/custom/tuturuuu-logo.tsx +25 -7
  36. package/src/components/ui/custom/workspace-select-helpers.ts +20 -0
  37. package/src/components/ui/custom/workspace-select.tsx +33 -12
  38. package/src/components/ui/finance/invoices/components/invoice-checkout-summary.tsx +7 -1
  39. package/src/components/ui/finance/invoices/components/invoice-payment-settings.tsx +3 -0
  40. package/src/components/ui/finance/invoices/components/invoice-products-permission-warning.tsx +58 -0
  41. package/src/components/ui/finance/invoices/components/subscription-group-selector.tsx +12 -20
  42. package/src/components/ui/finance/invoices/hooks/use-subscription-auto-selection.ts +10 -9
  43. package/src/components/ui/finance/invoices/hooks/use-subscription-invoice-content.ts +10 -5
  44. package/src/components/ui/finance/invoices/hooks.ts +75 -20
  45. package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +137 -0
  46. package/src/components/ui/finance/invoices/new-invoice-page.tsx +86 -37
  47. package/src/components/ui/finance/invoices/product-selection.test.tsx +8 -26
  48. package/src/components/ui/finance/invoices/product-selection.tsx +2 -10
  49. package/src/components/ui/finance/invoices/standard-invoice.tsx +88 -26
  50. package/src/components/ui/finance/invoices/subscription-invoice.tsx +154 -46
  51. package/src/components/ui/finance/invoices/utils.test.ts +50 -0
  52. package/src/components/ui/finance/invoices/utils.ts +75 -17
  53. package/src/components/ui/finance/shared/finance-display-amount.tsx +3 -1
  54. package/src/components/ui/finance/shared/finance-permission-warning-dialog.test.tsx +34 -0
  55. package/src/components/ui/finance/shared/finance-permission-warning-dialog.tsx +157 -0
  56. package/src/components/ui/finance/transactions/form-basic-tab.tsx +8 -0
  57. package/src/components/ui/finance/transactions/form-more-tab.tsx +8 -0
  58. package/src/components/ui/finance/transactions/form-types.ts +2 -0
  59. package/src/components/ui/finance/transactions/form.test.tsx +43 -0
  60. package/src/components/ui/finance/transactions/form.tsx +60 -0
  61. package/src/components/ui/finance/transactions/infinite-transactions-list.tsx +27 -0
  62. package/src/components/ui/finance/transactions/transactions-create-summary.tsx +13 -1
  63. package/src/components/ui/finance/transactions/transactions-infinite-page.tsx +4 -0
  64. package/src/components/ui/finance/transactions/transactions-page.tsx +23 -1
  65. package/src/components/ui/finance/wallets/walletId/wallet-details-actions.tsx +4 -0
  66. package/src/components/ui/finance/wallets/walletId/wallet-details-page.tsx +5 -0
  67. package/src/components/ui/legacy/calendar/calendar-content.tsx +9 -1
  68. package/src/components/ui/legacy/calendar/event-modal.tsx +146 -2
  69. package/src/components/ui/legacy/calendar/event-preview-popover.tsx +200 -0
  70. package/src/components/ui/legacy/calendar/smart-calendar.test.tsx +76 -0
  71. package/src/components/ui/legacy/calendar/smart-calendar.tsx +13 -1
  72. package/src/components/ui/legacy/meet/page.test.ts +180 -0
  73. package/src/components/ui/legacy/meet/page.tsx +87 -39
  74. package/src/components/ui/tu-do/boards/boardId/board-column.tsx +79 -25
  75. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/__tests__/bulk-mutations-external-workspaces.test.tsx +392 -0
  76. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-actions-island.test.tsx +57 -0
  77. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-actions-island.tsx +106 -0
  78. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-clear-delete.ts +106 -161
  79. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-relations-assignees.ts +96 -150
  80. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-relations-labels.ts +63 -79
  81. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-relations-projects.ts +64 -83
  82. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-updates.ts +115 -155
  83. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operation-utils.ts +319 -2
  84. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operations.ts +8 -1
  85. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +63 -37
  86. package/src/components/ui/tu-do/boards/boardId/kanban/kanban-column-collapse.ts +16 -0
  87. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +46 -0
  88. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +5 -3
  89. package/src/components/ui/tu-do/boards/boardId/kanban.tsx +19 -7
  90. package/src/components/ui/tu-do/boards/boardId/menus/__tests__/task-menus.test.tsx +181 -2
  91. package/src/components/ui/tu-do/boards/boardId/menus/index.ts +1 -0
  92. package/src/components/ui/tu-do/boards/boardId/menus/task-scheduling-menu.tsx +463 -0
  93. package/src/components/ui/tu-do/boards/boardId/menus/task-scheduling-utils.ts +109 -0
  94. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +4 -0
  95. package/src/components/ui/tu-do/boards/boardId/task-card/TaskCardCheckbox.tsx +6 -3
  96. package/src/components/ui/tu-do/boards/boardId/task-card/TaskCardDates.tsx +26 -9
  97. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-checkbox-style.ts +39 -0
  98. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.test.ts +43 -0
  99. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.ts +33 -0
  100. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-completion-checkbox-visibility.test.ts +31 -0
  101. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-completion-checkbox-visibility.ts +9 -0
  102. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-identifier-row.test.tsx +124 -0
  103. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-identifier-row.tsx +88 -0
  104. package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +151 -76
  105. package/src/components/ui/tu-do/boards/boardId/task-card/task-scheduling-badge.tsx +174 -0
  106. package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +34 -13
  107. package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +54 -1
  108. package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +158 -0
  109. package/src/components/ui/tu-do/shared/__tests__/task-dialog-manager.test.tsx +5 -2
  110. package/src/components/ui/tu-do/shared/board-client.tsx +12 -2
  111. package/src/components/ui/tu-do/shared/board-views.tsx +195 -328
  112. package/src/components/ui/tu-do/shared/list-view.tsx +18 -8
  113. package/src/components/ui/tu-do/shared/task-due-date-visibility.test.ts +72 -0
  114. package/src/components/ui/tu-do/shared/task-due-date-visibility.ts +38 -0
  115. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +6 -3
  116. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-save.ts +2 -2
  117. package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +33 -0
  118. package/src/hooks/__tests__/use-calendar-readonly.test.tsx +74 -3
  119. package/src/hooks/__tests__/use-task-actions.test.tsx +118 -0
  120. package/src/hooks/__tests__/use-user-config.test.tsx +65 -0
  121. package/src/hooks/__tests__/use-workspace-presence.test.tsx +1 -1
  122. package/src/hooks/use-calendar-sync.tsx +22 -277
  123. package/src/hooks/use-calendar.tsx +95 -525
  124. package/src/hooks/use-semantic-task-search.ts +10 -33
  125. package/src/hooks/use-task-actions.ts +43 -117
  126. package/src/hooks/use-user-config.ts +1 -1
  127. package/src/hooks/use-workspace-config.ts +6 -2
  128. package/src/hooks/use-workspace-presence.ts +1 -1
  129. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-actions-bar.tsx +0 -94
@@ -1,7 +1,7 @@
1
1
  import '@testing-library/jest-dom';
2
2
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
3
  import { act, render, screen, waitFor } from '@testing-library/react';
4
- import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
5
  import {
6
6
  getActiveBoardRefresh,
7
7
  setActiveBoardRefresh,
@@ -84,6 +84,10 @@ describe('BoardClient', () => {
84
84
  setActiveBoardRefresh(null);
85
85
  });
86
86
 
87
+ afterEach(() => {
88
+ vi.restoreAllMocks();
89
+ });
90
+
87
91
  it('loads dependent board data with the fetched board workspace id', async () => {
88
92
  const queryClient = new QueryClient({
89
93
  defaultOptions: {
@@ -149,4 +153,53 @@ describe('BoardClient', () => {
149
153
  });
150
154
  expect(revalidateLoadedListsMock).toHaveBeenCalledTimes(1);
151
155
  });
156
+
157
+ it('throttles focus-driven list revalidation for thirty seconds', async () => {
158
+ const nowSpy = vi.spyOn(Date, 'now').mockReturnValue(100_000);
159
+ const queryClient = new QueryClient({
160
+ defaultOptions: {
161
+ queries: {
162
+ retry: false,
163
+ },
164
+ },
165
+ });
166
+
167
+ render(
168
+ <QueryClientProvider client={queryClient}>
169
+ <BoardClient
170
+ boardId="board-1"
171
+ workspace={{ id: 'workspace-uuid', personal: false } as any}
172
+ currentUserId="user-1"
173
+ />
174
+ </QueryClientProvider>
175
+ );
176
+
177
+ expect(await screen.findByTestId('board-views')).toBeInTheDocument();
178
+
179
+ await act(async () => {
180
+ window.dispatchEvent(new Event('focus'));
181
+ });
182
+
183
+ await waitFor(() => {
184
+ expect(revalidateLoadedListsMock).toHaveBeenCalledTimes(1);
185
+ });
186
+
187
+ nowSpy.mockReturnValue(101_500);
188
+
189
+ await act(async () => {
190
+ window.dispatchEvent(new Event('focus'));
191
+ });
192
+
193
+ expect(revalidateLoadedListsMock).toHaveBeenCalledTimes(1);
194
+
195
+ nowSpy.mockReturnValue(130_000);
196
+
197
+ await act(async () => {
198
+ window.dispatchEvent(new Event('focus'));
199
+ });
200
+
201
+ await waitFor(() => {
202
+ expect(revalidateLoadedListsMock).toHaveBeenCalledTimes(2);
203
+ });
204
+ });
152
205
  });
@@ -135,6 +135,19 @@ const mockLists: TaskList[] = [
135
135
  },
136
136
  ];
137
137
 
138
+ const closedList: TaskList = {
139
+ archived: false,
140
+ board_id: 'board-1',
141
+ color: 'PURPLE',
142
+ created_at: '2026-03-07T00:00:00.000Z',
143
+ creator_id: 'user-1',
144
+ deleted: false,
145
+ id: 'list-closed',
146
+ name: 'Closed',
147
+ position: 2,
148
+ status: 'closed',
149
+ };
150
+
138
151
  const mockTasks: Task[] = [
139
152
  {
140
153
  assignees: [],
@@ -154,6 +167,7 @@ const mockTasks: Task[] = [
154
167
  const mockWorkspaceLabels: WorkspaceLabel[] = [];
155
168
 
156
169
  function renderBoardViews(overrides?: {
170
+ idleBottomIsland?: React.ReactNode;
157
171
  lists?: TaskList[];
158
172
  tasks?: Task[];
159
173
  workspace?: { id: string; personal: boolean };
@@ -176,6 +190,7 @@ function renderBoardViews(overrides?: {
176
190
  tasks={overrides?.tasks ?? mockTasks}
177
191
  workspace={(overrides?.workspace ?? mockWorkspace) as any}
178
192
  workspaceLabels={mockWorkspaceLabels}
193
+ idleBottomIsland={overrides?.idleBottomIsland}
179
194
  />
180
195
  </HotkeysProvider>
181
196
  </QueryClientProvider>
@@ -237,6 +252,51 @@ describe('BoardViews', () => {
237
252
  });
238
253
  });
239
254
 
255
+ it('toggles the idle bottom island around active kanban bulk selection', async () => {
256
+ renderBoardViews({
257
+ idleBottomIsland: <div data-testid="idle-bottom-island" />,
258
+ });
259
+
260
+ expect(screen.getByTestId('idle-bottom-island')).toBeInTheDocument();
261
+
262
+ act(() => {
263
+ kanbanBoardProps?.onBulkSelectionActiveChange?.(true);
264
+ });
265
+
266
+ expect(screen.queryByTestId('idle-bottom-island')).toBeNull();
267
+
268
+ act(() => {
269
+ kanbanBoardProps?.onBulkSelectionActiveChange?.(false);
270
+ });
271
+
272
+ expect(screen.getByTestId('idle-bottom-island')).toBeInTheDocument();
273
+ });
274
+
275
+ it('keeps the idle bottom island visible outside kanban view', async () => {
276
+ renderBoardViews({
277
+ idleBottomIsland: <div data-testid="idle-bottom-island" />,
278
+ });
279
+
280
+ act(() => {
281
+ kanbanBoardProps?.onBulkSelectionActiveChange?.(true);
282
+ boardHeaderProps?.onViewChange('list');
283
+ });
284
+
285
+ await waitFor(() => {
286
+ expect(screen.getByTestId('list-view')).toBeInTheDocument();
287
+ });
288
+ expect(screen.getByTestId('idle-bottom-island')).toBeInTheDocument();
289
+
290
+ act(() => {
291
+ boardHeaderProps?.onViewChange('timeline');
292
+ });
293
+
294
+ await waitFor(() => {
295
+ expect(screen.getByTestId('timeline-view')).toBeInTheDocument();
296
+ });
297
+ expect(screen.getByTestId('idle-bottom-island')).toBeInTheDocument();
298
+ });
299
+
240
300
  it('creates a task from the first visible list with the board filters when pressing C', () => {
241
301
  renderBoardViews();
242
302
 
@@ -358,6 +418,63 @@ describe('BoardViews', () => {
358
418
  });
359
419
  });
360
420
 
421
+ it('collapses closed task lists by default', () => {
422
+ renderBoardViews({
423
+ lists: [...mockLists, closedList],
424
+ });
425
+
426
+ expect(
427
+ kanbanBoardProps?.lists.find((list) => list.id === 'list-closed')
428
+ ).toEqual(
429
+ expect.objectContaining({
430
+ is_collapsed: true,
431
+ status: 'closed',
432
+ })
433
+ );
434
+ });
435
+
436
+ it('persists the collapsed closed task list state per board and list', async () => {
437
+ window.localStorage.setItem(
438
+ 'task-board-closed-list-collapsed:board-1:list-closed',
439
+ 'false'
440
+ );
441
+
442
+ renderBoardViews({
443
+ lists: [...mockLists, closedList],
444
+ });
445
+
446
+ await waitFor(() => {
447
+ expect(
448
+ kanbanBoardProps?.lists.find((list) => list.id === 'list-closed')
449
+ ).toEqual(
450
+ expect.objectContaining({
451
+ is_collapsed: false,
452
+ status: 'closed',
453
+ })
454
+ );
455
+ });
456
+
457
+ act(() => {
458
+ kanbanBoardProps?.onTaskListCollapsedChange?.('list-closed', true);
459
+ });
460
+
461
+ await waitFor(() => {
462
+ expect(
463
+ window.localStorage.getItem(
464
+ 'task-board-closed-list-collapsed:board-1:list-closed'
465
+ )
466
+ ).toBe('true');
467
+ expect(
468
+ kanbanBoardProps?.lists.find((list) => list.id === 'list-closed')
469
+ ).toEqual(
470
+ expect.objectContaining({
471
+ is_collapsed: true,
472
+ status: 'closed',
473
+ })
474
+ );
475
+ });
476
+ });
477
+
361
478
  it('excludes deleted lists from active board views and create shortcuts', () => {
362
479
  const listsWithDeletedFirst: TaskList[] = [
363
480
  {
@@ -500,6 +617,47 @@ describe('BoardViews', () => {
500
617
  });
501
618
  });
502
619
 
620
+ it('uses server-side search counts to hide task lists without matching tasks', async () => {
621
+ listWorkspaceTasksMock.mockImplementation(async (_workspaceId, options) => {
622
+ if (options?.includeListCounts) {
623
+ return {
624
+ listCounts: [{ count: 1, list_id: 'list-1' }],
625
+ tasks: [],
626
+ };
627
+ }
628
+
629
+ return { tasks: [mockTasks[0]!] };
630
+ });
631
+
632
+ renderBoardViews();
633
+
634
+ act(() => {
635
+ boardHeaderProps?.onFiltersChange({
636
+ ...boardHeaderProps.filters,
637
+ estimationRange: { max: 5, min: 2 },
638
+ searchQuery: 'TIMELINE',
639
+ });
640
+ });
641
+
642
+ await waitFor(() => {
643
+ expect(listWorkspaceTasksMock).toHaveBeenCalledWith(
644
+ 'ws-1',
645
+ expect.objectContaining({
646
+ boardId: 'board-1',
647
+ estimationMax: 5,
648
+ estimationMin: 2,
649
+ includeListCounts: true,
650
+ limit: 0,
651
+ q: 'TIMELINE',
652
+ })
653
+ );
654
+ });
655
+
656
+ await waitFor(() => {
657
+ expect(kanbanBoardProps?.lists).toEqual([mockLists[0]]);
658
+ });
659
+ });
660
+
503
661
  it('does not auto-load progressive list pages for server-backed source scopes', async () => {
504
662
  progressivePagination = {
505
663
  'list-1': {
@@ -52,17 +52,20 @@ const {
52
52
 
53
53
  vi.mock('@tuturuuu/internal-api', () => ({
54
54
  getCurrentUserProfile: mockGetCurrentUserProfile,
55
- listWorkspaceLabels: mockListWorkspaceLabels,
56
- listWorkspaceMembers: mockListWorkspaceMembers,
57
55
  }));
58
56
 
59
57
  vi.mock('@tuturuuu/internal-api/tasks', () => ({
60
58
  getCurrentUserTask: mockGetCurrentUserTask,
61
59
  getWorkspaceTask: mockGetWorkspaceTask,
60
+ listWorkspaceLabels: mockListWorkspaceLabels,
62
61
  listWorkspaceTaskProjectsByIds: mockListWorkspaceTaskProjectsByIds,
63
62
  resolveTaskProjectWorkspaceId: mockResolveTaskProjectWorkspaceId,
64
63
  }));
65
64
 
65
+ vi.mock('@tuturuuu/internal-api/workspaces', () => ({
66
+ listWorkspaceMembers: mockListWorkspaceMembers,
67
+ }));
68
+
66
69
  vi.mock('@tuturuuu/supabase/next/client', () => ({
67
70
  createClient: vi.fn(() => ({
68
71
  auth: {
@@ -14,7 +14,7 @@ import type { TaskList } from '@tuturuuu/types/primitives/TaskList';
14
14
  import { useBoardRealtime } from '@tuturuuu/ui/hooks/useBoardRealtime';
15
15
  import { useWorkspaceLabels } from '@tuturuuu/utils/task-helper';
16
16
  import { useRouter } from 'next/navigation';
17
- import { useCallback, useEffect, useMemo } from 'react';
17
+ import { type ReactNode, useCallback, useEffect, useMemo } from 'react';
18
18
  import {
19
19
  BoardBroadcastProvider,
20
20
  type BoardRefreshOptions,
@@ -26,16 +26,20 @@ import { ProgressiveLoaderProvider } from './progressive-loader-context';
26
26
  import { dispatchRecentSidebarVisit } from './recent-sidebar-events';
27
27
  import { useProgressiveBoardLoader } from './use-progressive-board-loader';
28
28
 
29
+ const BOARD_REVALIDATE_COOLDOWN_MS = 30_000;
30
+
29
31
  interface Props {
30
32
  boardId: string;
31
33
  workspace: Workspace;
32
34
  workspaceTier?: WorkspaceProductTier | null;
33
35
  currentUserId?: string;
34
36
  routePrefix?: string;
37
+ idleBottomIsland?: ReactNode;
35
38
  }
36
39
 
37
40
  export function BoardClient({
38
41
  boardId,
42
+ idleBottomIsland,
39
43
  workspace,
40
44
  workspaceTier,
41
45
  currentUserId,
@@ -100,7 +104,12 @@ export function BoardClient({
100
104
 
101
105
  const revalidateLoadedLists = () => {
102
106
  const now = Date.now();
103
- if (isRevalidating || now - lastRevalidateAt < 1500) return;
107
+ if (
108
+ isRevalidating ||
109
+ now - lastRevalidateAt < BOARD_REVALIDATE_COOLDOWN_MS
110
+ ) {
111
+ return;
112
+ }
104
113
 
105
114
  isRevalidating = true;
106
115
  lastRevalidateAt = now;
@@ -261,6 +270,7 @@ export function BoardClient({
261
270
  workspaceLabels={workspaceLabels}
262
271
  currentUserId={currentUserId}
263
272
  canManageBoard={canManageBoard}
273
+ idleBottomIsland={idleBottomIsland}
264
274
  />
265
275
  </ProgressiveLoaderProvider>
266
276
  </BoardBroadcastProvider>