Views in Partials aufgeteilt
Intervallfinder hinzugefügt
This commit is contained in:
File diff suppressed because it is too large
Load Diff
11
BeWo/packages.config
Normal file
11
BeWo/packages.config
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="ClrHeapAllocationAnalyzer" version="3.0.0" targetFramework="net45" />
|
||||
<package id="CsvHelper" version="15.0.5" targetFramework="net45" />
|
||||
<package id="Microsoft.CSharp" version="4.5.0" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net45" />
|
||||
<package id="RestSharp" version="105.2.3" targetFramework="net45" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net45" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net45" />
|
||||
<package id="System.ValueTuple" version="4.4.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -24,7 +24,7 @@
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile />
|
||||
<TargetFrameworkProfile />
|
||||
<Use64BitIISExpress />
|
||||
<Use64BitIISExpress>false</Use64BitIISExpress>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<TypeScriptToolsVersion>3.7</TypeScriptToolsVersion>
|
||||
@@ -87,8 +87,8 @@
|
||||
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.12.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.12\lib\net45\log4net.dll</HintPath>
|
||||
<Reference Include="log4net, Version=2.0.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.13\lib\net45\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=3.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.3.6.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
|
||||
@@ -103,8 +103,8 @@
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="RestSharp, Version=106.12.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RestSharp.106.12.0\lib\net452\RestSharp.dll</HintPath>
|
||||
<Reference Include="RestSharp, Version=106.13.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\RestSharp.106.13.0\lib\net452\RestSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
@@ -812,8 +812,8 @@
|
||||
<Content Include="Scripts\jquery-3.6.0.slim.min.js" />
|
||||
<Content Include="Scripts\devexpress-scripts\knockout-3.5.1.js" />
|
||||
<None Include="Scripts\jquery.validate-vsdoc.js" />
|
||||
<Content Include="Scripts\jquery-ui-1.12.1.js" />
|
||||
<Content Include="Scripts\jquery-ui-1.12.1.min.js" />
|
||||
<Content Include="Scripts\jquery-ui-1.13.0.js" />
|
||||
<Content Include="Scripts\jquery-ui-1.13.0.min.js" />
|
||||
<Content Include="Scripts\jquery.validate.js" />
|
||||
<Content Include="Scripts\jquery.validate.min.js" />
|
||||
<Content Include="Scripts\jquery.validate.unobtrusive.js" />
|
||||
@@ -1324,6 +1324,8 @@
|
||||
<Content Include="Scripts\umd\popper-utils.min.js" />
|
||||
<Content Include="Scripts\umd\popper.js" />
|
||||
<Content Include="Scripts\umd\popper.min.js" />
|
||||
<Content Include="Scripts\utils\list-utils.js" />
|
||||
<Content Include="Scripts\utils\resources-list-utils.js" />
|
||||
<Content Include="Scripts\utils\trimCanvas.js" />
|
||||
<Content Include="Scripts\utils\dateUtils.js" />
|
||||
<Content Include="Scripts\view-scripts\report.js" />
|
||||
@@ -1365,6 +1367,11 @@
|
||||
<Content Include="Views\Scheduler\FiveDaySchedulerPartial.cshtml" />
|
||||
<Content Include="Views\Scheduler\OneDaySchedulerPartial.cshtml" />
|
||||
<Content Include="Views\Scheduler\SevenDaySchedulerPartial.cshtml" />
|
||||
<Content Include="Views\Scheduler\AppointmentIntervalFinderPartial.cshtml" />
|
||||
<Content Include="Views\Scheduler\AppointmentIntervalFinderResultPartial.cshtml" />
|
||||
<Content Include="Views\Scheduler\AppointmentFormPartial.cshtml" />
|
||||
<Content Include="Views\Main\GroupBookingPartial.cshtml" />
|
||||
<Content Include="Views\Main\SingleBookingPartial.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="App_Data\" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<UseIISExpress>false</UseIISExpress>
|
||||
<Use64BitIISExpress />
|
||||
<Use64BitIISExpress>false</Use64BitIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
|
||||
@@ -95,4 +95,8 @@ $theme-colors: ( "bewo-goal-rating": #0000ff,"bewo-dev": #00cf7c, "primary": #FF
|
||||
}
|
||||
$font-family-sans-serif: 'Signika Negative', sans-serif;
|
||||
|
||||
.interval-finder-customer-text {}
|
||||
|
||||
// col-xxl 1200px und col-xxxl 1800px
|
||||
|
||||
@import "../node_modules/bootstrap/scss/bootstrap";
|
||||
@@ -23,7 +23,9 @@ namespace BeWoPlanerMobil.Controllers
|
||||
ViewData[LoginErrorIndex] = string.Empty;
|
||||
TempData[LoginErrorIndex] = string.Empty;
|
||||
|
||||
if (MobileSessionFacade.IsUserLoggedIn() && !Request.Browser.Browser.Equals("InternetExplorer"))
|
||||
var isUserLoggedIn = MobileSessionFacade.IsUserLoggedIn();
|
||||
|
||||
if (isUserLoggedIn && !Request.Browser.Browser.Equals("InternetExplorer"))
|
||||
{
|
||||
var loginState = MobileUtils.GetLoginState(MobileSessionFacade.Tenant);
|
||||
|
||||
@@ -67,7 +69,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
return RedirectToActionPermanent("Main", "Main");
|
||||
}
|
||||
|
||||
if(MobileSessionFacade.IsUserLoggedIn() && Request.Browser.Browser.Equals("InternetExplorer"))
|
||||
if(isUserLoggedIn && Request.Browser.Browser.Equals("InternetExplorer"))
|
||||
{
|
||||
MobileSessionFacade.LogUserOut();
|
||||
FormsAuthentication.SignOut();
|
||||
|
||||
@@ -175,6 +175,8 @@ namespace BeWoPlanerMobil.Controllers
|
||||
Model.Employees = new List<CompactEmployeeDC> { MobileSessionFacade.LoggedInCompactEmployee };
|
||||
}
|
||||
|
||||
Model.Employees = Model.Employees.OrderBy(e => e.LastName).ThenBy(e => e.FirstName).ToList();
|
||||
|
||||
if(Model?.Employee?.EmployeeOid.HasValue ?? false)
|
||||
{
|
||||
Model.SupportConcepts = EmployeeService.GetActiveSupportConceptsForEmployee(Model.Employee.EmployeeOid, Model.SelectedSupportConceptFilter);
|
||||
|
||||
@@ -237,15 +237,28 @@ namespace BeWoPlanerMobil.Controllers
|
||||
var location = formCollection[FormCollectionConstants.AppointmentLocationKey];
|
||||
var notice = formCollection[FormCollectionConstants.AppointmentNoticeKey];
|
||||
|
||||
var isPrivate = formCollection[FormCollectionConstants.AppointmentIsPrivate] == "true,false";
|
||||
var allDay = formCollection[FormCollectionConstants.AppointmentIsAllDay] == "true,false";
|
||||
|
||||
var isSuccessfulStartTime = DateTime.TryParseExact(rawStartTime, "HH:mm", null, DateTimeStyles.None, out var startTime);
|
||||
var isSuccessfulEndTime = DateTime.TryParseExact(rawEndTime, "HH:mm", null, DateTimeStyles.None, out var endTime);
|
||||
|
||||
if(rawStartTime == null)
|
||||
{
|
||||
rawStartTime = "00:00";
|
||||
}
|
||||
|
||||
if (rawEndTime == null)
|
||||
{
|
||||
rawEndTime = "00:00";
|
||||
}
|
||||
|
||||
var startAndEnd = ConvertStringDatesToDateTimes($"{rawStartDate} {rawStartTime}", $"{rawEndDate} {rawEndTime}");
|
||||
|
||||
var startDate = startAndEnd.StartDate;
|
||||
var endDate = startAndEnd.EndDate;
|
||||
|
||||
if (isSuccessfulStartTime && isSuccessfulEndTime)
|
||||
if (!allDay && isSuccessfulStartTime && isSuccessfulEndTime || allDay)
|
||||
{
|
||||
startDate = startDate.MergeDatesByDate(startTime);
|
||||
endDate = endDate.MergeDatesByDate(endTime);
|
||||
@@ -279,6 +292,8 @@ namespace BeWoPlanerMobil.Controllers
|
||||
appointmentToInsert.Originator = MobileSessionFacade.LoggedInCompactEmployee;
|
||||
appointmentToInsert.Location = location;
|
||||
appointmentToInsert.ActivationType = ActivationTypeId.Active;
|
||||
appointmentToInsert.IsPrivate = isPrivate;
|
||||
appointmentToInsert.AllDay = allDay;
|
||||
|
||||
if (!isNew)
|
||||
{
|
||||
@@ -380,9 +395,15 @@ namespace BeWoPlanerMobil.Controllers
|
||||
if (isSuccessful)
|
||||
{
|
||||
Model.SelectedAppointment = Model.Appointments.FirstOrDefault(app => app.SchedulerAppointmentOid.HasValue && app.SchedulerAppointmentOid.Value == appointmentOid);
|
||||
Model.SelectedResources = Model.SelectedAppointment?.ResourceList ?? new List<ResourceDC>();
|
||||
Model.SelectedEmployees = Model.SelectedAppointment?.EmployeeList.Select(e2a => e2a.Employee).ToList() ?? new List<CompactEmployeeDC>();
|
||||
Model.SelectedCustomers = Model.SelectedAppointment?.CustomerList ?? new List<CompactCustomerDC>();
|
||||
|
||||
if(Model.SelectedAppointment != null)
|
||||
{
|
||||
Model.IsAllDay = Model.SelectedAppointment.AllDay;
|
||||
Model.IsPrivate = Model.SelectedAppointment.IsPrivate;
|
||||
Model.SelectedResources = Model.SelectedAppointment?.ResourceList ?? new List<ResourceDC>();
|
||||
Model.SelectedEmployees = Model.SelectedAppointment?.EmployeeList.Select(e2a => e2a.Employee).ToList() ?? new List<CompactEmployeeDC>();
|
||||
Model.SelectedCustomers = Model.SelectedAppointment?.CustomerList ?? new List<CompactCustomerDC>();
|
||||
}
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
@@ -395,6 +416,8 @@ namespace BeWoPlanerMobil.Controllers
|
||||
{
|
||||
Model.SelectedAppointment = null;
|
||||
Model.SelectedResources.Clear();
|
||||
Model.IsAllDay = false;
|
||||
Model.IsPrivate = false;
|
||||
}
|
||||
|
||||
return Json(null, JsonRequestBehavior.AllowGet);
|
||||
@@ -467,7 +490,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public string SelectEmployeesForAppointment(string employeeOids)
|
||||
public string SelectEmployeesForAppointment(string oidString)
|
||||
{
|
||||
if (Model == null)
|
||||
{
|
||||
@@ -475,7 +498,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
var oidList = ConvertOidStringToList(employeeOids);
|
||||
var oidList = ConvertOidStringToList(oidString);
|
||||
|
||||
Model.SelectedEmployees = Model.AllEmployees.Where(employee => oidList.Contains(employee.EmployeeOid)).ToList();
|
||||
|
||||
@@ -483,7 +506,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public string SelectCustomersForAppointment(string customerOids)
|
||||
public string SelectCustomersForAppointment(string oidString)
|
||||
{
|
||||
if (Model == null)
|
||||
{
|
||||
@@ -491,7 +514,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
var oidList = ConvertOidStringToList(customerOids);
|
||||
var oidList = ConvertOidStringToList(oidString);
|
||||
|
||||
Model.SelectedCustomers = Model.AllCustomers.Where(customer => oidList.Contains(customer.CustomerOid)).ToList();
|
||||
|
||||
@@ -549,5 +572,177 @@ namespace BeWoPlanerMobil.Controllers
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost]
|
||||
public ActionResult FindFreeIntervals(FormCollection formCollection)
|
||||
{
|
||||
if(Model == null)
|
||||
{
|
||||
return Logout();
|
||||
}
|
||||
|
||||
var d = formCollection["Duration"];
|
||||
var s = formCollection["IntervalStart"];
|
||||
var st = formCollection["IntervalStartTime"];
|
||||
var e = formCollection["IntervalEnd"];
|
||||
var et = formCollection["IntervalEndTime"];
|
||||
|
||||
if (int.TryParse(d, out var duration) && DateTime.TryParse($"{s} {st}", out var start) && DateTime.TryParse($"{e} {et}", out var end) && Model.Employee.EmployeeOid.HasValue)
|
||||
{
|
||||
var customerOids = Model.SelectedCustomersForIntervalFinder.Select(c => c.CustomerOid).ToList();
|
||||
var employeeOids = Model.SelectedEmployeesForIntervalFinder.Select(m => m.EmployeeOid).ToList();
|
||||
var resourceOids = Model.SelectedResourcesForIntervalFinder.Where(w => w.ResourceOid.HasValue).Select(r => r.ResourceOid.Value).ToList();
|
||||
|
||||
Model.FreeIntervals = KalenderService.FindAppointmentsInRange(duration, start, end, resourceOids, customerOids, employeeOids, Model.Employee.EmployeeOid.Value);
|
||||
|
||||
Model.IntervalStartDate = start;
|
||||
Model.IntervalEndDate = end;
|
||||
Model.IntervalDuration = duration;
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public string SelectEmployeesForIntervalFinder(string oidString)
|
||||
{
|
||||
if (Model == null)
|
||||
{
|
||||
Logout();
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
var employeeOids = ConvertOidStringToList(oidString);
|
||||
|
||||
Model.SelectedEmployeesForIntervalFinder = Model.AllEmployees.Where(employee => employeeOids.Contains(employee.EmployeeOid)).ToList();
|
||||
|
||||
return JsonConvert.SerializeObject(Model.SelectedEmployeesForIntervalFinder.OrderBy(o => o.DetailDescription));
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public string SelectCustomersForIntervalFinder(string oidString)
|
||||
{
|
||||
if (Model == null)
|
||||
{
|
||||
Logout();
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
var customerOids = ConvertOidStringToList(oidString);
|
||||
|
||||
Model.SelectedCustomersForIntervalFinder = Model.AllCustomers.Where(customer => customerOids.Contains(customer.CustomerOid)).ToList();
|
||||
|
||||
return JsonConvert.SerializeObject(Model.SelectedCustomersForIntervalFinder.OrderBy(o => o.LastNameFirstName));
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public string SelectResourcesForIntervalFinder(string resourceOids)
|
||||
{
|
||||
if (Model == null)
|
||||
{
|
||||
Logout();
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
var resourceOidList = ConvertOidStringToList(resourceOids);
|
||||
|
||||
var list = new List<ResourceDC>();
|
||||
|
||||
Model.ResourceCategories2Resources.Values.DoForEach(l => l.DoForEach(s => list.AddIfNotIn(s)));
|
||||
|
||||
Model.SelectedResourcesForIntervalFinder = list.Where(resource => resource.ResourceOid.HasValue && resourceOidList.Contains(resource.ResourceOid.Value)).ToList();
|
||||
|
||||
return JsonConvert.SerializeObject(Model.SelectedResourcesForIntervalFinder);
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost]
|
||||
public ActionResult SetIsInIntervalFinderMode(FormCollection formCollection)
|
||||
{
|
||||
if(Model == null)
|
||||
{
|
||||
return Logout();
|
||||
}
|
||||
|
||||
var newValue = !Model.IsInIntervalFinderMode;
|
||||
|
||||
Model.IsInIntervalFinderMode = newValue;
|
||||
|
||||
if(!newValue)
|
||||
{
|
||||
Model.SelectedEmployeesForIntervalFinder.Clear();
|
||||
Model.SelectedCustomersForIntervalFinder.Clear();
|
||||
Model.SelectedResourcesForIntervalFinder.Clear();
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost]
|
||||
public ActionResult SelectIntervalForForm(FormCollection formCollection)
|
||||
{
|
||||
if(Model == null)
|
||||
{
|
||||
return Logout();
|
||||
}
|
||||
|
||||
var startStr = formCollection["startDate"];
|
||||
var endStr = formCollection["endDate"];
|
||||
|
||||
if(DateTime.TryParse(startStr, out var startDate) && DateTime.TryParse(endStr, out var endDate))
|
||||
{
|
||||
Model.IsInIntervalFinderMode = false;
|
||||
|
||||
var employees2Appointment = new List<Employee2SchedulerAppointmentDC>();
|
||||
|
||||
Model.SelectedEmployeesForIntervalFinder.DoForEach(employee =>
|
||||
{
|
||||
employees2Appointment.Add(new Employee2SchedulerAppointmentDC
|
||||
{
|
||||
Employee = employee
|
||||
});
|
||||
});
|
||||
|
||||
Model.SelectedAppointment = new SchedulerAppointmentDC()
|
||||
{
|
||||
ActivationType = ActivationTypeId.Active,
|
||||
IsTask = false,
|
||||
IsPrivate = false,
|
||||
Originator = MobileSessionFacade.LoggedInCompactEmployee,
|
||||
StartDate = startDate,
|
||||
EndDate = endDate
|
||||
};
|
||||
|
||||
Model.SelectedCustomers = Model.SelectedCustomersForIntervalFinder.Clone();
|
||||
Model.SelectedEmployees = Model.SelectedEmployeesForIntervalFinder.Clone();
|
||||
Model.SelectedResources = Model.SelectedResourcesForIntervalFinder.Clone();
|
||||
|
||||
Model.SelectedCustomersForIntervalFinder.Clear();
|
||||
Model.SelectedEmployeesForIntervalFinder.Clear();
|
||||
Model.SelectedResourcesForIntervalFinder.Clear();
|
||||
|
||||
Model.IntervalStartDate = null;
|
||||
Model.IntervalEndDate = null;
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public string ResetIntervalFinder()
|
||||
{
|
||||
if(Model == null)
|
||||
{
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
Model.SelectedCustomersForIntervalFinder.Clear();
|
||||
Model.SelectedEmployeesForIntervalFinder.Clear();
|
||||
Model.SelectedResourcesForIntervalFinder.Clear();
|
||||
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Web.Mvc;
|
||||
using BeWoPlanerMobil.Service;
|
||||
using BeWoPlanerMobil.Util;
|
||||
using BS.Shared;
|
||||
using BS.Shared.Core;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.DataContracts.Compact;
|
||||
using BS.Shared.Extensions;
|
||||
@@ -132,35 +133,7 @@ namespace BeWoPlanerMobil.Models
|
||||
public List<CompactCustomerDC> SelectedCustomers { get; set; } = new List<CompactCustomerDC>();
|
||||
|
||||
public bool IsInEditMode => SelectedAppointment != null;
|
||||
|
||||
// Wird nicht benötigt
|
||||
public string ColWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
var isOwnAppointment = !IsInEditMode || SelectedAppointment.Originator.EmployeeOid == Employee.EmployeeOid;
|
||||
|
||||
var v1 = HasRightToInsertEmployeeAppointments || IsInEditMode && HasRightToEditEmployeeAppointments;
|
||||
|
||||
var v2 = HasRightToInsertRessourceAppointments || IsInEditMode && HasRightToEditResourceAppointments;
|
||||
|
||||
if(IsInEditMode && !isOwnAppointment)
|
||||
{
|
||||
v2 = HasRightToEditOthersResourceAppointments;
|
||||
}
|
||||
|
||||
var v3 = HasRightToInsertCustomerAppointments || IsInEditMode && HasRightToEditCustomerAppointments;
|
||||
|
||||
var a = v1 ? 1 : 0;
|
||||
var b = v2 ? 1 : 0;
|
||||
var c = v3 ? 1 : 0;
|
||||
|
||||
var dividend = a + b + c;
|
||||
|
||||
return dividend == 0 ? "col-12" : $"col-{12 / a + b + c}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool HasResourcesEmployeesOrCustomers
|
||||
{
|
||||
get
|
||||
@@ -184,6 +157,32 @@ namespace BeWoPlanerMobil.Models
|
||||
|
||||
public bool ShowEmployeeButton => IsInEditMode ? HasRightToInsertEmployeeAppointments : HasRightToEditEmployeeAppointments;
|
||||
public bool ShowCustomerButton => IsInEditMode ? HasRightToInsertCustomerAppointments : HasRightToEditCustomerAppointments;
|
||||
|
||||
//IntervalFinder
|
||||
public List<CompactEmployeeDC> SelectedEmployeesForIntervalFinder { get; set; } = new List<CompactEmployeeDC>();
|
||||
public List<CompactCustomerDC> SelectedCustomersForIntervalFinder { get; set; } = new List<CompactCustomerDC>();
|
||||
public List<ResourceDC> SelectedResourcesForIntervalFinder { get; set; } = new List<ResourceDC>();
|
||||
|
||||
public Dictionary<DateTime, List<DateTimeSpan>> FreeIntervals { get; set; } = new Dictionary<DateTime, List<DateTimeSpan>>();
|
||||
|
||||
public bool IsInIntervalFinderMode { get; set; }
|
||||
public DateTime? IntervalStartDate { get; set; }
|
||||
public DateTime? IntervalEndDate { get; set; }
|
||||
|
||||
public string IntervalStartDateStr => IntervalStartDate.HasValue ? $"{IntervalStartDate:dd.MM.yyyy}" : string.Empty;
|
||||
public string IntervalEndDateStr => IntervalEndDate.HasValue ? $"{IntervalEndDate:dd.MM.yyyy}" : string.Empty;
|
||||
public string IntervalStartTimeStr => IntervalStartDate.HasValue ? $"{IntervalStartDate:HH:mm}" : string.Empty;
|
||||
public string IntervalEndTimeStr => IntervalEndDate.HasValue ? $"{IntervalEndDate:HH:mm}" : string.Empty;
|
||||
|
||||
public int? IntervalDuration { get; set; }
|
||||
|
||||
public string IntervalDurationStr => IntervalDuration.HasValue ? $"{IntervalDuration}" : string.Empty;
|
||||
|
||||
[Display(Name = "Ganztägig")]
|
||||
public bool IsAllDay { get; set; }
|
||||
|
||||
[Display(Name = "Privat")]
|
||||
public bool IsPrivate { get; set; }
|
||||
}
|
||||
|
||||
public class WeekViewObject
|
||||
@@ -197,7 +196,7 @@ namespace BeWoPlanerMobil.Models
|
||||
public KeyValuePair<DateTime, List<AppointmentListItem>> SaturdayAppointments { get; set; }
|
||||
public KeyValuePair<DateTime, List<AppointmentListItem>> SundayAppointments { get; set; }
|
||||
|
||||
public WeekViewObject(IReadOnlyCollection<SchedulerAppointmentDC> appointments, DateTime monday)
|
||||
public WeekViewObject(IEnumerable<SchedulerAppointmentDC> appointments, DateTime monday)
|
||||
{
|
||||
var first = monday.Date;
|
||||
var last = first.AddDays(6);
|
||||
|
||||
@@ -117,7 +117,7 @@ function addEmployeeToGroupBooking() {
|
||||
|
||||
var oidString = "";
|
||||
|
||||
$("#employee-list input:checked").each(function() {
|
||||
$("#group-booking-employee-selection-popup input:checked").each(function() {
|
||||
var oid = $(this).val();
|
||||
|
||||
selectedEmployees.push(oid);
|
||||
|
||||
13
BeWoPlanerMobil/Scripts/jquery-ui-1.12.1.min.js
vendored
13
BeWoPlanerMobil/Scripts/jquery-ui-1.12.1.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
6
BeWoPlanerMobil/Scripts/jquery-ui-1.13.0.min.js
vendored
Normal file
6
BeWoPlanerMobil/Scripts/jquery-ui-1.13.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -28,6 +28,19 @@ function showMessagePopup(title, message) {
|
||||
);
|
||||
}
|
||||
|
||||
function showMessagePopupWithHtml(title, messageAsHtml) {
|
||||
$("#popupTitle").text(title);
|
||||
|
||||
$("#modal-body").html(messageAsHtml);
|
||||
|
||||
$("#messagePopup").modal(
|
||||
{
|
||||
backdrop: "static",
|
||||
keyboard: false
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function showMessagePopupWithCallback(title, message, callback, executeCallbackByBothButtons) {
|
||||
$("#popupTitle").text(title);
|
||||
|
||||
@@ -292,4 +305,33 @@ function toggleChevron(chevronId, cardBodyId) {
|
||||
|
||||
function validateNonEmptyString(stringValue) {
|
||||
return !isUndefinedOrNull(stringValue) && !isEmptyOrSpaces(stringValue) && typeof stringValue === "string";
|
||||
}
|
||||
}
|
||||
|
||||
function showCollapsable(collapsableElement) {
|
||||
try {
|
||||
if (collapsableElement === null || collapsableElement === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!collapsableElement.hasClass("show")) {
|
||||
collapsableElement.addClass("show");
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function hideCollapsable(collapsableElement) {
|
||||
try {
|
||||
if (collapsableElement === null || collapsableElement === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (collapsableElement.hasClass("show")) {
|
||||
collapsableElement.removeClass("show");
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,14 @@
|
||||
|
||||
$("#scheduler-start-date, #scheduler-end-date").val(moment().format("DD.MM.YYYY"));
|
||||
|
||||
$("#resources-popup input:checked").each(function() {
|
||||
$("#resources-popup input:checked, #customers-popup input:checked, #employees-popup input:checked").each(function() {
|
||||
$(this).prop("checked", false);
|
||||
});
|
||||
|
||||
$("#selected-resources-list").empty();
|
||||
$("#selected-resources-list, #selected-employees-list, #selected-customers-list").empty();
|
||||
|
||||
$("#IsAllDay").prop("checked", false);
|
||||
$("#IsPrivate").prop("checked", false);
|
||||
}
|
||||
|
||||
function submitInsertAppointmentForm() {
|
||||
@@ -28,13 +31,16 @@ function submitSchedulerDateForm() {
|
||||
}
|
||||
|
||||
function validateAppointmentForm() {
|
||||
var isAllDay = $("#IsAllDay").prop("checked") === true;
|
||||
|
||||
|
||||
var startTimePicker = $("#scheduler-start-time-picker");
|
||||
var startDatePicker = $("#scheduler-start-date-picker");
|
||||
var endTimePicker = $("#scheduler-end-time-picker");
|
||||
var endDatePicker = $("#scheduler-end-date-picker");
|
||||
|
||||
var isStartTimeInputEmpty = isEmptyOrSpaces($("#scheduler-start-time").val());
|
||||
var isEndTimeInputEmpty = isEmptyOrSpaces($("#scheduler-end-time").val());
|
||||
var isStartTimeInputEmpty = isAllDay ? false : isEmptyOrSpaces($("#scheduler-start-time").val());
|
||||
var isEndTimeInputEmpty = isAllDay ? false : isEmptyOrSpaces($("#scheduler-end-time").val());
|
||||
var isStartDateInputEmpty = isEmptyOrSpaces($("#scheduler-start-date").val());
|
||||
var isEndDateInputEmpty = isEmptyOrSpaces($("#scheduler-end-date").val());
|
||||
|
||||
@@ -57,14 +63,15 @@ function validateAppointmentForm() {
|
||||
|
||||
var a = startDate === undefined || startDate === null || !startDate.isValid();
|
||||
var b = endDate === undefined || endDate === null || !endDate.isValid();
|
||||
var c = startTime === undefined || startTime === null || !startTime.isValid();
|
||||
var d = endTime === undefined || endTime === null || !endTime.isValid();
|
||||
|
||||
if(a || b || c || d || isStartDateInputEmpty || isStartTimeInputEmpty || isEndTimeInputEmpty || isEndDateInputEmpty) {
|
||||
var c = isAllDay ? false : startTime === undefined || startTime === null || !startTime.isValid();
|
||||
var d = isAllDay ? false : endTime === undefined || endTime === null || !endTime.isValid();
|
||||
|
||||
if (a || b || c || d || isStartDateInputEmpty || isStartTimeInputEmpty || isEndTimeInputEmpty || isEndDateInputEmpty) {
|
||||
|
||||
hideSpinner();
|
||||
$("#messagePopup .modal-body").html('<div class="alert alert-danger" role="alert">Die Zeit- und/oder Datumsangaben sind nicht korrekt.</div>');
|
||||
showMessagePopup("Fehler");
|
||||
|
||||
showMessagePopupWithHtml("Fehler", '<div class="alert alert-danger" role="alert">Die Zeit- und/oder Datumsangaben sind nicht korrekt.</div>');
|
||||
|
||||
$("#scheduler-start-time, #scheduler-end-time").val("");
|
||||
return;
|
||||
}
|
||||
@@ -73,11 +80,23 @@ function validateAppointmentForm() {
|
||||
endDate = startDate.clone();
|
||||
}
|
||||
|
||||
startDate = startDate.hours(startTime.hours());
|
||||
startDate = startDate.minutes(startTime.minutes());
|
||||
var startHours = 0;
|
||||
var startMinutes = 0;
|
||||
var endHours = 0;
|
||||
var endMinutes = 0;
|
||||
|
||||
endDate = endDate.hours(endTime.hours());
|
||||
endDate = endDate.minutes(endTime.minutes());
|
||||
if(isAllDay === false) {
|
||||
startHours = startTime.hours();
|
||||
startMinutes = startTime.minutes();
|
||||
endHours = endTime.hours();
|
||||
endMinutes = endTime.minutes();
|
||||
}
|
||||
|
||||
startDate = startDate.hours(startHours);
|
||||
startDate = startDate.minutes(startMinutes);
|
||||
|
||||
endDate = endDate.hours(endHours);
|
||||
endDate = endDate.minutes(endMinutes);
|
||||
|
||||
if(endDate.isBefore(startDate)) {
|
||||
hideSpinner();
|
||||
@@ -180,14 +199,18 @@ function insertOrUpdateAppointment(formattedStartDate, formattedEndDate, formatt
|
||||
}
|
||||
|
||||
function hideAppointmentForm() {
|
||||
logDebug("hiding appointment form");
|
||||
$("#form-container").addClass("d-none d-sm-none");
|
||||
}
|
||||
|
||||
function showAppointmentForm() {
|
||||
logDebug("showing appointment form");
|
||||
$("#form-container").removeClass("d-none d-sm-none");
|
||||
}
|
||||
|
||||
function toggleAppointmentForm() {
|
||||
logError("toggling appointment form");
|
||||
|
||||
var isVisible = $("#form-container").css("display") === "block";
|
||||
|
||||
if (isVisible) {
|
||||
@@ -197,183 +220,113 @@ function toggleAppointmentForm() {
|
||||
}
|
||||
}
|
||||
|
||||
function changeResourceSelection() {
|
||||
var selectedOids = [];
|
||||
var oidString = "";
|
||||
function listSearchOnChange(searchInputId, entryClass, textClass) {
|
||||
try {
|
||||
var text = $("#" + searchInputId).val().toLowerCase();
|
||||
|
||||
$("#resources-popup input:checked").each(function() {
|
||||
var id = $(this).attr("id");
|
||||
|
||||
selectedOids.push(id.split("-")[0]);
|
||||
});
|
||||
var entries = $("." + entryClass);
|
||||
|
||||
for (var i = 0; i < selectedOids.length; i++) {
|
||||
oidString += selectedOids[i] + ",";
|
||||
if (text.length === 0) {
|
||||
entries.show();
|
||||
}
|
||||
|
||||
$.each(entries, function (index, item) {
|
||||
var customer = $(item);
|
||||
|
||||
if (customer.find("." + textClass).text().toLowerCase().includes(text)) {
|
||||
customer.show();
|
||||
} else {
|
||||
customer.hide();
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
logError(error.message);
|
||||
}
|
||||
|
||||
$.get(getSelectResourcesForAppointmentUrl(), { resourceOids: oidString }).done(updateSelectedResourceList);
|
||||
}
|
||||
|
||||
function updateSelectedResourceList(jsonResult) {
|
||||
var list = $("#selected-resources-list");
|
||||
|
||||
list.empty();
|
||||
|
||||
if (isEmptyOrSpaces(jsonResult)) {
|
||||
return;
|
||||
function resetSearch(searchInputId, entryClass) {
|
||||
try {
|
||||
$("#" + searchInputId).val("");
|
||||
$("." + entryClass).show();
|
||||
} catch (error) {
|
||||
logError(error.message);
|
||||
}
|
||||
|
||||
var resourceList = $.parseJSON(jsonResult);
|
||||
|
||||
$.each(resourceList, function(index, customListItem) {
|
||||
var html =
|
||||
"<div class='list-group-item' id='relation-item-" + customListItem.ResourceOid + "'>" +
|
||||
"<div class='row'>" +
|
||||
"<div class='col my-auto'>" +
|
||||
"<i class='fas fa-cubes text-bewo-resource mr-2'></i>" + customListItem.Name +
|
||||
"</div>" +
|
||||
"<div class='col-auto my-auto'>" +
|
||||
"<button type='button' class='btn btn-primary' onclick='removeSelectedResource(" + customListItem.ResourceOid + ")'>" +
|
||||
"<span class='fas fa-times-circle'></span>" +
|
||||
"</button>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
|
||||
list.append(html);
|
||||
});
|
||||
}
|
||||
|
||||
function removeSelectedResource(resourceOid) {
|
||||
$("#relation-item-" + resourceOid).remove();
|
||||
function resourceSearchOnChange(searchInputId) {
|
||||
try {
|
||||
var text = $("#" + searchInputId).val().toLowerCase();
|
||||
|
||||
var checkbox = $("#" + resourceOid + "-checkbox");
|
||||
var entries = $(".resource-text");
|
||||
|
||||
if (checkbox.length) {
|
||||
checkbox.prop("checked", false);
|
||||
if (text.length === 0 || !text.replace(/\s\g/, '').length) {
|
||||
resetResourceSearch(searchInputId);
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(entries, function (index, entry) {
|
||||
var checkbox = $(entry);
|
||||
var categoryCard = checkbox.closest(".category-card");
|
||||
var list = categoryCard.find(".collapse");
|
||||
var resourceName = checkbox.find(".resource-name-label").text().toLowerCase();
|
||||
var includesText = resourceName.includes(text);
|
||||
|
||||
if (includesText) {
|
||||
checkbox.show();
|
||||
categoryCard.show();
|
||||
showCollapsable($(list));
|
||||
} else {
|
||||
checkbox.hide();
|
||||
}
|
||||
});
|
||||
|
||||
var lists = $(".resource-list");
|
||||
|
||||
var cardsToHide = [];
|
||||
|
||||
$.each(lists, function (index, item) {
|
||||
var children = $(item).children();
|
||||
var hasAtLeastOneVisibleChild = false;
|
||||
var card = $(item).parent().parent();
|
||||
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var child = children[i];
|
||||
|
||||
hasAtLeastOneVisibleChild = $(child).css("display") === "block";
|
||||
|
||||
if (hasAtLeastOneVisibleChild === true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAtLeastOneVisibleChild === false) {
|
||||
cardsToHide.push(card);
|
||||
}
|
||||
});
|
||||
|
||||
$.each(cardsToHide, function (index, item) {
|
||||
$(item).hide();
|
||||
});
|
||||
} catch (error) {
|
||||
logError(error.message);
|
||||
}
|
||||
|
||||
changeResourceSelection();
|
||||
}
|
||||
|
||||
// Mitarbeiter
|
||||
function changeEmployeeSelection() {
|
||||
var selectedOids = [];
|
||||
var oidString = "";
|
||||
function resetResourceSearch(searchInputId) {
|
||||
try {
|
||||
logDebug("reset resource search: " + searchInputId);
|
||||
|
||||
$("#employees-popup input:checked").each(function () {
|
||||
var id = $(this).attr("id");
|
||||
$("#" + searchInputId).val("");
|
||||
|
||||
selectedOids.push(id.split("-")[1]);
|
||||
});
|
||||
var entries = $(".resource-text");
|
||||
var categoryCard = $(".category-card");
|
||||
var collapsable = categoryCard.find(".collapse");
|
||||
|
||||
for (var i = 0; i < selectedOids.length; i++) {
|
||||
oidString += selectedOids[i] + ",";
|
||||
entries.show();
|
||||
categoryCard.show();
|
||||
|
||||
hideCollapsable(collapsable);
|
||||
} catch(error) {
|
||||
logError(error.message);
|
||||
}
|
||||
|
||||
$.get(getSelectEmployeesForAppointmentUrl(), { employeeOids: oidString }).done(updateSelectedEmployeeList);
|
||||
}
|
||||
|
||||
function updateSelectedEmployeeList(jsonResult) {
|
||||
var list = $("#selected-employees-list");
|
||||
|
||||
list.empty();
|
||||
|
||||
if (isEmptyOrSpaces(jsonResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var employeeList = $.parseJSON(jsonResult);
|
||||
|
||||
$.each(employeeList, function (index, customListItem) {
|
||||
var html =
|
||||
"<div class='list-group-item my-auto' id='related-employee-" + customListItem.EmployeeOid + "'>" +
|
||||
"<div class='row'>" +
|
||||
"<div class='input-group'>" +
|
||||
"<div class='input-group-prepend'>" +
|
||||
"<i class='fas fa-user text-bewo-employee h-100'></i>" +
|
||||
"</div>" +
|
||||
"<p class='form-control border-0 bg-transparent text-truncate'>" + customListItem.LastName + ", " + customListItem.FirstName + "<p>" +
|
||||
"<div class='input-group-append'>" +
|
||||
"<button class='btn btn-primary' type='button' onclick='removeSelectedEmployee(" + customListItem.EmployeeOid + ")'><span class='fas fa-times-circle'></span></button>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
|
||||
list.append(html);
|
||||
});
|
||||
}
|
||||
|
||||
function removeSelectedEmployee(employeeOid) {
|
||||
$("#related-employee-" + employeeOid).remove();
|
||||
|
||||
var checkbox = $("#employee-" + employeeOid + "-checkbox");
|
||||
|
||||
if (checkbox.length) {
|
||||
checkbox.prop("checked", false);
|
||||
}
|
||||
|
||||
changeEmployeeSelection();
|
||||
}
|
||||
|
||||
// Klienten
|
||||
function changeCustomerSelection() {
|
||||
var selectedOids = [];
|
||||
var oidString = "";
|
||||
|
||||
$("#customers-popup input:checked").each(function () {
|
||||
var id = $(this).attr("id");
|
||||
|
||||
selectedOids.push(id.split("-")[1]);
|
||||
});
|
||||
|
||||
for (var i = 0; i < selectedOids.length; i++) {
|
||||
oidString += selectedOids[i] + ",";
|
||||
}
|
||||
|
||||
$.get(getSelectCustomersForAppointmentUrl(), { customerOids: oidString }).done(updateSelectedCustomerList);
|
||||
}
|
||||
|
||||
function updateSelectedCustomerList(jsonResult) {
|
||||
var list = $("#selected-customers-list");
|
||||
|
||||
list.empty();
|
||||
|
||||
if (isEmptyOrSpaces(jsonResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var customerList = $.parseJSON(jsonResult);
|
||||
|
||||
$.each(customerList, function (index, customListItem) {
|
||||
var html =
|
||||
"<div class='list-group-item my-auto' id='related-customer-item-" + customListItem.CustomerOid + "'>" +
|
||||
"<div class='row'>" +
|
||||
"<div class='input-group'>" +
|
||||
"<div class='input-group-prepend'>" +
|
||||
"<i class='fas fa-user text-bewo-customers h-100'></i>" +
|
||||
"</div>" +
|
||||
"<p class='form-control border-0 bg-transparent text-truncate'>" + customListItem.LastName + ", " + customListItem.FirstName+ "<p>" +
|
||||
"<div class='input-group-append'>" +
|
||||
"<button class='btn btn-primary' type='button' onclick='removeSelectedCustomer(" + customListItem.CustomerOid + ")'><span class='fas fa-times-circle'></span></button>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
|
||||
list.append(html);
|
||||
});
|
||||
}
|
||||
|
||||
function removeSelectedCustomer(customerOid) {
|
||||
$("#related-customer-" + customerOid).remove();
|
||||
|
||||
var checkbox = $("#customer-" + customerOid + "-checkbox");
|
||||
|
||||
if (checkbox.length) {
|
||||
checkbox.prop("checked", false);
|
||||
}
|
||||
|
||||
changeCustomerSelection();
|
||||
}
|
||||
@@ -49,6 +49,7 @@ namespace BeWoPlanerMobil.Service
|
||||
var serverPath = HttpContext.Current.Server.MapPath("");
|
||||
|
||||
serverPath = Path.Combine(serverPath, ConfigurationManager.AppSettings.Get("MultitenancyPath"));
|
||||
|
||||
serverPath = Path.Combine(serverPath, MobileSessionFacade.Tenant + ".config");
|
||||
|
||||
if (!File.Exists(serverPath))
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
public static string AppointmentNoticeKey => "Notice";
|
||||
public static string AppointmentSchedulerDateKey => "SchedulerDate";
|
||||
public static string AppointmentSchedulerOidHolderKey => "scheduler-oid-holder";
|
||||
public static string AppointmentIsPrivate => "IsPrivate";
|
||||
public static string AppointmentIsAllDay => "IsAllDay";
|
||||
|
||||
|
||||
// Auswertung
|
||||
|
||||
371
BeWoPlanerMobil/Views/Main/GroupBookingPartial.cshtml
Normal file
371
BeWoPlanerMobil/Views/Main/GroupBookingPartial.cshtml
Normal file
@@ -0,0 +1,371 @@
|
||||
@using BeWoPlanerMobil.Models
|
||||
@model BeWoPlanerMobil.Models.MainModel
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-12">
|
||||
@if (Model != null)
|
||||
{
|
||||
var submitButtonText = Model.IsInEditingMode ? "Speichern" : "Anlegen";
|
||||
|
||||
using (Html.BeginForm("CreateOrUpdateGroupBooking", "Main", FormMethod.Post, new { onreset = "serviceDescriptionSelectOnReset()", id = "groupBookingForm" }))
|
||||
{
|
||||
var startDate = Model.SelectedServiceRecord?.Start?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
|
||||
var endDate = Model.SelectedServiceRecord?.End?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
|
||||
|
||||
var startTime = Model.SelectedServiceRecord?.Start?.ToShortTimeString() ?? string.Empty;
|
||||
var endTime = Model.SelectedServiceRecord?.End?.ToShortTimeString() ?? string.Empty;
|
||||
|
||||
var duration = Model.SelectedServiceRecord?.GroupRoundedDuration?.ToString() ?? string.Empty;
|
||||
var distance = Model.SelectedServiceRecord?.DistanceInMeter?.ToString() ?? string.Empty;
|
||||
|
||||
var notice0 = Model.SelectedServiceRecord?.Notice ?? string.Empty;
|
||||
var noticeList = new[] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty };
|
||||
|
||||
if (Model.SelectedServiceRecord?.NoticeList != null)
|
||||
{
|
||||
var selectedNoticeList = Model.SelectedServiceRecord.NoticeList;
|
||||
for (var i = 0; i < selectedNoticeList.Count; i++)
|
||||
{
|
||||
noticeList[i] = selectedNoticeList[i] ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
<div class="mt-3">
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="alert alert-danger collapse" role="alert" id="form-alert">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary btn-block" data-toggle="modal" data-target="#group-booking-popup" id="support-concepts-and-groups-button">Hilfepläne und Gruppen hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-cb2sc-list">
|
||||
@foreach (var selectedCb2ScRelation in Model.GroupBookingSelectionObject.SelectedRelations)
|
||||
{
|
||||
<div class="list-group-item" id="relation-item-@selectedCb2ScRelation.Value">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span>
|
||||
@selectedCb2ScRelation.Text1
|
||||
<br />
|
||||
<span class="@selectedCb2ScRelation.TextColor">
|
||||
@selectedCb2ScRelation.Text2
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-auto my-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="removeCb2ScRelation(@selectedCb2ScRelation.Value)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<button type="button" class="btn btn-primary btn-block" data-toggle="modal" data-target="#group-booking-employee-selection-popup" id="employees-button">
|
||||
Mitarbeiter hinzufügen <span class="badge badge-light text-primary" id="selected-employees-count-badge">@Model.SelectedEmployees.Count</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
@Html.LabelFor(m => m.SelectedServiceCategoryOid)
|
||||
@Html.DropDownListFor(m => m.SelectedServiceCategoryOid, Model.ServiceCategoryListItems, new { onchange = "loadServiceDescriptions()", @class = "custom-select", Id = "category-select" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="leistung-select">Leistung</label>
|
||||
<select class="custom-select" id="leistung-select" name="ServiceDescription" onchange="setServiceDescription('leistung-select')"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Startdatum</label>
|
||||
<div class="input-group date" id="start-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-date" name="Datum" class="form-control datetimepicker-input" data-target="#start-date-picker" data-toggle="datetimepicker" value="@startDate" />
|
||||
<div class="input-group-append" data-target="#start-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.IsEndDateVisible)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Enddatum</label>
|
||||
<div class="input-group date" id="end-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-date" name="Enddatum" class="form-control datetimepicker-input" data-target="#end-date-picker" data-toggle="datetimepicker" value="@endDate" />
|
||||
<div class="input-group-append" data-target="#end-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-time">Von</label>
|
||||
<div class="input-group date" id="start-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@startTime" />
|
||||
<div class="input-group-append" data-target="#start-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="end-time">Bis</label>
|
||||
<div class="input-group date" id="end-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@endTime" />
|
||||
<div class="input-group-append" data-target="#end-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="duration">Dauer</label>
|
||||
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@duration">
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.IsZeiterfassungInStdMin)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="hours-minutes-dropdown-btn">Minuten/Stunden</label>
|
||||
<div class="dropdown">
|
||||
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
|
||||
Minuten
|
||||
</button>
|
||||
<div class="dropdown-menu w-100">
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Minuten</a>
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Stunden</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (Model.ShowDistanceField)
|
||||
{
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="distance">Gefahrene Kilometer</label>
|
||||
<input type="text" class="form-control" id="distance" name="Distanz" onchange="validateDistanceInput()" value="@distance">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AbstractModel.HasRightToSeeTextModules)
|
||||
{
|
||||
<div class="form-row" id="textmodule-container">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary form-control mt-3" data-toggle="modal" data-target="#textbausteine-popup" id="textbausteine-button">Textbausteine</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md mt-3">
|
||||
@if (Model.NumberOfDokuTypes == 0)
|
||||
{
|
||||
<div class="form-group">
|
||||
<label for="dokufeld">Dokumentation</label>
|
||||
<textarea class="form-control" name="Dokumentation6" id="dokufeld">@notice0</textarea>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-tabs" role="tab-list">
|
||||
@for (var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var currentDokuType = Model.Dokutypes[i];
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="#doku_@i" id="doku_@i-tab" data-toggle="tab" role="tab" aria-controls="doku_@i" class="nav-link@(i == 0 ? " active" : string.Empty)" aria-selected="true">
|
||||
@currentDokuType.DisplayName
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<div class="tab-content" id="dokufelderTab">
|
||||
@for (var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var textareaName = i + 1 < 1 ? "Dokumentation" : "Dokumentation" + (i + 1);
|
||||
|
||||
<div class="tab-pane show@(i == 0 ? " active" : string.Empty)" id="doku_@i" role="tabpanel" aria-labelledby="doku_@i-tab">
|
||||
<textarea class="form-control doku-form-control" id="doku-textarea-@i" name="@textareaName">@noticeList[i]</textarea>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="d-flex bd-highlight mt-3">
|
||||
<div class="mr-auto bd-highlight">
|
||||
<!-- dient nur als Abstandshalter-->
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
@using (Html.BeginForm("ResetEditingMode", "Main", FormMethod.Post))
|
||||
{
|
||||
<button type="submit" class="btn btn-primary" onclick="showSpinner()">Abbrechen</button>
|
||||
}
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="create-button" onclick="submitGroupBookingForm()">@submitButtonText</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- (Gruppenbuchung) Hilfeplan- und Gruppenauswahl Popup -->
|
||||
<div class="modal" data-backdrop="static" tabindex="-1" role="dialog" id="group-booking-popup">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Gruppen und Hilfepläne für Gruppenbuchung</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<nav class="nav nav-pills nav-fill">
|
||||
<a class="nav-item nav-link active" href="#group-booking-supportconcepts" data-toggle="tab" role="tab">Hilfepläne</a>
|
||||
<a class="nav-item nav-link" href="#group-booking-groups" data-toggle="tab" role="tab">Gruppen</a>
|
||||
</nav>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane show active" role="tabpanel" id="group-booking-supportconcepts">
|
||||
<ul class="list-group">
|
||||
@foreach (var cb2Sc in Model.SupportConceptListObjectsForGroupBooking)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
@{
|
||||
var timeSpanColorClass2 = cb2Sc.IsAboutToExpire ? "text-bewo-is-about-to-expire" : cb2Sc.ExpiresInThreeMonthsOrLess ? "text-bewo-expires-in-three-months" : "text-dark";
|
||||
|
||||
var wasSuccessful = long.TryParse(cb2Sc.CostBearer2SupportConceptOid, out var cb2ScOid);
|
||||
|
||||
var checkedValue = wasSuccessful ? Model.SelectedConceptCostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.Equals(cb2ScOid)) : wasSuccessful;
|
||||
}
|
||||
|
||||
<div class="custom-control custom-checkbox custom-control-inline">
|
||||
<input type="checkbox"
|
||||
@{ if (checkedValue) { @Html.Raw("checked=\"checked\"") ; } }
|
||||
class="custom-control-input" id="cb2sc-checkbox-@cb2Sc.CostBearer2SupportConceptOid" onchange="addCostBearer2SupportConceptsToGroupBooking()" name="cb2sc-checkbox-@cb2Sc.CostBearer2SupportConceptOid" value="@cb2Sc.CostBearer2SupportConceptOid">
|
||||
<label for="cb2sc-checkbox-@cb2Sc.CostBearer2SupportConceptOid" class="custom-control-label">
|
||||
<span class="justify-content-between mb-1 text-dark text-left">
|
||||
@cb2Sc.NameAndDateOfBirth
|
||||
</span>
|
||||
<br />
|
||||
<span class="mb-1 text-left @timeSpanColorClass2">
|
||||
@cb2Sc.SupportConceptTimeSpan
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-pane show" role="tabpanel" id="group-booking-groups">
|
||||
<ul class="list-group">
|
||||
@foreach (var group in Model.GroupOfPeopleListItems)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
@{
|
||||
long groupOid;
|
||||
var wasSuccessful = long.TryParse(group.Value, out groupOid);
|
||||
|
||||
var shouldBeChecked = wasSuccessful ? Model.SelectedGroupOfPeopleOids.Contains(groupOid) : wasSuccessful;
|
||||
|
||||
var attribute = shouldBeChecked ? "checked=\"checked\"" : string.Empty;
|
||||
}
|
||||
<div class="custom-control custom-checkbox custom-control-inline">
|
||||
<input type="checkbox" @attribute class="custom-control-input" id="group-checkbox-@group.Value" value="@group.Value" onchange="addCostBearer2SupportConceptsToGroupBooking()" />
|
||||
<label for="group-checkbox-@group.Value" class="custom-control-label">
|
||||
@group.Text
|
||||
</label>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- (Gruppenbuchung) Mitarbeiterauswahl Popup -->
|
||||
<div class="modal" tabindex="-1" role="dialog" id="group-booking-employee-selection-popup">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Mitarbeiter hinzufügen</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetSearch('gb-employee-search-input', 'employee-text')">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" id="gb-employee-search-input" placeholder="Suchen..." oninput="listSearchOnChange('gb-employee-search-input', 'employee-text', 'employee-name-label')" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="resetSearch('gb-employee-search-input', 'employee-text')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach (var employee in Model.Employees)
|
||||
{
|
||||
var checkedValue = Model.SelectedEmployees.Contains(employee) ? "checked=\"checked\"" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox employee-text">
|
||||
<input type="checkbox" @checkedValue class="custom-control-input" id="group-employee-@employee.EmployeeOid" onchange="addEmployeeToGroupBooking()" value="@employee.EmployeeOid" />
|
||||
<label for="group-employee-@employee.EmployeeOid" class="custom-control-label employee-name-label">@employee.DetailDescription</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -341,848 +341,20 @@
|
||||
<div class="container-fluid mb-3" id="main-container">
|
||||
@if(!Model.IsInGroupBookingMode)
|
||||
{
|
||||
<div class="row">
|
||||
<!-- Einzelbuchungsformular -->
|
||||
<div class="col col-12 col-md-5">
|
||||
@if(Model != null)
|
||||
{
|
||||
using(Html.BeginForm("SelectSupportConcept", "Main", FormMethod.Post, new { Id = "selectSupportConceptForm" }))
|
||||
{
|
||||
var selectedSuportConceptTimeSpanColorClass = Model.SelectedSupportConceptListObject.IsAboutToExpire ? "text-bewo-is-about-to-expire" : Model.SelectedSupportConceptListObject.ExpiresInThreeMonthsOrLess ? "text-bewo-expires-in-three-months" : "text-dark";
|
||||
<div>
|
||||
<div class="container p-0">
|
||||
<div class="row">
|
||||
<div class="col mt-3">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item flex-column align-items-start no-underline" data-toggle="modal" data-target="#supportConceptList">
|
||||
<div class="d-flex">
|
||||
<h5 class="mb-1 text-dark text-left" id="selectedSupportConceptCustomerInfo">@Model.SelectedSupportConceptListObject.NameAndDateOfBirth</h5>
|
||||
</div>
|
||||
<p class="mb-1 text-left @selectedSuportConceptTimeSpanColorClass" id="selectedSupportConceptInfo">
|
||||
@Model.SelectedSupportConceptListObject.SupportConceptTimeSpan
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@if(Model.CostBearer2SupportConceptOid != null && Model.CostBearer2SupportConceptOid > 0)
|
||||
{
|
||||
<div class="col-md-auto mt-3">
|
||||
<button type="button" class="btn btn-outline-primary w-100 h-100" id="statistics-button" data-toggle="modal" data-target="#statistics-popup" onclick="showPieChart()">
|
||||
<span class="d-md-none align-middle">Statistik</span>
|
||||
<span class="fas fa-chart-pie align-middle" style="font-size: 2rem;"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Hilfeplanauswahlpopup modal-dialog-centered-->
|
||||
<div class="modal" role="dialog" tabindex="-1" id="supportConceptList">
|
||||
<div class="modal-dialog text-center" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Hilfeplanauswahl</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Hilfeplansuche -->
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="supportConceptSearchOnChange()" id="support-concept-search-input" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="resetSupportConceptSearch()">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<!-- Hilfeplanliste -->
|
||||
<div class="list-group">
|
||||
@foreach(var supportConceptListObject in Model.SupportConceptListObjects)
|
||||
{
|
||||
var timeSpanColorClass = supportConceptListObject.IsAboutToExpire ? "text-bewo-is-about-to-expire" : supportConceptListObject.ExpiresInThreeMonthsOrLess ? "text-bewo-expires-in-three-months" : "text-dark";
|
||||
|
||||
<a href="#" class="list-group-item flex-column align-items-start no-underline blubb-test" onclick="selectSupportConcept(@supportConceptListObject.CostBearer2SupportConceptOid)" data-dismiss="modal">
|
||||
<div class="justify-content-between">
|
||||
<h5 class="mb-1 text-dark text-left supportconcept-name-header">
|
||||
@supportConceptListObject.NameAndDateOfBirth
|
||||
</h5>
|
||||
</div>
|
||||
<p class="mb-1 text-left @timeSpanColorClass">
|
||||
@supportConceptListObject.SupportConceptTimeSpan
|
||||
</p>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Hilfeplanauswahlpopup -->
|
||||
|
||||
<input type="text" class="d-none" name="CostBearer2SupportConceptOid" id="CostBearer2SupportConceptOid" value="@Model.SelectedSupportConceptListObject.CostBearer2SupportConceptOid">
|
||||
}
|
||||
|
||||
using(Html.BeginForm("CreateOrUpdateServiceRecord", "Main", FormMethod.Post, new { onreset = "serviceDescriptionSelectOnReset()", id = "singleBookingForm" }))
|
||||
{
|
||||
<div class="mt-3">
|
||||
<!-- Einzelbuchung: Mitarbeiter -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
@Html.LabelFor(m => m.SelectedEmployeeOid)
|
||||
@Html.DropDownListFor(m => m.SelectedEmployeeOid, Model.EmployeeListItems, new { id = "employeesDropDown", @class = "custom-select", onchange = "setSelectedEmployee()" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if(Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any())
|
||||
{
|
||||
<!-- Einzelbuchung: Ziele -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary form-control my-3" data-toggle="collapse" data-target="#goals-container" id="goals-button">Ziele</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="collapse w-100 mt-1 max-vw-50" id="goals-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<!-- Einzelbuchung: Leistungskategorie -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
@Html.LabelFor(m => m.SelectedServiceCategoryOid)
|
||||
@Html.DropDownListFor(m => m.SelectedServiceCategoryOid, Model.ServiceCategoryListItems, new { onchange = "loadServiceDescriptions()", @class = "custom-select", Id = "category-select" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Einzelbuchung: Leistung -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="leistung-select">Leistung</label>
|
||||
<select class="custom-select" id="leistung-select" name="ServiceDescription" onchange="setServiceDescription('leistung-select')">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Startdatum -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Startdatum</label>
|
||||
<div class="input-group date" id="start-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-date" name="Datum" class="form-control datetimepicker-input" data-target="#start-date-picker" data-toggle="datetimepicker" value="@Model.StartDateToEdit" />
|
||||
<div class="input-group-append" data-target="#start-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Enddatum -->
|
||||
@if(Model.IsEndDateVisible)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Enddatum</label>
|
||||
<div class="input-group date" id="end-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-date" name="Enddatum" class="form-control datetimepicker-input" data-target="#end-date-picker" data-toggle="datetimepicker" value="@Model.EndDateToEdit" />
|
||||
<div class="input-group-append" data-target="#end-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<!-- Einzelbuchung: Von -->
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-time">Von</label>
|
||||
<div class="input-group date" id="start-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@Model.StartTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#start-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Bis -->
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="end-time">Bis</label>
|
||||
<div class="input-group date" id="end-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@Model.EndTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#end-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Dauer -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="duration">Dauer</label>
|
||||
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@Model.DurationToEdit">
|
||||
</div>
|
||||
</div>
|
||||
@if(Model.IsZeiterfassungInStdMin)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="hours-minutes-dropdown-btn">Minuten/Stunden</label>
|
||||
<div class="dropdown">
|
||||
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
|
||||
Minuten
|
||||
</button>
|
||||
<div class="dropdown-menu w-100">
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Minuten</a>
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Stunden</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- Einzelbuchung: Distanz -->
|
||||
@if(Model.ShowDistanceField)
|
||||
{
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="distance">Gefahrene Kilometer</label>
|
||||
<input class="form-control" id="distance" name="Distanz" onchange="validateDistanceInput()" value="@Model.DistanceToEdit">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if(AbstractModel.HasRightToSeeTextModules)
|
||||
{
|
||||
<!-- Einzelbuchung: Textbausteine -->
|
||||
<div class="form-row" id="textmodule-container">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary form-control mt-3" data-toggle="modal" data-target="#textbausteine-popup" id="textbausteine-button">Textbausteine</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="form-row">
|
||||
<div class="col-md mt-3">
|
||||
@if(Model.NumberOfDokuTypes == 0)
|
||||
{
|
||||
<div class="form-group">
|
||||
<label for="dokufeld">Dokumentation</label>
|
||||
<textarea class="form-control" name="Dokumentation6" id="dokufeld">@Model.NoticeToEdit</textarea>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-tabs" role="tab-list">
|
||||
@for(var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var currentDokuType = Model.Dokutypes[i];
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="#doku_@i" id="doku_@i-tab" data-toggle="tab" role="tab" aria-controls="doku_@i" class="nav-link@(i == 0 ? " active" : string.Empty)" aria-selected="true">
|
||||
@currentDokuType.DisplayName
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<div class="tab-content" id="dokufelderTab">
|
||||
@for(var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var textareaName = i + 1 < 1 ? "Dokumentation" : "Dokumentation" + (i + 1);
|
||||
|
||||
<div class="tab-pane show@(i == 0 ? " active" : string.Empty)" id="doku_@i" role="tabpanel" aria-labelledby="doku_@i-tab">
|
||||
<textarea class="form-control doku-form-control" id="doku-textarea-@i" name="@textareaName">@Model.NoticeListToEdit[i]</textarea>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="d-flex bd-highlight mt-3">
|
||||
<div class="mr-auto bd-highlight">
|
||||
|
||||
</div>
|
||||
@if(Model.IsInEditingMode)
|
||||
{
|
||||
using(Html.BeginForm("ResetEditingMode", "Main", FormMethod.Post))
|
||||
{
|
||||
<button type="submit" class="btn btn-primary" onclick="showSpinner()">Abbrechen</button>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="reset-button" onclick="resetSingleBookingForm()">Abbrechen</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="create-button" onclick="submitSingleBookingForm()">@Model.SubmitButtonValue</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- /Einzelbuchungsformular -->
|
||||
|
||||
<!-- Liste mit den Einträgen und dem Auswahl-Select -->
|
||||
<div class="col col-12 col-md-7">
|
||||
@if(Model != null)
|
||||
{
|
||||
if(Model.SelectedSupportConcept != null || Model.CostBearer2SupportConceptOid == -2)
|
||||
{
|
||||
<div class="container-fluid w-100 mt-3 p-0">
|
||||
@using(Html.BeginForm("LoadServiceRecords", "Main", FormMethod.Post, new { id = "selectServiceRecordForm" }))
|
||||
{
|
||||
<select name="Records" class="custom-select" onchange="showSpinner();this.form.submit();" id="timeFrameSelect">
|
||||
<option value="-1">Zeitraum wählen</option>
|
||||
<option value="7"
|
||||
@{if(Model.Zeitraum == 7) { @Html.Raw("selected") }}>
|
||||
Letzte 7 Tage
|
||||
</option>
|
||||
<option value="30"
|
||||
@{if(Model.Zeitraum == 30) { @Html.Raw("selected") }}>
|
||||
Letzte 30 Tage
|
||||
</option>
|
||||
<option value="90"
|
||||
@{if(Model.Zeitraum == 90) { @Html.Raw("selected") }}>
|
||||
Letzte 90 Tage
|
||||
</option>
|
||||
<option value="0"
|
||||
@{if(Model.Zeitraum == 0) { @Html.Raw("selected") }}>
|
||||
Alle
|
||||
</option>
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<div class="container-fluid mt-3">
|
||||
@{
|
||||
foreach(var serviceRecord in Model.ServiceRecords)
|
||||
{
|
||||
if(serviceRecord.Start == null || serviceRecord.End == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var start = serviceRecord.Start.Value;
|
||||
var end = serviceRecord.End.Value;
|
||||
var hasSignatureStr = serviceRecord.SignatureOid.HasValue ? "JA" : "NEIN";
|
||||
|
||||
var duration = (end - start).TotalMinutes;
|
||||
var roundedDuration = MobileUtils.GetDecimalValueWithMaxDecimal(serviceRecord.RoundedDuration, 2);
|
||||
|
||||
if(serviceRecord.ServiceDescription.Category.Percentage > 0 && serviceRecord.ServiceDescription.Category.Percentage < 100)
|
||||
{
|
||||
roundedDuration = roundedDuration * serviceRecord.ServiceDescription.Category.Percentage / 100;
|
||||
}
|
||||
|
||||
var durationStr = serviceRecord.GroupOid.HasValue ? string.Format("{0:###0.#} ({0:###0.#})", roundedDuration) : $"{duration:###0.#} ({roundedDuration:###0.#})";
|
||||
|
||||
var goalsString = string.Empty;
|
||||
|
||||
if(serviceRecord.Goals != null && serviceRecord.Goals.Count > 0)
|
||||
{
|
||||
foreach(var goal in serviceRecord.Goals)
|
||||
{
|
||||
goalsString += goal.TypeDescription;
|
||||
|
||||
if(serviceRecord.Goals.IndexOf(goal) < serviceRecord.Goals.Count - 1)
|
||||
{
|
||||
goalsString += ", ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cardBackground = serviceRecord.GroupOid.HasValue ? "bg-bewo-group-booking" : string.Empty;
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="card w-100 @cardBackground">
|
||||
<div class="card-header" onclick="cardHeaderClick('#chevron-@serviceRecord.ServiceRecordOid', '#collapse-service-record-@serviceRecord.ServiceRecordOid')">
|
||||
<div class="d-inline-flex">
|
||||
<i class="fas fa-chevron-down h-100 text-primary" id="chevron-@serviceRecord.ServiceRecordOid"></i>
|
||||
</div>
|
||||
<div class="p2 d-inline-flex text-primary h-100">
|
||||
<button type="button" class="btn btn-link">
|
||||
@MainModel.GetServiceRecordTimeHeader(serviceRecord, true)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-service-record-@serviceRecord.ServiceRecordOid" class="collapse">
|
||||
<div class="card-body">
|
||||
<div class="container">
|
||||
<div class="row mb-3">
|
||||
@if(Model.HasRightToEditServiceRecord(serviceRecord))
|
||||
{
|
||||
using(Html.BeginForm("SelectRecordToEdit", "Main", FormMethod.Post))
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="fas fa-edit"></span>
|
||||
</button>
|
||||
<input type="hidden" name="service-record-oid-holder" value="@serviceRecord.ServiceRecordOid" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@if(MainModel.IsAllowedToDeleteServiceRecord(serviceRecord))
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="deleteServiceRecord(@serviceRecord.ServiceRecordOid)">
|
||||
<span class="fas fa-trash-alt"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if(Model.ShowSignature && !serviceRecord.SignatureOid.HasValue)
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="initializeSignature(@serviceRecord.ServiceRecordOid)">
|
||||
<span class="fas fa-signature"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
else if(Model.ShowSignature && serviceRecord.SignatureOid.HasValue)
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="submit" data-toggle="modal" class="btn btn-primary" onclick="getSignatureImage(@serviceRecord.ServiceRecordOid.Value, @serviceRecord.SignatureOid.Value)">
|
||||
<span class="fas fa-file-contract"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Minuten (gerundet):
|
||||
</div>
|
||||
<div class="col text-info">
|
||||
@durationStr
|
||||
</div>
|
||||
</div>
|
||||
@if(Model.ShowDistanceField && serviceRecord.DistanceInMeter != null && serviceRecord.DistanceInMeter.Value > 0)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Gefahrene Kilometer:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.DistanceInMeter.ToString()
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if(serviceRecord.Goals != null && serviceRecord.Goals.Count > 0)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Ziele:
|
||||
</div>
|
||||
<div class="col">
|
||||
@goalsString
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Leistungskategorie:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.ServiceDescription.CategoryName
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Leistung:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.ServiceDescription.Name
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Mitarbeiter:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.Employee.ToString()
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Angelegt am:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.InsertedOn
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@{
|
||||
var header1 = "Dokumentation";
|
||||
if(Model.NumberOfDokuTypes >= 1)
|
||||
{
|
||||
header1 = Model.Dokutypes[0].TypeDescription;
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
@header1:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.Notice
|
||||
</div>
|
||||
</div>
|
||||
|
||||
for(var i = 1; i < serviceRecord.NoticeList.Count; i++)
|
||||
{
|
||||
var notice = serviceRecord.NoticeList[i];
|
||||
|
||||
if(string.IsNullOrWhiteSpace(notice) || Model.NumberOfDokuTypes <= i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var header = $"Dokumentation {i + 1}";
|
||||
|
||||
if(Model.NumberOfDokuTypes >= 2)
|
||||
{
|
||||
if(Model.NumberOfDokuTypes <= i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
header = Model.Dokutypes[i].TypeDescription;
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
@header:
|
||||
</div>
|
||||
<div class="col">
|
||||
@notice
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Unterschrieben:
|
||||
</div>
|
||||
<div class="col">
|
||||
@hasSignatureStr
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- /Liste mit den Einträgen und dem Auswahl-Select -->
|
||||
</div>
|
||||
@Html.Partial("SingleBookingPartial", Model)
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="container mb-3">
|
||||
@if(Model.IsInGroupBookingMode)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col col-12">
|
||||
@if(Model != null)
|
||||
{
|
||||
var submitButtonText = Model.IsInEditingMode ? "Speichern" : "Anlegen";
|
||||
|
||||
using(Html.BeginForm("CreateOrUpdateGroupBooking", "Main", FormMethod.Post, new { onreset = "serviceDescriptionSelectOnReset()", id = "groupBookingForm" }))
|
||||
{
|
||||
var startDate = Model.SelectedServiceRecord?.Start?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
|
||||
var endDate = Model.SelectedServiceRecord?.End?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
|
||||
|
||||
var startTime = Model.SelectedServiceRecord?.Start?.ToShortTimeString() ?? string.Empty;
|
||||
var endTime = Model.SelectedServiceRecord?.End?.ToShortTimeString() ?? string.Empty;
|
||||
|
||||
var duration = Model.SelectedServiceRecord?.GroupRoundedDuration?.ToString() ?? string.Empty;
|
||||
var distance = Model.SelectedServiceRecord?.DistanceInMeter?.ToString() ?? string.Empty;
|
||||
|
||||
var notice0 = Model.SelectedServiceRecord?.Notice ?? string.Empty;
|
||||
var noticeList = new string[] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty };
|
||||
|
||||
if(Model.SelectedServiceRecord?.NoticeList != null)
|
||||
{
|
||||
var selectedNoticeList = Model.SelectedServiceRecord.NoticeList;
|
||||
for(var i = 0; i < selectedNoticeList.Count; i++)
|
||||
{
|
||||
noticeList[i] = selectedNoticeList[i] ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
<div class="mt-3">
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="alert alert-danger collapse" role="alert" id="form-alert">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Hilfepläne und Gruppen -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary btn-block" data-toggle="modal" data-target="#group-booking-popup" id="support-concepts-and-groups-button">Hilfepläne und Gruppen hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Hilfepläne hinzufügen -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-cb2sc-list">
|
||||
@foreach(var selectedCb2ScRelation in Model.GroupBookingSelectionObject.SelectedRelations)
|
||||
{
|
||||
<div class="list-group-item" id="relation-item-@selectedCb2ScRelation.Value">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span>
|
||||
@selectedCb2ScRelation.Text1
|
||||
<br />
|
||||
<span class="@selectedCb2ScRelation.TextColor">
|
||||
@selectedCb2ScRelation.Text2
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-auto my-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="removeCb2ScRelation(@selectedCb2ScRelation.Value)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Mitarbeiter hinzufügen -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<button type="button" class="btn btn-primary btn-block" data-toggle="modal" data-target="#group-booking-employee-selection-popup" id="employees-button">
|
||||
Mitarbeiter hinzufügen <span class="badge badge-light text-primary" id="selected-employees-count-badge">@Model.SelectedEmployees.Count</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Leistungskategorien -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
@Html.LabelFor(m => m.SelectedServiceCategoryOid)
|
||||
@Html.DropDownListFor(m => m.SelectedServiceCategoryOid, Model.ServiceCategoryListItems, new { onchange = "loadServiceDescriptions()", @class = "custom-select", Id = "category-select" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Leistung -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="leistung-select">Leistung</label>
|
||||
<select class="custom-select" id="leistung-select" name="ServiceDescription" onchange="setServiceDescription('leistung-select')"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Datum -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Startdatum</label>
|
||||
<div class="input-group date" id="start-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-date" name="Datum" class="form-control datetimepicker-input" data-target="#start-date-picker" data-toggle="datetimepicker" value="@startDate" />
|
||||
<div class="input-group-append" data-target="#start-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Enddatum -->
|
||||
@if(Model.IsEndDateVisible)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Enddatum</label>
|
||||
<div class="input-group date" id="end-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-date" name="Enddatum" class="form-control datetimepicker-input" data-target="#end-date-picker" data-toggle="datetimepicker" value="@endDate" />
|
||||
<div class="input-group-append" data-target="#end-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Start- und Endzeit -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-time">Von</label>
|
||||
<div class="input-group date" id="start-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@startTime" />
|
||||
<div class="input-group-append" data-target="#start-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="end-time">Bis</label>
|
||||
<div class="input-group date" id="end-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@endTime" />
|
||||
<div class="input-group-append" data-target="#end-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Dauer -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="duration">Dauer</label>
|
||||
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@duration">
|
||||
</div>
|
||||
</div>
|
||||
@if(Model.IsZeiterfassungInStdMin)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="hours-minutes-dropdown-btn">Minuten/Stunden</label>
|
||||
<div class="dropdown">
|
||||
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
|
||||
Minuten
|
||||
</button>
|
||||
<div class="dropdown-menu w-100">
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Minuten</a>
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Stunden</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Gruppenbuchung: Distanz -->
|
||||
@if(Model.ShowDistanceField)
|
||||
{
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="distance">Gefahrene Kilometer</label>
|
||||
<input type="text" class="form-control" id="distance" name="Distanz" onchange="validateDistanceInput()" value="@distance">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Gruppenbuchung: Textbausteine -->
|
||||
@if(AbstractModel.HasRightToSeeTextModules)
|
||||
{
|
||||
<div class="form-row" id="textmodule-container">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary form-control mt-3" data-toggle="modal" data-target="#textbausteine-popup" id="textbausteine-button">Textbausteine</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Gruppenbuchung: Dokufelder -->
|
||||
<div class="form-row">
|
||||
<div class="col-md mt-3">
|
||||
@if(Model.NumberOfDokuTypes == 0)
|
||||
{
|
||||
<div class="form-group">
|
||||
<label for="dokufeld">Dokumentation</label>
|
||||
<textarea class="form-control" name="Dokumentation6" id="dokufeld">@notice0</textarea>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-tabs" role="tab-list">
|
||||
@for(var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var currentDokuType = Model.Dokutypes[i];
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="#doku_@i" id="doku_@i-tab" data-toggle="tab" role="tab" aria-controls="doku_@i" class="nav-link@(i == 0 ? " active" : string.Empty)" aria-selected="true">
|
||||
@currentDokuType.DisplayName
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<div class="tab-content" id="dokufelderTab">
|
||||
@for(var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var textareaName = i + 1 < 1 ? "Dokumentation" : "Dokumentation" + (i + 1);
|
||||
|
||||
<div class="tab-pane show@(i == 0 ? " active" : string.Empty)" id="doku_@i" role="tabpanel" aria-labelledby="doku_@i-tab">
|
||||
<textarea class="form-control doku-form-control" id="doku-textarea-@i" name="@textareaName">@noticeList[i]</textarea>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="d-flex bd-highlight mt-3">
|
||||
<div class="mr-auto bd-highlight">
|
||||
<!-- dient nur als Abstandshalter-->
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
@using(Html.BeginForm("ResetEditingMode", "Main", FormMethod.Post))
|
||||
{
|
||||
<button type="submit" class="btn btn-primary" onclick="showSpinner()">Abbrechen</button>
|
||||
}
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="create-button" onclick="submitGroupBookingForm()">@submitButtonText</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@Html.Partial("GroupBookingPartial", Model)
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Textbausteine-Popup-->
|
||||
<div class="modal" tabindex="-1" role="dialog" id="textbausteine-popup">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title">Textbausteine</h6>
|
||||
@@ -1220,112 +392,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- (Gruppenbuchung) Hilfeplan- und Gruppenauswahl Popup -->
|
||||
<div class="modal" data-backdrop="static" tabindex="-1" role="dialog" id="group-booking-popup">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Gruppen und Hilfepläne für Gruppenbuchung</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<nav class="nav nav-pills nav-fill">
|
||||
<a class="nav-item nav-link active" href="#group-booking-supportconcepts" data-toggle="tab" role="tab">Hilfepläne</a>
|
||||
<a class="nav-item nav-link" href="#group-booking-groups" data-toggle="tab" role="tab">Gruppen</a>
|
||||
</nav>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane show active" role="tabpanel" id="group-booking-supportconcepts">
|
||||
<ul class="list-group">
|
||||
@foreach(var cb2Sc in Model.SupportConceptListObjectsForGroupBooking)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
@{
|
||||
var timeSpanColorClass2 = cb2Sc.IsAboutToExpire ? "text-bewo-is-about-to-expire" : cb2Sc.ExpiresInThreeMonthsOrLess ? "text-bewo-expires-in-three-months" : "text-dark";
|
||||
|
||||
var wasSuccessful = long.TryParse(cb2Sc.CostBearer2SupportConceptOid, out var cb2ScOid);
|
||||
|
||||
var checkedValue = wasSuccessful ? Model.SelectedConceptCostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.Equals(cb2ScOid)) : wasSuccessful;
|
||||
}
|
||||
|
||||
<div class="custom-control custom-checkbox custom-control-inline">
|
||||
<input type="checkbox"
|
||||
@{ if(checkedValue) { @Html.Raw("checked=\"checked\"") ; } }
|
||||
class="custom-control-input" id="cb2sc-checkbox-@cb2Sc.CostBearer2SupportConceptOid" onchange="addCostBearer2SupportConceptsToGroupBooking()" name="cb2sc-checkbox-@cb2Sc.CostBearer2SupportConceptOid" value="@cb2Sc.CostBearer2SupportConceptOid">
|
||||
<label for="cb2sc-checkbox-@cb2Sc.CostBearer2SupportConceptOid" class="custom-control-label">
|
||||
<span class="justify-content-between mb-1 text-dark text-left">
|
||||
@cb2Sc.NameAndDateOfBirth
|
||||
</span>
|
||||
<br />
|
||||
<span class="mb-1 text-left @timeSpanColorClass2">
|
||||
@cb2Sc.SupportConceptTimeSpan
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-pane show" role="tabpanel" id="group-booking-groups">
|
||||
<ul class="list-group">
|
||||
@foreach(var group in Model.GroupOfPeopleListItems)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
@{
|
||||
long groupOid;
|
||||
var wasSuccessful = long.TryParse(group.Value, out groupOid);
|
||||
|
||||
var shouldBeChecked = wasSuccessful ? Model.SelectedGroupOfPeopleOids.Contains(groupOid) : wasSuccessful;
|
||||
|
||||
var attribute = shouldBeChecked ? "checked=\"checked\"" : string.Empty;
|
||||
}
|
||||
<div class="custom-control custom-checkbox custom-control-inline">
|
||||
<input type="checkbox" @attribute class="custom-control-input" id="group-checkbox-@group.Value" value="@group.Value" onchange="addCostBearer2SupportConceptsToGroupBooking()" />
|
||||
<label for="group-checkbox-@group.Value" class="custom-control-label">
|
||||
@group.Text
|
||||
</label>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- (Gruppenbuchung) Mitarbeiterauswahl Popup -->
|
||||
<div class="modal" tabindex="-1" role="dialog" id="group-booking-employee-selection-popup">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Mitarbeiter hinzufügen</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="list-group" id="employee-list">
|
||||
@foreach(var employee in Model.Employees)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
@{
|
||||
var checkedValue = Model.SelectedEmployees.Contains(employee) ? "checked=\"checked\"" : string.Empty;
|
||||
}
|
||||
|
||||
<div class="custom-control custom-checkbox custom-control-inline">
|
||||
<input type="checkbox" @checkedValue class="custom-control-input" id="group-employee-@employee.EmployeeOid" onchange="addEmployeeToGroupBooking()" value="@employee.EmployeeOid" />
|
||||
<label for="group-employee-@employee.EmployeeOid" class="custom-control-label">@employee.DetailDescription</label>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Unterschriften-Layover -->
|
||||
<div class="container-fluid d-none mb-3" id="signature-container">
|
||||
@@ -1404,7 +471,7 @@
|
||||
|
||||
<!-- Statistik-Popup -->
|
||||
<div id="statistics-popup" class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title" id="statistics-header"></h6>
|
||||
|
||||
562
BeWoPlanerMobil/Views/Main/SingleBookingPartial.cshtml
Normal file
562
BeWoPlanerMobil/Views/Main/SingleBookingPartial.cshtml
Normal file
@@ -0,0 +1,562 @@
|
||||
@using BeWoPlanerMobil.Models
|
||||
@model MainModel
|
||||
|
||||
<div class="row">
|
||||
<!-- Einzelbuchungsformular -->
|
||||
<div class="col col-12 col-md-5">
|
||||
@if (Model != null)
|
||||
{
|
||||
using (Html.BeginForm("SelectSupportConcept", "Main", FormMethod.Post, new { Id = "selectSupportConceptForm" }))
|
||||
{
|
||||
var selectedSuportConceptTimeSpanColorClass = Model.SelectedSupportConceptListObject.IsAboutToExpire ? "text-bewo-is-about-to-expire" : Model.SelectedSupportConceptListObject.ExpiresInThreeMonthsOrLess ? "text-bewo-expires-in-three-months" : "text-dark";
|
||||
<div>
|
||||
<div class="container p-0">
|
||||
<div class="row">
|
||||
<div class="col mt-3">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item flex-column align-items-start no-underline" data-toggle="modal" data-target="#supportConceptList">
|
||||
<div class="d-flex">
|
||||
<h5 class="mb-1 text-dark text-left" id="selectedSupportConceptCustomerInfo">@Model.SelectedSupportConceptListObject.NameAndDateOfBirth</h5>
|
||||
</div>
|
||||
<p class="mb-1 text-left @selectedSuportConceptTimeSpanColorClass" id="selectedSupportConceptInfo">
|
||||
@Model.SelectedSupportConceptListObject.SupportConceptTimeSpan
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.CostBearer2SupportConceptOid != null && Model.CostBearer2SupportConceptOid > 0)
|
||||
{
|
||||
<div class="col-md-auto mt-3">
|
||||
<button type="button" class="btn btn-outline-primary w-100 h-100" id="statistics-button" data-toggle="modal" data-target="#statistics-popup" onclick="showPieChart()">
|
||||
<span class="d-md-none align-middle">Statistik</span>
|
||||
<span class="fas fa-chart-pie align-middle" style="font-size: 2rem;"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Hilfeplanauswahlpopup modal-dialog-centered-->
|
||||
<div class="modal" role="dialog" tabindex="-1" id="supportConceptList">
|
||||
<div class="modal-dialog text-center" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Hilfeplanauswahl</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetSupportConceptSearch()">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Hilfeplansuche -->
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="supportConceptSearchOnChange()" id="support-concept-search-input" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="resetSupportConceptSearch()">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<!-- Hilfeplanliste -->
|
||||
<div class="list-group">
|
||||
@foreach (var supportConceptListObject in Model.SupportConceptListObjects)
|
||||
{
|
||||
var timeSpanColorClass = supportConceptListObject.IsAboutToExpire ? "text-bewo-is-about-to-expire" : supportConceptListObject.ExpiresInThreeMonthsOrLess ? "text-bewo-expires-in-three-months" : "text-dark";
|
||||
|
||||
<a href="#" class="list-group-item flex-column align-items-start no-underline blubb-test" onclick="selectSupportConcept(@supportConceptListObject.CostBearer2SupportConceptOid)" data-dismiss="modal">
|
||||
<div class="justify-content-between">
|
||||
<h5 class="mb-1 text-dark text-left supportconcept-name-header">
|
||||
@supportConceptListObject.NameAndDateOfBirth
|
||||
</h5>
|
||||
</div>
|
||||
<p class="mb-1 text-left @timeSpanColorClass">
|
||||
@supportConceptListObject.SupportConceptTimeSpan
|
||||
</p>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /Hilfeplanauswahlpopup -->
|
||||
|
||||
<input type="text" class="d-none" name="CostBearer2SupportConceptOid" id="CostBearer2SupportConceptOid" value="@Model.SelectedSupportConceptListObject.CostBearer2SupportConceptOid">
|
||||
}
|
||||
|
||||
using (Html.BeginForm("CreateOrUpdateServiceRecord", "Main", FormMethod.Post, new { onreset = "serviceDescriptionSelectOnReset()", id = "singleBookingForm" }))
|
||||
{
|
||||
<div class="mt-3">
|
||||
<!-- Einzelbuchung: Mitarbeiter -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
@Html.LabelFor(m => m.SelectedEmployeeOid)
|
||||
@Html.DropDownListFor(m => m.SelectedEmployeeOid, Model.EmployeeListItems, new { id = "employeesDropDown", @class = "custom-select", onchange = "setSelectedEmployee()" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any())
|
||||
{
|
||||
<!-- Einzelbuchung: Ziele -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary form-control my-3" data-toggle="collapse" data-target="#goals-container" id="goals-button">Ziele</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="collapse w-100 mt-1 max-vw-50" id="goals-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<!-- Einzelbuchung: Leistungskategorie -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
@Html.LabelFor(m => m.SelectedServiceCategoryOid)
|
||||
@Html.DropDownListFor(m => m.SelectedServiceCategoryOid, Model.ServiceCategoryListItems, new { onchange = "loadServiceDescriptions()", @class = "custom-select", Id = "category-select" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Einzelbuchung: Leistung -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="leistung-select">Leistung</label>
|
||||
<select class="custom-select" id="leistung-select" name="ServiceDescription" onchange="setServiceDescription('leistung-select')">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Startdatum -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Startdatum</label>
|
||||
<div class="input-group date" id="start-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-date" name="Datum" class="form-control datetimepicker-input" data-target="#start-date-picker" data-toggle="datetimepicker" value="@Model.StartDateToEdit" />
|
||||
<div class="input-group-append" data-target="#start-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Enddatum -->
|
||||
@if (Model.IsEndDateVisible)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-date">Enddatum</label>
|
||||
<div class="input-group date" id="end-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-date" name="Enddatum" class="form-control datetimepicker-input" data-target="#end-date-picker" data-toggle="datetimepicker" value="@Model.EndDateToEdit" />
|
||||
<div class="input-group-append" data-target="#end-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<!-- Einzelbuchung: Von -->
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="start-time">Von</label>
|
||||
<div class="input-group date" id="start-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@Model.StartTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#start-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Bis -->
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="end-time">Bis</label>
|
||||
<div class="input-group date" id="end-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@Model.EndTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#end-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Einzelbuchung: Dauer -->
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="duration">Dauer</label>
|
||||
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@Model.DurationToEdit">
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.IsZeiterfassungInStdMin)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="hours-minutes-dropdown-btn">Minuten/Stunden</label>
|
||||
<div class="dropdown">
|
||||
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
|
||||
Minuten
|
||||
</button>
|
||||
<div class="dropdown-menu w-100">
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Minuten</a>
|
||||
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Stunden</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- Einzelbuchung: Distanz -->
|
||||
@if (Model.ShowDistanceField)
|
||||
{
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="distance">Gefahrene Kilometer</label>
|
||||
<input class="form-control" id="distance" name="Distanz" onchange="validateDistanceInput()" value="@Model.DistanceToEdit">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToSeeTextModules)
|
||||
{
|
||||
<!-- Einzelbuchung: Textbausteine -->
|
||||
<div class="form-row" id="textmodule-container">
|
||||
<div class="col-md">
|
||||
<button type="button" class="btn btn-primary form-control mt-3" data-toggle="modal" data-target="#textbausteine-popup" id="textbausteine-button">Textbausteine</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="form-row">
|
||||
<div class="col-md mt-3">
|
||||
@if (Model.NumberOfDokuTypes == 0)
|
||||
{
|
||||
<div class="form-group">
|
||||
<label for="dokufeld">Dokumentation</label>
|
||||
<textarea class="form-control" name="Dokumentation6" id="dokufeld">@Model.NoticeToEdit</textarea>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-tabs" role="tab-list">
|
||||
@for (var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var currentDokuType = Model.Dokutypes[i];
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="#doku_@i" id="doku_@i-tab" data-toggle="tab" role="tab" aria-controls="doku_@i" class="nav-link@(i == 0 ? " active" : string.Empty)" aria-selected="true">
|
||||
@currentDokuType.DisplayName
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<div class="tab-content" id="dokufelderTab">
|
||||
@for (var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var textareaName = i + 1 < 1 ? "Dokumentation" : "Dokumentation" + (i + 1);
|
||||
|
||||
<div class="tab-pane show@(i == 0 ? " active" : string.Empty)" id="doku_@i" role="tabpanel" aria-labelledby="doku_@i-tab">
|
||||
<textarea class="form-control doku-form-control" id="doku-textarea-@i" name="@textareaName">@Model.NoticeListToEdit[i]</textarea>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="d-flex bd-highlight mt-3">
|
||||
<div class="mr-auto bd-highlight">
|
||||
|
||||
</div>
|
||||
@if (Model.IsInEditingMode)
|
||||
{
|
||||
using (Html.BeginForm("ResetEditingMode", "Main", FormMethod.Post))
|
||||
{
|
||||
<button type="submit" class="btn btn-primary" onclick="showSpinner()">Abbrechen</button>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="reset-button" onclick="resetSingleBookingForm()">Abbrechen</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="create-button" onclick="submitSingleBookingForm()">@Model.SubmitButtonValue</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- /Einzelbuchungsformular -->
|
||||
<!-- Liste mit den Einträgen und dem Auswahl-Select -->
|
||||
<div class="col col-12 col-md-7">
|
||||
@if (Model != null)
|
||||
{
|
||||
if (Model.SelectedSupportConcept != null || Model.CostBearer2SupportConceptOid == -2)
|
||||
{
|
||||
<div class="container-fluid w-100 mt-3 p-0">
|
||||
@using (Html.BeginForm("LoadServiceRecords", "Main", FormMethod.Post, new { id = "selectServiceRecordForm" }))
|
||||
{
|
||||
<select name="Records" class="custom-select" onchange="showSpinner();this.form.submit();" id="timeFrameSelect">
|
||||
<option value="-1">Zeitraum wählen</option>
|
||||
<option value="7"
|
||||
@{if (Model.Zeitraum == 7) { @Html.Raw("selected") }}>
|
||||
Letzte 7 Tage
|
||||
</option>
|
||||
<option value="30"
|
||||
@{if (Model.Zeitraum == 30) { @Html.Raw("selected") }}>
|
||||
Letzte 30 Tage
|
||||
</option>
|
||||
<option value="90"
|
||||
@{if (Model.Zeitraum == 90) { @Html.Raw("selected") }}>
|
||||
Letzte 90 Tage
|
||||
</option>
|
||||
<option value="0"
|
||||
@{if (Model.Zeitraum == 0) { @Html.Raw("selected") }}>
|
||||
Alle
|
||||
</option>
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<div class="container-fluid mt-3">
|
||||
@{
|
||||
foreach (var serviceRecord in Model.ServiceRecords)
|
||||
{
|
||||
if (serviceRecord.Start == null || serviceRecord.End == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var start = serviceRecord.Start.Value;
|
||||
var end = serviceRecord.End.Value;
|
||||
var hasSignatureStr = serviceRecord.SignatureOid.HasValue ? "JA" : "NEIN";
|
||||
|
||||
var duration = (end - start).TotalMinutes;
|
||||
var roundedDuration = MobileUtils.GetDecimalValueWithMaxDecimal(serviceRecord.RoundedDuration, 2);
|
||||
|
||||
if (serviceRecord.ServiceDescription.Category.Percentage > 0 && serviceRecord.ServiceDescription.Category.Percentage < 100)
|
||||
{
|
||||
roundedDuration = roundedDuration * serviceRecord.ServiceDescription.Category.Percentage / 100;
|
||||
}
|
||||
|
||||
var durationStr = serviceRecord.GroupOid.HasValue ? string.Format("{0:###0.#} ({0:###0.#})", roundedDuration) : $"{duration:###0.#} ({roundedDuration:###0.#})";
|
||||
|
||||
var goalsString = string.Empty;
|
||||
|
||||
if (serviceRecord.Goals != null && serviceRecord.Goals.Count > 0)
|
||||
{
|
||||
foreach (var goal in serviceRecord.Goals)
|
||||
{
|
||||
goalsString += goal.TypeDescription;
|
||||
|
||||
if (serviceRecord.Goals.IndexOf(goal) < serviceRecord.Goals.Count - 1)
|
||||
{
|
||||
goalsString += ", ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cardBackground = serviceRecord.GroupOid.HasValue ? "bg-bewo-group-booking" : string.Empty;
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="card w-100 @cardBackground">
|
||||
<div class="card-header" onclick="cardHeaderClick('#chevron-@serviceRecord.ServiceRecordOid', '#collapse-service-record-@serviceRecord.ServiceRecordOid')">
|
||||
<div class="d-inline-flex">
|
||||
<i class="fas fa-chevron-down h-100 text-primary" id="chevron-@serviceRecord.ServiceRecordOid"></i>
|
||||
</div>
|
||||
<div class="p2 d-inline-flex text-primary h-100">
|
||||
<button type="button" class="btn btn-link">
|
||||
@MainModel.GetServiceRecordTimeHeader(serviceRecord, true)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-service-record-@serviceRecord.ServiceRecordOid" class="collapse">
|
||||
<div class="card-body">
|
||||
<div class="container">
|
||||
<div class="row mb-3">
|
||||
@if (Model.HasRightToEditServiceRecord(serviceRecord))
|
||||
{
|
||||
using (Html.BeginForm("SelectRecordToEdit", "Main", FormMethod.Post))
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="fas fa-edit"></span>
|
||||
</button>
|
||||
<input type="hidden" name="service-record-oid-holder" value="@serviceRecord.ServiceRecordOid" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@if (MainModel.IsAllowedToDeleteServiceRecord(serviceRecord))
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="deleteServiceRecord(@serviceRecord.ServiceRecordOid)">
|
||||
<span class="fas fa-trash-alt"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Model.ShowSignature && !serviceRecord.SignatureOid.HasValue)
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="initializeSignature(@serviceRecord.ServiceRecordOid)">
|
||||
<span class="fas fa-signature"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
else if (Model.ShowSignature && serviceRecord.SignatureOid.HasValue)
|
||||
{
|
||||
<div class="col-auto">
|
||||
<button type="submit" data-toggle="modal" class="btn btn-primary" onclick="getSignatureImage(@serviceRecord.ServiceRecordOid.Value, @serviceRecord.SignatureOid.Value)">
|
||||
<span class="fas fa-file-contract"></span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Minuten (gerundet):
|
||||
</div>
|
||||
<div class="col text-info">
|
||||
@durationStr
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.ShowDistanceField && serviceRecord.DistanceInMeter != null && serviceRecord.DistanceInMeter.Value > 0)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Gefahrene Kilometer:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.DistanceInMeter.ToString()
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (serviceRecord.Goals != null && serviceRecord.Goals.Count > 0)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Ziele:
|
||||
</div>
|
||||
<div class="col">
|
||||
@goalsString
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Leistungskategorie:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.ServiceDescription.CategoryName
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Leistung:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.ServiceDescription.Name
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Mitarbeiter:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.Employee.ToString()
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Angelegt am:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.InsertedOn
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@{
|
||||
var header1 = "Dokumentation";
|
||||
if (Model.NumberOfDokuTypes >= 1)
|
||||
{
|
||||
header1 = Model.Dokutypes[0].TypeDescription;
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
@header1:
|
||||
</div>
|
||||
<div class="col">
|
||||
@serviceRecord.Notice
|
||||
</div>
|
||||
</div>
|
||||
|
||||
for (var i = 1; i < serviceRecord.NoticeList.Count; i++)
|
||||
{
|
||||
var notice = serviceRecord.NoticeList[i];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(notice) || Model.NumberOfDokuTypes <= i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var header = $"Dokumentation {i + 1}";
|
||||
|
||||
if (Model.NumberOfDokuTypes >= 2)
|
||||
{
|
||||
if (Model.NumberOfDokuTypes <= i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
header = Model.Dokutypes[i].TypeDescription;
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
@header:
|
||||
</div>
|
||||
<div class="col">
|
||||
@notice
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-secondary">
|
||||
Unterschrieben:
|
||||
</div>
|
||||
<div class="col">
|
||||
@hasSignatureStr
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- /Liste mit den Einträgen und dem Auswahl-Select -->
|
||||
</div>
|
||||
@@ -187,8 +187,6 @@
|
||||
customerSignatureOidsString += signatureOid + ",";
|
||||
}
|
||||
|
||||
customerSignatureOidsString = customerSignatureOidsString.TrimEnd(',');
|
||||
|
||||
var employeeSignatureOidsString = "";
|
||||
|
||||
foreach(var employeeSignatureOid in result.EmployeeSignatureOids)
|
||||
@@ -196,8 +194,6 @@
|
||||
employeeSignatureOidsString += employeeSignatureOid + ",";
|
||||
}
|
||||
|
||||
employeeSignatureOidsString = employeeSignatureOidsString.TrimEnd(',');
|
||||
|
||||
var employeeSignatureState = result.EmployeeSignatureState;
|
||||
var customerSignatureState = result.CustomerSignatureState;
|
||||
|
||||
|
||||
386
BeWoPlanerMobil/Views/Scheduler/AppointmentFormPartial.cshtml
Normal file
386
BeWoPlanerMobil/Views/Scheduler/AppointmentFormPartial.cshtml
Normal file
@@ -0,0 +1,386 @@
|
||||
@using BeWoPlanerMobil.Models
|
||||
@model SchedulerModel
|
||||
<script>
|
||||
function alldayChange() {
|
||||
try {
|
||||
if ($("#IsAllDay").prop("checked")) {
|
||||
$("#scheduler-start-time, #scheduler-end-time").attr("disabled", true);
|
||||
} else {
|
||||
$("#scheduler-start-time, #scheduler-end-time").attr("disabled", false);
|
||||
}
|
||||
} catch(error) {
|
||||
logError(error.message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@using (Html.BeginForm("InsertOrUpdateAppointment", "Scheduler", FormMethod.Post, new { id = "insert-appointment-form" }))
|
||||
{
|
||||
<div class="mt-3">
|
||||
<div class="form-row">
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-start-date">Start</label>
|
||||
<div class="input-group date" id="scheduler-start-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-start-date" name="StartDate" class="form-control datetimepicker-input" data-target="#scheduler-start-date-picker" data-toggle="datetimepicker" value="@Model.StartDateToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-start-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-start-time">Von</label>
|
||||
<div class="input-group date" id="scheduler-start-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-start-time" name="StartTime" class="form-control datetimepicker-input" data-target="#scheduler-start-time-picker" value="@Model.StartTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-start-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-end-date">Ende</label>
|
||||
<div class="input-group date" id="scheduler-end-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-end-date" name="EndDate" class="form-control datetimepicker-input" data-target="#scheduler-end-date-picker" data-toggle="datetimepicker" value="@Model.EndDateToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-end-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-end-time">Bis</label>
|
||||
<div class="input-group date" id="scheduler-end-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-end-time" name="EndTime" class="form-control datetimepicker-input" data-target="#scheduler-end-time-picker" value="@Model.EndTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-end-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-6 mx-auto">
|
||||
<div class="custom-control custom-checkbox custom-control-inline mx-auto">
|
||||
@Html.CheckBoxFor(m => m.IsPrivate, new { @class = "custom-control-input" })
|
||||
@Html.LabelFor(m => m.IsPrivate, new { @class="custom-control-label" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 mx-auto">
|
||||
<div class="custom-control custom-checkbox custom-control-inline mx-auto">
|
||||
@Html.CheckBoxFor(m => m.IsAllDay, new { @class = "custom-control-input", onchange = "alldayChange()" })
|
||||
@Html.LabelFor(m => m.IsAllDay, new { @class = "custom-control-label" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.HasResourcesEmployeesOrCustomers)
|
||||
{
|
||||
<div class="form-row">
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#employees-popup">Mitarbeiter<br />hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#customers-popup">Klienten<br />hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#resources-popup">Ressourcen<br />hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments)
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-employees-list">
|
||||
@foreach (var selectedEmployee in Model.SelectedEmployees)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="related-employee-@selectedEmployee.EmployeeOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-user text-bewo-employee h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedEmployee.DetailDescription
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedItem(@selectedEmployee.EmployeeOid, '-checkbox', false, '@Url.Action("SelectEmployeesForAppointment", "Scheduler")', 'employees-popup', 'selected-employees-list', 'related-employee-')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments)
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-customers-list">
|
||||
@foreach (var selectedCustomer in Model.SelectedCustomers)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="related-customer-@selectedCustomer.CustomerOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-user text-bewo-customers h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedCustomer.DetailDescription
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
@{
|
||||
var url = Url.Action("SelectCustomersForAppointment", "Scheduler");
|
||||
var oid = selectedCustomer.CustomerOid;
|
||||
|
||||
var onClickParams = $"{oid}, '-checkbox', true, '{url}', 'customers-popup', 'selected-customers-list', 'related-customer-'";
|
||||
}
|
||||
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedItem(@onClickParams)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-resources-list">
|
||||
@foreach (var selectedResource in Model.SelectedResources)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="relation-item-@selectedResource.ResourceOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-cubes text-bewo-resource h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedResource.Name
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedResource('relation-item-@selectedResource.ResourceOid', 'resource-@selectedResource.ResourceOid-checkbox', 'resources-popup', '@Url.Action("SelectResourcesForAppointment", "Scheduler")', 'selected-resources-list')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="subject">Betreff</label>
|
||||
<input type="text" id="subject" name="Subject" class="form-control" value="@Model.SubjectToEdit" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="location">Ort</label>
|
||||
<input type="text" id="location" name="Location" class="form-control" value="@Model.LocationToEdit" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="notice">Notiz</label>
|
||||
<textarea class="form-control" id="notice" name="Notice">@Model.DescriptionToEdit</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="d-flex bd-highlight mt-3">
|
||||
<div class="mr-auto bd-highlight">
|
||||
<!-- Abstandshalter -->
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="reset-button" onclick="resetInsertAppointmentForm()">Abbrechen</button>
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="create-button" onclick="submitInsertAppointmentForm()">Speichern</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="resources-popup">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title text-center w-100">Ressourcen</h6>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetResourceSearch('resource-search-input')">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="resourceSearchOnChange('resource-search-input')" id="resource-search-input" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="resetResourceSearch('resource-search-input')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach (var category2Resources in Model.ResourceCategories2Resources)
|
||||
{
|
||||
<div class="card w-100 mb-3 category-card" id="resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="card-header" data-toggle="collapse" data-target="#collapsable-resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mr-auto">@category2Resources.Key.DisplayName</h5>
|
||||
<div class="btn-group" role="group">
|
||||
<span class="fas fa-chevron-down text-primary"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="collapsable-resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="card-body resource-list">
|
||||
@foreach (var resource in category2Resources.Value)
|
||||
{
|
||||
var checkedValue = Model.SelectedResources.Contains(resource) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox resource-text">
|
||||
<input type="checkbox" class="custom-control-input" id="resource-@resource.ResourceOid-checkbox" @checkedValue onchange="changeResourceSelection('resources-popup', '@Url.Action("SelectResourcesForAppointment", "Scheduler")', 'selected-resources-list', 'relation-item-', '-checkbox')" />
|
||||
<label class="custom-control-label resource-name-label" for="resource-@resource.ResourceOid-checkbox">@resource.Name</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments && Model.AllEmployees.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="employees-popup">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title text-center w-100">Mitarbeiter</h6>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetSearch('employee-search-input', 'employee-text')">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="listSearchOnChange('employee-search-input', 'employee-text', 'employee-name-label')" id="employee-search-input" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="resetSearch('employee-search-input', 'employee-text')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach (var employee in Model.AllEmployees)
|
||||
{
|
||||
var checkedValue = Model.SelectedEmployees.Contains(employee) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox employee-text">
|
||||
<input type="checkbox" class="custom-control-input" id="employee-@employee.EmployeeOid-checkbox" @checkedValue onchange="changeItemListSelection('@Url.Action("SelectEmployeesForAppointment", "Scheduler")', 'employees-popup', 'selected-employees-list', 'related-employee-', false, '-checkbox')" />
|
||||
<label class="custom-control-label employee-name-label" for="employee-@employee.EmployeeOid-checkbox">@employee.DetailDescription</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments && Model.AllCustomers.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="customers-popup">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title text-center w-100">Klienten</h6>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetSearch('customer-search-input', 'customer-text')">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="listSearchOnChange('customer-search-input', 'customer-text', 'customer-name-label')" id="customer-search-input" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="resetSearch('customer-search-input', 'customer-text')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach (var customer in Model.AllCustomers)
|
||||
{
|
||||
var checkedValue = Model.SelectedCustomers.Contains(customer) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox customer-text">
|
||||
<input type="checkbox" class="custom-control-input" id="customer-@customer.CustomerOid-checkbox" @checkedValue onchange="changeItemListSelection('@Url.Action("SelectCustomersForAppointment", "Scheduler")', 'customers-popup', 'selected-customers-list', 'related-customer-', true, '-checkbox')" />
|
||||
<label class="custom-control-label customer-name-label" for="customer-@customer.CustomerOid-checkbox">@customer.DetailDescription</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
@using BeWoPlanerMobil.Models
|
||||
@model BeWoPlanerMobil.Models.SchedulerModel
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$("#scheduler-interval-start-picker").datetimepicker({
|
||||
locale: "de",
|
||||
format: "L"
|
||||
});
|
||||
|
||||
$("#scheduler-interval-end-picker").datetimepicker({
|
||||
locale: "de",
|
||||
format: "L"
|
||||
});
|
||||
|
||||
$("#scheduler-interval-start-time-picker").datetimepicker({
|
||||
locale: "de",
|
||||
format: "LT"
|
||||
});
|
||||
|
||||
$("#scheduler-interval-end-time-picker").datetimepicker({
|
||||
locale: "de",
|
||||
format: "LT"
|
||||
});
|
||||
});
|
||||
|
||||
function resetIntervalFinderForm() {
|
||||
$("#scheduler-interval-start-time, #scheduler-interval-end-time, #duration").val("");
|
||||
$("#scheduler-interval-start, #scheduler-interval-end").val(moment().format("DD.MM.YYYY"));
|
||||
|
||||
$("#resources-interval-finder-popup input:checked, #customers-interval-finder-popup input:checked, #employees-interval-finder-popup input:checked").each(function() {
|
||||
$(this).prop("checked", false);
|
||||
});
|
||||
|
||||
$("#selected-resources-interval-finder-list, #selected-employees-interval-finder-list, #selected-customers-interval-finder-list").empty();
|
||||
|
||||
var url = '@Url.Action("ResetIntervalFinder", "Scheduler")';
|
||||
|
||||
$.get(url);
|
||||
}
|
||||
|
||||
function submitIntervalFinderForm() {
|
||||
try {
|
||||
showSpinner();
|
||||
$("#find-appointment-intervals-form").submit();
|
||||
} catch(error) {
|
||||
logError(error.message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="interval-form-container">
|
||||
@using (Html.BeginForm("FindFreeIntervals", "Scheduler", FormMethod.Post, new { id = "find-appointment-intervals-form" }))
|
||||
{
|
||||
<div class="mt-3">
|
||||
<div class="form-row">
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-interval-start">Datum-Zeitraum (von)</label>
|
||||
<div class="input-group date" id="scheduler-interval-start-picker" data-target-input="nearest">
|
||||
<input value="@Model.IntervalStartDateStr" type="text" id="scheduler-interval-start" name="IntervalStart" class="form-control datetimepicker-input" data-target="#scheduler-interval-start-picker" data-toggle="datetimepicker" />
|
||||
<div class="input-group-append" data-target="#scheduler-interval-start-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-interval-start-time">Zwischen Uhrzeit (von)</label>
|
||||
<div class="input-group date" id="scheduler-interval-start-time-picker" data-target-input="nearest">
|
||||
<input value="@Model.IntervalStartTimeStr" type="text" id="scheduler-interval-start-time" name="IntervalStartTime" class="form-control datetimepicker-input" data-target="#scheduler-interval-start-time-picker" />
|
||||
<div class="input-group-append" data-target="#scheduler-interval-start-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-interval-end">Datum-Zeitraum (bis)</label>
|
||||
<div class="input-group date" id="scheduler-interval-end-picker" data-target-input="nearest">
|
||||
<input value="@Model.IntervalEndDateStr" type="text" id="scheduler-interval-end" name="IntervalEnd" class="form-control datetimepicker-input" data-target="#scheduler-interval-end-picker" data-toggle="datetimepicker" />
|
||||
<div class="input-group-append" data-target="#scheduler-interval-end-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-interval-end-time">Zwischen Uhrzeit (bis)</label>
|
||||
<div class="input-group date" id="scheduler-interval-end-time-picker" data-target-input="nearest">
|
||||
<input value="@Model.IntervalEndTimeStr" type="text" id="scheduler-interval-end-time" name="IntervalEndTime" class="form-control datetimepicker-input" data-target="#scheduler-interval-end-time-picker" />
|
||||
<div class="input-group-append" data-target="#scheduler-interval-end-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="interval-duration">Dauer</label>
|
||||
<input value="@Model.IntervalDurationStr" type="number" id="interval-duration" name="Duration" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.HasResourcesEmployeesOrCustomers)
|
||||
{
|
||||
<!-- Hinzufügen-Buttons -->
|
||||
<div class="form-row">
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#employees-interval-finder-popup">Mitarbeiter<br/>hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#customers-interval-finder-popup">Klienten<br />hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#resources-interval-finder-popup">Ressourcen<br />hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments)
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-employees-interval-finder-list">
|
||||
@foreach (var selectedEmployee in Model.SelectedEmployeesForIntervalFinder)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="related-employee-interval-finder-@selectedEmployee.EmployeeOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-user text-bewo-employee h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedEmployee.DetailDescription
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
@{
|
||||
var url = Url.Action("SelectEmployeesForIntervalFinder", "Scheduler");
|
||||
var oid = selectedEmployee.EmployeeOid;
|
||||
|
||||
var onClickParams = $"{oid}, '-interval-finder-checkbox', false, '{url}', 'employees-interval-finder-popup', 'employees-interval-finder-popup', 'related-employee-interval-finder-'";
|
||||
}
|
||||
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedItem(@onClickParams)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments)
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-customers-interval-finder-list">
|
||||
@foreach (var selectedCustomer in Model.SelectedCustomersForIntervalFinder)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="related-customer-interval-finder-@selectedCustomer.CustomerOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-user text-bewo-customers h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedCustomer.DetailDescription
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
@{
|
||||
var url = Url.Action("SelectCustomersForIntervalFinder", "Scheduler");
|
||||
var oid = selectedCustomer.CustomerOid;
|
||||
|
||||
var onClickParams = $"{oid}, '-interval-finder-checkbox', false, '{url}', 'customers-interval-finder-popup', 'customers-interval-finder-popup', 'related-customer-interval-finder-'";
|
||||
}
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedItem(@onClickParams)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-resources-interval-finder-list">
|
||||
@foreach (var selectedResource in Model.SelectedResourcesForIntervalFinder)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="related-resource-interval-finder-item-@selectedResource.ResourceOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-cubes text-bewo-resource h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedResource.Name
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedResource('related-resource-interval-finder-item-@selectedResource.ResourceOid', 'resource-@selectedResource.ResourceOid-interval-finder-checkbox', 'resources-interval-finder-popup', '@Url.Action("SelectResourcesForIntervalFinder", "Scheduler")', 'selected-resources-interval-finder-list')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="d-flex bd-highlight mt-3">
|
||||
<div class="mr-auto bd-highlight">
|
||||
<!-- Abstandshalter -->
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="reset-interval-finder-button" onclick="resetIntervalFinderForm()">Abbrechen</button>
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="find-interval-finder-button" onclick="submitIntervalFinderForm()">Intervalle Prüfen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="resources-interval-finder-popup">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title text-center w-100">Ressourcen</h6>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetResourceSearch('interval-finder-resource-search-input')">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="resourceSearchOnChange('interval-finder-resource-search-input')" id="interval-finder-resource-search-input" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="resetResourceSearch('interval-finder-resource-search-input')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach(var category2Resources in Model.ResourceCategories2Resources)
|
||||
{
|
||||
<div class="card w-100 mb-3 category-card" id="resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="card-header" data-toggle="collapse" data-target="#collapsable-resource-category-interval-finder-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mr-auto">@category2Resources.Key.DisplayName</h5>
|
||||
<div class="btn-group" role="group">
|
||||
<span class="fas fa-chevron-down text-primary"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="collapsable-resource-category-interval-finder-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="card-body resource-list">
|
||||
@foreach(var resource in category2Resources.Value)
|
||||
{
|
||||
var checkedValue = Model.SelectedResourcesForIntervalFinder.Contains(resource) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox resource-text">
|
||||
<input type="checkbox" class="custom-control-input" id="resource-@resource.ResourceOid-interval-finder-checkbox" @checkedValue onchange="changeResourceSelection('resources-interval-finder-popup', '@Url.Action("SelectResourcesForIntervalFinder", "Scheduler")', 'selected-resources-interval-finder-list', 'related-resource-interval-finder-item-', '-interval-finder-checkbox')"/>
|
||||
<label class="custom-control-label resource-name-label" for="resource-@resource.ResourceOid-interval-finder-checkbox">@resource.Name</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments && Model.AllEmployees.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="employees-interval-finder-popup">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title text-center w-100">Mitarbeiter</h6>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetSearch('interval-finder-employee-search-input', 'interval-finder-employee-text')">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="listSearchOnChange('interval-finder-employee-search-input', 'interval-finder-employee-text', 'interval-finder-employee-name-label')" id="interval-finder-employee-search-input" />
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="resetSearch('interval-finder-employee-search-input', 'interval-finder-employee-text')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach(var employee in Model.AllEmployees)
|
||||
{
|
||||
var checkedValue = Model.SelectedEmployeesForIntervalFinder.Contains(employee) ? "checked" : string.Empty;
|
||||
|
||||
var url = Url.Action("SelectEmployeesForIntervalFinder", "Scheduler");
|
||||
|
||||
var onClickParams = $"'{url}', 'employees-interval-finder-popup', 'selected-employees-interval-finder-list', 'related-employee-interval-finder-', false, '-interval-finder-checkbox'";
|
||||
|
||||
<div class="custom-control custom-checkbox interval-finder-employee-text">
|
||||
<input type="checkbox" class="custom-control-input" id="employee-@employee.EmployeeOid-interval-finder-checkbox" @checkedValue onchange="changeItemListSelection(@onClickParams)" />
|
||||
<label class="custom-control-label interval-finder-employee-name-label" for="employee-@employee.EmployeeOid-interval-finder-checkbox">@employee.DetailDescription</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments && Model.AllCustomers.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="customers-interval-finder-popup">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title text-center w-100">Klienten</h6>
|
||||
<button type="button" class="close" data-dismiss="modal" onclick="resetSearch('interval-finder-customer-search-input', 'interval-finder-customer-text')">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="listSearchOnChange('interval-finder-customer-search-input', 'interval-finder-customer-text', 'interval-finder-customer-name-label')" id="interval-finder-customer-search-input"/>
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="resetSearch('interval-finder-customer-search-input', 'interval-finder-customer-text')">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach(var customer in Model.AllCustomers)
|
||||
{
|
||||
var checkedValue = Model.SelectedCustomersForIntervalFinder.Contains(customer) ? "checked" : string.Empty;
|
||||
|
||||
var url = Url.Action("SelectCustomersForIntervalFinder", "Scheduler");
|
||||
|
||||
var onClickParams = $"'{url}', 'customers-interval-finder-popup', 'selected-customers-interval-finder-list', 'related-customer-interval-finder-', true, '-interval-finder-checkbox'";
|
||||
|
||||
<div class="custom-control custom-checkbox interval-finder-customer-text">
|
||||
<input type="checkbox" class="custom-control-input" id="customer-@customer.CustomerOid-interval-finder-checkbox" @checkedValue onchange="changeItemListSelection(@onClickParams)"/>
|
||||
<label class="custom-control-label interval-finder-customer-name-label" for="customer-@customer.CustomerOid-interval-finder-checkbox">@customer.DetailDescription</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
@model BeWoPlanerMobil.Models.SchedulerModel
|
||||
|
||||
<script>
|
||||
$(window).ready(showSize);
|
||||
|
||||
$(window).resize(showSize);
|
||||
|
||||
function showSize() {
|
||||
var width = $(window).width();
|
||||
|
||||
var breakingPoint = getBreakingPoint(width);
|
||||
|
||||
//console.log(breakingPoint + "(" + width + "px)");
|
||||
}
|
||||
</script>
|
||||
|
||||
@if (Model.FreeIntervals.Count > 0)
|
||||
{
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
@foreach(var kv in Model.FreeIntervals)
|
||||
{
|
||||
<div class="col-sm-12 col-md-6 col-lg-4">
|
||||
<div class="card w-100 mb-3">
|
||||
<div class="card-header" data-toggle="collapse" data-target="#collapsable-date-list-@kv.Key.Ticks">
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mr-auto">@kv.Key.ToShortDateString()</h5>
|
||||
<div class="btn-group" role="group">
|
||||
<span class="fas fa-chevron-down text-primary"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="collapsable-date-list-@kv.Key.Ticks">
|
||||
<div class="card-body px-1 py-1">
|
||||
<div class="form-group my-0">
|
||||
<div class="list-group">
|
||||
@foreach(var dts in kv.Value)
|
||||
{
|
||||
<div class="list-group-item my-auto">
|
||||
@using(Html.BeginForm("SelectIntervalForForm", "Scheduler", FormMethod.Post))
|
||||
{
|
||||
<div class="input-group">
|
||||
<p class="form-control border-0 bg-transparent">
|
||||
@dts.StartDate.ToString("HH:mm") - @dts.EndDate.ToString("HH:mm")
|
||||
</p>
|
||||
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary" type="submit" onclick="showSpinner()">
|
||||
<span class="far fa-calendar-plus"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" value="@dts.StartDate.ToString("dd.MM.yyyy HH:mm")" name="startDate"/>
|
||||
<input type="hidden" value="@dts.EndDate.ToString("dd.MM.yyyy HH:mm")" name="endDate"/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@using BeWoPlanerMobil.Models;
|
||||
@using BeWoPlanerMobil.Util
|
||||
@using NHibernate.Criterion
|
||||
@using BeWoPlanerMobil.Models
|
||||
|
||||
@model SchedulerModel
|
||||
@{
|
||||
@@ -47,39 +45,25 @@
|
||||
return "@Url.Action("CheckForOverlappingAppointments", "Scheduler")";
|
||||
}
|
||||
|
||||
function getSelectResourcesForAppointmentUrl() {
|
||||
return "@Url.Action("SelectResourcesForAppointment", "Scheduler")";
|
||||
}
|
||||
|
||||
function getCheckResourcesAvailabilityUrl() {
|
||||
return "@Url.Action("CheckResourcesAvailability", "Scheduler")";
|
||||
}
|
||||
|
||||
function getIsAppointmentSelectedUrl() {
|
||||
return "@Url.Action("HasSelectedAppointment", "Scheduler")";
|
||||
}
|
||||
|
||||
function getSelectEmployeesForAppointmentUrl() {
|
||||
return "@Url.Action("SelectEmployeesForAppointment", "Scheduler")";
|
||||
}
|
||||
|
||||
function getSelectCustomersForAppointmentUrl() {
|
||||
return "@Url.Action("SelectCustomersForAppointment", "Scheduler")";
|
||||
}
|
||||
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
@if (Model?.SelectedAppointment != null)
|
||||
@if(Model != null)
|
||||
{
|
||||
<text>
|
||||
showAppointmentForm();
|
||||
</text>
|
||||
if (Model.SelectedAppointment != null && !Model.IsInIntervalFinderMode)
|
||||
{
|
||||
<text>
|
||||
showAppointmentForm();
|
||||
</text>
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="container mt-3">
|
||||
@if(Html.IsInDebugMode())
|
||||
@*@if(Html.IsInDebugMode())
|
||||
{
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-auto px-1">
|
||||
@@ -96,7 +80,7 @@
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}*@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-auto pr-1 pl-0 pt-1">
|
||||
@using(Html.BeginForm("NavigateToPreviousDate", "Scheduler", FormMethod.Post))
|
||||
@@ -147,220 +131,45 @@
|
||||
}
|
||||
}
|
||||
<div class="col col-12 @editorCol col-lg-3">
|
||||
<div id="form-container" class="d-none d-sm-none d-md-block">
|
||||
@using (Html.BeginForm("InsertOrUpdateAppointment", "Scheduler", FormMethod.Post, new { id = "insert-appointment-form" }))
|
||||
{
|
||||
<div class="mt-3">
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-start-date">Start</label>
|
||||
<div class="input-group date" id="scheduler-start-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-start-date" name="StartDate" class="form-control datetimepicker-input" data-target="#scheduler-start-date-picker" data-toggle="datetimepicker" value="@Model.StartDateToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-start-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-start-time">Von</label>
|
||||
<div class="input-group date" id="scheduler-start-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-start-time" name="StartTime" class="form-control datetimepicker-input" data-target="#scheduler-start-time-picker" value="@Model.StartTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-start-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-end-date">Ende</label>
|
||||
<div class="input-group date" id="scheduler-end-date-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-end-date" name="EndDate" class="form-control datetimepicker-input" data-target="#scheduler-end-date-picker" data-toggle="datetimepicker" value="@Model.EndDateToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-end-date-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar-alt"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="scheduler-end-time">Bis</label>
|
||||
<div class="input-group date" id="scheduler-end-time-picker" data-target-input="nearest">
|
||||
<input type="text" id="scheduler-end-time" name="EndTime" class="form-control datetimepicker-input" data-target="#scheduler-end-time-picker" value="@Model.EndTimeToEdit" />
|
||||
<div class="input-group-append" data-target="#scheduler-end-time-picker" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-clock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.HasResourcesEmployeesOrCustomers)
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
@using (Html.BeginForm("SetIsInIntervalFinderMode", "Scheduler", FormMethod.Post))
|
||||
{
|
||||
<div class="form-row">
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#employees-popup">Mitarbeiter hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#customers-popup">Klienten hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#resources-popup">Ressourcen hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
var buttonValue = Model.IsInIntervalFinderMode ? "Zurück" : "Freie Termine suchen";
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-employees-list">
|
||||
@foreach (var selectedEmployee in Model.SelectedEmployees)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="related-employee-@selectedEmployee.EmployeeOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-user text-bewo-employee h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedEmployee.DetailDescription
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedEmployee(@selectedEmployee.EmployeeOid)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments)
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-customers-list">
|
||||
@foreach (var selectedCustomer in Model.SelectedCustomers)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="related-customer-@selectedCustomer.CustomerOid">
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<i class="fas fa-user text-bewo-customers h-100"></i>
|
||||
</div>
|
||||
<p class="form-control border-0 bg-transparent text-truncate">
|
||||
@selectedCustomer.DetailDescription
|
||||
</p>
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedCustomer(@selectedCustomer.CustomerOid)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-resources-list">
|
||||
@foreach (var selectedResource in Model.SelectedResources)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="relation-item-@selectedResource.ResourceOid">
|
||||
<div class="row">
|
||||
<div class="col my-auto">
|
||||
<i class="fas fa-cubes text-bewo-resource mr-2"></i>
|
||||
@selectedResource.Name
|
||||
</div>
|
||||
<div class="col-auto my-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedResource(@selectedResource.ResourceOid)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<button id="find-free-appointments-btn" type="submit" class="btn btn-primary" onclick="showSpinner()">@buttonValue</button>
|
||||
}
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="subject">Betreff</label>
|
||||
<input type="text" id="subject" name="Subject" class="form-control" value="@Model.SubjectToEdit" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="location">Ort</label>
|
||||
<input type="text" id="location" name="Location" class="form-control" value="@Model.LocationToEdit" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
<label for="notice">Notiz</label>
|
||||
<textarea class="form-control" id="notice" name="Notice">@Model.DescriptionToEdit</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="d-flex bd-highlight mt-3">
|
||||
<div class="mr-auto bd-highlight">
|
||||
<!-- Abstandshalter -->
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="reset-button" onclick="resetInsertAppointmentForm()">Abbrechen</button>
|
||||
</div>
|
||||
<div class="ml-3 bd-highlight">
|
||||
<button type="button" class="btn btn-primary" id="create-button" onclick="submitInsertAppointmentForm()">Speichern</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.IsInIntervalFinderMode)
|
||||
{
|
||||
<!-- Intervallfinder -->
|
||||
<div id="interval-finder-container">
|
||||
@Html.Partial("AppointmentIntervalFinderPartial", Model)
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<!-- Formular -->
|
||||
<div id="form-container" class="d-none d-sm-none d-md-block">
|
||||
@Html.Partial("AppointmentFormPartial", Model)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Terminliste -->
|
||||
<div class="col col-12 @listCol col-lg-9 mt-3">
|
||||
@if (Model.SelectedSchedulerView == "1")
|
||||
<!-- TODO: VORERST NICHT LÖSCHEN!-->
|
||||
@if(Model.IsInIntervalFinderMode)
|
||||
{
|
||||
@Html.Partial("AppointmentIntervalFinderResultPartial", Model)
|
||||
}
|
||||
else
|
||||
{
|
||||
@Html.Partial("OneDaySchedulerPartial", Model)
|
||||
}
|
||||
|
||||
@*@if (Model.SelectedSchedulerView == "1")
|
||||
{
|
||||
@Html.Partial("OneDaySchedulerPartial", Model)
|
||||
}
|
||||
@@ -371,121 +180,7 @@
|
||||
else if (Model.SelectedSchedulerView == "7")
|
||||
{
|
||||
@Html.Partial("SevenDaySchedulerPartial", Model)
|
||||
}
|
||||
}*@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="resources-popup">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title">Ressourcen</h6>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
@foreach (var category2Resources in Model.ResourceCategories2Resources)
|
||||
{
|
||||
<div class="card w-100 mb-3" id="resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="card-header" data-toggle="collapse" data-target="#collapsable-resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mr-auto">@category2Resources.Key.DisplayName</h5>
|
||||
<div class="btn-group" role="group">
|
||||
<span class="fas fa-chevron-down text-primary"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="collapsable-resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="card-body">
|
||||
@foreach (var resource in category2Resources.Value)
|
||||
{
|
||||
var checkedValue = Model.SelectedResources.Contains(resource) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="@resource.ResourceOid-checkbox" @checkedValue onchange="changeResourceSelection()" />
|
||||
<label class="custom-control-label" for="@resource.ResourceOid-checkbox">@resource.Name</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AbstractModel.HasRightToInsertEmployeeAppointments && Model.AllEmployees.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="employees-popup">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title">Mitarbeiter</h6>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
@foreach (var employee in Model.AllEmployees)
|
||||
{
|
||||
var checkedValue = Model.SelectedEmployees.Contains(employee) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="employee-@employee.EmployeeOid-checkbox" @checkedValue onchange="changeEmployeeSelection()" />
|
||||
<label class="custom-control-label" for="employee-@employee.EmployeeOid-checkbox">@employee.DetailDescription</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AbstractModel.HasRightToInsertCustomerAppointments && Model.AllCustomers.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="customers-popup">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title">Klienten</h6>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
@foreach (var customer in Model.AllCustomers)
|
||||
{
|
||||
var checkedValue = Model.SelectedCustomers.Contains(customer) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="customer-@customer.CustomerOid-checkbox" @checkedValue onchange="changeCustomerSelection()" />
|
||||
<label class="custom-control-label" for="customer-@customer.CustomerOid-checkbox">@customer.DetailDescription</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<!-- TODO: Mitarbeiter hinzufügen und vielleicht in dem Zuge auch Klienten? Oder doch erst den Scheduler von DevExpress testen? -->
|
||||
</div>
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- jquery first, then Popper.js, then Bootstrap JS -->
|
||||
<script src="@Url.Content("~/Scripts/jquery-3.6.0.min.js")" type="text/javascript"></script>
|
||||
|
||||
<script src="@Url.Content("~/Scripts/jquery-ui-1.12.1.min.js")"></script>
|
||||
<script src="@Url.Content("~/Scripts/jquery-ui-1.13.0.min.js")"></script>
|
||||
<script src="@Url.Content("~/Scripts/src-min/ace.js")"></script>
|
||||
<script src="@Url.Content("~/Scripts/devexpress-scripts/knockout-3.5.1.js")"></script>
|
||||
<script src="@Url.Content("~/node_modules/cldrjs/dist/cldr.js")"></script>
|
||||
@@ -41,6 +41,8 @@
|
||||
<script src="~/Scripts/view-scripts/report.js?v=1.10"></script>
|
||||
<script src="~/Scripts/signature_pad-3.2.min.js?v=1.10"></script>
|
||||
<script src="~/Scripts/utils/trimCanvas.js?v=1.10"></script>
|
||||
<script src="~/Scripts/utils/resources-list-utils.js?v=1.10"></script>
|
||||
<script src="~/Scripts/utils/list-utils.js?v=1.10"></script>
|
||||
|
||||
@Html.DevExpress().GetStyleSheets(
|
||||
new StyleSheet { ExtensionSuite = ExtensionSuite.NavigationAndLayout },
|
||||
@@ -86,7 +88,7 @@
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
try {
|
||||
logWidthAndBreakingPoint();
|
||||
//logWidthAndBreakingPoint();
|
||||
|
||||
var timeoutInMilliseconds = parseInt("@AbstractBaseController.TimeoutLimit", 10) * 60 * 1000;
|
||||
|
||||
@@ -132,7 +134,7 @@
|
||||
});
|
||||
|
||||
$(window).resize(function() {
|
||||
logWidthAndBreakingPoint();
|
||||
//logWidthAndBreakingPoint();
|
||||
});
|
||||
|
||||
function logWidthAndBreakingPoint() {
|
||||
@@ -256,7 +258,7 @@
|
||||
<i class="fas fa-file-invoice text-bewo-report">
|
||||
|
||||
</i>
|
||||
Auswertung
|
||||
Quittierungsbelege
|
||||
</button>
|
||||
</li>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<configuration>
|
||||
<configSections>
|
||||
@@ -227,6 +227,7 @@
|
||||
<forms loginUrl="~/Login" />
|
||||
</authentication>
|
||||
<sessionState timeout="20" />
|
||||
<identity impersonate="false" />
|
||||
</system.web>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
|
||||
350
BeWoPlanerMobil/package-lock.json
generated
350
BeWoPlanerMobil/package-lock.json
generated
@@ -1,19 +1,305 @@
|
||||
{
|
||||
"name": "bewoplanermobil",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bewoplanermobil",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bootstrap": "^4.4.1",
|
||||
"globalize": "^1.7.0",
|
||||
"sass": "^1.27.0"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
|
||||
"integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jquery": "1.9.1 - 3",
|
||||
"popper.js": "^1.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/cldrjs": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.5.tgz",
|
||||
"integrity": "sha512-KDwzwbmLIPfCgd8JERVDpQKrUUM1U4KpFJJg2IROv89rF172lLufoJnqJ/Wea6fXL5bO6WjuLMzY8V52UWPvkA=="
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/globalize": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/globalize/-/globalize-1.7.0.tgz",
|
||||
"integrity": "sha512-faR46vTIbFCeAemyuc9E6/d7Wrx9k2ae2L60UhakztFg6VuE42gENVJNuPFtt7Sdjrk9m2w8+py7Jj+JTNy59w==",
|
||||
"dependencies": {
|
||||
"cldrjs": "^0.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.27.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz",
|
||||
"integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==",
|
||||
"dependencies": {
|
||||
"chokidar": ">=2.0.0 <4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sass": "sass.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
|
||||
"integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA=="
|
||||
"integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==",
|
||||
"requires": {}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"requires": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
}
|
||||
},
|
||||
"cldrjs": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.5.tgz",
|
||||
"integrity": "sha512-KDwzwbmLIPfCgd8JERVDpQKrUUM1U4KpFJJg2IROv89rF172lLufoJnqJ/Wea6fXL5bO6WjuLMzY8V52UWPvkA=="
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"optional": true
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"globalize": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/globalize/-/globalize-1.7.0.tgz",
|
||||
@@ -21,6 +307,66 @@
|
||||
"requires": {
|
||||
"cldrjs": "^0.5.4"
|
||||
}
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"requires": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"requires": {
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.27.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz",
|
||||
"integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==",
|
||||
"requires": {
|
||||
"chokidar": ">=2.0.0 <4.0.0"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bootstrap": "^4.4.1",
|
||||
"globalize": "^1.7.0"
|
||||
"globalize": "^1.7.0",
|
||||
"sass": "^1.27.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"description": ""
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<package id="cldrjs" version="0.5.1" targetFramework="net472" />
|
||||
<package id="EntityFramework" version="6.4.4" targetFramework="net472" />
|
||||
<package id="jQuery" version="3.6.0" targetFramework="net472" />
|
||||
<package id="jQuery.UI.Combined" version="1.12.1" targetFramework="net472" />
|
||||
<package id="jQuery.UI.Combined" version="1.13.0" targetFramework="net472" />
|
||||
<package id="jQuery.Validation" version="1.19.3" targetFramework="net472" />
|
||||
<package id="log4net" version="2.0.12" targetFramework="net472" />
|
||||
<package id="log4net" version="2.0.13" targetFramework="net472" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net472" />
|
||||
<package id="Microsoft.AspNet.Providers.Core" version="2.0.0" targetFramework="net472" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net472" />
|
||||
@@ -25,9 +25,10 @@
|
||||
<package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.6" targetFramework="net472" />
|
||||
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.12" targetFramework="net472" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net472" />
|
||||
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.1" targetFramework="net472" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
|
||||
<package id="Moment.js" version="2.29.1" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
|
||||
<package id="RestSharp" version="106.12.0" targetFramework="net472" />
|
||||
<package id="RestSharp" version="106.13.0" targetFramework="net472" />
|
||||
<package id="WebGrease" version="1.6.0" targetFramework="net472" />
|
||||
</packages>
|
||||
4
Controls/packages.config
Normal file
4
Controls/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="ClrHeapAllocationAnalyzer" version="3.0.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -127,7 +127,7 @@ namespace BeWo.Data
|
||||
var name = context.Request.Params["ctl00$tb_login"];
|
||||
var password = context.Request.Params["ctl00$tb_password"];
|
||||
|
||||
if (!Utils.IsAnyNullOrEmpty(name, password))
|
||||
if (!BS.Shared.Core.Utils.IsAnyNullOrEmpty(name, password))
|
||||
{
|
||||
ApplicationUser user = DAOFactory.UserDAO.FindUserByLoginName(name);
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace BeWo.Data
|
||||
lPassword = context.Request.Params["token"];
|
||||
}
|
||||
|
||||
if (!Utils.IsAnyNullOrEmpty(lUserName, lPassword))
|
||||
if (!BS.Shared.Core.Utils.IsAnyNullOrEmpty(lUserName, lPassword))
|
||||
{
|
||||
string ip = null;
|
||||
if (context.Request != null)
|
||||
|
||||
@@ -54,5 +54,10 @@ namespace BeWo.Data.Access
|
||||
{
|
||||
//WORKAROUND: Bei geleichzeitigen Asynchronen Calls kann e
|
||||
}
|
||||
|
||||
protected ICriteria CreateCriteriaIsActiveWithAlias<T>(string alias) where T : BeWoEntityBase
|
||||
{
|
||||
return Session.CreateCriteria(typeof(T), alias).Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using BeWo.Data.Entities;
|
||||
using BeWo.Data.Utils;
|
||||
using BeWo.View.Navigation.Filter;
|
||||
using BS.Shared.Extensions;
|
||||
using NHibernate;
|
||||
@@ -488,7 +490,7 @@ namespace BeWo.Data.Access
|
||||
if(!IsNullOrEmpty(pCustomerReferenceNumber))
|
||||
lCriteria.Add(Restrictions.Eq(Customer.PropertyName_ReferenceNumber, pCustomerReferenceNumber));
|
||||
|
||||
if(!Utils.AreAllNullOrEmpty(pCustomerFirstName, pCustomerLastName))
|
||||
if(!BS.Shared.Core.Utils.AreAllNullOrEmpty(pCustomerFirstName, pCustomerLastName))
|
||||
lCriteria.CreateCriteria(Customer.PropertyName_Person)
|
||||
.Add(Restrictions.Like(Person.PropertyName_FirstName, pCustomerFirstName, MatchMode.Anywhere))
|
||||
.Add(Restrictions.Like(Person.PropertyName_LastName, pCustomerLastName, MatchMode.Anywhere));
|
||||
@@ -1417,8 +1419,8 @@ namespace BeWo.Data.Access
|
||||
var schedulerAppointments = appointments as IList<SchedulerAppointment> ?? appointments.ToList();
|
||||
|
||||
// Serientermine anhand der RecurrenceInfo erzeugen und den schedulerAppointments hinzufügen ------------------------------------------------------------
|
||||
var deletedOccurences = schedulerAppointments.Where(app => app.Type == 4).Select(app => Utils.GetOccurrenceId(app.RecurrenceInfo)).ToList();
|
||||
var changedOccurences = schedulerAppointments.Where(app => app.Type == 3).Select(app => Utils.GetOccurrenceId(app.RecurrenceInfo)).ToList();
|
||||
var deletedOccurences = schedulerAppointments.Where(app => app.Type == 4).Select(app => BS.Shared.Core.Utils.GetOccurrenceId(app.RecurrenceInfo)).ToList();
|
||||
var changedOccurences = schedulerAppointments.Where(app => app.Type == 3).Select(app => BS.Shared.Core.Utils.GetOccurrenceId(app.RecurrenceInfo)).ToList();
|
||||
|
||||
var recurringAppointmentsCriteria = CreateRecurrenceCriteria(start, end).Add(Restrictions.Eq(nameof(SchedulerAppointment.Type), 1));
|
||||
|
||||
@@ -2772,20 +2774,10 @@ namespace BeWo.Data.Access
|
||||
var employee2SchedCrit = Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria1);
|
||||
|
||||
var originatorCrit = Restrictions.In(SchedulerAppointment.PropertyName_Originator, pSelectedEmployees);
|
||||
//var notEmployee2SchedCrit = Subqueries.PropertyNotex(BeWoEntityBase.PropertyName_Oid, detachedCriteria1);
|
||||
|
||||
//and not exists(
|
||||
// SELECT
|
||||
//this_0_.Oid as y0_
|
||||
//FROM
|
||||
// Employee2NewSchApp this_0_
|
||||
// WHERE
|
||||
//this_0_.NewSchAppOid = this_.Oid
|
||||
// )
|
||||
|
||||
var detachedCriteria2 = DetachedCriteria.For<Employee2SchedulerAppointment>("e2s2")
|
||||
.SetProjection(Projections.Property(BeWoEntityBase.PropertyName_Oid))
|
||||
.Add(Restrictions.EqProperty("e2s2." + Employee2SchedulerAppointment.PropertyName_SchedulerAppointment, "sa.Oid"));
|
||||
//.Add(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment + ".Oid", mainCriteria.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_Oid))));
|
||||
|
||||
var employee2SchedCrit2 = Subqueries.NotExists(detachedCriteria2);
|
||||
|
||||
@@ -2832,7 +2824,6 @@ namespace BeWo.Data.Access
|
||||
resourceCriterion = Expression.Sql(blah);
|
||||
}
|
||||
|
||||
// AND {SchedulerAppointment.PropertyName_RecurrenceInfo} IS NOT NULL AND {SchedulerAppointment.PropertyName_RecurrenceInfo} NOT LIKE '%Index%'
|
||||
var listOfCriterias = new List<ICriterion>
|
||||
{
|
||||
employeeCriterion,
|
||||
@@ -2957,13 +2948,18 @@ namespace BeWo.Data.Access
|
||||
return ownAppointmentCriterion;
|
||||
}
|
||||
|
||||
private ICriteria CreateRecurrenceCriteria(DateTime start, DateTime end, bool pIncludeInactiveOnes = false)
|
||||
private ICriteria CreateRecurrenceCriteria(DateTime start, DateTime end, bool pIncludeInactiveOnes = false, bool excludeTasks = false)
|
||||
{
|
||||
var recurrenceBetween = Format("'{0:yyyy-MM-dd} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", start, SchedulerAppointment.PropertyName_RecurrenceInfo);
|
||||
var recurrenceAfter = $"'{start:yyyy-MM-dd} 00:00:00' > STR_TO_DATE(SUBSTRING({SchedulerAppointment.PropertyName_RecurrenceInfo}, 24, 19), '%m/%d/%Y %H:%i:%s')";
|
||||
|
||||
var criteria = CreateCriteria<SchedulerAppointment>("sa");
|
||||
|
||||
if(!excludeTasks)
|
||||
{
|
||||
criteria.Add(Restrictions.Not(Restrictions.Eq(nameof(SchedulerAppointment.IsTask), true)));
|
||||
}
|
||||
|
||||
if(!pIncludeInactiveOnes)
|
||||
{
|
||||
criteria.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active));
|
||||
@@ -3324,7 +3320,7 @@ namespace BeWo.Data.Access
|
||||
{
|
||||
var c = CreateCriteria<SchedulerAppointment>();
|
||||
|
||||
c.Add(Restrictions.Eq(nameof(BeWoEntityBase.Notice), Utils.TestAppointmentNotice));
|
||||
c.Add(Restrictions.Eq(nameof(BeWoEntityBase.Notice), BS.Shared.Core.Utils.TestAppointmentNotice));
|
||||
|
||||
return c.List<SchedulerAppointment>();
|
||||
}
|
||||
@@ -4635,5 +4631,203 @@ namespace BeWo.Data.Access
|
||||
|
||||
return list.ToList();
|
||||
}
|
||||
|
||||
// TODO: Intervalle werden als frei angezeigt, wenn sie am Ende eines Tages sind und sich mit Serienterminen überschneiden
|
||||
public Dictionary<DateTime, List<DateTimeSpan>> FindAppointmentsInRange(int duration, DateTime intervalStart, DateTime intervalEnd, List<long> resourceOids, List<long> customerOids, List<long> employeeOids, long loggedInEmployeeOid, int intervalBuffer = 30, bool skipWeekends = true)
|
||||
{
|
||||
var result = new List<SchedulerAppointment>();
|
||||
var intervals = IntervalFinderHelper.CreateIntervals(duration, intervalStart, intervalEnd, skipWeekends, intervalBuffer);
|
||||
|
||||
var subset = IntervalFinderHelper.GenereateIntervalsForChecking(intervalStart, intervalEnd);
|
||||
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
foreach (var dts in subset)
|
||||
{
|
||||
var start = dts.StartDate.MergeDatesByDate(intervalStart);
|
||||
var end = dts.EndDate.MergeDatesByDate(intervalEnd);
|
||||
|
||||
var apptmts = LoadAppointmentsForIntervalFinder(start, end, resourceOids, customerOids, employeeOids, loggedInEmployeeOid, skipWeekends);
|
||||
|
||||
result.AddRangeIfElementsNotIn(apptmts);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
var ms = sw.ElapsedMilliseconds;
|
||||
Debug.WriteLine($"FindAppointmentsInRange: Es dauerte {ms}ms {result.Count} Termine zwischen dem {intervalStart:dd.MM.yyyy HH:mm} und dem {intervalEnd:dd.MM.yyyy HH:mm} aus der Datenbank zu laden");
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Normal = 0,
|
||||
Pattern = 1,
|
||||
Occurrence = 2,
|
||||
ChangedOccurrence = 3,
|
||||
DeletedOccurrence = 4
|
||||
|
||||
*/
|
||||
|
||||
var changedOccurrences = result.Where(a => a.Type == 3).Select(s => BS.Shared.Core.Utils.GetOccurrenceId(s.RecurrenceInfo)).ToList();
|
||||
var deletedOccurrences = result.Where(a => a.Type == 4).Select(s => BS.Shared.Core.Utils.GetOccurrenceId(s.RecurrenceInfo)).ToList();
|
||||
|
||||
var kek = IntervalFinderHelper.GetRecurrencesForIntervalFinder(result, intervalStart, intervalEnd, changedOccurrences, deletedOccurrences, skipWeekends);
|
||||
|
||||
result.AddRange(kek);
|
||||
|
||||
var freeIntervals = new List<DateTimeSpan>();
|
||||
|
||||
if (intervals.Count > 0)
|
||||
{
|
||||
if(result.Count > 0)
|
||||
{
|
||||
foreach (var interval in intervals)
|
||||
{
|
||||
if (!result.Any(a => a.StartDate.HasValue && a.EndDate.HasValue && a.StartDate.Value.IsInInterval(a.EndDate.Value, interval.StartDate, interval.EndDate)))
|
||||
{
|
||||
freeIntervals.Add(interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return IntervalFinderHelper.CreateFreeIntervalsDictionary(intervals);
|
||||
}
|
||||
}
|
||||
|
||||
return IntervalFinderHelper.CreateFreeIntervalsDictionary(freeIntervals);
|
||||
}
|
||||
|
||||
private IEnumerable<SchedulerAppointment> LoadAppointmentsForIntervalFinder(DateTime intervalStart, DateTime intervalEnd, IReadOnlyCollection<long> resourceOids, IReadOnlyCollection<long> customerOids, List<long> employeeOids, long loggedInEmployeeOid, bool skipWeekends)
|
||||
{
|
||||
var result = new List<SchedulerAppointment>();
|
||||
|
||||
if (intervalStart < intervalEnd)
|
||||
{
|
||||
var intervals = IntervalFinderHelper.GenerateIntervalsForCriteria(intervalStart, intervalEnd, skipWeekends);
|
||||
|
||||
var intervalRecurrenceCriterias = IntervalFinderHelper.CreateIntervalRecurrenceCriterias(intervals, skipWeekends);
|
||||
|
||||
var or = CreateOrCriteria(intervalRecurrenceCriterias);
|
||||
|
||||
var criteria = CreateCriteriaIsActiveWithAlias<SchedulerAppointment>("sa")
|
||||
.Add(Restrictions.Not(Restrictions.Eq(nameof(SchedulerAppointment.IsTask), true)));
|
||||
|
||||
if(intervals.Count > 0)
|
||||
{
|
||||
if(intervals.Count > 1)
|
||||
{
|
||||
var criterionList = new List<ICriterion>();
|
||||
|
||||
foreach (var dts in intervals)
|
||||
{
|
||||
criterionList.AddIfNotIn(
|
||||
Restrictions.Or(
|
||||
Restrictions.Between(nameof(SchedulerAppointment.StartDate), dts.StartDate, dts.EndDate),
|
||||
Restrictions.Or(
|
||||
Restrictions.Between(nameof(SchedulerAppointment.EndDate), dts.StartDate, dts.EndDate),
|
||||
Restrictions.And(
|
||||
Restrictions.Lt(nameof(SchedulerAppointment.StartDate), dts.StartDate),
|
||||
Restrictions.Gt(nameof(SchedulerAppointment.EndDate), dts.EndDate)))
|
||||
));
|
||||
}
|
||||
|
||||
criteria.Add(Restrictions.Or(or, CreateOrCriteria(criterionList)));
|
||||
}
|
||||
else
|
||||
{
|
||||
var dts = intervals.FirstOrDefault();
|
||||
|
||||
if (dts != null)
|
||||
{
|
||||
var cri = Restrictions.Or(
|
||||
Restrictions.Between(nameof(SchedulerAppointment.StartDate), dts.StartDate, dts.EndDate),
|
||||
Restrictions.Or(
|
||||
Restrictions.Between(nameof(SchedulerAppointment.EndDate), dts.StartDate, dts.EndDate),
|
||||
Restrictions.And(
|
||||
Restrictions.Lt(nameof(SchedulerAppointment.StartDate), dts.StartDate),
|
||||
Restrictions.Gt(nameof(SchedulerAppointment.EndDate), dts.EndDate)))
|
||||
);
|
||||
|
||||
criteria.Add(Restrictions.Or(or, cri));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ICriterion resourceCriterion = null;
|
||||
ICriterion customerCriterion = null;
|
||||
|
||||
if (employeeOids.Count == 0)
|
||||
{
|
||||
employeeOids.Add(loggedInEmployeeOid);
|
||||
}
|
||||
|
||||
var detachedCriteria1 = DetachedCriteria.For<Employee2SchedulerAppointment>()
|
||||
.Add(Restrictions.In(nameof(Employee2SchedulerAppointment.Employee) + ".Oid", employeeOids))
|
||||
.SetProjection(Projections.Property(nameof(Employee2SchedulerAppointment.SchedulerAppointmentOid)));
|
||||
var employee2SchedCrit = Subqueries.PropertyIn(nameof(BeWoEntityBase.Oid), detachedCriteria1);
|
||||
|
||||
var originatorCrit = Restrictions.In(nameof(SchedulerAppointment.Originator), employeeOids);
|
||||
|
||||
var detachedCriteria2 = DetachedCriteria.For<Employee2SchedulerAppointment>("e2s2")
|
||||
.SetProjection(Projections.Property(nameof(BeWoEntityBase.Oid)))
|
||||
.Add(Restrictions.EqProperty("e2s2." + nameof(Employee2SchedulerAppointment.SchedulerAppointmentOid), "sa.Oid"));
|
||||
|
||||
var employee2SchedCrit2 = Subqueries.NotExists(detachedCriteria2);
|
||||
|
||||
var and = Restrictions.And(originatorCrit, employee2SchedCrit2);
|
||||
|
||||
var employeeCriterion = Restrictions.Or(employee2SchedCrit, and);
|
||||
|
||||
if (customerOids?.Count > 0)
|
||||
{
|
||||
var customerSql = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM customer2newschapp WHERE customeroid IN ({customerOids.ToSeparatedString(",")}))";
|
||||
customerCriterion = Expression.Sql(customerSql);
|
||||
}
|
||||
|
||||
if (resourceOids?.Count > 0)
|
||||
{
|
||||
var resourceSql = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM resource2newschapp WHERE resourceoid IN ({resourceOids.ToSeparatedString(",")}))";
|
||||
resourceCriterion = Expression.Sql(resourceSql);
|
||||
}
|
||||
|
||||
var listOfCriterias = new List<ICriterion>
|
||||
{
|
||||
employeeCriterion,
|
||||
customerCriterion,
|
||||
resourceCriterion
|
||||
};
|
||||
|
||||
if (listOfCriterias.Count > 0)
|
||||
{
|
||||
var orCriteria = CreateOrCriteria(listOfCriterias);
|
||||
|
||||
if (orCriteria != null)
|
||||
{
|
||||
criteria.Add(orCriteria);
|
||||
}
|
||||
}
|
||||
|
||||
var criteriaAsString = criteria.ToString();
|
||||
|
||||
var appointments = criteria.List<SchedulerAppointment>().ToList();
|
||||
|
||||
result.AddRange(appointments);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetGeneratedSql(ICriteria criteria)
|
||||
{
|
||||
var criteriaImpl = (CriteriaImpl) criteria;
|
||||
var sessionImpl = (SessionImpl) criteriaImpl.Session;
|
||||
var factory = (SessionFactoryImpl) sessionImpl.SessionFactory;
|
||||
var implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName);
|
||||
var loader = new CriteriaLoader((IOuterJoinLoadable) factory.GetEntityPersister(implementors[0]), factory, criteriaImpl, implementors[0], sessionImpl.EnabledFilters);
|
||||
|
||||
return loader.SqlString.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,6 +372,8 @@
|
||||
<Compile Include="Entities\Employee.cs" />
|
||||
<Compile Include="Entities\Person.cs" />
|
||||
<Compile Include="UpdInsInterceptor.cs" />
|
||||
<Compile Include="Utils\AppointmentSearchResult.cs" />
|
||||
<Compile Include="Utils\IntervalFinderHelper.cs" />
|
||||
<Compile Include="WCFHibernateSessionManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
@@ -873,6 +875,7 @@
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace BeWo.Data.ICD10
|
||||
}
|
||||
}
|
||||
|
||||
return Utils.Compress(sr.ToString());
|
||||
return BS.Shared.Core.Utils.Compress(sr.ToString());
|
||||
}
|
||||
|
||||
public static string GetDiagnosisForCode(string code)
|
||||
|
||||
13
Data/Utils/AppointmentSearchResult.cs
Normal file
13
Data/Utils/AppointmentSearchResult.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using BeWo.Data.Entities;
|
||||
using BS.Shared.Core;
|
||||
|
||||
namespace BeWo.Data.Utils
|
||||
{
|
||||
public class AppointmentSearchResult
|
||||
{
|
||||
public List<SchedulerAppointment> Appointments { get; set; } = new List<SchedulerAppointment>();
|
||||
|
||||
public List<DateTimeSpan> Intervals { get; set; } = new List<DateTimeSpan>();
|
||||
}
|
||||
}
|
||||
320
Data/Utils/IntervalFinderHelper.cs
Normal file
320
Data/Utils/IntervalFinderHelper.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BeWo.Data.Entities;
|
||||
using BS.Shared.Core;
|
||||
using BS.Shared.Extensions;
|
||||
using DevExpress.XtraScheduler;
|
||||
using DevExpress.XtraScheduler.Compatibility;
|
||||
using NHibernate.Criterion;
|
||||
using NHibernate.SqlCommand;
|
||||
|
||||
namespace BeWo.Data.Utils
|
||||
{
|
||||
public class IntervalFinderHelper
|
||||
{
|
||||
public static List<DateTimeSpan> GenerateIntervalsForCriteria(DateTime intervalStart, DateTime intervalEnd, bool skipWeekends)
|
||||
{
|
||||
var result = new List<DateTimeSpan>();
|
||||
|
||||
if (intervalEnd <= intervalStart)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var start = intervalStart;
|
||||
var end = start.MergeDatesByDate(intervalEnd);
|
||||
|
||||
while (end <= intervalEnd)
|
||||
{
|
||||
end = start.MergeDatesByDate(intervalEnd);
|
||||
|
||||
if (skipWeekends && (start.Date.DayOfWeek == DayOfWeek.Saturday || start.Date.DayOfWeek == DayOfWeek.Sunday))
|
||||
{
|
||||
start = start.AddDays(1);
|
||||
end = start.MergeDatesByDate(intervalEnd);
|
||||
continue;
|
||||
}
|
||||
|
||||
result.AddIfNotIn(new DateTimeSpan(start, end));
|
||||
|
||||
start = start.AddDays(1);
|
||||
end = start.MergeDatesByDate(intervalEnd);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<ICriterion> CreateIntervalRecurrenceCriterias(List<DateTimeSpan> intervals, bool skipWeekends)
|
||||
{
|
||||
var result = new List<ICriterion>();
|
||||
|
||||
foreach(var interval in intervals)
|
||||
{
|
||||
var start = interval.StartDate;
|
||||
var end = interval.EndDate;
|
||||
|
||||
result.AddIfNotIn(CreateRecurrenceCriterion(start, end));
|
||||
}
|
||||
|
||||
// TODO: KGW
|
||||
//for (var i = 0; i < totalDays; i++)
|
||||
//{
|
||||
// start = start.AddDays(i).MergeDatesByDate(startDate);
|
||||
|
||||
// if (skipWeekends && (start.DayOfWeek == DayOfWeek.Saturday || start.DayOfWeek == DayOfWeek.Sunday))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// DateTime e;
|
||||
// var end = start.MergeDatesByDate(endDate);
|
||||
|
||||
// while ((e = start.AddMinutes(duration)) <= end && start <= end.AddMinutes(-1 * duration))
|
||||
// {
|
||||
// result.AddIfNotIn(CreateRecurrenceCriterion(start, e));
|
||||
|
||||
// start = start.AddMinutes(intervalBuffer);
|
||||
// }
|
||||
//}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ICriterion CreateRecurrenceCriterion(DateTime start, DateTime end)
|
||||
{
|
||||
var recurrenceBetween = $"'{start:yyyy-MM-dd HH:mm:ss}' BETWEEN STR_TO_DATE(SUBSTRING(RecurrenceInfo, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING(RecurrenceInfo, 50, 19), '%m/%d/%Y %H:%i:%s')";
|
||||
var recurrenceAfter = $"'{start:yyyy-MM-dd HH:mm:ss}' > STR_TO_DATE(SUBSTRING(RecurrenceInfo, 24, 19), '%m/%d/%Y %H:%i:%s')";
|
||||
|
||||
var result = Restrictions.Or(
|
||||
Restrictions.And(
|
||||
Restrictions.Not(Restrictions.Like(nameof(SchedulerAppointment.RecurrenceInfo), "Range", MatchMode.Anywhere)),
|
||||
Restrictions.Like(nameof(SchedulerAppointment.RecurrenceInfo), "OccurrenceCount=\"10\"", MatchMode.Anywhere)),
|
||||
Restrictions.Or(
|
||||
Restrictions.Or(
|
||||
Restrictions.And(Restrictions.Lt(nameof(SchedulerAppointment.StartDate), end), Restrictions.Ge(nameof(SchedulerAppointment.EndDate), start)),
|
||||
Restrictions.Or(Restrictions.And(
|
||||
Restrictions.Like(nameof(SchedulerAppointment.RecurrenceInfo), "End", MatchMode.Anywhere),
|
||||
Restrictions.And(Restrictions.IsNotNull(nameof(SchedulerAppointment.RecurrenceInfo)), Expression.Sql(new SqlString(recurrenceBetween)))
|
||||
), Restrictions.And(
|
||||
Restrictions.And(
|
||||
Restrictions.IsNotNull(nameof(SchedulerAppointment.RecurrenceInfo)),
|
||||
Restrictions.Not(Restrictions.Like(nameof(SchedulerAppointment.RecurrenceInfo), "End", MatchMode.Anywhere))),
|
||||
Expression.Sql(recurrenceAfter)))
|
||||
),
|
||||
Restrictions.And(Restrictions.Eq(nameof(SchedulerAppointment.Type), 3), Expression.Sql(new SqlString(recurrenceBetween)))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Dictionary<DateTime, List<DateTimeSpan>> CreateFreeIntervalsDictionary(IEnumerable<DateTimeSpan> freeIntervals)
|
||||
{
|
||||
var result = new Dictionary<DateTime, List<DateTimeSpan>>();
|
||||
|
||||
var groupedIntervals = from dateTimeSpan in freeIntervals group dateTimeSpan by dateTimeSpan.StartDate.Date;
|
||||
|
||||
var unsortedDictionary = new Dictionary<DateTime, List<DateTimeSpan>>();
|
||||
|
||||
foreach (var grouping in groupedIntervals)
|
||||
{
|
||||
var orderedList = grouping.OrderBy(dateTimeSpan => dateTimeSpan.StartDate).ToList();
|
||||
|
||||
unsortedDictionary.AddOrUpdateValueInDictionary(grouping.Key, orderedList);
|
||||
}
|
||||
|
||||
var keys = unsortedDictionary.Keys.OrderBy(key => key.Date).ToList();
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
result.Add(key, unsortedDictionary[key]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<DateTimeSpan> CreateIntervals(int duration, DateTime intervalStart, DateTime intervalEnd, bool skipWeekends, int intervalBuffer)
|
||||
{
|
||||
var result = new List<DateTimeSpan>();
|
||||
|
||||
if (duration > 0 && intervalStart < intervalEnd && intervalBuffer > 10)
|
||||
{
|
||||
var timeSpan = intervalEnd - intervalStart;
|
||||
|
||||
var totalDays = Convert.ToInt32(Math.Ceiling(timeSpan.TotalDays));
|
||||
|
||||
for (var i = 0; i < totalDays; i++)
|
||||
{
|
||||
var start = intervalStart.AddDays(i).MergeDatesByDate(intervalStart);
|
||||
|
||||
if (skipWeekends && (start.DayOfWeek == DayOfWeek.Saturday || start.DayOfWeek == DayOfWeek.Sunday))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DateTime e;
|
||||
var end = start.MergeDatesByDate(intervalEnd);
|
||||
|
||||
while ((e = start.AddMinutes(duration)) <= end && start <= end.AddMinutes(-1 * duration))
|
||||
{
|
||||
result.Add(new DateTimeSpan(start, e));
|
||||
|
||||
start = start.AddMinutes(intervalBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<DateTimeSpan> GenereateIntervalsForChecking(DateTime intervalStart, DateTime intervalEnd)
|
||||
{
|
||||
var start = intervalStart.Date;
|
||||
var end = intervalEnd.Date;
|
||||
|
||||
var result = new List<DateTimeSpan>();
|
||||
|
||||
if (end < start)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var days = Convert.ToInt32((end - start).TotalDays);
|
||||
|
||||
if (days == 0)
|
||||
{
|
||||
days = 1;
|
||||
}
|
||||
|
||||
var rest = days % 6;
|
||||
var limit = (days - rest) / 6;
|
||||
|
||||
var s = start;
|
||||
DateTime e;
|
||||
|
||||
for (var i = 0; i < limit; i++)
|
||||
{
|
||||
e = s.AddDays(5);
|
||||
|
||||
result.Add(new DateTimeSpan(s, e));
|
||||
|
||||
s = e.AddDays(1);
|
||||
}
|
||||
|
||||
if (rest > 0)
|
||||
{
|
||||
e = s.AddDays(rest);
|
||||
|
||||
if (rest == 1)
|
||||
{
|
||||
e = e.AddDays(-1);
|
||||
}
|
||||
|
||||
result.Add(new DateTimeSpan(s, e));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IEnumerable<SchedulerAppointment> CalculateRecurrences(IEnumerable<SchedulerAppointment> appointments, DateTime start, DateTime end, IReadOnlyCollection<RecurrenceInformation> changedOccurrences, IReadOnlyCollection<RecurrenceInformation> deletedOccurrences)
|
||||
{
|
||||
var result = new List<SchedulerAppointment>();
|
||||
|
||||
var interval = new TimeInterval(start, end);
|
||||
|
||||
foreach (var appointment in appointments.Where(app => app.RecurrenceInfo != null && app.Type == 1 && app.StartDate.HasValue && app.EndDate.HasValue))
|
||||
{
|
||||
var recurrenceInfo = new RecurrenceInfo();
|
||||
recurrenceInfo.FromXml(appointment.RecurrenceInfo);
|
||||
var occurrenceCalculator = OccurrenceCalculator.CreateInstance(recurrenceInfo);
|
||||
|
||||
var pattern = StaticAppointmentFactory.CreateAppointment(AppointmentType.Pattern);
|
||||
pattern.RecurrenceInfo.FromXml(appointment.RecurrenceInfo);
|
||||
pattern.Start = pattern.RecurrenceInfo.Start;
|
||||
pattern.End = pattern.RecurrenceInfo.End;
|
||||
var patternId = pattern.RecurrenceInfo.Id.ToString();
|
||||
|
||||
var occurrences = occurrenceCalculator.CalcOccurrences(interval, pattern);
|
||||
|
||||
if (occurrences.Count > 0)
|
||||
{
|
||||
foreach (var app in occurrences.GetAppointments(interval))
|
||||
{
|
||||
if(appointment.EndDate == null || appointment.StartDate == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var index = app.RecurrenceIndex;
|
||||
|
||||
var duration = (appointment.EndDate.Value - appointment.StartDate.Value).TotalMinutes;
|
||||
|
||||
var s = app.Start;
|
||||
var e = app.Start.AddMinutes(duration);
|
||||
|
||||
var isOutOfInterval = s.AreInBetweenDates(e, start, end) == false;
|
||||
var isChangedOccurrence = changedOccurrences.Any(a => a.PatternId.Equals(patternId) && a.Index == index);
|
||||
var isDeletedOccurrence = deletedOccurrences.Any(a => a.PatternId.Equals(patternId) && a.Index == index);
|
||||
|
||||
if (isOutOfInterval || isChangedOccurrence || isDeletedOccurrence)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var recurringAppointment = new SchedulerAppointment
|
||||
{
|
||||
AllDay = appointment.AllDay,
|
||||
CustomerList = appointment.CustomerList,
|
||||
Notice = appointment.Notice,
|
||||
EmployeeList = appointment.EmployeeList,
|
||||
EndDate = app.Start.AddMinutes(duration),
|
||||
FormerBookingSequenceOid = appointment.FormerBookingSequenceOid,
|
||||
IsPrivate = appointment.IsPrivate,
|
||||
Location = appointment.Location,
|
||||
Originator = appointment.Originator,
|
||||
RecurrenceInfo = app.RecurrenceInfo.ToXml(),
|
||||
ReminderInfo = appointment.ReminderInfo,
|
||||
ResourceList = appointment.ResourceList,
|
||||
StartDate = app.Start,
|
||||
Subject = appointment.Subject ?? string.Empty,
|
||||
Type = appointment.Type
|
||||
};
|
||||
|
||||
result.AddIfNotIn(recurringAppointment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IEnumerable<SchedulerAppointment> GetRecurrencesForIntervalFinder(List<SchedulerAppointment> appointments, DateTime startDate, DateTime endDate, IReadOnlyCollection<RecurrenceInformation> changedOccurrences, IReadOnlyCollection<RecurrenceInformation> deletedOccurrences, bool skipWeekends)
|
||||
{
|
||||
var result = new List<SchedulerAppointment>();
|
||||
|
||||
var dayCount = Convert.ToInt32(Math.Ceiling((endDate - startDate).TotalDays));
|
||||
|
||||
if (dayCount <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
for (var i = 0; i < dayCount; i++)
|
||||
{
|
||||
var start = startDate.AddDays(i);
|
||||
|
||||
if (skipWeekends && (start.DayOfWeek == DayOfWeek.Saturday || start.DayOfWeek == DayOfWeek.Sunday))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var end = start.MergeDatesByDate(endDate);
|
||||
|
||||
var calculatedRecurrences = CalculateRecurrences(appointments, start, end, changedOccurrences, deletedOccurrences);
|
||||
|
||||
result.AddRange(calculatedRecurrences);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Data/packages.config
Normal file
28
Data/packages.config
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="ClrHeapAllocationAnalyzer" version="3.0.0" targetFramework="net472" />
|
||||
<package id="EntityFramework" version="6.4.0" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Providers.Core" version="2.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.Analyzers" version="2.9.6" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.VisualBasic" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.VisualBasic.Workspaces" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.Workspaces.Common" version="3.4.0" targetFramework="net472" />
|
||||
<package id="System.Buffers" version="4.4.0" targetFramework="net472" />
|
||||
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net472" />
|
||||
<package id="System.Composition" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.AttributedModel" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Convention" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Hosting" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Runtime" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.TypedParts" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Memory" version="4.5.3" targetFramework="net472" />
|
||||
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
|
||||
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" />
|
||||
<package id="System.Text.Encoding.CodePages" version="4.5.1" targetFramework="net472" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net472" />
|
||||
</packages>
|
||||
@@ -26,7 +26,7 @@
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile />
|
||||
<Use64BitIISExpress />
|
||||
<Use64BitIISExpress>false</Use64BitIISExpress>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<NameOfLastUsedPublishProfile>BeWo2.0</NameOfLastUsedPublishProfile>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
|
||||
<Use64BitIISExpress />
|
||||
<Use64BitIISExpress>false</Use64BitIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
|
||||
25
Report/packages.config
Normal file
25
Report/packages.config
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.CodeAnalysis" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.Analyzers" version="2.9.6" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.VisualBasic" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.VisualBasic.Workspaces" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.Workspaces.Common" version="3.4.0" targetFramework="net472" />
|
||||
<package id="System.Buffers" version="4.4.0" targetFramework="net472" />
|
||||
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net472" />
|
||||
<package id="System.Composition" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.AttributedModel" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Convention" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Hosting" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Runtime" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.TypedParts" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Memory" version="4.5.3" targetFramework="net472" />
|
||||
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
|
||||
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" />
|
||||
<package id="System.Text.Encoding.CodePages" version="4.5.1" targetFramework="net472" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net472" />
|
||||
</packages>
|
||||
26
ReportService/packages.config
Normal file
26
ReportService/packages.config
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="ClrHeapAllocationAnalyzer" version="3.0.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.Analyzers" version="2.9.6" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.VisualBasic" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.VisualBasic.Workspaces" version="3.4.0" targetFramework="net472" />
|
||||
<package id="Microsoft.CodeAnalysis.Workspaces.Common" version="3.4.0" targetFramework="net472" />
|
||||
<package id="System.Buffers" version="4.4.0" targetFramework="net472" />
|
||||
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net472" />
|
||||
<package id="System.Composition" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.AttributedModel" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Convention" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Hosting" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.Runtime" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Composition.TypedParts" version="1.0.31" targetFramework="net472" />
|
||||
<package id="System.Memory" version="4.5.3" targetFramework="net472" />
|
||||
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
|
||||
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" />
|
||||
<package id="System.Text.Encoding.CodePages" version="4.5.1" targetFramework="net472" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net472" />
|
||||
</packages>
|
||||
@@ -17,35 +17,32 @@ namespace BeWo.Service.DCEntityMapper
|
||||
pDataContract.SchedulerAppointmentOid = pEntity.Oid;
|
||||
pDataContract.NewSchedulerAppointmentVersion = pEntity.Version;
|
||||
|
||||
pDataContract.AllDay = pEntity.AllDay;
|
||||
pDataContract.EndDate = pEntity.EndDate;
|
||||
pDataContract.StartDate = pEntity.StartDate;
|
||||
pDataContract.Status = pEntity.Status;
|
||||
pDataContract.Subject = pEntity.Subject;
|
||||
pDataContract.Type = pEntity.Type;
|
||||
pDataContract.Location = pEntity.Location;
|
||||
pDataContract.Description = pEntity.Notice;
|
||||
pDataContract.AllDay = pEntity.AllDay;
|
||||
pDataContract.EndDate = pEntity.EndDate;
|
||||
pDataContract.StartDate = pEntity.StartDate;
|
||||
pDataContract.Status = pEntity.Status;
|
||||
pDataContract.Subject = pEntity.Subject;
|
||||
pDataContract.Type = pEntity.Type;
|
||||
pDataContract.Location = pEntity.Location;
|
||||
pDataContract.Description = pEntity.Notice;
|
||||
pDataContract.RecurrenceInfo = pEntity.RecurrenceInfo;
|
||||
pDataContract.ReminderInfo = pEntity.ReminderInfo;
|
||||
pDataContract.ReminderInfo = pEntity.ReminderInfo;
|
||||
|
||||
pDataContract.IsPrivate = pEntity.IsPrivate;
|
||||
pDataContract.IsPrivate = pEntity.IsPrivate;
|
||||
pDataContract.CustomerList = MapperFactory.CompactCustomerDC_Customer.MapToNewDCs(pEntity.CustomerList);
|
||||
pDataContract.ResourceList = MapperFactory.ResourceDC_Resource.MapToNewDCs(pEntity.ResourceList);
|
||||
pDataContract.EmployeeList = MapperFactory.Employee2SchedulerAppointmentDC_Employee2SchedulerAppointment.MapToNewDCs(pEntity.EmployeeList);
|
||||
|
||||
pDataContract.IsTask = pEntity.IsTask;
|
||||
pDataContract.IsTask = pEntity.IsTask;
|
||||
pDataContract.TaskDescription = pEntity.TaskDescription;
|
||||
pDataContract.CompletedNotice = pEntity.CompletedNotice;
|
||||
pDataContract.CompletedDate = pEntity.CompletedDate;
|
||||
|
||||
pDataContract.DueDate = pEntity.DueDate;
|
||||
pDataContract.CompletedDate = pEntity.CompletedDate;
|
||||
|
||||
pDataContract.DueDate = pEntity.DueDate;
|
||||
pDataContract.FormerBookingSequenceOid = pEntity.FormerBookingSequenceOid;
|
||||
pDataContract.SupportConceptList = MapperFactory.CompactSupportConceptDC_SupportConcept.MapToNewDCs(pEntity.SupportConceptList);
|
||||
|
||||
pDataContract.FormerTaskOid = pEntity.FormerTaskOid;
|
||||
|
||||
pDataContract.HasServiceRecordEntry = pEntity.HasServiceRecordEntry;
|
||||
pDataContract.SupportConceptList = MapperFactory.CompactSupportConceptDC_SupportConcept.MapToNewDCs(pEntity.SupportConceptList);
|
||||
pDataContract.FormerTaskOid = pEntity.FormerTaskOid;
|
||||
pDataContract.HasServiceRecordEntry = pEntity.HasServiceRecordEntry;
|
||||
|
||||
if (pEntity.Originator != null)
|
||||
{
|
||||
@@ -61,29 +58,25 @@ namespace BeWo.Service.DCEntityMapper
|
||||
{
|
||||
ConcurrencyCheck(pDataContract.NewSchedulerAppointmentVersion, pEntity);
|
||||
|
||||
pEntity.Oid = pDataContract.SchedulerAppointmentOid;
|
||||
pEntity.Version = pDataContract.NewSchedulerAppointmentVersion;
|
||||
|
||||
pEntity.AllDay = pDataContract.AllDay;
|
||||
pEntity.EndDate = pDataContract.EndDate;
|
||||
pEntity.StartDate = pDataContract.StartDate;
|
||||
pEntity.Status = pDataContract.Status;
|
||||
pEntity.Subject = pDataContract.Subject;
|
||||
pEntity.Type = pDataContract.Type;
|
||||
pEntity.Location = pDataContract.Location;
|
||||
pEntity.Notice = pDataContract.Description;
|
||||
pEntity.RecurrenceInfo = pDataContract.RecurrenceInfo;
|
||||
pEntity.ReminderInfo = pDataContract.ReminderInfo;
|
||||
|
||||
pEntity.Oid = pDataContract.SchedulerAppointmentOid;
|
||||
pEntity.Version = pDataContract.NewSchedulerAppointmentVersion;
|
||||
pEntity.AllDay = pDataContract.AllDay;
|
||||
pEntity.EndDate = pDataContract.EndDate;
|
||||
pEntity.StartDate = pDataContract.StartDate;
|
||||
pEntity.Status = pDataContract.Status;
|
||||
pEntity.Subject = pDataContract.Subject;
|
||||
pEntity.Type = pDataContract.Type;
|
||||
pEntity.Location = pDataContract.Location;
|
||||
pEntity.Notice = pDataContract.Description;
|
||||
pEntity.RecurrenceInfo = pDataContract.RecurrenceInfo;
|
||||
pEntity.ReminderInfo = pDataContract.ReminderInfo;
|
||||
pEntity.FormerBookingSequenceOid = pDataContract.FormerBookingSequenceOid;
|
||||
|
||||
pEntity.IsTask = pDataContract.IsTask;
|
||||
pEntity.TaskDescription = pDataContract.TaskDescription;
|
||||
pEntity.CompletedNotice = pDataContract.CompletedNotice;
|
||||
pEntity.CompletedDate = pDataContract.CompletedDate;
|
||||
pEntity.DueDate = pDataContract.DueDate;
|
||||
|
||||
pEntity.FormerTaskOid = pDataContract.FormerTaskOid;
|
||||
pEntity.IsTask = pDataContract.IsTask;
|
||||
pEntity.TaskDescription = pDataContract.TaskDescription;
|
||||
pEntity.CompletedNotice = pDataContract.CompletedNotice;
|
||||
pEntity.CompletedDate = pDataContract.CompletedDate;
|
||||
pEntity.DueDate = pDataContract.DueDate;
|
||||
pEntity.FormerTaskOid = pDataContract.FormerTaskOid;
|
||||
|
||||
if (pDataContract.Originator != null)
|
||||
{
|
||||
@@ -91,8 +84,7 @@ namespace BeWo.Service.DCEntityMapper
|
||||
}
|
||||
|
||||
pEntity.IsPrivate = pDataContract.IsPrivate;
|
||||
|
||||
pEntity.HasServiceRecordEntry = pDataContract.HasServiceRecordEntry;
|
||||
pEntity.HasServiceRecordEntry = pDataContract.HasServiceRecordEntry;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
|
||||
using BS.Shared.Core;
|
||||
using BS.Shared.DataContracts;
|
||||
|
||||
namespace BeWo.Service.ServiceContracts
|
||||
@@ -224,5 +224,9 @@ namespace BeWo.Service.ServiceContracts
|
||||
[FaultContract(typeof(BeWoFault))]
|
||||
[OperationContract]
|
||||
List<SchedulerAppointmentDC> LoadOccurrencesByRecurrenceId(string recurrenceId);
|
||||
|
||||
[FaultContract(typeof(BeWoFault))]
|
||||
[OperationContract]
|
||||
Dictionary<DateTime, List<DateTimeSpan>> FindAppointmentsInRange(int duration, DateTime startDate, DateTime endDate, List<long> resourceOids, List<long> customerOids, List<long> employeeOids, long loggedInEmployeeOid, int intervalBuffer = 30, bool skipWeekends = true);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ using BS.Shared.Core;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.DataContracts.Compact;
|
||||
using BS.Shared.Extensions;
|
||||
using DevExpress.Utils;
|
||||
using DevExpress.XtraScheduler;
|
||||
using static System.String;
|
||||
using Resource = BeWo.Data.Entities.Resource;
|
||||
@@ -1190,7 +1191,7 @@ namespace BeWo.Service.ServiceImplementations
|
||||
|
||||
var result = FilterAppointments(all, pEmployeeOid, filteredEmployeeOids, pSelectedCustomer, pSelectedResources, pCustomersOnly, pResourcesOnly, pShowTasks);
|
||||
|
||||
//Check fehlerhaftes RecurrenceInfos
|
||||
//Check fehlerhafte RecurrenceInfos
|
||||
foreach(var app in result)
|
||||
{
|
||||
if(!IsNullOrEmpty(app.RecurrenceInfo))
|
||||
@@ -2314,5 +2315,19 @@ namespace BeWo.Service.ServiceImplementations
|
||||
throw Utils.CreateBeWoFaultException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<DateTime, List<DateTimeSpan>> FindAppointmentsInRange(int duration, DateTime startDate, DateTime endDate, List<long> resourceOids, List<long> customerOids, List<long> employeeOids, long loggedInEmployeeOid, int intervalBuffer = 30, bool skipWeekends = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var intervals = DAOFactory.SearchDAO.FindAppointmentsInRange(duration, startDate, endDate, resourceOids, customerOids, employeeOids, loggedInEmployeeOid, intervalBuffer, skipWeekends);
|
||||
|
||||
return intervals;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw Utils.CreateBeWoFaultException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,6 +184,16 @@ namespace BS.Shared.Core
|
||||
|
||||
return new ArbeitszeitEintragDateTimeObject(start, end);
|
||||
}
|
||||
|
||||
public static string GetTwoDateString(this DateTime date1, DateTime date2)
|
||||
{
|
||||
if (date1.Date.Equals(date2.Date))
|
||||
{
|
||||
return date2 > date1 ? $"{date1:dd.MM.yyyy HH:mm} - {date2:HH:mm}" : $"{date2:dd.MM.yyyy HH:mm} - {date1:HH:mm}";
|
||||
}
|
||||
|
||||
return date2 > date1 ? $"{date1:dd.MM.yyyy HH:mm} - {date2:dd.MM.yyyy HH:mm}" : $"{date2:dd.MM.yyyy HH:mm} - {date1:dd.MM.yyyy HH:mm}";
|
||||
}
|
||||
}
|
||||
|
||||
public class AnzahlMonate
|
||||
|
||||
@@ -100,5 +100,10 @@ namespace BS.Shared.Extensions
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<T> Clone<T>(this IList<T> list)
|
||||
{
|
||||
return list?.ToList() ?? new List<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user