This commit is contained in:
2026-05-08 11:05:48 +02:00
parent b6d5701ef3
commit f915d88c0b
18 changed files with 759 additions and 374 deletions

View File

@@ -726,6 +726,8 @@
<Content Include="Views\DevExpressScheduler\NotificationPopupContent.cshtml" />
<Content Include="Views\DevExpressScheduler\NotificationsPopupContent.cshtml" />
<Content Include="Views\DevExpressScheduler\CustomEmployeeSelectPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\CustomCustomerSelectPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\CustomResourceSelectPartial.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.config" />

View File

@@ -89,6 +89,13 @@ namespace BeWoPlanerMobil.Controllers
AppointmentModel.PossibleEmployees = EmployeeService.GetAllAuthorizedCompactEmployees();
AppointmentModel.PossibleCustomers = CustomerService.GetAllAuthorizedCompactCustomers();
AppointmentModel.PossibleResources = KalenderService.GetAllResources();
AppointmentModel.ResourceCategories2Resources = new Dictionary<ValueListEntryDC, List<ResourceDC>>();
foreach(var resource in AppointmentModel.PossibleResources)
{
AppointmentModel.ResourceCategories2Resources.AddOrUpdateValueInDictionary(resource.ResourceCategory, resource);
}
}
private void InitViewModel()
@@ -349,13 +356,7 @@ namespace BeWoPlanerMobil.Controllers
{
appointment.CustomerList = AppointmentModel.SelectedCustomers;
appointment.ResourceList = AppointmentModel.SelectedResources;
appointment.EmployeeList = new List<Employee2SchedulerAppointmentDC>();
foreach(var selectedEmployee in AppointmentModel.SelectedEmployees ?? new List<CompactEmployeeDC>())
{
appointment.EmployeeList.Add(new Employee2SchedulerAppointmentDC { Employee = selectedEmployee });
}
appointment.EmployeeList = AppointmentModel.SelectedEmployee2SchedulerAppointments;
appointment.Originator = Model.LoggedInUser.Employee;
@@ -398,41 +399,41 @@ namespace BeWoPlanerMobil.Controllers
ReloadAppointments();
}
[HttpPost]
public ActionResult CustomerMultiSelectPartial(string value)
{
var selectedCustomerOids = GridLookupExtension.GetSelectedValues<long?>("CustomerGridLookup") ?? Array.Empty<long?>();
//[HttpPost]
//public ActionResult CustomerMultiSelectPartial(string value)
//{
// var selectedCustomerOids = GridLookupExtension.GetSelectedValues<long?>("CustomerGridLookup") ?? Array.Empty<long?>();
AppointmentModel.SelectedCustomerOids = selectedCustomerOids.Where(oid => oid.HasValue).Select(oid => oid.Value).ToList();
// AppointmentModel.SelectedCustomerOids = selectedCustomerOids.Where(oid => oid.HasValue).Select(oid => oid.Value).ToList();
return PartialView("CustomerMultiSelectPartial", AppointmentModel);
}
// return PartialView("CustomerMultiSelectPartial", AppointmentModel);
//}
[HttpPost]
public ActionResult ResourceGridLookupPartial(string value)
{
var selectedResourceOids = GridLookupExtension.GetSelectedValues<long?>("ResourceGridLookup") ?? Array.Empty<long?>();
//[HttpPost]
//public ActionResult ResourceGridLookupPartial(string value)
//{
// var selectedResourceOids = GridLookupExtension.GetSelectedValues<long?>("ResourceGridLookup") ?? Array.Empty<long?>();
AppointmentModel.SelectedResourceOids = selectedResourceOids.Where(oid => oid.HasValue).Select(oid => oid.Value).ToList();
// AppointmentModel.SelectedResourceOids = selectedResourceOids.Where(oid => oid.HasValue).Select(oid => oid.Value).ToList();
return PartialView("ResourceMultiSelectPartial", AppointmentModel);
}
// return PartialView("ResourceMultiSelectPartial", AppointmentModel);
//}
[HttpPost]
public ActionResult EmployeeGridLookupPartial(string value)
{
/*
* Im AppointmentModel müssen die PossibleEmployees bleiben, denn daraus wählt man die Mitarbeiter, die noch nicht mit dem Termin
* verknüpft sind und es müssen - zumindest beim Bearbeiten - die bereits mit dem Termin verbundenen Mitarbeiter-zu-Termin-Relationen
* zwischengespeichert werden.
*
*/
var selectedEmployeeOids = GridLookupExtension.GetSelectedValues<long?>("EmployeeGridLookup") ?? Array.Empty<long?>();
//[HttpPost]
//public ActionResult EmployeeGridLookupPartial(string value)
//{
// /*
// * Im AppointmentModel müssen die PossibleEmployees bleiben, denn daraus wählt man die Mitarbeiter, die noch nicht mit dem Termin
// * verknüpft sind und es müssen - zumindest beim Bearbeiten - die bereits mit dem Termin verbundenen Mitarbeiter-zu-Termin-Relationen
// * zwischengespeichert werden.
// *
// */
// var selectedEmployeeOids = GridLookupExtension.GetSelectedValues<long?>("EmployeeGridLookup") ?? Array.Empty<long?>();
AppointmentModel.SelectedEmployeeOids = selectedEmployeeOids.Where(oid => oid.HasValue).Select(oid => oid.Value).ToList();
// AppointmentModel.SelectedEmployeeOids = selectedEmployeeOids.Where(oid => oid.HasValue).Select(oid => oid.Value).ToList();
return PartialView("EmployeeMultiSelectPartial", AppointmentModel);
}
// return PartialView("EmployeeMultiSelectPartial", AppointmentModel);
//}
[Authorize]
public string SelectActiveViewType(string viewTypeName)
@@ -654,7 +655,7 @@ namespace BeWoPlanerMobil.Controllers
}
[Authorize]
public ActionResult UpdateEmployeeSelection(long[] selectedOids)
public ActionResult UpdateEmployeeFilterSelection(long[] selectedOids)
{
if(Model is null)
{
@@ -676,7 +677,7 @@ namespace BeWoPlanerMobil.Controllers
}
[Authorize]
public ActionResult UpdateCustomerSelection(long[] selectedOids)
public ActionResult UpdateCustomerFilterSelection(long[] selectedOids)
{
if(Model is null)
{
@@ -698,7 +699,7 @@ namespace BeWoPlanerMobil.Controllers
}
[Authorize]
public ActionResult UpdateResourceSelection(long[] selectedOids)
public ActionResult UpdateResourceFilterSelection(long[] selectedOids)
{
if(Model is null)
{
@@ -860,5 +861,83 @@ namespace BeWoPlanerMobil.Controllers
return PartialView("SchedulerPagePartial", Model);
}
[Authorize]
public string GetEmployeePageCount()
{
return JsonConvert.SerializeObject(new EditFormInfo(AppointmentModel.EmployeePageCount, AppointmentModel.EmployeePageLimit));
}
[Authorize]
public string GetCustomerPageCount()
{
return JsonConvert.SerializeObject(new EditFormInfo(AppointmentModel.CustomerPageCount, AppointmentModel.CustomerPageLimit));
}
[Authorize]
public string GetResourcePageCount()
{
return JsonConvert.SerializeObject(new EditFormInfo(AppointmentModel.ResourcePageCount, AppointmentModel.ResourcePageLimit));
}
[Authorize]
public string UpdateAppointmentEmployeeSelection(string selectedOids)
{
if(selectedOids is null)
{
selectedOids = string.Empty;
}
var selectedEmployeeOids = selectedOids.Length == 0 ? new List<long>() : selectedOids.Split(',').Select(long.Parse).ToList();
AppointmentModel.SelectedEmployee2SchedulerAppointments = new List<Employee2SchedulerAppointmentDC>();
var employees = AppointmentModel.PossibleEmployees.Where(possibleEmployee => selectedEmployeeOids.Contains(possibleEmployee.EmployeeOid)).ToList();
foreach(var employee in employees)
{
AppointmentModel.SelectedEmployee2SchedulerAppointments.Add(new Employee2SchedulerAppointmentDC { Employee = employee });
}
return LeerzeichenFuerGetMethoden;
}
[Authorize]
public string UpdateAppointmentCustomerSelection(string selectedOids)
{
if(selectedOids is null)
{
selectedOids = string.Empty;
}
AppointmentModel.SelectedCustomerOids = selectedOids.Length == 0 ? new List<long>() : selectedOids.Split(',').Select(long.Parse).ToList();
return LeerzeichenFuerGetMethoden;
}
[Authorize]
public string UpdateAppointmentResourceSelection(string selectedOids)
{
if(selectedOids is null)
{
selectedOids = string.Empty;
}
AppointmentModel.SelectedResourceOids = selectedOids.Length == 0 ? new List<long>() : selectedOids.Split(',').Select(long.Parse).ToList();
return LeerzeichenFuerGetMethoden;
}
}
public class EditFormInfo
{
public int PageCount { get; }
public int PageLimit { get; }
public EditFormInfo(int pageCount, int pageLimit)
{
PageCount = pageCount;
PageLimit = pageLimit;
}
}
}

View File

@@ -1530,7 +1530,7 @@ namespace BeWoPlanerMobil.Controllers
if(false == Model.IsInEditingMode)
{
if(Model.NewServiceRecord.CostBearer != null && Model.ShowSignature && (Model.NewServiceRecord.ServiceDescription.Category.IsBillable || Model.NewServiceRecord.ServiceDescription.Category.BillableAmount > 0m || Model.NewServiceRecord.ServiceDescription.BillableAmount > 0m))
if(Model.NewServiceRecord.CostBearer != null && Model.ShowSignature)
{
var valRes = OperationsService.ValidateServiceRecord(Model.NewServiceRecord, null, 0, null, null);
var doppelt = valRes.Count > 0 && valRes.FirstOrDefault(v => v.ResultType == DoppelterEintrag) != null;
@@ -1540,8 +1540,7 @@ namespace BeWoPlanerMobil.Controllers
var oidList = OperationsService.InsertNewServiceRecords(new List<ServiceRecordDC> { Model.NewServiceRecord });
Model.LastCreatedServiceRecordOid = oidList[0];
if(Model.IsAllowedToCreateSignature(Model.NewServiceRecord))
{
if(Model.NewServiceRecord.CostBearer != null && Model.ShowSignature && (Model.NewServiceRecord.ServiceDescription.Category.IsBillable || Model.NewServiceRecord.ServiceDescription.Category.BillableAmount > 0m || Model.NewServiceRecord.ServiceDescription.BillableAmount > 0m))

View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
namespace BeWoPlanerMobil.Models
{
@@ -30,64 +31,16 @@ namespace BeWoPlanerMobil.Models
public string CompletedNotice { get; set; }
public string CompletedUser { get; set; }
public string TaskDescription { get; set; }
public List<CompactCustomerDC> SelectedCustomers
{
get
{
return SelectedCustomerOids is null ?
null :
PossibleCustomers.Where(customer => SelectedCustomerOids.Contains(customer.CustomerOid)).ToList();
}
set
{
SelectedCustomerOids = value?.Select(customer => customer.CustomerOid).ToList();
}
}
public List<ResourceDC> SelectedResources
{
get
{
return SelectedResourceOids is null ?
null :
PossibleResources.Where(resource => resource.ResourceOid.HasValue && SelectedResourceOids.Contains(resource.ResourceOid.Value)).ToList();
}
set
{
SelectedResourceOids = value?.Where(resource => resource.ResourceOid.HasValue).Select(resource => resource.ResourceOid.Value).ToList();
}
}
public bool HasServiceRecordEntry { get; set; }
public List<ServiceRecordDC> ServiceRecordList { get; set; }
public List<CompactCustomerDC> PossibleCustomers { get; set; }
public List<ResourceDC> PossibleResources { get; set; }
public List<long> SelectedCustomerOids
{
get => AppointmentSessionModel.SelectedCustomerOids;
set => AppointmentSessionModel.SelectedCustomerOids = value;
}
public List<long> SelectedResourceOids
{
get => AppointmentSessionModel.SelectedResourceOids;
set => AppointmentSessionModel.SelectedResourceOids = value;
}
/* Mitarbeiter */
#region Mitarbeiter
public List<CompactEmployeeDC> PossibleEmployees { get; set; }
public int EmployeePageLimit => 10;
public int EmployeePageCount => (PossibleEmployees?.Count ?? 0) / EmployeePageLimit;
public List<Employee2SchedulerAppointmentDC> SelectedEmployee2SchedulerAppointments { get; set; }
public List<CompactEmployeeDC> SelectedEmployees { get; set; }
@@ -103,12 +56,64 @@ namespace BeWoPlanerMobil.Models
get => AppointmentSessionModel.SelectedEmployees2Appointments;
set => AppointmentSessionModel.SelectedEmployees2Appointments = value;
}
/* /Mitarbeiter */
#endregion
#region Klienten
public List<CompactCustomerDC> PossibleCustomers { get; set; }
public int CustomerPageLimit => 10;
public int CustomerPageCount => (PossibleCustomers?.Count ?? 0) / CustomerPageLimit;
public List<CompactCustomerDC> SelectedCustomers
{
get
{
return SelectedCustomerOids is null ? null : PossibleCustomers.Where(customer => SelectedCustomerOids.Contains(customer.CustomerOid)).ToList();
}
set
{
SelectedCustomerOids = value?.Select(customer => customer.CustomerOid).ToList();
}
}
public List<long> SelectedCustomerOids
{
get => AppointmentSessionModel.SelectedCustomerOids;
set => AppointmentSessionModel.SelectedCustomerOids = value;
}
#endregion
#region Ressourcen
public Dictionary<ValueListEntryDC, List<ResourceDC>> ResourceCategories2Resources { get; set; }
public List<ResourceDC> PossibleResources { get; set; }
public int ResourcePageLimit => 10;
public int ResourcePageCount => (ResourceCategories2Resources?.Keys?.Count ?? 0) / ResourcePageLimit;
public List<ResourceDC> SelectedResources
{
get
{
return SelectedResourceOids is null ?
null :
PossibleResources.Where(resource => resource.ResourceOid.HasValue && SelectedResourceOids.Contains(resource.ResourceOid.Value)).ToList();
}
set
{
SelectedResourceOids = value?.Where(resource => resource.ResourceOid.HasValue).Select(resource => resource.ResourceOid.Value).ToList();
}
}
public List<long> SelectedResourceOids
{
get => AppointmentSessionModel.SelectedResourceOids;
set => AppointmentSessionModel.SelectedResourceOids = value;
}
#endregion
public AppointmentModel()
@@ -122,6 +127,13 @@ namespace BeWoPlanerMobil.Models
PossibleResources = possibleResources;
PossibleEmployees = possibleEmployees;
ResourceCategories2Resources = new Dictionary<ValueListEntryDC, List<ResourceDC>>();
foreach(var resource in PossibleResources)
{
ResourceCategories2Resources.AddOrUpdateValueInDictionary(resource.ResourceCategory, resource);
}
SessionModel = new AppointmentSessionModel();
}

View File

@@ -4,20 +4,20 @@ namespace BeWoPlanerMobil.Models
{
public class AppointmentSessionModel : BaseSessionModel
{
public List<long> SelectedCustomerOids { get; set; }
public List<long> SelectedEmployeeOids { get; set; }
public List<long> SelectedCustomerOids { get; set; }
public List<long> SelectedResourceOids { get; set; }
public List<long> SelectedEmployees2Appointments { get; set; }
public List<long> SelectedEmployees2Appointments { get; set; } = new List<long>();
public override void ResetValues()
{
base.ResetValues();
SelectedCustomerOids = null;
SelectedEmployeeOids = null;
SelectedResourceOids = null;
SelectedEmployees2Appointments = null;
SelectedCustomerOids = new List<long>();
SelectedEmployeeOids = new List<long>();
SelectedResourceOids = new List<long>();
SelectedEmployees2Appointments = new List<long>();
}
}
}

View File

@@ -103,29 +103,6 @@ namespace BeWoPlanerMobil.Models
public List<CompactCustomerDC> SelectedCustomersForFiltering { get; set; }
public List<ResourceDC> SelectedResourcesForFiltering { get; set; }
public List<CompactEmployeeDC> SelectedEmployeesForIntervalFinder { get; set; }
public List<CompactCustomerDC> SelectedCustomersForIntervalFinder { get; set; }
public List<ResourceDC> SelectedResourcesForIntervalFinder { get; set; }
public List<long> SelectedEmployeeOidsForIntervalFinder
{
get => DevExpressSchedulerSessionModel.SelectedEmployeeOidsForIntervalFinder;
set => DevExpressSchedulerSessionModel.SelectedEmployeeOidsForIntervalFinder = value;
}
public List<long> SelectedCustomerOidsForIntervalFinder
{
get => DevExpressSchedulerSessionModel.SelectedCustomerOidsForIntervalFinder;
set => DevExpressSchedulerSessionModel.SelectedCustomerOidsForIntervalFinder = value;
}
public List<long> SelectedResourceOidsForIntervalFinder
{
get => DevExpressSchedulerSessionModel.SelectedResourceOidsForIntervalFinder;
set => DevExpressSchedulerSessionModel.SelectedResourceOidsForIntervalFinder = value;
}
public bool ShowTasks
{

View File

@@ -14,10 +14,6 @@ namespace BeWoPlanerMobil.Models
public List<long> SelectedCustomerOidsForFiltering { get; set; }
public List<long> SelectedResourceOidsForFiltering { get; set; }
public List<long> SelectedEmployeeOidsForIntervalFinder { get; set; }
public List<long> SelectedCustomerOidsForIntervalFinder { get; set; }
public List<long> SelectedResourceOidsForIntervalFinder { get; set; }
public List<long> OpenAppointmentOids { get; set; }
public long? AppointmentOid2Answer { get; set; }
@@ -44,10 +40,6 @@ namespace BeWoPlanerMobil.Models
SelectedCustomerOidsForFiltering = new List<long>();
SelectedResourceOidsForFiltering = new List<long>();
SelectedEmployeeOidsForIntervalFinder = new List<long>();
SelectedCustomerOidsForIntervalFinder = new List<long>();
SelectedResourceOidsForIntervalFinder = new List<long>();
OpenAppointmentOids = new List<long>();
ShowTasks = false;

View File

@@ -1068,7 +1068,7 @@
</div>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, "customer-betreuung-collapsible")" , id="customer-betreuung-collapsible">
<div class="card-body p-1">
<div id="betreuungscontainer">
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3" id="betreuungscontainer">
@Html.Partial("CustomerBetreuungPartial", Model)
</div>
</div>

View File

@@ -10,111 +10,93 @@
@if(hasRelatedEmployees && Model.SelectedCustomer != null)
{
<div class="card w-100 h-100">
<div class="card-header" onclick="cardHeaderClick2(this)">
<div class="d-inline-flex">
<i class="fas fa-chevron-down h-100 text-bewo-customer-card-header" id="chevron-customer-betreuung-list"></i>
</div>
<div class="d-inline d-inline-flex text-bewo-customer-card-header h-100">
<button type="button" class="btn btn-link text-bewo-customer-card-header" style="font-size: 20px;">
Betreuung
</button>
</div>
</div>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, "collapse-customer-betreuung-list")" id="collapse-customer-betreuung-list">
<div class="card-body p-1">
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3">
@foreach(var relation in Model.SelectedCustomer.RelatedEmployees)
{
var start = relation.StartDate.HasValue ? $"{relation.StartDate.Value:dd.MM.yyyy}" : "";
var end = relation.EndDate.HasValue ? $"{relation.EndDate.Value:dd.MM.yyyy}" : "";
foreach(var relation in Model.SelectedCustomer.RelatedEmployees)
{
var start = relation.StartDate.HasValue ? $"{relation.StartDate.Value:dd.MM.yyyy}" : "";
var end = relation.EndDate.HasValue ? $"{relation.EndDate.Value:dd.MM.yyyy}" : "";
var relationRole = relation.RelationRole?.DisplayName ?? string.Empty;
var relationRole = relation.RelationRole?.DisplayName ?? string.Empty;
<div class="col mb-3">
<div class="card h-100">
<div class="card-body">
<table class="w-100">
<tbody>
<tr>
<td class="text-secondary align-text-top">Betreuer:</td>
<td class="text-right align-text-top">@relation.Employee</td>
</tr>
<tr>
<td class="text-secondary align-text-top">Rolle:</td>
<td class="text-right align-text-top">@relationRole</td>
</tr>
@if(!string.IsNullOrWhiteSpace(start))
{
<tr>
<td class="text-secondary align-text-top">Startdatum:</td>
<td class="text-right align-text-top">@start</td>
</tr>
}
@if(!string.IsNullOrWhiteSpace(end))
{
<tr>
<td class="text-secondary align-text-top">Enddatum:</td>
<td class="text-right align-text-top">@end</td>
</tr>
}
@if(!string.IsNullOrWhiteSpace(relation.Notice))
{
<tr>
<td class="text-secondary align-text-top pr-1">Erläuterung:</td>
<td class="text-justify align-text-top">@relation.Notice</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
<div class="col mb-3">
<div class="card h-100">
<div class="card-body">
<table class="w-100">
<tbody>
<tr>
<td class="text-secondary align-text-top">Betreuer:</td>
<td class="text-right align-text-top">@relation.Employee</td>
</tr>
<tr>
<td class="text-secondary align-text-top">Rolle:</td>
<td class="text-right align-text-top">@relationRole</td>
</tr>
@if(!string.IsNullOrWhiteSpace(start))
{
<tr>
<td class="text-secondary align-text-top">Startdatum:</td>
<td class="text-right align-text-top">@start</td>
</tr>
}
@if(!string.IsNullOrWhiteSpace(end))
{
<tr>
<td class="text-secondary align-text-top">Enddatum:</td>
<td class="text-right align-text-top">@end</td>
</tr>
}
@if(!string.IsNullOrWhiteSpace(relation.Notice))
{
<tr>
<td class="text-secondary align-text-top pr-1">Erläuterung:</td>
<td class="text-justify align-text-top">@relation.Notice</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
}
}
@*Teams*@
@if(hasRelatedTeams && Model.SelectedCustomer != null)
{
<div class="card w-100 h-100 mt-3">
<div class="card-header" onclick="cardHeaderClick2(this)">
<div class="d-inline-flex">
<i class="fas fa-chevron-down h-100 text-bewo-customer-card-header" id="chevron-customer-betreuung-teams"></i>
<div class="card w-100 h-100 mt-3">
<div class="card-header" onclick="cardHeaderClick2(this)">
<div class="d-inline-flex">
<i class="fas fa-chevron-down h-100 text-bewo-customer-card-header" id="chevron-customer-betreuung-teams"></i>
</div>
<div class="d-inline d-inline-flex text-bewo-customer-card-header h-100">
<button type="button" class="btn btn-link text-bewo-customer-card-header" style="font-size: 20px;">
Teams
</button>
</div>
</div>
<div class="d-inline d-inline-flex text-bewo-customer-card-header h-100">
<button type="button" class="btn btn-link text-bewo-customer-card-header" style="font-size: 20px;">
Teams
</button>
</div>
</div>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, "collapse-customer-betreuung-teams")" id="collapse-customer-betreuung-teams">
<div class="card-body">
@foreach(var teamRelation in Model.SelectedCustomer.RelatedTeams)
{
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4">
<div class="col mb-0">
<div class="card h-100">
<div class="card-body">
<table class="w-100">
<tbody>
<tr>
<td class="text-secondary">Team:</td>
<td class="text-right">@teamRelation.Team.Name</td>
</tr>
</tbody>
</table>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, "collapse-customer-betreuung-teams")" id="collapse-customer-betreuung-teams">
<div class="card-body">
@foreach(var teamRelation in Model.SelectedCustomer.RelatedTeams)
{
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4">
<div class="col mb-0">
<div class="card h-100">
<div class="card-body">
<table class="w-100">
<tbody>
<tr>
<td class="text-secondary">Team:</td>
<td class="text-right">@teamRelation.Team.Name</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
}
</div>
}
</div>
</div>
</div>
}

View File

@@ -52,7 +52,7 @@
showSpinner();
$("#customer-input-container").load(
"@Url.Action("UpdateCustomerSelection")",
"@Url.Action("UpdateCustomerFilterSelection")",
{ selectedOids: selectedCustomerOids },
() => {
scheduler.Refresh();

View File

@@ -62,7 +62,7 @@
logInfo3(`Es wurden ${selectedEmployeeOids.length} Mitarbeiter ausgewählt.`);
$("#employee-input-container").load(
"@Url.Action("UpdateEmployeeSelection", "DevExpressScheduler")",
"@Url.Action("UpdateEmployeeFilterSelection", "DevExpressScheduler")",
{
selectedOids: selectedEmployeeOids
},

View File

@@ -27,7 +27,7 @@
showSpinner();
$("#resource-input-container").load(
"@Url.Action("UpdateResourceSelection")",
"@Url.Action("UpdateResourceFilterSelection")",
{
selectedOids: selectedResourceOids
},

View File

@@ -6,6 +6,7 @@
@{
Html.EnableClientValidation();
Html.EnableUnobtrusiveJavaScript();
}
<style type="text/css">
@@ -18,6 +19,52 @@
@using(Html.BeginForm())
{
<table id="abc-table">
@* Betreff *@
<tr>
<td>
@Html.DevExpress().Label(
settings =>
{
settings.AssociatedControlName = nameof(SchedulerAppointmentDC.Subject);
settings.Text = "Betreff:";
settings.Width = Unit.Percentage(100);
}).GetHtml()
</td>
<td colspan="3" style="width: 100%; padding: .25em;">
@Html.DevExpress().TextBox(
settings =>
{
settings.Name = nameof(SchedulerAppointmentDC.Subject);
settings.ShowModelErrors = true;
settings.Properties.ValidationSettings.Display = Display.Dynamic;
settings.Width = Unit.Percentage(100);
}).Bind(Model.Subject).GetHtml()
</td>
</tr>
@* Ort *@
<tr>
<td>
@Html.DevExpress().Label(
settings =>
{
settings.AssociatedControlName = nameof(SchedulerAppointmentDC.Location);
settings.Text = "Ort:";
settings.Width = Unit.Percentage(100);
}).GetHtml()
</td>
<td colspan="3" style="width: 100%; padding: .25em;">
@Html.DevExpress().TextBox(
settings =>
{
settings.Name = nameof(SchedulerAppointmentDC.Location);
settings.ShowModelErrors = true;
settings.Properties.ValidationSettings.Display = Display.Dynamic;
settings.Width = Unit.Percentage(100);
}).Bind(Model.Location).GetHtml()
</td>
</tr>
@* Start *@
<tr>
<td style="white-space: nowrap;">
@@ -111,90 +158,24 @@
</table>
</td>
</tr>
@* Mitarbeiter, Klienten, Ressourcen *@
<tr>
<td colspan="4">
<table>
<tr>
<td style="width: 33%; padding: .25em;">
@Html.Partial("EmployeeMultiSelectPartial")
</td>
<td style="width: 33%; padding: .25em;">
@Html.Partial("CustomerMultiSelectPartial")
</td>
<td style="width: 33%; padding: .25em;">
@Html.Partial("ResourceMultiSelectPartial")
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="4">
<table>
<table class="w-100">
<tr>
<td style="width: 33%; padding: .25em;">
@Html.Partial("CustomEmployeeSelectPartial", Model)
</td>
<td style="width: 33%; padding: .25em;">
@Html.Partial("CustomCustomerSelectPartial", Model)
</td>
<td style="width: 33%; padding: .25em;">
@Html.Partial("CustomResourceSelectPartial", Model)
</td>
</tr>
</table>
</td>
</tr>
@* Betreff *@
<tr>
<td>
@Html.DevExpress().Label(
settings =>
{
settings.AssociatedControlName = nameof(SchedulerAppointmentDC.Subject);
settings.Text = "Betreff:";
settings.Width = Unit.Percentage(100);
}).GetHtml()
</td>
<td colspan="3" style="width: 100%; padding: .25em;">
@Html.DevExpress().TextBox(
settings =>
{
settings.Name = nameof(SchedulerAppointmentDC.Subject);
settings.ShowModelErrors = true;
settings.Properties.ValidationSettings.Display = Display.Dynamic;
settings.Width = Unit.Percentage(100);
}).Bind(Model.Subject).GetHtml()
</td>
</tr>
@* Ort *@
<tr>
<td>
@Html.DevExpress().Label(
settings =>
{
settings.AssociatedControlName = nameof(SchedulerAppointmentDC.Location);
settings.Text = "Ort:";
settings.Width = Unit.Percentage(100);
}).GetHtml()
</td>
<td colspan="3" style="width: 100%; padding: .25em;">
@Html.DevExpress().TextBox(
settings =>
{
settings.Name = nameof(SchedulerAppointmentDC.Location);
settings.ShowModelErrors = true;
settings.Properties.ValidationSettings.Display = Display.Dynamic;
settings.Width = Unit.Percentage(100);
}).Bind(Model.Location).GetHtml()
</td>
</tr>
@* Notiz *@
<tr>
<td colspan="4">

View File

@@ -1,80 +1,100 @@
@using BS.Shared
@using BS.Shared.Core.Utilities
@using BS.Shared.Extensions
@model BeWoPlanerMobil.Models.AppointmentModel
<script type="text/javascript">
</script>
<style type="text/css">
li {
cursor: pointer;
}
</style>
@functions
{
string GetParticipationColor(ParticipationAnswer participationAnswer)
{
var background = "";
static string GetParticipationColor(ParticipationAnswer participationAnswer)
{
var background = "";
switch(participationAnswer)
{
case ParticipationAnswer.Zusage:
background = "#48D44E";
break;
case ParticipationAnswer.Vorbehalt:
background = "#B927D9";
break;
case ParticipationAnswer.Absage:
background = "#AB0030";
break;
}
switch(participationAnswer)
{
case ParticipationAnswer.Zusage:
background = "#48D44E";
break;
case ParticipationAnswer.Vorbehalt:
background = "#B927D9";
break;
case ParticipationAnswer.Absage:
background = "#AB0030";
break;
}
return background;
}
return background;
}
}
<div class="dropdown">
<button class="btn btn-bewo-employee dropdown-toggle" type="button" data-toggle="dropdown">
Mitarbeiter
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
@{
var areAllSelected = Model.SelectedEmployee2SchedulerAppointments.Select(x => x.Employee.EmployeeOid).ToList().AreListEqual(Model.PossibleEmployees.Select(employee => employee.EmployeeOid).ToList());
@foreach(var employee in Model.PossibleEmployees)
{
var isChecked = Model.SelectedEmployeeOids.Contains(employee.EmployeeOid) ? "checked" : string.Empty;
var employee2Appointment = Model.SelectedEmployee2SchedulerAppointments.FirstOrDefault(e2A => e2A.Employee.EmployeeOid.Equals(employee.EmployeeOid));
var allChecked = areAllSelected ? "checked" : string.Empty;
}
var background = "";
<div class="dropdown w-100" id="employees-dropdown">
<button class="btn btn-bewo-employee dropdown-toggle w-100" type="button" data-toggle="dropdown">
Mitarbeiter <span class="badge badge-light">@Model.SelectedEmployee2SchedulerAppointments.Count</span>
</button>
<div class="dropdown-menu" onclick="event.stopPropagation();">
<div class="dropdown-item py-1 px-2">
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<div class="input-group-text">
<input type="checkbox" @allChecked onclick="selectAllEmployeeCustomerResource('emp')" id="apt-emp-select-all">
</div>
</div>
<input type="text" class="form-control" id="emp-drop-search-input" placeholder="Suchen ..." oninput="onNewSearchInput('emp')">
<div class="input-group-append">
<button type="button" class="btn btn-outline-secondary" onclick="resetNewSearch('emp')">
<span class="fas fa-times-circle"></span>
</button>
</div>
</div>
</div>
<div class="dropdown-divider"></div>
<div id="dropdown-emp-itm-container">
@for(var i = 0; i < Model.PossibleEmployees.Count; i++)
{
var employee = Model.PossibleEmployees[i];
var isChecked = Model.SelectedEmployeeOids.Contains(employee.EmployeeOid) ? "checked" : string.Empty;
var employee2Appointment = Model.SelectedEmployee2SchedulerAppointments.FirstOrDefault(e2A => e2A.Employee.EmployeeOid.Equals(employee.EmployeeOid));
if(employee2Appointment != null)
{
background = GetParticipationColor(employee2Appointment.ParticipationAnswer);
}
var background = employee2Appointment is null ? string.Empty : GetParticipationColor(employee2Appointment.ParticipationAnswer);
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">
var x = WebUtils.CheckColorString(employee.EmployeeColor) ? "" : string.Empty;
</div>
</div>
</div>
var dNone = i / Model.EmployeePageLimit + 1 != 1 ? " d-none" : string.Empty;
<div class="dropdown-item w-100 @dNone" id="dropdown-item-@i">
<form class="form-inline justify-content-between">
<div class="form-group form-check">
<input class="form-check-input" type="checkbox" id="apt-edit-emp-@employee.EmployeeOid" @isChecked onclick="updateEmployeeCustomerResourceSelection('emp')" />
<label for="apt-edit-emp-@employee.EmployeeOid" class="form-check-label">
@employee.DetailDescription
</label>
</div>
<a class="dropdown-item" href="#">@employee.DetailDescription</a>
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" @isChecked id="apt-edit-emp-@employee.EmployeeOid" />
<label class="form-check-label" for="apt-edit-emp-@employee.EmployeeOid">@employee.DetailDescription</label>
</div>
</form>
/*
*<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="only-my-own-appointments-cb2" @isOnlyOwnAptsChecked onclick="filterAppointments()">
<label class="form-check-label" for="only-my-own-appointments-cb2">Nur meine Termine</label>
</div>
</form>
*/
}
</div>
@if(WebUtils.CheckColorString(employee.EmployeeColor))
{
<div class="float-right" style="width: 10px; height: 10px; background-color: @employee.EmployeeColor; border: 1px solid @employee.EmployeeColor; border-radius: 3px;"></div>
}
</form>
</div>
}
</div>
<div class="dropdown-divider" id="apt-emp-pag-divider"></div>
<div class="dropdown-item" id="apt-emp-pag-dropdow-item">
<nav id="apt-emp-pag-nav">
<ul class="pagination justify-content-center" id="apt-emp-pagination">
</ul>
</nav>
</div>
</div>
</div>

View File

@@ -22,6 +22,20 @@
const vw = $(window).width();
if(editFormPopup.outerWidth() !== undefined) {
$.get("@Url.Action("GetEmployeePageCount")", function(editFormInfo) {
pageCountCallback(editFormInfo, "emp");
});
$.get("@Url.Action("GetCustomerPageCount")", function(editFormInfo) {
pageCountCallback(editFormInfo, "cus");
});
$.get("@Url.Action("GetResourcePageCount")", function(editFormInfo) {
pageCountCallback(editFormInfo, "res");
});
}
if(editFormPopup.outerWidth() !== undefined && vw < 678) {
const newWidth = vw * .95;
@@ -51,6 +65,31 @@
}
}
function pageCountCallback(editFormInfo, prefix) {
const info = JSON.parse(editFormInfo);
const items = $(`#dropdown-${prefix}-itm-container .dropdown-item`);
switch(prefix) {
case "emp":
aptEmpSelPageCount = info.PageCount;
aptEmpSelPageLimit = info.PageLimit;
aptEmpSelItems = items;
break;
case "cus":
aptCusSelPageCount = info.PageCount;
aptCusSelPageLimit = info.PageLimit;
aptCusSelItems = items;
break;
case "res":
aptResSelPageCount = info.PageCount;
aptResSelPageLimit = info.PageLimit;
aptResSelItems = items;
break;
}
window.buildPagination(1, 5, 1, prefix);
}
function OnAppointmentFormSave(s, e) {
if(IsValidAppointment()) {
scheduler.AppointmentFormSave();
@@ -68,6 +107,7 @@
CustomerGridLookup.HideDropDown();
}
// ToDo: Löschen
function CloseEmployeeGridLookup() {
EmployeeGridLookup.ConfirmCurrentSelection();
EmployeeGridLookup.HideDropDown();
@@ -117,7 +157,7 @@
}
function OnAppointmentMenuPopup(s, e) {
const id = scheduler.GetSelectedAppointmentIds()[0];
const id = scheduler.GetSelectedAppointmentIds()[0];
const selectedAppointment = scheduler.GetAppointmentById(id);
for(let i = 0; i < e.item.items.length; i++) {
@@ -125,14 +165,14 @@
switch(currentItem.name) {
case "ToServiceRecord":
if(id === undefined || selectedAppointment.IsAbsenceTime || selectedAppointment.IsTask) {
currentItem.SetVisible(false);
if(id === undefined || selectedAppointment.IsAbsenceTime || selectedAppointment.IsTask) {
currentItem.SetVisible(false);
}
break;
case "ConfirmApt":
if(id === undefined || selectedAppointment.CanConfirm === false) {
currentItem.SetVisible(false);
currentItem.SetVisible(false);
}
break;
case "MaybeApt":
@@ -174,8 +214,8 @@
scheduler.PerformCallback({
apptID: "",
actionId: "FilterAppointments",
args: [selectedBoxes]
actionId: "FilterAppointments",
args: [selectedBoxes]
});
}
@@ -189,15 +229,15 @@
switch(filterType) {
case "employee":
url = "@Url.Action("UpdateEmployeeSelection")";
url = "@Url.Action("UpdateEmployeeFilterSelection")";
getSelectedCountUrl = "@Url.Action("GetSelectedEmployeesForAptFlt")";
break;
case "customer":
url = "@Url.Action("UpdateCustomerSelection")";
url = "@Url.Action("UpdateCustomerFilterSelection")";
getSelectedCountUrl = "@Url.Action("GetSelectedCustomersForAptFlt")";
break;
case "resource":
url = "@Url.Action("UpdateResourceSelection")";
url = "@Url.Action("UpdateResourceFilterSelection")";
getSelectedCountUrl = "@Url.Action("GetSelectedResourcesForAptFlt")";
break;
}
@@ -216,12 +256,304 @@
}
function performReload() {
$("#scheduler-notification-container").load("@Url.Action("GetNotifications")");
$("#scheduler-notification-container").load("@Url.Action("GetNotifications")");
}
function reloadScheduler() {
scheduler.PerformCallback({ apptID: "", actionId: "Reload", args: null }, () => { performReload(); hideSpinner(); });
}
@* CustomECRSelectionPartial *@
function onNewSearchInput(prefix) {
var searchText = $(`#${prefix}-drop-search-input`).val();
const menuItems = $(`#dropdown-${prefix}-itm-container .dropdown-item`);
if(searchText === null || searchText === undefined || searchText.length === 0) {
menuItems.show();
return;
}
menuItems.hide();
$.each(menuItems,
function(index, item) {
const itemText = $(item).text().toLowerCase();
if(itemText.includes(searchText.toLowerCase())) {
$(item).show();
}
}
);
}
function resetNewSearch(prefix) {
$(`#${prefix}-drop-search-input`).val("");
buildPagination(1, 5, 1, prefix);
showPage(1, prefix);
const e = window.event;
e.cancelBubble = true;
if(e.stopPropagation) {
e.stopPropagation();
}
}
var aptEmpSelPageCount = 0;
var aptEmpSelItems = [];
var aptEmpSelCurrentPage = 1;
var aptEmpSelPageLimit = 0;
var aptCusSelPageCount = 0;
var aptCusSelItems = [];
var aptCusSelCurrentPage = 1;
var aptCusSelPageLimit = 0;
var aptResSelPageCount = 0;
var aptResSelItems = [];
var aptResSelCurrentPage = 1;
var aptResSelPageLimit = 0;
function buildPagination(firstShownButton, lastShownButton, activeButton, prefix) {
const pagination = $(`#apt-${prefix}-pagination`);
pagination.empty();
var pageCount = 1;
var currentPage = 1;
switch(prefix) {
case "emp":
pageCount = aptEmpSelPageCount;
currentPage = aptEmpSelCurrentPage;
break;
case "cus":
pageCount = aptCusSelPageCount;
currentPage = aptCusSelCurrentPage;
break;
case "res":
pageCount = aptResSelPageCount;
currentPage = aptResSelCurrentPage;
break;
}
if(prefix === "res") {
logInfo2(`Es gibt ${pageCount} Seiten für die Ressourcen`);
}
if(pageCount <= 1) {
$(`#apt-${prefix}-pag-divider, #apt-${prefix}-pag-dropdow-item`).hide();
return;
}
$(`#apt-${prefix}-pag-divider, #apt-${prefix}-pag-dropdow-item`).show();
var limit = lastShownButton;
if(pageCount < limit) {
limit = pageCount;
}
const firstPageLiClass = firstShownButton === 1 ? "page-item disabled" : "page-igem";
const lastPageLiClass = lastShownButton === pageCount ? "page-item disabled" : "page-igem";
const prevPageLiClass = activeButton === 1 ? "page-item disabled" : "page-item";
const nextPageLiClass = activeButton === pageCount ? "page-item disabled" : "page-igem";
$(`<li class="${firstPageLiClass}" id="first-page-li"><button type="button" class="page-link" tabeindex="-1" onclick="showPage(${1}, '${prefix}')"><span class="fas fa-angle-double-left"></span></button></li>`).appendTo(pagination);
$(`<li class="${prevPageLiClass}" id="prev-page-li"><button type="button" class="page-link" tabeindex="-1" onclick="showPage(${currentPage - 1}, '${prefix}')"><span class="fas fa-angle-left"></span></button></li>`).appendTo(pagination);
for(let i = firstShownButton; i <= limit; i++) {
$(`<li class="page-item ${(i === activeButton ? "active" : "")}"><button class="page-link" tabindex="-1" type="button" onclick="showPage(${i}, '${prefix}')">${i}</button></li>`).appendTo(pagination);
}
$(`<li class="${nextPageLiClass}" id="next-page-li"><button type="button" class="page-link" tabeindex="-1" onclick="showPage(${currentPage + 1}, '${prefix}')"><span class="fas fa-angle-right"></span></button></li>`).appendTo(pagination);
$(`<li class="${lastPageLiClass}" id="last-page-li"><button type="button" class="page-link" tabeindex="-1" onclick="showPage(${pageCount}, '${prefix}')"><span class="fas fa-angle-double-right"></span></button></li>`).appendTo(pagination);
}
function showPage(page, prefix) {
var pageCount = 1;
var items = [];
switch(prefix) {
case "emp":
pageCount = aptEmpSelPageCount;
items = aptEmpSelItems;
break;
case "cus":
pageCount = aptCusSelPageCount;
items = aptCusSelItems;
break;
case "res":
pageCount = aptResSelPageCount;
items = aptResSelItems;
break;
}
const total = (items.length / 10) | 0;
const currentPage = Math.max(1, Math.min(page, total));
switch(prefix) {
case "emp":
aptEmpSelCurrentPage = currentPage;
break;
case "cus":
aptCusSelCurrentPage = currentPage;
break;
case "res":
aptResSelCurrentPage = currentPage;
break;
}
const start = (currentPage - 1) * 10;
const end = currentPage * 10;
items.hide();
$.each(items.slice(start, end), function(index, item) {
$(item).removeClass("d-none");
$(item).show();
});
const last = Math.min(pageCount, currentPage + 2);
const first = Math.max(1, last - 4);
buildPagination(first, last, currentPage, prefix);
}
function updateEmployeeCustomerResourceSelection(prefix) {
const checkedBoxes = $(`#dropdown-${prefix}-itm-container input[type=checkbox]:checked`);
var url = "";
switch(prefix) {
case "emp":
url = "@Url.Action("UpdateAppointmentEmployeeSelection")";
break;
case "cus":
url = "@Url.Action("UpdateAppointmentCustomerSelection")";
break;
case "res":
url = "@Url.Action("UpdateAppointmentResourceSelection")";
break;
}
var selectedOids = [];
checkedBoxes.each(function() {
const id = $(this).prop("id");
const employeeOid = id.split("-")[3];
selectedOids.push(employeeOid.toString());
});
showSpinner();
$.get(
url,
{ selectedOids: selectedOids.join(", ") },
function() {
hideSpinner();
});
}
function selectAllEmployeeCustomerResource(prefix) {
const isChecked = $(`#apt-${prefix}-select-all`).prop("checked");
$(`#dropdown-${prefix}-itm-container input[type=checkbox]`).prop("checked", isChecked);
updateEmployeeCustomerResourceSelection(prefix);
}
function categoryCardHeaderClick(collapsibleId) {
const collapsible = $(`#${collapsibleId}`);
if(collapsible.length === false) {
return;
}
collapsible.collapse("toggle");
const e = window.event;
e.cancelBubble = true;
if(e.stopPropagation) {
e.stopPropagation();
}
}
function onNewResourceSeachInput() {
var searchText = $(`#res-drop-search-input`).val().toLowerCase();
const category2Resources = $(`#dropdown-res-itm-container .dropdown-item`);
const collapse = $(`#dropdown-res-itm-container .dropdown-item .collapse`);
if(searchText === null || searchText === undefined || searchText.length === 0) {
showAllResources();
return;
}
category2Resources.hide();
$.each(category2Resources,
function(index, item) {
const categoryName = $(item).find("h6").text().toLowerCase();
if(categoryName.includes(searchText)) {
$(item).show();
}
const resources = $(item).find("form");
resources.hide();
$.each(resources, function(resourceIndex, resourceItem) {
const itemText = $(resourceItem).text().toLowerCase();
if(itemText.includes(searchText)) {
$(resourceItem).show();
$(item).show();
collapse.collapse("show");
}
});
}
);
}
function resetNewResourceSearch() {
$(`#res-drop-search-input`).val("");
showAllResources();
buildPagination(1, 5, 1, "res");
showPage(1, "res");
const e = window.event;
e.cancelBubble = true;
if(e.stopPropagation) {
e.stopPropagation();
}
}
function showAllResources() {
const category2Resources = $(`#dropdown-res-itm-container .dropdown-item`);
const collapse = $(`#dropdown-res-itm-container .dropdown-item .collapse`);
$.each(category2Resources, function(cardIndex, card) {
$(card).show();
const resources = $(item).find("form");
$.each(resources, function(formIndex, form) {
$(form).show();
});
});
collapse.collapse("show");
}
@* /CustomECRSelectionPartial *@
</script>
<div class="dropdown">

View File

@@ -253,6 +253,8 @@
SelectedEmployee2SchedulerAppointments = employees2Appointment,
SelectedCustomers = customerList,
SelectedResources = resourceList,
SelectedCustomerOids = customerList?.Select(customer => customer.CustomerOid)?.ToList() ?? new List<long>(),
SelectedResourceOids = resourceList?.Select(resource => resource.ResourceOid.Value)?.ToList() ?? new List<long>(),
SelectedEmployeeOids = employees2Appointment.Select(employee2Appointment => employee2Appointment.Employee.EmployeeOid).ToList(),
CompletedNotice = container.Appointment.CustomFields["CompletedNotice"]?.ToString(),
CompletedUser = container.Appointment.CustomFields["CompletedUser"]?.ToString(),