Skip to content

feat(calendar): Add actionable empty state with Create Event CTA#39931

Open
VedantGupta-DTU wants to merge 1 commit intoRocketChat:developfrom
VedantGupta-DTU:feat/calendar-empty-state-cta
Open

feat(calendar): Add actionable empty state with Create Event CTA#39931
VedantGupta-DTU wants to merge 1 commit intoRocketChat:developfrom
VedantGupta-DTU:feat/calendar-empty-state-cta

Conversation

@VedantGupta-DTU
Copy link
Copy Markdown

@VedantGupta-DTU VedantGupta-DTU commented Mar 28, 2026

Proposed changes (including videos or screenshots)

Currently, encountering an empty state in the Outlook Calendar events list displays a very generic No_history warning 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_today and adding a helpful subtitle. Furthermore, it adds a "Create Event" CTA utilizing StatesAction that opens the user's configured Outlook_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

  1. Setup and sync the Outlook Calendar integration in your workspace.
  2. Ensure you have a day with zero events.
  3. Open the Outlook Calendar sidebar and observe the newly added actionable state.

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

  • Improvements
    • Enhanced the empty calendar state messaging to provide clearer guidance when no events are scheduled for the current day, including a helpful prompt encouraging users to take a break or get started by creating an event.
    • Added a new action button in the empty state that opens Outlook directly, allowing users to quickly create new events without leaving the application.

@VedantGupta-DTU VedantGupta-DTU requested a review from a team as a code owner March 28, 2026 17:37
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Mar 28, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 28, 2026

⚠️ No Changeset found

Latest commit: 73b8912

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

Walkthrough

Updated the empty state UI in the Outlook Events List component by changing the "no results" message from No_history to No_events_for_today, adding an explanatory subtitle, and conditionally rendering a "Create Event" action button that opens the Outlook URL in a new tab when available.

Changes

Cohort / File(s) Summary
Outlook Events Empty State
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
Updated empty state messaging (title and subtitle text keys), added conditional rendering of a StatesAction button to create events when outlookUrl is available, and expanded Fuselage component imports to include StatesAction and StatesActions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

type: feature

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding an actionable empty state with a Create Event CTA to the Outlook Calendar view.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot added the type: feature Pull requests that introduces new feature label Mar 28, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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')}>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Suggested change
<StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}>
<StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank', 'noopener,noreferrer')}>
Fix with Cubic

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4235cd9 and 73b8912.

📒 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 StatesAction and StatesActions from Fuselage to support the new empty state action.

Comment on lines +68 to +69
<StatesTitle>{t('No_events_for_today')}</StatesTitle>
<StatesSubtitle>{t('Take_a_break_or_create_an_event_to_get_started')}</StatesSubtitle>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 -C1

Repository: 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
fi

Repository: 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.

Comment on lines +70 to +76
{outlookUrl && (
<StatesActions>
<StatesAction icon='new-window' onClick={() => window.open(outlookUrl, '_blank')}>
{t('Create_Event')}
</StatesAction>
</StatesActions>
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
{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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community type: feature Pull requests that introduces new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant