Add BitFullCalendar extras component (#12449)#12450
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR adds the FullCalendar extras component, its shared state and helpers, multiple calendar views, timeline layouts, styling, and demo/navigation entries. ChangesBitFullCalendar feature
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Tools execution failed with the following error: Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error) 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 |
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 1
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
🟡 Minor comments (11)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor-5-5 (1)
5-5:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPolish the page description text for user-facing docs.
Current wording is awkward and inconsistent in casing (
"fullcalendar component of the bit BlazorUI components"). Consider a clearer description, e.g. “FullCalendar component for Bit BlazorUI.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor` at line 5, The Description attribute text in the BitFullCalendarDemo.razor component has awkward wording and inconsistent casing. Update the Description property to use proper casing for "FullCalendar" (currently lowercase) and simplify the text to remove redundancy. Instead of "fullcalendar component of the bit BlazorUI components", use clearer phrasing such as "FullCalendar component for Bit BlazorUI" to improve readability and consistency for user-facing documentation.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs-213-218 (1)
213-218:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse active culture for time labels instead of
InvariantCulture.At Line 216 and Line 253, forcing invariant formatting breaks localization consistency for time strings in non-English cultures.
Suggested fix
- public static string FormatTime(DateTime date, bool use24Hour) + public static string FormatTime(DateTime date, bool use24Hour, CultureInfo? culture = null) { + culture ??= CultureInfo.CurrentUICulture; return use24Hour - ? date.ToString("HH:mm", CultureInfo.InvariantCulture) - : date.ToString("h:mm tt", CultureInfo.InvariantCulture); + ? date.ToString("HH:mm", culture) + : date.ToString("h:mm tt", culture); } @@ - public static string FormatHourLabel(int hour, bool use24Hour) + public static string FormatHourLabel(int hour, bool use24Hour, CultureInfo? culture = null) { var dt = DateTime.Today.AddHours(hour); + culture ??= CultureInfo.CurrentUICulture; return use24Hour - ? dt.ToString("HH:00", CultureInfo.InvariantCulture) - : dt.ToString("h tt", CultureInfo.InvariantCulture); + ? dt.ToString("HH:00", culture) + : dt.ToString("h tt", culture); }Also applies to: 248-254
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs` around lines 213 - 218, The FormatTime method is using CultureInfo.InvariantCulture for both the 24-hour and 12-hour time format calls, which prevents localization for non-English cultures. Replace CultureInfo.InvariantCulture with CultureInfo.CurrentCulture in both date.ToString() calls within the FormatTime method to respect the user's active culture settings. Apply the same fix to the similar time formatting code mentioned in the "Also applies to" section around lines 248-254.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs-25-27 (1)
25-27:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTreat midnight
EndDateas exclusive for day-span classification.At Line 25,
IsSingleDayuses directDateequality, so an event like2026-06-20 22:00 -> 2026-06-21 00:00is flagged as multi-day even though it ends at the day boundary.Suggested fix
public class BitFullCalendarEvent { @@ - public bool IsSingleDay => StartDate.Date == EndDate.Date; + private DateTime EndDateForDaySpan => + EndDate.TimeOfDay == TimeSpan.Zero && EndDate > StartDate + ? EndDate.AddTicks(-1) + : EndDate; + + public bool IsSingleDay => StartDate.Date == EndDateForDaySpan.Date; public bool IsMultiDay => !IsSingleDay; public TimeSpan Duration => EndDate - StartDate;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs` around lines 25 - 27, The IsSingleDay property at line 25 of BitFullCalendarEvent class does not treat midnight EndDate as exclusive, causing events ending at 00:00 of the next day to be incorrectly classified as multi-day. Fix this by adjusting the Date comparison in the IsSingleDay property to subtract one tick or unit of time from EndDate before comparing dates, ensuring that an EndDate at midnight is treated as the end of the previous day rather than the start of the next day.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cs-49-49 (1)
49-49:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMake
Sourcerequired to prevent silent origin misclassification.If omitted,
Sourcedefaults toDialog(enum zero), which can report incorrect origin metadata in emitted change payloads. Mark itrequiredto force explicit assignment.Proposed fix
- public BitFullCalendarChangeSource Source { get; init; } + public required BitFullCalendarChangeSource Source { get; init; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cs` at line 49, Add the `required` keyword to the Source property in the BitFullCalendarChangeEventArgs class to force callers to explicitly assign a BitFullCalendarChangeSource value, preventing silent defaults to Dialog (the zero enum value) which can cause incorrect origin metadata in change payloads.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor-20-23 (1)
20-23:⚠️ Potential issue | 🟡 MinorSet add-event button type explicitly to avoid accidental form submission.
Without
type="button", this button defaults totype="submit"per HTML specification. If the FullCalendar component is used inside a form context, the button will unintentionally trigger form submission instead of only calling theOnAddEventClickhandler. Adding the explicit type prevents this risk.🛠️ Suggested fix
- <button class="bit-bfc-btn bit-bfc-btn-primary bit-bfc-btn-sm" `@onclick`="OnAddEventClick"> + <button type="button" class="bit-bfc-btn bit-bfc-btn-primary bit-bfc-btn-sm" `@onclick`="OnAddEventClick">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor` around lines 20 - 23, The button element with the OnAddEventClick handler in BitFcCalendarHeader.razor lacks an explicit type attribute, causing it to default to type="submit" per HTML specification. This can trigger unintended form submission if the FullCalendar component is placed within a form context. Add type="button" explicitly to the button element that contains the OnAddEventClick event handler to ensure it only calls the click handler and does not submit any parent form.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor-6-6 (1)
6-6:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse calendar culture for the dialog date header.
This currently formats with default culture instead of
State.Culture, causing localization inconsistencies.Suggested fix
- <h3>`@Texts.EventListTitlePrefix` `@Date.ToString`("dddd, MMM d, yyyy")</h3> + <h3>`@Texts.EventListTitlePrefix` `@Date.ToString`("dddd, MMM d, yyyy", State.Culture)</h3>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor` at line 6, In the BitFcEventListDialog.razor component's h3 element, the date formatting using Date.ToString("dddd, MMM d, yyyy") does not respect the calendar's culture setting. Modify the Date.ToString call to include State.Culture as a culture parameter so that the date is formatted according to the calendar's culture instead of the default culture. This will ensure the date header displays in the correct localized format.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cs-19-23 (1)
19-23:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAwait
OnClose.InvokeAsync()in the edit-close flow.The callback task is currently not awaited.
Suggested fix
- private void OnEditClose() + private async Task OnEditClose() { _showEdit = false; - OnClose.InvokeAsync(); + await OnClose.InvokeAsync(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cs` around lines 19 - 23, The OnEditClose() method invokes the OnClose callback asynchronously but does not await the result, which can cause the callback to not complete properly. Change the OnEditClose() method signature from void to async Task, and add the await keyword before the OnClose.InvokeAsync() call to ensure the asynchronous operation completes before the method returns.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cs-36-49 (1)
36-49:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winKeep
SelectedDateconsistent across both add-event paths.
State.SetSelectedDate(day)is only applied whenOnAddClickis delegated, not when using the built-in add dialog.Suggested fix
private async Task OnHourClickAsync(DateTime day, int hour) { + State.SetSelectedDate(day); + if (OnAddClick.HasDelegate) { - State.SetSelectedDate(day); var draft = BitFullCalendarHelpers.CreateDraftEventForTimeSlot(day, hour); await OnAddClick.InvokeAsync(draft); return; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cs` around lines 36 - 49, The OnHourClickAsync method only calls State.SetSelectedDate(day) when OnAddClick has a delegate, but not when using the built-in add dialog (when _addDate, _addHour, and _showAddDialog are set). Move the State.SetSelectedDate(day) call outside of the if block so it executes regardless of which path is taken, ensuring the SelectedDate remains consistent across both the delegated callback path and the built-in dialog path.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor-8-10 (1)
8-10:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse calendar month count instead of hardcoded 12.
Line 8 should use the active calendar’s month count (
GetMonthsInYear) to avoid incorrect year rendering in calendars that don’t match a fixed 12-month assumption.Proposed fix
- var months = Enumerable.Range(1, 12) + var monthsInYear = cal.GetMonthsInYear(culturalYear); + var months = Enumerable.Range(1, monthsInYear) .Select(m => cal.ToDateTime(culturalYear, m, 1, 0, 0, 0, 0)) .ToArray();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor` around lines 8 - 10, Replace the hardcoded value 12 in the Enumerable.Range call within the months variable assignment with a dynamic call to the calendar's month count method. Instead of Range(1, 12), use Range(1, cal.GetMonthsInYear(culturalYear)) or the appropriate equivalent method on the cal object to retrieve the actual number of months in the given year, ensuring the code correctly handles calendars with varying month counts.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor-79-80 (1)
79-80:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDrop preview can stick after drag cancellation.
Preview class application should be tied to active drag state; otherwise stale highlights can remain after drag ends outside a drop target.
Suggested fix
- var isPreview = _dragResourceId == rowKey && _dragDay == day.Date; + var isPreview = State.IsDragging && _dragResourceId == rowKey && _dragDay == day.Date; ... - var isPreview = _dragResourceId == rowKey && _dragDay == day.Date; + var isPreview = State.IsDragging && _dragResourceId == rowKey && _dragDay == day.Date;Also applies to: 106-107
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor` around lines 79 - 80, The isPreview condition on lines 79-80 (and also on lines 106-107) only checks if the current cell matches the drag source cell, but does not verify if an active drag operation is in progress. When a drag is cancelled, these variables retain their values, causing stale preview highlights to remain. Add a check for an active drag state (such as a boolean flag tracking whether a drag is currently in progress) to the isPreview condition so that the preview class is only applied when there is both an active drag operation and the cell matches the drag source.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor-60-61 (1)
60-61:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDrop preview can remain visible after drag cancel/end.
Preview styling is computed without checking active drag state, so a canceled drag can leave stale highlighted cells.
Suggested fix
- var isPreviewHour = _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 0; - var isPreviewHalf = _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 30; + var isPreviewHour = State.IsDragging && _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 0; + var isPreviewHalf = State.IsDragging && _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 30; ... - var isPreviewHour = _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 0; - var isPreviewHalf = _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 30; + var isPreviewHour = State.IsDragging && _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 0; + var isPreviewHalf = State.IsDragging && _dragResourceId == rowKey && _dragHour == hour && _dragMinute == 30;Also applies to: 95-96
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor` around lines 60 - 61, The preview styling for drag operations in BitFcTimelineDayView.razor is computed without verifying that an active drag is in progress, allowing stale preview highlighting to persist after a drag is canceled. Add a check to verify that a drag operation is currently active before setting isPreviewHour and isPreviewHalf variables around lines 60-61. Additionally, apply the same fix to the similar preview checks mentioned at lines 95-96. The condition should verify that _dragResourceId is not null or empty and that an active drag state exists before allowing the preview styles to be applied.
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs (1)
90-101: 🏗️ Heavy liftUse deterministic lexical fallback for unknown color IDs.
Line 101 uses a hash-based fallback, which does not implement “unknown ids by name” and can reorder groups between process runs. Prefer a stable secondary textual key at sort callsites (e.g.,
ThenBy(colorId, OrdinalIgnoreCase)).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs` around lines 90 - 101, The GetSortOrder method in BitFullCalendarColorScheme currently uses StringComparer.OrdinalIgnoreCase.GetHashCode() for unknown color IDs, which is non-deterministic across process runs and doesn't implement text-based sorting as documented. Replace the hash-based fallback on line 101 with a deterministic approach that sorts unknown IDs lexically by their string value instead of relying on hash codes, such as computing a value based on the ordinal character values of the trimmed string or implementing a stable text-based comparison alternative.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor (1)
11-16: ⚡ Quick winPre-index week events to avoid repeated linear scans in render.
At Line 14,
FirstOrDefaultover_weekEventsruns inside nested day/row loops, which makes rerenders grow quadratically with event volume. Precompute a(day,row) -> eventlookup inOnParametersSetand render with O(1) lookups.♻️ Proposed optimization
--- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cs @@ - private Dictionary<string, int> _eventRows = new(); + private Dictionary<string, int> _eventRows = new(); + private Dictionary<(DateTime Day, int Row), BitFullCalendarEvent> _weekEventsByDayRow = new(); @@ - _eventRows = new Dictionary<string, int>(); + _eventRows = new Dictionary<string, int>(); + _weekEventsByDayRow = new(); @@ - foreach (var d in evDays) - rowUsageByDay[d.Date].Add(row); + foreach (var d in evDays) + { + var day = d.Date; + rowUsageByDay[day].Add(row); + _weekEventsByDayRow[(day, row)] = ev; + } break; } } }--- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor @@ - var ev = _weekEvents.FirstOrDefault(e => - _eventRows.GetValueOrDefault(e.Id) == r && - e.StartDate.Date <= d.Date && e.EndDate.Date >= d.Date); + _weekEventsByDayRow.TryGetValue((d.Date, r), out var ev);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor` around lines 11 - 16, The FirstOrDefault call over _weekEvents is executed inside nested loops for each day and row, causing quadratic time complexity during rerenders. Create a precomputed lookup dictionary in the OnParametersSet lifecycle method that maps (date, row) tuples to events based on the same filtering criteria (checking _eventRows values and date ranges with StartDate.Date and EndDate.Date comparisons). Then replace the FirstOrDefault logic in the render loop with a simple O(1) dictionary lookup using the current day and row as the key.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cs`:
- Around line 8-21: The RemoveAfterDelay method mutates _toasts without
dispatcher protection on line 19, creating a race condition with the Razor
template's foreach loop. Additionally, delayed removal tasks are never canceled
when the component is disposed. To fix this, wrap the _toasts.RemoveAll() call
inside RemoveAfterDelay with InvokeAsync() to ensure it runs on the renderer
dispatcher. Next, create a collection to track CancellationTokenSource objects
for each delayed removal task, modify RemoveAfterDelay to accept a
CancellationToken and check it after the Task.Delay, and implement
IAsyncDisposable on the component class to cancel all pending removal tasks when
the component is disposed.
---
Major comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cs`:
- Around line 156-159: The ResolveCulture() method in BitFullCalendar.razor.cs
attempts to instantiate CultureInfo with a user-provided name without handling
potential exceptions. Wrap the CultureInfo(name) constructor call in a try-catch
block that catches CultureNotFoundException and falls back to the default
culture (Culture ?? CultureInfo.CurrentUICulture) when an invalid culture name
is provided. This prevents the component initialization from failing due to
invalid CultureName parameter values.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss`:
- Line 3: Remove the `.scss` file extension from the import statement in the
BitFullCalendar.scss file. The import path for the functions partial currently
includes `functions.scss` but should be changed to `functions` (without the
extension) to comply with the scss/load-partial-extension linting rule. Update
the import statement to remove the `.scss` extension while keeping the relative
path and quotes intact.
- Line 197: The keyframe names bfcFadeIn and bfcSlideUp are using camelCase
naming, which violates the stylelint keyframes-name-pattern rule that requires
kebab-case. Rename bfcFadeIn to bfc-fade-in and bfcSlideUp to bfc-slide-up in
both their keyframe definitions (where they are declared with `@keyframes`) and in
all animation property references throughout the BitFullCalendar.scss file.
Ensure all 8 occurrences are updated consistently to use the kebab-case format.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.ts`:
- Around line 113-134: In the endResize function, the OnResizeEnd call must
always execute even if the OnResizeMove invocation fails. Wrap the await
dotNetRef.invokeMethodAsync call for OnResizeMove in a try-finally block, and
move the await dotNetRef.invokeMethodAsync call for OnResizeEnd into the finally
block to guarantee it always executes regardless of whether the OnResizeMove
call succeeds or throws an error. Apply the same fix to the corresponding
endResize function in the other section mentioned at lines 183-204.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor`:
- Around line 16-17: Labels in the BitFcAddEditEventDialog component are not
programmatically associated with their corresponding input controls, which
breaks accessibility for screen readers. Add a unique id attribute to each input
element (the text inputs near the TitleLabel, and other form fields at lines
25-26, 30-31, 39-40, 49-50, and 76-79), then add a for attribute to each label
element that matches the id of its paired input. For example, add
id="_titleInput" to the input with `@bind`="_title" and add for="_titleInput" to
the label for TitleLabel.
- Around line 68-70: The attendee remove button at line 68 is an icon-only
button without an accessible label, which makes it unclear to assistive
technologies. Add an aria-label attribute to the button element that calls
RemoveAttendee(attendee) to provide a descriptive accessible name such as
"Remove attendee" or "Remove [attendee name]" so screen readers can properly
announce the button's purpose to users.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs`:
- Around line 71-74: The OnFocusOut method closes the picker unconditionally
whenever any internal element loses focus, causing the picker to close when
focus moves between internal controls like the trigger button and time/day
controls. Modify the OnFocusOut method to check whether focus is moving to
another element within the component container before closing the picker. You
should verify if the newly focused element (accessible through FocusEventArgs or
related properties) is still a child of the component, and only set _isOpen to
false when focus actually leaves the entire component bounds.
- Around line 54-57: In the SelectDate method, the new DateTime being
constructed uses date.Kind as the DateTimeKind parameter, which can
inadvertently downgrade a previously set Utc or Local kind to Unspecified. To
preserve the bound DateTimeKind, replace date.Kind with Value.Kind when
constructing the selected DateTime object, ensuring the original kind property
is maintained throughout the selection process.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor`:
- Around line 4-11: The icon-only navigation buttons using
State.NavigatePrevious and State.NavigateNext rely only on the title attribute
for accessibility, which may not be consistently announced by assistive
technologies. Add aria-label attributes to both buttons with descriptive text
matching the button's purpose (e.g., "Previous" and "Next"), and also add
type="button" to both button elements to ensure they are semantically correct
and properly recognized by assistive technologies.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor`:
- Around line 8-19: The entire mode tabs container in BitFcModeTabs.razor is
hidden when State.Resources.Count is zero, which traps users in Timeline mode if
resources become empty since they have no UI way to switch back to Event mode.
Remove the outer conditional check on State.Resources.Count so that the mode
tabs remain visible even when resources are empty. Keep the tabs accessible at
all times by rendering the entire div with the foreach loop over _modes and the
State.SetMode(mode) calls regardless of whether State.Resources has items.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor`:
- Around line 12-47: The checkbox inputs in the three dropdown items (for badge
variant toggle, time format toggle, and event layout toggle) and the number
input for day start hour lack proper accessible associations with their labels.
Add unique `id` attributes to each input element (the three checkboxes and the
number input), then update the `label` elements wrapping the checkboxes to
include `for` attributes referencing their corresponding input ids, and for the
number input that doesn't have a wrapping label, add an `aria-labelledby`
attribute that references the id of the span containing DayStartsAtLabel text to
establish the semantic relationship for screen readers.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs`:
- Around line 20-28: The constructor in BitFullCalendarColorScheme keeps a live
reference to the caller-provided options list on line 21 by directly assigning
it to the Options property, while the _byId dictionary is built only once during
construction. If the source list is mutated after construction, Options and the
_byId lookup dictionary can become inconsistent. To fix this, create a defensive
copy/snapshot of the options list (using ToList() or similar) before assigning
it to Options, ensuring that both Options and _byId always represent the same
immutable state regardless of external mutations to the original list.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cs`:
- Line 19: The date.ToString("yyyy-MM-dd") call on the date variable is
culture-sensitive and may produce non-ASCII digits in certain locales, which
will break JavaScript date matching and parsing. Modify the ToString call to
explicitly use CultureInfo.InvariantCulture as the second parameter to ensure
the date is always formatted with ASCII digits in the yyyy-MM-dd format,
regardless of the system locale.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cs`:
- Around line 68-82: The CloneEvent method in BitFullCalendarChangeNotifier
performs a shallow copy of the Data property by directly assigning the reference
instead of creating a deep clone, which violates the deep-snapshot contract.
Modify the Data assignment in the CloneEvent method to deep clone the
source.Data object rather than copying the reference, using an appropriate deep
cloning mechanism such as JSON serialization and deserialization to ensure
mutable objects are not shared between the original and cloned event payloads.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs`:
- Around line 178-186: The EventsMatch method is using reference equality checks
only, which means when parent components modify existing event instances without
changing the reference, SyncEvents skips the update thinking nothing changed.
Update the EventsMatch method to perform deep content-based comparison of the
event properties instead of just ReferenceEquals checks, so that mutations to
existing items are properly detected. Apply the same fix to the SyncResources
method and its corresponding ResourcesMatch comparison method to ensure
consistent behavior across both event and resource synchronization.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cs`:
- Around line 3-90: The BitFcCalendarDayView component displays current events
based on DateTime.Now but never triggers periodic re-renders, causing the
"Happening now" status to become stale during long sessions. Add a timer
mechanism in the component lifecycle (such as in OnInitializedAsync or
OnAfterRenderAsync) that periodically calls StateHasChanged() at regular
intervals (e.g., every minute) to refresh the component and keep the current
event status accurate. Ensure the timer is properly disposed in the component's
cleanup to prevent memory leaks, similar to how the scroll signature is managed
in the existing lifecycle methods.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs`:
- Around line 13-17: In the timer callback initialization for _timer, both
UpdatePosition() and StateHasChanged() must be wrapped inside a single
InvokeAsync call to ensure they execute on the Blazor renderer thread. Currently
UpdatePosition() is called directly on the timer thread before being marshaled,
which can cause race conditions since _positionPx is modified. Move the
UpdatePosition() call inside the InvokeAsync delegate so that both methods
execute atomically on the renderer thread, preventing state modification outside
the renderer's synchronization context.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor`:
- Around line 43-47: The week time slot divs with class bit-bfc-hour-row are
currently only clickable, which excludes keyboard users. Add a keyboard event
handler by binding `@onkeydown` to a new method (OnHourSlotKeyDownAsync) that
accepts KeyboardEventArgs along with the day and hour parameters, and invoke the
existing OnHourClickAsync method when the Enter or Space keys are pressed. Apply
this keyboard handler binding to both affected div elements in the week view
grid (the ones currently showing `@onclick`="() => OnHourClickAsync(d, hour)").
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor`:
- Around line 28-35: The BitFcEventBlock event container div is not
keyboard-accessible, preventing keyboard users from activating event details.
Add the tabindex="0" attribute to the div element to make it focusable, then add
the `@onkeydown`="OnKeyDown" event binding to the same div. Implement the
OnKeyDown method that takes KeyboardEventArgs as a parameter and calls the
existing OnClick method when the user presses Enter or Space keys.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor`:
- Around line 15-21: The icon-only buttons for PrevMonth and NextMonth
navigation lack accessible labels for screen readers, making them inaccessible.
Add aria-label attributes to both buttons with descriptive text like "Previous
month" and "Next month" respectively. Additionally, the day selection elements
(the clickable span elements referenced at lines 43-45) need keyboard support -
convert them to button elements or add keyboard event handlers (onkeydown) to
make them accessible via keyboard navigation, ensuring they can be focused and
activated with Enter/Space keys like standard controls.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cs`:
- Around line 9-15: The `_displayMonth` field is initialized only once in
`OnInitialized()` and can become out of sync with `State.SelectedDate` when the
selected date changes externally. Override the `OnParametersSet()` lifecycle
method in the BitFcMiniCalendar component to synchronize `_displayMonth`
whenever parameters change, using the same logic that calculates `_displayMonth`
from `State.SelectedDate` as in `OnInitialized()`. This ensures `_displayMonth`
stays synchronized with external changes to the selected date.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor`:
- Around line 8-12: The clickable div elements in the BitFcDayCell component
(around line 8 with the OnCellClick handler and the additional clickable element
around line 44) do not support keyboard navigation and activation, making them
inaccessible to keyboard users. Convert these interactive divs to proper
keyboard-accessible controls by adding a tabindex attribute to make them
focusable, an ARIA role to identify them as interactive elements, and keyboard
event handlers (`@onkeydown` or `@onkeyup`) that trigger the same OnCellClick action
when Enter or Space keys are pressed, matching the click behavior.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor`:
- Around line 19-25: The BitFcMonthEventBadge component's event badge div is not
keyboard-accessible. Add tabindex="0" to the div element to make it focusable,
and add an `@onkeydown` event handler that detects Enter or Space key presses and
invokes OnSelected.InvokeAsync(Event) when those keys are pressed, matching the
behavior of the existing click handler for keyboard users.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cs`:
- Line 18: The constant _scrollContainerId in the BitFcTimelineDayView component
uses a fixed DOM id that can collide when multiple calendar instances render on
the same page. Change _scrollContainerId from a constant to an instance field
that generates a unique identifier per component instance (such as using a GUID
or unique suffix), ensuring each calendar instance has its own unique scroll
container id to prevent the scrollTimelineToTarget method from operating on the
wrong element.
- Around line 72-85: The OnSlotClickAsync method accepts a minute parameter but
discards it in the internal add flow when OnAddClick is not delegated. Store the
minute value by adding a field similar to _addStartHour (for example,
_addStartMinute), then assign the minute parameter to this field when setting
_showAddDialog to true. Next, pass this stored minute value to the
BitFcAddEditEventDialog component by updating its parameters, and ensure the
dialog component supports and respects the minute parameter when initializing
the time selection to preserve half-hour slot precision.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cs`:
- Around line 71-74: The catch block in BitFcTimelineEventBlock.razor.cs
currently only catches JSException, but common Blazor lifecycle exceptions like
JSDisconnectedException, InvalidOperationException, and
OperationCanceledException can also be thrown during interop calls and will
crash the render if not handled. Expand the catch clause to handle all these
exception types alongside JSException so they are properly swallowed and the
render retry logic is executed for all expected failure scenarios.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor`:
- Around line 23-27: The `!hasResources` conditional in
BitFcTimelineLayout.razor prevents the rendering of unassigned event rows
because the else block never executes when hasResources is false. Restructure
the logic to ensure that the unassigned-row rendering (referenced at lines
58-70) is not blocked by the !hasResources check. Either move the unassigned row
rendering outside of or before the hasResources conditional, or add a separate
condition that allows unassigned events to display independently of whether
resources exist.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs`:
- Line 18: The _scrollContainerId constant in BitFcTimelineMonthView is
hardcoded, causing ID collisions when multiple calendar instances are rendered.
Replace the const declaration with a property or field that generates a unique
identifier per component instance (such as using a Guid or unique prefix based
on component state), ensuring each rendered timeline month view has a distinct
scroll container id that won't conflict with other instances on the same page.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor`:
- Around line 21-26: The code filters out null/empty resource IDs on line 21,
but then uses unguarded dictionary lookups with resource.Id and rowKey as keys
on lines 60, 91, and 126 without verifying they are not null or empty. Add guard
conditions before each dictionary lookup at these locations to check if the
resource ID or rowKey is null or empty, and either skip the operation or provide
a safe fallback to prevent runtime exceptions when rendering rows with invalid
resource identifiers.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cs`:
- Line 18: The constant _scrollContainerId with a hardcoded value
"bit-bfc-tl-week-scroll" will cause id collisions when multiple calendar
instances are rendered on the same page. Replace this constant with a
per-instance field that generates a unique scroll container id for each
BitFcTimelineWeekView component instance, such as using a generated guid or
unique identifier that is assigned when the component initializes.
- Around line 74-87: The OnSlotClickAsync method receives a minute parameter but
only uses it when OnAddClick has a delegate. In the fallback branch where the
built-in add dialog is shown (lines 84-86), the minute value is ignored. Store
the minute parameter in a new field (similar to how _addStartHour stores the
hour) such as _addStartMinute, and ensure this field is set when _showAddDialog
is set to true. Additionally, verify that the BitFcAddEditEventDialog component
uses this _addStartMinute field when initializing the event time, adding support
for StartMinute if it does not currently exist.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor`:
- Around line 21-22: The div elements with click handlers at lines 21-22 and
40-41 in BitFcCalendarYearView.razor lack keyboard accessibility, preventing
keyboard-only users from navigating. Add keyboard event support to both div
elements by implementing an onkeydown event handler that triggers the same
action (GoToMonth call at line 21 and the day/event navigation at line 40) when
Enter or Space keys are pressed. Additionally, add appropriate ARIA attributes
(role and tabindex) to make these divs focusable and semantically indicate they
are interactive elements to assistive technologies.
- Around line 37-38: The dayEvents filter in BitFcCalendarYearView.razor uses
only StartDate.Date comparison, which excludes multi-day events from
intermediate and end dates. Modify the Where clause to check if cell.Date falls
within a date-range overlap by comparing against both the event's StartDate and
EndDate properties, ensuring a multi-day event is included on every day it
spans, not just its start date.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Line 7: The stylelint rule scss/load-partial-extension is being violated in
the extra-components.scss file. Remove the explicit .scss file extension from
the `@import` statement for BitFullCalendar - the stylelint rule requires that
SCSS partials be imported without their file extension, so the import should
reference only the directory path and filename without the .scss suffix.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor`:
- Around line 18-23: The BitLink component in BitFullCalendarDemo.razor has
Target="_blank" set to open an external link in a new tab, but it is missing the
rel attribute required for security. Add rel="noopener noreferrer" to the
BitLink component that points to the NuGet package URL to prevent
reverse-tabnabbing vulnerabilities and properly isolate the opener context when
opening external links in a new tab.
---
Minor comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cs`:
- Around line 19-23: The OnEditClose() method invokes the OnClose callback
asynchronously but does not await the result, which can cause the callback to
not complete properly. Change the OnEditClose() method signature from void to
async Task, and add the await keyword before the OnClose.InvokeAsync() call to
ensure the asynchronous operation completes before the method returns.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor`:
- Line 6: In the BitFcEventListDialog.razor component's h3 element, the date
formatting using Date.ToString("dddd, MMM d, yyyy") does not respect the
calendar's culture setting. Modify the Date.ToString call to include
State.Culture as a culture parameter so that the date is formatted according to
the calendar's culture instead of the default culture. This will ensure the date
header displays in the correct localized format.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor`:
- Around line 20-23: The button element with the OnAddEventClick handler in
BitFcCalendarHeader.razor lacks an explicit type attribute, causing it to
default to type="submit" per HTML specification. This can trigger unintended
form submission if the FullCalendar component is placed within a form context.
Add type="button" explicitly to the button element that contains the
OnAddEventClick event handler to ensure it only calls the click handler and does
not submit any parent form.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cs`:
- Line 49: Add the `required` keyword to the Source property in the
BitFullCalendarChangeEventArgs class to force callers to explicitly assign a
BitFullCalendarChangeSource value, preventing silent defaults to Dialog (the
zero enum value) which can cause incorrect origin metadata in change payloads.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs`:
- Around line 25-27: The IsSingleDay property at line 25 of BitFullCalendarEvent
class does not treat midnight EndDate as exclusive, causing events ending at
00:00 of the next day to be incorrectly classified as multi-day. Fix this by
adjusting the Date comparison in the IsSingleDay property to subtract one tick
or unit of time from EndDate before comparing dates, ensuring that an EndDate at
midnight is treated as the end of the previous day rather than the start of the
next day.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs`:
- Around line 213-218: The FormatTime method is using
CultureInfo.InvariantCulture for both the 24-hour and 12-hour time format calls,
which prevents localization for non-English cultures. Replace
CultureInfo.InvariantCulture with CultureInfo.CurrentCulture in both
date.ToString() calls within the FormatTime method to respect the user's active
culture settings. Apply the same fix to the similar time formatting code
mentioned in the "Also applies to" section around lines 248-254.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cs`:
- Around line 36-49: The OnHourClickAsync method only calls
State.SetSelectedDate(day) when OnAddClick has a delegate, but not when using
the built-in add dialog (when _addDate, _addHour, and _showAddDialog are set).
Move the State.SetSelectedDate(day) call outside of the if block so it executes
regardless of which path is taken, ensuring the SelectedDate remains consistent
across both the delegated callback path and the built-in dialog path.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor`:
- Around line 60-61: The preview styling for drag operations in
BitFcTimelineDayView.razor is computed without verifying that an active drag is
in progress, allowing stale preview highlighting to persist after a drag is
canceled. Add a check to verify that a drag operation is currently active before
setting isPreviewHour and isPreviewHalf variables around lines 60-61.
Additionally, apply the same fix to the similar preview checks mentioned at
lines 95-96. The condition should verify that _dragResourceId is not null or
empty and that an active drag state exists before allowing the preview styles to
be applied.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor`:
- Around line 79-80: The isPreview condition on lines 79-80 (and also on lines
106-107) only checks if the current cell matches the drag source cell, but does
not verify if an active drag operation is in progress. When a drag is cancelled,
these variables retain their values, causing stale preview highlights to remain.
Add a check for an active drag state (such as a boolean flag tracking whether a
drag is currently in progress) to the isPreview condition so that the preview
class is only applied when there is both an active drag operation and the cell
matches the drag source.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor`:
- Around line 8-10: Replace the hardcoded value 12 in the Enumerable.Range call
within the months variable assignment with a dynamic call to the calendar's
month count method. Instead of Range(1, 12), use Range(1,
cal.GetMonthsInYear(culturalYear)) or the appropriate equivalent method on the
cal object to retrieve the actual number of months in the given year, ensuring
the code correctly handles calendars with varying month counts.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor`:
- Line 5: The Description attribute text in the BitFullCalendarDemo.razor
component has awkward wording and inconsistent casing. Update the Description
property to use proper casing for "FullCalendar" (currently lowercase) and
simplify the text to remove redundancy. Instead of "fullcalendar component of
the bit BlazorUI components", use clearer phrasing such as "FullCalendar
component for Bit BlazorUI" to improve readability and consistency for
user-facing documentation.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs`:
- Around line 90-101: The GetSortOrder method in BitFullCalendarColorScheme
currently uses StringComparer.OrdinalIgnoreCase.GetHashCode() for unknown color
IDs, which is non-deterministic across process runs and doesn't implement
text-based sorting as documented. Replace the hash-based fallback on line 101
with a deterministic approach that sorts unknown IDs lexically by their string
value instead of relying on hash codes, such as computing a value based on the
ordinal character values of the trimmed string or implementing a stable
text-based comparison alternative.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor`:
- Around line 11-16: The FirstOrDefault call over _weekEvents is executed inside
nested loops for each day and row, causing quadratic time complexity during
rerenders. Create a precomputed lookup dictionary in the OnParametersSet
lifecycle method that maps (date, row) tuples to events based on the same
filtering criteria (checking _eventRows values and date ranges with
StartDate.Date and EndDate.Date comparisons). Then replace the FirstOrDefault
logic in the render loop with a simple O(1) dictionary lookup using the current
day and row as the key.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e0daf90b-d30d-468a-b05d-3f9abc65f4a8
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 20
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (6)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cs-16-17 (1)
16-17:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winValidate
StartOfDayHouragainst the documented 0–16 range.Line 17 accepts any integer even though the public contract documents 0–16, and the value is applied directly in
BitFullCalendar.razor.cs(Lines 199-210). Add clamping or validation to prevent out-of-range runtime behavior.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cs` around lines 16 - 17, The StartOfDayHour property in BitFullCalendarOptions class lacks validation for the documented 0-16 range constraint, allowing any integer value to be set. This causes runtime issues when the unconstrained value is applied in BitFullCalendar.razor.cs. Add validation logic to the StartOfDayHour property setter to enforce the 0-16 range by either clamping the value using Math.Clamp or throwing an ArgumentException if an out-of-range value is provided, ensuring the property contract matches its documentation.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs-83-87 (1)
83-87:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse current UI culture when
cultureis omitted inStartOfWeek.Line 85 falls back to
DayOfWeek.Sundayinstead ofCultureInfo.CurrentUICulture, which makes this helper inconsistent with other culture-aware methods and can produce incorrect week boundaries for callers that passnull.Suggested fix
public static DateTime StartOfWeek(DateTime date, CultureInfo? culture = null) { - var startDay = culture?.DateTimeFormat.FirstDayOfWeek ?? DayOfWeek.Sunday; + culture ??= CultureInfo.CurrentUICulture; + var startDay = culture.DateTimeFormat.FirstDayOfWeek; return StartOfWeek(date, startDay); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs` around lines 83 - 87, The StartOfWeek method currently falls back to DayOfWeek.Sunday when the culture parameter is null, instead of using the current UI culture. Modify the startDay assignment in the StartOfWeek method to use CultureInfo.CurrentUICulture.DateTimeFormat.FirstDayOfWeek as the fallback instead of DayOfWeek.Sunday. This will make the method consistent with other culture-aware methods and properly respect regional week start conventions when no culture is explicitly provided.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor-4-7 (1)
4-7:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPrevent browser default behavior on drop.
dropshould also prevent default to avoid accidental browser navigation/content handling on external drops.Suggested fix
<div class="bit-bfc-droppable @(_isOver ? "drag-over" : "") `@Class`" `@ondragover`="OnDragOver" `@ondragover`:preventDefault="true" `@ondragleave`="OnDragLeave" - `@ondrop`="OnDrop"> + `@ondrop`="OnDrop" + `@ondrop`:preventDefault="true">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor` around lines 4 - 7, The `@ondrop` event binding in the BitFcDroppableArea component is missing the preventDefault directive that is already applied to `@ondragover`. Add the :preventDefault="true" modifier to the `@ondrop` binding (similar to how it is applied to `@ondragover`) to ensure the browser's default behavior is prevented when items are dropped on the droppable area, avoiding accidental navigation or unwanted content handling from external drops.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor-13-14 (1)
13-14:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winSet explicit button type to prevent accidental form submission.
These mode-tab buttons should be
type="button"; otherwise default submit behavior can fire when the calendar is placed inside a form.Suggested patch
- <button class="bit-bfc-mode-tab @(State.Mode == mode ? "active" : "")" + <button type="button" class="bit-bfc-mode-tab @(State.Mode == mode ? "active" : "")" `@onclick`="() => State.SetMode(mode)">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor` around lines 13 - 14, Add an explicit type="button" attribute to the button element with class "bit-bfc-mode-tab" to prevent it from defaulting to type submit and causing accidental form submissions when the calendar component is placed within a form. This ensures the button only triggers the onclick handler without submitting any parent form.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs-12-23 (1)
12-23:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlign the first timer tick to the next minute boundary.
Line 22 schedules the first refresh exactly 60 seconds after init, which can keep the “current time” marker one minute behind clock boundaries. Aligning initial due-time to the next minute makes updates accurate on
HH:mmtransitions.Suggested fix
protected override void OnInitialized() { UpdatePosition(); + var now = DateTime.Now; + var due = TimeSpan.FromMinutes(1) + - TimeSpan.FromSeconds(now.Second) + - TimeSpan.FromMilliseconds(now.Millisecond); + if (due <= TimeSpan.Zero) due = TimeSpan.FromMinutes(1); + _timer = new Timer(_ => { // Run both the state mutation and the re-render on the renderer's dispatcher so // _positionPx is never modified outside the synchronization context. InvokeAsync(() => { UpdatePosition(); StateHasChanged(); }); - }, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); + }, null, due, TimeSpan.FromMinutes(1)); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs` around lines 12 - 23, The Timer in the BitFcCalendarTimeline component is configured with an initial due time of one minute, which causes the first refresh to occur one minute after initialization rather than at the next minute boundary. This misalignment can leave the "current time" marker behind by up to 60 seconds. Calculate the time remaining until the next minute boundary by finding the current time's seconds and milliseconds, then subtracting from one minute, and use this calculated TimeSpan as the dueTime parameter in the Timer constructor instead of TimeSpan.FromMinutes(1), keeping TimeSpan.FromMinutes(1) as the period for subsequent ticks. This ensures UpdatePosition is called at clock minute transitions rather than arbitrary intervals.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs-115-121 (1)
115-121:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid repeated scroll interop when selected month is not the current month.
When no “today” target exists, this path retries JS interop every render. Add a month guard and cache the signature to prevent unnecessary calls.
Proposed change
protected override async Task OnAfterRenderAsync(bool firstRender) { var sig = $"{State.SelectedDate:yyyy-MM}|{DateTime.Today:yyyy-MM-dd}"; if (sig == _scrollSignature) return; + var cal = State.Culture.Calendar; + var today = DateTime.Today; + var selectedYear = cal.GetYear(State.SelectedDate); + var selectedMonth = cal.GetMonth(State.SelectedDate); + var todayYear = cal.GetYear(today); + var todayMonth = cal.GetMonth(today); + if (selectedYear != todayYear || selectedMonth != todayMonth) + { + _scrollSignature = sig; + return; + } + if (await BitFcTimelineScrollInterop.TryScrollToTargetAsync(JS, _scrollContainerId)) _scrollSignature = sig; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs` around lines 115 - 121, The OnAfterRenderAsync method calls BitFcTimelineScrollInterop.TryScrollToTargetAsync on every render even when the selected month is not the current month, resulting in unnecessary JavaScript interop calls since there is no "today" target to scroll to in those cases. Add a guard condition before calling BitFcTimelineScrollInterop.TryScrollToTargetAsync that checks whether State.SelectedDate (year and month) matches DateTime.Today (year and month), so the interop only executes when the selected month is the current month. Keep the existing _scrollSignature caching logic to prevent duplicate calls within the same month.
🧹 Nitpick comments (4)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cs (1)
3-10: ⚡ Quick winAdd XML documentation for consistency.
BitFullCalendarView lacks documentation while BitFullCalendarEventLayout and BitFullCalendarMode have comprehensive XML doc comments. Adding documentation would improve consistency across the public enum API and help developers understand which views are supported in different modes.
📝 Suggested documentation
+/// <summary> +/// Calendar view types available in Event mode. +/// Note: Timeline mode supports only Day, Week, and Month views. +/// </summary> public enum BitFullCalendarView { + /// <summary>Single day view with hourly time grid.</summary> Day, + /// <summary>Seven-day week view with hourly time grid.</summary> Week, + /// <summary>Month grid view showing all days and weeks of the month.</summary> Month, + /// <summary>Full year view with all months.</summary> Year, + /// <summary>Chronological agenda/list view groupable by date or color.</summary> Agenda }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cs` around lines 3 - 10, Add XML documentation comments to the BitFullCalendarView enum and all its members (Day, Week, Month, Year, Agenda) to match the documentation style and completeness of BitFullCalendarEventLayout and BitFullCalendarMode. Include a summary comment for the enum itself explaining its purpose as the supported calendar view types, and add brief documentation for each enum member describing what each view represents or when it should be used.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor (1)
43-45: ⚡ Quick winUse a semantic button for day selection.
The current clickable
<span>is not keyboard-friendly. Converting it to a<button>improves accessibility with minimal change.Proposed change
- <span class="bit-bfc-mini-calendar-day `@cls`" `@onclick`="() => SelectDate(cell.Date)"> - `@cell.Day` - </span> + <button type="button" + class="bit-bfc-mini-calendar-day `@cls`" + `@onclick`="() => SelectDate(cell.Date)" + aria-pressed="@(isSelected.ToString().ToLowerInvariant())"> + `@cell.Day` + </button>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor` around lines 43 - 45, Replace the non-semantic `<span>` element used for day selection in the BitFcMiniCalendar component with a `<button>` element to improve accessibility and keyboard navigation. The span element with the class "bit-bfc-mini-calendar-day" and the `@onclick` handler for SelectDate should be converted to a button while preserving the class binding, the onclick handler that calls SelectDate(cell.Date), and the displayed content `@cell.Day`.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor (1)
40-44: 🏗️ Heavy liftMake resize handles keyboard-accessible.
The resize affordances are pointer-only, so keyboard users cannot perform duration edits from this component. Please add a keyboard path (focusable handle + key bindings) with accessible semantics.
Also applies to: 68-72
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor` around lines 40 - 44, The resize handles in BitFcEventBlock are only accessible via pointer events, preventing keyboard users from resizing events. Make the resize handles keyboard-accessible by adding tabindex="0" to make them focusable, adding keyboard event handlers (like `@onkeydown`) alongside the existing `@onpointerdown` handlers to respond to arrow keys or Enter, and including appropriate ARIA attributes such as role="button" and aria-label to describe the handle's purpose. Apply these changes to both the top resize handle (with _topHandleId) and the bottom resize handle referenced in the "Also applies to" comment at lines 68-72.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor (1)
80-86: ⚡ Quick winMake timeline slot cells keyboard-operable.
These clickable
<div>slots currently require a pointer. Add focusability + keyboard activation to support keyboard users for slot-based add interactions.Also applies to: 107-113
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor` around lines 80 - 86, The `<div>` element with class "bit-bfc-tl-cell" is only operable via mouse click. To make it keyboard-accessible, add the tabindex="0" attribute to the div to make it focusable, then add an `@onkeydown` event handler that detects Enter or Space key presses and calls the same OnSlotClickAsync(rowKey, day) method that the `@onclick` handler uses. Apply the same changes to all similar timeline slot cell elements throughout the component (also at lines 107-113).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cs`:
- Around line 6-7: The BitFcCalendarToast component stores
CancellationTokenSource objects in the _removalTokens list but never removes
them after they are no longer needed, only cleaning them up at component
disposal. To prevent unbounded list growth on long-lived pages, remove each
CancellationTokenSource from the _removalTokens list after its associated toast
timer completes or the toast is manually dismissed. Locate where new
CancellationTokenSource instances are added to _removalTokens around line 16 and
the disposal logic at line 39, then add cleanup logic that removes the token
from the list immediately after the timeout or dismissal occurs rather than
waiting for component disposal.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss`:
- Line 3: Remove the .scss file extension from the import statement on line 3
where "functions.scss" is being imported, changing it to just "functions" to
comply with the scss/load-partial-extension rule. Additionally, locate the
keyframe definitions around lines 200 and 1106 in the BitFullCalendar.scss file
and rename them to follow the keyframes-name-pattern convention, which typically
requires lowercase names with hyphens rather than camelCase or other formats.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.ts`:
- Around line 104-141: The onPointerMove callback and endResize function
currently process events from any pointer instead of just the pointer that
initiated the resize operation. Add a check in the onPointerMove function to
verify that the incoming event's pointerId matches the activePointerId before
updating latestY. Similarly, in the endResize function, verify that the
triggering pointer's pointerId matches activePointerId before executing the
resize end logic. This ensures that multi-pointer input on touch or pen devices
only responds to movement and events from the pointer that started the resize
operation. Apply the same gate logic to the second occurrence of these event
handlers mentioned in the comment (lines 179-215).
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs`:
- Around line 71-74: The OnFocusOut method unconditionally closes the panel by
setting _isOpen to false, which causes it to close prematurely when users
interact with child controls. Instead of always closing, modify the OnFocusOut
method to check whether the focus is moving to a child element within the picker
component or genuinely leaving it entirely. You can inspect the relatedTarget
property from the FocusEventArgs to determine if focus is moving to an internal
child element (in which case keep the picker open) or if it's moving outside the
component (in which case close it). Alternatively, implement a small delay
before closing to allow child click handlers to execute, then check if focus has
returned to the picker before proceeding with the close operation.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor`:
- Around line 3-8: The BitFcDraggableEvent component's interactive div element
is currently not keyboard-accessible. To fix this, add keyboard event handling
to the div by adding an `@onkeydown` event handler that triggers the same OnClick
behavior when the Enter or Space key is pressed, and add a tabindex="0"
attribute to make the div focusable for keyboard users. This ensures that
keyboard users can interact with the draggable event the same way mouse users
can through the click handler.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor`:
- Around line 54-63: The Agenda Group By options use non-semantic div elements
with `@onclick` handlers which are not keyboard-accessible or focusable. Replace
both div elements (the one with
SetAgendaModeGroupBy(BitFullCalendarAgendaGroupBy.Date) and the one with
SetAgendaModeGroupBy(BitFullCalendarAgendaGroupBy.Color)) with button elements
instead. Keep all the same class bindings, style bindings, and click handlers
intact, but change the element type from div to button to make them properly
focusable and keyboard-operable.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cs`:
- Around line 14-43: The Defaults property in the BitFullCalendarColorOption
class exposes a list of mutable objects that can be modified by consumers,
causing global side effects across all calendar instances. Make the
BitFullCalendarColorOption class immutable by converting it to a record type or
by changing the Id, Title, and Value properties to use init-only accessors
instead of set accessors. This ensures that the default color instances returned
from the Defaults property cannot be mutated after initialization.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs`:
- Around line 20-29: The snapshot of options in the BitFullCalendarColorScheme
constructor is shallow, copying only list references not the individual
BitFullCalendarColorOption objects themselves. This means if any
BitFullCalendarColorOption (especially its Id property) is mutated after
construction, the _byId dictionary will become out of sync with the Options
list. To fix this, perform a deep copy of each BitFullCalendarColorOption object
when populating the Options collection, and build the _byId dictionary from this
deep-copied Options collection to ensure the lookup and options list remain
consistent even if the original objects are mutated later.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs`:
- Around line 8-9: The BitFullCalendarEvent model allows invalid event ranges
where EndDate could be less than StartDate, resulting in a negative duration
calculation at line 27 that propagates to the HandleDrop method in
BitFullCalendarState and causes invalid state updates. Add validation in the
BitFullCalendarEvent class (either in property setters for StartDate and EndDate
or in a constructor) to enforce the invariant that EndDate must be greater than
or equal to StartDate, rejecting any attempt to create or update an event with
an inverted date range at the model boundary before the invalid data reaches the
drag/drop logic.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs`:
- Around line 510-515: The Where clause filtering events in the day range check
is inconsistent with how GroupEventsByDayRange handles exclusive midnight
boundaries. Currently using ev.EndDate.Date treats midnight as inclusive,
causing events ending at 00:00 to appear on the next day. Modify the EndDate
logic in this Where clause (around the line with ev.EndDate.Date) to match the
exclusive-midnight handling already implemented in GroupEventsByDayRange at line
375, ensuring events ending at midnight do not appear as carry-over in
subsequent month cells.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs`:
- Around line 178-186: The SyncEvents method short-circuits when EventsMatch
returns true on lines 180-181 without calling ApplyFilters on line 184, causing
filtered events to become stale when individual event objects are mutated
in-place (such as Color or attendees changes). Remove the early return condition
or restructure the method to ensure ApplyFilters and NotifyStateChanged are
always executed, even when the event list structure matches. This same issue
also exists in the other similar code block around lines 216-227.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor`:
- Line 47: The search input element in BitFcAgendaEvents.razor lacks an
accessible label for screen readers, and the event rows referenced at lines
62-63 appear to be clickable divs rather than semantic interactive elements. Add
an associated label element (using for attribute) or aria-label to the search
input to describe its purpose, and convert the event row divs to button elements
or add proper ARIA role, tabindex, and keyboard event handlers to make them
accessible to keyboard and screen reader users.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor`:
- Around line 34-38: The div elements used for hourly time slots in
BitFcCalendarDayView.razor (such as the div with class "bit-bfc-hour-row
bit-bfc-droppable" and `@onclick` handler "OnHourClickAsync") lack keyboard
accessibility, preventing keyboard-only users from creating events. Convert
these div elements to semantic button elements or add appropriate ARIA
attributes (role="button", tabindex, and `@onkeydown` handlers) to enable keyboard
interaction. Apply this fix to all similar time-slot divs including those around
the mentioned lines, ensuring both mouse clicks and keyboard events (Enter/Space
keys) trigger the OnHourClickAsync method.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor`:
- Around line 35-37: The current filtering logic in the Where clause for
dayEvents uses date equality checks (e.StartDate.Date == d.Date ||
e.EndDate.Date == d.Date) which fails to correctly identify overlapping events,
particularly for events spanning multiple days or with exclusive end times.
Replace this equality-based filtering with proper interval overlap logic that
checks if the event overlaps with the current day using the condition:
event.StartDate is before the day's end AND event.EndDate is after the day's
start. This ensures all events that have any overlap with the day column are
included in dayEvents for the GroupEvents operation.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor`:
- Around line 19-22: Add a `@key` directive to the BitFcDayCell component in the
foreach loop that iterates over cells to prevent Blazor from reusing component
instances by position when the month data changes. Use a unique identifier from
the cell object (such as the cell's date or a unique ID property) as the key
value to ensure each day cell maintains its own state and prevents stale UI
state like open dialogs from appearing in the wrong date cell.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor`:
- Around line 8-12: The BitFcDayCell component's interactive div element is
currently only accessible via mouse clicks. To make it keyboard-accessible, add
tabindex="0" and role="button" attributes to the div element containing the
bit-bfc-month-cell class, then add an `@onkeydown` event handler that calls a new
OnCellKeyDown method. In the BitFcDayCell.razor.cs code-behind file, implement
the OnCellKeyDown handler that checks if the pressed key is Enter or Space, and
if so, awaits the OnCellClick() method to perform the same action as the click
handler.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor`:
- Around line 108-121: The div elements with classes bit-bfc-tl-cell and
bit-bfc-tl-cell-half are currently non-focusable and only respond to mouse
events (onclick, ondrop, ondragenter), preventing keyboard-only users from
interacting with them. Make these elements keyboard-accessible by either
converting them to button elements with appropriate aria-labels, or keeping them
as divs but adding tabindex="0" to make them focusable and adding keyboard event
handlers (such as `@onkeydown`) that trigger the same OnSlotClickAsync and event
handler methods when Enter or Space keys are pressed.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor`:
- Around line 31-38: The code is performing an expensive linear search through
all events for every cell in the year view, creating an O(cells × events)
performance bottleneck. Before the foreach loop that iterates over cells,
pre-compute a dictionary or lookup structure that maps dates to their
corresponding events from the allEvents collection. Then inside the foreach loop
in BitFcCalendarYearView.razor, replace the Where query with a simple dictionary
lookup using cell.Date.Date as the key to retrieve the dayEvents, eliminating
the per-cell scanning of all events.
- Around line 40-42: The year-day cell container (the div with class
bit-bfc-year-day) is using a clickable div element which is not
keyboard-accessible by default. To fix this in the BitFcCalendarYearView
component, replace the div with a button element (or add keyboard event handlers
like `@onkeydown` for Enter/Space keys along with tabindex="0" and appropriate
ARIA attributes if a button is not suitable). This will ensure that users can
open the ShowEventsForDay event list using keyboard navigation, making the
component fully accessible.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Line 7: The import statement for BitFullCalendar includes the `.scss` file
extension, which violates the stylelint scss/load-partial-extension rule. Remove
the `.scss` extension from the import path in the statement `@import
"../Components/FullCalendar/BitFullCalendar.scss";` so that it imports the
partial without the extension, allowing Stylelint to properly validate the
import and preventing pipeline check failures.
---
Minor comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor`:
- Around line 4-7: The `@ondrop` event binding in the BitFcDroppableArea component
is missing the preventDefault directive that is already applied to `@ondragover`.
Add the :preventDefault="true" modifier to the `@ondrop` binding (similar to how
it is applied to `@ondragover`) to ensure the browser's default behavior is
prevented when items are dropped on the droppable area, avoiding accidental
navigation or unwanted content handling from external drops.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor`:
- Around line 13-14: Add an explicit type="button" attribute to the button
element with class "bit-bfc-mode-tab" to prevent it from defaulting to type
submit and causing accidental form submissions when the calendar component is
placed within a form. This ensures the button only triggers the onclick handler
without submitting any parent form.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cs`:
- Around line 16-17: The StartOfDayHour property in BitFullCalendarOptions class
lacks validation for the documented 0-16 range constraint, allowing any integer
value to be set. This causes runtime issues when the unconstrained value is
applied in BitFullCalendar.razor.cs. Add validation logic to the StartOfDayHour
property setter to enforce the 0-16 range by either clamping the value using
Math.Clamp or throwing an ArgumentException if an out-of-range value is
provided, ensuring the property contract matches its documentation.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs`:
- Around line 83-87: The StartOfWeek method currently falls back to
DayOfWeek.Sunday when the culture parameter is null, instead of using the
current UI culture. Modify the startDay assignment in the StartOfWeek method to
use CultureInfo.CurrentUICulture.DateTimeFormat.FirstDayOfWeek as the fallback
instead of DayOfWeek.Sunday. This will make the method consistent with other
culture-aware methods and properly respect regional week start conventions when
no culture is explicitly provided.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs`:
- Around line 12-23: The Timer in the BitFcCalendarTimeline component is
configured with an initial due time of one minute, which causes the first
refresh to occur one minute after initialization rather than at the next minute
boundary. This misalignment can leave the "current time" marker behind by up to
60 seconds. Calculate the time remaining until the next minute boundary by
finding the current time's seconds and milliseconds, then subtracting from one
minute, and use this calculated TimeSpan as the dueTime parameter in the Timer
constructor instead of TimeSpan.FromMinutes(1), keeping TimeSpan.FromMinutes(1)
as the period for subsequent ticks. This ensures UpdatePosition is called at
clock minute transitions rather than arbitrary intervals.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs`:
- Around line 115-121: The OnAfterRenderAsync method calls
BitFcTimelineScrollInterop.TryScrollToTargetAsync on every render even when the
selected month is not the current month, resulting in unnecessary JavaScript
interop calls since there is no "today" target to scroll to in those cases. Add
a guard condition before calling
BitFcTimelineScrollInterop.TryScrollToTargetAsync that checks whether
State.SelectedDate (year and month) matches DateTime.Today (year and month), so
the interop only executes when the selected month is the current month. Keep the
existing _scrollSignature caching logic to prevent duplicate calls within the
same month.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cs`:
- Around line 3-10: Add XML documentation comments to the BitFullCalendarView
enum and all its members (Day, Week, Month, Year, Agenda) to match the
documentation style and completeness of BitFullCalendarEventLayout and
BitFullCalendarMode. Include a summary comment for the enum itself explaining
its purpose as the supported calendar view types, and add brief documentation
for each enum member describing what each view represents or when it should be
used.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor`:
- Around line 40-44: The resize handles in BitFcEventBlock are only accessible
via pointer events, preventing keyboard users from resizing events. Make the
resize handles keyboard-accessible by adding tabindex="0" to make them
focusable, adding keyboard event handlers (like `@onkeydown`) alongside the
existing `@onpointerdown` handlers to respond to arrow keys or Enter, and
including appropriate ARIA attributes such as role="button" and aria-label to
describe the handle's purpose. Apply these changes to both the top resize handle
(with _topHandleId) and the bottom resize handle referenced in the "Also applies
to" comment at lines 68-72.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor`:
- Around line 43-45: Replace the non-semantic `<span>` element used for day
selection in the BitFcMiniCalendar component with a `<button>` element to
improve accessibility and keyboard navigation. The span element with the class
"bit-bfc-mini-calendar-day" and the `@onclick` handler for SelectDate should be
converted to a button while preserving the class binding, the onclick handler
that calls SelectDate(cell.Date), and the displayed content `@cell.Day`.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor`:
- Around line 80-86: The `<div>` element with class "bit-bfc-tl-cell" is only
operable via mouse click. To make it keyboard-accessible, add the tabindex="0"
attribute to the div to make it focusable, then add an `@onkeydown` event handler
that detects Enter or Space key presses and calls the same
OnSlotClickAsync(rowKey, day) method that the `@onclick` handler uses. Apply the
same changes to all similar timeline slot cell elements throughout the component
(also at lines 107-113).
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 41c6cbda-5cbb-4b9d-844e-f448795bf9ba
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 16
🧹 Nitpick comments (3)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cs (1)
15-16: ⚡ Quick winAvoid redundant drag-over state writes.
ondragoverfires continuously; setting_isOver = trueeach time can cause unnecessary re-renders.Suggested fix
- private void OnDragOver() => _isOver = true; - private void OnDragLeave() => _isOver = false; + private void OnDragOver() + { + if (_isOver) return; + _isOver = true; + } + + private void OnDragLeave() + { + if (_isOver is false) return; + _isOver = false; + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cs` around lines 15 - 16, The OnDragOver method continuously sets _isOver to true every time the ondragover event fires, causing unnecessary re-renders even when the value is already true. Add a guard condition in the OnDragOver method to check if _isOver is already true before assigning the value, so that a re-render is only triggered when the state actually transitions from false to true.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cs (1)
68-82: ⚡ Quick win
CloneEventdocumentation overstates deep-copy behavior.
Datais copied by reference on Line 81, so this is not a full deep snapshot. Either deep-cloneData(if supported) or adjust the XML docs to avoid a misleading contract.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cs` around lines 68 - 82, The CloneEvent method's XML documentation claims to create a deep snapshot, but the Data property on Line 81 is copied by reference rather than being deep-cloned, making the documentation misleading. Either implement deep-cloning logic for the Data property assignment in the CloneEvent method to match the documented behavior, or revise the XML documentation summary to accurately describe that this method creates a shallow copy of the event with reference-type properties like Data and Attendees being copied by reference rather than cloned.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor (1)
4-10: ⚡ Quick winExpose dropdown expanded state for accessibility.
The toggle button currently doesn’t announce menu state/ownership. Adding
aria-expanded/aria-controlsimproves keyboard and screen-reader flow.💡 Suggested fix
- <button class="bit-bfc-btn bit-bfc-btn-icon bit-bfc-btn-sm" `@onclick`="() => _open = !_open" title="`@Texts.SettingsButtonTitle`"> + <button type="button" + class="bit-bfc-btn bit-bfc-btn-icon bit-bfc-btn-sm" + `@onclick`="() => _open = !_open" + title="`@Texts.SettingsButtonTitle`" + aria-haspopup="menu" + aria-expanded="`@_open`" + aria-controls="bit-bfc-settings-menu"> @@ - <div class="bit-bfc-dropdown-menu"> + <div id="bit-bfc-settings-menu" class="bit-bfc-dropdown-menu" role="menu">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor` around lines 4 - 10, The button element in BitFcSettings.razor that toggles the dropdown menu is missing accessibility attributes. Add the aria-expanded attribute to the button and bind it to the _open variable to expose the expanded state to screen readers, add an id attribute to the div with class bit-bfc-dropdown-menu to uniquely identify it, and add the aria-controls attribute to the button to establish the relationship between the button and the dropdown menu it controls by referencing the dropdown menu's id.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.ts`:
- Around line 96-143: The event listeners for pointermove, pointerup, and
pointercancel are being registered after awaiting OnResizeStart, which allows a
fast pointer release to occur before the listeners are attached, causing the
endResize handler to be missed and leaving event listeners active. Move the
three addEventListener calls (for pointermove with onPointerMove, pointerup with
endResize, and pointercancel with endResize) to execute before the await of
OnResizeStart so that any pointer events are properly captured. Apply this same
ordering fix to the initResizeHorizontal function as well.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor`:
- Around line 76-78: The three input fields for attendee information
(_newFirstName, _newLastName, and _newId) lack explicit labels or aria-label
attributes, making them inaccessible to screen readers. Add aria-label
attributes to each of these input elements that describe the field's purpose
using the corresponding localized text from the Texts resource
(FirstNamePlaceholder, LastNamePlaceholder, and IdOptionalPlaceholder). This
ensures screen reader users can understand what information each field expects
without relying solely on visual placeholders.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor`:
- Around line 14-18: The aria-label attributes on the navigation buttons (lines
14 and 18) in BitFcDateTimePicker.razor are hard-coded with English text,
preventing localization based on the selected culture. Add two new string
parameters named PreviousMonthAriaLabel and NextMonthAriaLabel to the
component's code-behind (BitFcDateTimePicker.razor.cs) with appropriate default
English values, then bind these parameters to the respective aria-label
attributes in the Razor markup by replacing the hard-coded strings with property
bindings.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor`:
- Around line 12-23: The event row in BitFcEventListDialog.razor is currently
only mouse-clickable and inaccessible to keyboard users. The div with class
"bit-bfc-agenda-item" needs to be made keyboard-operable by adding a tabindex
attribute to make it focusable, and adding a keyboard event handler (such as
`@onkeydown`) that triggers the SelectEvent method when the user presses Enter or
Space keys. This ensures both mouse and keyboard users can select events from
the dialog.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor`:
- Around line 8-20: The guard condition at the start of the BitFcModeTabs
component hides the entire mode tabs container when there are no resources,
which removes the Event mode switching UI entirely. Instead of conditionally
rendering the entire div based on resource count, you should keep the mode tabs
container always visible and conditionally filter or render only the
Timeline-specific mode from the _modes collection when resources are available.
This way the Event mode tab remains accessible for users to switch between modes
even when the resources list is empty.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cs`:
- Around line 11-12: The SetStartOfDayHour method is being called with an
unclamped parsed value, which bypasses min/max validation that only exists on
the input element. After successfully parsing the value into the variable val
using int.TryParse, clamp val to the appropriate valid range (e.g., 0-23 for
hours) before passing it to State.SetStartOfDayHour to ensure the state
invariant is enforced at the handler level regardless of input element
constraints.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor`:
- Around line 9-10: The button element in BitFcViewTabs.razor does not have an
explicit type attribute, which causes it to default to type="submit" when inside
a form, potentially triggering unwanted form submissions. Add the type="button"
attribute to the button element that has the class "bit-bfc-view-tab" and the
onclick handler that calls State.SetView(view) to ensure it functions as a
regular button rather than a submit button.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs`:
- Around line 201-210: The GetEventsForYear method in BitFullCalendarHelpers
treats EndDate.Date as inclusive in its overlap comparison, but this causes
inconsistency with the exclusive-end convention used elsewhere where midnight is
treated as the boundary. Fix the comparison logic in the where clause for
GetEventsForYear to treat EndDate as exclusive by changing the condition from
ev.EndDate.Date >= yearStart to ev.EndDate > yearStart. Apply this same
exclusive-end rule consistently across all other related date-overlap helper
methods mentioned in the comment (at lines 468-471, 578-588, 591-597, 599-609)
to ensure events ending at midnight do not incorrectly appear in the next
period.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor`:
- Around line 43-47: The clickable div element in the BitFcCalendarWeekView
component that handles the `@onclick`="() => OnHourClickAsync(d, hour)" event is
not keyboard accessible. To fix this, add a role="button" attribute to indicate
this element is interactive, add tabindex="0" to make it focusable for keyboard
navigation, and add an `@onkeydown` event handler that triggers OnHourClickAsync
when the Enter or Space keys are pressed to allow keyboard-only users to create
events from the week grid view.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor`:
- Around line 43-45: Replace the span element with role="button" in the
BitFcMiniCalendar component with a native button element for proper keyboard
semantics. Change the span that contains the SelectDate click handler and
OnDayKeyDown keyboard handler to a button element. Remove the role="button",
tabindex="0" attributes and the `@onkeydown` handler since native buttons
automatically handle keyboard interactions like Space and Enter. Keep the class
attribute with bit-bfc-mini-calendar-day and the `@onclick` handler bound to
SelectDate(cell.Date).
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor`:
- Around line 47-49: The div element with class "bit-bfc-month-more" in
BitFcDayCell.razor is not keyboard-accessible because it only responds to click
events. Add an `@onkeydown` event handler to this div that calls a new
OnMoreKeyDown method, which should check if the pressed key is Enter, Space, or
Spacebar and set _showEventList to true when triggered. Additionally, add
tabindex="0" and role="button" attributes to the div to make it focusable and
semantically correct for keyboard users.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor`:
- Around line 47-50: The time display in the MonthView badge incorrectly shows
Event.StartDate for all positions, including when Position is "last". For
multi-day events, the last segment should display Event.EndDate instead of
Event.StartDate to correctly represent the trailing day's time. Modify the
condition that checks showTime to conditionally use either Event.EndDate when
Position equals "last" or Event.StartDate otherwise, passing the appropriate
date value to the BitFullCalendarHelpers.FormatTime method.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor`:
- Around line 16-19: The code filters out resources with empty IDs on line 17
when grouping events using `Where(id => !string.IsNullOrEmpty(id))`, but the
same filtering is not applied when rendering rows and drop targets around line
55 where raw `resource.Id` values are used directly. This inconsistency causes
resources with empty IDs to render but fail to retain dropped or created events
properly since the BitFullCalendarEvent.Resource contract treats empty IDs as
unassigned. Apply the same empty ID filtering logic when iterating through
resources for row and drop target rendering to ensure consistency between the
grouping logic and the rendering logic.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cs`:
- Around line 78-83: In the `OnResizeStart` method in
BitFcTimelineEventBlock.razor.cs, instead of storing a direct reference to the
Event object in `_resizeBaseEvent`, capture an immutable copy or deep clone of
the Event object to preserve its pre-resize state. This ensures that when
`State.UpdateEvent(updated)` is called later and the original Event object is
mutated, the `_resizeBaseEvent` will still contain the original unmodified state
needed for building the accurate `OldEvent` property. Apply the same fix to the
corresponding resize end handler method that also uses `_resizeBaseEvent` to
construct `OldEvent`.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs`:
- Around line 119-124: The year and month comparison in the conditional check
within the method is using Gregorian calendar properties directly
(State.SelectedDate.Year and State.SelectedDate.Month), but the rendered
calendar may use a different calendar system based on the active culture.
Replace the direct Year and Month property comparisons with culture-aware date
comparison that respects the calendar system being used for rendering, ensuring
that the scroll-to-today functionality works correctly for non-Gregorian
calendar cultures.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor`:
- Around line 44-46: The clickable div element with `@onclick` handler for
GoToMonth month navigation is not keyboard-accessible. Replace the div element
with a button element to make it keyboard-operable by default, which will allow
users to navigate using Tab and Enter keys. The button should maintain the same
click handler `@onclick`="() => GoToMonth(monthDate)" and display the monthName
content.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cs`:
- Around line 15-16: The OnDragOver method continuously sets _isOver to true
every time the ondragover event fires, causing unnecessary re-renders even when
the value is already true. Add a guard condition in the OnDragOver method to
check if _isOver is already true before assigning the value, so that a re-render
is only triggered when the state actually transitions from false to true.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor`:
- Around line 4-10: The button element in BitFcSettings.razor that toggles the
dropdown menu is missing accessibility attributes. Add the aria-expanded
attribute to the button and bind it to the _open variable to expose the expanded
state to screen readers, add an id attribute to the div with class
bit-bfc-dropdown-menu to uniquely identify it, and add the aria-controls
attribute to the button to establish the relationship between the button and the
dropdown menu it controls by referencing the dropdown menu's id.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cs`:
- Around line 68-82: The CloneEvent method's XML documentation claims to create
a deep snapshot, but the Data property on Line 81 is copied by reference rather
than being deep-cloned, making the documentation misleading. Either implement
deep-cloning logic for the Data property assignment in the CloneEvent method to
match the documented behavior, or revise the XML documentation summary to
accurately describe that this method creates a shallow copy of the event with
reference-type properties like Data and Attendees being copied by reference
rather than cloned.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 336fa9f8-c43a-4be3-81b7-7b5b95625510
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 10
♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cs (1)
11-12:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winClamp parsed start-hour before updating state.
Line 11–12 still forwards raw parsed values; enforce the 0–16 bound in the handler so state cannot drift out of range.
Suggested fix
- if (int.TryParse(e.Value?.ToString(), out int val)) - State.SetStartOfDayHour(val); + if (int.TryParse(e.Value?.ToString(), out int val)) + State.SetStartOfDayHour(Math.Clamp(val, 0, 16));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cs` around lines 11 - 12, The handler for the start-hour input does not validate that the parsed value falls within the valid 0-16 range before forwarding it to State.SetStartOfDayHour. After successfully parsing the value with int.TryParse, clamp the parsed integer val to ensure it stays within bounds (minimum 0, maximum 16) before passing it to the SetStartOfDayHour method call.
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cs (1)
199-210: 💤 Low valueOptions changes not detected when properties are modified in place.
ReferenceEqualscheck means if the consumer modifies properties on the existingOptionsinstance (e.g.,Options.Use24HourFormat = false) without assigning a new object, those changes won't be applied. Consider adding a version/hash check or documenting that a newOptionsinstance must be assigned for changes to take effect.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cs` around lines 199 - 210, The ApplyOptions method uses ReferenceEquals to compare Options with _appliedOptions, which only detects changes when a completely new Options object is assigned, not when individual properties are modified on the existing instance. To fix this, implement a version tracking mechanism or hash-based comparison that can detect property changes within the same Options object. You could add a version property to the Options class that increments when properties change, or compute a hash of the Options properties and compare that instead of just the reference. Store the computed hash or version in _appliedOptions alongside or in place of the Options reference, then check if the current hash/version differs from the stored one in the ApplyOptions method.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cs (1)
100-107: Add State.IsDragging guard to OnDrop for consistency.While
HandleResourceDropAsyncproperly guards against null dragged events, theOnDropmethod should match the defensive pattern used in allOnDragEnterimplementations by checkingif (!State.IsDragging) return;early. This prevents unnecessary notifier calls and ensures consistent drag-state gating across event handlers.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cs` around lines 100 - 107, Add a defensive guard clause at the beginning of the OnDrop method to check State.IsDragging, returning early if it is false. This ensures consistency with the defensive pattern used in OnDragEnter implementations and prevents unnecessary notifier calls when dragging is not actually in progress.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs`:
- Around line 21-32: The OnParametersSet method currently only reinitializes
_visibleMonthAnchor when the Value parameter changes, but does not account for
culture or calendar changes. To fix this, track the current culture or calendar
system similar to how _lastSyncedDate is tracked, and modify the OnParametersSet
method to reinitialize _visibleMonthAnchor not only when Value changes but also
when the culture or calendar system changes. This ensures that month anchoring
remains correct when switching between different calendar systems while
maintaining the same date value.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor`:
- Around line 4-9: The button element in BitFcSettings component uses a
hardcoded ID "bit-bfc-settings-menu" in the aria-controls attribute, and the
menu div also uses the same hardcoded id. When multiple calendar instances exist
on the same page, this creates duplicate IDs which breaks accessibility by
causing assistive technology to point to the wrong menu. Generate a unique
identifier for each BitFcSettings component instance (typically using Guid in
the code-behind section) and replace both the aria-controls attribute on the
button and the id attribute on the menu div to use this generated unique ID
instead of the hardcoded string.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor`:
- Line 3: The button element in BitFcTodayButton.razor with the onclick handler
State.GoToToday and classes bit-bfc-btn bit-bfc-btn-sm is missing an explicit
type attribute. Add type="button" to the button element to ensure it never
accidentally submits a parent form when clicked.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cs`:
- Around line 15-17: The Initials property getter assumes FirstName and LastName
are non-null strings, which can cause null reference exceptions when these
properties are externally assigned null values. Add null checks before accessing
the Length property on FirstName and LastName in the Initials getter. Use the
null-coalescing operator or conditional checks to ensure that null values are
safely handled, treating them as empty strings when determining the initials.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs`:
- Around line 213-218: The FormatTime method uses CultureInfo.InvariantCulture
for date formatting, which prevents localized time strings (particularly AM/PM
indicators) from respecting the user's UI culture settings. Replace
CultureInfo.InvariantCulture with CultureInfo.CurrentUICulture in both toString
calls within the FormatTime method to ensure time formatting respects the user's
locale. Additionally, apply the same fix to the similar code at lines 248-254
that handles the same formatting issue.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs`:
- Around line 48-52: The SetCulture method updates the Culture property and
calls UpdateUI() but fails to notify listeners about date-range changes. When
culture changes, the date range representation may change due to locale-specific
formatting, so consumers listening for range changes miss required updates. Add
a call to NotifyDateRangeChanged() after the UpdateUI() call in the SetCulture
method to ensure all listeners are properly notified of the date-range change.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs`:
- Line 3: The BitFcCalendarTimeline class has a Dispose() method defined on line
37 but does not implement the IDisposable interface on the class declaration on
line 3. Update the class declaration to implement IDisposable so that Blazor
will automatically call the Dispose() method when the component is destroyed,
ensuring the timer resource is properly cleaned up and doesn't leak.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cs`:
- Around line 66-76: The catch block in the resize initialization section of
BitFcEventBlock only catches JSException, but other exceptions like
JSDisconnectedException, InvalidOperationException, and
OperationCanceledException can occur during Blazor teardown and disconnect
scenarios. Update the catch block that surrounds the JS.InvokeVoidAsync calls
for "BitBlazorUI.FullCalendar.initResize" (in the OnAfterRenderAsync method) to
catch all these exception types together, aligning the exception handling
pattern with the equivalent implementation in BitFcTimelineEventBlock.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor`:
- Around line 40-47: The div element in the BitFcTimelineEventBlock component is
not keyboard-accessible because it lacks focus capability and keyboard event
handling. Make the event block keyboard-activatable by adding a tabindex
attribute to make the div focusable, adding an onkeydown event binding to the
div element, and implementing the corresponding OnKeyDown method that checks if
the pressed key is Enter, Space, or Spacebar before invoking the same OnClick
handler used for mouse clicks.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor`:
- Around line 80-85: The timeline month slot cells in the BitFcTimelineMonthView
component (the div elements with classes bit-bfc-tl-cell bit-bfc-tl-cell-day at
lines 80-85 and 107-112) currently only respond to mouse interactions through
onclick handlers. To make these cells keyboard-operable, add keyboard event
handlers (`@onkeydown` or similar) to the div elements that trigger the same
OnSlotClickAsync method when the Enter or Space keys are pressed. This will
enable users to create events using keyboard navigation without requiring a
mouse, improving accessibility.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cs`:
- Around line 11-12: The handler for the start-hour input does not validate that
the parsed value falls within the valid 0-16 range before forwarding it to
State.SetStartOfDayHour. After successfully parsing the value with int.TryParse,
clamp the parsed integer val to ensure it stays within bounds (minimum 0,
maximum 16) before passing it to the SetStartOfDayHour method call.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cs`:
- Around line 199-210: The ApplyOptions method uses ReferenceEquals to compare
Options with _appliedOptions, which only detects changes when a completely new
Options object is assigned, not when individual properties are modified on the
existing instance. To fix this, implement a version tracking mechanism or
hash-based comparison that can detect property changes within the same Options
object. You could add a version property to the Options class that increments
when properties change, or compute a hash of the Options properties and compare
that instead of just the reference. Store the computed hash or version in
_appliedOptions alongside or in place of the Options reference, then check if
the current hash/version differs from the stored one in the ApplyOptions method.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cs`:
- Around line 100-107: Add a defensive guard clause at the beginning of the
OnDrop method to check State.IsDragging, returning early if it is false. This
ensures consistency with the defensive pattern used in OnDragEnter
implementations and prevents unnecessary notifier calls when dragging is not
actually in progress.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5c0cef1e-f38f-4cd6-8f87-040157a9122a
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (6)
src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss (1)
7-7:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove the
.scssextension to satisfy Stylelint.The static analysis tool flags this import as violating
scss/load-partial-extension. Other imports in this file omit the extension for consistency.Suggested fix
-@import "../Components/FullCalendar/BitFullCalendar.scss"; +@import "../Components/FullCalendar/BitFullCalendar";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss` at line 7, The import statement in the extra-components.scss file includes the .scss file extension on the BitFullCalendar.scss import, which violates the scss/load-partial-extension Stylelint rule. Remove the .scss extension from the import path so it matches the pattern used by other imports in the file, changing the import to reference just the module name without the extension.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor (1)
108-126:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTimeline week slot cells lack keyboard accessibility.
Unlike
BitFcTimelineMonthView.razorwhich was updated withrole="button",tabindex="0", and@onkeydownhandlers, these week view cells remain mouse-only. Keyboard users cannot create events in this view.Add the same keyboard support pattern used in the month view:
Suggested fix for outer cell
<div class="bit-bfc-tl-cell @(isPreviewHour ? "bit-bfc-tl-drop-preview" : "")" style="left:@(leftPx)px;width:@(hourWidth)px;" + role="button" + tabindex="0" `@ondragenter`="() => OnDragEnter(rowKey, day, hour, 0)" `@ondragover`:preventDefault="true" `@ondrop`="() => OnDrop(rowKey, day, hour, 0)" - `@onclick`="() => OnSlotClickAsync(rowKey, day, hour, 0)"> + `@onclick`="() => OnSlotClickAsync(rowKey, day, hour, 0)" + `@onkeydown`="e => OnSlotKeyDownAsync(e, rowKey, day, hour, 0)">Also applies to lines 151-165 in UnassignedRowContent.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor` around lines 108 - 126, The timeline week view cells in BitFcTimelineWeekView.razor are not keyboard accessible like they are in BitFcTimelineMonthView.razor. Add keyboard support to both the outer cell div with class "bit-bfc-tl-cell" and the inner cell-half div with class "bit-bfc-tl-cell-half" by adding three attributes to each: role="button" to provide semantic meaning, tabindex="0" to make them focusable, and `@onkeydown` event handler that calls the same OnSlotClickAsync method as the `@onclick` handler (with the same rowKey, day, hour, and minute parameters). Apply the same fix to both occurrences in the week view at the specified line ranges and also to the same cells in the UnassignedRowContent section at lines 151-165.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs (1)
3-3:⚠️ Potential issue | 🟠 Major | ⚡ Quick winImplement
IDisposableon the component type.Line 37 defines
Dispose(), but Line 3 does not implementIDisposable; Blazor lifecycle disposal won’t reliably invoke this cleanup, so the timer can outlive the component.Suggested fix
-public partial class BitFcCalendarTimeline +public partial class BitFcCalendarTimeline : IDisposableAlso applies to: 37-37
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs` at line 3, The BitFcCalendarTimeline class has a Dispose() method defined but does not implement the IDisposable interface. This prevents Blazor from reliably calling the cleanup method, allowing the timer to outlive the component. Add the IDisposable interface implementation to the BitFcCalendarTimeline class declaration so that the existing Dispose() method is properly recognized and invoked during component lifecycle cleanup.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss (1)
3-3:⚠️ Potential issue | 🟡 Minor | 💤 Low valueRemove
.scssextension from import path.The stylelint rule
scss/load-partial-extensionflags this. SCSS partials should be imported without the extension.-@import "../../../Bit.BlazorUI/Styles/functions.scss"; +@import "../../../Bit.BlazorUI/Styles/functions";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss` at line 3, The import statement for the functions.scss partial includes the file extension, which violates the scss/load-partial-extension stylelint rule. Remove the .scss extension from the import path in the `@import` statement that references ../../../Bit.BlazorUI/Styles/functions.scss, so the partial is imported without its extension as per SCSS conventions.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs (1)
8-9:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce
EndDate >= StartDatein the model.Line 27 can return a negative duration today, and that value is consumed downstream when events are moved/resized. Reject inverted ranges at this boundary so invalid events never enter state logic.
Suggested fix
public class BitFullCalendarEvent { + private DateTime _startDate; + private DateTime _endDate; + public string Id { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; - public DateTime StartDate { get; set; } - public DateTime EndDate { get; set; } + public DateTime StartDate + { + get => _startDate; + set + { + _startDate = value; + EnsureValidRange(); + } + } + public DateTime EndDate + { + get => _endDate; + set + { + _endDate = value; + EnsureValidRange(); + } + } @@ public TimeSpan Duration => EndDate - StartDate; @@ public object? Data { get; set; } + + private void EnsureValidRange() + { + if (_startDate != default && _endDate != default && _endDate < _startDate) + throw new ArgumentOutOfRangeException(nameof(EndDate), "EndDate must be greater than or equal to StartDate."); + } }Also applies to: 27-27
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs` around lines 8 - 9, The BitFullCalendarEvent model's StartDate and EndDate properties do not validate that EndDate is greater than or equal to StartDate, which allows negative durations to be calculated and propagated to downstream logic. Add validation logic to the EndDate property setter to ensure it is never set to a value less than the current StartDate value, and similarly validate the StartDate property setter to ensure it is never set to a value greater than the current EndDate value. This will prevent invalid inverted date ranges from being created at the model boundary and protect the duration calculations and event manipulation logic downstream.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs (1)
181-186:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
SyncEventsstill skips filter recomputation for in-place mutations.Line 182 returns early when references match, so
_filteredEventscan stay stale after mutating event properties (for exampleColororAttendees) on shared instances.Suggested fix
public void SyncEvents(List<BitFullCalendarEvent> events) { if (EventsMatch(events)) - return; + { + ApplyFilters(); + return; + } _allEvents = [.. events]; ApplyFilters(); NotifyStateChanged(); }Also applies to: 217-227
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs` around lines 181 - 186, The SyncEvents method currently returns early when EventsMatch(events) is true, but this optimization causes _filteredEvents to become stale when individual event properties are mutated in-place (such as Color or Attendees changes on shared event instances). Remove the early return condition and the EventsMatch check so that ApplyFilters() and NotifyStateChanged() are always executed, ensuring that any in-place mutations to event properties trigger filter recomputation. Apply the same fix to the similar code block mentioned in the comment (lines 217-227) to ensure consistent behavior across all event synchronization paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor`:
- Line 4: The button element in BitFcSettings.razor that toggles the _open state
is missing an explicit type attribute, which causes it to default to
type="submit" and can unintentionally submit a parent form. Add type="button" to
the button element with the `@onclick`="() => _open = !_open" handler to prevent
form submission behavior and explicitly declare that this is a regular button
control.
- Around line 12-37: The three toggle setting rows use non-semantic `<div>`
elements with `@onclick` handlers instead of proper button controls, making them
inaccessible via keyboard and screen readers. Replace each `<div
class="bit-bfc-dropdown-item">` element (the ones containing SetBadgeVariant,
ToggleTimeFormat, and ToggleEventLayout handlers) with `<button type="button">`
elements, preserving the existing `@onclick` handlers and all internal content
including the span labels and toggle markup. This ensures keyboard navigation
and proper semantic accessibility.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cs`:
- Around line 97-104: The OnDrop method is calling HandleResourceDropAsync
unconditionally, but it should only do so when a drag operation is actually
active. Before calling the Notifier.HandleResourceDropAsync method in OnDrop,
add a guard condition to check if an active drag state exists (such as verifying
that _dragResourceId is not null before the reset). If no drag is active, the
method should return early without processing the drop logic, making it
consistent with the week view implementation.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor`:
- Around line 25-30: The condition checking `!hasResources` at line 25 prevents
the unassigned timeline row from rendering when resources are empty. Modify the
logic to show the empty state message only if both resources are empty AND there
are no unassigned rows to display. When resources are empty but
`HasUnassignedRow` is true or `UnassignedRowContent` exists, render the
unassigned timeline row instead of the no-resources message. Apply the same fix
to the related section at lines 60-72 to ensure consistent behavior throughout
the BitFcTimelineLayout component.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs`:
- Around line 111-119: The OnDrop method in BitFcTimelineMonthView.razor.cs is
missing a drag-state precondition check at the start of the method. Add a guard
clause at the beginning of the OnDrop method that checks if drag mode is active
(validate that _dragResourceId and _dragDay are not null) and returns early if
drag is not active, matching the behavior implemented in the timeline week view.
This check should occur before clearing the drag state variables and calling
HandleResourceDropAsync.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor`:
- Line 5: The Description attribute in the BitFullCalendarDemo.razor file
contains inconsistent casing that makes it appear unprofessional and awkward for
users. Update the Description property value to properly capitalize component
names: change "fullcalendar" to "FullCalendar" and "bit BlazorUI" to "Bit
BlazorUI". Consider also improving the overall phrasing to be more polished and
user-facing, such as emphasizing that this is a powerful calendar component
within the Bit BlazorUI library rather than just stating it is a component of
it.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss`:
- Line 3: The import statement for the functions.scss partial includes the file
extension, which violates the scss/load-partial-extension stylelint rule. Remove
the .scss extension from the import path in the `@import` statement that
references ../../../Bit.BlazorUI/Styles/functions.scss, so the partial is
imported without its extension as per SCSS conventions.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs`:
- Around line 8-9: The BitFullCalendarEvent model's StartDate and EndDate
properties do not validate that EndDate is greater than or equal to StartDate,
which allows negative durations to be calculated and propagated to downstream
logic. Add validation logic to the EndDate property setter to ensure it is never
set to a value less than the current StartDate value, and similarly validate the
StartDate property setter to ensure it is never set to a value greater than the
current EndDate value. This will prevent invalid inverted date ranges from being
created at the model boundary and protect the duration calculations and event
manipulation logic downstream.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs`:
- Around line 181-186: The SyncEvents method currently returns early when
EventsMatch(events) is true, but this optimization causes _filteredEvents to
become stale when individual event properties are mutated in-place (such as
Color or Attendees changes on shared event instances). Remove the early return
condition and the EventsMatch check so that ApplyFilters() and
NotifyStateChanged() are always executed, ensuring that any in-place mutations
to event properties trigger filter recomputation. Apply the same fix to the
similar code block mentioned in the comment (lines 217-227) to ensure consistent
behavior across all event synchronization paths.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs`:
- Line 3: The BitFcCalendarTimeline class has a Dispose() method defined but
does not implement the IDisposable interface. This prevents Blazor from reliably
calling the cleanup method, allowing the timer to outlive the component. Add the
IDisposable interface implementation to the BitFcCalendarTimeline class
declaration so that the existing Dispose() method is properly recognized and
invoked during component lifecycle cleanup.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor`:
- Around line 108-126: The timeline week view cells in
BitFcTimelineWeekView.razor are not keyboard accessible like they are in
BitFcTimelineMonthView.razor. Add keyboard support to both the outer cell div
with class "bit-bfc-tl-cell" and the inner cell-half div with class
"bit-bfc-tl-cell-half" by adding three attributes to each: role="button" to
provide semantic meaning, tabindex="0" to make them focusable, and `@onkeydown`
event handler that calls the same OnSlotClickAsync method as the `@onclick`
handler (with the same rowKey, day, hour, and minute parameters). Apply the same
fix to both occurrences in the week view at the specified line ranges and also
to the same cells in the UnassignedRowContent section at lines 151-165.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Line 7: The import statement in the extra-components.scss file includes the
.scss file extension on the BitFullCalendar.scss import, which violates the
scss/load-partial-extension Stylelint rule. Remove the .scss extension from the
import path so it matches the pattern used by other imports in the file,
changing the import to reference just the module name without the extension.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e07c6d12-2eca-4898-a0d1-6974feaee4e1
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cs (1)
18-18:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse a per-instance default for
ScrollContainerId.Line 18 uses a fixed DOM id. If multiple timeline layouts render without explicitly overriding this parameter, JS scroll targeting can hit the wrong container.
Suggested fix
- [Parameter] public string ScrollContainerId { get; set; } = "bit-bfc-tl-scroll"; + [Parameter] public string ScrollContainerId { get; set; } = $"bit-bfc-tl-scroll-{Guid.NewGuid():N}";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cs` at line 18, The ScrollContainerId parameter in BitFcTimelineLayout has a fixed default value that will cause conflicts when multiple timeline layouts are rendered on the same page, as they would all target the same DOM element. Generate a unique per-instance identifier for ScrollContainerId instead of using a hardcoded string, such as by using a Guid or similar unique value generation approach that executes once per component instance to ensure each timeline layout has its own unique scroll container identifier.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cs (1)
14-14:⚠️ Potential issue | 🟠 Major | ⚡ Quick winResource identity should not default to an empty string.
Line 14 initializes
Idasstring.Empty, which allows uninitialized resources to share the same identity and can blur “valid resource id” vs “unassigned” handling during event-resource mapping. Please enforce non-empty IDs at the model boundary (required/validated assignment).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cs` at line 14, The Id property in the BitFullCalendarResource class currently defaults to string.Empty, which allows multiple uninitialized resources to have the same identity and creates ambiguity during event-resource mapping. Remove the default string.Empty initialization from the Id property declaration and enforce non-empty IDs at the model boundary by either marking the property as required (using the required keyword if targeting C#11+) or by implementing validation logic that prevents empty or null ID assignments. This ensures that every BitFullCalendarResource instance must have a valid, non-empty identifier.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor`:
- Around line 46-56: The BitFullCalendarHelpers.FormatTime method calls on both
the start and end date rows are not receiving the State.Culture parameter,
causing the time formatting to use a different locale than the date formatting
on the same lines. Pass State.Culture as an additional parameter to both
BitFullCalendarHelpers.FormatTime calls (for Event.StartDate and Event.EndDate)
alongside the existing State.Use24HourFormat parameter to ensure consistent
locale formatting throughout each event detail row.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor`:
- Line 21: The call to BitFullCalendarHelpers.FormatTime() on line 21 is missing
the State.Culture parameter, causing time formatting to use the ambient culture
instead of the calendar's configured culture. Update the
BitFullCalendarHelpers.FormatTime() method invocation to include State.Culture
as a parameter alongside the existing ev.StartDate and State.Use24HourFormat
arguments to ensure consistent culture-aware formatting throughout the
BitFcEventListDialog component.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cs`:
- Around line 356-436: The texts-class metadata definition has an incomplete
Parameters array that is missing three properties that exist on the
BitFullCalendarTexts class: PreviousMonthAriaLabel, NextMonthAriaLabel, and
RemoveAttendeeAriaLabel. Add these three missing parameter entries to the
Parameters array within the texts-class metadata block, following the same
pattern as the existing entries with appropriate Type, DefaultValue (as
strings), and Description fields that describe their purpose for month
navigation aria labels and attendee removal.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cs`:
- Line 14: The Id property in the BitFullCalendarResource class currently
defaults to string.Empty, which allows multiple uninitialized resources to have
the same identity and creates ambiguity during event-resource mapping. Remove
the default string.Empty initialization from the Id property declaration and
enforce non-empty IDs at the model boundary by either marking the property as
required (using the required keyword if targeting C#11+) or by implementing
validation logic that prevents empty or null ID assignments. This ensures that
every BitFullCalendarResource instance must have a valid, non-empty identifier.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cs`:
- Line 18: The ScrollContainerId parameter in BitFcTimelineLayout has a fixed
default value that will cause conflicts when multiple timeline layouts are
rendered on the same page, as they would all target the same DOM element.
Generate a unique per-instance identifier for ScrollContainerId instead of using
a hardcoded string, such as by using a Guid or similar unique value generation
approach that executes once per component instance to ensure each timeline
layout has its own unique scroll container identifier.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: b2a29b5e-2d33-486b-8051-3b00d7c9991a
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs (1)
8-9:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce
EndDate >= StartDateinvariant at the model boundary.
StartDate/EndDatecurrently allow inverted ranges, and Line 27 then emits negativeDuration. Reject invalid assignments early (setters or central validator) so invalid events cannot enter state.Suggested patch
public class BitFullCalendarEvent { + private DateTime _startDate; + private DateTime _endDate; + public string Id { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; - public DateTime StartDate { get; set; } - public DateTime EndDate { get; set; } + public DateTime StartDate + { + get => _startDate; + set + { + if (_endDate != default && value > _endDate) + throw new ArgumentException("StartDate must be less than or equal to EndDate."); + _startDate = value; + } + } + public DateTime EndDate + { + get => _endDate; + set + { + if (_startDate != default && value < _startDate) + throw new ArgumentException("EndDate must be greater than or equal to StartDate."); + _endDate = value; + } + } @@ public TimeSpan Duration => EndDate - StartDate;Also applies to: 27-27
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs` around lines 8 - 9, The StartDate and EndDate properties in the BitFullCalendarEvent class currently allow invalid date ranges where EndDate is less than StartDate, which results in negative Duration calculations at line 27. Add validation logic to the setters of both StartDate and EndDate properties to enforce the invariant that EndDate must be greater than or equal to StartDate. Either validate within each property setter or implement a central validator that prevents invalid assignments from being accepted into the model state.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cs (1)
27-50:⚠️ Potential issue | 🟠 Major | ⚡ Quick winReinitialize dialog form state on parameter changes, not only once.
Line 27 seeds the form in
OnInitialized(), so reused dialog instances can keep stale values whenExistingEvent/start parameters change. Move initialization toOnParametersSet()(with an init-key guard) to keep add/edit state accurate across reopens.Suggested patch
+ private (string? EventId, DateTime? StartDate, int? StartHour, int? StartMinute)? _initKey; + - protected override void OnInitialized() + protected override void OnParametersSet() + { + var key = (ExistingEvent?.Id, StartDate?.Date, StartHour, StartMinute); + if (_initKey == key) return; + _initKey = key; + InitializeForm(); + } + + private void InitializeForm() { _isEditing = ExistingEvent != null; var defaultColor = ColorScheme.Options.Count > 0 ? ColorScheme.Options[0].Id : BitFullCalendarColorScheme.FallbackColorId; @@ - } + }#!/bin/bash # Read-only verification: # 1) Locate all dialog usages. # 2) Check whether usages include `@key` to force instance recreation. rg -n --iglob '*.razor' -C2 '<BitFcAddEditEventDialog\b' rg -n --iglob '*.razor' -C1 '<BitFcAddEditEventDialog\b.*`@key`='🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cs` around lines 27 - 50, The form initialization logic in OnInitialized() only runs once when the component first loads, causing stale values to persist when the dialog is reused with different ExistingEvent or start date parameters. Move the entire initialization block from OnInitialized() to OnParametersSet() to ensure form fields (_title, _description, _startDate, _endDate, _color, _attendees) are refreshed whenever component parameters change. Add a guard condition to track whether initialization has already occurred for the current parameter set to prevent unnecessary reinitializations.
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cs (1)
14-18: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winGuard constructor dependencies with fail-fast null checks.
This avoids deferred null-reference failures in drop/notify paths and gives clearer exception context.
Suggested patch
public BitFullCalendarChangeNotifier(BitFullCalendarState state, Func<BitFullCalendarChangeEventArgs, Task> dispatch) { + ArgumentNullException.ThrowIfNull(state); + ArgumentNullException.ThrowIfNull(dispatch); _state = state; _dispatch = dispatch; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cs` around lines 14 - 18, Add null-check guards at the beginning of the BitFullCalendarChangeNotifier constructor to validate the state and dispatch parameters before they are assigned to _state and _dispatch fields. If either parameter is null, throw an ArgumentNullException with the appropriate parameter name to provide fail-fast detection and clearer exception context instead of deferring null-reference failures to later use in drop/notify paths.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs (1)
330-332: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winUse state culture when ordering attendee labels.
Current sorting uses ambient thread culture, which can differ from
State.Cultureand produce inconsistent ordering in per-instance localized calendars.Suggested patch
- return map - .OrderBy(kv => kv.Value, StringComparer.CurrentCultureIgnoreCase) + return map + .OrderBy(kv => kv.Value, StringComparer.Create(Culture, ignoreCase: true)) .Select(kv => (kv.Key, kv.Value)) .ToList();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs` around lines 330 - 332, The OrderBy method in the attendee label ordering logic uses StringComparer.CurrentCultureIgnoreCase which relies on the ambient thread culture instead of the calendar's configured culture. Replace the StringComparer.CurrentCultureIgnoreCase with a culture-aware comparer that uses State.Culture to ensure consistent and predictable ordering that respects the per-instance localization settings of the calendar.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cs`:
- Around line 183-188: The `Options` and `Texts` parameters in the
BitFullCalendar component can be null when passed externally, which causes
runtime exceptions in the `ApplyOptions` method and downstream cascaded usage.
In the `OnParametersSet` method, add normalization logic to check if `Options`
and `Texts` are null and assign them to appropriate default instances before
they are used in `ApplyOptions` or passed to child components. This ensures that
nullable parameters are always initialized to valid defaults before any
downstream code attempts to access their properties.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cs`:
- Around line 80-84: The OnResizeMove method (which is referenced in the "Also
applies to" section at lines 118-129) currently treats any direction value that
is not "top" as "bottom", which could lead to incorrect behavior if unexpected
values are sent from JavaScript interop. Add explicit validation of the resize
direction parameter to only accept "top" and "bottom" as valid values, and then
use explicit branching for each known direction instead of using a negation
check as the fallback condition. This ensures that unexpected direction values
are properly handled and do not silently produce incorrect end-time updates.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor`:
- Line 15: The BitFcDayCell component has focusable div elements with keyboard
event handlers that need to prevent the browser's default Space-key scrolling
behavior. Add the preventDefault modifier to the `@onkeydown` directive binding
(where `@onkeydown`="OnCellKeyDown" is currently set) by changing it to include
`@onkeydown`:preventDefault="true" to preserve button-like keyboard behavior.
Apply this same fix at both locations mentioned (line 15 and line 47).
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cs`:
- Around line 27-50: The form initialization logic in OnInitialized() only runs
once when the component first loads, causing stale values to persist when the
dialog is reused with different ExistingEvent or start date parameters. Move the
entire initialization block from OnInitialized() to OnParametersSet() to ensure
form fields (_title, _description, _startDate, _endDate, _color, _attendees) are
refreshed whenever component parameters change. Add a guard condition to track
whether initialization has already occurred for the current parameter set to
prevent unnecessary reinitializations.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs`:
- Around line 8-9: The StartDate and EndDate properties in the
BitFullCalendarEvent class currently allow invalid date ranges where EndDate is
less than StartDate, which results in negative Duration calculations at line 27.
Add validation logic to the setters of both StartDate and EndDate properties to
enforce the invariant that EndDate must be greater than or equal to StartDate.
Either validate within each property setter or implement a central validator
that prevents invalid assignments from being accepted into the model state.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cs`:
- Around line 14-18: Add null-check guards at the beginning of the
BitFullCalendarChangeNotifier constructor to validate the state and dispatch
parameters before they are assigned to _state and _dispatch fields. If either
parameter is null, throw an ArgumentNullException with the appropriate parameter
name to provide fail-fast detection and clearer exception context instead of
deferring null-reference failures to later use in drop/notify paths.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs`:
- Around line 330-332: The OrderBy method in the attendee label ordering logic
uses StringComparer.CurrentCultureIgnoreCase which relies on the ambient thread
culture instead of the calendar's configured culture. Replace the
StringComparer.CurrentCultureIgnoreCase with a culture-aware comparer that uses
State.Culture to ensure consistent and predictable ordering that respects the
per-instance localization settings of the calendar.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d77822b1-a651-462e-a61e-e8119a18b22a
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (3)
src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss (1)
7-7:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix Stylelint violation on import path.
Line 7 imports with
.scssextension, which violates the currentscss/load-partial-extensionrule and can fail lint checks.Suggested patch
-@import "../Components/FullCalendar/BitFullCalendar.scss"; +@import "../Components/FullCalendar/BitFullCalendar";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss` at line 7, The import statement for BitFullCalendar in the extra-components.scss file includes the `.scss` extension, which violates the scss/load-partial-extension Stylelint rule. Remove the `.scss` extension from the end of the import path so that the import statement follows proper SCSS conventions and passes lint validation.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs (1)
3-3:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
Dispose()won’t be called automatically unless the component implementsIDisposable.The timer cleanup path exists, but Line 3 does not implement
IDisposable, so the cleanup hook is not reliably part of the component lifecycle.Suggested fix
-public partial class BitFcCalendarTimeline +public partial class BitFcCalendarTimeline : IDisposableAlso applies to: 37-37
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs` at line 3, The BitFcCalendarTimeline component class declaration does not implement the IDisposable interface, which means the Dispose() method containing timer cleanup logic will not be called automatically as part of the component lifecycle. Add IDisposable to the class declaration (after the partial keyword) to ensure the cleanup hook is reliably invoked when the component is disposed.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cs (1)
31-36:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTimer callback still has a post-disposal race window.
Line 33 guards before queuing work, but disposal can still occur between that check and
InvokeAsync, allowing a render to be queued after disposal. Add a second_isDisposedcheck inside the dispatched delegate.Suggested fix
- _nowTimer = new Timer(_ => - { - if (_isDisposed) - return; - InvokeAsync(StateHasChanged); - }, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); + _nowTimer = new Timer(_ => + { + if (_isDisposed) + return; + + _ = InvokeAsync(() => + { + if (_isDisposed) + return; + StateHasChanged(); + }); + }, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));Also applies to: 118-121
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cs` around lines 31 - 36, The timer callback in the _nowTimer initialization has a race condition where disposal can occur between the initial _isDisposed check and the execution of InvokeAsync(StateHasChanged). Add a second _isDisposed check inside the delegate passed to InvokeAsync to guard the StateHasChanged call, ensuring the component hasn't been disposed by the time the asynchronous work actually executes. Apply the same fix to the similar timer callback at lines 118-121 that also has this post-disposal race window.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs`:
- Around line 97-100: The comparison at line 99 in the GetSortOrder method is
comparing raw Options[i].Id against the trimmed ID variable, but the Find method
trims IDs before lookup, causing inconsistency when option IDs contain leading
or trailing spaces. Trim Options[i].Id before the string comparison using
string.Equals to ensure both sides of the comparison are normalized, so that IDs
are consistently matched regardless of whitespace.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor`:
- Around line 15-16: Remove the `@onkeydown`:preventDefault="true" attribute from
the `@onkeydown` event handler in the BitFcDayCell.razor component at both
occurrences (line 16 and line 48). This will allow default keyboard behavior
like Tab navigation to function normally instead of creating a keyboard trap
that blocks focus navigation.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cs`:
- Around line 73-87: The OnSlotClickAsync method properly handles the resourceId
when OnAddClick delegate is provided, but when the built-in add-dialog flow is
triggered (when OnAddClick.HasDelegate is false), the resourceId parameter is
not preserved. Add a private field to store the resourceId (similar to the
existing _addStartDate, _addStartHour, and _addStartMinute fields) and assign
the resourceId parameter value to this field in the else branch when
_showAddDialog is set to true, ensuring the resource information is available
when the built-in dialog is displayed.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cs`:
- Around line 84-89: Add validation in the OnResizeStart method to verify that
the direction parameter is either "start" or "end" before assigning it to
_resizeDirection, and apply the same validation in the OnResizeMove method. This
will prevent unexpected interop direction values from being treated as "end"
resize operations and applying incorrect resize logic. Reject or return early if
the direction value is neither "start" nor "end".
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs`:
- Around line 83-96: The OnSlotClickAsync method correctly preserves the
resourceId when OnAddClick has a delegate, but the fallback path (when
OnAddClick is absent) only sets _addStartDate and _addStartHour without storing
the resourceId context. This causes events created through the default dialog to
lose their resource assignment. Add a field to store the selected resource ID
(similar to _addStartDate and _addStartHour) and set it in the fallback path
with the same logic used in the OnAddClick path: storing null if resourceId
equals _unassignedKey, otherwise storing the resourceId itself. Ensure this
stored resource ID is then used when the add dialog creates new events.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cs`:
- Around line 75-89: The OnSlotClickAsync method currently discards the
resourceId parameter when the OnAddClick delegate is not available. In the
fallback path where _showAddDialog is set to true, you need to store the
resourceId so it can be used when creating the event through the dialog. Add a
new private field to store the resourceId selection (similar to _addStartDate,
_addStartHour, and _addStartMinute), and assign the resourceId value in the
fallback branch, ensuring to apply the same unassigned logic (resourceId ==
_unassignedKey converts to null) that is used in the OnAddClick callback path.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cs`:
- Around line 31-36: The timer callback in the _nowTimer initialization has a
race condition where disposal can occur between the initial _isDisposed check
and the execution of InvokeAsync(StateHasChanged). Add a second _isDisposed
check inside the delegate passed to InvokeAsync to guard the StateHasChanged
call, ensuring the component hasn't been disposed by the time the asynchronous
work actually executes. Apply the same fix to the similar timer callback at
lines 118-121 that also has this post-disposal race window.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs`:
- Line 3: The BitFcCalendarTimeline component class declaration does not
implement the IDisposable interface, which means the Dispose() method containing
timer cleanup logic will not be called automatically as part of the component
lifecycle. Add IDisposable to the class declaration (after the partial keyword)
to ensure the cleanup hook is reliably invoked when the component is disposed.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Line 7: The import statement for BitFullCalendar in the extra-components.scss
file includes the `.scss` extension, which violates the
scss/load-partial-extension Stylelint rule. Remove the `.scss` extension from
the end of the import path so that the import statement follows proper SCSS
conventions and passes lint validation.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: afc35257-0296-4942-a393-dbced67038b4
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs (1)
18-37: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse semantic culture/calendar tracking instead of reference identity.
The current
cultureChangedcheck uses object reference equality, which can mis-detect real culture/calendar state changes and cause incorrect month re-anchoring behavior.💡 Suggested patch
- private CultureInfo? _lastSyncedCulture; + private string? _lastCultureKey; @@ - var cultureChanged = !ReferenceEquals(_lastSyncedCulture, Culture); + var cultureKey = $"{Culture.Name}|{Culture.DateTimeFormat.Calendar.GetType().FullName}"; + var cultureChanged = _lastCultureKey != cultureKey; @@ - _lastSyncedCulture = Culture; + _lastCultureKey = cultureKey;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs` around lines 18 - 37, The cultureChanged detection in the OnParametersSet method uses ReferenceEquals to compare the Culture object with _lastSyncedCulture, which only checks object reference identity rather than actual culture/calendar state equality. This causes real culture changes to be missed if they come from a different object instance. Replace the ReferenceEquals check with semantic equality comparison using the Culture's Equals method or by comparing the culture names/identifiers directly to properly detect when the actual culture/calendar system has changed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cs`:
- Around line 368-374: In the HandleStateChanged() method, capture the current
value of _applyingParameters into a local variable before passing it to the
InvokeAsync callback. The issue is that _applyingParameters is evaluated inside
the queued callback rather than at the time HandleStateChanged() is invoked,
which means its value may have changed by the time ReconcileBoundState executes
(since line 302 resets it to false). By capturing it immediately before
InvokeAsync, the correct value will be used for the raiseEvents parameter
regardless of when the callback actually runs.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cs`:
- Around line 53-76: The initialization code in BitFcAddEditEventDialog is not
resetting transient state like _errors and attendee draft inputs, which causes
stale validation errors and editing state to persist when the dialog is reused.
Add initialization of _errors to an empty collection and reset any attendee
draft input variables (such as temporary attendee input fields being edited) to
their default empty states alongside the existing initializations of _title,
_description, _startDate, _endDate, _color, and _attendees to ensure clean state
each time the dialog opens.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor`:
- Around line 59-70: The div elements with role="button" for the
BitFullCalendarAgendaGroupBy.Date and BitFullCalendarAgendaGroupBy.Color options
have `@onkeydown` handlers (OnGroupByKeyDown method) that do not suppress the
default Space key behavior, allowing unwanted page scrolling when users activate
these controls with Space. Modify the OnGroupByKeyDown method to detect when the
Space key is pressed and prevent its default behavior, or alternatively add the
`@onkeydown`:preventDefault directive to the `@onkeydown` bindings on both div
elements to ensure keyboard-only users can interact with these controls without
triggering page scroll.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cs`:
- Around line 20-29: The timer callback in the BitFcCalendarTimeline component
can execute after the component is disposed, causing an ObjectDisposedException
when StateHasChanged is called. To fix this, add a private boolean field
_isDisposed to track disposal state, then add guard checks at the beginning of
the timer callback (before InvokeAsync) to return early if _isDisposed is true,
and in the Dispose method set _isDisposed to true before disposing the timer to
prevent any queued callbacks from executing state mutations on a disposed
component.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor`:
- Around line 108-130: The BitFcTimelineWeekView.razor component has nested
focusable button controls which creates accessibility issues. The outer hour
cell div contains role="button" with tabindex="0", and inside it is a half-hour
cell div that also has role="button" with tabindex="0". Remove the role="button"
and tabindex attributes from the outer hour cell div to make it a
non-interactive positioning wrapper, then restructure the markup to render the
0-minute and 30-minute slot targets as two sibling interactive button elements
instead of nesting them. Apply this same restructuring pattern to both the main
timeline slot section and the unassigned row section (the second location noted
in the comment).
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs`:
- Around line 18-37: The cultureChanged detection in the OnParametersSet method
uses ReferenceEquals to compare the Culture object with _lastSyncedCulture,
which only checks object reference identity rather than actual culture/calendar
state equality. This causes real culture changes to be missed if they come from
a different object instance. Replace the ReferenceEquals check with semantic
equality comparison using the Culture's Equals method or by comparing the
culture names/identifiers directly to properly detect when the actual
culture/calendar system has changed.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 06f5e0b1-2682-423b-96ad-3d3f6f446a2e
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarSettings.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (3)
src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss (1)
7-7: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winRemove the
.scssextension from this import.Line 7 still violates
scss/load-partial-extension, which can block stylelint checks.Suggested fix
-@import "../Components/FullCalendar/BitFullCalendar.scss"; +@import "../Components/FullCalendar/BitFullCalendar";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss` at line 7, The import statement for BitFullCalendar violates the scss/load-partial-extension stylelint rule because it explicitly includes the .scss file extension. Remove the .scss extension from the import path in the `@import` statement so that it reads "../Components/FullCalendar/BitFullCalendar" instead of "../Components/FullCalendar/BitFullCalendar.scss". This will allow stylelint to pass the check while maintaining the correct import functionality.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor (1)
16-19: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winNormalize blank resource IDs before using them as row interaction keys.
Line 17 excludes empty resource IDs from grouping, but Line 55 still uses raw
resource.Idfor slot/drop actions (Lines 67-70). This can route interactions through keys that are not part of the grouped resource contract.Suggested minimal normalization
- var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrEmpty(id)).ToList(); + var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrWhiteSpace(id)).ToList(); @@ - @{ var rowKey = resource.Id; var rowLabel = resource.Title; } + @{ var rowKey = string.IsNullOrWhiteSpace(resource.Id) ? _unassignedKey : resource.Id; var rowLabel = resource.Title; }Also applies to: 55-70
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor` around lines 16 - 19, The code on line 17 filters out empty or null resource IDs when building the resourceIds list for grouping, but the drop and slot action handlers around lines 55-70 use raw resource.Id values directly as interaction keys, which could include empty IDs. Apply the same normalization pattern used in line 17 (the Where clause that filters out empty IDs) to the resource IDs used as keys in the slot and drop action handlers so that only valid, non-empty resource IDs are used for row interactions and they match the grouped resource contract.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs (1)
28-30: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winDetect calendar-system changes, not just culture name.
Line 28 compares only
Culture.Name. If callers reuse the same culture name with a different calendar configuration,_visibleMonthAnchorwon’t re-anchor correctly.💡 Minimal patch
- private CultureInfo? _lastSyncedCulture; + private string? _lastCultureKey; @@ - var cultureChanged = !string.Equals(_lastSyncedCulture?.Name, Culture.Name, StringComparison.Ordinal); + var cultureKey = $"{Culture.Name}|{Culture.DateTimeFormat.Calendar.GetType().FullName}"; + var cultureChanged = !string.Equals(_lastCultureKey, cultureKey, StringComparison.Ordinal); @@ - _lastSyncedCulture = Culture; + _lastCultureKey = cultureKey;As per coding guidelines, cross-file and configuration/state checks should validate actual values, and the active calendar type is part of this component’s date contract.
Also applies to: 38-39
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs` around lines 28 - 30, The cultureChanged variable in the BitFcDateTimePicker component currently only compares the Culture.Name property, but this misses cases where the same culture is reused with a different calendar system. Modify the cultureChanged assignment to also check if the calendar system has changed by comparing the Calendar property of _lastSyncedCulture and Culture (in addition to comparing their Name properties). This same pattern check also appears elsewhere in the file (around lines 38-39) and should be updated consistently to detect both culture name and calendar-system changes.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cs`:
- Around line 15-17: The InitialExtraction method in BitFullCalendarAttendee is
not trimming whitespace from FirstName and LastName before extracting initials,
which causes leading spaces in names to produce blank initials. Apply the Trim()
method to FirstName and LastName before checking their length and extracting the
first character to ensure whitespace-prefixed names generate correct initials.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cs`:
- Line 14: The SelectedColors property in BitFullCalendarState class is exposed
as a public mutable List that allows external callers to directly modify it,
bypassing the UpdateUI() notification mechanism and causing state
desynchronization. Change the SelectedColors property to expose only a read-only
collection (such as IReadOnlyList or ReadOnlyCollection) while keeping the
internal list private, ensuring all modifications to the selected colors go
through controlled methods that properly trigger UpdateUI() and maintain state
consistency.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor`:
- Line 45: The hardcoded id "bit-bfc-agenda-scroll" on the div element in the
BitFcAgendaEvents component will be duplicated across multiple calendar
instances on the same page, causing DOM id conflicts and incorrect scrolling
behavior. Generate or use a unique instance identifier (such as a GUID or
component parameter) and incorporate it into the id attribute so each calendar
instance has a distinct id. This will ensure id-based scrolling targets the
correct agenda container.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cs`:
- Around line 107-119: The BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync
method is called with a hardcoded element ID string
"bit-bfc-day-timegrid-scroll", which causes issues when multiple calendar
instances render simultaneously as they reference the same target element. To
fix this, create a private unique identifier field per component instance
(following the GUID-backed pattern used in timeline views), replace the
hardcoded string "bit-bfc-day-timegrid-scroll" in the TryScrollToStartOfDayAsync
call with this unique field, and update the corresponding .razor markup to bind
the scroll container's id attribute to this same unique field value.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cs`:
- Around line 13-14: The _eventRows dictionary in
BitFcWeekViewMultiDayEventsRow.razor.cs currently uses ev.Id as a key, which
relies on a user-supplied ID string that can be duplicate or missing, causing
incorrect row placement for multi-day events. Change the key from the event's
string Id to a unique identifier that represents the event instance itself (such
as the event object reference or a tuple combining the event with date
information). Apply this change consistently across all locations where
_eventRows is populated or accessed, including the references at lines 41-42 and
56-57, to ensure row allocation is based on event instance identity rather than
potentially unreliable ID values.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cs`:
- Around line 28-30: The cultureChanged variable in the BitFcDateTimePicker
component currently only compares the Culture.Name property, but this misses
cases where the same culture is reused with a different calendar system. Modify
the cultureChanged assignment to also check if the calendar system has changed
by comparing the Calendar property of _lastSyncedCulture and Culture (in
addition to comparing their Name properties). This same pattern check also
appears elsewhere in the file (around lines 38-39) and should be updated
consistently to detect both culture name and calendar-system changes.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor`:
- Around line 16-19: The code on line 17 filters out empty or null resource IDs
when building the resourceIds list for grouping, but the drop and slot action
handlers around lines 55-70 use raw resource.Id values directly as interaction
keys, which could include empty IDs. Apply the same normalization pattern used
in line 17 (the Where clause that filters out empty IDs) to the resource IDs
used as keys in the slot and drop action handlers so that only valid, non-empty
resource IDs are used for row interactions and they match the grouped resource
contract.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Line 7: The import statement for BitFullCalendar violates the
scss/load-partial-extension stylelint rule because it explicitly includes the
.scss file extension. Remove the .scss extension from the import path in the
`@import` statement so that it reads "../Components/FullCalendar/BitFullCalendar"
instead of "../Components/FullCalendar/BitFullCalendar.scss". This will allow
stylelint to pass the check while maintaining the correct import functionality.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 50cd2d85-9a04-4492-ae4f-bb5588f42b81
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarSettings.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 8
♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor (1)
9-21: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winKeep Event mode tab visible when there are no resources.
Line 9 hides the entire mode-tab container when
State.Resources.Count == 0, which removes Event mode switching entirely. Keep the container rendered and only suppress the Timeline tab when resources are unavailable.Suggested minimal patch
-@if (State.Resources.Count > 0) -{ - <div class="bit-bfc-mode-tabs"> - `@foreach` (var mode in _modes) - { - <button class="bit-bfc-mode-tab @(State.Mode == mode ? "active" : "")" - type="button" - `@onclick`="() => State.SetMode(mode)"> - `@Texts.GetModeLabel`(mode) - </button> - } - </div> -} +<div class="bit-bfc-mode-tabs"> + `@foreach` (var mode in _modes) + { + if (mode is BitFullCalendarMode.Timeline && State.Resources.Count == 0) continue; + + <button class="bit-bfc-mode-tab @(State.Mode == mode ? "active" : "")" + type="button" + `@onclick`="() => State.SetMode(mode)"> + `@Texts.GetModeLabel`(mode) + </button> + } +</div>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor` around lines 9 - 21, The outer conditional in BitFcModeTabs.razor that checks State.Resources.Count > 0 prevents the entire mode-tabs container from rendering when there are no resources, which removes the Event mode option. Remove the outer if condition that wraps the div with class bit-bfc-mode-tabs so the container always renders. Then inside the foreach loop that iterates through _modes, add a conditional check to skip rendering the button only when the current mode is Timeline and State.Resources.Count is zero, allowing Event mode to remain available while suppressing the Timeline tab.
🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor (1)
6-10: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd
@keyto stabilize badge identity during list updates.Without a key, Blazor can reuse badge component instances by position when event ordering changes.
♻️ Suggested change
`@foreach` (var ev in _multiDayForDay) { var position = GetPosition(ev); - <BitFcMonthEventBadge Event="ev" CellDate="Date" Position="`@position`" OnSelected="ShowEventDetails" EventTemplate="EventTemplate" /> + <BitFcMonthEventBadge `@key`="ev.Id" Event="ev" CellDate="Date" Position="`@position`" OnSelected="ShowEventDetails" EventTemplate="EventTemplate" /> }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor` around lines 6 - 10, The foreach loop that renders BitFcMonthEventBadge components is missing a `@key` directive, which allows Blazor to reuse component instances by position when the _multiDayForDay list order changes, causing potential state and rendering issues. Add a `@key` directive to the foreach loop iterating over _multiDayForDay, using a unique identifier from the event object (such as the event's Id property) as the key value to ensure each BitFcMonthEventBadge component maintains stable identity across re-renders.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cs`:
- Around line 38-43: The parametersChanged variable in the comparison logic is
missing a check for the Resource parameter. Add Resource to the reinitialization
change key by including a comparison between the current Resource and a stored
_lastResource field (similar to how _lastExistingEvent, _lastStartDate,
_lastStartHour, and _lastStartMinute are compared). This will ensure that when
the dialog is reused with the same event and start parameters but a different
resource, it properly reinitializes instead of maintaining stale draft state.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cs`:
- Around line 690-701: The CreateDraftEventForTimeSlot method accepts hour,
startMinute, and durationMinutes parameters without validation, allowing invalid
values to create malformed date ranges. Add explicit input validation at the
start of the CreateDraftEventForTimeSlot method to ensure hour is between 0 and
23, startMinute is between 0 and 59, and durationMinutes is greater than zero.
If any validation fails, throw an appropriate exception with a descriptive
message to catch these errors at the boundary.
- Around line 640-653: The XML documentation for the CeilToMinuteInterval method
claims results will be on the same calendar day, but the implementation at line
652 can return a time on the next calendar day when the interval calculation
crosses midnight (e.g., 23:59 with a 30-minute interval). Either update the XML
documentation lines to accurately reflect that the result may span into the next
day, or modify the implementation logic to clamp the result back to the current
day or throw an exception when the interval exceeds the day boundary. Choose the
approach that best aligns with the intended use cases for this method.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cs`:
- Around line 20-28: The await call to
BitFcAgendaScrollInterop.TryScrollToDateAsync in the OnAfterRenderAsync method
lacks exception handling, which can cause render path failures during prerender,
teardown, or disconnect scenarios. Wrap the await statement in a try-catch block
to handle transient JavaScript interop exceptions gracefully, using the same
error handling pattern that is already implemented elsewhere in this feature for
similar interop calls. The catch block should log the exception or handle it
silently to prevent circuit crashes while still allowing the scroll
functionality to attempt execution.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cs`:
- Around line 101-104: The BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync
call uses a hard-coded DOM id string "bit-bfc-week-timegrid-scroll" which causes
all instances of BitFcCalendarWeekView to target the same element. Create an
instance-scoped field (for example, _timeGridScrollElementId) to generate a
unique id per component instance, then replace the hard-coded string with this
field in the TryScrollToStartOfDayAsync call. Additionally, in the
BitFcCalendarWeekView.razor template, update the timegrid container element's id
attribute to use the same instance field (id="`@_timeGridScrollElementId`") to
ensure the interop targets the correct element for each instance.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cs`:
- Around line 97-101: The SlotAriaLabel method currently calls
BitFullCalendarHelpers.FormatTime without passing the State.Culture parameter,
which causes the time to be formatted using the default culture instead of the
selected calendar culture. Update the FormatTime call on line 100 to include
State.Culture as an additional parameter so that the ARIA label time formatting
matches the calendar's selected culture.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cs`:
- Around line 136-143: The scroll signature is not being reset when navigating
away from the current month. Currently, when the year or month of the selected
date doesn't match today's year or month, the method returns early without
clearing the _scrollSignature variable. This causes the scroll-to-today logic to
be skipped when navigating back to the same current month later, since the old
signature still matches. To fix this, assign an empty string to _scrollSignature
before the early return statement in the condition that checks if
cal.GetYear(State.SelectedDate) and cal.GetMonth(State.SelectedDate) don't match
the current date's year and month.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cs`:
- Around line 99-103: The SlotAriaLabel method's call to
BitFullCalendarHelpers.FormatTime is not passing the State.Culture parameter,
causing the time formatting to use the default culture instead of the selected
calendar culture. Modify the FormatTime method call to include State.Culture as
a parameter alongside State.Use24HourFormat to ensure the ARIA label respects
the user's selected culture setting.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor`:
- Around line 9-21: The outer conditional in BitFcModeTabs.razor that checks
State.Resources.Count > 0 prevents the entire mode-tabs container from rendering
when there are no resources, which removes the Event mode option. Remove the
outer if condition that wraps the div with class bit-bfc-mode-tabs so the
container always renders. Then inside the foreach loop that iterates through
_modes, add a conditional check to skip rendering the button only when the
current mode is Timeline and State.Resources.Count is zero, allowing Event mode
to remain available while suppressing the Timeline tab.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor`:
- Around line 6-10: The foreach loop that renders BitFcMonthEventBadge
components is missing a `@key` directive, which allows Blazor to reuse component
instances by position when the _multiDayForDay list order changes, causing
potential state and rendering issues. Add a `@key` directive to the foreach loop
iterating over _multiDayForDay, using a unique identifier from the event object
(such as the event's Id property) as the key value to ensure each
BitFcMonthEventBadge component maintains stable identity across re-renders.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 9b59eb62-014d-44f3-bed9-5231c2243e42
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarSettings.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cs`:
- Around line 39-44: The parametersChanged check in BitFcAddEditEventDialog does
not account for changes to the fallback date source. Since line 83-84 uses
StartDate ?? State.SelectedDate to derive the new-event base date, the
reinitialization logic must also track State.SelectedDate in addition to
StartDate. If StartDate is null and State.SelectedDate changes, the dialog will
not reinitialize and will keep stale date values. Add State.SelectedDate to the
parametersChanged comparison by storing the last known value (such as
_lastSelectedDate) and comparing it against the current State.SelectedDate,
similar to how StartDate, StartHour, StartMinute, and Resource are already being
tracked in the parametersChanged condition.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs`:
- Line 16: The Attendees property in BitFullCalendarEvent initializes to an
empty list but allows null to be assigned through its public setter, causing
NullReferenceException in downstream code that iterates over Attendees. Guard
the property setter to prevent null assignment by implementing a setter that
either rejects null values or coalesces null assignments to an empty list,
ensuring Attendees is never null at the model boundary.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor`:
- Around line 29-30: The `@onkeydown` event handler in BitFcMonthEventBadge.razor
is missing event propagation stopping, which allows keyboard events to bubble up
to the parent BitFcDayCell.razor component and trigger both the badge action and
the cell's add-event action. Add :stopPropagation="true" to the `@onkeydown`
directive (similar to how it's already applied to
`@onclick`:stopPropagation="true" on the same element) to prevent keyboard events
from bubbling to the parent day-cell key handler.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor`:
- Around line 41-43: The issue is that HasUnassignedRow becomes false when there
are no resources and no existing unassigned events, resulting in no slot cells
being rendered. Update the logic that determines HasUnassignedRow to ensure it
returns true when State.Resources is empty, even if there are currently no
unassigned events. This will render an empty unassigned row that allows users to
create the first event. The same fix should also be applied at lines 122-124
where similar logic exists.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor`:
- Around line 48-49: The timeline week view becomes unusable when
State.Resources is empty and there are no unassigned events, because
hasUnassigned evaluates to false and no rows render. Modify the hasUnassigned
variable calculation in BitFcTimelineWeekView to also check if State.Resources
is empty or contains no items. The unassigned lane should be displayed whenever
there are no resources, ensuring there is always at least one row available
where users can add the first event to the timeline.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 96e37496-1ba6-4aaf-bd89-45ba2df89212
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarSettings.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 8
♻️ Duplicate comments (7)
src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss (1)
7-7: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winRemove the extension from the SCSS import to satisfy stylelint.
Line 7 still violates
scss/load-partial-extension; this can fail lint checks.Suggested fix
-@import "../Components/FullCalendar/BitFullCalendar.scss"; +@import "../Components/FullCalendar/BitFullCalendar";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss` at line 7, The SCSS import statement violates the scss/load-partial-extension stylelint rule because it includes the .scss file extension in the path. Remove the .scss extension from the import statement that references BitFullCalendar so that it imports the partial file without the extension. This will allow the stylelint check to pass.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs (1)
8-9: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
EndDate >= StartDateinvariant is still not enforced.The model still allows inverted ranges, so
Durationcan be negative and downstream scheduling logic can process invalid event windows.Suggested fix
public class BitFullCalendarEvent { + private DateTime _startDate; + private DateTime _endDate; + @@ - public DateTime StartDate { get; set; } - public DateTime EndDate { get; set; } + public DateTime StartDate + { + get => _startDate; + set + { + _startDate = value; + if (_endDate < _startDate) + throw new ArgumentException("EndDate must be greater than or equal to StartDate."); + } + } + + public DateTime EndDate + { + get => _endDate; + set + { + if (value < _startDate) + throw new ArgumentException("EndDate must be greater than or equal to StartDate."); + _endDate = value; + } + }Also applies to: 34-37
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs` around lines 8 - 9, The BitFullCalendarEvent model does not enforce the invariant that EndDate must be greater than or equal to StartDate, allowing invalid event windows where Duration becomes negative. Add validation logic to the property setters for StartDate and EndDate (also apply to the corresponding properties mentioned at lines 34-37) to ensure EndDate is never less than StartDate. When either property is set, validate the relationship between both dates and throw an appropriate exception if the invariant would be violated.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs (1)
20-29: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winConstructor snapshot is still shallow, so lookup/order can drift.
Optionscopies references, not option objects. External mutation of an option (notablyId) can desync_byIdfromOptions.Suggested fix
public BitFullCalendarColorScheme(IReadOnlyList<BitFullCalendarColorOption>? options) { var list = options is { Count: > 0 } ? options : BitFullCalendarColorOption.Defaults; - // Snapshot the source so Options and the _byId lookup can't drift apart if the caller mutates the original list. - Options = [.. list]; + // Deep snapshot to prevent external mutations from drifting lookup/order. + Options = list.Select(o => new BitFullCalendarColorOption + { + Id = o.Id, + Title = o.Title, + Value = o.Value + }).ToArray(); _byId = new Dictionary<string, BitFullCalendarColorOption>(StringComparer.OrdinalIgnoreCase); - foreach (var o in list) + foreach (var o in Options) { var id = o.Id?.Trim(); if (!string.IsNullOrEmpty(id) && !_byId.ContainsKey(id)) _byId[id] = o; } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs` around lines 20 - 29, The Options field assignment creates a shallow copy of the list, meaning the array contains references to the original BitFullCalendarColorOption objects. If external code mutates an option's Id property after construction, the _byId dictionary lookup will become desynchronized from Options. To fix this, create a deep copy by cloning each BitFullCalendarColorOption object when populating the Options array instead of copying references directly. Each BitFullCalendarColorOption in the Options snapshot should be an independent copy so that external mutations to the original objects cannot affect the internal state of Options and _byId.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cs (1)
24-31: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDispose path can still race
Task.Delaytoken access.Disposing each
CancellationTokenSourceinDisposeAsynccan happen beforeRemoveAfterDelayreadscts.Token, which can fault the background task withObjectDisposedException. Keep cancellation inDisposeAsync, but letRemoveAfterDelayown disposal.Suggested minimal fix
private async Task RemoveAfterDelay(int id, CancellationTokenSource cts) { @@ finally { - // Drop the token as soon as its timer finishes (or is cancelled) so _removalTokens - // doesn't grow unbounded on long-lived pages that show many toasts. - bool removed; lock (_removalTokensLock) { - removed = _removalTokens.Remove(cts); + _removalTokens.Remove(cts); } - if (removed) - cts.Dispose(); + cts.Dispose(); } } @@ foreach (var cts in tokens) { - try - { - cts.Cancel(); - cts.Dispose(); - } - catch (ObjectDisposedException) - { - // Already disposed by RemoveAfterDelay's cleanup; nothing to do. - } + cts.Cancel(); }Also applies to: 44-55, 69-79
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cs` around lines 24 - 31, The RemoveAfterDelay method has a race condition where DisposeAsync can dispose the CancellationTokenSource before RemoveAfterDelay accesses the cts.Token property, causing an ObjectDisposedException. To fix this, modify RemoveAfterDelay to take ownership of disposing the CancellationTokenSource after it completes its operation. In DisposeAsync, keep the cancellation logic (call cts.Cancel()) to signal cancellation but remove the direct disposal of the CancellationTokenSource instances. Instead, let each RemoveAfterDelay invocation dispose its own cts in a finally block after the Task.Delay completes, ensuring the token is never accessed after disposal.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss (1)
3-3: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winFix the SCSS import to satisfy
scss/load-partial-extension.Line 3 still imports with
.scss, which keeps the prior lint blocker unresolved.Suggested fix
-@import "../../../Bit.BlazorUI/Styles/functions.scss"; +@import "../../../Bit.BlazorUI/Styles/functions";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss` at line 3, The SCSS import statement in the BitFullCalendar.scss file is including the `.scss` file extension in the import path, which violates the scss/load-partial-extension linter rule. Remove the `.scss` extension from the import path for the functions.scss file on line 3, as SCSS partials can be imported without their file extension. This will resolve the lint rule violation while maintaining the same functionality.src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.ts (1)
123-127: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winCapture early pointer-up coordinates before deferring resize end.
Line 126 and Line 230 defer
endResizebefore copying pointer position. If release happens beforeOnResizeStartcompletes (and no move event fires), final delta can be stale/zero.💡 Minimal patch
const endResize = async (ev?: PointerEvent) => { if (ev && activePointerId != null && ev.pointerId !== activePointerId) return; + if (ev) latestY = ev.clientY; // A pointer release before resize-start completes is deferred and replayed afterwards. if (!startSucceeded) { pendingEnd = true; return; } if (ended) return; @@ const endResize = async (ev?: PointerEvent) => { if (ev && activePointerId != null && ev.pointerId !== activePointerId) return; + if (ev) latestX = ev.clientX; // A pointer release before resize-start completes is deferred and replayed afterwards. if (!startSucceeded) { pendingEnd = true; return; } if (ended) return;Also applies to: 227-231
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.ts` around lines 123 - 127, The endResize function defers execution when startSucceeded is false by setting pendingEnd to true and returning early, but the pointer event coordinates (such as clientX and clientY from the ev parameter) are not captured at that moment of deferral. This means when endResize is replayed later after OnResizeStart completes, if no move event fires in between, the pointer coordinates will be stale or zero, resulting in incorrect final delta calculations. Capture and store the pointer event coordinates from the ev parameter before returning on the deferred condition (when !startSucceeded is true), then use these stored coordinates when the deferred endResize is replayed. Apply the same fix to the corresponding deferred handler around line 230 which handles the same scenario (lines 227-231).src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cs (1)
84-84: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winCapture
OldEventsnapshot before callingState.UpdateEvent.Line 84 stores a live reference (
_resizeBaseEvent = Event), and Line 196 clones after Line 191 updates state. IfState.UpdateEventmutates the existing instance,OldEventcan be emitted with updated values instead of the pre-resize state.Suggested fix
[JSInvokable] public void OnResizeStart(string direction) { _isResizing = true; _resizeDirection = direction; - _resizeBaseEvent = Event; + _resizeBaseEvent = BitFullCalendarChangeNotifier.CloneEvent(Event); @@ if (s != _resizeBaseEvent.StartDate || e != _resizeBaseEvent.EndDate) { var b = _resizeBaseEvent; + var oldSnapshot = BitFullCalendarChangeNotifier.CloneEvent(b); var updated = new BitFullCalendarEvent { @@ await Notifier.NotifyAsync(new BitFullCalendarChangeEventArgs { Event = BitFullCalendarChangeNotifier.CloneEvent(updated), - OldEvent = BitFullCalendarChangeNotifier.CloneEvent(b), + OldEvent = oldSnapshot, Kind = BitFullCalendarChangeKind.Edit, Source = BitFullCalendarChangeSource.Resize }); }Also applies to: 191-197
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cs` at line 84, The assignment at line 84 stores a live reference to the Event instead of a snapshot, which means if State.UpdateEvent mutates the event instance at line 191, the _resizeBaseEvent reference will also be mutated. This causes OldEvent to be emitted with updated values instead of the pre-resize state. Create a deep clone or snapshot of the Event when assigning to _resizeBaseEvent at line 84 to ensure OldEvent captures the original pre-resize state before State.UpdateEvent is called on lines 191-197.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor`:
- Line 12: The focusable div element with class "bit-bfc-agenda-item" and
tabindex="0" has a `@onkeydown` handler binding that calls OnEventKeyDown, but the
default Space key scroll behavior is not being prevented, causing unwanted
page/dialog scrolling. Modify the `@onkeydown` directive on this div element to
include preventDefault behavior to stop the default scroll action from occurring
when Space or Enter keys are pressed on the focusable element.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor`:
- Line 10: The `@onkeydown` directive in the BitFcDraggableEvent component needs
to prevent the default browser behavior for Space and Enter key presses to avoid
unwanted page scrolling. Add preventDefault handling to the `@onkeydown` event
binding by either using `@onkeydown`:preventDefault="true" on the directive, or
modify the OnKeyDown event handler method to call preventDefault when Space or
Enter keys are detected. This ensures keyboard activation behaves predictably
without triggering default scroll behavior.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cs`:
- Around line 111-122: The BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync
call in the OnAfterRenderAsync method can throw transient JavaScript lifecycle
exceptions during prerender or disconnect phases. Wrap this interop call in a
try-catch block to guard against these transient failures, and only update the
_timeGridScrollSignature property when the operation completes successfully
without throwing an exception.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cs`:
- Around line 96-107: The call to
BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync in the OnAfterRenderAsync
method can throw exceptions during JavaScript unavailability
(disconnect/teardown scenarios), causing render failures. Wrap the entire
if-statement containing the TryScrollToStartOfDayAsync call in a try-catch block
to gracefully catch and handle these transient exceptions without allowing them
to propagate and fail the render.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor`:
- Around line 16-19: The hasUnassigned flag only becomes true when unassigned
events already exist, but it should also be true when there are no valid
resources, ensuring an unassigned row is always rendered. Modify the logic that
sets hasUnassigned to check not only for the existence of unassigned events in
the grouped data, but also to return true when the resourceIds list is empty, so
that users can create events even in an empty calendar with no resources.
- Around line 62-84: Remove the nested focusable structure in
BitFcTimelineDayView.razor where the hour slot (outer div with role="button")
contains a half-hour slot (inner div with role="button"). Instead, render both
the 0-minute and 30-minute time slot targets as sibling native button elements
(button type="button") outside of each other, ensuring each button independently
calls the same event handlers OnDragEnter, OnDrop, OnSlotClickAsync, and
OnSlotKeyDownAsync with their respective minute values (0 or 30). Apply this
same restructuring to the other instance mentioned at lines 106-128.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor`:
- Around line 18-19: The resource filtering logic in the
BitFcTimelineLayout.razor file uses string.IsNullOrEmpty to check if a resource
ID is assigned, but this does not handle whitespace-only strings which should
also be treated as unassigned. Replace the string.IsNullOrEmpty call on r.Id
with string.IsNullOrWhiteSpace to properly filter out resources with empty or
whitespace-only IDs in the Where clause that filters State.Resources.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor`:
- Around line 20-21: The hasUnassigned logic in the BitFcTimelineWeekView
component (referenced at lines 48-52) is currently checking against the raw
resource count rather than the valid resource IDs. Since resourceIds is already
filtered to exclude empty IDs using the Select and Where chain, update the
hasUnassigned check to base its condition on the count of valid resourceIds
instead of the total resources count to ensure the unassigned fallback row is
properly shown when there are no valid resources with non-empty IDs.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cs`:
- Around line 24-31: The RemoveAfterDelay method has a race condition where
DisposeAsync can dispose the CancellationTokenSource before RemoveAfterDelay
accesses the cts.Token property, causing an ObjectDisposedException. To fix
this, modify RemoveAfterDelay to take ownership of disposing the
CancellationTokenSource after it completes its operation. In DisposeAsync, keep
the cancellation logic (call cts.Cancel()) to signal cancellation but remove the
direct disposal of the CancellationTokenSource instances. Instead, let each
RemoveAfterDelay invocation dispose its own cts in a finally block after the
Task.Delay completes, ensuring the token is never accessed after disposal.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scss`:
- Line 3: The SCSS import statement in the BitFullCalendar.scss file is
including the `.scss` file extension in the import path, which violates the
scss/load-partial-extension linter rule. Remove the `.scss` extension from the
import path for the functions.scss file on line 3, as SCSS partials can be
imported without their file extension. This will resolve the lint rule violation
while maintaining the same functionality.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.ts`:
- Around line 123-127: The endResize function defers execution when
startSucceeded is false by setting pendingEnd to true and returning early, but
the pointer event coordinates (such as clientX and clientY from the ev
parameter) are not captured at that moment of deferral. This means when
endResize is replayed later after OnResizeStart completes, if no move event
fires in between, the pointer coordinates will be stale or zero, resulting in
incorrect final delta calculations. Capture and store the pointer event
coordinates from the ev parameter before returning on the deferred condition
(when !startSucceeded is true), then use these stored coordinates when the
deferred endResize is replayed. Apply the same fix to the corresponding deferred
handler around line 230 which handles the same scenario (lines 227-231).
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cs`:
- Around line 20-29: The Options field assignment creates a shallow copy of the
list, meaning the array contains references to the original
BitFullCalendarColorOption objects. If external code mutates an option's Id
property after construction, the _byId dictionary lookup will become
desynchronized from Options. To fix this, create a deep copy by cloning each
BitFullCalendarColorOption object when populating the Options array instead of
copying references directly. Each BitFullCalendarColorOption in the Options
snapshot should be an independent copy so that external mutations to the
original objects cannot affect the internal state of Options and _byId.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cs`:
- Around line 8-9: The BitFullCalendarEvent model does not enforce the invariant
that EndDate must be greater than or equal to StartDate, allowing invalid event
windows where Duration becomes negative. Add validation logic to the property
setters for StartDate and EndDate (also apply to the corresponding properties
mentioned at lines 34-37) to ensure EndDate is never less than StartDate. When
either property is set, validate the relationship between both dates and throw
an appropriate exception if the invariant would be violated.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cs`:
- Line 84: The assignment at line 84 stores a live reference to the Event
instead of a snapshot, which means if State.UpdateEvent mutates the event
instance at line 191, the _resizeBaseEvent reference will also be mutated. This
causes OldEvent to be emitted with updated values instead of the pre-resize
state. Create a deep clone or snapshot of the Event when assigning to
_resizeBaseEvent at line 84 to ensure OldEvent captures the original pre-resize
state before State.UpdateEvent is called on lines 191-197.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Line 7: The SCSS import statement violates the scss/load-partial-extension
stylelint rule because it includes the .scss file extension in the path. Remove
the .scss extension from the import statement that references BitFullCalendar so
that it imports the partial file without the extension. This will allow the
stylelint check to pass.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5eea49d8-8794-422a-a7e2-7b792ef16a23
📒 Files selected for processing (100)
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcAddEditEventDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcDateTimePicker.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventDetailsDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDroppableArea.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarAgendaGroupBy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarBadgeVariant.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarEventLayout.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Enums/BitFullCalendarView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcCalendarHeader.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcDateNavigator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcFilterEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcModeTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcSettings.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcTodayButton.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Header/BitFcViewTabs.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarAttendee.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarCell.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorOption.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarColorScheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarDateChangeEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarEvent.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarResource.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarSettings.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Models/BitFullCalendarTexts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcAgendaScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimeGridScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFcTimelineScrollInterop.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarChangeNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarHelpers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Services/BitFullCalendarState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/AgendaView/BitFcAgendaEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarTimeline.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcDayViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcMiniCalendar.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcRenderGroupedEvents.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcTimeColumn.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcWeekViewMultiDayEventsRow.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcCalendarMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcDayCell.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcEventBullet.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/MonthView/BitFcMonthEventBadge.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineEventBlock.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineMonthView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/YearView/BitFcCalendarYearView.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/FullCalendar/BitFullCalendarDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Home/ComponentsSection.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
| <div class="bit-bfc-dialog-body" style="max-height:400px;overflow-y:auto;"> | ||
| @foreach (var ev in Events) | ||
| { | ||
| <div class="bit-bfc-agenda-item" tabindex="0" role="button" @onclick="() => SelectEvent(ev)" @onkeydown="@(e => OnEventKeyDown(e, ev))"> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Prevent page scroll when activating event rows with Space.
Line 12 binds Space/Enter via @onkeydown, but Space on a focusable div can still scroll the dialog/page by default. Add keydown prevent-default on this element.
Suggested patch
- <div class="bit-bfc-agenda-item" tabindex="0" role="button" `@onclick`="() => SelectEvent(ev)" `@onkeydown`="@(e => OnEventKeyDown(e, ev))">
+ <div class="bit-bfc-agenda-item"
+ tabindex="0"
+ role="button"
+ `@onclick`="() => SelectEvent(ev)"
+ `@onkeydown`="@(e => OnEventKeyDown(e, ev))"
+ `@onkeydown`:preventDefault="true">📝 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.
| <div class="bit-bfc-agenda-item" tabindex="0" role="button" @onclick="() => SelectEvent(ev)" @onkeydown="@(e => OnEventKeyDown(e, ev))"> | |
| <div class="bit-bfc-agenda-item" | |
| tabindex="0" | |
| role="button" | |
| `@onclick`="() => SelectEvent(ev)" | |
| `@onkeydown`="@(e => OnEventKeyDown(e, ev))" | |
| `@onkeydown`:preventDefault="true"> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Dialogs/BitFcEventListDialog.razor`
at line 12, The focusable div element with class "bit-bfc-agenda-item" and
tabindex="0" has a `@onkeydown` handler binding that calls OnEventKeyDown, but the
default Space key scroll behavior is not being prevented, causing unwanted
page/dialog scrolling. Modify the `@onkeydown` directive on this div element to
include preventDefault behavior to stop the default scroll action from occurring
when Space or Enter keys are pressed on the focusable element.
| @ondragstart="OnDragStart" | ||
| @ondragend="OnDragEnd" | ||
| @onclick="OnClick" | ||
| @onkeydown="OnKeyDown" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Prevent default keydown behavior for keyboard activation.
Line 10 handles Space/Enter, but default Space behavior can scroll the page on focused div. Prevent default on keydown to keep activation predictable.
Suggested patch
<div draggable="true"
class="@(_isDragged ? "bit-bfc-dragging" : "") `@Class`"
role="button"
tabindex="0"
`@ondragstart`="OnDragStart"
`@ondragend`="OnDragEnd"
`@onclick`="OnClick"
`@onkeydown`="OnKeyDown"
+ `@onkeydown`:preventDefault="true"
`@onclick`:stopPropagation="true">📝 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.
| @onkeydown="OnKeyDown" | |
| <div draggable="true" | |
| class="@(_isDragged ? "bit-bfc-dragging" : "") `@Class`" | |
| role="button" | |
| tabindex="0" | |
| `@ondragstart`="OnDragStart" | |
| `@ondragend`="OnDragEnd" | |
| `@onclick`="OnClick" | |
| `@onkeydown`="OnKeyDown" | |
| `@onkeydown`:preventDefault="true" | |
| `@onclick`:stopPropagation="true"> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/DragDrop/BitFcDraggableEvent.razor`
at line 10, The `@onkeydown` directive in the BitFcDraggableEvent component needs
to prevent the default browser behavior for Space and Enter key presses to avoid
unwanted page scrolling. Add preventDefault handling to the `@onkeydown` event
binding by either using `@onkeydown`:preventDefault="true" on the directive, or
modify the OnKeyDown event handler method to call preventDefault when Space or
Enter keys are detected. This ensures keyboard activation behaves predictably
without triggering default scroll behavior.
| protected override async Task OnAfterRenderAsync(bool firstRender) | ||
| { | ||
| var sig = BuildTimeGridScrollSignature(); | ||
| if (sig == _timeGridScrollSignature) | ||
| return; | ||
|
|
||
| if (await BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync( | ||
| JS, | ||
| _scrollContainerId, | ||
| State.StartOfDayHour)) | ||
| _timeGridScrollSignature = sig; | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Guard day-view time-grid interop against transient JS lifecycle failures.
Line 117 can throw during prerender/disconnect and break the render path. Wrap the interop call in a transient-exception guard and only update _timeGridScrollSignature on success.
Suggested patch
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var sig = BuildTimeGridScrollSignature();
if (sig == _timeGridScrollSignature)
return;
- if (await BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync(
- JS,
- _scrollContainerId,
- State.StartOfDayHour))
- _timeGridScrollSignature = sig;
+ try
+ {
+ if (await BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync(
+ JS,
+ _scrollContainerId,
+ State.StartOfDayHour))
+ _timeGridScrollSignature = sig;
+ }
+ catch (Exception ex) when (ex is JSException or JSDisconnectedException or InvalidOperationException or OperationCanceledException)
+ {
+ // JS/runtime unavailable during transient lifecycle states; retry on a later render.
+ }
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarDayView.razor.cs`
around lines 111 - 122, The
BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync call in the
OnAfterRenderAsync method can throw transient JavaScript lifecycle exceptions
during prerender or disconnect phases. Wrap this interop call in a try-catch
block to guard against these transient failures, and only update the
_timeGridScrollSignature property when the operation completes successfully
without throwing an exception.
| protected override async Task OnAfterRenderAsync(bool firstRender) | ||
| { | ||
| var sig = BuildTimeGridScrollSignature(); | ||
| if (sig == _timeGridScrollSignature) | ||
| return; | ||
|
|
||
| if (await BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync( | ||
| JS, | ||
| _timeGridScrollElementId, | ||
| State.StartOfDayHour)) | ||
| _timeGridScrollSignature = sig; | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Add transient exception handling around week-view scroll interop.
Line 102 is in the render path and can throw during JS unavailability (disconnect/teardown), causing avoidable render failures.
Suggested patch
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var sig = BuildTimeGridScrollSignature();
if (sig == _timeGridScrollSignature)
return;
- if (await BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync(
- JS,
- _timeGridScrollElementId,
- State.StartOfDayHour))
- _timeGridScrollSignature = sig;
+ try
+ {
+ if (await BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync(
+ JS,
+ _timeGridScrollElementId,
+ State.StartOfDayHour))
+ _timeGridScrollSignature = sig;
+ }
+ catch (Exception ex) when (ex is JSException or JSDisconnectedException or InvalidOperationException or OperationCanceledException)
+ {
+ // Transient renderer/JS lifecycle condition; retry on a later render.
+ }
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/DayWeekView/BitFcCalendarWeekView.razor.cs`
around lines 96 - 107, The call to
BitFcTimeGridScrollInterop.TryScrollToStartOfDayAsync in the OnAfterRenderAsync
method can throw exceptions during JavaScript unavailability
(disconnect/teardown scenarios), causing render failures. Wrap the entire
if-statement containing the TryScrollToStartOfDayAsync call in a try-catch block
to gracefully catch and handle these transient exceptions without allowing them
to propagate and fail the render.
| var resources = State.Resources; | ||
| var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrEmpty(id)).ToList(); | ||
| var grouped = BitFullCalendarHelpers.GroupEventsByResourceForDay( | ||
| Events, State.SelectedDate, resourceIds, _unassignedKey); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Render an unassigned row when there are no valid resources.
Currently hasUnassigned is only true when unassigned events already exist. With an empty calendar and no resources, the timeline renders no rows, so users have nowhere to create the first event.
🐛 Proposed fix
- var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrEmpty(id)).ToList();
+ var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrWhiteSpace(id)).ToList();
@@
- var hasUnassigned = grouped.TryGetValue(_unassignedKey, out var u) && u.Count > 0;
+ var hasUnassignedEvents = grouped.TryGetValue(_unassignedKey, out var unassignedLanes) && unassignedLanes.Count > 0;
+ var hasUnassigned = hasUnassignedEvents || resourceIds.Count == 0;
+ var unassignedLaneCount = hasUnassignedEvents ? unassignedLanes.Count : 1;
var scrollHour = State.StartOfDayHour;
}
@@
- UnassignedRowHeight="RowHeight(hasUnassigned ? grouped[_unassignedKey].Count : 1)">
+ UnassignedRowHeight="RowHeight(unassignedLaneCount)">Also applies to: 30-39
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor`
around lines 16 - 19, The hasUnassigned flag only becomes true when unassigned
events already exist, but it should also be true when there are no valid
resources, ensuring an unassigned row is always rendered. Modify the logic that
sets hasUnassigned to check not only for the existence of unassigned events in
the grouped data, but also to return true when the resourceIds list is empty, so
that users can create events even in an empty calendar with no resources.
| <div class="bit-bfc-tl-cell @(isPreviewHour ? "bit-bfc-tl-drop-preview" : "")" | ||
| style="left:@(hour * hourWidth)px;width:@(hourWidth)px;" | ||
| role="button" | ||
| tabindex="0" | ||
| aria-label="@SlotAriaLabel(rowLabel, hour, 0)" | ||
| @ondragenter="() => OnDragEnter(rowKey, hour, 0)" | ||
| @ondragover:preventDefault="true" | ||
| @ondrop="() => OnDrop(rowKey, hour, 0)" | ||
| @onclick="() => OnSlotClickAsync(rowKey, hour, 0)" | ||
| @onkeydown="e => OnSlotKeyDownAsync(e, rowKey, hour, 0)"> | ||
| <div class="bit-bfc-tl-cell-half @(isPreviewHalf ? "bit-bfc-tl-drop-preview" : "")" | ||
| role="button" | ||
| tabindex="0" | ||
| aria-label="@SlotAriaLabel(rowLabel, hour, 30)" | ||
| @ondragenter="() => OnDragEnter(rowKey, hour, 30)" | ||
| @ondragenter:stopPropagation="true" | ||
| @ondragover:preventDefault="true" | ||
| @ondrop:stopPropagation="true" | ||
| @ondrop="() => OnDrop(rowKey, hour, 30)" | ||
| @onclick:stopPropagation="true" | ||
| @onclick="() => OnSlotClickAsync(rowKey, hour, 30)" | ||
| @onkeydown="e => OnSlotKeyDownAsync(e, rowKey, hour, 30)" | ||
| @onkeydown:stopPropagation="true"></div> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Avoid nested focusable slot controls.
The hour slot is focusable with role="button", and it contains another focusable role="button" for the half-hour target. Nested interactive controls are unreliable for keyboard and assistive-tech activation; render the 0-minute and 30-minute targets as sibling controls, preferably native button type="button" elements.
Also applies to: 106-128
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineDayView.razor`
around lines 62 - 84, Remove the nested focusable structure in
BitFcTimelineDayView.razor where the hour slot (outer div with role="button")
contains a half-hour slot (inner div with role="button"). Instead, render both
the 0-minute and 30-minute time slot targets as sibling native button elements
(button type="button") outside of each other, ensuring each button independently
calls the same event handlers OnDragEnter, OnDrop, OnSlotClickAsync, and
OnSlotKeyDownAsync with their respective minute values (0 or 30). Apply this
same restructuring to the other instance mentioned at lines 106-128.
| var resources = State.Resources.Where(r => !string.IsNullOrEmpty(r.Id)).ToList(); | ||
| var hasResources = resources.Count > 0; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Handle whitespace-only resource IDs as unassigned.
Line 18 uses !string.IsNullOrEmpty(r.Id), so IDs like " " still render as normal resources even though this path treats empty IDs as unassigned.
Suggested fix
- var resources = State.Resources.Where(r => !string.IsNullOrEmpty(r.Id)).ToList();
+ var resources = State.Resources.Where(r => !string.IsNullOrWhiteSpace(r.Id)).ToList();📝 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.
| var resources = State.Resources.Where(r => !string.IsNullOrEmpty(r.Id)).ToList(); | |
| var hasResources = resources.Count > 0; | |
| var resources = State.Resources.Where(r => !string.IsNullOrWhiteSpace(r.Id)).ToList(); | |
| var hasResources = resources.Count > 0; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineLayout.razor`
around lines 18 - 19, The resource filtering logic in the
BitFcTimelineLayout.razor file uses string.IsNullOrEmpty to check if a resource
ID is assigned, but this does not handle whitespace-only strings which should
also be treated as unassigned. Replace the string.IsNullOrEmpty call on r.Id
with string.IsNullOrWhiteSpace to properly filter out resources with empty or
whitespace-only IDs in the Where clause that filters State.Resources.
| var resources = State.Resources; | ||
| var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrEmpty(id)).ToList(); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Base the empty-resource fallback on valid resource IDs.
Event grouping already ignores empty resource IDs, but hasUnassigned checks the raw resource count. If all configured resources have blank IDs, the week timeline skips the unassigned fallback row even though there are no valid resource rows for events to persist against.
🐛 Proposed fix
- var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrEmpty(id)).ToList();
+ var resourceIds = resources.Select(r => r.Id).Where(id => !string.IsNullOrWhiteSpace(id)).ToList();
@@
- var hasUnassigned = hasUnassignedEvents || resources.Count == 0;
+ var hasUnassigned = hasUnassignedEvents || resourceIds.Count == 0;Also applies to: 48-52
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/Views/TimelineMode/BitFcTimelineWeekView.razor`
around lines 20 - 21, The hasUnassigned logic in the BitFcTimelineWeekView
component (referenced at lines 48-52) is currently checking against the raw
resource count rather than the valid resource IDs. Since resourceIds is already
filtered to exclude empty IDs using the Select and Where chain, update the
hasUnassigned check to base its condition on the count of valid resourceIds
instead of the total resources count to ensure the unassigned fallback row is
properly shown when there are no valid resources with non-empty IDs.
closes #12449
Summary by CodeRabbit
BitFullCalendarcomponent with Month/Week/Day/Year/Agenda and resource-based Timeline views, including RTL styling, sticky timeline lanes, and culture-aware navigation/formatting./components/fullcalendardemo page showcasing configuration, templates, localization, and bindings.