feat(calendar): Add actionable empty state with Create Event CTA#39931
feat(calendar): Add actionable empty state with Create Event CTA#39931VedantGupta-DTU wants to merge 1 commit intoRocketChat:developfrom
Conversation
|
Looks like this PR is not ready to merge, because of the following issues:
Please fix the issues and try again If you have any trouble, please check the PR guidelines |
|
WalkthroughUpdated the empty state UI in the Outlook Events List component by changing the "no results" message from Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
1 issue found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx">
<violation number="1" location="apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx:72">
P2: New external-link CTA opens a `_blank` window without `noopener`/`noreferrer`, allowing opener access (reverse-tabnabbing risk) for configurable Outlook URLs.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| <StatesSubtitle>{t('Take_a_break_or_create_an_event_to_get_started')}</StatesSubtitle> | ||
| {outlookUrl && ( | ||
| <StatesActions> | ||
| <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}> |
There was a problem hiding this comment.
P2: New external-link CTA opens a _blank window without noopener/noreferrer, allowing opener access (reverse-tabnabbing risk) for configurable Outlook URLs.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx, line 72:
<comment>New external-link CTA opens a `_blank` window without `noopener`/`noreferrer`, allowing opener access (reverse-tabnabbing risk) for configurable Outlook URLs.</comment>
<file context>
@@ -65,7 +65,15 @@ const OutlookEventsList = ({ onClose, changeRoute }: OutlookEventsListProps): Re
+ <StatesSubtitle>{t('Take_a_break_or_create_an_event_to_get_started')}</StatesSubtitle>
+ {outlookUrl && (
+ <StatesActions>
+ <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}>
+ {t('Create_Event')}
+ </StatesAction>
</file context>
| <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}> | |
| <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank', 'noopener,noreferrer')}> |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx`:
- Around line 70-76: The onClick handlers in the OutlookEventsList component
call window.open(outlookUrl, '_blank') (inside the StatesAction in
OutlookEventsList.tsx) which leaves window.opener exposed; update these calls to
include the noopener and noreferrer flags by calling window.open(outlookUrl,
'_blank', 'noopener,noreferrer') (and apply the same change to the other
window.open call around line 99) so the opened tab cannot access the opener and
referrer is suppressed.
- Around line 68-69: Add the missing translation keys used in
OutlookEventsList.tsx by updating packages/i18n/src/locales/en.i18n.json: add
"No_events_for_today", "Take_a_break_or_create_an_event_to_get_started", and
"Create_Event" with appropriate English values (e.g., "No events for today",
"Take a break or create an event to get started", "Create Event") so the calls
to t('No_events_for_today'), t('Take_a_break_or_create_an_event_to_get_started')
and t('Create_Event') resolve correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 04979c96-d3d7-4204-9cd5-976390250d9c
📒 Files selected for processing (1)
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: cubic · AI code reviewer
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation
Files:
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
🧠 Learnings (2)
📚 Learning: 2026-02-26T19:22:36.646Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/views/CallHistoryContextualbar/CallHistoryActions.tsx:40-40
Timestamp: 2026-02-26T19:22:36.646Z
Learning: In packages/ui-voip/src/views/CallHistoryContextualbar/CallHistoryActions.tsx, when the media session state is 'unavailable', the voiceCall action is not included in the actions object passed to CallHistoryActions, so it won't appear in the menu at all. The action filtering happens upstream before getItems is called, preventing any tooltip confusion for the unavailable state.
Applied to files:
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.
Applied to files:
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
🔇 Additional comments (1)
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx (1)
1-1: LGTM!Import correctly includes
StatesActionandStatesActionsfrom Fuselage to support the new empty state action.
| <StatesTitle>{t('No_events_for_today')}</StatesTitle> | ||
| <StatesSubtitle>{t('Take_a_break_or_create_an_event_to_get_started')}</StatesSubtitle> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for the new translation keys in the codebase
echo "=== Checking No_events_for_today ==="
rg -l "No_events_for_today" --type json
echo "=== Checking Take_a_break_or_create_an_event_to_get_started ==="
rg -l "Take_a_break_or_create_an_event_to_get_started" --type json
echo "=== Checking Create_Event ==="
rg -l "Create_Event" --type json
echo "=== Sample content if found ==="
rg '"No_events_for_today"' --type json -C1
rg '"Take_a_break_or_create_an_event_to_get_started"' --type json -C1
rg '"Create_Event"' --type json -C1Repository: RocketChat/Rocket.Chat
Length of output: 228
🏁 Script executed:
# Check if en.i18n.json exists and search for the specific keys
echo "=== Checking en.i18n.json for the keys ==="
if [ -f "packages/i18n/src/locales/en.i18n.json" ]; then
echo "File found. Searching for keys..."
rg "No_events_for_today|Take_a_break_or_create_an_event_to_get_started|Create_Event" packages/i18n/src/locales/en.i18n.json
else
echo "File not found at expected location"
fi
echo ""
echo "=== Verify OutlookEventsList.tsx exists ==="
find . -name "OutlookEventsList.tsx" -type f
echo ""
echo "=== Check the relevant lines in the file ==="
if [ -f "apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx" ]; then
sed -n '65,75p' apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
fiRepository: RocketChat/Rocket.Chat
Length of output: 800
Add missing translation keys to en.i18n.json.
The keys No_events_for_today, Take_a_break_or_create_an_event_to_get_started, and Create_Event are used in the code but missing from packages/i18n/src/locales/en.i18n.json. Add these keys with appropriate English values to the translation file.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx`
around lines 68 - 69, Add the missing translation keys used in
OutlookEventsList.tsx by updating packages/i18n/src/locales/en.i18n.json: add
"No_events_for_today", "Take_a_break_or_create_an_event_to_get_started", and
"Create_Event" with appropriate English values (e.g., "No events for today",
"Take a break or create an event to get started", "Create Event") so the calls
to t('No_events_for_today'), t('Take_a_break_or_create_an_event_to_get_started')
and t('Create_Event') resolve correctly.
| {outlookUrl && ( | ||
| <StatesActions> | ||
| <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}> | ||
| {t('Create_Event')} | ||
| </StatesAction> | ||
| </StatesActions> | ||
| )} |
There was a problem hiding this comment.
Add noopener,noreferrer to window.open for security.
Using window.open(url, '_blank') without specifying noopener allows the opened page to access window.opener, which can be exploited for phishing (reverse tabnabbing). The same pattern exists at line 99.
🔒 Proposed fix
- <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}>
+ <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank', 'noopener,noreferrer')}>
{t('Create_Event')}
</StatesAction>Also apply to line 99:
- <Button icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}>
+ <Button icon='new-window' onClick={() => window.open(outlookUrl, '_blank', 'noopener,noreferrer')}>
{t('Open_Outlook')}
</Button>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {outlookUrl && ( | |
| <StatesActions> | |
| <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}> | |
| {t('Create_Event')} | |
| </StatesAction> | |
| </StatesActions> | |
| )} | |
| {outlookUrl && ( | |
| <StatesActions> | |
| <StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank', 'noopener,noreferrer')}> | |
| {t('Create_Event')} | |
| </StatesAction> | |
| </StatesActions> | |
| )} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx`
around lines 70 - 76, The onClick handlers in the OutlookEventsList component
call window.open(outlookUrl, '_blank') (inside the StatesAction in
OutlookEventsList.tsx) which leaves window.opener exposed; update these calls to
include the noopener and noreferrer flags by calling window.open(outlookUrl,
'_blank', 'noopener,noreferrer') (and apply the same change to the other
window.open call around line 99) so the opened tab cannot access the opener and
referrer is suppressed.
Proposed changes (including videos or screenshots)
Currently, encountering an empty state in the Outlook Calendar events list displays a very generic
No_historywarning without any actionable paths for the user to resolve this (such as by creating a new event).This PR reworks the empty state by upgrading the text to
No_events_for_todayand adding a helpful subtitle. Furthermore, it adds a "Create Event" CTA utilizingStatesActionthat opens the user's configuredOutlook_Url(if available), turning an abrupt dead-end into a seamless workflow.(This PR is raised as an initial contribution towards the GSoC Personal Calendar project proposal).
Issue(s)
N/A (Related to Google Summer of Code 'Personal Calendar' Preparation)
Steps to test or reproduce
Further comments
This solves a UX dead-end for users looking to quickly add events directly from their Rocket.Chat client!
Summary by CodeRabbit
Release Notes