Skip to content

Commit

Permalink
Added drag support for mobile devices.
Browse files Browse the repository at this point in the history
  • Loading branch information
V45370 committed Feb 27, 2024
1 parent 6103d31 commit 56e8064
Show file tree
Hide file tree
Showing 18 changed files with 579 additions and 53 deletions.
6 changes: 3 additions & 3 deletions Radzen.Blazor/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public static IServiceCollection AddRadzenComponents(this IServiceCollection ser
return services;
}
}

/// <summary>
/// Month enum
/// </summary>
Expand Down Expand Up @@ -560,9 +560,9 @@ public class GoogleMapClickEventArgs
}

/// <summary>
/// Supplies information about a <see cref="ViewBase.AppointmentMove" /> event that is being raised.
/// Supplies information about a <see cref="DropableViewBase.AppointmentMove" /> event that is being raised.
/// </summary>
public class AppointmentMoveEventArgs
public class SchedulerAppointmentMoveEventArgs
{
/// <summary>
/// Gets or sets the appointment data.
Expand Down
5 changes: 5 additions & 0 deletions Radzen.Blazor/IScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ namespace Radzen.Blazor
/// </summary>
public interface IScheduler
{
/// <summary>
/// Gets or sets the appointment move event callback.
/// </summary>
/// <value>The appointment move event callback.</value>
EventCallback<SchedulerAppointmentMoveEventArgs> AppointmentMove { get; set; }
/// <summary>
/// Gets the appointments in the specified range.
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions Radzen.Blazor/ISchedulerView.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;

namespace Radzen.Blazor
Expand Down Expand Up @@ -49,5 +50,11 @@ public interface ISchedulerView
/// Gets the end date.
/// </summary>
DateTime EndDate { get; }
/// <summary>
/// Handles appointent move event.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
Task OnAppointmentMove(SchedulerAppointmentMoveEventArgs data);
}
}
4 changes: 2 additions & 2 deletions Radzen.Blazor/RadzenDayView.razor
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
{
var appointments = Scheduler.GetAppointmentsInRange(StartDate, EndDate).ToList();

return
return
@<CascadingValue Value=@Scheduler>
<DayView StartDate=@StartDate EndDate=@EndDate StartTime=@StartTime EndTime=@EndTime Appointments=@appointments
TimeFormat=@TimeFormat MinutesPerSlot=@MinutesPerSlot AppointmentMove=@OnAppointmentMove />
TimeFormat=@TimeFormat MinutesPerSlot=@MinutesPerSlot AppointmentMove=@OnAppointmentMove />
</CascadingValue>
;
}
Expand Down
26 changes: 26 additions & 0 deletions Radzen.Blazor/RadzenScheduler.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,32 @@ public partial class RadzenScheduler<TItem> : RadzenComponent, IScheduler
[Parameter]
public EventCallback<SchedulerLoadDataEventArgs> LoadData { get; set; }

/// <summary>
/// A callback that will be invoked when an appointment is being dragged and then dropped on a different slot.
/// Commonly used to change it to a different timeslot.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenScheduler Data=@appointments AppointmentMove=@OnAppointmentMove&gt;
/// &lt;/RadzenScheduler&gt;
/// @code {
/// async Task OnAppointmentMove(SchedulerAppointmentMoveEventArgs moved)
/// {
/// var draggedAppointment = appointments.SingleOrDefault(x => x == (Appointment)moved.Appointment.Data);
/// if (draggedAppointment != null)
/// {
/// draggedAppointment.Start = draggedAppointment.Start + moved.TimeSpan;
/// draggedAppointment.End = draggedAppointment.End + moved.TimeSpan;
/// await scheduler.Reload();
/// }
/// }
/// }
/// </code>
/// </example>
/// <value></value>
[Parameter]
public EventCallback<SchedulerAppointmentMoveEventArgs> AppointmentMove { get; set; }

IList<ISchedulerView> Views { get; set; } = new List<ISchedulerView>();

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion Radzen.Blazor/RadzenYearPlannerView.razor
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
StartMonth=@StartMonth
MaxAppointmentsInSlot=@maxAppointmentsInSlot
MoreText=@MoreText
Appointments=@appointments />
Appointments=@appointments
AppointmentMove=@OnAppointmentMove />
</CascadingValue>;
}
}
3 changes: 2 additions & 1 deletion Radzen.Blazor/RadzenYearTimelineView.razor
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
StartMonth=@StartMonth
MaxAppointmentsInSlot=@maxAppointmentsInSlot
MoreText=@MoreText
Appointments=@appointments />
Appointments=@appointments
AppointmentMove=@OnAppointmentMove />
</CascadingValue>;
}
}
2 changes: 1 addition & 1 deletion Radzen.Blazor/Rendering/Appointment.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@using Radzen.Blazor
@using Radzen.Blazor.Rendering

<div @ref=@element class="@($"{"rz-event"} {CssClass}".Trim())" draggable="true" style=@Style @onclick=@OnClick @onmouseenter=@OnMouseEnter @onmouseleave=@OnMouseLeave @ondragstart=@OnDragStart>
<div @ref=@element class="@($"{"rz-event"} {CssClass}".Trim())" draggable="true" style=@Style @onclick=@OnClick @onmouseenter=@OnMouseEnter @onmouseleave=@OnMouseLeave @ondragstart=@OnDragStart @ontouchstart=@OnDragStart >
<div class="rz-event-content" title=@Title @attributes=@Attributes>
@if (ShowAppointmentContent)
{
Expand Down
7 changes: 4 additions & 3 deletions Radzen.Blazor/Rendering/DayView.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@using Radzen.Blazor
@inherits ViewBase
@inherits DropableViewBase

<div class="rz-view rz-day-view">
<div class="rz-view-header">
Expand All @@ -16,7 +16,7 @@
@for (var date = StartDate; date < EndDate; date = date.AddMinutes(MinutesPerSlot))
{
var slotDate = date;
<div @onclick=@(args => OnSlotClick(slotDate)) @attributes=@Attributes(date) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(slotDate))></div>
<div @onclick=@(args => OnSlotClick(slotDate)) @attributes=@Attributes(date) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(slotDate)) @ontouchend='@(args => @OnDrop(slotDate))'></div>
}
</div>
</div>
Expand Down Expand Up @@ -67,7 +67,8 @@
IDictionary<string, object> Attributes(DateTime date)
{
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(MinutesPerSlot));
attributes["class"] = ClassList.Create("rz-slot dropzone").Add("rz-slot-minor", (date.Minute / MinutesPerSlot) % 2 == 1).Add(attributes).ToString();
attributes["class"] = ClassList.Create("rz-slot").Add("rz-slot-minor", (date.Minute / MinutesPerSlot) % 2 == 1).Add(attributes).ToString();
attributes["dropzone"] = "move";
return attributes;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace Radzen.Blazor.Rendering
{
/// <summary>
/// A base class for <see cref="MonthView" /> <see cref="DayView" /> <see cref="WeekView" /> views.
/// A base class for <see cref="MonthView" /> <see cref="DayView" /> <see cref="WeekView" /> <see cref="YearPlannerView" /> <see cref="YearTimelineView" /> views.
/// </summary>
public abstract class ViewBase : ComponentBase
public abstract class DropableViewBase : ComponentBase
{
private bool dragStarted = false;
private AppointmentData draggedAppointment;
Expand All @@ -16,7 +16,7 @@ public abstract class ViewBase : ComponentBase
/// </summary>
/// <value>The appointment move event callback.</value>
[Parameter]
public EventCallback<AppointmentMoveEventArgs> AppointmentMove { get; set; }
public EventCallback<SchedulerAppointmentMoveEventArgs> AppointmentMove { get; set; }

/// <summary>
/// Handles on slot drop.
Expand All @@ -25,9 +25,13 @@ public abstract class ViewBase : ComponentBase
/// <returns>Task</returns>
public async Task OnDrop(DateTime slotDate)
{
if(draggedAppointment != null)
{
TimeSpan timespan = slotDate - draggedAppointment.Start;
await AppointmentMove.InvokeAsync(new SchedulerAppointmentMoveEventArgs() { Appointment = draggedAppointment, TimeSpan = timespan });
draggedAppointment = null;
}
dragStarted = false;
TimeSpan timespan = slotDate - draggedAppointment.Start;
await AppointmentMove.InvokeAsync(new AppointmentMoveEventArgs() { Appointment = draggedAppointment, TimeSpan = timespan });
}

/// <summary>
Expand Down
25 changes: 13 additions & 12 deletions Radzen.Blazor/Rendering/MonthView.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@using Radzen.Blazor
@using Radzen.Blazor.Rendering
@inject DialogService DialogService
@inherits ViewBase
@inherits DropableViewBase


<div class="rz-view rz-month-view">
Expand Down Expand Up @@ -115,7 +115,8 @@
IDictionary<string, object> Attributes(DateTime start)
{
var attributes = Scheduler.GetSlotAttributes(start, start.AddDays(1));
attributes["class"] = ClassList.Create("rz-slot dropzone").Add(attributes).ToString();
attributes["class"] = ClassList.Create("rz-slot").Add(attributes).ToString();
attributes["dropzone"] = "move";
return attributes;
}

Expand Down Expand Up @@ -177,16 +178,16 @@

if (!preventDefault)
{
await DialogService.OpenAsync(date.ToShortDateString(), ds =>
@<div class="rz-event-list">
<CascadingValue Value=@Scheduler>
@foreach(var item in appointments)
{
<Appointment Data=@item Click="OnListEventClick" />
}
</CascadingValue>
</div>
);
await DialogService.OpenAsync(date.ToShortDateString(), ds =>
@<div class="rz-event-list">
<CascadingValue Value=@Scheduler>
@foreach(var item in appointments)
{
<Appointment Data=@item Click="OnListEventClick" />
}
</CascadingValue>
</div>
);
}
}

Expand Down
9 changes: 5 additions & 4 deletions Radzen.Blazor/Rendering/WeekView.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@using Radzen.Blazor
@using Microsoft.JSInterop
@inherits ViewBase
@inherits DropableViewBase
@inject IJSRuntime JSRuntime

<div class="rz-view rz-week-view">
Expand All @@ -21,12 +21,12 @@
{
var start = day.Add(StartTime);
var end = day.Add(EndTime);
<div class="rz-slots @(day == CurrentDate ? " rz-state-focused" : "")">
<div class="rz-slots @(day == CurrentDate ? " rz-state-focused" : "")">
<DaySlotEvents MinutesPerSlot=@MinutesPerSlot StartDate=@start EndDate=@end Appointments=@Appointments CurrentDate="@CurrentDate" CurrentAppointment="@currentAppointment"AppointmentDragStart=@OnAppointmentDragStart/>
@for (var date = start; date < end; date = date.AddMinutes(MinutesPerSlot))
{
var slotDate = date;
<div @onclick=@(args => OnSlotClick(slotDate)) @attributes=@Attributes(date) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(slotDate))></div>
<div @onclick=@(args => OnSlotClick(slotDate)) @attributes=@Attributes(date) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(slotDate)) @ontouchend=@(args => @OnDrop(slotDate))></div>
}
</div>
}
Expand Down Expand Up @@ -81,7 +81,8 @@
IDictionary<string, object> Attributes(DateTime date)
{
var attributes = Scheduler.GetSlotAttributes(date, date.AddMinutes(MinutesPerSlot));
attributes["class"] = ClassList.Create("rz-slot dropzone").Add("rz-slot-minor", (date.Minute / MinutesPerSlot) % 2 == 1).Add(attributes).ToString();
attributes["class"] = ClassList.Create("rz-slot").Add("rz-slot-minor", (date.Minute / MinutesPerSlot) % 2 == 1).Add(attributes).ToString();
attributes["dropzone"] = "move";
return attributes;
}

Expand Down
10 changes: 6 additions & 4 deletions Radzen.Blazor/Rendering/YearPlannerView.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@using Radzen
@using Radzen.Blazor
@using Radzen.Blazor.Rendering
@inherits DropableViewBase
@inject DialogService DialogService

@{
Expand Down Expand Up @@ -66,15 +67,15 @@

@if (item.Start >= realstart && item.Start <= end)
{
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick ShowAppointmentContent=false />
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick ShowAppointmentContent=false DragStart=@OnAppointmentDragStart />
}
else if (realstart == start)
{
left = startSlotIndex * slotWidth;
length = Math.Max(1, Math.Min(daysinmonth, Math.Ceiling(item.End.Subtract(date).TotalDays - (startSlotIndex - 1))));
width = length * slotWidth;

<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick ShowAppointmentContent=false />
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick ShowAppointmentContent=false DragStart=@OnAppointmentDragStart />
}
}

Expand Down Expand Up @@ -109,15 +110,15 @@

@if (slotInMonth)
{
<div @onclick="@(args => OnSlotClick(dayOfWeek))" @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType} {(CurrentDate.Date == dayOfWeek.Date ? "rz-state-focused" : "")}"), slotInMonth)>
<div @onclick="@(args => OnSlotClick(dayOfWeek))" @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType} {(CurrentDate.Date == dayOfWeek.Date ? "rz-state-focused" : "")}"), slotInMonth) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(dayOfWeek)) @ontouchend=@(args => @OnDrop(dayOfWeek))>
<div class="rz-slot-title">
@dayOfWeek.Day
</div>
</div>
}
else
{
<div @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"), slotInMonth)>
<div @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"), slotInMonth) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(dayOfWeek)) @ontouchend=@(args => @OnDrop(dayOfWeek))>
<div class="rz-slot-title">
</div>
</div>
Expand Down Expand Up @@ -162,6 +163,7 @@
{
var attributes = Scheduler.GetSlotAttributes(start, start.AddDays(1));
attributes["class"] = ClassList.Create(className).Add(attributes).ToString();
attributes["dropzone"] = "move";
if (!slotInMonth)
{
attributes.Remove("style");
Expand Down
10 changes: 6 additions & 4 deletions Radzen.Blazor/Rendering/YearTimelineView.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@using Radzen.Blazor.Rendering
@using Microsoft.JSInterop
@inject DialogService DialogService
@inherits DropableViewBase
@inject IJSRuntime JSRuntime
@{
var points = new Dictionary<AppointmentData, double>();
Expand Down Expand Up @@ -67,15 +68,15 @@

@if (item.Start >= realstart && item.Start <= end)
{
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick />
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick DragStart=@OnAppointmentDragStart />
}
else if (realstart == start)
{
left = startSlotIndex * slotWidth;
length = Math.Max(1, Math.Min(daysinmonth, Math.Ceiling(item.End.Subtract(date).TotalDays - (startSlotIndex - 1))));
width = length * slotWidth;

<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick />
<Appointment Data=@item Top=@top Left=@left Width=@width Height=@height Click=@OnAppointmentClick DragStart=@OnAppointmentDragStart />
}
}

Expand Down Expand Up @@ -109,15 +110,15 @@

@if (slotInMonth)
{
<div @onclick="@(args => OnSlotClick(dayOfWeek))" @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType} {(CurrentDate.Date == dayOfWeek.Date ? "rz-state-focused" : "")}"), slotInMonth)>
<div @onclick="@(args => OnSlotClick(dayOfWeek))" @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType} {(CurrentDate.Date == dayOfWeek.Date ? "rz-state-focused" : "")}"), slotInMonth) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(dayOfWeek)) @ontouchend=@(args => @OnDrop(dayOfWeek))>
<div class="rz-slot-title">
@dayOfWeek.Day
</div>
</div>
}
else
{
<div @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"), slotInMonth)>
<div @attributes=@Attributes(dayOfWeek, ($"rz-slot {dayType}"), slotInMonth) ondragover="event.preventDefault();" @ondrop=@(args => @OnDrop(dayOfWeek)) @ontouchend=@(args => @OnDrop(dayOfWeek))>
<div class="rz-slot-title">
</div>
</div>
Expand Down Expand Up @@ -154,6 +155,7 @@
{
var attributes = Scheduler.GetSlotAttributes(start, start.AddDays(1));
attributes["class"] = ClassList.Create(className).Add(attributes).ToString();
attributes["dropzone"] = "move";
if (!slotInMonth)
{
attributes.Remove("style");
Expand Down
Loading

0 comments on commit 56e8064

Please sign in to comment.