@tuturuuu/ui 0.30.2 → 0.31.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.
- package/CHANGELOG.md +41 -0
- package/biome.json +1 -1
- package/package.json +95 -49
- package/src/components/ui/calendar-app/calendar-client-page.test.tsx +57 -0
- package/src/components/ui/calendar-app/calendar-client-page.tsx +13 -4
- package/src/components/ui/calendar-app/calendar-page-shell.tsx +7 -1
- package/src/components/ui/calendar-app/components/calendar-connections-compact.tsx +47 -39
- package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +14 -0
- package/src/components/ui/calendar-app/components/calendar-connections-unified.tsx +4 -0
- package/src/components/ui/calendar-app/components/calendar-sync-attention-button.tsx +47 -0
- package/src/components/ui/calendar-app/components/calendar-sync-recovery.test.tsx +112 -0
- package/src/components/ui/calendar-app/components/calendar-sync-recovery.tsx +206 -0
- package/src/components/ui/calendar-app/components/calendar-types.ts +1 -1
- package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +86 -90
- package/src/components/ui/custom/language-dropdown-item.tsx +6 -14
- package/src/components/ui/custom/nav-link.tsx +7 -7
- package/src/components/ui/custom/nav.tsx +15 -63
- package/src/components/ui/custom/notification-card.tsx +361 -0
- package/src/components/ui/custom/notification-list.tsx +178 -0
- package/src/components/ui/custom/notification-popover-client.tsx +12 -780
- package/src/components/ui/custom/notification-runtime.tsx +23 -0
- package/src/components/ui/custom/onboarding-settings-panel.tsx +8 -55
- package/src/components/ui/custom/satellite-account-switcher-menu.tsx +212 -0
- package/src/components/ui/custom/satellite-brand.tsx +122 -0
- package/src/components/ui/custom/satellite-content.tsx +148 -0
- package/src/components/ui/custom/satellite-footer-actions.tsx +350 -0
- package/src/components/ui/custom/satellite-language-item.tsx +26 -0
- package/src/components/ui/custom/satellite-navigation.tsx +86 -0
- package/src/components/ui/custom/satellite-notification-popover.tsx +272 -0
- package/src/components/ui/custom/satellite-onboarding-settings-panel.tsx +80 -0
- package/src/components/ui/custom/satellite-settings-dialog-shell.tsx +621 -0
- package/src/components/ui/custom/satellite-shell-utils.ts +163 -0
- package/src/components/ui/custom/satellite-shell.test.tsx +169 -0
- package/src/components/ui/custom/satellite-shell.tsx +50 -0
- package/src/components/ui/custom/satellite-theme-dropdown-items.tsx +92 -0
- package/src/components/ui/custom/satellite-user-menu-items.tsx +190 -0
- package/src/components/ui/custom/satellite-user-menu.tsx +93 -0
- package/src/components/ui/custom/satellite-workspace-section.tsx +46 -0
- package/src/components/ui/custom/settings/keyboard-shortcuts-settings.tsx +16 -0
- package/src/components/ui/custom/settings-dialog-shell.tsx +21 -600
- package/src/components/ui/custom/sidebar-context.tsx +5 -14
- package/src/components/ui/custom/sidebar-footer-actions.tsx +19 -322
- package/src/components/ui/custom/structure.tsx +14 -0
- package/src/components/ui/custom/system-language-dropdown-item.tsx +7 -14
- package/src/components/ui/custom/theme-dropdown-items.tsx +2 -85
- package/src/components/ui/custom/use-satellite-shell.tsx +165 -0
- package/src/components/ui/legacy/calendar/agenda-view.tsx +139 -47
- package/src/components/ui/legacy/calendar/calendar-content.test.tsx +116 -0
- package/src/components/ui/legacy/calendar/calendar-content.tsx +38 -74
- package/src/components/ui/legacy/calendar/calendar-event-tone.ts +20 -0
- package/src/components/ui/legacy/calendar/calendar-meeting-link.test.ts +27 -0
- package/src/components/ui/legacy/calendar/calendar-meeting-link.ts +34 -0
- package/src/components/ui/legacy/calendar/calendar-period.ts +28 -0
- package/src/components/ui/legacy/calendar/calendar-shortcuts.test.tsx +107 -0
- package/src/components/ui/legacy/calendar/calendar-views.test.tsx +169 -0
- package/src/components/ui/legacy/calendar/event-modal-header.tsx +52 -0
- package/src/components/ui/legacy/calendar/event-modal.tsx +107 -156
- package/src/components/ui/legacy/calendar/month-calendar.tsx +242 -933
- package/src/components/ui/legacy/calendar/save-calendar-event-drafts.test.ts +25 -0
- package/src/components/ui/legacy/calendar/save-calendar-event-drafts.ts +32 -0
- package/src/components/ui/legacy/calendar/smart-calendar.tsx +3 -0
- package/src/components/ui/legacy/calendar/use-calendar-view-shortcuts.ts +54 -0
- package/src/components/ui/legacy/calendar/use-event-draft-session.test.tsx +59 -0
- package/src/components/ui/legacy/calendar/use-event-draft-session.ts +20 -0
- package/src/components/ui/legacy/calendar/year-calendar.tsx +34 -16
- package/src/components/ui/pwa-status.test.tsx +53 -0
- package/src/components/ui/pwa-status.tsx +113 -0
- package/src/components/ui/report-problem-dialog-content.tsx +350 -0
- package/src/components/ui/report-problem-dialog.tsx +6 -975
- package/src/components/ui/report-problem-model.ts +133 -0
- package/src/components/ui/report-problem-mutation.ts +122 -0
- package/src/components/ui/save-notification.test.tsx +36 -0
- package/src/components/ui/save-notification.tsx +17 -0
- package/src/components/ui/use-report-problem.ts +488 -0
- package/src/declarations.d.ts +2 -0
- package/src/hooks/__tests__/use-calendar-readonly.test.tsx +46 -4
- package/src/hooks/__tests__/use-calendar-sync.test.tsx +24 -0
- package/src/hooks/calendar-date-utils.ts +11 -0
- package/src/hooks/calendar-event-lookup.test.ts +77 -0
- package/src/hooks/calendar-event-lookup.ts +47 -0
- package/src/hooks/calendar-range-cache.ts +52 -0
- package/src/hooks/pwa-install-prompt.ts +44 -0
- package/src/hooks/use-calendar-sync.tsx +23 -100
- package/src/hooks/use-calendar.tsx +21 -77
- package/src/hooks/use-notifications.ts +9 -24
- package/src/hooks/use-open-initial-calendar-event.ts +27 -0
- package/src/hooks/use-settings-dialog-shortcut.test.tsx +41 -0
- package/src/hooks/use-settings-dialog-shortcut.ts +12 -14
- package/src/hooks/use-workspace-presence.ts +0 -18
- package/src/lib/tasks-app-url.test.ts +25 -0
- package/src/lib/tasks-app-url.ts +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.31.0](https://github.com/tutur3u/platform/compare/ui-v0.30.2...ui-v0.31.0) (2026-09-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **calendar:** add installable apps and bounded PWA caching ([f4b2a1c](https://github.com/tutur3u/platform/commit/f4b2a1cf7943783fddc45f537df73589f19594f6))
|
|
9
|
+
* **calendar:** add installable Tasks and Calendar with bounded caching ([#5231](https://github.com/tutur3u/platform/issues/5231)) ([7078824](https://github.com/tutur3u/platform/commit/70788244874d811da3e1ce3a9af2c9389739a8c3))
|
|
10
|
+
* **colab:** launch multiplayer prompt workshops on Cloudflare ([7a4a3f9](https://github.com/tutur3u/platform/commit/7a4a3f9b4a12a0d7439cdb296398a21c0cd8939f))
|
|
11
|
+
* **colab:** make workshops a login-first workspace ([89613ca](https://github.com/tutur3u/platform/commit/89613ca10de53fe39412c58342ee453cd0db4006))
|
|
12
|
+
* **colab:** reuse the shared Tuturuuu structure shell ([11ca1fa](https://github.com/tutur3u/platform/commit/11ca1fa35bba8a64fdb9b56972b5c0f11c87339f))
|
|
13
|
+
* **meet:** integrate instant rooms with Calendar ([9631fd1](https://github.com/tutur3u/platform/commit/9631fd1373615f3e8be55dd028d54b441e78a023))
|
|
14
|
+
* **meet:** integrate instant rooms with Calendar ([#5248](https://github.com/tutur3u/platform/issues/5248)) ([5f3e77d](https://github.com/tutur3u/platform/commit/5f3e77df20e636fe270cdc7d1b1d88817a3f00bd))
|
|
15
|
+
* **planning:** integrate tasks and calendar workflows ([454bb45](https://github.com/tutur3u/platform/commit/454bb4589cdc85967a75a1cb04e01dd004223cbd))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **calendar:** align view controls and stabilize event pagination ([0497af1](https://github.com/tutur3u/platform/commit/0497af126102a59d1d12af6615505a98a2ccb6a7))
|
|
21
|
+
* **calendar:** contain month cell content on mobile ([a3518bb](https://github.com/tutur3u/platform/commit/a3518bbbe90009f87f6a7f38078027996bdcb3a3))
|
|
22
|
+
* **calendar:** expose sync failures and repair completion tracking ([a5601a5](https://github.com/tutur3u/platform/commit/a5601a5f0fd33741392a6f6e16dad337ba4f0a35))
|
|
23
|
+
* **calendar:** fail closed on linked event access ([9071075](https://github.com/tutur3u/platform/commit/90710750398ff0143f2a71f2b19c8631469018e9))
|
|
24
|
+
* **calendar:** handle partial sync in every client action ([b820bbc](https://github.com/tutur3u/platform/commit/b820bbcdb725e38c13342eed96062b2f4a0afacb))
|
|
25
|
+
* **calendar:** harden PWA lifecycle and cache retention ([14565c0](https://github.com/tutur3u/platform/commit/14565c0106e74b947e152fd8bb787de7f70bc54d))
|
|
26
|
+
* **calendar:** import sync helper from calendar entry point ([753dd22](https://github.com/tutur3u/platform/commit/753dd22ab9a480144ee94384aa9983d58787d311))
|
|
27
|
+
* **calendar:** initialize draft timezone helper ([e1b81c7](https://github.com/tutur3u/platform/commit/e1b81c75b8aef6d9ded2c162511f0c32b03b7db1))
|
|
28
|
+
* **calendar:** make sync failures visible and recoverable ([#5227](https://github.com/tutur3u/platform/issues/5227)) ([465c9f8](https://github.com/tutur3u/platform/commit/465c9f82c5464a54675fa9d9f814c630902916e6))
|
|
29
|
+
* **calendar:** preserve concurrent connection updates ([8307cbb](https://github.com/tutur3u/platform/commit/8307cbbc5d0ccb943eee77a259ab76147c1c698c))
|
|
30
|
+
* **calendar:** recover failed syncs and redesign calendar views ([7d22948](https://github.com/tutur3u/platform/commit/7d22948095a29d236f698d42dde362fc38311dd0))
|
|
31
|
+
* **calendar:** recover failed syncs and redesign calendar views ([#5230](https://github.com/tutur3u/platform/issues/5230)) ([e52605d](https://github.com/tutur3u/platform/commit/e52605d671f921b1564746afcdedf2478deee78e))
|
|
32
|
+
* **calendar:** respect week preferences and classify DNS failures ([ff88780](https://github.com/tutur3u/platform/commit/ff88780dc3d25edb46b5e15ee323d8eee3ad26db))
|
|
33
|
+
* **calendar:** restore provider assets in tasks and format sync time ([0359132](https://github.com/tutur3u/platform/commit/0359132f96947aaeeb02bb776af3d2a24794e0b2))
|
|
34
|
+
* **calendar:** show sync recovery with sidebar navigation ([033e04b](https://github.com/tutur3u/platform/commit/033e04bb44d8b1ca466ad0638e9525ca96c84202))
|
|
35
|
+
* **colab:** complete shared profile and footer controls ([4cc8959](https://github.com/tutur3u/platform/commit/4cc895951d9181f86972362ca864e4aa2bba9ed2))
|
|
36
|
+
* **colab:** preserve Next.js account menu parity ([1910015](https://github.com/tutur3u/platform/commit/19100151cb43220277d0970047fc8903d942348e))
|
|
37
|
+
* **meet:** make Calendar scheduling atomic ([aa3a4cc](https://github.com/tutur3u/platform/commit/aa3a4cc46ccdfccfa7648923bcd8207a7a91467f))
|
|
38
|
+
* **meet:** make Calendar scheduling atomic ([#5249](https://github.com/tutur3u/platform/issues/5249)) ([a2914ca](https://github.com/tutur3u/platform/commit/a2914cabde82b4f9a5549801807f73e9d2c728b0))
|
|
39
|
+
* **planning:** repair embedded APIs and simplify navigation ([5e82d77](https://github.com/tutur3u/platform/commit/5e82d77e183c5603d04cbe76bf3bba8bf3a94eca))
|
|
40
|
+
* **tasks:** preserve calendar drafts and recover failed task creation ([#5237](https://github.com/tutur3u/platform/issues/5237)) ([2b9acbf](https://github.com/tutur3u/platform/commit/2b9acbfcb19edff9680f4eb2c5c5b18a0e56ec8b))
|
|
41
|
+
* **tasks:** preserve task and calendar drafts until saves finish ([34b4902](https://github.com/tutur3u/platform/commit/34b4902b0382a3aa9e10249a0d83205c9a530878))
|
|
42
|
+
* **tasks:** recover partial saves and display actionable errors ([c4887c9](https://github.com/tutur3u/platform/commit/c4887c98377fd8493f3e6ae4219763d8872e2a5b))
|
|
43
|
+
|
|
3
44
|
## [0.30.2](https://github.com/tutur3u/platform/compare/ui-v0.30.1...ui-v0.30.2) (2026-08-31)
|
|
4
45
|
|
|
5
46
|
|
package/biome.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuturuuu/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -60,40 +60,40 @@
|
|
|
60
60
|
"@tanstack/react-query": "^5.102.8",
|
|
61
61
|
"@tanstack/react-table": "^9.2.3",
|
|
62
62
|
"@tanstack/react-virtual": "^3.14.10",
|
|
63
|
-
"@tiptap/core": "3.
|
|
64
|
-
"@tiptap/extension-collaboration": "3.
|
|
65
|
-
"@tiptap/extension-collaboration-caret": "3.
|
|
66
|
-
"@tiptap/extension-color": "3.
|
|
67
|
-
"@tiptap/extension-details": "3.
|
|
68
|
-
"@tiptap/extension-drag-handle": "3.
|
|
69
|
-
"@tiptap/extension-drag-handle-react": "3.
|
|
70
|
-
"@tiptap/extension-highlight": "3.
|
|
71
|
-
"@tiptap/extension-horizontal-rule": "3.
|
|
72
|
-
"@tiptap/extension-image": "3.
|
|
73
|
-
"@tiptap/extension-link": "3.
|
|
74
|
-
"@tiptap/extension-list": "3.
|
|
75
|
-
"@tiptap/extension-node-range": "3.
|
|
76
|
-
"@tiptap/extension-placeholder": "3.
|
|
77
|
-
"@tiptap/extension-strike": "3.
|
|
78
|
-
"@tiptap/extension-subscript": "3.
|
|
79
|
-
"@tiptap/extension-superscript": "3.
|
|
80
|
-
"@tiptap/extension-table": "3.
|
|
81
|
-
"@tiptap/extension-table-cell": "3.
|
|
82
|
-
"@tiptap/extension-table-header": "3.
|
|
83
|
-
"@tiptap/extension-table-row": "3.
|
|
84
|
-
"@tiptap/extension-text-align": "3.
|
|
85
|
-
"@tiptap/extension-text-style": "3.
|
|
86
|
-
"@tiptap/extension-youtube": "3.
|
|
87
|
-
"@tiptap/pm": "3.
|
|
88
|
-
"@tiptap/react": "3.
|
|
89
|
-
"@tiptap/starter-kit": "3.
|
|
90
|
-
"@tuturuuu/ai": "0.
|
|
63
|
+
"@tiptap/core": "3.31.2",
|
|
64
|
+
"@tiptap/extension-collaboration": "3.31.2",
|
|
65
|
+
"@tiptap/extension-collaboration-caret": "3.31.2",
|
|
66
|
+
"@tiptap/extension-color": "3.31.2",
|
|
67
|
+
"@tiptap/extension-details": "3.31.2",
|
|
68
|
+
"@tiptap/extension-drag-handle": "3.31.2",
|
|
69
|
+
"@tiptap/extension-drag-handle-react": "3.31.2",
|
|
70
|
+
"@tiptap/extension-highlight": "3.31.2",
|
|
71
|
+
"@tiptap/extension-horizontal-rule": "3.31.2",
|
|
72
|
+
"@tiptap/extension-image": "3.31.2",
|
|
73
|
+
"@tiptap/extension-link": "3.31.2",
|
|
74
|
+
"@tiptap/extension-list": "3.31.2",
|
|
75
|
+
"@tiptap/extension-node-range": "3.31.2",
|
|
76
|
+
"@tiptap/extension-placeholder": "3.31.2",
|
|
77
|
+
"@tiptap/extension-strike": "3.31.2",
|
|
78
|
+
"@tiptap/extension-subscript": "3.31.2",
|
|
79
|
+
"@tiptap/extension-superscript": "3.31.2",
|
|
80
|
+
"@tiptap/extension-table": "3.31.2",
|
|
81
|
+
"@tiptap/extension-table-cell": "3.31.2",
|
|
82
|
+
"@tiptap/extension-table-header": "3.31.2",
|
|
83
|
+
"@tiptap/extension-table-row": "3.31.2",
|
|
84
|
+
"@tiptap/extension-text-align": "3.31.2",
|
|
85
|
+
"@tiptap/extension-text-style": "3.31.2",
|
|
86
|
+
"@tiptap/extension-youtube": "3.31.2",
|
|
87
|
+
"@tiptap/pm": "3.31.2",
|
|
88
|
+
"@tiptap/react": "3.31.2",
|
|
89
|
+
"@tiptap/starter-kit": "3.31.2",
|
|
90
|
+
"@tuturuuu/ai": "0.9.0",
|
|
91
91
|
"@tuturuuu/apis": "0.11.3",
|
|
92
92
|
"@tuturuuu/hooks": "0.1.1",
|
|
93
93
|
"@tuturuuu/icons": "0.1.0",
|
|
94
|
-
"@tuturuuu/internal-api": "0.
|
|
94
|
+
"@tuturuuu/internal-api": "0.34.0",
|
|
95
95
|
"@tuturuuu/supabase": "0.5.1",
|
|
96
|
-
"@tuturuuu/utils": "0.
|
|
96
|
+
"@tuturuuu/utils": "0.28.0",
|
|
97
97
|
"@types/debug": "^4.1.13",
|
|
98
98
|
"browser-image-compression": "^2.0.2",
|
|
99
99
|
"class-variance-authority": "^0.7.1",
|
|
@@ -105,28 +105,28 @@
|
|
|
105
105
|
"debug": "^4.4.3",
|
|
106
106
|
"embla-carousel-react": "^8.6.0",
|
|
107
107
|
"eventemitter3": "^5.0.4",
|
|
108
|
-
"framer-motion": "^13.
|
|
108
|
+
"framer-motion": "^13.2.0",
|
|
109
109
|
"gsap": "^3.15.0",
|
|
110
110
|
"html-entities": "^2.6.0",
|
|
111
|
-
"html2canvas-pro": "^2.4.
|
|
111
|
+
"html2canvas-pro": "^2.4.1",
|
|
112
112
|
"input-otp": "^1.5.0",
|
|
113
|
-
"katex": "^0.18.
|
|
113
|
+
"katex": "^0.18.5",
|
|
114
114
|
"lodash": "4.18.1",
|
|
115
115
|
"moment": "^2.30.1",
|
|
116
|
-
"motion": "^13.
|
|
117
|
-
"next": "^16.3.
|
|
118
|
-
"next-intl": "^4.14.
|
|
116
|
+
"motion": "^13.2.0",
|
|
117
|
+
"next": "^16.3.4",
|
|
118
|
+
"next-intl": "^4.14.2",
|
|
119
119
|
"next-themes": "^0.4.6",
|
|
120
120
|
"nuqs": "^2.10.1",
|
|
121
121
|
"prosemirror-state": "^1.4.4",
|
|
122
122
|
"prosemirror-view": "1.42.3",
|
|
123
123
|
"qrcode.react": "^4.2.0",
|
|
124
124
|
"react": "^19.2.8",
|
|
125
|
-
"react-colorful": "^5.8.
|
|
125
|
+
"react-colorful": "^5.8.1",
|
|
126
126
|
"react-day-picker": "^10.0.1",
|
|
127
127
|
"react-dom": "^19.2.8",
|
|
128
128
|
"react-dropzone": "^20.1.1",
|
|
129
|
-
"react-hook-form": "^7.
|
|
129
|
+
"react-hook-form": "^7.87.0",
|
|
130
130
|
"react-markdown": "^10.1.0",
|
|
131
131
|
"react-papaparse": "^4.4.0",
|
|
132
132
|
"react-pdf": "^10.5.0",
|
|
@@ -145,34 +145,34 @@
|
|
|
145
145
|
"vaul": "^1.1.2",
|
|
146
146
|
"y-protocols": "^1.0.7",
|
|
147
147
|
"yjs": "^13.6.32",
|
|
148
|
-
"zod": "^4.4
|
|
148
|
+
"zod": "^4.5.4"
|
|
149
149
|
},
|
|
150
150
|
"devDependencies": {
|
|
151
151
|
"@tailwindcss/postcss": "^4.3.3",
|
|
152
152
|
"@tailwindcss/typography": "^0.5.20",
|
|
153
153
|
"@tanstack/react-query": "^5.102.8",
|
|
154
|
-
"@tanstack/react-table": "^9.2.
|
|
154
|
+
"@tanstack/react-table": "^9.2.4",
|
|
155
155
|
"@testing-library/jest-dom": "^7.0.1",
|
|
156
156
|
"@testing-library/react": "^16.3.3",
|
|
157
|
-
"@tuturuuu/types": "0.
|
|
157
|
+
"@tuturuuu/types": "0.29.0",
|
|
158
158
|
"@tuturuuu/typescript-config": "0.1.2",
|
|
159
159
|
"@types/html2canvas": "^1.0.0",
|
|
160
160
|
"@types/lodash": "^4.17.25",
|
|
161
|
-
"@types/node": "^26.4.
|
|
161
|
+
"@types/node": "^26.4.1",
|
|
162
162
|
"@types/react": "^19.2.18",
|
|
163
|
-
"@types/react-dom": "^19.2.
|
|
163
|
+
"@types/react-dom": "^19.2.7",
|
|
164
164
|
"@types/react-resizable": "^4.0.0",
|
|
165
165
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
166
166
|
"@types/uuid": "^11.0.0",
|
|
167
167
|
"@vitejs/plugin-react": "^6.1.1",
|
|
168
168
|
"autoprefixer": "^10.5.4",
|
|
169
169
|
"jsdom": "^30.0.1",
|
|
170
|
-
"postcss": "^8.5.
|
|
170
|
+
"postcss": "^8.5.28",
|
|
171
171
|
"postcss-load-config": "^6.0.1",
|
|
172
172
|
"tailwindcss": "^4.3.3",
|
|
173
173
|
"typescript": "7.0.2",
|
|
174
174
|
"uuid": "^14.0.2",
|
|
175
|
-
"vitest": "^
|
|
175
|
+
"vitest": "^5.0.0"
|
|
176
176
|
},
|
|
177
177
|
"peerDependencies": {
|
|
178
178
|
"@tanstack/react-query": "^5.101.2",
|
|
@@ -335,7 +335,8 @@
|
|
|
335
335
|
},
|
|
336
336
|
"./custom/notification-popover-client": {
|
|
337
337
|
"types": "./src/components/ui/custom/notification-popover-client.tsx",
|
|
338
|
-
"import": "./src/components/ui/custom/notification-popover-client.tsx"
|
|
338
|
+
"import": "./src/components/ui/custom/notification-popover-client.tsx",
|
|
339
|
+
"default": "./src/components/ui/custom/notification-popover-client.tsx"
|
|
339
340
|
},
|
|
340
341
|
"./custom/sidebar-footer-actions": {
|
|
341
342
|
"types": "./src/components/ui/custom/sidebar-footer-actions.tsx",
|
|
@@ -447,7 +448,52 @@
|
|
|
447
448
|
"./text-editor/text-replacements": {
|
|
448
449
|
"types": "./src/components/ui/text-editor/text-replacements.ts",
|
|
449
450
|
"import": "./src/components/ui/text-editor/text-replacements.ts"
|
|
450
|
-
}
|
|
451
|
+
},
|
|
452
|
+
"./custom/satellite-brand": {
|
|
453
|
+
"types": "./src/components/ui/custom/satellite-brand.tsx",
|
|
454
|
+
"import": "./src/components/ui/custom/satellite-brand.tsx"
|
|
455
|
+
},
|
|
456
|
+
"./custom/satellite-navigation": {
|
|
457
|
+
"types": "./src/components/ui/custom/satellite-navigation.tsx",
|
|
458
|
+
"import": "./src/components/ui/custom/satellite-navigation.tsx"
|
|
459
|
+
},
|
|
460
|
+
"./custom/satellite-content": {
|
|
461
|
+
"types": "./src/components/ui/custom/satellite-content.tsx",
|
|
462
|
+
"import": "./src/components/ui/custom/satellite-content.tsx"
|
|
463
|
+
},
|
|
464
|
+
"./custom/satellite-workspace-section": {
|
|
465
|
+
"types": "./src/components/ui/custom/satellite-workspace-section.tsx",
|
|
466
|
+
"import": "./src/components/ui/custom/satellite-workspace-section.tsx"
|
|
467
|
+
},
|
|
468
|
+
"./custom/satellite-shell-utils": {
|
|
469
|
+
"types": "./src/components/ui/custom/satellite-shell-utils.ts",
|
|
470
|
+
"import": "./src/components/ui/custom/satellite-shell-utils.ts"
|
|
471
|
+
},
|
|
472
|
+
"./custom/satellite-shell": {
|
|
473
|
+
"types": "./src/components/ui/custom/satellite-shell.tsx",
|
|
474
|
+
"import": "./src/components/ui/custom/satellite-shell.tsx"
|
|
475
|
+
},
|
|
476
|
+
"./custom/use-satellite-shell": {
|
|
477
|
+
"types": "./src/components/ui/custom/use-satellite-shell.tsx",
|
|
478
|
+
"import": "./src/components/ui/custom/use-satellite-shell.tsx"
|
|
479
|
+
},
|
|
480
|
+
"./custom/satellite-user-menu": {
|
|
481
|
+
"types": "./src/components/ui/custom/satellite-user-menu.tsx",
|
|
482
|
+
"default": "./src/components/ui/custom/satellite-user-menu.tsx"
|
|
483
|
+
},
|
|
484
|
+
"./custom/satellite-footer-actions": {
|
|
485
|
+
"types": "./src/components/ui/custom/satellite-footer-actions.tsx",
|
|
486
|
+
"default": "./src/components/ui/custom/satellite-footer-actions.tsx"
|
|
487
|
+
},
|
|
488
|
+
"./custom/satellite-user-menu-items": "./src/components/ui/custom/satellite-user-menu-items.tsx",
|
|
489
|
+
"./custom/satellite-account-switcher-menu": "./src/components/ui/custom/satellite-account-switcher-menu.tsx",
|
|
490
|
+
"./custom/satellite-theme-dropdown-items": "./src/components/ui/custom/satellite-theme-dropdown-items.tsx",
|
|
491
|
+
"./custom/satellite-language-item": "./src/components/ui/custom/satellite-language-item.tsx",
|
|
492
|
+
"./report-problem-dialog-content": "./src/components/ui/report-problem-dialog-content.tsx",
|
|
493
|
+
"./custom/satellite-settings-dialog-shell": "./src/components/ui/custom/satellite-settings-dialog-shell.tsx",
|
|
494
|
+
"./custom/satellite-onboarding-settings-panel": "./src/components/ui/custom/satellite-onboarding-settings-panel.tsx",
|
|
495
|
+
"./custom/satellite-notification-popover": "./src/components/ui/custom/satellite-notification-popover.tsx",
|
|
496
|
+
"./custom/notification-runtime": "./src/components/ui/custom/notification-runtime.tsx"
|
|
451
497
|
},
|
|
452
|
-
"packageManager": "bun@1.4.
|
|
498
|
+
"packageManager": "bun@1.4.1"
|
|
453
499
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import type { Workspace } from '@tuturuuu/types';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
5
|
+
|
|
6
|
+
vi.mock('next-intl', () => ({
|
|
7
|
+
useLocale: () => 'en',
|
|
8
|
+
useTranslations: () => (key: string) => key,
|
|
9
|
+
}));
|
|
10
|
+
vi.mock('./hooks', () => ({
|
|
11
|
+
useCalendarSettings: () => ({
|
|
12
|
+
initialSettings: {},
|
|
13
|
+
needsCalendarGate: false,
|
|
14
|
+
}),
|
|
15
|
+
}));
|
|
16
|
+
vi.mock('./components/require-workspace-timezone-dialog', () => ({
|
|
17
|
+
RequireWorkspaceTimezoneDialog: () => null,
|
|
18
|
+
}));
|
|
19
|
+
vi.mock('@tuturuuu/ui/legacy/calendar/smart-calendar', () => ({
|
|
20
|
+
SmartCalendar: ({ extras }: { extras: ReactNode }) => <div>{extras}</div>,
|
|
21
|
+
}));
|
|
22
|
+
vi.mock('./components/calendar-connections-unified', () => ({
|
|
23
|
+
default: ({ variant }: { variant: string }) => (
|
|
24
|
+
<div data-testid="sync-entry">{variant}</div>
|
|
25
|
+
),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
import { CalendarClientPage } from './calendar-client-page';
|
|
29
|
+
|
|
30
|
+
const workspace = { id: 'workspace' } as Workspace;
|
|
31
|
+
const HeaderActions = () => <span>Calendar actions</span>;
|
|
32
|
+
|
|
33
|
+
describe('calendar sync warning placement', () => {
|
|
34
|
+
it('keeps a header recovery entry when Calendar uses its sidebar for calendar selection', () => {
|
|
35
|
+
render(
|
|
36
|
+
<CalendarClientPage
|
|
37
|
+
workspace={workspace}
|
|
38
|
+
HeaderActions={HeaderActions}
|
|
39
|
+
enableSmartScheduling={false}
|
|
40
|
+
showConnectionsManager={false}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
expect(screen.getByTestId('sync-entry').textContent).toBe('status');
|
|
44
|
+
expect(screen.getByText('Calendar actions')).toBeTruthy();
|
|
45
|
+
});
|
|
46
|
+
it('lets the normal calendar picker own recovery in the embedded Tasks calendar', () => {
|
|
47
|
+
render(
|
|
48
|
+
<CalendarClientPage
|
|
49
|
+
workspace={workspace}
|
|
50
|
+
HeaderActions={HeaderActions}
|
|
51
|
+
enableSmartScheduling={false}
|
|
52
|
+
showConnectionsManager
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
expect(screen.queryByTestId('sync-entry')).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type SetStateAction,
|
|
15
15
|
useState,
|
|
16
16
|
} from 'react';
|
|
17
|
+
import CalendarConnectionsUnified from './components/calendar-connections-unified';
|
|
17
18
|
import { RequireWorkspaceTimezoneDialog } from './components/require-workspace-timezone-dialog';
|
|
18
19
|
import { useCalendarSettings } from './hooks';
|
|
19
20
|
|
|
@@ -28,6 +29,7 @@ export type CalendarHeaderActionsComponent =
|
|
|
28
29
|
interface CalendarClientPageProps {
|
|
29
30
|
HeaderActions: CalendarHeaderActionsComponent;
|
|
30
31
|
experimentalGoogleToken?: WorkspaceCalendarGoogleTokenClient | null;
|
|
32
|
+
initialEventId?: string;
|
|
31
33
|
workspace: Workspace;
|
|
32
34
|
enableSmartScheduling: boolean;
|
|
33
35
|
externalState?: {
|
|
@@ -42,6 +44,7 @@ interface CalendarClientPageProps {
|
|
|
42
44
|
|
|
43
45
|
export function CalendarClientPage({
|
|
44
46
|
experimentalGoogleToken,
|
|
47
|
+
initialEventId,
|
|
45
48
|
workspace,
|
|
46
49
|
enableSmartScheduling,
|
|
47
50
|
externalState,
|
|
@@ -59,10 +62,15 @@ export function CalendarClientPage({
|
|
|
59
62
|
const needsCalendarGate = !calendarGateCompleted && settingsNeedGate;
|
|
60
63
|
|
|
61
64
|
const extras = (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
<>
|
|
66
|
+
{showConnectionsManager === false && (
|
|
67
|
+
<CalendarConnectionsUnified wsId={workspace.id} variant="status" />
|
|
68
|
+
)}
|
|
69
|
+
<HeaderActions
|
|
70
|
+
workspaceId={workspace.id}
|
|
71
|
+
enableSmartScheduling={enableSmartScheduling}
|
|
72
|
+
/>
|
|
73
|
+
</>
|
|
66
74
|
);
|
|
67
75
|
|
|
68
76
|
return (
|
|
@@ -84,6 +92,7 @@ export function CalendarClientPage({
|
|
|
84
92
|
? experimentalGoogleToken
|
|
85
93
|
: null
|
|
86
94
|
}
|
|
95
|
+
initialEventId={initialEventId}
|
|
87
96
|
extras={extras}
|
|
88
97
|
externalState={externalState}
|
|
89
98
|
initialSettings={initialSettings}
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
WorkspaceCalendarGoogleTokenClient,
|
|
5
5
|
} from '@tuturuuu/types';
|
|
6
6
|
import { CalendarSyncProvider } from '@tuturuuu/ui/hooks/use-calendar-sync';
|
|
7
|
+
import { cn } from '@tuturuuu/utils/format';
|
|
7
8
|
import type { ComponentType } from 'react';
|
|
8
9
|
import type { CalendarView } from '../../../hooks/use-view-transition';
|
|
9
10
|
import type { ExtendedWorkspaceTask } from '../time-tracker/types';
|
|
@@ -26,6 +27,7 @@ interface CalendarPageShellProps {
|
|
|
26
27
|
calendarConnections: CalendarConnection[] | null;
|
|
27
28
|
enableSmartScheduling: boolean;
|
|
28
29
|
experimentalGoogleToken?: WorkspaceCalendarGoogleTokenClient | null;
|
|
30
|
+
initialEventId?: string;
|
|
29
31
|
HeaderActions: CalendarHeaderActionsComponent;
|
|
30
32
|
locale: string;
|
|
31
33
|
smartSchedulingTasks?: ExtendedWorkspaceTask[];
|
|
@@ -41,12 +43,14 @@ interface CalendarPageShellProps {
|
|
|
41
43
|
};
|
|
42
44
|
manageCalendarSyncProvider?: boolean;
|
|
43
45
|
showConnectionsManager?: boolean;
|
|
46
|
+
className?: string;
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
export function CalendarPageShell({
|
|
47
50
|
calendarConnections,
|
|
48
51
|
enableSmartScheduling,
|
|
49
52
|
experimentalGoogleToken,
|
|
53
|
+
initialEventId,
|
|
50
54
|
HeaderActions,
|
|
51
55
|
locale,
|
|
52
56
|
smartSchedulingTasks = [],
|
|
@@ -56,11 +60,13 @@ export function CalendarPageShell({
|
|
|
56
60
|
externalState,
|
|
57
61
|
manageCalendarSyncProvider = true,
|
|
58
62
|
showConnectionsManager = true,
|
|
63
|
+
className,
|
|
59
64
|
}: CalendarPageShellProps) {
|
|
60
65
|
const content = (
|
|
61
|
-
<div className=
|
|
66
|
+
<div className={cn('flex h-[calc(100dvh-2rem)] min-w-0', className)}>
|
|
62
67
|
<CalendarClientPage
|
|
63
68
|
experimentalGoogleToken={experimentalGoogleToken}
|
|
69
|
+
initialEventId={initialEventId}
|
|
64
70
|
workspace={workspace}
|
|
65
71
|
enableSmartScheduling={enableSmartScheduling}
|
|
66
72
|
externalState={externalState}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AlertTriangle,
|
|
2
3
|
Calendar,
|
|
3
4
|
ChevronDown,
|
|
4
|
-
ExternalLink,
|
|
5
5
|
Eye,
|
|
6
6
|
EyeOff,
|
|
7
7
|
Loader2,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
Settings,
|
|
11
11
|
} from '@tuturuuu/icons';
|
|
12
12
|
import Image from 'next/image';
|
|
13
|
+
import { useState } from 'react';
|
|
13
14
|
import { Badge } from '../../badge';
|
|
14
15
|
import { Button } from '../../button';
|
|
15
16
|
import {
|
|
@@ -28,6 +29,10 @@ import {
|
|
|
28
29
|
import { Popover, PopoverContent, PopoverTrigger } from '../../popover';
|
|
29
30
|
import { Separator } from '../../separator';
|
|
30
31
|
import { CalendarConnectionsSettingsContent } from './calendar-connections-settings-content';
|
|
32
|
+
import {
|
|
33
|
+
CalendarSyncRecovery,
|
|
34
|
+
needsCalendarSyncAttention,
|
|
35
|
+
} from './calendar-sync-recovery';
|
|
31
36
|
import type { CalendarConnectionsManagerState } from './use-calendar-connections-manager';
|
|
32
37
|
|
|
33
38
|
export function CalendarConnectionsCompact({
|
|
@@ -35,6 +40,8 @@ export function CalendarConnectionsCompact({
|
|
|
35
40
|
}: {
|
|
36
41
|
state: CalendarConnectionsManagerState;
|
|
37
42
|
}) {
|
|
43
|
+
const [open, setOpen] = useState(false);
|
|
44
|
+
const needsAttention = needsCalendarSyncAttention(state);
|
|
38
45
|
const {
|
|
39
46
|
accounts,
|
|
40
47
|
calendarConnections,
|
|
@@ -52,7 +59,6 @@ export function CalendarConnectionsCompact({
|
|
|
52
59
|
syncHealth,
|
|
53
60
|
syncMutation,
|
|
54
61
|
syncStatusStyles,
|
|
55
|
-
syncToTuturuuu,
|
|
56
62
|
t,
|
|
57
63
|
togglingIds,
|
|
58
64
|
togglingTuturuuuIds,
|
|
@@ -62,9 +68,9 @@ export function CalendarConnectionsCompact({
|
|
|
62
68
|
} = state;
|
|
63
69
|
|
|
64
70
|
return (
|
|
65
|
-
<div className="flex items-center gap-2">
|
|
71
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
66
72
|
{/* Quick calendar visibility toggle */}
|
|
67
|
-
<Popover>
|
|
73
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
68
74
|
<PopoverTrigger asChild>
|
|
69
75
|
<Button variant="outline" size="sm" className="gap-2">
|
|
70
76
|
<Calendar className="h-4 w-4" />
|
|
@@ -353,6 +359,7 @@ export function CalendarConnectionsCompact({
|
|
|
353
359
|
)}
|
|
354
360
|
</div>
|
|
355
361
|
|
|
362
|
+
<CalendarSyncRecovery state={state} />
|
|
356
363
|
<Separator />
|
|
357
364
|
|
|
358
365
|
{/* Sync actions */}
|
|
@@ -365,50 +372,51 @@ export function CalendarConnectionsCompact({
|
|
|
365
372
|
)}
|
|
366
373
|
{syncHealth?.state === 'degraded'
|
|
367
374
|
? t('degraded') || 'Degraded'
|
|
368
|
-
: syncHealth?.state === '
|
|
369
|
-
? t('
|
|
370
|
-
: syncHealth?.state === '
|
|
371
|
-
? t('
|
|
372
|
-
:
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
size="icon"
|
|
378
|
-
className="h-7 w-7"
|
|
379
|
-
onClick={() => syncMutation.mutate()}
|
|
380
|
-
disabled={manualSyncDisabled}
|
|
381
|
-
title={t('sync_now') || 'Sync now'}
|
|
382
|
-
>
|
|
383
|
-
<ExternalLink
|
|
384
|
-
className={`h-3.5 w-3.5 ${
|
|
385
|
-
manualSyncDisabled ? 'animate-pulse' : ''
|
|
386
|
-
}`}
|
|
387
|
-
/>
|
|
388
|
-
</Button>
|
|
389
|
-
<Button
|
|
390
|
-
variant="ghost"
|
|
391
|
-
size="icon"
|
|
392
|
-
className="h-7 w-7"
|
|
393
|
-
onClick={() => syncToTuturuuu()}
|
|
394
|
-
disabled={manualSyncDisabled}
|
|
395
|
-
title={t('sync_from_google')}
|
|
396
|
-
>
|
|
397
|
-
<RefreshCw
|
|
398
|
-
className={`h-3.5 w-3.5 ${manualSyncDisabled ? 'animate-spin' : ''}`}
|
|
399
|
-
/>
|
|
400
|
-
</Button>
|
|
375
|
+
: syncHealth?.state === 'paused'
|
|
376
|
+
? t('sync_recovery.paused')
|
|
377
|
+
: syncHealth?.state === 'healthy'
|
|
378
|
+
? t('healthy') || 'Healthy'
|
|
379
|
+
: syncHealth?.state === 'disconnected'
|
|
380
|
+
? t('connect_accounts') || 'Connect accounts'
|
|
381
|
+
: syncHealth?.state === 'syncing'
|
|
382
|
+
? t('syncing_calendars')
|
|
383
|
+
: t('sync_recovery.unavailable')}
|
|
401
384
|
</div>
|
|
385
|
+
<Button
|
|
386
|
+
variant="outline"
|
|
387
|
+
size="sm"
|
|
388
|
+
onClick={() => syncMutation.mutate()}
|
|
389
|
+
disabled={manualSyncDisabled}
|
|
390
|
+
>
|
|
391
|
+
<RefreshCw
|
|
392
|
+
className={
|
|
393
|
+
syncMutation.isPending ? 'size-4 animate-spin' : 'size-4'
|
|
394
|
+
}
|
|
395
|
+
/>
|
|
396
|
+
{t('sync_now')}
|
|
397
|
+
</Button>
|
|
402
398
|
</div>
|
|
403
399
|
{syncHealth?.lastSuccessAt && (
|
|
404
400
|
<p className="text-muted-foreground text-xs">
|
|
405
|
-
{t('last_synced_at'
|
|
406
|
-
|
|
401
|
+
{t('last_synced_at', {
|
|
402
|
+
time: new Date(syncHealth.lastSuccessAt).toLocaleString(),
|
|
403
|
+
})}
|
|
407
404
|
</p>
|
|
408
405
|
)}
|
|
409
406
|
</div>
|
|
410
407
|
</PopoverContent>
|
|
411
408
|
</Popover>
|
|
409
|
+
{needsAttention && (
|
|
410
|
+
<Button
|
|
411
|
+
variant="outline"
|
|
412
|
+
size="sm"
|
|
413
|
+
className="gap-1.5 border-dynamic-orange/40 text-dynamic-orange"
|
|
414
|
+
onClick={() => setOpen(true)}
|
|
415
|
+
>
|
|
416
|
+
<AlertTriangle className="size-4 shrink-0" />
|
|
417
|
+
<span>{t('sync_recovery.attention')}</span>
|
|
418
|
+
</Button>
|
|
419
|
+
)}
|
|
412
420
|
</div>
|
|
413
421
|
);
|
|
414
422
|
}
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
import { Separator } from '../../separator';
|
|
48
48
|
import { Switch } from '../../switch';
|
|
49
49
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../tabs';
|
|
50
|
+
import { CalendarSyncRecovery } from './calendar-sync-recovery';
|
|
50
51
|
import { CalendarSyncSettingsPanel } from './calendar-sync-settings-panel';
|
|
51
52
|
import type { CalendarConnectionsManagerState } from './use-calendar-connections-manager';
|
|
52
53
|
|
|
@@ -104,6 +105,7 @@ export function CalendarConnectionsSettingsContent({
|
|
|
104
105
|
|
|
105
106
|
return (
|
|
106
107
|
<div className={className ? `space-y-4 ${className}` : 'space-y-4'}>
|
|
108
|
+
<CalendarSyncRecovery state={state} />
|
|
107
109
|
<Tabs defaultValue="calendars" className="py-4">
|
|
108
110
|
<TabsList className="grid w-full grid-cols-3">
|
|
109
111
|
<TabsTrigger value="calendars">
|
|
@@ -401,6 +403,12 @@ export function CalendarConnectionsSettingsContent({
|
|
|
401
403
|
{t('reconnect_required') || 'Reconnect'}
|
|
402
404
|
</Badge>
|
|
403
405
|
)}
|
|
406
|
+
{providerAccountStatuses[account.id]?.state ===
|
|
407
|
+
'temporarily_unavailable' && (
|
|
408
|
+
<Badge variant="secondary" className="text-xs">
|
|
409
|
+
{t('sync_recovery.attention')}
|
|
410
|
+
</Badge>
|
|
411
|
+
)}
|
|
404
412
|
<Badge variant="outline" className="text-xs capitalize">
|
|
405
413
|
{account.provider}
|
|
406
414
|
</Badge>
|
|
@@ -434,6 +442,12 @@ export function CalendarConnectionsSettingsContent({
|
|
|
434
442
|
</Button>
|
|
435
443
|
</div>
|
|
436
444
|
)}
|
|
445
|
+
{providerAccountStatuses[account.id]?.state ===
|
|
446
|
+
'temporarily_unavailable' && (
|
|
447
|
+
<p className="rounded-md border p-2 text-muted-foreground text-xs">
|
|
448
|
+
{t('sync_recovery.provider_unavailable')}
|
|
449
|
+
</p>
|
|
450
|
+
)}
|
|
437
451
|
{(calendarsByAccount[account.id] || []).length > 0 ? (
|
|
438
452
|
(calendarsByAccount[account.id] || []).map((cal) => {
|
|
439
453
|
const syncControlsDisabled =
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { CalendarConnectionsCompact } from './calendar-connections-compact';
|
|
4
4
|
import { CalendarConnectionsSettingsContent } from './calendar-connections-settings-content';
|
|
5
|
+
import { CalendarSyncAttentionButton } from './calendar-sync-attention-button';
|
|
5
6
|
import {
|
|
6
7
|
type CalendarConnectionsUnifiedVariant,
|
|
7
8
|
useCalendarConnectionsManager,
|
|
@@ -21,6 +22,9 @@ export default function CalendarConnectionsUnified({
|
|
|
21
22
|
}) {
|
|
22
23
|
const state = useCalendarConnectionsManager(wsId);
|
|
23
24
|
|
|
25
|
+
if (variant === 'status')
|
|
26
|
+
return <CalendarSyncAttentionButton state={state} />;
|
|
27
|
+
|
|
24
28
|
if (variant === 'settings') {
|
|
25
29
|
return (
|
|
26
30
|
<CalendarConnectionsSettingsContent state={state} className={className} />
|