From 6127059e44fcdb7e034d428653701ae131037f15 Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Wed, 25 Oct 2023 16:19:40 +0200 Subject: [PATCH 01/11] Made day headers fixed in month view --- Heron.MudCalendar/Styles/_monthView.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Heron.MudCalendar/Styles/_monthView.scss b/Heron.MudCalendar/Styles/_monthView.scss index ead3a52..62b88fc 100644 --- a/Heron.MudCalendar/Styles/_monthView.scss +++ b/Heron.MudCalendar/Styles/_monthView.scss @@ -28,7 +28,7 @@ } .mud-cal-month-cell-events { - flex-grow: 1; + overflow-y: scroll; } .mud-cal-month-link { From b203f2e4d027f335c77ee5ff38e26152737ab892 Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Wed, 25 Oct 2023 16:54:42 +0200 Subject: [PATCH 02/11] Added additional time intervals --- .../Calendar/Examples/TimeIntervalCalendarExample.razor | 4 ++++ Heron.MudCalendar/Base/DayWeekViewBase.razor | 5 +++-- Heron.MudCalendar/Enums/CalendarTimeInterval.cs | 6 +++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Heron.MudCalendar.Docs/Pages/Calendar/Examples/TimeIntervalCalendarExample.razor b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/TimeIntervalCalendarExample.razor index 229db9b..1802363 100644 --- a/Heron.MudCalendar.Docs/Pages/Calendar/Examples/TimeIntervalCalendarExample.razor +++ b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/TimeIntervalCalendarExample.razor @@ -5,9 +5,13 @@ + 10 Minutes 15 Minutes + 20 Minutes 30 Minutes 1 Hour + 2 Hours + 3 Hours diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor b/Heron.MudCalendar/Base/DayWeekViewBase.razor index 6ba5878..6857fc6 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor @@ -1,6 +1,7 @@ @namespace Heron.MudCalendar @inherits CalendarViewBase @using Microsoft.JSInterop +@using CategoryTypes = Heron.MudCalendar.Attributes.CategoryTypes @inject IJSRuntime JsRuntime @Render @@ -74,10 +75,10 @@ @for (var i = 0; i < CellsInDay; i++) { - @if (i % (60 / (int)Calendar.DayTimeInterval) == 0) + @if ((int)Calendar.DayTimeInterval >= 60 || i % (60 / (int)Calendar.DayTimeInterval) == 0) { - @(i / (60 / (int)Calendar.DayTimeInterval)):00 + @(i / (60 / (double)Calendar.DayTimeInterval)):00 } diff --git a/Heron.MudCalendar/Enums/CalendarTimeInterval.cs b/Heron.MudCalendar/Enums/CalendarTimeInterval.cs index 71a1591..362c518 100644 --- a/Heron.MudCalendar/Enums/CalendarTimeInterval.cs +++ b/Heron.MudCalendar/Enums/CalendarTimeInterval.cs @@ -2,7 +2,11 @@ namespace Heron.MudCalendar; public enum CalendarTimeInterval { + Minutes10 = 10, Minutes15 = 15, + Minutes20 = 20, Minutes30 = 30, - Minutes60 = 60 + Minutes60 = 60, + Minutes120 = 120, + Minutes180 = 180 } From 903745897cb63548c5376fb48b87938d35fde3b0 Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Wed, 25 Oct 2023 17:33:40 +0200 Subject: [PATCH 03/11] Reviewed access modifiers of styles and classes to help with extending MudCalendar --- Heron.MudCalendar/Base/DayWeekViewBase.razor.cs | 9 ++++----- Heron.MudCalendar/Components/MudCalendar.razor.cs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs index 5cd2a8f..dad520a 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs @@ -1,6 +1,5 @@ using Heron.MudCalendar.Services; using Microsoft.AspNetCore.Components; -using MudBlazor; using MudBlazor.Extensions; using MudBlazor.Utilities; @@ -39,7 +38,7 @@ protected virtual string DayStyle(CalendarCell calendarCell) .Build(); } - private string EventStyle(ItemPosition position) + protected virtual string EventStyle(ItemPosition position) { return new StyleBuilder() .AddStyle("position", "absolute") @@ -51,14 +50,14 @@ private string EventStyle(ItemPosition position) .Build(); } - private string CellHeightStyle() + protected virtual string CellHeightStyle() { return new StyleBuilder() .AddStyle("height", $"{Calendar.DayCellHeight}px") .Build(); } - private string TimelineStyle() + protected virtual string TimelineStyle() { return new StyleBuilder() .AddStyle("position", "absolute") @@ -172,7 +171,7 @@ private static IEnumerable CalcPositions(IEnumerable return positions; } - private class ItemPosition + protected class ItemPosition { public CalendarItem Item { get; set; } = new(); public int Position { get; set; } diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index bd7f81a..2bc7fbc 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -216,7 +216,7 @@ private DateTime? PickerDate .AddStyle(Style) .Build(); - private string ViewClassname => + protected virtual string ViewClassname => new CssBuilder("flex-grow-1") .AddClass("d-none", AllowedViews().Count == 0) .Build(); From f3784815fe283e43b6cca37e56710592cb63975b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aitor=20Garc=C3=ADa?= Date: Thu, 2 Nov 2023 16:16:27 +0100 Subject: [PATCH 04/11] added EventCallback for CalendarItem clicked --- Heron.MudCalendar/Base/DayWeekViewBase.razor | 18 +++++++-- .../Base/DayWeekViewBase.razor.cs | 39 +++++++++++++------ .../Components/MudCalendar.razor.cs | 6 +++ 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor b/Heron.MudCalendar/Base/DayWeekViewBase.razor index 6857fc6..275d1b0 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor @@ -111,7 +111,7 @@
@if (cell.Today && Calendar.ShowCurrentTime) { -
+
}
@@ -170,9 +170,19 @@ var positions = CalcPositions(cell.Items, DateOnly.FromDateTime(cell.Date)); foreach (var position in positions) { -
- @CellTemplate?.Invoke(position.Item) -
+ @if (Calendar.CalendarItemClicked.HasDelegate) + { +
+ @CellTemplate?.Invoke(position.Item) +
+ } + else + { +
+ @CellTemplate?.Invoke(position.Item) +
+ } } }; + } \ No newline at end of file diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs index dad520a..6f439f1 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs @@ -9,7 +9,7 @@ public abstract partial class DayWeekViewBase : CalendarViewBase, IAsyncDisposab { private ElementReference _scrollDiv; private JsService? _jsService; - + private const int MinutesInDay = 24 * 60; private int PixelsInCell => Calendar.DayCellHeight; @@ -34,7 +34,8 @@ protected override async Task OnAfterRenderAsync(bool firstRender) protected virtual string DayStyle(CalendarCell calendarCell) { return new StyleBuilder() - .AddStyle("border", $"1px solid var(--mud-palette-{Calendar.Color.ToDescriptionString()})", calendarCell.Today && Calendar.HighlightToday) + .AddStyle("border", $"1px solid var(--mud-palette-{Calendar.Color.ToDescriptionString()})", + calendarCell.Today && Calendar.HighlightToday) .Build(); } @@ -45,8 +46,10 @@ protected virtual string EventStyle(ItemPosition position) .AddStyle("top", $"{CalcTop(position)}px") .AddStyle("height", $"{CalcHeight(position)}px") .AddStyle("overflow", "hidden") - .AddStyle("left", (((position.Position / (double)position.Total) - (1.0 / position.Total)) * 100).ToInvariantString() + "%") - .AddStyle("width", (100 / position.Total) + "%" ) + .AddStyle("left", + (((position.Position / (double)position.Total) - (1.0 / position.Total)) * 100).ToInvariantString() + + "%") + .AddStyle("width", (100 / position.Total) + "%") .Build(); } @@ -63,7 +66,8 @@ protected virtual string TimelineStyle() .AddStyle("position", "absolute") .AddStyle("width", "100%") .AddStyle("border", "1px solid var(--mud-palette-grey-default)") - .AddStyle("top", $"{(int)((DateTime.Now.Subtract(DateTime.Today).TotalMinutes / MinutesInDay) * PixelsInDay)}px") + .AddStyle("top", + $"{(int)((DateTime.Now.Subtract(DateTime.Today).TotalMinutes / MinutesInDay) * PixelsInDay)}px") .Build(); } @@ -79,6 +83,16 @@ protected virtual Task OnCellLinkClicked(CalendarCell cell, int row) return Calendar.CellClicked.InvokeAsync(date); } + /// + /// Method invoked when the user clicks on the calendar item. + /// + /// The calendar item that was clicked. + /// + protected virtual Task OnCalendarItemClicked(CalendarItem item) + { + return Calendar.CalendarItemClicked.InvokeAsync(item); + } + private int CalcTop(ItemPosition position) { double minutes = 0; @@ -86,6 +100,7 @@ private int CalcTop(ItemPosition position) { minutes = position.Item.Start.Hour * 60 + position.Item.Start.Minute; } + var percent = minutes / MinutesInDay; var top = PixelsInDay * percent; @@ -150,8 +165,9 @@ private static IEnumerable CalcPositions(IEnumerable position.Position = i; } } + if (position.Position == 0) position.Position = overlaps.Count + 1; - + overlaps.Add(position); var maxPosition = overlaps.Max(o => o.Position); foreach (var overlap in overlaps) @@ -159,12 +175,13 @@ private static IEnumerable CalcPositions(IEnumerable overlap.Total = maxPosition; } } - + // Calculate the total overlapping events foreach (var position in positions) { - var max = positions.Where(p => p.Item.Start < (position.Item.End ?? position.Item.Start.AddHours(1)) - && (p.Item.End ?? p.Item.Start.AddHours(1)) > position.Item.Start).Max(p => p.Total); + var max = positions.Where(p => p.Item.Start < (position.Item.End ?? position.Item.Start.AddHours(1)) + && (p.Item.End ?? p.Item.Start.AddHours(1)) > position.Item.Start) + .Max(p => p.Total); position.Total = max; } @@ -178,11 +195,11 @@ protected class ItemPosition public int Total { get; set; } public DateOnly Date { get; set; } } - + public async ValueTask DisposeAsync() { GC.SuppressFinalize(this); - + if (_jsService != null) { await _jsService.DisposeAsync(); diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index 2bc7fbc..f87a668 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -186,6 +186,12 @@ public partial class MudCalendar : MudComponentBase /// [Parameter] public EventCallback CellClicked { get; set; } + + /// + /// Called when a CalendarItem is clicked. + /// + [Parameter] + public EventCallback CalendarItemClicked { get; set; } private DateTime? PickerDate { From 444f7537c0b29397c3cbd20238f279225cd1ea38 Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Sat, 4 Nov 2023 07:00:54 +0100 Subject: [PATCH 05/11] Added click event on Month View. Docs + Tests. --- .../Pages/Calendar/CalendarPage.razor | 1 + .../Examples/EventsCalendarExample.razor | 24 ++++++++++++++++-- .../Calendar/CalendarItemClickTest.razor | 25 +++++++++++++++++++ .../Components/CalendarTests.cs | 22 ++++++++++++++++ Heron.MudCalendar/Base/DayWeekViewBase.razor | 4 +-- .../Base/DayWeekViewBase.razor.cs | 4 +-- Heron.MudCalendar/Components/MonthView.razor | 13 +++++++++- .../Components/MonthView.razor.cs | 10 ++++++++ .../Components/MudCalendar.razor.cs | 2 +- Heron.MudCalendar/Styles/_cellTemplate.scss | 8 ++++++ 10 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarItemClickTest.razor diff --git a/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor b/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor index 34e32a8..cef7d3c 100644 --- a/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor +++ b/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor @@ -76,6 +76,7 @@ The CellClicked event will be raised when a calendar cell is clicked. This can be used, for example, to add new events to the calendar. + The ItemClicked event will be raised when an item in the calendar is clicked. diff --git a/Heron.MudCalendar.Docs/Pages/Calendar/Examples/EventsCalendarExample.razor b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/EventsCalendarExample.razor index 0b3117b..74e0137 100644 --- a/Heron.MudCalendar.Docs/Pages/Calendar/Examples/EventsCalendarExample.razor +++ b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/EventsCalendarExample.razor @@ -1,6 +1,6 @@ @namespace Heron.MudCalendar.Docs.Examples - + @code { @@ -9,7 +9,27 @@ private Task CellClicked(DateTime dateTime) { - return DialogService.ShowMessageBox("Click", dateTime.ToString(Thread.CurrentThread.CurrentCulture)); + return DialogService.ShowMessageBox("Cell Clicked", dateTime.ToString(Thread.CurrentThread.CurrentCulture)); } + private Task ItemClicked(CalendarItem item) + { + return DialogService.ShowMessageBox("Item Clicked", item.Text); + } + + private List _events = new() + { + new CalendarItem + { + Start = DateTime.Today.AddHours(10), + End = DateTime.Today.AddHours(11), + Text = "Event today" + }, + new CalendarItem + { + Start = DateTime.Today.AddDays(1).AddHours(11), + End = DateTime.Today.AddDays(1).AddHours(12.5), + Text = "Event tomorrow" + } + }; } \ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarItemClickTest.razor b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarItemClickTest.razor new file mode 100644 index 0000000..b08c333 --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarItemClickTest.razor @@ -0,0 +1,25 @@ + + + +@code { + public static string __description__ = "Calendar Item Click Test"; + + private string _value = string.Empty; + + private MudCalendar _mudCalendar; + + private void TestClick(CalendarItem item) + { + _value = string.Concat(item.Text, "_", _mudCalendar.View.ToString()); + } + + private List _events = new() + { + new CalendarItem + { + Start = DateTime.Today.AddHours(10), + End = DateTime.Today.AddHours(11), + Text = "Event" + } + }; +} \ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs index 0e6303a..7afaef2 100644 --- a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs +++ b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs @@ -136,6 +136,28 @@ public void CellClick() comp.Find("div.mud-cal-week-layer a").Click(); textField.Instance.Text.Should().Be("8"); } + + [Test] + public void ItemsClick() + { + var cut = Context.RenderComponent(); + var comp = cut.FindComponent(); + var textField = cut.FindComponent>(); + + // Month View + comp.Find("div.mud-cal-cell-template").Click(); + textField.Instance.Text.Should().Be("Event_Month"); + + // Week View + comp.SetParam(x => x.View, CalendarView.Week); + comp.Find("div.mud-cal-cell-template").Click(); + textField.Instance.Text.Should().Be("Event_Week"); + + // Day View + comp.SetParam(x => x.View, CalendarView.Day); + comp.Find("div.mud-cal-cell-template").Click(); + textField.Instance.Text.Should().Be("Event_Day"); + } [Test] public void EnsureAllDays() diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor b/Heron.MudCalendar/Base/DayWeekViewBase.razor index 275d1b0..870198e 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor @@ -170,9 +170,9 @@ var positions = CalcPositions(cell.Items, DateOnly.FromDateTime(cell.Date)); foreach (var position in positions) { - @if (Calendar.CalendarItemClicked.HasDelegate) + @if (Calendar.ItemClicked.HasDelegate) { -
+
@CellTemplate?.Invoke(position.Item)
} diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs index 6f439f1..92a497e 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs @@ -88,9 +88,9 @@ protected virtual Task OnCellLinkClicked(CalendarCell cell, int row) /// /// The calendar item that was clicked. /// - protected virtual Task OnCalendarItemClicked(CalendarItem item) + protected virtual Task OnItemClicked(CalendarItem item) { - return Calendar.CalendarItemClicked.InvokeAsync(item); + return Calendar.ItemClicked.InvokeAsync(item); } private int CalcTop(ItemPosition position) diff --git a/Heron.MudCalendar/Components/MonthView.razor b/Heron.MudCalendar/Components/MonthView.razor index c82c23a..ad881a0 100644 --- a/Heron.MudCalendar/Components/MonthView.razor +++ b/Heron.MudCalendar/Components/MonthView.razor @@ -91,7 +91,18 @@ @
@foreach (var item in cell.Items) { - @CellTemplate?.Invoke(item) + @if (Calendar.ItemClicked.HasDelegate) + { +
+ @CellTemplate?.Invoke(item) +
+ } + else + { +
+ @CellTemplate?.Invoke(item) +
+ } }
; diff --git a/Heron.MudCalendar/Components/MonthView.razor.cs b/Heron.MudCalendar/Components/MonthView.razor.cs index 5f4433e..93286a1 100644 --- a/Heron.MudCalendar/Components/MonthView.razor.cs +++ b/Heron.MudCalendar/Components/MonthView.razor.cs @@ -61,6 +61,16 @@ protected virtual Task OnCellLinkClicked(CalendarCell cell) return Calendar.CellClicked.InvokeAsync(cell.Date); } + /// + /// Method invoked when the user clicks on the calendar item. + /// + /// The calendar item that was clicked. + /// + protected virtual Task OnItemClicked(CalendarItem item) + { + return Calendar.ItemClicked.InvokeAsync(item); + } + protected override List BuildCells() { var cells = new List(); diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index f87a668..74160d1 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -191,7 +191,7 @@ public partial class MudCalendar : MudComponentBase /// Called when a CalendarItem is clicked. /// [Parameter] - public EventCallback CalendarItemClicked { get; set; } + public EventCallback ItemClicked { get; set; } private DateTime? PickerDate { diff --git a/Heron.MudCalendar/Styles/_cellTemplate.scss b/Heron.MudCalendar/Styles/_cellTemplate.scss index df08708..1cbf7fe 100644 --- a/Heron.MudCalendar/Styles/_cellTemplate.scss +++ b/Heron.MudCalendar/Styles/_cellTemplate.scss @@ -16,3 +16,11 @@ width: 100%; margin: 0; } + +.mud-cal-clickable { + cursor: pointer; + + .mud-chip { + cursor: inherit; + } +} \ No newline at end of file From 55c6c4a6f0bfbcf25f1f4a5f216695e99c80f16e Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Sat, 4 Nov 2023 08:42:30 +0100 Subject: [PATCH 06/11] Set head content with javascript --- .../Shared/MainLayout.razor | 10 ++++++++++ Heron.MudCalendar/Components/MudCalendar.razor | 18 ++---------------- .../Components/MudCalendar.razor.cs | 16 ++++++++++++++++ Heron.MudCalendar/Services/JsService.cs | 13 +++++++++++++ Heron.MudCalendar/wwwroot/Heron.MudCalendar.js | 11 +++++++++++ 5 files changed, 52 insertions(+), 16 deletions(-) diff --git a/Heron.MudCalendar.UnitTests.Viewer/Shared/MainLayout.razor b/Heron.MudCalendar.UnitTests.Viewer/Shared/MainLayout.razor index cbb9613..1f291ab 100644 --- a/Heron.MudCalendar.UnitTests.Viewer/Shared/MainLayout.razor +++ b/Heron.MudCalendar.UnitTests.Viewer/Shared/MainLayout.razor @@ -1,7 +1,17 @@ @inherits LayoutComponentBase + + + + @Body + +@code { + + private string _description = "Description set by code"; + +} \ No newline at end of file diff --git a/Heron.MudCalendar/Components/MudCalendar.razor b/Heron.MudCalendar/Components/MudCalendar.razor index 72245ee..f7e908b 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor +++ b/Heron.MudCalendar/Components/MudCalendar.razor @@ -1,32 +1,18 @@ @namespace Heron.MudCalendar @inherits MudComponentBase @using CategoryTypes = Heron.MudCalendar.Attributes.CategoryTypes +@using Microsoft.JSInterop +@inject IJSRuntime JsRuntime @Render @code { - /// - /// Renders the html page head element. - /// - protected virtual RenderFragment RenderHead => - @ - @RenderHeaderContent - ; - - /// - /// Renders the contents of the head element. - /// - protected virtual RenderFragment RenderHeaderContent => - @; - /// /// Renders the component. /// protected virtual RenderFragment Render => __builder => { - RenderHead(__builder); -
diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index 74160d1..85db28c 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -1,3 +1,4 @@ +using Heron.MudCalendar.Services; using Microsoft.AspNetCore.Components; using MudBlazor.Utilities; using MudBlazor; @@ -8,6 +9,8 @@ namespace Heron.MudCalendar; public partial class MudCalendar : MudComponentBase { + private JsService? _jsService; + /// /// The higher the number, the heavier the drop-shadow. 0 for no shadow. /// @@ -255,6 +258,8 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { //await DateRangeChanged.InvokeAsync(new CalendarDateRange(CurrentDay, View)); await ChangeDateRange(); + + await SetLinks(); } } @@ -305,6 +310,17 @@ protected virtual Task OnPreviousClicked() return ChangeDateRange(); } + private async Task SetLinks() + { + // Check if link is already set + _jsService ??= new JsService(JsRuntime); + var head = await _jsService.GetHeadContent(); + if (!string.IsNullOrEmpty(head) && head.Contains("Heron.MudCalendar.min.css")) return; + + // Add link + await _jsService.AddLink("_content/Heron.MudCalendar/Heron.MudCalendar.min.css", "stylesheet"); + } + private Task DatePickerDateChanged(DateTime? dateTime) { PickerDate = dateTime; diff --git a/Heron.MudCalendar/Services/JsService.cs b/Heron.MudCalendar/Services/JsService.cs index 1046efa..c7620eb 100644 --- a/Heron.MudCalendar/Services/JsService.cs +++ b/Heron.MudCalendar/Services/JsService.cs @@ -1,3 +1,4 @@ +using System.Runtime.InteropServices; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; @@ -18,6 +19,18 @@ public async Task Scroll(ElementReference element, int top) var module = await _moduleTask.Value; await module.InvokeVoidAsync("scroll", element, top); } + + public async Task GetHeadContent() + { + var module = await _moduleTask.Value; + return await module.InvokeAsync("getHeadContent"); + } + + public async Task AddLink(string href, string rel) + { + var module = await _moduleTask.Value; + await module.InvokeVoidAsync("addLink", href, rel); + } public async ValueTask DisposeAsync() { diff --git a/Heron.MudCalendar/wwwroot/Heron.MudCalendar.js b/Heron.MudCalendar/wwwroot/Heron.MudCalendar.js index 6e31c39..206b96e 100644 --- a/Heron.MudCalendar/wwwroot/Heron.MudCalendar.js +++ b/Heron.MudCalendar/wwwroot/Heron.MudCalendar.js @@ -1,3 +1,14 @@ export function scroll(element, top) { element.scrollTo(0, top); +} + +export function getHeadContent() { + return document.head.innerHTML; +} + +export function addLink(href, rel) { + const link = document.createElement("link"); + link.href = href; + link.rel = rel; + document.head.appendChild(link); } \ No newline at end of file From c158f2d8e736ada61c0816344fc05c5ac6711874 Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Sat, 4 Nov 2023 11:23:17 +0100 Subject: [PATCH 07/11] Added option for 12 hour clock --- .../Components/CalendarTests.cs | 14 ++++++++++++++ Heron.MudCalendar/Base/DayWeekViewBase.razor | 3 +-- Heron.MudCalendar/Base/DayWeekViewBase.razor.cs | 9 +++++++++ Heron.MudCalendar/Components/MudCalendar.razor.cs | 7 +++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs index 7afaef2..50dda26 100644 --- a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs +++ b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs @@ -322,4 +322,18 @@ public void DateChangedEvent() comp.FindAll("button.mud-icon-button")[1].Click(); table.Children.Length.Should().Be(2); } + + [Test] + public void ClockType() + { + var cut = Context.RenderComponent(); + var comp = cut.FindComponent(); + + // Check 24 hour clock + comp.FindAll("td.mud-cal-time-cell")[18].TextContent.Trim().Should().Be("18:00"); + + // Check 12 hour clock + comp.SetParam(x => x.Use24HourClock, false); + comp.FindAll("td.mud-cal-time-cell")[18].TextContent.Trim().Should().Be("6 pm"); + } } diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor b/Heron.MudCalendar/Base/DayWeekViewBase.razor index 870198e..de2db7c 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor @@ -1,7 +1,6 @@ @namespace Heron.MudCalendar @inherits CalendarViewBase @using Microsoft.JSInterop -@using CategoryTypes = Heron.MudCalendar.Attributes.CategoryTypes @inject IJSRuntime JsRuntime @Render @@ -78,7 +77,7 @@ @if ((int)Calendar.DayTimeInterval >= 60 || i % (60 / (int)Calendar.DayTimeInterval) == 0) { - @(i / (60 / (double)Calendar.DayTimeInterval)):00 + @DrawTime(i) } diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs index 92a497e..4da7139 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs @@ -93,6 +93,15 @@ protected virtual Task OnItemClicked(CalendarItem item) return Calendar.ItemClicked.InvokeAsync(item); } + protected virtual string DrawTime(int row) + { + var hour = row / (60.0 / (double)Calendar.DayTimeInterval); + var timeSpan = TimeSpan.FromHours(hour); + var time = TimeOnly.FromTimeSpan(timeSpan); + + return Calendar.Use24HourClock ? time.ToString("HH:mm") : time.ToString("h tt"); + } + private int CalcTop(ItemPosition position) { double minutes = 0; diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index 85db28c..029d805 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -143,6 +143,13 @@ public partial class MudCalendar : MudComponentBase [Parameter] [Category(CategoryTypes.Calendar.Appearance)] public bool ShowCurrentTime { get; set; } = false; + + /// + /// If true then use 24 hour clock, otherwise use 12 hour format (am/pm). + /// + [Parameter] + [Category(CategoryTypes.Calendar.Appearance)] + public bool Use24HourClock { get; set; } = true; /// /// Defines the cell content for the Month view. From 0579fa042025454e5e5ee0b27126a8652f137ca1 Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Sat, 4 Nov 2023 14:46:24 +0100 Subject: [PATCH 08/11] Added Today button --- .../Examples/OptionsCalendarExample.razor | 4 +- .../Calendar/CalendarTest.razor | 2 +- .../Components/CalendarTests.cs | 4 +- .../Components/MudCalendar.razor | 10 +++-- .../Components/MudCalendar.razor.cs | 43 ++++++++++++++++++- .../Resources/CalendarView.bg.resx | 19 -------- .../Resources/CalendarView.cs.resx | 19 -------- .../Resources/CalendarView.da.resx | 19 -------- .../Resources/CalendarView.de.resx | 12 ------ .../Resources/CalendarView.el.resx | 19 -------- .../Resources/CalendarView.es.resx | 19 -------- .../Resources/CalendarView.et.resx | 19 -------- .../Resources/CalendarView.fi.resx | 19 -------- .../Resources/CalendarView.fr.resx | 19 -------- .../Resources/CalendarView.hu.resx | 19 -------- .../Resources/CalendarView.id.resx | 19 -------- .../Resources/CalendarView.it.resx | 19 -------- .../Resources/CalendarView.ja.resx | 19 -------- .../Resources/CalendarView.ko.resx | 19 -------- .../Resources/CalendarView.lt.resx | 19 -------- .../Resources/CalendarView.lv.resx | 19 -------- .../Resources/CalendarView.nb.resx | 19 -------- .../Resources/CalendarView.nl.resx | 19 -------- .../Resources/CalendarView.pl.resx | 19 -------- .../Resources/CalendarView.pt.resx | 19 -------- Heron.MudCalendar/Resources/CalendarView.resx | 19 -------- .../Resources/CalendarView.ro.resx | 19 -------- .../Resources/CalendarView.ru.resx | 19 -------- .../Resources/CalendarView.sk.resx | 19 -------- .../Resources/CalendarView.sl.resx | 19 -------- .../Resources/CalendarView.sv.resx | 19 -------- .../Resources/CalendarView.tr.resx | 19 -------- .../Resources/CalendarView.uk.resx | 19 -------- .../Resources/CalendarView.zh.resx | 19 -------- .../Resources/MudCalendar.bg.resx | 5 +++ .../Resources/MudCalendar.cs.resx | 5 +++ .../Resources/MudCalendar.da.resx | 5 +++ .../Resources/MudCalendar.de.resx | 5 +++ .../Resources/MudCalendar.el.resx | 5 +++ .../Resources/MudCalendar.es.resx | 5 +++ .../Resources/MudCalendar.et.resx | 5 +++ .../Resources/MudCalendar.fi.resx | 5 +++ .../Resources/MudCalendar.fr.resx | 5 +++ .../Resources/MudCalendar.hu.resx | 5 +++ .../Resources/MudCalendar.id.resx | 5 +++ .../Resources/MudCalendar.it.resx | 5 +++ .../Resources/MudCalendar.ja.resx | 5 +++ .../Resources/MudCalendar.ko.resx | 5 +++ .../Resources/MudCalendar.lt.resx | 5 +++ .../Resources/MudCalendar.lv.resx | 5 +++ .../Resources/MudCalendar.nb.resx | 5 +++ .../Resources/MudCalendar.nl.resx | 5 +++ .../Resources/MudCalendar.pl.resx | 5 +++ .../Resources/MudCalendar.pt.resx | 5 +++ Heron.MudCalendar/Resources/MudCalendar.resx | 5 +++ .../Resources/MudCalendar.ro.resx | 5 +++ .../Resources/MudCalendar.ru.resx | 5 +++ .../Resources/MudCalendar.sk.resx | 5 +++ .../Resources/MudCalendar.sl.resx | 5 +++ .../Resources/MudCalendar.sv.resx | 5 +++ .../Resources/MudCalendar.tr.resx | 5 +++ .../Resources/MudCalendar.uk.resx | 5 +++ .../Resources/MudCalendar.zh.resx | 5 +++ 63 files changed, 199 insertions(+), 553 deletions(-) create mode 100644 Heron.MudCalendar/Resources/MudCalendar.bg.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.cs.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.da.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.de.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.el.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.es.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.et.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.fi.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.fr.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.hu.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.id.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.it.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.ja.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.ko.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.lt.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.lv.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.nb.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.nl.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.pl.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.pt.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.ro.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.ru.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.sk.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.sl.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.sv.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.tr.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.uk.resx create mode 100644 Heron.MudCalendar/Resources/MudCalendar.zh.resx diff --git a/Heron.MudCalendar.Docs/Pages/Calendar/Examples/OptionsCalendarExample.razor b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/OptionsCalendarExample.razor index 9404d70..6a9fb04 100644 --- a/Heron.MudCalendar.Docs/Pages/Calendar/Examples/OptionsCalendarExample.razor +++ b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/OptionsCalendarExample.razor @@ -1,11 +1,12 @@ @namespace Heron.MudCalendar.Docs.Examples - + Outlined Prev/Next Buttons Date Picker + Today Button Primary Secondary @@ -22,6 +23,7 @@ private bool _outlined; private bool _prevNext = true; private bool _datePicker = true; + private bool _todayButton = false; private Color _color = Color.Primary; private Variant _buttonVariant = Variant.Filled; } diff --git a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarTest.razor b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarTest.razor index 4b304c4..c291b96 100644 --- a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarTest.razor +++ b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarTest.razor @@ -1,6 +1,6 @@ - + @code { public static string __description__ = "Basic Calendar Tests"; diff --git a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs index 50dda26..7cefd23 100644 --- a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs +++ b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs @@ -1,6 +1,4 @@ using System; -using System.Threading; -using AngleSharp.Dom; using FluentAssertions; using Heron.MudCalendar.UnitTests.Viewer.TestComponents.Calendar; using MudBlazor; @@ -214,6 +212,8 @@ public void ViewNameLocalization() comp.Find("div.mud-button-group-root button.mud-button-root span.mud-button-label").TextContent.Should() .Be("Monat"); + + comp.FindAll("div.mud-cal-toolbar > div > button")[2].TextContent.Should().Be("Heute"); } [Test] diff --git a/Heron.MudCalendar/Components/MudCalendar.razor b/Heron.MudCalendar/Components/MudCalendar.razor index f7e908b..eba5ce7 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor +++ b/Heron.MudCalendar/Components/MudCalendar.razor @@ -58,12 +58,16 @@
@if (ShowPrevNextButtons) { - - + + } @if (ShowDatePicker) { - + + } + @if (ShowTodayButton) + { + @DrawTodayText() }
diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index 029d805..00c2520 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -1,5 +1,9 @@ +using System.Globalization; using Heron.MudCalendar.Services; using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using MudBlazor.Utilities; using MudBlazor; using CategoryAttribute = Heron.MudCalendar.Attributes.CategoryAttribute; @@ -9,8 +13,6 @@ namespace Heron.MudCalendar; public partial class MudCalendar : MudComponentBase { - private JsService? _jsService; - /// /// The higher the number, the heavier the drop-shadow. 0 for no shadow. /// @@ -116,6 +118,13 @@ public partial class MudCalendar : MudComponentBase [Category(CategoryTypes.Calendar.Behavior)] public bool ShowDatePicker { get; set; } = true; + /// + /// If true the Today button is shown. + /// + [Parameter] + [Category(CategoryTypes.Calendar.Behavior)] + public bool ShowTodayButton { get; set; } = false; + /// /// Set the day start time for week/day views. /// @@ -212,6 +221,11 @@ private DateTime? PickerDate private CalendarDateRange? _currentDateRange; private CalendarDatePicker? _datePicker; + + private JsService? _jsService; + + private static CultureInfo? _uiCulture; + private static string? _todayText; /// /// Classes added to main div of component. @@ -317,6 +331,31 @@ protected virtual Task OnPreviousClicked() return ChangeDateRange(); } + /// + /// Method invoked when the user clicks the today button. + /// + /// + protected virtual Task OnTodayClicked() + { + CurrentDay = DateTime.Today; + + return ChangeDateRange(); + } + + protected string DrawTodayText() + { + if (_todayText != null && Equals(_uiCulture, Thread.CurrentThread.CurrentUICulture)) return _todayText; + + var options = Options.Create(new LocalizationOptions { ResourcesPath = "Resources" }); + var factory = new ResourceManagerStringLocalizerFactory(options, NullLoggerFactory.Instance); + var localizer = new StringLocalizer(factory); + + _uiCulture = Thread.CurrentThread.CurrentUICulture; + _todayText = localizer["Today"]; + + return _todayText; + } + private async Task SetLinks() { // Check if link is already set diff --git a/Heron.MudCalendar/Resources/CalendarView.bg.resx b/Heron.MudCalendar/Resources/CalendarView.bg.resx index 401cd19..f71f892 100644 --- a/Heron.MudCalendar/Resources/CalendarView.bg.resx +++ b/Heron.MudCalendar/Resources/CalendarView.bg.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Ден diff --git a/Heron.MudCalendar/Resources/CalendarView.cs.resx b/Heron.MudCalendar/Resources/CalendarView.cs.resx index a1ee2d1..cfb64e8 100644 --- a/Heron.MudCalendar/Resources/CalendarView.cs.resx +++ b/Heron.MudCalendar/Resources/CalendarView.cs.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Den diff --git a/Heron.MudCalendar/Resources/CalendarView.da.resx b/Heron.MudCalendar/Resources/CalendarView.da.resx index 82f557d..48c7049 100644 --- a/Heron.MudCalendar/Resources/CalendarView.da.resx +++ b/Heron.MudCalendar/Resources/CalendarView.da.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Dag diff --git a/Heron.MudCalendar/Resources/CalendarView.de.resx b/Heron.MudCalendar/Resources/CalendarView.de.resx index 6a5ed9b..d947e5b 100644 --- a/Heron.MudCalendar/Resources/CalendarView.de.resx +++ b/Heron.MudCalendar/Resources/CalendarView.de.resx @@ -1,16 +1,4 @@ - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Tag diff --git a/Heron.MudCalendar/Resources/CalendarView.el.resx b/Heron.MudCalendar/Resources/CalendarView.el.resx index 200c3c2..f0201ff 100644 --- a/Heron.MudCalendar/Resources/CalendarView.el.resx +++ b/Heron.MudCalendar/Resources/CalendarView.el.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Ημέρα diff --git a/Heron.MudCalendar/Resources/CalendarView.es.resx b/Heron.MudCalendar/Resources/CalendarView.es.resx index 55d6693..2db213c 100644 --- a/Heron.MudCalendar/Resources/CalendarView.es.resx +++ b/Heron.MudCalendar/Resources/CalendarView.es.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Día diff --git a/Heron.MudCalendar/Resources/CalendarView.et.resx b/Heron.MudCalendar/Resources/CalendarView.et.resx index fc98548..00b97db 100644 --- a/Heron.MudCalendar/Resources/CalendarView.et.resx +++ b/Heron.MudCalendar/Resources/CalendarView.et.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Päev diff --git a/Heron.MudCalendar/Resources/CalendarView.fi.resx b/Heron.MudCalendar/Resources/CalendarView.fi.resx index 2411fcf..95ed609 100644 --- a/Heron.MudCalendar/Resources/CalendarView.fi.resx +++ b/Heron.MudCalendar/Resources/CalendarView.fi.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Päivä diff --git a/Heron.MudCalendar/Resources/CalendarView.fr.resx b/Heron.MudCalendar/Resources/CalendarView.fr.resx index c3981d3..ff7ffb0 100644 --- a/Heron.MudCalendar/Resources/CalendarView.fr.resx +++ b/Heron.MudCalendar/Resources/CalendarView.fr.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Jour diff --git a/Heron.MudCalendar/Resources/CalendarView.hu.resx b/Heron.MudCalendar/Resources/CalendarView.hu.resx index 44c1185..1b9b1bf 100644 --- a/Heron.MudCalendar/Resources/CalendarView.hu.resx +++ b/Heron.MudCalendar/Resources/CalendarView.hu.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Nap diff --git a/Heron.MudCalendar/Resources/CalendarView.id.resx b/Heron.MudCalendar/Resources/CalendarView.id.resx index 7959d86..af9255c 100644 --- a/Heron.MudCalendar/Resources/CalendarView.id.resx +++ b/Heron.MudCalendar/Resources/CalendarView.id.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Hari diff --git a/Heron.MudCalendar/Resources/CalendarView.it.resx b/Heron.MudCalendar/Resources/CalendarView.it.resx index 5300363..8aab147 100644 --- a/Heron.MudCalendar/Resources/CalendarView.it.resx +++ b/Heron.MudCalendar/Resources/CalendarView.it.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Giorno diff --git a/Heron.MudCalendar/Resources/CalendarView.ja.resx b/Heron.MudCalendar/Resources/CalendarView.ja.resx index b34a3a0..bd22a00 100644 --- a/Heron.MudCalendar/Resources/CalendarView.ja.resx +++ b/Heron.MudCalendar/Resources/CalendarView.ja.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - diff --git a/Heron.MudCalendar/Resources/CalendarView.ko.resx b/Heron.MudCalendar/Resources/CalendarView.ko.resx index 566e958..f155e56 100644 --- a/Heron.MudCalendar/Resources/CalendarView.ko.resx +++ b/Heron.MudCalendar/Resources/CalendarView.ko.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - diff --git a/Heron.MudCalendar/Resources/CalendarView.lt.resx b/Heron.MudCalendar/Resources/CalendarView.lt.resx index 893af34..a60e7c0 100644 --- a/Heron.MudCalendar/Resources/CalendarView.lt.resx +++ b/Heron.MudCalendar/Resources/CalendarView.lt.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Diena diff --git a/Heron.MudCalendar/Resources/CalendarView.lv.resx b/Heron.MudCalendar/Resources/CalendarView.lv.resx index 849ed4e..c7ea100 100644 --- a/Heron.MudCalendar/Resources/CalendarView.lv.resx +++ b/Heron.MudCalendar/Resources/CalendarView.lv.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Diena diff --git a/Heron.MudCalendar/Resources/CalendarView.nb.resx b/Heron.MudCalendar/Resources/CalendarView.nb.resx index fcc8bb4..2262a0c 100644 --- a/Heron.MudCalendar/Resources/CalendarView.nb.resx +++ b/Heron.MudCalendar/Resources/CalendarView.nb.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Dag diff --git a/Heron.MudCalendar/Resources/CalendarView.nl.resx b/Heron.MudCalendar/Resources/CalendarView.nl.resx index f87f3ee..67aa628 100644 --- a/Heron.MudCalendar/Resources/CalendarView.nl.resx +++ b/Heron.MudCalendar/Resources/CalendarView.nl.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Dag diff --git a/Heron.MudCalendar/Resources/CalendarView.pl.resx b/Heron.MudCalendar/Resources/CalendarView.pl.resx index 2235c0b..c192347 100644 --- a/Heron.MudCalendar/Resources/CalendarView.pl.resx +++ b/Heron.MudCalendar/Resources/CalendarView.pl.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Dzień diff --git a/Heron.MudCalendar/Resources/CalendarView.pt.resx b/Heron.MudCalendar/Resources/CalendarView.pt.resx index 103f3d4..ce98623 100644 --- a/Heron.MudCalendar/Resources/CalendarView.pt.resx +++ b/Heron.MudCalendar/Resources/CalendarView.pt.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Dia diff --git a/Heron.MudCalendar/Resources/CalendarView.resx b/Heron.MudCalendar/Resources/CalendarView.resx index 36d0399..a7a9272 100644 --- a/Heron.MudCalendar/Resources/CalendarView.resx +++ b/Heron.MudCalendar/Resources/CalendarView.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Day diff --git a/Heron.MudCalendar/Resources/CalendarView.ro.resx b/Heron.MudCalendar/Resources/CalendarView.ro.resx index e9dc66d..e57c3a8 100644 --- a/Heron.MudCalendar/Resources/CalendarView.ro.resx +++ b/Heron.MudCalendar/Resources/CalendarView.ro.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Ziua diff --git a/Heron.MudCalendar/Resources/CalendarView.ru.resx b/Heron.MudCalendar/Resources/CalendarView.ru.resx index cb2dc6a..b942444 100644 --- a/Heron.MudCalendar/Resources/CalendarView.ru.resx +++ b/Heron.MudCalendar/Resources/CalendarView.ru.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - День diff --git a/Heron.MudCalendar/Resources/CalendarView.sk.resx b/Heron.MudCalendar/Resources/CalendarView.sk.resx index 823656f..9a57f82 100644 --- a/Heron.MudCalendar/Resources/CalendarView.sk.resx +++ b/Heron.MudCalendar/Resources/CalendarView.sk.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Deň diff --git a/Heron.MudCalendar/Resources/CalendarView.sl.resx b/Heron.MudCalendar/Resources/CalendarView.sl.resx index c80ccd2..e165b77 100644 --- a/Heron.MudCalendar/Resources/CalendarView.sl.resx +++ b/Heron.MudCalendar/Resources/CalendarView.sl.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Dan diff --git a/Heron.MudCalendar/Resources/CalendarView.sv.resx b/Heron.MudCalendar/Resources/CalendarView.sv.resx index 811a624..f9023c6 100644 --- a/Heron.MudCalendar/Resources/CalendarView.sv.resx +++ b/Heron.MudCalendar/Resources/CalendarView.sv.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Dag diff --git a/Heron.MudCalendar/Resources/CalendarView.tr.resx b/Heron.MudCalendar/Resources/CalendarView.tr.resx index a676ada..1dea430 100644 --- a/Heron.MudCalendar/Resources/CalendarView.tr.resx +++ b/Heron.MudCalendar/Resources/CalendarView.tr.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Gün diff --git a/Heron.MudCalendar/Resources/CalendarView.uk.resx b/Heron.MudCalendar/Resources/CalendarView.uk.resx index 18e35c4..7fca095 100644 --- a/Heron.MudCalendar/Resources/CalendarView.uk.resx +++ b/Heron.MudCalendar/Resources/CalendarView.uk.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - День diff --git a/Heron.MudCalendar/Resources/CalendarView.zh.resx b/Heron.MudCalendar/Resources/CalendarView.zh.resx index 5aaa52b..776ab94 100644 --- a/Heron.MudCalendar/Resources/CalendarView.zh.resx +++ b/Heron.MudCalendar/Resources/CalendarView.zh.resx @@ -1,23 +1,4 @@ - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - diff --git a/Heron.MudCalendar/Resources/MudCalendar.bg.resx b/Heron.MudCalendar/Resources/MudCalendar.bg.resx new file mode 100644 index 0000000..168bb00 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.bg.resx @@ -0,0 +1,5 @@ + + + Днес + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.cs.resx b/Heron.MudCalendar/Resources/MudCalendar.cs.resx new file mode 100644 index 0000000..82b4fa5 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.cs.resx @@ -0,0 +1,5 @@ + + + Dnes + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.da.resx b/Heron.MudCalendar/Resources/MudCalendar.da.resx new file mode 100644 index 0000000..d4c5255 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.da.resx @@ -0,0 +1,5 @@ + + + I dag + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.de.resx b/Heron.MudCalendar/Resources/MudCalendar.de.resx new file mode 100644 index 0000000..6f4661b --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.de.resx @@ -0,0 +1,5 @@ + + + Heute + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.el.resx b/Heron.MudCalendar/Resources/MudCalendar.el.resx new file mode 100644 index 0000000..7ecd1f4 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.el.resx @@ -0,0 +1,5 @@ + + + Σήμερα + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.es.resx b/Heron.MudCalendar/Resources/MudCalendar.es.resx new file mode 100644 index 0000000..b0009a2 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.es.resx @@ -0,0 +1,5 @@ + + + Hoy + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.et.resx b/Heron.MudCalendar/Resources/MudCalendar.et.resx new file mode 100644 index 0000000..f83cf80 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.et.resx @@ -0,0 +1,5 @@ + + + Täna + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.fi.resx b/Heron.MudCalendar/Resources/MudCalendar.fi.resx new file mode 100644 index 0000000..8bd8380 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.fi.resx @@ -0,0 +1,5 @@ + + + Tänään + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.fr.resx b/Heron.MudCalendar/Resources/MudCalendar.fr.resx new file mode 100644 index 0000000..9720228 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.fr.resx @@ -0,0 +1,5 @@ + + + Aujourd'hui + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.hu.resx b/Heron.MudCalendar/Resources/MudCalendar.hu.resx new file mode 100644 index 0000000..a43b278 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.hu.resx @@ -0,0 +1,5 @@ + + + Ma + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.id.resx b/Heron.MudCalendar/Resources/MudCalendar.id.resx new file mode 100644 index 0000000..0d1f912 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.id.resx @@ -0,0 +1,5 @@ + + + Hari ini + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.it.resx b/Heron.MudCalendar/Resources/MudCalendar.it.resx new file mode 100644 index 0000000..fc66bc4 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.it.resx @@ -0,0 +1,5 @@ + + + Oggi + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.ja.resx b/Heron.MudCalendar/Resources/MudCalendar.ja.resx new file mode 100644 index 0000000..7cd17a4 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.ja.resx @@ -0,0 +1,5 @@ + + + 今日 + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.ko.resx b/Heron.MudCalendar/Resources/MudCalendar.ko.resx new file mode 100644 index 0000000..8bbc702 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.ko.resx @@ -0,0 +1,5 @@ + + + 오늘 + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.lt.resx b/Heron.MudCalendar/Resources/MudCalendar.lt.resx new file mode 100644 index 0000000..a159904 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.lt.resx @@ -0,0 +1,5 @@ + + + Šiandien + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.lv.resx b/Heron.MudCalendar/Resources/MudCalendar.lv.resx new file mode 100644 index 0000000..15892b4 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.lv.resx @@ -0,0 +1,5 @@ + + + Šodien + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.nb.resx b/Heron.MudCalendar/Resources/MudCalendar.nb.resx new file mode 100644 index 0000000..d4c5255 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.nb.resx @@ -0,0 +1,5 @@ + + + I dag + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.nl.resx b/Heron.MudCalendar/Resources/MudCalendar.nl.resx new file mode 100644 index 0000000..3bbc53e --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.nl.resx @@ -0,0 +1,5 @@ + + + Vandaag + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.pl.resx b/Heron.MudCalendar/Resources/MudCalendar.pl.resx new file mode 100644 index 0000000..25a8abd --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.pl.resx @@ -0,0 +1,5 @@ + + + Dzisiaj + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.pt.resx b/Heron.MudCalendar/Resources/MudCalendar.pt.resx new file mode 100644 index 0000000..0e6e32c --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.pt.resx @@ -0,0 +1,5 @@ + + + Hoje + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.resx b/Heron.MudCalendar/Resources/MudCalendar.resx new file mode 100644 index 0000000..37f31c3 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.resx @@ -0,0 +1,5 @@ + + + Today + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.ro.resx b/Heron.MudCalendar/Resources/MudCalendar.ro.resx new file mode 100644 index 0000000..2c41e04 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.ro.resx @@ -0,0 +1,5 @@ + + + Astăzi + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.ru.resx b/Heron.MudCalendar/Resources/MudCalendar.ru.resx new file mode 100644 index 0000000..94beffa --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.ru.resx @@ -0,0 +1,5 @@ + + + Сегодня + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.sk.resx b/Heron.MudCalendar/Resources/MudCalendar.sk.resx new file mode 100644 index 0000000..82b4fa5 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.sk.resx @@ -0,0 +1,5 @@ + + + Dnes + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.sl.resx b/Heron.MudCalendar/Resources/MudCalendar.sl.resx new file mode 100644 index 0000000..aeeb272 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.sl.resx @@ -0,0 +1,5 @@ + + + Danes + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.sv.resx b/Heron.MudCalendar/Resources/MudCalendar.sv.resx new file mode 100644 index 0000000..1b9c53b --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.sv.resx @@ -0,0 +1,5 @@ + + + Idag + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.tr.resx b/Heron.MudCalendar/Resources/MudCalendar.tr.resx new file mode 100644 index 0000000..8234ed8 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.tr.resx @@ -0,0 +1,5 @@ + + + Bugün + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.uk.resx b/Heron.MudCalendar/Resources/MudCalendar.uk.resx new file mode 100644 index 0000000..e4789c7 --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.uk.resx @@ -0,0 +1,5 @@ + + + Сьогодні + + \ No newline at end of file diff --git a/Heron.MudCalendar/Resources/MudCalendar.zh.resx b/Heron.MudCalendar/Resources/MudCalendar.zh.resx new file mode 100644 index 0000000..f2ad5ae --- /dev/null +++ b/Heron.MudCalendar/Resources/MudCalendar.zh.resx @@ -0,0 +1,5 @@ + + + 今天 + + \ No newline at end of file From 6a2884a16b3e5aa9f0054f3a496f002c8a383816 Mon Sep 17 00:00:00 2001 From: Dan Heron <51314385+danheron@users.noreply.github.com> Date: Tue, 14 Nov 2023 15:27:42 +0100 Subject: [PATCH 09/11] Feature/drag events (#72) Added option to drag and drop items. Added option to allow user to resize items --- .gitignore | 2 + .../Heron.MudCalendar.Docs.csproj | 6 +- .../Pages/Calendar/CalendarPage.razor | 13 + .../Examples/DragDropCalendarExample.razor | 16 ++ Heron.MudCalendar.Docs/Theme/Theme.cs | 8 +- Heron.MudCalendar.Docs/wwwroot/index.html | 5 +- .../App.razor | 11 + ...MudCalendar.UnitTests.Viewer.Server.csproj | 21 ++ .../Pages/_Host.cshtml | 32 +++ .../Program.cs | 26 ++ .../Properties/launchSettings.json | 35 +++ .../_Imports.razor | 6 + .../Heron.MudCalendar.UnitTests.Viewer.csproj | 6 +- .../Calendar/CalendarDragTest.razor | 30 +++ .../Calendar/CalendarMultiDayEventTest.razor | 2 +- .../Calendar/CalendarSameDayEventsTest.razor | 14 +- .../Components/CalendarTests.cs | 39 ++- .../Heron.MudCalendar.UnitTests.csproj | 2 +- Heron.MudCalendar/.config/dotnet-tools.json | 2 +- Heron.MudCalendar/Base/DayWeekViewBase.razor | 120 +++++---- .../Base/DayWeekViewBase.razor.cs | 125 ++++++++- Heron.MudCalendar/Components/CalendarItem.cs | 5 + Heron.MudCalendar/Components/MonthView.razor | 108 +++++--- .../Components/MonthView.razor.cs | 58 +++- .../Components/MudCalendar.razor | 2 +- .../Components/MudCalendar.razor.cs | 36 ++- Heron.MudCalendar/Components/Resizer.razor | 5 + Heron.MudCalendar/Components/Resizer.razor.cs | 66 +++++ .../Components/WeekDropZone.razor | 8 + .../Components/WeekDropZone.razor.cs | 50 ++++ .../Extensions/EnumExtensions.cs | 19 ++ Heron.MudCalendar/Heron.MudCalendar.csproj | 29 +- Heron.MudCalendar/Scripts/DragAndDrop.js | 8 + Heron.MudCalendar/Scripts/Resizer.js | 60 +++++ .../Scroll.js} | 0 Heron.MudCalendar/Services/JsService.cs | 10 +- .../Styles/Heron.MudCalendar.css | 248 ++++++++++++++++++ Heron.MudCalendar/Styles/_calendar.scss | 1 + Heron.MudCalendar/Styles/_monthView.scss | 36 ++- Heron.MudCalendar/Styles/_weekView.scss | 30 +++ Heron.MudCalendar/excubowebcompiler.json | 9 +- Heron.MudCalendarWithDocs.sln | 6 + 42 files changed, 1150 insertions(+), 165 deletions(-) create mode 100644 Heron.MudCalendar.Docs/Pages/Calendar/Examples/DragDropCalendarExample.razor create mode 100644 Heron.MudCalendar.UnitTests.Viewer.Server/App.razor create mode 100644 Heron.MudCalendar.UnitTests.Viewer.Server/Heron.MudCalendar.UnitTests.Viewer.Server.csproj create mode 100644 Heron.MudCalendar.UnitTests.Viewer.Server/Pages/_Host.cshtml create mode 100644 Heron.MudCalendar.UnitTests.Viewer.Server/Program.cs create mode 100644 Heron.MudCalendar.UnitTests.Viewer.Server/Properties/launchSettings.json create mode 100644 Heron.MudCalendar.UnitTests.Viewer.Server/_Imports.razor create mode 100644 Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarDragTest.razor create mode 100644 Heron.MudCalendar/Components/Resizer.razor create mode 100644 Heron.MudCalendar/Components/Resizer.razor.cs create mode 100644 Heron.MudCalendar/Components/WeekDropZone.razor create mode 100644 Heron.MudCalendar/Components/WeekDropZone.razor.cs create mode 100644 Heron.MudCalendar/Extensions/EnumExtensions.cs create mode 100644 Heron.MudCalendar/Scripts/DragAndDrop.js create mode 100644 Heron.MudCalendar/Scripts/Resizer.js rename Heron.MudCalendar/{wwwroot/Heron.MudCalendar.js => Scripts/Scroll.js} (100%) create mode 100644 Heron.MudCalendar/Styles/Heron.MudCalendar.css diff --git a/.gitignore b/.gitignore index 989b029..f121e04 100644 --- a/.gitignore +++ b/.gitignore @@ -401,4 +401,6 @@ FodyWeavers.xsd # Autogenerated files **/Heron.MudCalendar.min.css +**/Heron.MudCalendar.min.js +**/Heron.MudCalendar.js Heron.MudCalendar.Docs/NewFilesToBuild.txt diff --git a/Heron.MudCalendar.Docs/Heron.MudCalendar.Docs.csproj b/Heron.MudCalendar.Docs/Heron.MudCalendar.Docs.csproj index 3f72348..5f42e4a 100644 --- a/Heron.MudCalendar.Docs/Heron.MudCalendar.Docs.csproj +++ b/Heron.MudCalendar.Docs/Heron.MudCalendar.Docs.csproj @@ -10,9 +10,9 @@ - - - + + + diff --git a/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor b/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor index cef7d3c..1c1fbf2 100644 --- a/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor +++ b/Heron.MudCalendar.Docs/Pages/Calendar/CalendarPage.razor @@ -50,6 +50,19 @@ + + + + Drag and Drop of items can be enabled by setting the EnableDragItems property to true. + Allow the user to resize items by setting the EnableResizeItems property to true. + Be notified when the start or end date of an item was changed by dragging or resizing with the ItemChanged event. + + + + + + + diff --git a/Heron.MudCalendar.Docs/Pages/Calendar/Examples/DragDropCalendarExample.razor b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/DragDropCalendarExample.razor new file mode 100644 index 0000000..469d2fa --- /dev/null +++ b/Heron.MudCalendar.Docs/Pages/Calendar/Examples/DragDropCalendarExample.razor @@ -0,0 +1,16 @@ +@namespace Heron.MudCalendar.Docs.Examples + + + +@code { + + private readonly List _events = new() + { + new CalendarItem + { + Start = DateTime.Today.AddHours(10), + End = DateTime.Today.AddHours(12), + Text = "Event today" + } + }; +} \ No newline at end of file diff --git a/Heron.MudCalendar.Docs/Theme/Theme.cs b/Heron.MudCalendar.Docs/Theme/Theme.cs index 3312690..f9e3e40 100644 --- a/Heron.MudCalendar.Docs/Theme/Theme.cs +++ b/Heron.MudCalendar.Docs/Theme/Theme.cs @@ -42,7 +42,7 @@ public static MudTheme DocsTheme() #region Docs - private static readonly Palette DocsLightPalette = new() + private static readonly PaletteLight DocsLightPalette = new() { Black = "#110e2d", AppbarText = "#424242", @@ -52,7 +52,7 @@ public static MudTheme DocsTheme() GrayLighter = "#f9f9f9" }; - private static readonly Palette DocsDarkPalette = new() + private static readonly PaletteDark DocsDarkPalette = new() { Primary = "#7e6fff", Surface= "#1e1e2d", @@ -144,7 +144,7 @@ public static MudTheme DocsTheme() TextTransform = "none" } }; - private static readonly Palette LandingPageLightPalette = new() + private static readonly PaletteLight LandingPageLightPalette = new() { AppbarText = "#424242", AppbarBackground = "rgba(0,0,0,0)", @@ -156,7 +156,7 @@ public static MudTheme DocsTheme() GrayLight = "#9CA3AF", GrayLighter = "#adbdccff" }; - private static readonly Palette LandingPageDarkPalette = new() + private static readonly PaletteDark LandingPageDarkPalette = new() { AppbarText = "#92929f", AppbarBackground = "rgba(0,0,0,0)", diff --git a/Heron.MudCalendar.Docs/wwwroot/index.html b/Heron.MudCalendar.Docs/wwwroot/index.html index 9c49980..00c4737 100644 --- a/Heron.MudCalendar.Docs/wwwroot/index.html +++ b/Heron.MudCalendar.Docs/wwwroot/index.html @@ -7,8 +7,9 @@ Heron.MudCalendar.Docs - - + + + diff --git a/Heron.MudCalendar.UnitTests.Viewer.Server/App.razor b/Heron.MudCalendar.UnitTests.Viewer.Server/App.razor new file mode 100644 index 0000000..e6ab3a8 --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer.Server/App.razor @@ -0,0 +1,11 @@ + + + + + + Not found + +

Sorry, there's nothing at this address.

+
+
+
\ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests.Viewer.Server/Heron.MudCalendar.UnitTests.Viewer.Server.csproj b/Heron.MudCalendar.UnitTests.Viewer.Server/Heron.MudCalendar.UnitTests.Viewer.Server.csproj new file mode 100644 index 0000000..ce067db --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer.Server/Heron.MudCalendar.UnitTests.Viewer.Server.csproj @@ -0,0 +1,21 @@ + + + + net7.0 + enable + enable + + + + + + + + + + + + + + + diff --git a/Heron.MudCalendar.UnitTests.Viewer.Server/Pages/_Host.cshtml b/Heron.MudCalendar.UnitTests.Viewer.Server/Pages/_Host.cshtml new file mode 100644 index 0000000..31b5d46 --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer.Server/Pages/_Host.cshtml @@ -0,0 +1,32 @@ +@page "/" +@using Microsoft.AspNetCore.Components.Web +@namespace Heron.MudCalendar.UnitTests.Viewer.Server.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + + + + + Heron.MudCalendar.UnitTests.Viewer.Server + + + + + + + + +
+ + An error has occurred. This application may no longer respond until reloaded. + + + An unhandled exception has occurred. See browser dev tools for details. + + Reload + 🗙 +
+ + + + + \ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests.Viewer.Server/Program.cs b/Heron.MudCalendar.UnitTests.Viewer.Server/Program.cs new file mode 100644 index 0000000..cf15c2f --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer.Server/Program.cs @@ -0,0 +1,26 @@ +using MudBlazor.Services; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddRazorPages(); +builder.Services.AddServerSideBlazor(); + +builder.Services.AddMudServices(); + +var app = builder.Build(); + +if (!app.Environment.IsDevelopment()) +{ + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +app.UseHttpsRedirection(); + +app.UseStaticFiles(); + +app.UseRouting(); + +app.MapBlazorHub(); +app.MapFallbackToPage("/_Host"); + +app.Run(); \ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests.Viewer.Server/Properties/launchSettings.json b/Heron.MudCalendar.UnitTests.Viewer.Server/Properties/launchSettings.json new file mode 100644 index 0000000..18227cb --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer.Server/Properties/launchSettings.json @@ -0,0 +1,35 @@ +{ + "iisSettings": { + "iisExpress": { + "applicationUrl": "http://localhost:42361", + "sslPort": 44328 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5018", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7269;http://localhost:5018", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Heron.MudCalendar.UnitTests.Viewer.Server/_Imports.razor b/Heron.MudCalendar.UnitTests.Viewer.Server/_Imports.razor new file mode 100644 index 0000000..58ea705 --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer.Server/_Imports.razor @@ -0,0 +1,6 @@ +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.JSInterop +@using MudBlazor; +@using Heron.MudCalendar.UnitTests.Viewer +@using Heron.MudCalendar.UnitTests.Viewer.Server \ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests.Viewer/Heron.MudCalendar.UnitTests.Viewer.csproj b/Heron.MudCalendar.UnitTests.Viewer/Heron.MudCalendar.UnitTests.Viewer.csproj index 7d61bad..378bfed 100644 --- a/Heron.MudCalendar.UnitTests.Viewer/Heron.MudCalendar.UnitTests.Viewer.csproj +++ b/Heron.MudCalendar.UnitTests.Viewer/Heron.MudCalendar.UnitTests.Viewer.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarDragTest.razor b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarDragTest.razor new file mode 100644 index 0000000..8a83df8 --- /dev/null +++ b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarDragTest.razor @@ -0,0 +1,30 @@ + + + + + +@code { + public static string __description__ = "Drag and Resize Calendar Tests"; + + private string _value = string.Empty; + + private List _events = new() + { + new CalendarItem + { + Start = DateTime.Today.AddHours(10), + Text = "Event today" + }, + new CalendarItem + { + Start = DateTime.Today.AddDays(1).AddHours(11), + End = DateTime.Today.AddDays(1).AddHours(12.5), + Text = "Event tomorrow" + } + }; + + private void ItemChanged(CalendarItem item) + { + _value = $"Item Changed: {item.Text}, Start: {item.Start}, End: {item.End}"; + } +} diff --git a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarMultiDayEventTest.razor b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarMultiDayEventTest.razor index 7b9bdd0..31092fa 100644 --- a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarMultiDayEventTest.razor +++ b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarMultiDayEventTest.razor @@ -1,4 +1,4 @@ - + @code { public static string __description__ = "Calendar Multi-Day Events Tests"; diff --git a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarSameDayEventsTest.razor b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarSameDayEventsTest.razor index 2339b2b..0b35132 100644 --- a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarSameDayEventsTest.razor +++ b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarSameDayEventsTest.razor @@ -1,4 +1,6 @@ - + + +Add Item @code { public static string __description__ = "Calendar Same Day Events Tests"; @@ -24,4 +26,14 @@ Text = "Event 3" } }; + + private void AddItem() + { + _events.Add(new CalendarItem + { + Start = DateTime.Today.AddHours(10.5), + End = DateTime.Today.AddHours(11.5), + Text = "Event 2.5" + }); + } } \ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs index 7cefd23..a8286dc 100644 --- a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs +++ b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs @@ -200,7 +200,10 @@ public void EventOrder() var cut = Context.RenderComponent(); var comp = cut.FindComponent(); - comp.Find("div.mud-cal-month-cell-events div.mud-cal-cell-template").TextContent.Should().Be("Event 1"); + comp.Find("div.mud-cal-month-dropzone div.mud-cal-cell-template").TextContent.Should().Be("Event 1"); + + cut.Find("button.add-item").Click(); + comp.FindAll("div.mud-cal-month-dropzone div.mud-cal-cell-template")[2].TextContent.Should().Be("Event 2.5"); } [Test] @@ -265,7 +268,7 @@ public void OverlappingEvents() var comp = cut.FindComponent(); comp.SetParam(x => x.View, CalendarView.Day); - var event2 = comp.FindAll("td.mud-cal-week-cell-holder > div")[1]; + var event2 = comp.FindAll("td.mud-cal-week-cell-holder > div.mud-cal-week-drop-item")[1]; event2.Attributes["style"].Should().NotBeNull(); event2.Attributes["style"]?.Value.Should().Contain("left:33"); event2.Attributes["style"]?.Value.Should().Contain("width:33"); @@ -278,9 +281,14 @@ public void MultiDayMonthView() var comp = cut.FindComponent(); comp.SetParam(x => x.CurrentDay, new DateTime(2023, 2, 1)); - comp.FindAll("div.mud-cal-month-cell > div.mud-cal-month-cell-title")[2].TextContent.Should().Be("1"); - comp.FindAll("div.mud-cal-month-cell > div.mud-cal-month-cell-events")[2].Children.Length.Should().Be(1); - comp.FindAll("div.mud-cal-month-cell > div.mud-cal-month-cell-events")[3].Children.Length.Should().Be(1); + comp.FindAll("div.mud-cal-month-cell > div.mud-drop-zone > div.mud-cal-month-cell-title")[2].TextContent.Should().Be("1"); + comp.FindAll("div.mud-cal-month-cell > div.mud-drop-zone")[2].Children.Length.Should().Be(2); + comp.FindAll("div.mud-cal-month-cell > div.mud-drop-zone")[3].Children.Length.Should().Be(2); + + comp.SetParam(x => x.EnableDragItems, true); + comp.FindAll("div.mud-cal-month-cell > div.mud-drop-zone > div.mud-cal-month-cell-title")[2].TextContent.Should().Be("1"); + comp.FindAll("div.mud-cal-month-cell > div.mud-drop-zone")[2].Children.Length.Should().Be(2); + comp.FindAll("div.mud-cal-month-cell > div.mud-drop-zone")[3].Children.Length.Should().Be(2); } [Test] @@ -291,8 +299,12 @@ public void MultiDayWeekView() comp.SetParam(x => x.CurrentDay, new DateTime(2023, 2, 1)); comp.SetParam(x => x.View, CalendarView.Week); - comp.FindAll("td.mud-cal-week-cell-holder")[2].Children.Length.Should().Be(1); - comp.FindAll("td.mud-cal-week-cell-holder")[3].Children.Length.Should().Be(1); + comp.FindAll("div.mud-cal-week-layer tr td:nth-child(4) div.mud-cal-cell-template").Count.Should().Be(1); + comp.FindAll("div.mud-cal-week-layer tr td:nth-child(5) div.mud-cal-cell-template").Count.Should().Be(1); + + comp.SetParam(x => x.EnableDragItems, true); + comp.FindAll("div.mud-cal-week-layer tr td:nth-child(4) div.mud-cal-cell-template").Count.Should().Be(1); + comp.FindAll("div.mud-cal-week-layer tr td:nth-child(5) div.mud-cal-cell-template").Count.Should().Be(1); } [Test] @@ -304,10 +316,19 @@ public void MultiDayDayView() comp.SetParam(x => x.View, CalendarView.Day); comp.SetParam(x => x.CurrentDay, new DateTime(2023, 2, 1)); - comp.FindAll("td.mud-cal-week-cell-holder")[0].Children.Length.Should().Be(1); + comp.FindAll("td.mud-cal-week-cell-holder div.mud-drop-item").Count.Should().Be(1); + + comp.SetParam(x => x.CurrentDay, new DateTime(2023, 2, 2)); + comp.FindAll("td.mud-cal-week-cell-holder div.mud-drop-item").Count.Should().Be(0); + comp.FindAll("td.mud-cal-week-cell-holder div.mud-cal-cell-template").Count.Should().Be(1); + + comp.SetParam(x => x.EnableDragItems, true); + comp.SetParam(x => x.CurrentDay, new DateTime(2023, 2, 1)); + comp.FindAll("td.mud-cal-week-cell-holder div.mud-drop-item").Count.Should().Be(1); comp.SetParam(x => x.CurrentDay, new DateTime(2023, 2, 2)); - comp.FindAll("td.mud-cal-week-cell-holder")[0].Children.Length.Should().Be(1); + comp.FindAll("td.mud-cal-week-cell-holder div.mud-drop-item").Count.Should().Be(0); + comp.FindAll("td.mud-cal-week-cell-holder div.mud-cal-cell-template").Count.Should().Be(1); } [Test] diff --git a/Heron.MudCalendar.UnitTests/Heron.MudCalendar.UnitTests.csproj b/Heron.MudCalendar.UnitTests/Heron.MudCalendar.UnitTests.csproj index 623da44..6a98a36 100644 --- a/Heron.MudCalendar.UnitTests/Heron.MudCalendar.UnitTests.csproj +++ b/Heron.MudCalendar.UnitTests/Heron.MudCalendar.UnitTests.csproj @@ -30,7 +30,7 @@ - + diff --git a/Heron.MudCalendar/.config/dotnet-tools.json b/Heron.MudCalendar/.config/dotnet-tools.json index 873ad45..5cf2076 100644 --- a/Heron.MudCalendar/.config/dotnet-tools.json +++ b/Heron.MudCalendar/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "excubo.webcompiler": { - "version": "2.7.14", + "version": "3.5.78", "commands": [ "webcompiler" ] diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor b/Heron.MudCalendar/Base/DayWeekViewBase.razor index de2db7c..fa0859a 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor @@ -19,8 +19,22 @@
@RenderTimes - @RenderDays - @RenderCells + @* @RenderDays *@ + + + @RenderCells + + + @RenderTemplate(context) + +
@@ -62,7 +76,7 @@ }; /// - /// Renders the times of day. + /// Renders the day/week structure. /// protected virtual RenderFragment RenderTimes => @
@@ -71,20 +85,23 @@ - @for (var i = 0; i < CellsInDay; i++) + @for (var row = 0; row < CellsInDay; row++) { - @if ((int)Calendar.DayTimeInterval >= 60 || i % (60 / (int)Calendar.DayTimeInterval) == 0) + + @if (IsHourCell(row)) + { + @DrawTime(row) + } + + @foreach (var cell in Cells) { - - @DrawTime(i) + + @if (Calendar.ShowCurrentTime && TimelineRow() == row) + { +
+ } - - } - else - { - - } } @@ -92,34 +109,6 @@
; - /// - /// Renders each day. - /// - protected virtual RenderFragment RenderDays => - @
- - - - - - - - @foreach (var cell in Cells) - { - - } - - -
-
- @if (cell.Today && Calendar.ShowCurrentTime) - { -
- } -
-
-
; - /// /// Renders the cells. /// @@ -145,18 +134,19 @@ /// Renders an individual cell. ///
protected virtual RenderFragment RenderCell(CalendarCell cell) => - @ - @if (Calendar.CellClicked.HasDelegate) + @ + @for (var i = 0; i < CellsInDay; i++) { - for (var i = 0; i < CellsInDay; i++) - { - var row = i; -
+ var row = i; + + @if (Calendar.CellClicked.HasDelegate) + { -
- } + } +   + } @RenderCellContents(cell) ; @@ -169,19 +159,41 @@ var positions = CalcPositions(cell.Items, DateOnly.FromDateTime(cell.Date)); foreach (var position in positions) { - @if (Calendar.ItemClicked.HasDelegate) + if (position.Item.Start.Date == cell.Date.Date) { -
- @CellTemplate?.Invoke(position.Item) -
+ + @if (Calendar.EnableResizeItems && !position.Item.IsMultiDay) + { + + } + } else {
- @CellTemplate?.Invoke(position.Item) + @RenderTemplate(position.Item)
} } }; + + /// + /// Renders the CellTemplate with a click handler if required. + /// + protected virtual RenderFragment RenderTemplate(CalendarItem item) => __builder => + { + @if (Calendar.ItemClicked.HasDelegate) + { +
+ @CellTemplate.Invoke(item) +
+ } + else + { +
+ @CellTemplate.Invoke(item) +
+ } + }; } \ No newline at end of file diff --git a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs index 4da7139..30170e4 100644 --- a/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs +++ b/Heron.MudCalendar/Base/DayWeekViewBase.razor.cs @@ -1,7 +1,9 @@ using Heron.MudCalendar.Services; using Microsoft.AspNetCore.Components; +using MudBlazor; using MudBlazor.Extensions; using MudBlazor.Utilities; +using EnumExtensions = Heron.MudCalendar.Extensions.EnumExtensions; namespace Heron.MudCalendar; @@ -15,6 +17,8 @@ public abstract partial class DayWeekViewBase : CalendarViewBase, IAsyncDisposab private int CellsInDay => MinutesInDay / (int)Calendar.DayTimeInterval; private int PixelsInDay => CellsInDay * PixelsInCell; + + private MudDropContainer? _dropContainer; protected override async Task OnAfterRenderAsync(bool firstRender) { @@ -30,15 +34,23 @@ protected override async Task OnAfterRenderAsync(bool firstRender) /// Styles added to each day. /// /// The cell. + /// The current row in the table being rendered. /// - protected virtual string DayStyle(CalendarCell calendarCell) + protected virtual string DayStyle(CalendarCell calendarCell, int row) { return new StyleBuilder() - .AddStyle("border", $"1px solid var(--mud-palette-{Calendar.Color.ToDescriptionString()})", - calendarCell.Today && Calendar.HighlightToday) + .AddStyle("border-left", $"1px solid var(--mud-palette-{EnumExtensions.ToDescriptionString(Calendar.Color)})", calendarCell.Today && Calendar.HighlightToday) + .AddStyle("border-right", $"1px solid var(--mud-palette-{EnumExtensions.ToDescriptionString(Calendar.Color)})", calendarCell.Today && Calendar.HighlightToday) + .AddStyle("border-top", $"1px solid var(--mud-palette-{EnumExtensions.ToDescriptionString(Calendar.Color)})", row == 0 && calendarCell.Today && Calendar.HighlightToday) + .AddStyle("border-bottom", $"1px solid var(--mud-palette-{EnumExtensions.ToDescriptionString(Calendar.Color)})", row + 1 == CellsInDay && calendarCell.Today && Calendar.HighlightToday) .Build(); } + /// + /// Styles the position and height of the div containing an item. + /// + /// Position information for the div. + /// protected virtual string EventStyle(ItemPosition position) { return new StyleBuilder() @@ -46,13 +58,41 @@ protected virtual string EventStyle(ItemPosition position) .AddStyle("top", $"{CalcTop(position)}px") .AddStyle("height", $"{CalcHeight(position)}px") .AddStyle("overflow", "hidden") - .AddStyle("left", - (((position.Position / (double)position.Total) - (1.0 / position.Total)) * 100).ToInvariantString() + - "%") - .AddStyle("width", (100 / position.Total) + "%") + .AddStyle("left", (((position.Position / (double)position.Total) - (1.0 / position.Total)) * 100).ToInvariantString() + "%") + .AddStyle("width", (100 / position.Total) + "%" ) .Build(); } + /// + /// Styles for the cell where the time is displayed.. + /// + /// The row being styled. + /// + protected virtual string TimeCellClassname(int row) + { + return new CssBuilder() + .AddClass("mud-cal-week-cell", IsHourCell(row)) + .AddClass("mud-cal-time-cell", IsHourCell(row)) + .Build(); + } + + /// + /// Styles for each cell in the view. + /// + /// The row being styled. + /// + protected virtual string DayCellClassname(int row) + { + return new CssBuilder() + .AddClass("mud-cal-week-cell") + .AddClass("mud-cal-week-cell-half", !IsHourCell(row)) + .Build(); + } + + /// + /// Styles that set the height of each cell. + /// + /// protected virtual string CellHeightStyle() { return new StyleBuilder() @@ -60,14 +100,18 @@ protected virtual string CellHeightStyle() .Build(); } + /// + /// The style of the line showing the current time. + /// + /// protected virtual string TimelineStyle() { return new StyleBuilder() .AddStyle("position", "absolute") .AddStyle("width", "100%") .AddStyle("border", "1px solid var(--mud-palette-grey-default)") - .AddStyle("top", - $"{(int)((DateTime.Now.Subtract(DateTime.Today).TotalMinutes / MinutesInDay) * PixelsInDay)}px") + //.AddStyle("top", $"{(int)((DateTime.Now.Subtract(DateTime.Today).TotalMinutes / MinutesInDay) * PixelsInDay)}px") + .AddStyle("top", $"{TimelinePosition()}px") .Build(); } @@ -82,7 +126,7 @@ protected virtual Task OnCellLinkClicked(CalendarCell cell, int row) var date = cell.Date.AddHours(row / (60.0 / (int)Calendar.DayTimeInterval)); return Calendar.CellClicked.InvokeAsync(date); } - + /// /// Method invoked when the user clicks on the calendar item. /// @@ -92,7 +136,12 @@ protected virtual Task OnItemClicked(CalendarItem item) { return Calendar.ItemClicked.InvokeAsync(item); } - + + /// + /// Creates a string with the time to be displayed. + /// + /// The current row in the table. + /// protected virtual string DrawTime(int row) { var hour = row / (60.0 / (double)Calendar.DayTimeInterval); @@ -101,6 +150,31 @@ protected virtual string DrawTime(int row) return Calendar.Use24HourClock ? time.ToString("HH:mm") : time.ToString("h tt"); } + + protected int TimelineRow() + { + var minutes = DateTime.Now.Subtract(DateTime.Today).TotalMinutes; + var row = (int)Math.Floor(minutes / (int)Calendar.DayTimeInterval); + + return row; + } + + private double TimelinePosition() + { + var minutes = DateTime.Now.Subtract(DateTime.Today).TotalMinutes - (TimelineRow() * (int)Calendar.DayTimeInterval); + var position = (minutes / (int)Calendar.DayTimeInterval) * Calendar.DayCellHeight; + + return position; + } + + protected Task ItemHeightChanged(CalendarItem item, int newHeight) + { + // Calculate end time from height + var minutes = (newHeight / (double)PixelsInDay) * MinutesInDay; + item.End = item.Start.AddMinutes(minutes); + + return Calendar.ItemChanged.InvokeAsync(item); + } private int CalcTop(ItemPosition position) { @@ -196,6 +270,35 @@ private static IEnumerable CalcPositions(IEnumerable return positions; } + + private async Task ItemDropped(MudItemDropInfo dropItem) + { + if (dropItem.Item == null) return; + var item = dropItem.Item; + var duration = item.End?.Subtract(item.Start) ?? TimeSpan.Zero; + + var ids = dropItem.DropzoneIdentifier.Split("_"); + if (!DateTime.TryParse(ids[0], out var date)) return; + var cell = int.Parse(ids[1]); + var minutes = ((double)cell / CellsInDay) * MinutesInDay; + date = date.AddMinutes(minutes); + + // Update start and end time + item.Start = date; + if (item.End.HasValue) + { + item.End = item.Start.Add(duration); + } + + Calendar.Refresh(); + + await Calendar.ItemChanged.InvokeAsync(item); + } + + private bool IsHourCell(int row) + { + return (int)Calendar.DayTimeInterval >= 60 || row % (60 / (int)Calendar.DayTimeInterval) == 0; + } protected class ItemPosition { diff --git a/Heron.MudCalendar/Components/CalendarItem.cs b/Heron.MudCalendar/Components/CalendarItem.cs index d9dcf09..e13e74c 100644 --- a/Heron.MudCalendar/Components/CalendarItem.cs +++ b/Heron.MudCalendar/Components/CalendarItem.cs @@ -9,4 +9,9 @@ public class CalendarItem public bool AllDay { get; set; } public string Text { get; set; } = string.Empty; + + protected internal bool IsMultiDay => (End == null && Start.TimeOfDay > TimeSpan.FromHours(23)) || + (End.HasValue && End.Value.Date > Start.Date); + + protected internal readonly string Id = Guid.NewGuid().ToString(); } diff --git a/Heron.MudCalendar/Components/MonthView.razor b/Heron.MudCalendar/Components/MonthView.razor index ad881a0..135f510 100644 --- a/Heron.MudCalendar/Components/MonthView.razor +++ b/Heron.MudCalendar/Components/MonthView.razor @@ -9,16 +9,32 @@ /// Renders the component. /// protected virtual RenderFragment Render => - @
- - - @RenderHeader - - - @RenderBody - -
-
; + @ + + + + @RenderHeader + + + @RenderBody + +
+
+ + @*
*@ + @* @CellTemplate.Invoke(context) *@ + @*
*@ + @RenderTemplate(context) +
+
; /// /// Renders the header of the component that contains the day names. @@ -60,20 +76,20 @@ /// protected virtual RenderFragment RenderCell(CalendarCell cell) => @ - @if (Calendar.CellClicked.HasDelegate) - { - - } - else - { -
+
+ @RenderCellDayNumber(cell) - @RenderCellContents(cell) -
- } + @if (cell.Items.Any()) + { +
+ @foreach (var item in cell.Items) + { + @CellTemplate?.Invoke(item) + } +
+ } + +
; /// @@ -87,23 +103,37 @@ /// /// Renders the contents of the cell. /// - protected virtual RenderFragment RenderCellContents(CalendarCell cell) => - @
- @foreach (var item in cell.Items) - { - @if (Calendar.ItemClicked.HasDelegate) - { -
- @CellTemplate?.Invoke(item) -
- } - else + protected virtual RenderFragment RenderCellContents(CalendarCell cell) => __builder => + { + if (cell.Items.Any()) + { +
+ @foreach (var item in cell.Items) { -
- @CellTemplate?.Invoke(item) -
+ @RenderTemplate(item) } - } -
; +
+ } + + }; + + /// + /// Renders the CellTemplate with a click handler if required. + /// + protected virtual RenderFragment RenderTemplate(CalendarItem item) => __builder => + { + @if (Calendar.ItemClicked.HasDelegate) + { +
+ @CellTemplate?.Invoke(item) +
+ } + else + { +
+ @CellTemplate?.Invoke(item) +
+ } + }; } \ No newline at end of file diff --git a/Heron.MudCalendar/Components/MonthView.razor.cs b/Heron.MudCalendar/Components/MonthView.razor.cs index 93286a1..3835a1f 100644 --- a/Heron.MudCalendar/Components/MonthView.razor.cs +++ b/Heron.MudCalendar/Components/MonthView.razor.cs @@ -7,6 +7,8 @@ namespace Heron.MudCalendar; public partial class MonthView : CalendarViewBase { + private MudDropContainer? _dropContainer; + /// /// Classes added to main div of component. /// @@ -24,6 +26,15 @@ public partial class MonthView : CalendarViewBase .AddStyle("height", $"{100 / (Cells.Count / 7)}%", Calendar.MonthCellMinHeight == 0) .Build(); + /// + /// Classes added to each month cell. + /// + protected virtual string CellClassname => + new CssBuilder() + .AddClass("mud-cal-month-cell") + .AddClass("mud-cal-month-link", Calendar.CellClicked.HasDelegate) + .Build(); + /// /// Classes added to the day number. /// @@ -45,7 +56,7 @@ protected virtual string DayClassname(CalendarCell calendarCell) protected virtual string DayStyle(CalendarCell calendarCell) { return new StyleBuilder() - .AddStyle("border", $"1px solid var(--mud-palette-{Calendar.Color.ToDescriptionString()})", + .AddStyle("border", $"1px solid var(--mud-palette-{Calendar.Color.ToDescriptionString()})", calendarCell.Today && Calendar.HighlightToday) .AddStyle("min-height", Calendar.MonthCellMinHeight + "px", Calendar.MonthCellMinHeight > 0) .Build(); @@ -56,9 +67,20 @@ protected virtual string DayStyle(CalendarCell calendarCell) ///
/// The cell that was clicked. /// - protected virtual Task OnCellLinkClicked(CalendarCell cell) + protected virtual async Task OnCellLinkClicked(CalendarCell cell) + { + if (Calendar.CellClicked.HasDelegate) + { + await Calendar.CellClicked.InvokeAsync(cell.Date); + } + } + + protected override void OnParametersSet() { - return Calendar.CellClicked.InvokeAsync(cell.Date); + base.OnParametersSet(); + + // Ensure that the order of items is correct + _dropContainer?.Refresh(); } /// @@ -86,11 +108,11 @@ protected override List BuildCells() { var cell = BuildCell(date, monthStart, monthEnd); cells.Add(cell); - + // Next day date = date.AddDays(1); } - + return cells; } @@ -110,12 +132,30 @@ protected virtual CalendarCell BuildCell(DateTime date, DateTime monthStart, Dat cell.Outside = true; } cell.Items = Calendar.Items.Where(i => - (i.Start.Date == date) || - (i.Start.Date <= date && i.End.HasValue && i.End.Value.Date >= date)) - .OrderBy(i => i.Start) - .ToList(); + (i.Start.Date < date && i.End.HasValue && i.End.Value.Date >= date)) + .OrderBy(i => i.Start) + .ToList(); + return cell; } + private async Task ItemDropped(MudItemDropInfo dropItem) + { + if (dropItem.Item == null) return; + var item = dropItem.Item; + + // Update start and end time + var duration = item.End?.Subtract(item.Start) ?? TimeSpan.Zero; + item.Start = DateTime.Parse(dropItem.DropzoneIdentifier).Add(item.Start.TimeOfDay); + if (item.End.HasValue) + { + item.End = item.Start.Add(duration); + } + + Calendar.Refresh(); + + await Calendar.ItemChanged.InvokeAsync(item); + } + private RenderFragment CellTemplate => Calendar.MonthTemplate ?? Calendar.CellTemplate; } \ No newline at end of file diff --git a/Heron.MudCalendar/Components/MudCalendar.razor b/Heron.MudCalendar/Components/MudCalendar.razor index eba5ce7..47b15cf 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor +++ b/Heron.MudCalendar/Components/MudCalendar.razor @@ -55,7 +55,7 @@ /// protected virtual RenderFragment RenderToolbar => @
-
+
@if (ShowPrevNextButtons) { diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index 00c2520..c8154ed 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -123,7 +123,7 @@ public partial class MudCalendar : MudComponentBase /// [Parameter] [Category(CategoryTypes.Calendar.Behavior)] - public bool ShowTodayButton { get; set; } = false; + public bool ShowTodayButton { get; set; } /// /// Set the day start time for week/day views. @@ -151,7 +151,21 @@ public partial class MudCalendar : MudComponentBase /// [Parameter] [Category(CategoryTypes.Calendar.Appearance)] - public bool ShowCurrentTime { get; set; } = false; + public bool ShowCurrentTime { get; set; } + + /// + /// If true then calendar items can be drag/dropped to different dates/times. + /// + [Parameter] + [Category(CategoryTypes.Calendar.Behavior)] + public bool EnableDragItems { get; set; } + + /// + /// If true then the user can change the duration of an item by resizing the item. + /// + [Parameter] + [Category(CategoryTypes.Calendar.Behavior)] + public bool EnableResizeItems { get; set; } /// /// If true then use 24 hour clock, otherwise use 12 hour format (am/pm). @@ -193,7 +207,13 @@ public partial class MudCalendar : MudComponentBase /// [Parameter] public EventCallback DateRangeChanged { get; set; } - + + /// + /// Called when an item is changed, for example by dragging or resizing the item. + /// + [Parameter] + public EventCallback ItemChanged { get; set; } + /// /// Called when the View is changed. /// @@ -277,12 +297,20 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender) { - //await DateRangeChanged.InvokeAsync(new CalendarDateRange(CurrentDay, View)); await ChangeDateRange(); await SetLinks(); } } + + /// + /// Forces the component to be redrawn. + /// + /// + public void Refresh() + { + StateHasChanged(); + } /// /// Method invoked when the user changes the view. diff --git a/Heron.MudCalendar/Components/Resizer.razor b/Heron.MudCalendar/Components/Resizer.razor new file mode 100644 index 0000000..ec1c0c0 --- /dev/null +++ b/Heron.MudCalendar/Components/Resizer.razor @@ -0,0 +1,5 @@ +@using Microsoft.JSInterop +@namespace Heron.MudCalendar +@inject IJSRuntime JsRuntime + +
diff --git a/Heron.MudCalendar/Components/Resizer.razor.cs b/Heron.MudCalendar/Components/Resizer.razor.cs new file mode 100644 index 0000000..e1f48de --- /dev/null +++ b/Heron.MudCalendar/Components/Resizer.razor.cs @@ -0,0 +1,66 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; + +namespace Heron.MudCalendar; + +public partial class Resizer : IAsyncDisposable +{ + private readonly string _id = Guid.NewGuid().ToString(); + + private readonly Lazy> _moduleTask; + private IJSObjectReference? _resizer; + private DotNetObjectReference? _this; + + [Parameter] + public int IntervalSize { get; set; } = 36; + + [Parameter] + public EventCallback HeightChanged { get; set; } + + public Resizer() + { + _moduleTask = new Lazy>( + () => + JsRuntime.InvokeAsync("import", + "./_content/Heron.MudCalendar/Heron.MudCalendar.min.js").AsTask()); + } + + [JSInvokable] + public Task ResizeFinished(int newHeight) + { + return HeightChanged.InvokeAsync(newHeight); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + if (firstRender) + { + await CreateResizer(); + } + } + + private async Task CreateResizer() + { + _this ??= DotNetObjectReference.Create(this); + var module = await _moduleTask.Value; + _resizer = await module.InvokeAsync("newResizer", _id, IntervalSize, _this); + } + + public async ValueTask DisposeAsync() + { + GC.SuppressFinalize(this); + + _this?.Dispose(); + if (_resizer != null) + { + await _resizer.DisposeAsync(); + } + if (_moduleTask.IsValueCreated) + { + var module = await _moduleTask.Value; + await module.DisposeAsync(); + } + } +} \ No newline at end of file diff --git a/Heron.MudCalendar/Components/WeekDropZone.razor b/Heron.MudCalendar/Components/WeekDropZone.razor new file mode 100644 index 0000000..5d5120f --- /dev/null +++ b/Heron.MudCalendar/Components/WeekDropZone.razor @@ -0,0 +1,8 @@ +@using Microsoft.JSInterop +@using System.Globalization +@namespace Heron.MudCalendar +@inject IJSRuntime JsRuntime + + + @ChildContent + diff --git a/Heron.MudCalendar/Components/WeekDropZone.razor.cs b/Heron.MudCalendar/Components/WeekDropZone.razor.cs new file mode 100644 index 0000000..8b0f29a --- /dev/null +++ b/Heron.MudCalendar/Components/WeekDropZone.razor.cs @@ -0,0 +1,50 @@ +using Heron.MudCalendar.Services; +using Microsoft.AspNetCore.Components; +using MudBlazor.Utilities; + +namespace Heron.MudCalendar; + +public partial class WeekDropZone : IAsyncDisposable +{ + [CascadingParameter] + public MudCalendar Calendar { get; set; } = new(); + + private string _id = Guid.NewGuid().ToString(); + + private JsService? _jsService; + + [Parameter] + public RenderFragment? ChildContent { get; set; } + + [Parameter] + public CalendarItem? Item { get; set; } + + [Parameter] + public string? Style { get; set; } + + private string Classname => + new CssBuilder("mud-cal-week-drop-item") + .AddClass($"mud-cal-{_id}") + .Build(); + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + if (firstRender) + { + _jsService ??= new JsService(JsRuntime); + await _jsService.AddDragHandler($"mud-cal-{_id}"); + } + } + + public async ValueTask DisposeAsync() + { + GC.SuppressFinalize(this); + + if (_jsService != null) + { + await _jsService.DisposeAsync(); + } + } +} \ No newline at end of file diff --git a/Heron.MudCalendar/Extensions/EnumExtensions.cs b/Heron.MudCalendar/Extensions/EnumExtensions.cs new file mode 100644 index 0000000..4fad7ae --- /dev/null +++ b/Heron.MudCalendar/Extensions/EnumExtensions.cs @@ -0,0 +1,19 @@ +using System.ComponentModel; + +namespace Heron.MudCalendar.Extensions; + +public static class EnumExtensions +{ + public static string ToDescriptionString(this Enum value) + { + var field = value.GetType().GetField(value.ToString()); + if (field is null) + { + return value.ToString().ToLower(); + } + + return Attribute.GetCustomAttributes(field, typeof(DescriptionAttribute), false) is DescriptionAttribute[] { Length: > 0 } attributes + ? attributes[0].Description + : value.ToString().ToLower(); + } +} \ No newline at end of file diff --git a/Heron.MudCalendar/Heron.MudCalendar.csproj b/Heron.MudCalendar/Heron.MudCalendar.csproj index c33cfdf..e7f4897 100644 --- a/Heron.MudCalendar/Heron.MudCalendar.csproj +++ b/Heron.MudCalendar/Heron.MudCalendar.csproj @@ -56,17 +56,17 @@ - - + + - - + + - + @@ -161,17 +161,30 @@ - + + + + + + + + + + + + + - + + <_NewCompiledCssFiles Include="wwwroot/Heron.MudCalendar.min.css" Exclude="@(Content)" /> - <_NewCompiledJsFiles Include="wwwroot/Heron.MudCalendar.js" Exclude="@(Content)" /> + <_NewCompiledJsFiles Include="wwwroot/Heron.MudCalendar.min.js" Exclude="@(Content)" /> diff --git a/Heron.MudCalendar/Scripts/DragAndDrop.js b/Heron.MudCalendar/Scripts/DragAndDrop.js new file mode 100644 index 0000000..e421324 --- /dev/null +++ b/Heron.MudCalendar/Scripts/DragAndDrop.js @@ -0,0 +1,8 @@ +export function addDragHandler(id) { + if (document.getElementsByClassName(id).length === 0) return; + const dragZone = document.getElementsByClassName(id)[0]; + if (dragZone.children.length === 0) return; + const dragItem = dragZone.getElementsByClassName("mud-drop-item")[0]; + const xPos = dragItem.offsetWidth / 2; + document.getElementsByClassName(id)[0].addEventListener("dragstart", (e) => e.dataTransfer.setDragImage(dragItem, xPos, 18)); +} diff --git a/Heron.MudCalendar/Scripts/Resizer.js b/Heron.MudCalendar/Scripts/Resizer.js new file mode 100644 index 0000000..a1a0ab8 --- /dev/null +++ b/Heron.MudCalendar/Scripts/Resizer.js @@ -0,0 +1,60 @@ +export class Resizer { + + _obj; + _handle; + _intervalSize; + _item; + _startHeight; + _startY; + + constructor(handleId, intervalSize, obj) { + this._obj = obj; + this._handle = document.getElementById(handleId); + this._intervalSize = intervalSize; + this._item = this._handle.parentElement; + + this._handle.addEventListener("mousedown", this.onMouseDown); + } + + onMouseDown = (e) => { + e.stopPropagation(); + + this._startHeight = this._item.clientHeight; + this._startY = e.clientY; + + document.addEventListener("mouseup", this.onMouseUp); + document.addEventListener("mousemove", this.onMouseMove); + } + + onMouseUp = async () => { + document.removeEventListener("mouseup", this.onMouseUp); + document.removeEventListener("mousemove", this.onMouseMove); + + const newHeight = this.update(); + + await this._obj.invokeMethodAsync("ResizeFinished", newHeight); + } + + onMouseMove = (e) => { + this._position = e.clientY; + + this.update(); + } + + update() { + const movement = this._position - this._startY; + let height = this._startHeight + movement; + if (height < this._intervalSize) height = this._intervalSize; + + // Find closest interval + height = Math.round(height / this._intervalSize) * this._intervalSize; + + this._item.style.height = height + "px"; + + return height; + } +} + +export function newResizer(handleId, intervalSize, obj) { + return new Resizer(handleId, intervalSize, obj); +} \ No newline at end of file diff --git a/Heron.MudCalendar/wwwroot/Heron.MudCalendar.js b/Heron.MudCalendar/Scripts/Scroll.js similarity index 100% rename from Heron.MudCalendar/wwwroot/Heron.MudCalendar.js rename to Heron.MudCalendar/Scripts/Scroll.js diff --git a/Heron.MudCalendar/Services/JsService.cs b/Heron.MudCalendar/Services/JsService.cs index c7620eb..0d16c17 100644 --- a/Heron.MudCalendar/Services/JsService.cs +++ b/Heron.MudCalendar/Services/JsService.cs @@ -11,7 +11,7 @@ internal class JsService : IAsyncDisposable public JsService(IJSRuntime jsRuntime) { _moduleTask = new Lazy>(() => jsRuntime.InvokeAsync( - "import", "./_content/Heron.MudCalendar/Heron.MudCalendar.js").AsTask()); + "import", "./_content/Heron.MudCalendar/Heron.MudCalendar.min.js").AsTask()); } public async Task Scroll(ElementReference element, int top) @@ -19,7 +19,7 @@ public async Task Scroll(ElementReference element, int top) var module = await _moduleTask.Value; await module.InvokeVoidAsync("scroll", element, top); } - + public async Task GetHeadContent() { var module = await _moduleTask.Value; @@ -32,6 +32,12 @@ public async Task AddLink(string href, string rel) await module.InvokeVoidAsync("addLink", href, rel); } + public async Task AddDragHandler(string id) + { + var module = await _moduleTask.Value; + await module.InvokeVoidAsync("addDragHandler", id); + } + public async ValueTask DisposeAsync() { GC.SuppressFinalize(this); diff --git a/Heron.MudCalendar/Styles/Heron.MudCalendar.css b/Heron.MudCalendar/Styles/Heron.MudCalendar.css new file mode 100644 index 0000000..d76037f --- /dev/null +++ b/Heron.MudCalendar/Styles/Heron.MudCalendar.css @@ -0,0 +1,248 @@ +.mud-calendar { + color: var(--mud-palette-text-primary); + background-color: var(--mud-palette-surface); + border-radius: var(--mud-default-borderradius); + transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; + padding-top: 8px; + display: grid; + user-select: none; +} +.mud-calendar.mud-cal-square { + border-radius: 0; +} +.mud-calendar.mud-cal-outlined { + border: 1px solid var(--mud-palette-lines-default); +} +.mud-calendar table { + width: 100%; + height: 100%; + display: table; + border-spacing: 0; + border-collapse: collapse; + table-layout: fixed; +} +.mud-calendar table thead { + display: table-header-group; +} +.mud-calendar table thead th { + padding: 8px; + text-align: center; +} +.mud-calendar table tbody { + display: table-row-group; +} +.mud-calendar table tbody td { + border-right: 1px solid var(--mud-palette-table-lines); +} +.mud-calendar table * tr { + color: inherit; + display: table-row; + outline: 0; +} +.mud-calendar table * tr > td, .mud-calendar table * tr th { + display: table-cell; + font-size: 0.875rem; + font-weight: 400; + line-height: 1.43; + border-bottom: 1px solid var(--mud-palette-table-lines); + letter-spacing: 0.01071em; + vertical-align: inherit; +} +.mud-calendar table * tr > td:last-child, .mud-calendar table * tr th:last-child { + border-right: none; +} +.mud-calendar table * tr > th { + font-weight: 500; + line-height: 1.5rem; +} +.mud-calendar table tbody tr:last-child td { + border-bottom: none; +} +.mud-calendar .mud-picker { + display: inline; +} + +.mud-cal-toolbar { + display: flex; + justify-content: space-between; +} + +:root { + --mud-cal-cell-hover: color-mix(in srgb, var(--mud-palette-surface) 90%, black); +} + +.mud-cal-month-view { + height: 100%; +} + +.mud-cal-month-fixed-height .mud-cal-month-cell { + overflow-y: auto; +} + +.mud-cal-month-cell { + height: 100%; +} + +.mud-cal-month-cell-title { + padding: 8px; + position: sticky; + top: 0; + z-index: 1; + background-color: var(--mud-palette-surface); + transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; +} +.mud-cal-month-cell-title.mud-cal-month-outside { + color: var(--mud-palette-text-disabled); +} +.mud-cal-month-cell-title .mud-link { + color: inherit !important; + cursor: pointer; +} + +.mud-cal-month-link { + height: 100%; + width: 100%; + cursor: pointer; + transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; +} + +.mud-cal-month-link:hover { + background-color: var(--mud-cal-cell-hover); +} +.mud-cal-month-link:hover .mud-cal-month-cell-title { + background-color: var(--mud-cal-cell-hover); +} + +.mud-cal-month-dropzone { + height: 100%; + min-height: inherit; + overflow-y: scroll; +} + +.mud-cal-month-drop-ok { + background-color: var(--mud-cal-cell-hover); +} +.mud-cal-month-drop-ok .mud-cal-month-cell-title { + background-color: var(--mud-cal-cell-hover); +} + +.mud-cal-week-view { + height: 100%; +} +.mud-cal-week-view table { + border-collapse: separate; +} +.mud-cal-week-view table * tr > td { + border-bottom: none; +} + +.mud-cal-week-cell { + border-top: 1px solid var(--mud-palette-lines-default); + position: relative; +} +.mud-cal-week-cell.mud-cal-week-cell-half { + border-top: 1px solid var(--mud-palette-divider); +} + +.mud-cal-time-column { + width: 60px; +} + +.mud-cal-time-cell { + text-align: center; +} + +.mud-cal-week-day-holder { + height: 100%; + position: relative; +} + +.mud-cal-week-scroll { + display: block; + position: absolute; + height: 100%; + top: 0; + left: 0; + overflow-y: scroll; +} + +.mud-cal-week-layer { + display: block; + position: absolute; + height: 100%; + width: 100%; + left: 0; + top: 0; +} + +.mud-cal-week-cell-holder { + position: relative; + border: none; +} + +.mud-cal-week-link { + height: 100%; + width: 100%; + cursor: pointer; +} + +.mud-cal-week-link:hover { + background-color: rgba(0, 0, 0, 0.05); +} + +.mud-cal-week-cell-link { + cursor: pointer; + z-index: 100; +} + +.mud-cal-week-drop-item { + transition: none; +} + +.mud-cal-week-drop-item > .mud-drop-item { + height: 100%; + border: none; +} + +.mud-cal-week-drop-ok { + background-color: var(--mud-cal-cell-hover); +} + +.mud-cal-week-template-holder { + height: 100%; +} + +.mud-cal-resizer { + position: absolute; + bottom: 0; + width: 100%; + border-bottom: 10px solid transparent; + z-index: 1; + cursor: ns-resize; +} + +.mud-cal-cell-template { + width: 100%; + padding: 2px; + min-height: 36px; +} + +.mud-cal-week-view .mud-cal-cell-template { + height: 100%; +} + +.mud-cal-week-view .mud-cal-cell-template-chip { + height: 100%; +} + +.mud-cal-cell-template-chip { + width: 100%; + margin: 0; +} + +.mud-cal-clickable { + cursor: pointer; +} +.mud-cal-clickable .mud-chip { + cursor: inherit; +} \ No newline at end of file diff --git a/Heron.MudCalendar/Styles/_calendar.scss b/Heron.MudCalendar/Styles/_calendar.scss index 3074cda..60af28c 100644 --- a/Heron.MudCalendar/Styles/_calendar.scss +++ b/Heron.MudCalendar/Styles/_calendar.scss @@ -5,6 +5,7 @@ transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; padding-top: 8px; display: grid; + user-select: none; &.mud-cal-square { border-radius: 0; diff --git a/Heron.MudCalendar/Styles/_monthView.scss b/Heron.MudCalendar/Styles/_monthView.scss index 62b88fc..1719cb9 100644 --- a/Heron.MudCalendar/Styles/_monthView.scss +++ b/Heron.MudCalendar/Styles/_monthView.scss @@ -1,3 +1,7 @@ +:root { + --mud-cal-cell-hover: color-mix(in srgb, var(--mud-palette-surface) 90%, black); +} + .mud-cal-month-view { height: 100%; } @@ -10,12 +14,15 @@ .mud-cal-month-cell { height: 100%; - display: flex; - flex-direction: column; } .mud-cal-month-cell-title { padding: 8px; + position: sticky; + top: 0; + z-index: 1; + background-color: var(--mud-palette-surface); + transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; &.mud-cal-month-outside { color: var(--mud-palette-text-disabled); @@ -27,16 +34,31 @@ } } -.mud-cal-month-cell-events { - overflow-y: scroll; -} - .mud-cal-month-link { height: 100%; width: 100%; cursor: pointer; + transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; } .mud-cal-month-link:hover { - background-color: rgba(0, 0, 0, 0.05); + background-color: var(--mud-cal-cell-hover); + + .mud-cal-month-cell-title { + background-color: var(--mud-cal-cell-hover); + } +} + +.mud-cal-month-dropzone { + height: 100%; + min-height: inherit; + overflow-y: scroll; +} + +.mud-cal-month-drop-ok { + background-color: var(--mud-cal-cell-hover); + + .mud-cal-month-cell-title { + background-color: var(--mud-cal-cell-hover); + } } \ No newline at end of file diff --git a/Heron.MudCalendar/Styles/_weekView.scss b/Heron.MudCalendar/Styles/_weekView.scss index d88b972..05e4b24 100644 --- a/Heron.MudCalendar/Styles/_weekView.scss +++ b/Heron.MudCalendar/Styles/_weekView.scss @@ -2,6 +2,8 @@ height: 100%; table { + border-collapse: separate; + * tr { > td { border-bottom: none; @@ -12,6 +14,7 @@ .mud-cal-week-cell { border-top: 1px solid var(--mud-palette-lines-default); + position: relative; &.mud-cal-week-cell-half { border-top: 1px solid var(--mud-palette-divider); @@ -51,6 +54,7 @@ .mud-cal-week-cell-holder { position: relative; + border: none; } .mud-cal-week-link { @@ -67,3 +71,29 @@ cursor: pointer; z-index: 100; } + +.mud-cal-week-drop-item { + transition: none; +} + +.mud-cal-week-drop-item > .mud-drop-item { + height: 100%; + border: none; +} + +.mud-cal-week-drop-ok { + background-color: var(--mud-cal-cell-hover); +} + +.mud-cal-week-template-holder { + height: 100%; +} + +.mud-cal-resizer { + position: absolute; + bottom: 0; + width: 100%; + border-bottom: 10px solid transparent; + z-index: 1; + cursor: ns-resize; +} \ No newline at end of file diff --git a/Heron.MudCalendar/excubowebcompiler.json b/Heron.MudCalendar/excubowebcompiler.json index a28ced4..cabc0ad 100644 --- a/Heron.MudCalendar/excubowebcompiler.json +++ b/Heron.MudCalendar/excubowebcompiler.json @@ -10,7 +10,7 @@ "IndentSize": 2 }, "Javascript": { - "RenameLocals": true, + "RenameLocals": false, "PreserveImportantComments": true, "EvalTreatment": "Ignore", "TermSemicolons": true, @@ -42,15 +42,14 @@ "Sass": { "IndentType": "Space", "IndentWidth": 2, - "OutputStyle": "Nested", - "Precision": 5, + "OutputStyle": "Expanded", "RelativeUrls": true, "LineFeed": "Lf", "SourceMap": false } }, "Output": { - "Preserve": false, + "Preserve": true, "Directory": "./wwwroot" } -} \ No newline at end of file +} diff --git a/Heron.MudCalendarWithDocs.sln b/Heron.MudCalendarWithDocs.sln index de62dc6..7ca9401 100644 --- a/Heron.MudCalendarWithDocs.sln +++ b/Heron.MudCalendarWithDocs.sln @@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Heron.MudCalendar.UnitTests EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Heron.MudCalendar.UnitTests.Viewer", "Heron.MudCalendar.UnitTests.Viewer\Heron.MudCalendar.UnitTests.Viewer.csproj", "{1758F5B2-7F14-4E61-80DC-845D7E6EE208}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Heron.MudCalendar.UnitTests.Viewer.Server", "Heron.MudCalendar.UnitTests.Viewer.Server\Heron.MudCalendar.UnitTests.Viewer.Server.csproj", "{B27514EB-09BD-4534-BBE8-5FAAF8FEF204}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,5 +32,9 @@ Global {1758F5B2-7F14-4E61-80DC-845D7E6EE208}.Debug|Any CPU.Build.0 = Debug|Any CPU {1758F5B2-7F14-4E61-80DC-845D7E6EE208}.Release|Any CPU.ActiveCfg = Release|Any CPU {1758F5B2-7F14-4E61-80DC-845D7E6EE208}.Release|Any CPU.Build.0 = Release|Any CPU + {B27514EB-09BD-4534-BBE8-5FAAF8FEF204}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B27514EB-09BD-4534-BBE8-5FAAF8FEF204}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B27514EB-09BD-4534-BBE8-5FAAF8FEF204}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B27514EB-09BD-4534-BBE8-5FAAF8FEF204}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal From c4736b290800f0d7ffd2bb4a8583645e6855d15c Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Wed, 15 Nov 2023 10:21:28 +0100 Subject: [PATCH 10/11] Added CurrentDayChanged event --- .../Calendar/CalendarEventsTest.razor | 66 ++++++++++++++----- .../Components/CalendarTests.cs | 26 +++++++- .../Components/MudCalendar.razor.cs | 35 +++++++--- 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarEventsTest.razor b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarEventsTest.razor index f040bb4..6ba8665 100644 --- a/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarEventsTest.razor +++ b/Heron.MudCalendar.UnitTests.Viewer/TestComponents/Calendar/CalendarEventsTest.razor @@ -1,36 +1,66 @@ - + - - - +
+ + + + Time Start Date End Date - - - - @foreach (var item in _events) - { + + + + @foreach (var item in _dateRangeEvents) + { + + @foreach (var x in item.Split()) + { + @x + } + + } + + + + + - @foreach (var x in item.Split()) - { - @x - } + Time + Date - } - - + + + @foreach (var item in _currentDayEvents) + { + + @foreach (var x in item.Split()) + { + @x + } + + } + + + +
@code { public static string __description__ = "Calendar Event Tests"; - private readonly List _events = new(); + private readonly List _dateRangeEvents = new(); + private readonly List _currentDayEvents = new(); private void DateRangeChanged(DateRange dateRange) { var start = dateRange.Start.HasValue ? dateRange.Start.Value.Date.ToShortDateString() : string.Empty; var end = dateRange.End.HasValue ? dateRange.End.Value.Date.ToShortDateString() : string.Empty; - _events.Add($"{DateTime.Now.ToLongTimeString()} {start} {end}"); + _dateRangeEvents.Add($"{DateTime.Now.ToLongTimeString()} {start} {end}"); + } + + private void CurrentDayChanged(DateTime date) + { + _currentDayEvents.Add($"{DateTime.Now.ToLongTimeString()} {date}"); } } \ No newline at end of file diff --git a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs index a8286dc..4b3445d 100644 --- a/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs +++ b/Heron.MudCalendar.UnitTests/Components/CalendarTests.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using FluentAssertions; using Heron.MudCalendar.UnitTests.Viewer.TestComponents.Calendar; using MudBlazor; @@ -337,10 +338,31 @@ public void DateChangedEvent() var cut = Context.RenderComponent(); var comp = cut.FindComponent(); - var table = cut.Find("tbody.events-table"); - table.Children.Length.Should().Be(1); + comp.SetParam(x => x.CurrentDay, new DateTime(2023, 1, 1)); + + var table = cut.Find("tbody.daterange-events-table"); + table.Children.Length.Should().Be(2); comp.FindAll("button.mud-icon-button")[1].Click(); + table.Children.Length.Should().Be(3); + } + + [Test] + public void CurrentDayChangedEvent() + { + var cut = Context.RenderComponent(); + var comp = cut.FindComponent(); + + comp.SetParam(x => x.CurrentDay, new DateTime(2023, 1, 1)); + + var table = cut.Find("tbody.currentday-events-table"); + table.Children.Length.Should().Be(0); + + comp.FindAll("button.mud-icon-button")[1].Click(); + table.Children.Length.Should().Be(1); + + var picker = cut.FindComponent(); + picker.SetParam(p => p.Date!, new DateTime(2023, 1, 2)); table.Children.Length.Should().Be(2); } diff --git a/Heron.MudCalendar/Components/MudCalendar.razor.cs b/Heron.MudCalendar/Components/MudCalendar.razor.cs index c8154ed..604940b 100644 --- a/Heron.MudCalendar/Components/MudCalendar.razor.cs +++ b/Heron.MudCalendar/Components/MudCalendar.razor.cs @@ -207,6 +207,12 @@ public partial class MudCalendar : MudComponentBase ///
[Parameter] public EventCallback DateRangeChanged { get; set; } + + /// + /// Called when the current day changes. + /// + [Parameter] + public EventCallback CurrentDayChanged { get; set; } /// /// Called when an item is changed, for example by dragging or resizing the item. @@ -329,7 +335,7 @@ protected virtual Task OnViewChanging(CalendarView view) /// Method invoked when the user clicks the next button. /// /// - protected virtual Task OnNextClicked() + protected virtual async Task OnNextClicked() { CurrentDay = View switch { @@ -339,14 +345,16 @@ protected virtual Task OnNextClicked() _ => CurrentDay }; - return ChangeDateRange(); + await CurrentDayChanged.InvokeAsync(CurrentDay); + + await ChangeDateRange(); } /// /// Method invoked when the user clicks the previous button. /// /// - protected virtual Task OnPreviousClicked() + protected virtual async Task OnPreviousClicked() { CurrentDay = View switch { @@ -355,19 +363,25 @@ protected virtual Task OnPreviousClicked() CalendarView.Month => CurrentDay.AddMonths(-1), _ => CurrentDay }; + + await CurrentDayChanged.InvokeAsync(CurrentDay); - return ChangeDateRange(); + await ChangeDateRange(); } /// /// Method invoked when the user clicks the today button. /// /// - protected virtual Task OnTodayClicked() + protected virtual async Task OnTodayClicked() { + if (CurrentDay == DateTime.Today) return; + CurrentDay = DateTime.Today; - return ChangeDateRange(); + await CurrentDayChanged.InvokeAsync(CurrentDay); + + await ChangeDateRange(); } protected string DrawTodayText() @@ -395,10 +409,15 @@ private async Task SetLinks() await _jsService.AddLink("_content/Heron.MudCalendar/Heron.MudCalendar.min.css", "stylesheet"); } - private Task DatePickerDateChanged(DateTime? dateTime) + private async Task DatePickerDateChanged(DateTime? dateTime) { + var dateChanged = dateTime.HasValue && dateTime != CurrentDay; + PickerDate = dateTime; - return ChangeDateRange(new CalendarDateRange(dateTime ?? DateTime.Today, View)); + + if (dateChanged) await CurrentDayChanged.InvokeAsync(CurrentDay); + + await ChangeDateRange(new CalendarDateRange(dateTime ?? DateTime.Today, View)); } private void OnDatePickerOpened() From cbdaaa51ce821e88eac9521e6186809e54f0f0df Mon Sep 17 00:00:00 2001 From: Dan Heron Date: Thu, 16 Nov 2023 14:36:37 +0100 Subject: [PATCH 11/11] Added loading message to docs project --- Heron.MudCalendar.Docs/wwwroot/index.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Heron.MudCalendar.Docs/wwwroot/index.html b/Heron.MudCalendar.Docs/wwwroot/index.html index 00c4737..cd894d3 100644 --- a/Heron.MudCalendar.Docs/wwwroot/index.html +++ b/Heron.MudCalendar.Docs/wwwroot/index.html @@ -13,7 +13,14 @@ -
Loading...
+
+
+
+

Heron.MudCalendar

+

Loading...

+
+
+
An unhandled error has occurred.