Commit Graph

114 Commits

Author SHA1 Message Date
lenhanphung 8681e88390 fix: preserve recurrence exceptions when RSVP to recurring events (#234)
When an attendee accepts/rejects/tentative a recurring event with
exceptions, only update the PARTSTAT without removing exception events.

Add removeOverrides: false parameter to updateSeriesAsync call in
handleRSVP function to preserve all recurrence exceptions.

Fixes: Recurrence exceptions being deleted when accepting/rejecting
all events in a recurring series

* fix: update PARTSTAT on all VEVENTs when RSVP to recurring events

When an attendee accepts/rejects/tentative a recurring event with exceptions,
update PARTSTAT on ALL VEVENTs (master + exceptions) to reflect the correct
attendance status across the entire series.

Changes:
- Add updateSeriesPartstat() in EventApi.ts to update PARTSTAT on all VEVENTs
- Update handleRSVP() to use new function instead of updateSeriesAsync
- Preserve exception times while updating PARTSTAT consistently
- Update test to verify new function is called correctly

Fixes: Exception events not accepting when user chooses 'Accept all events'
2025-10-23 05:36:34 +02:00
lenhanphung 1c8826facc Form validation for event create/update (#218)
* refactor: migrate EventModal to use shared EventFormFields component

* feat: add form validation for event create/update

- Validate title is required
- Validate end datetime must be after start datetime
- Disable save button when form is invalid
- Show error messages below invalid fields with red highlight (MUI)
- Title validation in create mode only shows error after field is touched
- Track touched state to avoid showing errors on initial load

* feat: improve event modal UX with auto-focus and default times

- Auto-focus title field when opening create/update event modal
- Set default datetime when creating event without selecting range:
  * Start time = current time + 1 hour (rounded to :00)
  * End time = start time + 1 hour
- Applied duplicate event to display datetime from original event
- Fix logic to detect empty event object vs valid event with uid

* fix: improve validation UX and add required field indicator

- Only show validation errors when modal is open (isOpen check)
- Add red asterisk (*) to Title label to indicate required field
- Prevent validation error flash when closing modal
- Fix TypeScript errors in EventUpdateModal
- Keep validation behavior: only show error after user types and deletes

* feat: auto-focus title field when toggling between normal and extended mode in event modal


* update: only validation when click on save button

* fix: prevent form data loss and validation errors in event modals

Fixes:
1. Form fields no longer clear when changing start/end dates
2. Extended mode stays active when modifying dates
3. No validation errors shown after successful save
2025-10-22 11:52:38 +02:00
Camille Moussu e99c56f03f Handle long descriptions (#228)
Co-authored-by: Camille Moussu <cmoussu@linagora.com>
2025-10-21 12:17:36 +02:00
Camille Moussu 6411ed636b [#197] added missing infos 2025-10-20 14:03:42 +02:00
lenhanphung ed8bb41ca9 fix: resolve timezone properly in TimezoneSelector and EventModal
- Resolve timezone alias to main timezone in TimezoneSelector before passing to TimezoneAutocomplete
- Resolve timezone in EventModal useState initialization to ensure correct timezone display
- Sync resolved timezone when modal opens or Redux timezone changes
- Ensure timezone is always resolved in resetAllStateToDefault callback
- Fix issue where TimezoneAutocomplete doesn't show correct timezone on first load
2025-10-20 07:22:00 +02:00
lenhanphung 6421f53a8d refactor: extract reusable TimezoneAutocomplete component
- Create new TimezoneAutocomplete component for shared timezone selection logic
- Update TimezoneSelector to use the new component
- Replace inline Autocomplete in EventFormFields with TimezoneAutocomplete
- Replace inline Autocomplete in EventModal with TimezoneAutocomplete
- Reduce code duplication and improve maintainability
2025-10-20 07:22:00 +02:00
lenhanphung 2ab7c448bf refactor: replace timezone Select with Autocomplete
- Replace timezone Select field with Autocomplete in EventModal and EventFormFields
- Add search functionality for timezones with text input
- Add timezone icon to match PeopleSearch component style
- Remove 'Mark as important' checkbox from EventModal (re showup when rebase)
- Remove gap space in description when desc field show up
2025-10-20 07:22:00 +02:00
Camille Moussu adbb77fe8a [#222] removed malformed param (#225)
Co-authored-by: Camille Moussu <cmoussu@linagora.com>
2025-10-17 15:38:40 +02:00
Camille Moussu f278caf041 [#168] changed temp calendar reload to reload only thoses that are impacted 2025-10-17 11:26:50 +02:00
Camille Moussu 29f984b347 [#168] added refresh to temp calendars when updating 2025-10-17 11:26:50 +02:00
lenhanphung 4c18bf3a52 feat: Update event modal UI with header icons and improved actions layout
- Add expand and close icons to ResponsiveDialog header in normal mode
- Change 'Show More' button to 'More options' with Add icon
- Hide Cancel button in normal mode, show only in extended mode
- Add showHeaderActions prop to ResponsiveDialog for UI control
- Preserve EventDisplayPreview modal with old UI (no header icons)
- Update all affected test cases to match new UI behavior
2025-10-16 10:36:28 +02:00
lenhanphung 4936b89e8b fix: add timezone offset display to EventDisplayPreview for non-allday events 2025-10-15 08:29:28 +02:00
lenhanphung 5c38b2fd99 refactor: extract complex logic from EventUpdateModal to testable helpers
- Add combineMasterDateWithFormTime helper for date/time combination
- Add detectRecurringEventChanges helper for change detection
- Add normalizeRepetition and normalizeTimezone utilities
- Reduce EventUpdateModal complexity
- Add 18 unit tests for new helpers
2025-10-15 08:29:28 +02:00
lenhanphung af47923478 fix: recurring events edit all instances issues
- Fix master event detection in getEvent() to find VEVENT without recurrence-id
- Add removeOverrides parameter to updateSeries() to control override deletion
- Fetch master event when editing 'all events' to preserve original start date
- Combine master's date with form's time when updating all instances
- Detect time changes separately from date changes to preserve optimistic updates
- Only remove overrides when date/time/timezone/repeat rules change
- Keep overrides when only properties (title, description, etc) change

Fixes:
1. Old UI not cleared when editing all events
2. Start date not preserved when editing from different instance
3. Solo overrides incorrectly removed when only properties changed
4. Optimistic updates lost when editing recurring events
2025-10-15 08:29:28 +02:00
lenhanphung 5017c1bd6b fix: improve event editing UX and allday toggle behavior
- Fix allday toggle: when unchecking allday, set end date = start date with rounded time (30min intervals)
- Fix ResponsiveDialog CSS: set height only for expanded mode, remove maxHeight from normal mode
- Show repeat info when editing solo instance of recurring event (checkbox checked and disabled)
- Clear old event UI when updating recurring event allday status
2025-10-15 08:29:28 +02:00
lenhanphung a31825ce3a fix: set timezone changes as repetition rule changes for recurring events 2025-10-15 08:29:28 +02:00
lenhanphung 16317356fb feat: optimize recurring event updates with smart cache management 2025-10-15 08:29:28 +02:00
lenhanphung 59e7992cfe refactor: implement optimistic updates for recurring event edits
- Replace refreshCalendars() with optimistic Redux updates for update all instances
- Add rollback mechanism: revert to old data if API fails
- Add notification placeholder function (ready for future toast implementation)
- Update single instance also uses optimistic update + rollback pattern
- Remove unnecessary refreshCalendars and getCalendarRange imports
- No view reload, instant UI updates, smooth UX

Performance improvements:
- API calls reduced from N+1 to 1 (eliminated fetch for all calendars)
- UI update time reduced from ~1s to <50ms
- Consistent behavior across all update operations
2025-10-15 08:29:28 +02:00
lenhanphung 942b203b0f fix: correct recurring to non-recurring event update logic
- Fix bug where updating recurring event to non-recurring created duplicate events
- Deduplicate URLs before deletion to avoid multiple delete calls on same file
- Add onCloseAll prop to close both preview and update modals after save
- Adjust smooth UI

Resolves issue where repeat->no-repeat conversion left old recurring events visible
2025-10-15 08:29:28 +02:00
lenhanphung 8160ed459a feat: restore logging for status 201 in putEvent as requested in PR #54
- Restore test case to verify logging behavior
2025-10-15 08:29:28 +02:00
lenhanphung 40f0179be6 fix: directly delete recurring events when converting to non-recurring
- Use direct API call to delete recurring events instead of going through Redux store
- Construct event URL directly for more reliable deletion
- Add error handling and small delay to ensure complete deletion
- Clean up all instances from store after deletion
2025-10-15 08:29:28 +02:00
lenhanphung 2ba80fcdb6 fix: handle converting recurring events to non-recurring events in edit all mode 2025-10-15 08:29:28 +02:00
lenhanphung 474ff22cab fix: properly handle recurring events in EventUpdateModal
- Fix handling of solo vs. all event updates for recurring events
- Add calendar refresh for update all events
- Disable repeat option when editing a single occurrence (solo mode)
- Fix event recurrence editing in modals to match main branch
- Properly link EventDisplayPreview with EventUpdateModal for typeOfAction
2025-10-15 08:29:28 +02:00
lenhanphung 9ff8354950 fix: update EventDisplay and EventRepetition tests
- Fix formatLocalDateTime import in EventDisplay.tsx (now in EventFormFields)
- Update test expectations: 'Edit Event' -> 'Update Event'
- Remove getEventAsync spy (no longer called before modal opens)
2025-10-15 08:29:28 +02:00
lenhanphung 6433086332 fix: use main's EventDisplay.tsx and fix test imports
- Revert to main's EventDisplay.tsx (had wrong version from old commits)
- Fix EventRepetition.test.tsx import path
2025-10-15 08:29:28 +02:00
lenhanphung 601c75db33 feat: integrate main's EventDisplayPreview UI with EventUpdateModal
1. Replace old EventDisplayPreview with main's new Figma UI
   - Use ResponsiveDialog instead of Popover
   - Keep file at features/Events/ location (not components/Event/)
   - Integrate InfoRow, EditModeDialog components from main
   - Fix all imports to work with new location

2. Add EventUpdateModal integration
   - Edit icon now opens EventUpdateModal instead of EventDisplayModal
   - EventUpdateModal uses shared EventFormFields component

3. Fix imports and exports
   - Use default import for ResponsiveDialog
   - Use named import for EditModeDialog
   - Fix anchorPosition to be optional with default value

4. Performance improvement
   - Open EventUpdateModal immediately without waiting for API
   - Let modal fetch fresh data in background via useEffect

5. Fix Checkbox styling warning
   - Use sx prop instead of style for nested MUI selectors
   - Fix 'Unsupported style property &.Mui-checked' console warning
2025-10-15 08:29:28 +02:00
lenhanphung 64393bf161 fix: preserve original timezone when reopening event update modal
- Add formatDateTimeInTimezone() helper to format dates in event's original timezone
- Fix EventUpdateModal to display event times in original timezone instead of browser timezone
- Fix EventModal (duplicate event) with same timezone handling
- Update EventDisplay tests to use flexible date pattern
2025-10-15 08:29:28 +02:00
lenhanphung 80c1babb7f refactor: remove 'mark as important' field and clean up console.log statements
- Remove 'important' field from EventFormFields component and all event modals
- Remove all console.log statements from event create/update flow
- Fix import issues and type compatibility in EventModal
2025-10-15 08:29:28 +02:00
lenhanphung 42c953ccf9 feat(events): align Update modal with Create; extract shared form fields
- ux: close Update modal immediately on Save; run API in background
- fix: remove stale single-instance when converting to repeating
- test: adjust EventDisplay expectations
- refactor: share form via components/Event/EventFormFields (used by Create/Update)
2025-10-15 08:29:28 +02:00
Camille Moussu 770257c03b [#154] added timezone component to change timezone of calendar (#207)
Co-authored-by: Camille Moussu <cmoussu@linagora.com>
2025-10-14 15:25:28 +02:00
Camille Moussu 26e69091d9 [#137] added duration management when no end + added moment library to manage duration 2025-10-10 11:19:09 +02:00
Camille Moussu a00f179dbd [#121] added error handler and snackbar 2025-10-10 11:19:09 +02:00
Camille Moussu c86db8fa49 refactor recurring event modification (#173) 2025-10-07 18:16:00 +02:00
Camille Moussu 3f8f3eff23 [#162] changed preview modal looks to follow figma (#163)
Co-authored-by: Camille Moussu <cmoussu@linagora.com>
2025-10-07 11:20:09 +02:00
Camille Moussu 40c383c334 Revamp calendar dialog (#158)
Co-authored-by: Camille Moussu <cmoussu@linagora.com>
2025-10-07 11:14:08 +02:00
lenhanphung f99b3fb223 css: fix prettier and hidden slot minor 2025-10-03 17:31:24 +07:00
lenhanphung 4ef3a887ee fix: resolve infinite loop and week calculation issues in EventModal
- Fix infinite loop in EventModal useEffect by using useRef for userPersonnalCalendars
- Fix weekStart calculation in putEventAsync to use Monday as first day (consistent with FullCalendar firstDay=1)
- Add computeWeekRange utility function for consistent week calculations
- Improve state reset logic when closing EventModal popup
- Ensure repeat checkbox state is properly reset to prevent stale repetition data
2025-10-03 17:22:19 +07:00
lenhanphung f245991816 feat: improve video conference UI in EventModal
- Replace 'Meeting link generated' text with 'Join Visio conference' button
- Button opens video conference link in new tab when clicked
- Use contained variant styling to match Save button appearance
- Maintain copy and delete functionality for meeting links
2025-10-03 14:51:40 +07:00
lenhanphung 04fa2d0629 feat: add byday field support for event repetition
- Add byday field to RepetitionObject interface in EventsTypes.ts
- Update calendarEventToJCal to handle byday field (array or null)
- Update parseCalendarEvent to parse byday from JCal format
- Fix all-day event dtend logic to increment by 1 day when start equals end
- Add comprehensive test cases for byday field handling
2025-10-03 11:32:42 +07:00
lenhanphung cea576e5e8 fix: improve video conference link positioning and null safety
- Fix calendarUtils.ts null safety for calendars[id] access
- Update video conference link to be added on line 2 instead of line 3
- Update regex in handleDeleteVideoConference to match new format
- Update all test cases for videoConferenceUtils to match new format
- Add null checks in updateCalsDetails function
2025-10-03 10:46:34 +07:00
lenhanphung ff54840ac8 fix: resolve all failing test suites
- Fix RepeatEvent.test.tsx (15/15 tests): Update selectors to match actual UI text ('Day(s)', 'Week(s)', etc.) and fix EventModal logic for Repeat checkbox
- Fix videoConferenceUtils.test.ts (1/1 test): Mock window object for Node.js environment
- Fix EventModal.test.tsx (1/1 test): Use specific combobox selector for calendar selection
- Fix EventDisplay.test.tsx (1/1 test): Remove incorrect Repeat checkbox expectation
2025-10-03 10:07:08 +07:00
lenhanphung 407290702f fix: resolve all failing test suites
- Fix RepeatEvent.test.tsx (15/15 tests): Update selectors to match actual UI text ('Day(s)', 'Week(s)', etc.) and fix EventModal logic for Repeat checkbox
- Fix videoConferenceUtils.test.ts (1/1 test): Mock window object for Node.js environment
- Fix EventModal.test.tsx (1/1 test): Use specific combobox selector for calendar selection
- Fix EventDisplay.test.tsx (1/1 test): Remove incorrect Repeat checkbox expectation
2025-10-02 18:11:55 +07:00
lenhanphung 298b69b3e1 feat: add video conference meeting link generation to event modal
- Add video conference utility functions for generating random meeting IDs
- Implement video meeting button with camera icon in EventModal
- Add copy and delete functionality with IconButton components
- Support X-OPENPAAS-VIDEOCONFERENCE field in CalendarEvent type
- Handle state management for editing events with/without video conference
- Add meeting link footer to event description
- Include comprehensive test suite for video conference utilities

Features:
- Generate random meeting links (format: xxx-xxxx-xxx)
- Copy meeting link to clipboard
- Remove video conference from events
- Proper state sync when editing different events
- Integration with existing JCal/ICS conversion
2025-10-02 16:16:04 +07:00
lenhanphung 4eb2c86771 fix: update test cases to match new UI labels
- Update RepeatEvent.test.tsx to use correct selectors and text matching
- Update EventDisplay.test.tsx to use 'Notification' instead of 'Alarm'
- Update EventModal.test.tsx to use new label names and fix description input tests
- Update Calendar.test.tsx to use new placeholder text 'Start typing a name or email'
- Fix EventDisplay.tsx to use 'Notification' label consistently
2025-10-02 14:19:05 +07:00
lenhanphung 3261479874 refactor: improve EventModal UI labels and visibility controls
- Rename 'Alarm' to 'Notification' for better clarity
- Rename 'Attendees' to 'Participants' with updated placeholder text
- Replace 'Visibility' dropdown with 'Visible to' toggle buttons (All/Participants)
- Remove CONFIDENTIAL option, keep only PUBLIC and PRIVATE
- Add icons (PublicIcon/LockIcon) with fixed sizing for toggle buttons
- Rename 'Show as' to 'Show me as'
- Fix ResponsiveDialog scroll bar positioning in expanded mode
- Update PeopleSearch placeholder to 'Start typing a name or email'
2025-10-02 14:19:05 +07:00
lenhanphung 7c6240442c feat: redesign event modal with responsive dialog and improved layout
Implemented a new ResponsiveDialog component and redesigned EventModal
with better UX for both normal and extended modes.

New Features:
- Created reusable ResponsiveDialog component (src/components/Dialog/)
  * Normal mode: 685px centered popup
  * Extended mode: fullscreen with 90px header preservation
  * Auto spacing via MUI Stack (16px normal, 24px extended)
  * Back arrow navigation in extended mode
  * No backdrop/shadow in extended mode for seamless integration
  * Configurable props for all dimensions and behaviors

EventModal Improvements:
- Replaced native checkbox with MUI Checkbox component
- Migrated from Popover to ResponsiveDialog
- Reorganized field layout

=> Comprehensive documentation in Dialog/README.md

Note: RepeatEvent integration tests need additional refactoring (tracked separately)
2025-10-02 14:19:05 +07:00
lenhanphung 3870bceb6d feat: prepare project for cozy-ui migration (#157)
* feat: prepare project for cozy-ui migration

Build Configuration
- Add Stylus support via @rsbuild/plugin-stylus
- Add SVGR support via @rsbuild/plugin-svgr
- Update rsbuild.config.ts with custom configuration
- Add historyApiFallback for SPA routing

ESLint Configuration
- Create .eslintrc.json with react-app configuration
- Remove eslintConfig from package.json

CSS to Stylus Migration
Convert all 5 CSS files to Stylus (.styl) format:
  - src/App.css to src/App.styl
  - src/index.css to src/index.styl
  - src/components/Calendar/Calendar.css to src/components/Calendar/Calendar.styl
  - src/components/Calendar/CustomCalendar.css to src/components/Calendar/CustomCalendar.styl
  - src/components/Menubar/Menubar.css to src/components/Menubar/Menubar.styl
- Update all imports from .css to .styl
- Preserve all styling rules and values

MUI Styling Cleanup
- Replace all MUI sx props with standard style props across 15+ components
- Convert MUI spacing units (mr: 2 to marginRight: 16px)
- Convert MUI shorthand props (p: 2 to padding: 16px, mb: 1 to marginBottom: 8px)
- Remove MUI-specific syntax (&.Mui-checked selectors)
- Maintain exact visual appearance

FullCalendar Fixes
- Comment out problematic CSS rule in CustomCalendar.styl
- Fix display issues with timegrid slot labels

Files Modified
- Config: rsbuild.config.ts, .eslintrc.json, package.json
- Styling: 5 CSS to Stylus conversions, 15+ component sx to style updates
- Components: All components using MUI sx props updated

Development Workflow
- Continue using existing development commands
- Stylus files are now the source of truth for styling
- MUI components work with standard style props
- ESLint uses familiar react-app rules

Dependencies Added
- @rsbuild/plugin-stylus
- @rsbuild/plugin-svgr
2025-10-01 17:31:18 +02:00
Camille Moussu ac9db2b520 [#101] fixed regex for attendee mail cleanup 2025-09-30 06:42:31 +02:00
lenhanphung 7b8a2e74a5 fix prettier 2025-09-25 17:16:12 +07:00
lenhanphung b9d7a8fa6b feat: enhance calendar with view sync, Redux fixes, and dynamic slot label dimming
- Sync calendar view state between Calendar and Menubar components
- Fix Redux serialization errors by using string dates instead of Date objects
- Add null checks for eventResize handler to prevent undefined errors
- Implement dynamic slot label dimming near current time indicator
- Slot labels fade to opacity 0.2 when now indicator is within 15 minutes
- Add smooth CSS transitions for better user experience
- Handle edge cases around midnight for proper time calculation
- Update slot label visibility on view changes and time updates
2025-09-25 17:12:07 +07:00