Hello!
Since I am evaluating Your controls, we are currently testing Scheduler component, as it is our main interest and a deciding factor in a purchase process for my company.
Currently we are trying to decide what would be the Syncfusion preferred way of presented action:
Given:
Objective:
Scheduler should load only appointments that are currently visible to user (user has daily / monthly timeline views available),
so there will not be a repetitive data polling for data that are not needed.
We have to be able to determine current action when user is adding / modifying / deleting an appointment, with granularity of "modified single occurrence from recurring appointment", "deleted single appointment occurrence from recurring appointment" etc - Those details are a must, because our database schema does not hold something like Your "Recurrence string" and keeps every exception as a separate database entry.
Given those two main concerns, what is the suggested way to go?
- Using OnActionBegin / ActionCompleted? if so, how to limit initial load of data and just grab appointments that are currently visible (remember, no db connection, only queries like "GetAppointmentsFromBetweenDates(date1, date2))
- Using custom data manager? It does provide (at least we think that) required date range for querying only needed appointment range, but then - how to determine current action with separation of "editing occurrence", "modifying single occurrence" etc, etc.
Best regards,
Henryk
|
CurrentAction action = ScheduleRef.GetCurrentAction(); |
Thanks for quick reply.
Main concern is that scheduler instance CANNOT BE static.
Lets say we will use Custom Data Adaptor.
Since Custom Adaptor is it's own object, which instance is created by Your scheduler, how can we get access to the scheduler's GetCurrentAction() method?
Whole of actual database communication is performed by using command or query objects, that are called upon inside Custom Data Adaptor - in which we seem to not be able to get instance of scheduler to grab the action that triggered for example the "BatchUpdate" method inside adaptor.
So, in simple terms - how, inside custom adaptor, get the actual action (for example
"EditOccurrence") that triggered adaptor method (for example "batch update") when scheduler instance is NOT static and adaptor is it's own object, in it's
Current database operation method prevents direct database connection / action.
There is no way to access any form of context, nor sql, dapper or EF.
Only way to use scheduler is with the atomic-level actions, like:
Therefore, to perform such actions, one must know, or be able to determine programmatically, which of given actions was performed by user, so one can use the data provided by data manager to perform one of mentioned actions.
More detailed information in either data manager and / or OnActionSuccess would be very useful.
For example a list of properties, that have been changed with additional information about built-in actions that were performed would be useful.
Example:
User edits an recurring appointment - he adds one new modified occurrence to the series. He changed subject and time of meeting. Developer would get the list of actions performed upon:
A - appointment series - exception to rule added
B - new exceptional appointment - Exception appointment created, subject was changed to... , date was changed to...
If modification is not possible, than at least some sort of algorithm that is used in scheduler would be useful - how to determine 100% which atomic action(s) were taken - for example BatchUpdate with one changed record and one added record, when created record have recurrence id = updated record id is a 100% "an exception to recurrence rule was just created", etc, etc/
I will write it again - there is no CRUD operation that can be performed directly on a database - there is NO such thing, nor there is any direct way of database connection.
For the sake of this conversation assume following:
- No access to Entity framework.
- No dapper
- No access to any form of direct database communication
- No access to performing any kind of SQL query
- no access to SQLconnection string
- For simplicity - no SQL, it does not exist in our case, same for EF, Dapper, etc - non-existent.
Assume that in this case database is just a fairytale, a something that someone is heard something about, but have never - ever saw it and he will never see it.
You, as a programmer, can only use provided custom commands, that are executed by a object using mediator pattern. Nothing else.
You, as a programmer, can send a command, for example a command named "CreateNewExcemptionFromRecurrenceRule(Appointment appointment, Appointment exception, DateTime replaceTime)". appointment in this case is base appointment with some recurrence, exception is a appointment object that replaces one of the base occurrences and replaceTime is a precise date of the replaced appointment time.
Nothing else, no more, no less - this is the only form of communication with something, that is passing your "messages" further into the "no-one saw it never ever ever" database-land.
There are many different commands or queries, that will ask data source for something, but there is no DIRECT way of just performing any sort of query,
Therefor - a 100% reliable information about user action, be it add, remove, property change, exception to recurrence rule creation or similar is needed.
|
<SfSchedule @ref="ScheduleRef" TValue="AppointmentData" Width="100%" Height="650px" SelectedDate="@(new DateTime(2020, 1, 9))">
<ScheduleEventSettings TValue="AppointmentData">
<SfDataManager Adaptor="Adaptors.CustomAdaptor">
<CustomAdaptor></CustomAdaptor>
</SfDataManager>
</ScheduleEventSettings>
</SfSchedule>
@code {
[Inject]
protected AppointmentDataService Service { get; set; }
public SfSchedule<AppointmentData> ScheduleRef;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Service.ScheduleRef = ScheduleRef;
}
await base.OnAfterRenderAsync(firstRender);
}
} |
|
<CascadingValue Value="@this">
@ChildContent
</CascadingValue>
@code {
[Parameter]
[JsonIgnore]
public RenderFragment ChildContent { get; set; }
[Inject]
protected AppointmentDataService ServicePage { get; set; }
List<AppointmentData> EventData = new AppointmentDataService().DataList();
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null)
{
await Task.Delay(100); //To mimic asynchronous operation, we delayed this operation using Task.Delay
return dataManagerRequest.RequiresCounts ? new DataResult() { Result = EventData, Count = EventData.Count() } : (object)EventData;
}
public async override Task<object> InsertAsync(DataManager dataManager, object data, string key)
{
ServicePage.ScheduleRef.GetCurrentAction();
await Task.Delay(100); //To mimic asynchronous operation, we delayed this operation using Task.Delay
EventData.Insert(0, data as AppointmentData);
return data;
} |
Great answer - I will try it soon, thanks!