-
-
Notifications
You must be signed in to change notification settings - Fork 267
Add BitFullCalendar extras component (#12449) #12450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
msynk
wants to merge
38
commits into
bitfoundation:develop
Choose a base branch
from
msynk:12449-blazorui-fullcalendar-extras
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 5 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
b27f335
add BitFullCalendar extras component #12449
msynk df593ab
make theme compatible
msynk fdc0e72
rename css classes and move code blocks to code-behind
msynk 64e2d84
Merge branch 'develop' into 12449-blazorui-fullcalendar-extras
msynk 6b55009
fix a lot of issues
msynk 0124500
resolve review comments
msynk b48fff7
resolve review comments II
msynk fd3e6fb
resolve review comments III
msynk 4a9d1de
resolve review comments IV
msynk 897f9cc
resolve review comments V
msynk 44ef70c
resolve review comments VI
msynk 4339767
fix demo
msynk 6551fb9
resolve review comments VII
msynk cc3d16b
resolve review comments VIII
msynk 692dd36
resolve review comments IX
msynk 18435b9
resolve review comments X
msynk f181910
resolve review comments XI
msynk b01f279
resolve review comments XII
msynk d790e39
resolve review comments XIII
msynk 1c23485
resolve review comments XIV
msynk f498381
resolve review comments XV
msynk 318c8d5
add new features
msynk de8a32a
resolve review comments XVI
msynk b7746a6
resolve review comments XVII
msynk 7087703
resolve review comments XVIII
msynk 6a7360b
resolve review comments XIX
msynk e8e16eb
resolve review comments XX
msynk 41c0b78
resolve review comments XXI
msynk 955181c
Merge branch 'develop' into 12449-blazorui-fullcalendar-extras
msynk 2d5bbd1
resolve review comments XXII
msynk dff228a
resolve review comments XXIII
msynk 45b8421
resolve review comments XXIV
msynk 345c4a7
resolve review commnets XXV
msynk eda294c
resolve review comments XXVI
msynk dc60be6
resolve review comments XXVII
msynk cd3294a
resolve review comments XXVIII
msynk be8a448
resolve review comments XXIX
msynk 1db96b8
resolve review comments XXX
msynk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
44 changes: 44 additions & 0 deletions
44
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| @namespace Bit.BlazorUI | ||
| @implements IDisposable | ||
|
|
||
| <div class="bit-bfc-body" @key="(State.Mode, State.View)"> | ||
| @if (State.Mode == BitFullCalendarMode.Timeline) | ||
| { | ||
| switch (State.View) | ||
| { | ||
| case BitFullCalendarView.Day: | ||
| <BitFcTimelineDayView Events="State.Events.ToList()" EventTemplate="TimelineEventTemplate" /> | ||
| break; | ||
| case BitFullCalendarView.Week: | ||
| <BitFcTimelineWeekView Events="State.Events.ToList()" EventTemplate="TimelineEventTemplate" /> | ||
| break; | ||
| case BitFullCalendarView.Month: | ||
| <BitFcTimelineMonthView Events="State.Events.ToList()" EventTemplate="TimelineEventTemplate" /> | ||
| break; | ||
| default: | ||
| <BitFcTimelineWeekView Events="State.Events.ToList()" EventTemplate="TimelineEventTemplate" /> | ||
| break; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| switch (State.View) | ||
| { | ||
| case BitFullCalendarView.Month: | ||
| <BitFcCalendarMonthView SingleDayEvents="_singleDayEvents" MultiDayEvents="_multiDayEvents" EventTemplate="MonthEventTemplate" /> | ||
| break; | ||
| case BitFullCalendarView.Week: | ||
| <BitFcCalendarWeekView SingleDayEvents="_singleDayEvents" MultiDayEvents="_multiDayEvents" EventTemplate="WeekEventTemplate" /> | ||
| break; | ||
| case BitFullCalendarView.Day: | ||
| <BitFcCalendarDayView SingleDayEvents="_singleDayEvents" MultiDayEvents="_multiDayEvents" EventTemplate="DayEventTemplate" /> | ||
| break; | ||
| case BitFullCalendarView.Year: | ||
| <BitFcCalendarYearView SingleDayEvents="_singleDayEvents" MultiDayEvents="_multiDayEvents" /> | ||
| break; | ||
| case BitFullCalendarView.Agenda: | ||
| <BitFcAgendaEvents /> | ||
| break; | ||
| } | ||
| } | ||
| </div> |
34 changes: 34 additions & 0 deletions
34
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarBody.razor.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| namespace Bit.BlazorUI; | ||
|
|
||
| public partial class BitFcCalendarBody | ||
| { | ||
| [CascadingParameter] public BitFullCalendarState State { get; set; } = default!; | ||
|
|
||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? MonthEventTemplate { get; set; } | ||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? WeekEventTemplate { get; set; } | ||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? DayEventTemplate { get; set; } | ||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? TimelineEventTemplate { get; set; } | ||
|
|
||
| private List<BitFullCalendarEvent> _singleDayEvents = []; | ||
| private List<BitFullCalendarEvent> _multiDayEvents = []; | ||
|
|
||
| protected override void OnInitialized() | ||
| { | ||
| State.OnStateChanged += Refresh; | ||
| ComputeEvents(); | ||
| } | ||
|
|
||
| private void Refresh() | ||
| { | ||
| ComputeEvents(); | ||
| InvokeAsync(StateHasChanged); | ||
| } | ||
|
|
||
| private void ComputeEvents() | ||
| { | ||
| _singleDayEvents = State.Events.Where(e => e.IsSingleDay).ToList(); | ||
| _multiDayEvents = State.Events.Where(e => e.IsMultiDay).ToList(); | ||
| } | ||
|
|
||
| public void Dispose() => State.OnStateChanged -= Refresh; | ||
| } | ||
10 changes: 10 additions & 0 deletions
10
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| @namespace Bit.BlazorUI | ||
|
|
||
| <div class="bit-bfc-toast-container"> | ||
| @foreach (var toast in _toasts) | ||
| { | ||
| <div class="bit-bfc-toast @(toast.IsError ? "error" : "success")"> | ||
| @toast.Message | ||
| </div> | ||
|
msynk marked this conversation as resolved.
|
||
| } | ||
| </div> | ||
29 changes: 29 additions & 0 deletions
29
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFcCalendarToast.razor.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| namespace Bit.BlazorUI; | ||
|
|
||
| public partial class BitFcCalendarToast | ||
| { | ||
| private readonly List<ToastItem> _toasts = []; | ||
| private int _nextId; | ||
|
msynk marked this conversation as resolved.
|
||
|
|
||
| public void Show(string message, bool isError = false) | ||
| { | ||
| var item = new ToastItem { Id = _nextId++, Message = message, IsError = isError }; | ||
| _toasts.Add(item); | ||
| StateHasChanged(); | ||
| _ = RemoveAfterDelay(item.Id); | ||
| } | ||
|
|
||
| private async Task RemoveAfterDelay(int id) | ||
| { | ||
| await Task.Delay(3000); | ||
| _toasts.RemoveAll(t => t.Id == id); | ||
| await InvokeAsync(StateHasChanged); | ||
| } | ||
|
msynk marked this conversation as resolved.
|
||
|
|
||
| private class ToastItem | ||
| { | ||
| public int Id { get; set; } | ||
| public string Message { get; set; } = ""; | ||
| public bool IsError { get; set; } | ||
| } | ||
| } | ||
12 changes: 12 additions & 0 deletions
12
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| @namespace Bit.BlazorUI | ||
|
|
||
| <BitCascadingValueProvider ValueList="BuildCascadingValues()"> | ||
| <div class="bit-bfc" dir="@(State.IsRtl ? "rtl" : "ltr")"> | ||
| <BitFcCalendarHeader /> | ||
| <BitFcCalendarBody MonthEventTemplate="MonthEventTemplate" | ||
| WeekEventTemplate="WeekEventTemplate" | ||
| DayEventTemplate="DayEventTemplate" | ||
| TimelineEventTemplate="TimelineEventTemplate" /> | ||
| <BitFcCalendarToast /> | ||
| </div> | ||
| </BitCascadingValueProvider> |
214 changes: 214 additions & 0 deletions
214
src/BlazorUI/Bit.BlazorUI.Extras/Components/FullCalendar/BitFullCalendar.razor.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,214 @@ | ||
| using System.Globalization; | ||
|
|
||
| namespace Bit.BlazorUI; | ||
|
|
||
| public partial class BitFullCalendar : IDisposable | ||
| { | ||
| /// <summary> | ||
| /// Events displayed in the calendar. Assign a list from parent state; updates are synced on each | ||
| /// render when the reference or contents change. User-driven add, edit, and delete actions are | ||
| /// reported through <see cref="OnChange"/> - update this list (or your backing store) in the handler | ||
| /// to keep the UI in sync. | ||
| /// </summary> | ||
| [Parameter] public List<BitFullCalendarEvent>? Events { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Culture for the calendar. Accepts any CultureInfo, e.g. new CultureInfo("fa-IR"). | ||
| /// NOTE: do NOT use this parameter when the component is rendered with | ||
| /// @rendermode="InteractiveServer" - CultureInfo is not JSON-serializable. | ||
| /// Use <see cref="CultureName"/> instead for server-interactive scenarios. | ||
| /// </summary> | ||
| [Parameter] public CultureInfo? Culture { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Culture name string (e.g. "fa-IR", "ar-SA", "fr-FR"). | ||
| /// Preferred over <see cref="Culture"/> when using @rendermode="InteractiveServer" | ||
| /// because plain strings are safely serialized by Blazor's parameter persistence. | ||
| /// When both are supplied, CultureName takes precedence. | ||
| /// Blazor WebAssembly hosts must set <c>BlazorWebAssemblyLoadAllGlobalizationData</c> to | ||
| /// <c>true</c> (or load a custom ICU shard) for cultures outside the default EFIGS/CJK shards. | ||
| /// </summary> | ||
| [Parameter] public string? CultureName { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Localized strings for calendar UI labels, buttons, dialogs, filters, and accessibility text. | ||
| /// Defaults to English; override individual properties on a <see cref="BitFullCalendarTexts"/> | ||
| /// instance to localize the component without replacing built-in dialogs. | ||
| /// </summary> | ||
| [Parameter] public BitFullCalendarTexts Texts { get; set; } = new(); | ||
|
|
||
| /// <summary> | ||
| /// Ordered list of event colors shown in pickers, filters, agenda headers, badges, and bullets. | ||
| /// Each entry has its own <see cref="BitFullCalendarColorOption.Id"/> (matched against | ||
| /// <see cref="BitFullCalendarEvent.Color"/>), <see cref="BitFullCalendarColorOption.Title"/> | ||
| /// (the display name shown verbatim - for example <c>"SkyBlue"</c>), and | ||
| /// <see cref="BitFullCalendarColorOption.Value"/> (any CSS color value used for swatches and badges). | ||
| /// When <c>null</c> or empty, <see cref="BitFullCalendarColorOption.Defaults"/> is used. | ||
| /// </summary> | ||
| [Parameter] public IReadOnlyList<BitFullCalendarColorOption>? EventColorOptions { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Resources displayed as rows in the resource timeline view. When <c>null</c> or empty, | ||
| /// the resource timeline tab is hidden from the header. Each event's | ||
| /// <see cref="BitFullCalendarEvent.Resource"/> is matched against the resource <c>Id</c>. | ||
| /// </summary> | ||
| [Parameter] public IReadOnlyList<BitFullCalendarResource>? Resources { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Raised when a user adds, edits, or deletes an event in the calendar UI. | ||
| /// </summary> | ||
| [Parameter] public EventCallback<BitFullCalendarChangeEventArgs> OnChange { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// When assigned, the built-in add dialog is suppressed. The callback receives a draft | ||
| /// <see cref="BitFullCalendarEvent"/> with <see cref="BitFullCalendarEvent.StartDate"/> and | ||
| /// <see cref="BitFullCalendarEvent.EndDate"/> set from the interaction (for example the clicked day/week slot); | ||
| /// <see cref="BitFullCalendarEvent.Id"/> is empty and other fields are left at defaults. | ||
| /// Consumers should show their own UI and | ||
| /// raise <see cref="OnChange"/> (or mutate <see cref="Events"/> bound to parent state) after persisting changes. | ||
| /// </summary> | ||
| [Parameter] public EventCallback<BitFullCalendarEvent?> OnAddClick { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// When assigned, the built-in event details dialog is suppressed when an event is clicked. | ||
| /// The callback receives the clicked <see cref="BitFullCalendarEvent"/>. Consumers should | ||
| /// show their own event details UI. This applies to all views (day, week, month, agenda) and | ||
| /// to multi-day event rows and event list dialogs. | ||
| /// </summary> | ||
| [Parameter] public EventCallback<BitFullCalendarEvent> OnEventClick { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Raised when the visible date range changes - for example when the user navigates | ||
| /// with prev/next/today buttons or switches views. The callback receives the inclusive | ||
| /// start and end dates of the new range together with the active view. | ||
| /// </summary> | ||
| [Parameter] public EventCallback<BitFullCalendarDateChangeEventArgs> OnDateChange { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Optional template for customizing event rendering in the day view. | ||
| /// When provided, replaces the default event card content inside the time-grid blocks. | ||
| /// </summary> | ||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? DayEventTemplate { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Optional template for customizing event rendering in the week view. | ||
| /// When provided, replaces the default event card content inside the time-grid blocks. | ||
| /// </summary> | ||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? WeekEventTemplate { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Optional template for customizing event rendering in the month view. | ||
| /// When provided, replaces the default event badge content inside month grid cells. | ||
| /// </summary> | ||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? MonthEventTemplate { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Optional template for customizing event rendering in the resource timeline view. | ||
| /// When provided, replaces the default event card content inside the timeline blocks. | ||
| /// </summary> | ||
| [Parameter] public RenderFragment<BitFullCalendarEvent>? TimelineEventTemplate { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// When <c>true</c>, the built-in color and attendee filter dropdowns are hidden from the calendar header. | ||
| /// Consumers can provide their own external filter UI and pass pre-filtered events to the calendar. | ||
| /// </summary> | ||
| [Parameter] public bool HideFilters { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// When <c>true</c>, the built-in settings gear button is hidden from the calendar header. | ||
| /// Consumers can still drive settings programmatically through the <see cref="Options"/> object. | ||
| /// </summary> | ||
| [Parameter] public bool HideSettings { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Configuration options controlling initial calendar preferences | ||
| /// such as dark mode, time format, badge variant, day start hour, and agenda grouping. | ||
| /// Values are applied when the component initializes or when a new instance is assigned. | ||
| /// </summary> | ||
| [Parameter] public BitFullCalendarOptions Options { get; set; } = new(); | ||
|
|
||
| /// <summary> | ||
| /// Initial layout mode. <see cref="BitFullCalendarMode.Event"/> shows the standard | ||
| /// day/week/month/year/agenda views. <see cref="BitFullCalendarMode.Timeline"/> switches to | ||
| /// the resource × time layout (day, week, month) and requires <see cref="Resources"/> to contain | ||
| /// at least one entry; otherwise the Timeline tab and mode have no effect. | ||
| /// </summary> | ||
| [Parameter] public BitFullCalendarMode? InitialMode { get; set; } | ||
|
|
||
| public BitFullCalendarState State { get; set; } = new(); | ||
| private BitFullCalendarChangeNotifier _changeNotifier = default!; | ||
| private BitFullCalendarColorScheme _colorScheme = new(null); | ||
| private BitFullCalendarOptions? _appliedOptions; | ||
|
|
||
| private BitCascadingValueList BuildCascadingValues() => new() | ||
| { | ||
| { State }, | ||
| { Texts }, | ||
| { _changeNotifier }, | ||
| { _colorScheme }, | ||
| { Options }, | ||
| { HideFilters, "HideFilters" }, | ||
| { HideSettings, "HideSettings" }, | ||
| { OnAddClick, "OnAddClick" }, | ||
| { OnEventClick, "OnEventClick" }, | ||
| }; | ||
|
|
||
| private CultureInfo ResolveCulture() => | ||
| CultureName is { Length: > 0 } name | ||
| ? new CultureInfo(name) | ||
| : Culture ?? CultureInfo.CurrentUICulture; | ||
|
|
||
| protected override void OnInitialized() | ||
| { | ||
| State.Initialize(Events ?? [], ResolveCulture()); | ||
| ApplyOptions(); | ||
| if (InitialMode.HasValue) | ||
| State.SetMode(InitialMode.Value); | ||
| _changeNotifier = new BitFullCalendarChangeNotifier(State, args => OnChange.InvokeAsync(args)); | ||
|
msynk marked this conversation as resolved.
Outdated
|
||
| State.OnStateChanged += HandleStateChanged; | ||
| State.OnDateRangeChanged += HandleDateRangeChanged; | ||
| } | ||
|
|
||
| protected override void OnParametersSet() | ||
| { | ||
| _colorScheme = new BitFullCalendarColorScheme(EventColorOptions); | ||
| var resolved = ResolveCulture(); | ||
| if (!string.Equals(resolved.Name, State.Culture.Name, StringComparison.Ordinal)) | ||
| State.SetCulture(resolved); | ||
|
msynk marked this conversation as resolved.
Outdated
|
||
|
|
||
| if (Events is not null) | ||
| State.SyncEvents(Events); | ||
|
msynk marked this conversation as resolved.
Outdated
|
||
|
|
||
| State.SyncResources(Resources); | ||
|
|
||
| ApplyOptions(); | ||
| } | ||
|
msynk marked this conversation as resolved.
|
||
|
|
||
| private void ApplyOptions() | ||
| { | ||
| if (ReferenceEquals(Options, _appliedOptions)) | ||
| return; | ||
|
|
||
| _appliedOptions = Options; | ||
| State.SetUse24HourFormat(Options.Use24HourFormat); | ||
| State.SetBadgeVariant(Options.BadgeVariant); | ||
| State.SetStartOfDayHour(Options.StartOfDayHour); | ||
| State.SetAgendaModeGroupBy(Options.AgendaModeGroupBy); | ||
| State.SetEventLayout(Options.EventLayout); | ||
| } | ||
|
|
||
| private void HandleStateChanged() => InvokeAsync(StateHasChanged); | ||
|
|
||
| private void HandleDateRangeChanged(BitFullCalendarDateChangeEventArgs args) | ||
| { | ||
| InvokeAsync(() => OnDateChange.InvokeAsync(args)); | ||
| } | ||
|
|
||
|
|
||
|
|
||
| public void Dispose() | ||
| { | ||
| State.OnStateChanged -= HandleStateChanged; | ||
| State.OnDateRangeChanged -= HandleDateRangeChanged; | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.