Skip to content

Commit

Permalink
Merge pull request #25 from valincius/3.1.0
Browse files Browse the repository at this point in the history
3.1.0
  • Loading branch information
valincius committed Oct 21, 2021
2 parents b463da5 + c5fffb4 commit 3484bae
Show file tree
Hide file tree
Showing 44 changed files with 1,545 additions and 95 deletions.
6 changes: 6 additions & 0 deletions BlazorScheduler.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorScheduler", "BlazorSc
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DemoApp", "DemoApp\DemoApp.csproj", "{5FA9FE4D-C4C7-4A49-A10B-5B84E15D33E7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorServerDemoApp", "BlazorServerDemoApp\BlazorServerDemoApp.csproj", "{BAE2506B-3C6D-4F32-984E-03F9E074F491}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +23,10 @@ Global
{5FA9FE4D-C4C7-4A49-A10B-5B84E15D33E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FA9FE4D-C4C7-4A49-A10B-5B84E15D33E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FA9FE4D-C4C7-4A49-A10B-5B84E15D33E7}.Release|Any CPU.Build.0 = Release|Any CPU
{BAE2506B-3C6D-4F32-984E-03F9E074F491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAE2506B-3C6D-4F32-984E-03F9E074F491}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAE2506B-3C6D-4F32-984E-03F9E074F491}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAE2506B-3C6D-4F32-984E-03F9E074F491}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 1 addition & 1 deletion BlazorScheduler/BlazorScheduler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl></PackageProjectUrl>
<RepositoryUrl>https://github.com/valincius/BlazorScheduler</RepositoryUrl>
<Version>3.0.0</Version>
<Version>3.1.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
8 changes: 7 additions & 1 deletion BlazorScheduler/Components/Scheduler.razor
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,17 @@
</div>
<CascadingValue IsFixed="true" Value="this">
@Appointments
@if (_showNewAppointment)
{
<Appointment @ref="NewAppointment" Start="_newAppointmentStart" End="_newAppointmentEnd" Color="@Config.ThemeColor">
New Appointment
</Appointment>
}

@foreach (var week in GetDaysInRange().Chunk(7))
{
var (start, end) = (week.First(), week.Last());
<SchedulerWeek Start="start" End="end" Appointments="GetAppointments(start, end)" />
<SchedulerWeek Start="start" End="end" Appointments="GetAppointmentsInRange(start, end)" @key="week" />
}
</CascadingValue>
</div>
Expand Down
68 changes: 30 additions & 38 deletions BlazorScheduler/Components/Scheduler.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
using BlazorScheduler.Internal.Extensions;
using BlazorScheduler.Configuration;
using BlazorScheduler.Internal.Components;
using System.Collections.ObjectModel;

namespace BlazorScheduler
{
public partial class Scheduler
public partial class Scheduler : IDisposable
{
[Parameter] public RenderFragment Appointments { get; set; }
[Parameter] public RenderFragment<Scheduler> HeaderTemplate { get; set; }
Expand All @@ -25,8 +26,6 @@ public partial class Scheduler
public DateTime CurrentDate { get; private set; }
public Appointment NewAppointment { get; private set; }

internal event EventHandler OnInvalidate = delegate { };

private string MonthDisplay
{
get
Expand All @@ -40,16 +39,18 @@ private string MonthDisplay
}
}

private readonly HashSet<Appointment> _appointments = new();
private readonly ObservableCollection<Appointment> _appointments = new();
private DotNetObjectReference<Scheduler> _objReference;
private DateTime _draggingAppointmentAnchor;
private bool _doneDragging = false;
private bool _loading = false;

public bool _showNewAppointment;
private DateTime _draggingAppointmentAnchor;
private DateTime _newAppointmentStart, _newAppointmentEnd;

protected override async Task OnInitializedAsync()
{
_objReference = DotNetObjectReference.Create(this);
await SetCurrentMonth(DateTime.Today);
await SetCurrentMonth(DateTime.Today, true);

await base.OnInitializedAsync();
}
Expand All @@ -75,10 +76,13 @@ internal void RemoveAppointment(Appointment appointment)
StateHasChanged();
}

public async Task SetCurrentMonth(DateTime date)
public async Task SetCurrentMonth(DateTime date, bool skipJsInvoke = false)
{
CurrentDate = date;
await AttachMouseHandler();
if (!skipJsInvoke)
{
await AttachMouseHandler();
}
var (start, end) = GetDateRangeForCurrentMonth();
if (OnRequestNewData != null)
{
Expand All @@ -90,12 +94,6 @@ public async Task SetCurrentMonth(DateTime date)
StateHasChanged();
}

public void Invalidate()
{
OnInvalidate(this, new EventArgs());
StateHasChanged();
}

private async Task AttachMouseHandler()
{
await jsRuntime.InvokeVoidAsync("attachSchedulerMouseEventsHandler", _objReference);
Expand Down Expand Up @@ -123,31 +121,20 @@ private IEnumerable<DateTime> GetDaysInRange()
.Select(offset => start.AddDays(offset));
}

private IEnumerable<Appointment> GetAppointments(DateTime start, DateTime end)
private IEnumerable<Appointment> GetAppointmentsInRange(DateTime start, DateTime end)
{
var appointmentsInTimeframe = _appointments.Where(x => (start, end).Overlaps((x.Start, x.End))).ToList();
if (NewAppointment is not null && (start, end).Overlaps((NewAppointment.Start, NewAppointment.End)))
{
appointmentsInTimeframe.Add(NewAppointment);
}

var appointmentsInTimeframe = _appointments.Where(x => (start, end).Overlaps((x.Start, x.End)));
return appointmentsInTimeframe
.OrderBy(x => x.Start)
.ThenByDescending(x => (x.End - x.Start).Days);
}

public void BeginDrag(SchedulerDay day)
{
NewAppointment = new Appointment
{
ChildContent = new RenderFragment(builder => builder.AddContent(0, "New appointment")),
Start = day.Day,
End = day.Day,
Color = Config.ThemeColor
};
_doneDragging = false;

_draggingAppointmentAnchor = NewAppointment.Start;
_newAppointmentStart = _newAppointmentEnd = day.Day;
_showNewAppointment = true;

_draggingAppointmentAnchor = _newAppointmentStart;
StateHasChanged();
}

Expand All @@ -156,11 +143,10 @@ public async Task OnMouseUp(int button)
{
if (button == 0)
{
if (NewAppointment is not null && !_doneDragging)
if (_showNewAppointment)
{
_doneDragging = true;
await OnAddingNewAppointment?.Invoke(NewAppointment.Start, NewAppointment.End);
NewAppointment = default;
_showNewAppointment = false;
await OnAddingNewAppointment?.Invoke(_newAppointmentStart, _newAppointmentEnd);
StateHasChanged();
}
}
Expand All @@ -169,12 +155,18 @@ public async Task OnMouseUp(int button)
[JSInvokable]
public void OnMouseMove(string date)
{
if (NewAppointment is not null && !_doneDragging)
if (_showNewAppointment)
{
var day = DateTime.ParseExact(date, "yyyyMMdd", null);
(NewAppointment.Start, NewAppointment.End) = day < _draggingAppointmentAnchor ? (day, _draggingAppointmentAnchor) : (_draggingAppointmentAnchor, day);
(_newAppointmentStart, _newAppointmentEnd) = day < _draggingAppointmentAnchor ? (day, _draggingAppointmentAnchor) : (_draggingAppointmentAnchor, day);
StateHasChanged();
}
}

public void Dispose()
{
_objReference.Dispose();
GC.SuppressFinalize(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;

namespace BlazorScheduler.Internal.Components
Expand Down
17 changes: 2 additions & 15 deletions BlazorScheduler/Internal/Components/SchedulerDay.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace BlazorScheduler.Internal.Components
{
public partial class SchedulerDay : IDisposable
public partial class SchedulerDay
{
[CascadingParameter] public Scheduler Scheduler { get; set; }

Expand All @@ -23,20 +23,7 @@ private IEnumerable<string> Classes
yield return "diff-month";
}
}

protected override void OnInitialized()
{
Scheduler.OnInvalidate += Invalidate;
}

public void Dispose()
{
Scheduler.OnInvalidate -= Invalidate;
GC.SuppressFinalize(this);
}

private void Invalidate(object sender, EventArgs e) => StateHasChanged();


private void OnMouseDown(MouseEventArgs e)
{
if (e.Button == 0 && !Scheduler.Config.DisableDragging)
Expand Down
35 changes: 17 additions & 18 deletions BlazorScheduler/Internal/Components/SchedulerWeek.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,42 @@
<div class="days">
@for (var dt = Start; dt <= End; dt = dt.AddDays(1))
{
<SchedulerDay Day="dt"/>
<SchedulerDay Day="dt" @key="dt" />
}
</div>
<div class="appointments">
@foreach (var (appointment, order) in Orderings)
@foreach (var (appointment, order) in _orderings)
{
int maxOrderOfSpan = Orderings.Where(x => (x.Key.Start.Date, x.Key.End.Date).Overlaps((appointment.Start.Date, appointment.End.Date))).Max(x => (int?)x.Value) ?? 0;
if (order < MaxNumOfAppointmentsPerDay
|| (order == MaxNumOfAppointmentsPerDay && maxOrderOfSpan <= MaxNumOfAppointmentsPerDay)
|| ReferenceEquals(appointment, Scheduler.NewAppointment))
int maxOrderOfSpan = _orderings
.Where(x => (x.Key.Start.Date, x.Key.End.Date).Overlaps((appointment.Start.Date, appointment.End.Date)))
.Max(x => (int?)x.Value) ?? 0;
if (order < _maxNumOfAppointmentsPerDay || (order == _maxNumOfAppointmentsPerDay && maxOrderOfSpan <= _maxNumOfAppointmentsPerDay))
{
bool isTimedAppointment = appointment.Start.Date == appointment.End.Date && appointment.Start != appointment.End;
if (isTimedAppointment)
{
<SchedulerAppointment Appointment="appointment" Order="order" />
<SchedulerAppointment Appointment="appointment" Order="order" @key="appointment" />
}
else
{
var (start, end) = GetStartAndEndDayForAppointment(appointment);
<SchedulerAllDayAppointment Appointment="appointment" Order="order" Start="start" End="end" />
var (start, end) = _startsAndEnds[appointment];
<SchedulerAllDayAppointment Appointment="appointment" Order="order" Start="start" End="end" @key="appointment" />
}
}
}
@for (var dt = Start; dt <= End; dt = dt.AddDays(1))
{
var todaysAppointments = Orderings.Where(x => dt.Between(x.Key.Start.Date, x.Key.End.Date));
var todaysAppointments = _orderings.Where(x => dt.Between(x.Key.Start.Date, x.Key.End.Date));
int maxOrder = todaysAppointments.Max(x => (int?)x.Value) ?? 0;
if (maxOrder > MaxNumOfAppointmentsPerDay)
if (maxOrder > _maxNumOfAppointmentsPerDay)
{
var overflowAppointments = todaysAppointments
.Where(x => x.Value > MaxNumOfAppointmentsPerDay - 1)
.Select(x => x.Key).ToList().AsReadOnly();
<SchedulerAppointmentOverflow
Day="dt"
AppointmentCount="overflowAppointments.Count()"
var numOverFlowAppointments = todaysAppointments
.Count(x => x.Value > _maxNumOfAppointmentsPerDay - 1);
<SchedulerAppointmentOverflow Day="dt"
AppointmentCount="numOverFlowAppointments"
Start="(dt.DayOfWeek - Scheduler.Config.StartDayOfWeek + 7) % 7"
Order="MaxNumOfAppointmentsPerDay" />
Order="_maxNumOfAppointmentsPerDay"
@key="dt" />
}
}
</div>
Expand Down
30 changes: 16 additions & 14 deletions BlazorScheduler/Internal/Components/SchedulerWeek.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,25 @@ public partial class SchedulerWeek
[Parameter] public DateTime End { get; set; }
[Parameter] public IEnumerable<Appointment> Appointments { get; set; }

private readonly Dictionary<Appointment, int> Orderings = new();
private int MaxNumOfAppointmentsPerDay => Scheduler.Config.MaxVisibleAppointmentsPerDay;
private readonly Dictionary<Appointment, int> _orderings = new();
private readonly Dictionary<Appointment, (int, int)> _startsAndEnds = new();
private int _maxNumOfAppointmentsPerDay => Scheduler.Config.MaxVisibleAppointmentsPerDay;

protected override void OnInitialized()
{
foreach (var app in Appointments)
{
_startsAndEnds[app] = GetStartAndEndDayForAppointment(app);
}
base.OnInitialized();
}

protected override void OnParametersSet()
{
Orderings.Clear();
_orderings.Clear();
foreach (var app in Appointments)
{
Orderings[app] = GetBestOrderingForAppointment(app);
_orderings[app] = GetBestOrderingForAppointment(app);
}

base.OnParametersSet();
Expand All @@ -49,16 +59,8 @@ protected override void OnParametersSet()

private int GetBestOrderingForAppointment(Appointment appointment)
{
if (ReferenceEquals(appointment, Scheduler.NewAppointment))
{
return -1;
}

return Orderings
.Where(x => {
return GetStartAndEndDayForAppointment(appointment).Overlaps(GetStartAndEndDayForAppointment(x.Key))
&& !ReferenceEquals(x.Key, Scheduler.NewAppointment);
})
return _orderings
.Where(x => _startsAndEnds[appointment].Overlaps(_startsAndEnds[x.Key]))
.OrderBy(x => x.Value)
.TakeWhile((x, i) => x.Value == ++i)
.LastOrDefault().Value + 1;
Expand Down
10 changes: 10 additions & 0 deletions BlazorServerDemoApp/App.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
11 changes: 11 additions & 0 deletions BlazorServerDemoApp/BlazorServerDemoApp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\BlazorScheduler\BlazorScheduler.csproj" />
</ItemGroup>

</Project>
15 changes: 15 additions & 0 deletions BlazorServerDemoApp/Data/WeatherForecast.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace BlazorServerDemoApp.Data
{
public class WeatherForecast
{
public DateTime Date { get; set; }

public int TemperatureC { get; set; }

public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

public string Summary { get; set; }
}
}

0 comments on commit 3484bae

Please sign in to comment.