Files
BeWoPlaner/BeWoPlanerMobil/Views/Scheduler/AppointmentFormPartial.cshtml
Lyndon Jetten 3ca4ec5323 Das Gruppenbuchungsformular hat jetzt die Summe der Ziele aller ausgewählten Hilfepläne und die Schnittmenge deren Leistungen und Kategorien.
Das Mehrfachbuchungsformular hat ebenfalls die Schnittmenge der Leistungen und Kategorien von den ausgewählten Hilfeplänen.

Das Caching ist wieder aktiviert. Und lädt pro Post-Aufruf nur noch einmal 13 MB und danach nur noch 300 kb herunter.

Überall konsequent geprüft, ob das Model nicht null ist und falls dem so ist, wird ausgeloggt, damit es zu keinen Fehlern mehr kommt.
2024-06-26 12:29:22 +02:00

665 lines
36 KiB
Plaintext

@using BeWoPlanerMobil.Models
@using BeWoPlanerMobil.Util
@using BS.Shared.Extensions
@model SchedulerModel
@{
if(TempData[TempDataConstants.DoLogoutKey] is bool doLogout && doLogout)
{
<text>
<script type="text/javascript">
$("#second-logout-form").submit();
</script>
</text>
}
}
<script>
function alldayChange() {
try {
$("#scheduler-start-time, #scheduler-end-time").attr("disabled", $("#IsAllDay").prop("checked"));
} catch(error) {
showErrorPopup(error);
}
}
$("#insert-appointment-form").ready(function () {
calcPrependTextSizes();
});
function calcPrependTextSizes() {
try {
var width = getMaxWidth("scheduler-form-prepend-text");
if(width <= 0) {
return;
}
$(".scheduler-form-prepend-text").width(width);
} catch(error) {
showErrorPopup(error);
}
}
</script>
@using(Html.BeginForm("InsertOrUpdateAppointment", "Scheduler", FormMethod.Post, new { id = "insert-appointment-form" }))
{
var disabled = Model.SelectedAppointment?.AllDay ?? false ? "disabled" : string.Empty;
<div class="mt-3">
<div class="form-row">
<div class="col-7 mx-0 pr-1">
<div class="form-group mb-1 mr-0 pr-0">
<div class="input-group date" id="scheduler-start-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text scheduler-form-prepend-text">
Start
</div>
</div>
<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 px-2">
<i class="fas fa-calendar-alt"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-5 mx-0 pr-1">
<div class="form-group mb-1 ml-0 pl-0">
<div class="input-group date" id="scheduler-start-time-picker" data-target-input="nearest">
<input type="text" id="scheduler-start-time" @disabled 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 px-2">
<i class="fas fa-clock"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-row">
<div class="col-7 mx-0 pr-1">
<div class="form-group mb-1 mr-0 pr-0">
<div class="input-group date" id="scheduler-end-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text scheduler-form-prepend-text">
Ende
</div>
</div>
<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 px-2">
<i class="fas fa-calendar-alt"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-5 mx-0 pr-1">
<div class="form-group mb-1 ml-0 pl-0">
<div class="input-group date" id="scheduler-end-time-picker" data-target-input="nearest">
<input type="text" id="scheduler-end-time" @disabled 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 px-2">
<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.HasRightToViewEmployeeAppointments && AbstractModel.HasRightToInsertEmployeeAppointments)
{
<div class="col-md">
<div class="form-group my-1">
<button type="button" class="btn btn-bewo-employee w-100" data-toggle="modal" data-target="#employees-popup">Mitarbeiter</button>
</div>
</div>
}
@if(AbstractModel.HasRightToViewCustomerSelectionInScheduler && AbstractModel.HasRightToInsertCustomerAppointments)
{
<div class="col-md">
<div class="form-group my-1">
<button type="button" class="btn btn-bewo-customers w-100" data-toggle="modal" data-target="#customers-popup">Klienten</button>
</div>
</div>
}
@if(AbstractModel.HasRightToViewAllResourceAppointments && AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
{
<div class="col-md">
<div class="form-group my-1">
<button type="button" class="btn btn-bewo-resource w-100" data-toggle="modal" data-target="#resources-popup">Ressourcen</button>
</div>
</div>
}
</div>
<div class="form-row">
@if(AbstractModel.HasRightToViewEmployeeAppointments && 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="removeSelectedEmployee(@selectedEmployee.EmployeeOid)">
<span class="fas fa-times-circle"></span>
</button>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
}
@if(AbstractModel.HasRightToViewCustomerSelectionInScheduler && 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 filterAppointmentsUrl = Url.Action("FetchAppointments", "Scheduler");
var onClickParams = $"{oid}, '-checkbox', true, '{url}', 'customers-popup', 'selected-customers-list', 'related-customer-', '{filterAppointmentsUrl}'";
}
<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.HasRightToViewAllResourceAppointments && AbstractModel.HasRightToInsertRessourceAppointments)
{
<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', '@Url.Action("FetchAppointments")', 'relation-item-', '-checkbox', 'all-resources-checkbox')">
<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">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text scheduler-form-prepend-text">
Betreff
</div>
</div>
<input type="text" id="subject" name="Subject" class="form-control" maxlength="256" value="@Model.SubjectToEdit" />
</div>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md">
<div class="form-group mb-1">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text scheduler-form-prepend-text">
Ort
</div>
</div>
<input type="text" id="location" name="Location" class="form-control" maxlength="256" value="@Model.LocationToEdit" />
</div>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md">
<div class="form-group mb-1">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text scheduler-form-prepend-text">
Notiz
</div>
</div>
<textarea class="form-control" id="notice" name="Notice" maxlength="1024">@Model.DescriptionToEdit</textarea>
</div>
</div>
</div>
</div>
</div>
}
<div class="w-100 bd-highlight mt-3">
<div class="ml-0 bd-highlight float-left">
<button type="button" class="btn btn-primary" id="reset-button" onclick="resetInsertAppointmentForm()">Abbrechen</button>
</div>
<div class="ml-3 bd-highlight float-right">
<button type="button" class="btn btn-primary" id="create-button" onclick="submitInsertAppointmentForm()">Speichern</button>
</div>
</div>
@if(AbstractModel.HasRightToViewAllResourceAppointments && 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="resetTreeSearch('resource-search-input', 'resource-text', 'category-card')">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">
<div class="custom-control custom-checkbox custom-control-inline mx-auto">
@{
var allResourcesCheckedVal = Model.AllResources.AreListEqual(Model.SelectedResources) ? "checked" : string.Empty;
}
<input type="checkbox" class="custom-control-input" id="all-resources-checkbox" @allResourcesCheckedVal onchange="selectAllCheckboxOnChange('all-resources-checkbox', '@Url.Action("SelectResourcesForAppointment", "Scheduler")', 'resources-popup', 'selected-resources-list', 'relation-item-', false, null, '@Url.Action("FetchAppointments", "Scheduler")', null)" />
<label class="custom-control-label" for="all-resources-checkbox">Alle</label>
</div>
</div>
</div>
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="treeSearchOnChange('resource-search-input', 'resource-text', 'category-card', 'resource-name-label', 'resource-list')" id="resource-search-input" />
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" onclick="resetTreeSearch('resource-search-input', 'resource-text', 'category-card')">
<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 tree-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', '@Url.Action("FetchAppointments", "Scheduler")', 'all-resources-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.HasRightToViewEmployeeAppointments && AbstractModel.HasRightToInsertEmployeeAppointments && Model.AllEmployees.Any())
{
<script type="text/javascript">
function resetEmployeeSearch() {
try {
$("#employee-search-input").val("");
$(".employee-text").show();
} catch (error) {
showErrorPopup(error);
}
}
function employeeListSearchOnChange() {
try {
var text = $("#employee-search-input").val().toLowerCase();
var entries = $(".employee-text");
if (text.length === 0) {
entries.show();
}
$.each(entries, function (index, item) {
var employee = $(item);
if(employee.find(".employee-name-label").text().toLowerCase().includes(text)) {
employee.show();
} else {
employee.hide();
}
});
} catch(error) {
showErrorPopup(error);
}
}
function selectAllEmployeesOnChange() {
try {
var allChecked = $("#all-employees-checkbox").prop("checked");
$("#employees-popup .employee-input-container input[type=checkbox]").map(function() { $(this).prop("checked", allChecked); });
changeEmployeeListSelection();
} catch(error) {
showErrorPopup(error);
}
}
function changeEmployeeListSelection() {
try {
var selectedEmployeeOids = $("#employees-popup .employee-input-container input:checked").map(function() { return $(this).attr("id").split("-")[1]; }).get();
var allEmployeesCount = $("#employees-popup .employee-input-container input[type=checkbox]").map(function () { return $(this).attr("id").split("-")[1]; }).get().length;
var selectedEmployeesCount = selectedEmployeeOids.length;
$("#all-employees-checkbox").prop("checked", (allEmployeesCount === selectedEmployeesCount));
$.get('@Url.Action("SelectEmployeesForAppointment")', { oidString: selectedEmployeeOids.toString()}).done(function(jsonResult) {
updateSelectedEmployees(jsonResult);
$("#one-day-scheduler-partial-container").load('@Url.Action("FetchAppointments", "Scheduler")');
});
} catch(error) {
showErrorPopup(error);
}
}
function updateSelectedEmployees(jsonResult) {
try {
if(false === checkJson(jsonResult)) {
logWarning("updateSelectedEmployees: Der zurückgegebene Wert ist kein gültiges JSON!");
hideSpinner();
return;
}
var listItems = parseJason(jsonResult);
var list = $("#selected-employees-list");
list.empty();
$.each(listItems, function(index, item) {
var oid = item.EmployeeOid;
var id = "#related-employee-" + oid;
var html =
"<div class=\"list-group-item my-auto\" id=\"" + id + "\">" +
"<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\">" +
item.LastName + ", " + item.FirstName +
"</p>" +
"<div class=\"input-group-append\">" +
'<button class="btn btn-primary ficken" type="button" onclick="removeSelectedEmployee(' + oid + ')">' +
"<span class='fas fa-times-circle'></span>" +
"</button>" +
"</div>" +
"</div>" +
"</div>" +
"</div>";
list.append(html);
});
} catch (error) {
showErrorPopup(error);
}
}
function removeSelectedEmployee(employeeOid) {
try {
var checkbox = $("#employee-" + employeeOid + "-checkbox");
if(checkbox.length) {
checkbox.prop("checked", false);
}
changeEmployeeListSelection();
} catch (error) {
showErrorPopup(error);
}
}
function selectTeamForAppointment(teamOid) {
try {
$.get('@Url.Action("SelectTeamForAppointment")', {teamOidString: teamOid}).done(function (jsonResult) {
if(false === checkJson(jsonResult)) {
logWarning("selectTeamForAppointment: Der zurückgegebene Wert ist kein gültiges JSON!");
hideSpinner();
return;
}
var oids = parseJason(jsonResult);
$("#employees-popup .employee-input-container input[type=checkbox]").each(function () {
var id = $(this).attr("id").split("-")[1];
if ($.isNumeric(id) === false) {
return;
}
if(oids.includes(parseFloat(id))) {
$(this).prop("checked", true);
}
});
changeEmployeeListSelection();
});
} catch(error) {
showErrorPopup(error);
}
}
</script>
<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="resetEmployeeSearch()">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">
<div class="custom-control custom-checkbox custom-control-inline mx-auto">
@{
var allEmployeesCheckedVal = Model.AllEmployees.AreListEqual(Model.SelectedEmployees) ? "checked" : string.Empty;
}
<input type="checkbox" class="custom-control-input" id="all-employees-checkbox" @allEmployeesCheckedVal onchange="selectAllEmployeesOnChange()" />
<label class="custom-control-label" for="all-employees-checkbox">Alle</label>
</div>
</div>
</div>
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="employeeListSearchOnChange()" id="employee-search-input" />
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" onclick="resetEmployeeSearch()">
<span class="fas fa-times-circle"></span>
</button>
</div>
</div>
@if(AbstractModel.HasRightToViewTeams)
{
<div class="card w-100 mb-3">
<div class="card-header" data-toggle="collapse" data-target="#collapsable-teams-selection">
<div class="d-flex align-items-center">
<h5 class="mr-auto">Meine Teams</h5>
<div class="btn-group" role="group">
<span class="fas fa-chevron-down text-primary"></span>
</div>
</div>
</div>
<div class="collapse" id="collapsable-teams-selection">
<div class="card-body">
@foreach(var team in Model.MyTeams)
{
<button type="button" class="btn btn-bewo-teams w-100 my-2" onclick="selectTeamForAppointment(@team.TeamOid)">@team.Name</button>
}
</div>
</div>
</div>
<hr />
}
<div class="employee-input-container">
@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="changeEmployeeListSelection()" />
<label class="custom-control-label employee-name-label" for="employee-@employee.EmployeeOid-checkbox">@employee.DetailDescription</label>
</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.HasRightToViewCustomerSelectionInScheduler && 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>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">
@{
var allCustomersCheckedVal = Model.AllCustomers.AreListEqual(Model.SelectedCustomers) ? "checked" : string.Empty;
}
<div class="custom-control custom-checkbox custom-control-inline mx-auto">
<input type="checkbox" class="custom-control-input" id="all-customers-checkbox" @allCustomersCheckedVal onchange="selectAllCheckboxOnChange('all-customers-checkbox', '@Url.Action("SelectCustomersForAppointment", "Scheduler")', 'customers-popup', 'selected-customers-list', 'related-customer-', true, '-checkbox', '@Url.Action("FetchAppointments", "Scheduler")', '')" />
<label class="custom-control-label" for="all-customers-checkbox">Alle</label>
</div>
</div>
</div>
<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>
<div class="popup-list-item-container">
@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', '@Url.Action("FetchAppointments", "Scheduler")', '', getTeamMemberOids(), 'all-customers-checkbox')" />
<label class="custom-control-label customer-name-label" for="customer-@customer.CustomerOid-checkbox">@customer.DetailDescription</label>
</div>
}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
</div>
</div>
</div>
</div>
}