MoK: die bisherigen Zeit- und Datumsfelder durch browsereigene ersetzt und das Zwischenspeichern im LocalStorage im Browser für die Doku-Texte eingebaut.

This commit is contained in:
2025-05-16 19:24:16 +02:00
parent 931b1de798
commit b20102832c
29 changed files with 1720 additions and 1273 deletions

View File

@@ -746,7 +746,7 @@
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<UseIIS>True</UseIIS>
<AutoAssignPort>False</AutoAssignPort>
<DevelopmentServerPort>8808</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>

View File

@@ -15,7 +15,7 @@
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
<WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
<WebStackScaffolding_IsLayoutPageSelected>False</WebStackScaffolding_IsLayoutPageSelected>
<WebStackScaffolding_IsPartialViewSelected>False</WebStackScaffolding_IsPartialViewSelected>
<WebStackScaffolding_IsPartialViewSelected>True</WebStackScaffolding_IsPartialViewSelected>
<WebStackScaffolding_IsReferencingScriptLibrariesSelected>False</WebStackScaffolding_IsReferencingScriptLibrariesSelected>
<WebStackScaffolding_LayoutPageFile>
</WebStackScaffolding_LayoutPageFile>

View File

@@ -118,7 +118,7 @@ namespace BeWoPlanerMobil.Controllers
}
}
Model.ShowBetrag = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowBetrag);
AbstractModel.ShowBetrag = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowBetrag);
Model.ShowMarker = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowMarker);
}
@@ -127,6 +127,11 @@ namespace BeWoPlanerMobil.Controllers
Model.EinheitZeiterfassung = UserSettingsUtils.GetSettingValueAsInteger(mandatorSettings, SettingsKeys.EinheitZeiterfassung);
/*
* Minuten: 0
* Stunden: 1
* Min & Std: 2
*/
if(Model.EinheitZeiterfassung == 1)
{
Model.IsShowingDurationInHours = true;
@@ -166,7 +171,7 @@ namespace BeWoPlanerMobil.Controllers
Model.GroupsOfPeople = EmployeeService.GetAllGroups(GetUser().Employee.EmployeeOid).OrderBy(gop => gop.Name).ToList();
Model.ShowDistanceField = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.ShowDistanceFields);
AbstractModel.ShowDistanceField = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.ShowDistanceFields);
Model.Dokutypes = ValueListService.GetAllValueListEntrysByType(ValueListEntryType.DocumentType);
if(Model.Dokutypes != null)
@@ -184,7 +189,7 @@ namespace BeWoPlanerMobil.Controllers
Model.EmployeesForGroupAndMultiBooking = EmployeeService.GetAllCompactEmployees().Where(e => e.ActivationType == ActivationTypeId.Active).OrderBy(e => e.LastName).ToList();
}
if (MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreationForOtherEmployees))
if(MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreationForOtherEmployees))
{
Model.Employees = EmployeeService.GetAllActiveEmployeesCompact();
}
@@ -366,9 +371,7 @@ namespace BeWoPlanerMobil.Controllers
return;
}
var ratingTypes = OperationsService.GetAllRatingTypes().OrderBy(o => o.Position); ;
Model.GoalRatingTypes = ratingTypes.ToList();
Model.GoalRatingTypes = OperationsService.GetAllRatingTypes().OrderBy(o => o.Position).ToList();
}
[Authorize]
@@ -2343,8 +2346,6 @@ namespace BeWoPlanerMobil.Controllers
var startDt = startDate.AddHours(startHoursDt.Hour).AddMinutes(startHoursDt.Minute);
var endDt = endDate.AddHours(endHoursDt.Hour).AddMinutes(endHoursDt.Minute);
var dauer = (int) (endDt - startDt).TotalMinutes;
if(dauer == 0 || start == string.Empty && end == string.Empty)
@@ -4542,15 +4543,44 @@ namespace BeWoPlanerMobil.Controllers
var serviceRecordOids2GoalHeaders = new Dictionary<long, List<string>>();
var goalOids = new List<long>();
var measures = new List<ValueListEntryDC>();
//var measures = new List<ValueListEntryDC>();
serviceRecords.DoForEach(serviceRecord =>
{
measures.AddRangeIfElementsNotIn(serviceRecord.Goals);
//measures.AddRangeIfElementsNotIn(serviceRecord.Goals);
goalOids.AddRangeIfElementsNotIn(serviceRecord.Goals.Where(goal => goal.ParentOid.HasValue).Select(goal => goal.ParentOid.Value));
});
var goalCategories = ValueListService.GetGoalCategoriesByOids(goalOids);
//serviceRecords.DoForEach(serviceRecord =>
//{
// if(serviceRecord.ServiceRecordOid is null)
// {
// return;
// }
// serviceRecord.Goals.OrderBy(vle => $"{vle.Abbreviation}-{vle.TypeDescription}").DoForEach(goal =>
// {
// var goalCategory = goalCategories.FirstOrDefault(g => g.ValueListEntryOid.HasValue && goal.ValueListEntryOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ValueListEntryOid.Value) || (g.ValueListEntryOid.HasValue && goal.ParentOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ParentOid.Value)));
// if(goalCategory != null)
// {
// serviceRecordOids2GoalHeaders.AddOrUpdateValueInDictionary(serviceRecord.ServiceRecordOid.Value, new List<string> { goalCategory.DisplayName });
// }
// });
//});
Model.ServiceRecordOids2GoalHeader = GetServiceRecordOids2GoalHeaders(serviceRecords, goalCategories);
Model.ServiceRecords = serviceRecords;
}
[Authorize]
public static Dictionary<long, List<string>> GetServiceRecordOids2GoalHeaders(List<ServiceRecordDC> serviceRecords, List<ValueListEntryDC> goalCategories)
{
var serviceRecordOids2GoalHeaders = new Dictionary<long, List<string>>();
serviceRecords.DoForEach(serviceRecord =>
{
if(serviceRecord.ServiceRecordOid is null)
@@ -4569,9 +4599,7 @@ namespace BeWoPlanerMobil.Controllers
});
});
Model.ServiceRecordOids2GoalHeader = serviceRecordOids2GoalHeaders;
Model.ServiceRecords = serviceRecords;
return serviceRecordOids2GoalHeaders;
}
[Authorize]

View File

@@ -14,7 +14,6 @@ using System.Linq;
using System.Text;
using System.Web.Mvc;
using BeWo.Service.Plugins;
using BS.Shared.DataContracts.Compact;
// Controller des Quittierungsbelegsmoduls
@@ -113,23 +112,6 @@ namespace BeWoPlanerMobil.Controllers
Model.Customers.Clear();
//if(AbstractModel.CheckForAtLeastOneRight(new[] { UserRightType.CustomerView_View, UserRightType.ViewAll }))
//{
// Model.Customers = CustomerService.GetAllActiveCustomersForEmployee().OrderByDescending(x => x.LastName).ToList();
//}
//else
//{
// if(AbstractModel.CheckRight(UserRightType.Customer_ViewMyCustomers))
// {
// Model.Customers = MobileSessionFacade.LoggedInEmployee.RelatedCustomers.OrderByDescending(x => x.Customer.LastName).Select(customerEmployeeRelation => customerEmployeeRelation.Customer).ToList();
// }
// if(AbstractModel.CheckRight(UserRightType.Customer_ViewMyTeams))
// {
// Model.Customers.AddRangeIfElementsNotIn(EmployeeService.GetActiveCompactCustomersForEmployee());
// }
//}
Model.Customers = EmployeeService.GetActiveCompactCustomersForEmployee(Model.Employee.EmployeeOid.Value);
Model.Employees = EmployeeService.GetActiveCompactEmployeesForEmployee(MobileSessionFacade.LoggedInCompactEmployee.EmployeeOid);
@@ -140,6 +122,12 @@ namespace BeWoPlanerMobil.Controllers
Model.Organisations.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.CurrentCulture));
Model.AllTeams = EmployeeService.GetAllActiveCompactTeamsForEmployee(MobileSessionFacade.LoggedInEmployee.EmployeeOid);
Model.Dokutypes = ValueListService.GetAllValueListEntrysByType(ValueListEntryType.DocumentType);
if(Model.Dokutypes != null)
{
Model.Dokutypes = Model.Dokutypes.OrderBy(s => s.ValueListEntryOid).ToArray();
}
}
catch(Exception e)
{
@@ -1295,6 +1283,11 @@ namespace BeWoPlanerMobil.Controllers
Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.AddRangeIfElementsNotIn(confirmationReceiptResults.OrderBy(o => o.CustomerName));
if(Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.Any())
{
Model.GoalRatingTypes = OperationsService.GetAllRatingTypes().OrderBy(o => o.Position).ToList();
}
if(Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.All(qbItem => qbItem.Items.Count == 0))
{
TempData[TempDataConstants.HasWarningMessageKey] = true;
@@ -1312,6 +1305,7 @@ namespace BeWoPlanerMobil.Controllers
public class ConfirmationReceiptSignatureObject
{
public Guid Identifier { get; }
public string ImageStr { get; }
public string InsTsStr { get; }
public string PersonName { get; }
@@ -1321,6 +1315,8 @@ namespace BeWoPlanerMobil.Controllers
public ConfirmationReceiptSignatureObject(string imageStr, string insTsStr, string personName, bool isEmployeeSignature, List<ServiceRecordDC> serviceRecords)
{
Identifier = Guid.NewGuid();
ImageStr = imageStr;
InsTsStr = insTsStr;
PersonName = personName;

View File

@@ -29,13 +29,7 @@ namespace BeWoPlanerMobil
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
//Context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
// Context.Response.Cache.SetAllowResponseInBrowserHistory(false);
// Context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
// Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
// Context.Response.Cache.SetNoStore();
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
}

View File

@@ -248,5 +248,9 @@ namespace BeWoPlanerMobil.Models
return "1" == settingsValue;
}
}
public static bool ShowDistanceField { get; set; }
public static bool ShowBetrag { get; set; }
}
}

View File

@@ -229,8 +229,6 @@ namespace BeWoPlanerMobil.Models
public long? ServiceRecordOidToDelete { get; set; }
public bool ShowDistanceField { get; set; }
public MainModel()
{
NewServiceRecord = new ServiceRecordDC();
@@ -509,6 +507,10 @@ namespace BeWoPlanerMobil.Models
public int EinheitZeiterfassung { get; set; }
public string StartDateToEditJSFormat => SelectedServiceRecord?.Start?.ToString("yyyy-MM-dd") ?? DateTime.Today.ToString("yyyy-MM-dd");
public string EndDateToEditJSFormat => SelectedServiceRecord?.End?.ToString("yyyy-MM-dd") ?? DateTime.Today.ToString("yyyy-MM-dd");
public string StartDateToEdit => SelectedServiceRecord?.Start?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
public string EndDateToEdit => SelectedServiceRecord?.End?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
@@ -755,7 +757,7 @@ namespace BeWoPlanerMobil.Models
return SelectedServiceDescription;
}
public bool ShowBetrag { get; set; }
public string LocalStorageKey => $"bwp_{MobileSessionFacade.Tenant}_{MobileSessionFacade.LoggedInUser.Oid}";
}
public class CustomSelectListItem

View File

@@ -260,5 +260,13 @@ namespace BeWoPlanerMobil.Models
public int MaxResults { get; set; } = 10;
public int QbEntryPageCount { get; set; }
public int CurrentQbEntryPage { get; set; }
public List<RatingTypeDC> GoalRatingTypes { get; set; } = new List<RatingTypeDC>();
public Dictionary<long, List<string>> ServiceRecordOids2GoalHeader { get; set; }
public ValueListEntryDC[] Dokutypes { get; set; }
public int NumberOfDokuTypes => Dokutypes?.Length ?? 0;
}
}

View File

@@ -174,8 +174,8 @@ namespace BeWoPlanerMobil.Models
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 IntervalStartDateStr => IntervalStartDate.HasValue ? IntervalStartDate.Value.ToString("yyyy-MM-ddTHH:mm") : string.Empty;
public string IntervalEndDateStr => IntervalEndDate.HasValue ? IntervalEndDate.Value.ToString("yyyy-MM-ddTHH:mm") : string.Empty;
public string IntervalStartTimeStr => IntervalStartDate.HasValue ? $"{IntervalStartDate:HH:mm}" : string.Empty;
public string IntervalEndTimeStr => IntervalEndDate.HasValue ? $"{IntervalEndDate:HH:mm}" : string.Empty;

View File

@@ -190,14 +190,18 @@ function showAlertMessageBox(title, message, callback, executeCallbackByBothButt
$("#message-popup-ok-btn").off("click");
$("#message-popup-ok-btn").on("click", function() {
callback();
if(typeof callback === "function") {
callback();
}
});
$("#message-popup-close-btn").off("click");
if(executeCallbackByBothButtons === true) {
$("#message-popup-close-btn").on("click", function() {
callback();
if (typeof callback === "function") {
callback();
}
});
}

View File

@@ -3,6 +3,60 @@ function hideSignature() {
$("#signature-img-popup").modal("hide");
}
function updateCanvasSize(canvasJQueryElement) {
if(canvasJQueryElement.length === 0) {
logError("Canvas nicht gefunden!");
return;
}
const rowWidth = canvasJQueryElement.parent().parent().innerWidth();
const sourceCanvas = document.getElementById(canvasJQueryElement.attr("id"));
const canvasWidth = sourceCanvas.scrollWidth;
const newWidth = rowWidth;
var parsedNewWidth = parseInt(newWidth, 10);
const parsedCanvasWidth = parseInt(canvasWidth, 10);
let isMinDifferenceMet = false;
if (parsedCanvasWidth > parsedNewWidth) {
isMinDifferenceMet = parsedCanvasWidth - parsedNewWidth > 4;
} else {
isMinDifferenceMet = parsedNewWidth - parsedCanvasWidth > 4;
}
if (isMinDifferenceMet) {
var trimmedCanvas = trimCanvas(cloneCanvas(sourceCanvas));
var canvasContext = sourceCanvas.getContext("2d", { willReadFrequently: true });
canvasJQueryElement.prop("width", newWidth);
if(trimmedCanvas.width <= 0 || trimmedCanvas.height <= 0) {
return;
}
var img = new Image;
img.onload = function () {
if (trimmedCanvas.width > parsedNewWidth) {
const factor = trimmedCanvas.height / trimmedCanvas.width;
const newHeight = parsedNewWidth * factor;
canvasContext.drawImage(img, 0, 0, parsedNewWidth - 1, newHeight - 1);
} else {
canvasContext.drawImage(img, 0, 0);
}
};
img.src = trimmedCanvas.toDataURL();
}
}
// Veraltet seit 17.04.2025; Neue Funktion: updateCanvasSize(canvasJQueryElement)
function resizeCanvas(sketchPadId, canvasRoId) {
if($(sketchPadId).length !== 0) {
const rowWidth = $(canvasRoId).innerWidth();
@@ -38,9 +92,8 @@ function resizeCanvas(sketchPadId, canvasRoId) {
img.onload = function () {
if(trimmedCanvas.width > parsedNewWidth) {
var factor = trimmedCanvas.height / trimmedCanvas.width;
var newHeight = parsedNewWidth * factor;
const factor = trimmedCanvas.height / trimmedCanvas.width;
const newHeight = parsedNewWidth * factor;
canvasContext.drawImage(img, 0, 0, parsedNewWidth - 1, newHeight - 1);
} else {
@@ -53,13 +106,14 @@ function resizeCanvas(sketchPadId, canvasRoId) {
}
}
// Das Initialisieren der Einzelunterschrift
function initializeSignature(selectedServiceRecordOid) {
$("#main-container, #checkbox-container").hide();
$("#signature-container").addClass("d-block");
$.get(getSelectedRecordInformationUrlWithOid(), { oid: selectedServiceRecordOid }).done(function(jsonServiceRecord2Monatsunterschrift) {
$.get(window.getSelectedRecordInformationUrlWithOid(), { oid: selectedServiceRecordOid }).done(function(jsonServiceRecord2Monatsunterschrift) {
if(jsonServiceRecord2Monatsunterschrift === "SessionTimeout") {
window.location.href = getRedirectLink();
window.location.href = window.getRedirectLink();
return;
}
@@ -125,7 +179,7 @@ function initializeSignature(selectedServiceRecordOid) {
$("#signature-alert").removeClass("d-none");
}
resizeCanvas("#sketch-pad", "#canvas-row");
updateCanvasSize($("#sketch-pad"));
var canvas = document.getElementById("sketch-pad");

View File

@@ -84,13 +84,13 @@ function onDurationChange(startTimeId, endTimeId, startDateId, endDateId, durati
}
}
// ToDo: Erst Dauer, dann Start- oder Endzeit führt dazu, dass die Dauer in Stunden benutzt wird!
// ToDo: VERALTET (14.05.2025); Erst Dauer, dann Start- oder Endzeit führt dazu, dass die Dauer in Stunden benutzt wird!
function calculateDuration(isInvocatedByHoursMinutesButton, startTimeId, endTimeId, durationId, hoursMinutesDropdownBtnId, startDatePickerId, endDatePickerId, isInvokedByStartElement, isInvokedByEndElement) {
var startTime = $(`#${startTimeId}`).val();
var endTime = $(`#${endTimeId}`).val();
var duration = $(`#${durationId}`).val();
var hoursMinutesDropdownButton = $("#" + hoursMinutesDropdownBtnId);
var hoursMinutesDropdownButton = $(`#${hoursMinutesDropdownBtnId}`);
var isInMin = window.getIsZeiterfassungseinheitInMinutes();
@@ -192,6 +192,207 @@ function calculateDuration(isInvocatedByHoursMinutesButton, startTimeId, endTime
function calcTimeWithDuration() {
function calcDuration(idPrefix, isFormatChange, isInvokedByStart, isInvokedByEnd) {
const endDateInput = $(`#${idPrefix}-end-date-input`);
const startDateInput = $(`#${idPrefix}-start-date-input`);
const endTimeInput = $(`#${idPrefix}-end-time-input`);
const startTimeInput = $(`#${idPrefix}-start-time-input`);
const durationInput = $(`#${idPrefix}-duration-input`);
const hoursMinutesBtn = $(`#${idPrefix}-hours-minutes-dropdown-btn`);
const startDateValue = startDateInput.val();
const startTimeValue = startTimeInput.val();
const endDateValue = endDateInput.val();
const endTimeValue = endTimeInput.val();
const durationValue = durationInput.val();
const isInMin = hoursMinutesBtn.length === 0 || hoursMinutesBtn.length > 0 && hoursMinutesBtn.text().replaceAll(/\s/g, "") !== "Minuten";
const hasEndDate = endDateInput.length;
if (startDateValue.length === 0) {
return;
}
const isStartTimeValid = startTimeValue !== null && startTimeValue !== undefined && startTimeValue.length > 0;
const isEndTimeValid = endTimeValue !== null && endTimeValue !== undefined && endTimeValue.length > 0;
const duration = parseFloat(durationValue.replace(",", "."));
const isDurationValid = !isNaN(duration);
let start = new Date(startDateValue);
let end = hasEndDate ? new Date(endDateValue) : start;
if (true === isStartTimeValid && true === isEndTimeValid && false === isFormatChange) {
start = combineDateAndTime(start, startTimeValue);
end = combineDateAndTime(end, endTimeValue);
let dauer = (end.getTime() - start.getTime()) / 60000;
if (duration > 0 && true === isInvokedByStart && start >= end) {
end = new Date(start.getTime() + (false === isInMin ? duration * 60 : duration) / 60000);
endTimeInput.val(getTimeAsString(end));
endDateInput.val(getDateAsString(end));
dauer = (end.getTime() - start.getTime()) * 60000;
}
if (duration > 0 && true === isInvokedByEnd && start >= end) {
start = new Date(end.getTime() - (false === isInMin ? duration * 60 : duration) / 60000);
startTimeInput.val(getTimeAsString(start));
startDateInput.val(getDateAsString(start));
dauer = (end.getTime() - start.getTime()) * 60000;
}
durationInput.val(dauer);
} else if(true === isStartTimeValid && true === isDurationValid) {
if(true === isFormatChange) {
let newDurationValue = true === isInMin ? duration * 60.0 : duration / 60.0;
if(isNaN(newDurationValue)) {
durationInput.val("");
} else {
durationInput.val(newDurationValue);
}
}
calcTimeWithDuration(startTimeValue, endTimeInput, start, duration, isFormatChange, isInMin);
} else if(true === isEndTimeValid && true === isDurationValid) {
if(true === isFormatChange) {
durationInput.val(formatDuration(isInMin, true === isInMin ? duration * 60.0 : duration / 60.0));
}
calcTimeWithDuration(endTimeValue, startTimeInput, start, duration * -1.0, isFormatChange, isInMin);
} else if(true === isFormatChange) {
if (true === isFormatChange) {
durationInput.val(formatDuration(isInMin, true === isInMin ? duration * 60.0 : duration / 60.0));
}
}
}
function formatDuration(isInMin, durationAsNumber) {
if(true === isNaN(durationAsNumber)) {
return "";
}
const roundedValue = Math.round(durationAsNumber * 1000) / 1000;
if(isInMin) {
return roundedValue.toString().includes(".") ? roundedValue.toString().split(".")[0] : roundedValue;
} else {
if (roundedValue.toString().includes(".")) {
const splitRoundedValue = roundedValue.toString().split(".");
const [predecimalPlaces, decimalPlaces] = splitRoundedValue;
const end = decimalPlaces.length === 0 ? "00" : decimalPlaces.length > 2 ? decimalPlaces.substring(0, 2) : `${decimalPlaces}0`;
return `${predecimalPlaces},${end}`;
} else {
return `${roundedValue},00`;
}
}
}
function calcTimeWithDuration(timeAsString, timeElement, start, duration, isFormatChange, isInMin) {
start = combineDateAndTime(start, timeAsString);
const x = new Date(start.getTime() + duration * 60000);
timeElement.val(`${x.getMinutes().toString().padStart(2, "0")}:${x.getMinutes().toString().padStart(2, "0")}`);
}
function beiDaueraenderung(idPrefix) {
const startTimeInput = $(`#${idPrefix}-start-time-input`);
const endTimeInput = $(`#${idPrefix}-end-time-input`);
const durationInput = $(`#${idPrefix}-duration-input`);
const startDateInput = $(`#${idPrefix}-start-date-input`);
const endDateInput = $(`#${idPrefix}-end-date-input`);
const isInMin = $(`#${idPrefix}-hours-minutes-dropdown-btn`).text().replaceAll(/\s/g, "") === "Minuten";
const startTimeCondition = startTimeInput.val().length > 0;
const endTimeCondition = endTimeInput.val().length > 0;
let duration = parseFloat(durationInput.val().replace(",", "."));
const durationCondition = false === isNaN(duration);
if((false === startTimeCondition && false === endTimeCondition) || false === durationCondition) {
return;
}
if(false === isInMin) {
duration *= 60;
}
let start = new Date();
let end = new Date();
if(startDateInput.length > 0) {
start = new Date(startDateInput.val());
end = new Date(start);
}
if(endDateInput.length > 0) {
end = new Date(endDateInput.val());
}
if(true === startTimeCondition) {
const startDateAndTimeCombined = combineDateAndTime(start, startTimeInput.val());
end = new Date(startDateAndTimeCombined.getTime() + duration * 60000);
endTimeInput.val(getTimeAsString(end));
endDateInput.val(getDateAsString(end));
} else {
const endDateAndTimeCombined = combineDateAndTime(end, endTimeInput.val());
start = new Date(endDateAndTimeCombined.getTime() - duration * 60000);
startTimeInput.val(getTimeAsString(start));
startDateInput.val(getDateAsString(start));
}
}
function combineDateAndTime(date, time) {
const hours = time.split(":")[0];
const minutes = time.split(":")[1];
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), hours, minutes);
}
function getTimeAsString(date) {
const hours = date.getHours().toString().padStart(2, "0");
const minutes = date.getMinutes().toString().padStart(2, "0");
return `${hours}:${minutes}`;
}
function getDateAsString(dateObject) {
const year = dateObject.getFullYear();
const date = dateObject.getDate().toString().padStart(2, "0");
const month = (dateObject.getMonth() + 1).toString().padStart(2, "0");
return `${year}-${month}-${date}`;
}
function dateToDateMonthFullYearStr(date) {
const dayOfMonth = date.getDate();
const month = date.getMonth() + 1;
const fullYear = date.getFullYear();
return `${dayOfMonth}.${month}.${fullYear}`;
}

View File

@@ -44,39 +44,43 @@ function resetCreateForm() {
function submitSingleBookingForm() {
showSpinner();
validateForm($("#singleBookingForm"), null);
}
function submitCreateForm() {
showSpinner();
validateForm($("#serviceRecordCreationForm"), null);
}
function submitEditForm() {
showSpinner();
validateForm($("#serviceRecordEditForm"), null);
validateForm($("#singleBookingForm"), "sb");
}
function submitGroupBookingEditForm() {
showSpinner();
validateForm($("#groupBookingEditingForm"), null);
validateForm($("#groupBookingEditingForm"), "gb");
}
function submitGroupBookingForm() {
showSpinner();
validateForm($("#groupBookingForm"), null);
validateForm($("#groupBookingForm"), "gb");
}
function deactivateGroupBookingForm() {
$("#betrag, #employees-button, #category-select, #leistung-select, #start-date, #end-date, #start-time, #end-time, #duration, #distance, textarea, #reset-button, #create-button, #textbausteine-button, #hours-minutes-dropdown-btn, #marker-cb").prop("disabled", true);
}
function activateGroupBookingForm() {
$("#betrag, #employees-button, #category-select, #leistung-select, #start-date, #end-date, #start-time, #end-time, #duration, #distance, textarea, #reset-button, #create-button, #textbausteine-button, #hours-minutes-dropdown-btn, #marker-cb").prop("disabled", false);
function toggleGroupBookingForm() {
const isEnabled = $("#selected-cb2sc-list").children().length > 0;
$(
"#betrag, " +
".gb-restore-btn," +
"#employees-button, " +
"#category-select, " +
"#leistung-select, " +
"#gb-start-date-input, " +
"#gb-end-date-input, " +
"#gb-start-time-input, " +
"#gb-end-time-input, " +
"#db-duration-input, " +
"#gb-distance-input, " +
"textarea, " +
"#reset-button, " +
"#create-button, " +
"#textbausteine-button, " +
"#gb-hours-minutes-dropdown-btn, " +
"#marker-cb"
).prop("disabled", isEnabled ? false : true);
}
function deleteServiceRecord(serviceRecordOid) {
@@ -159,12 +163,12 @@ function validateForm(form, prefix) {
if(isNoticeMandatory) {
if(numberOfNoticeTextareas === 0) {
var doku = $(`#${prefix}dokufeld`).val();
var doku = $(`#${prefix}-dokufeld`).val();
isValid = doku.length > 0;
} else {
for(var i = 0; i < numberOfNoticeTextareas; i++) {
var d = $(`#${prefix}doku-textarea-${i}`).val();
var d = $(`#${prefix}-doku-textarea-${i}`).val();
isValid = d.length > 0;
@@ -202,17 +206,19 @@ function validateForm(form, prefix) {
if(startAndEndDates !== null && isValid) {
var [start, end] = startAndEndDates;
if(end.isBefore(start)) {
showAlertMessageBox("Fehler", "Das Ende muss vor dem Start liegen!", null, false);
if(end.getTime() < start.getTime()) {
showAlertMessageBox("Fehler", "Der Start muss vor dem Ende liegen!", null, false);
hideSpinner();
return;
}
var [doku1, doku2, doku3, doku4, doku5] = getDokuTexte();
var [doku1, doku2, doku3, doku4, doku5] = getDokuTexte(prefix);
var startTimeInput = $(`#${prefix}start-time`);
var endTimeInput = $(`#${prefix}end-time`);
$("#srv-date").val(start.format("DD.MM.YYYY"));
$("#srv-end-date").val(end.format("DD.MM.YYYY"));
var startTimeInput = $(`#${prefix}-start-time-input`);
var endTimeInput = $(`#${prefix}-end-time-input`);
$("#srv-date").val(`${dateToDateMonthFullYearStr(start)}`);
$("#srv-end-date").val(`${dateToDateMonthFullYearStr(end)}`);
$("#srv-start").val(startTimeInput.val());
$("#srv-end").val(endTimeInput.val());
@@ -221,11 +227,11 @@ function validateForm(form, prefix) {
$("#srv-doku3").val(doku3);
$("#srv-doku4").val(doku4);
$("#srv-doku5").val(doku5);
$("#srv-distance").val($(`#${prefix}distance`).val());
$("#srv-distance").val($(`#${prefix}-distance-input`).val());
$("#srv-form-id").val(form.attr("id"));
$("#srv-marker").val($(`#${prefix}marker-cb`).is(":checked") ? "on" : "off");
$("#srv-service-description").val($(`#${prefix}leistung-select`).find(":selected").val());
$("#srv-duration").val($(`#${prefix}duration`).val());
$("#srv-marker").val($(`#${prefix}-marker-cb`).is(":checked") ? "on" : "off");
$("#srv-service-description").val($(`#${prefix}-leistung-select`).find(":selected").val());
$("#srv-duration").val($(`#${prefix}-duration-input`).val());
$("#srv-betrag").val($("#betrag").val());
showSpinner();
@@ -233,21 +239,17 @@ function validateForm(form, prefix) {
}
}
function getDokuTexte() {
function getDokuTexte(prefix) {
const noticeList = [null, null, null, null, null];
try {
const noticeList = [null, null, null, null, null];
const isMultiBooking = $("#mb-dokufeld").length > 0 || $("#mb-doku-textarea-0").length > 0;
const multiBookingPrefix = isMultiBooking ? "mb-" : "";
const hasMultipleDokufelder = $(`#${multiBookingPrefix}dokufeld`).length === 0;
const hasMultipleDokufelder = $(`#${prefix}-dokufeld-textarea`).length === 0;
let dokufeldCounter = 0;
if(hasMultipleDokufelder) {
for(let i = 0; i < 5; i++) {
const dokufeld = $(`#${multiBookingPrefix}doku-textarea-${i}`);
const dokufeld = $(`#${prefix}-doku-textarea-${i}`);
if(dokufeld.length > 0) {
noticeList[i] = dokufeld.val();
@@ -255,22 +257,22 @@ function getDokuTexte() {
}
}
} else {
noticeList[0] = $(`#${multiBookingPrefix}dokufeld`).val();
noticeList[0] = $(`#${prefix}-dokufeld-textarea`).val();
dokufeldCounter = 1;
}
let x = "";
for(let ii = 0; ii < dokufeldCounter; ii++) {
x += noticeList[ii];
for(let j = 0; j < dokufeldCounter; j++) {
x += noticeList[j];
if(ii < noticeList.length - 1) {
if(j < noticeList.length - 1) {
x += ", ";
}
}
return noticeList;
} catch (error) {
window.showErrorPopup(error);
} finally {
return noticeList;
}
}
@@ -324,91 +326,38 @@ function checkNumberInput(inputId) {
}
// Wird bei der Validierung des Formulars benutzt
// ToDo: Umbauen zu JavaScript-Date-Objekt
function getStartAndEndDate(prefix) {
if(prefix === undefined || prefix === null) {
prefix = "";
}
var startTimePicker = $(`#${prefix}start-time-picker`);
var endTimePicker = $(`#${prefix}end-time-picker`);
var startDatePicker = $(`#${prefix}start-date-picker`);
var endDatePicker = $(`#${prefix}end-date-picker`);
const startDateInput = $(`#${prefix}-start-date-input`);
const endDateInput = $(`#${prefix}-end-date-input`);
const startTimeInput = $(`#${prefix}-start-time-input`);
const endTimeInput = $(`#${prefix}-end-time-input`);
startDatePicker.datetimepicker("show");
startDatePicker.datetimepicker("hide");
const startDate = new Date(startDateInput.val());
const startTime = startTimeInput.val();
endDatePicker.datetimepicker("show");
endDatePicker.datetimepicker("hide");
var startDate = startDatePicker.datetimepicker("date");
var endDate = endDatePicker.datetimepicker("date");
const endDate = new Date(endDateInput.val());
const endTime = endTimeInput.val();
var a = startDate === undefined || startDate === null || !startDate.isValid();
var b = endDatePicker.length === 0 ? false : endDate === undefined || endDate === null || !endDate.isValid();
const isStartDateValid = false === isNaN(startDate.getTime());
const isEndDateValid = endDateInput.length ? false === isNaN(endDate.getTime()) : true;
// Bei leeren Startzeit- und Endzeitfeldern. Muss ein Dummydate zurückgeben,
// damit das Speichern ohne Angabe der Start- und Endzeit möglich ist.
if(a && $(`#${prefix}start-time`).val().length === 0 || $(`#${prefix}end-time`).val().length === 0) {
var dummyStart = startDate;
var dummyEnd = endDatePicker.length === 0 ? startDate.clone() : endDate;
dummyStart.hours(0);
dummyStart.minutes(0);
dummyStart.seconds(1);
dummyEnd.hours(0);
dummyEnd.minutes(0);
dummyEnd.seconds(1);
if (dummyEnd.isBefore(dummyStart)) {
return null;
}
return [dummyStart, dummyEnd];
if(false === isStartDateValid && startTimeInput.length === 0 || false === isEndDateValid && endTimeInput.length === 0) {
return [new Date(`${startDate}T00:00:01`), new Date(`${endDate}T00:00:01`)];
}
startTimePicker.datetimepicker("show");
startTimePicker.datetimepicker("hide");
endTimePicker.datetimepicker("show");
endTimePicker.datetimepicker("hide");
var startTime = startTimePicker.datetimepicker("date");
var endTime = endTimePicker.datetimepicker("date");
var c = startTime === undefined || startTime === null || !startTime.isValid();
var d = endTime === undefined || endTime === null || !endTime.isValid();
const isStartTimeValid = startTime.length > 0;
const isEndTimeValid = endTime.length > 0;
if(a || b || c || d) {
if (false === isStartTimeValid || false === isStartDateValid || false === isEndTimeValid || false === isEndDateValid) {
return null;
}
if(endDatePicker.length === 0 || endDate.isValid() === false) {
endDate = startDate.clone();
}
startDate = startDate.hours(startTime.hours());
startDate = startDate.minutes(startTime.minutes());
endDate = endDate.hours(endTime.hours());
endDate = endDate.minutes(endTime.minutes());
if(endDate.isBefore(startDate)) {
// Wenn das Enddatum nicht sichtbar ist und der Termin länger als den Starttag geht, muss das Enddatum neu berechnet werden
// Bei Vorhandensein der Minuten/Stunden-Auswahl ist kein (h) im Dauertext!
var dropDownbutton = $(`#${prefix}hours-minutes-dropdown-btn`);
var hasMinHourDropdown = dropDownbutton.length > 0;
var duration = $(`#${prefix}duration`).val();
var isHour = $(`#${prefix}duration`).prev().text().trim() === "Dauer (h)" || (hasMinHourDropdown && $(`#${prefix}hours-minutes-dropdown-btn`).text() === "Stunden");
var minutesToAdd = isHour ? 60 * duration : duration;
endDate = startDate.clone().add(minutesToAdd, "minutes");
return endDate.isBefore(startDate) ? null : [startDate, endDate];
}
return [startDate, endDate];
return [combineDateAndTime(startDate, startTime), combineDateAndTime(endDate, endTime)];
}

View File

@@ -9,7 +9,8 @@
<script type="text/javascript">
$(document).ready(function() {
$(".collapse").on("shown.bs.collapse", function() {
$(".collapse").on("shown.bs.collapse", function () {
logInfo3(`Das Collapsible-Element '${$(this).attr("id")}' ist geöffnet.`);
window.saveCollapsibleState($(this).attr("id"), "@Url.Action("SaveCollapsibleStatus")");
});

View File

@@ -158,7 +158,7 @@
$("#transaktionsunterschriftencontainer").addClass("d-block");
$("#transaktionsunterschriftencontainer").removeClass("d-none");
resizeCanvas("#transaktionsunterschriftencanvas", "#transaktionsunterschriften-canvas-row");
updateCanvasSize($("#transaktionsunterschriftencanvas"));
const canvas = document.getElementById("transaktionsunterschriftencanvas");

View File

@@ -24,17 +24,17 @@ else if(Model != null)
{
<script type="text/javascript">
$(document).ready(function () {
resizeCanvas("#sketch-pad", "#canvas-row");
resizeCanvas($("#sketch-pad"));
var canvas = document.getElementById("sketch-pad");
const canvas = document.getElementById("sketch-pad");
var signaturePad = new SignaturePad(canvas, { backgroundColor: "rgba(255, 255, 255, 0)" });
var saveButton = document.getElementById("save-signature-btn");
var clearButton = document.getElementById("clear-canvas-btn");
const saveButton = document.getElementById("save-signature-btn");
const clearButton = document.getElementById("clear-canvas-btn");
var saveButtonClone = saveButton.cloneNode(true);
var clearButtonClone = clearButton.cloneNode(true);
const saveButtonClone = saveButton.cloneNode(true);
const clearButtonClone = clearButton.cloneNode(true);
saveButton.parentNode.replaceChild(saveButtonClone, saveButton);
clearButton.parentNode.replaceChild(clearButtonClone, clearButton);
@@ -56,18 +56,18 @@ else if(Model != null)
try {
showSpinner();
var date = moment(new Date());
const date = moment(new Date());
var clonedCanvas = trimCanvas(cloneCanvas(document.getElementById("sketch-pad")));
const clonedCanvas = trimCanvas(cloneCanvas(document.getElementById("sketch-pad")));
var context = clonedCanvas.getContext("2d", { willReadFrequently: true });
const context = clonedCanvas.getContext("2d", { willReadFrequently: true });
context.globalCompositeOperation = "destination-over";
context.fillStyle = "white";
context.fillRect(0, 0, clonedCanvas.width, clonedCanvas.height);
var dataUrl = clonedCanvas.toDataURL("image/png");
const dataUrl = clonedCanvas.toDataURL("image/png");
var formattedDate = date.format("DD.MM.YYYY HH:mm:ss");
const formattedDate = date.format("DD.MM.YYYY HH:mm:ss");
$.post("@Url.Action("SaveSignature")", {base64Image: dataUrl, creationDate: formattedDate}).done(function (response) {
hideSpinner();
@@ -86,7 +86,7 @@ else if(Model != null)
}
});
} catch (error) {
showErrorPopup(error);
window.showErrorPopup(error);
}
}
@@ -94,12 +94,12 @@ else if(Model != null)
try {
signaturePad.clear();
} catch(error) {
showErrorPopup(error);
window.showErrorPopup(error);
}
}
$(window).resize(function() {
resizeCanvas("#sketch-pad", "#canvas-row");
updateCanvasSize($("#sketch-pad"));
});
</script>
<div class="container m-3 mx-auto">

View File

@@ -8,65 +8,77 @@
{
<text>
<script type="text/javascript">
$("#second-logout-form").submit();
$("#second-logout-form").submit();
</script>
</text>
}
}
<script type="text/javascript">
function addScCbRelsToGroupBooking() {
var selectedGroups = [];
var selectedSupportConcepts = [];
function toggleForm() {
const checkedCheckboxes = $(".cb2sc-input:checkbox:checked");
$("#group-booking-supportconcepts input:checked").each(function () {
selectedSupportConcepts.push($(this).attr("value"));
});
$("#group-booking-groups input:checked").each(function () {
selectedGroups.push($(this).attr("value"));
});
$("#group-booking-sc-cb-rel-tab-content").load("@Url.Action("AddScCbRelsToGroupBooking")", {relOids: selectedSupportConcepts, groupOids: selectedGroups}, function() {
$("#groupbooking-selection-container").load("@Url.Action("ReloadGroupBookingForm")", function () {
const checkedCheckboxes = $(".cb2sc-input:checkbox:checked");
$("#employees-button, #category-select, #leistung-select, " +
"#start-date, #end-date, #start-time, #end-time, #duration, " +
"#distance, textarea, #reset-button, #create-button, #textbausteine-button, #hours-minutes-dropdown-btn, #marker-cb, #betrag")
.prop("disabled", (checkedCheckboxes.length > 0 ? false : true));
$("#goals-tree").load("@Url.Action("ReloadGoals")", function () {
$("#goal-ratings-container").load("@Url.Action("ReloadGoalRatings")", function() {
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
});
});
});
});
$(
"#employees-button, " +
"#category-select, " +
"#leistung-select, " +
"#gb-start-date-input, " +
"#gb-end-date-input, " +
"#gb-start-time-input, " +
"#gb-end-time-input, " +
"#gb-duration-input, " +
"#gb-distance-input, " +
"textarea, " +
"#reset-button, " +
"#create-button, " +
"#textbausteine-button, " +
"#gb-hours-minutes-dropdown-btn, " +
"#marker-cb")
.prop("disabled", (checkedCheckboxes.length > 0 ? false : true));
}
function removeSupportConceptCostBearerRel(relOid) {
$(`#cb2sc-checkbox-${relOid}`).prop("checked", false);
function addScCbRelsToGroupBooking() {
var selectedGroups = [];
var selectedSupportConcepts = [];
$("#groupbooking-selection-container").load("@Url.Action("RemoveSupportConceptCostbearerRel")", {relOid: relOid}
, function () {
$("#goals-tree").load("@Url.Action("ReloadGoals")"
, function () {
$("#goal-ratings-container").load("@Url.Action("ReloadGoalRatings")", function() {
const checkedCheckboxes = $(".cb2sc-input:checkbox:checked");
$("#group-booking-supportconcepts input:checked").each(function () {
selectedSupportConcepts.push($(this).attr("value"));
});
$("#employees-button, #category-select, #leistung-select, " +
"#start-date, #end-date, #start-time, #end-time, #duration, " +
"#distance, textarea, #reset-button, #create-button, #textbausteine-button, #hours-minutes-dropdown-btn, #marker-cb")
.prop("disabled", (checkedCheckboxes.length > 0 ? false : true));
$("#group-booking-groups input:checked").each(function () {
selectedGroups.push($(this).attr("value"));
});
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
});
}
);
}
);
}
$("#group-booking-sc-cb-rel-tab-content").load("@Url.Action("AddScCbRelsToGroupBooking")", {relOids: selectedSupportConcepts, groupOids: selectedGroups}, function() {
$("#groupbooking-selection-container").load("@Url.Action("ReloadGroupBookingForm")", function () {
toggleForm();
$("#goals-tree").load("@Url.Action("ReloadGoals")", function () {
$("#goal-ratings-container").load("@Url.Action("ReloadGoalRatings")", function() {
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
});
});
});
});
}
function removeSupportConceptCostBearerRel(relOid) {
$(`#cb2sc-checkbox-${relOid}`).prop("checked", false);
$("#groupbooking-selection-container").load("@Url.Action("RemoveSupportConceptCostbearerRel")", {relOid: relOid}
, function () {
$("#goals-tree").load("@Url.Action("ReloadGoals")"
, function () {
$("#goal-ratings-container").load("@Url.Action("ReloadGoalRatings")", function() {
toggleForm();
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
});
}
);
}
);
}
</script>
@if(Model != null)
@@ -75,8 +87,8 @@
using(Html.BeginForm("CreateOrUpdateGroupBooking", "Main", FormMethod.Post, new { id = "groupBookingForm" }))
{
var startDate = Model.SelectedServiceRecord?.Start?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
var endDate = Model.SelectedServiceRecord?.End?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
var startDate = Model.SelectedServiceRecord?.Start?.ToString("yyyy-MM-dd") ?? DateTime.Today.ToString("yyyy-MM-dd");
var endDate = Model.SelectedServiceRecord?.End?.ToString("yyyy-MM-dd") ?? DateTime.Today.ToString("yyyy-MM-dd");
var distance = Model.SelectedServiceRecord?.DistanceInMeter?.ToString() ?? string.Empty;
@@ -121,7 +133,7 @@
}
@* ----- Betrag ----- *@
@if(Model.ShowBetrag)
@if(AbstractModel.ShowBetrag)
{
var betrag = string.Empty;
if(Model.SelectedServiceRecord?.Betrag != null && Model.SelectedServiceRecord.Betrag.Value > 0)
@@ -152,109 +164,75 @@
<hr class="py-0 mt-2 mb-0" />
@* Start- und Enddatum *@
<div class="form-row">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="start-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Startdatum
</div>
</div>
<input type="text" autocomplete="on" 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>
@{
var columnWidth = Model.IsEndDateVisible ? "col-md-6" : "col";
}
@if(Model.IsEndDateVisible)
{
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="end-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Enddatum
</div>
</div>
<input type="text" autocomplete="on" 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="@columnWidth mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
Startdatum
</span>
</div>
<input class="form-control" type="date" name="Datum" id="gb-start-date-input" onchange="calcDuration('gb', false, true, false)" value="@startDate" />
</div>
</div>
@if(Model.IsEndDateVisible)
{
<div class="col-md-6 mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
Enddatum
</span>
</div>
<input class="form-control" type="date" name="Enddatum" id="gb-end-date-input" onchange="calcDuration('gb', false, false, true)" value="@endDate"/>
</div>
</div>
}
</div>
@* Von und Bis *@
<div class="form-row">
@{
var startTimeValue = Model.StartTimeToEdit;
var endTimeValue = Model.EndTimeToEdit;
var divisor = Model.SelectedDurationUnit == "Stunden" ? 60 : 1;
var durationValue = string.Empty;
@{
var startTimeValue = Model.StartTimeToEdit;
var endTimeValue = Model.EndTimeToEdit;
var divisor = Model.SelectedDurationUnit == "Stunden" ? 60 : 1;
var durationValue = string.Empty;
if(!(Model.SelectedServiceRecord is null))
{
durationValue = (Model.SelectedServiceRecord?.RoundedDuration / divisor).ToString();
}
if(!(Model.SelectedServiceRecord is null))
{
durationValue = (Model.SelectedServiceRecord?.RoundedDuration / divisor).ToString();
}
var afterValidationState = TempData[TempDataConstants.AfterValidationStateKey];
var afterValidationState = TempData[TempDataConstants.AfterValidationStateKey];
if(Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode && afterValidationState is bool isAfterValidation && isAfterValidation == false)
{
startTimeValue = Model.NewStartTime;
endTimeValue = Model.NewEndTime;
if(Model.NewDuration.HasValue)
{
durationValue = (Model.NewDuration / divisor).ToString();
}
}
}
if(Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode && afterValidationState is bool isAfterValidation && isAfterValidation == false)
{
startTimeValue = Model.NewStartTime;
endTimeValue = Model.NewEndTime;
if(Model.NewDuration.HasValue)
{
durationValue = (Model.NewDuration / divisor).ToString();
}
}
}
@* Von *@
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="start-time-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text sm-prepend-input-group-text">
Von
</div>
</div>
<input type="text" autocomplete="on" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@startTimeValue" />
<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>
@* Bis *@
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="end-time-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text sm-prepend-input-group-text">
Bis
</div>
</div>
<input type="text" autocomplete="on" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@endTimeValue" />
<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 class="col mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text prepend-input-group-text">
Von
</span>
</div>
<input class="form-control" type="time" name="Start" id="gb-start-time-input" onchange="calcDuration('gb', false, true, false)" value="@startTimeValue" />
<span class="input-group-text rounded-0 border-left-0 border-right-0">
Bis
</span>
<input class="form-control" type="time" name="Ende" id="gb-end-time-input" onchange="calcDuration('gb', false, false, true)" value="@endTimeValue" />
</div>
</div>
</div>
@@ -271,11 +249,11 @@
@labelText
</div>
</div>
<input type="text" autocomplete="on" class="form-control" id="duration" name="Dauer" onchange="onDurationChange('start-time', 'end-time', 'start-date', 'end-date', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker')" value="@durationValue">
<input type="text" autocomplete="on" class="form-control" id="gb-duration-input" name="Dauer" onchange="beiDaueraenderung('gb')" value="@durationValue">
@if(Model.IsZeiterfassungInStdMin)
{
<div class="input-group-append">
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle" type="button" data-toggle="dropdown">
<button id="gb-hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle" type="button" data-toggle="dropdown">
@Model.SelectedDurationUnit
</button>
<div class="dropdown-menu w-100">
@@ -290,7 +268,7 @@
</div>
@* Gefahrene Kilometer *@
@if(Model.ShowDistanceField)
@if(AbstractModel.ShowDistanceField)
{
<div class="form-row">
<div class="col-md">
@@ -299,7 +277,7 @@
<div class="input-group-prepend">
<div class="input-group-text">Gefahrene Kilometer</div>
</div>
<input type="text" autocomplete="on" class="form-control" id="distance" name="Distanz" onchange="validateDistanceInput()" value="@distance">
<input type="text" autocomplete="on" class="form-control" id="gb-distance-input" name="Distanz" onchange="validateDistanceInput()" value="@distance">
</div>
</div>
</div>
@@ -322,8 +300,11 @@
@if(Model.NumberOfDokuTypes == 0)
{
<div class="form-group">
<label for="dokufeld">Dokumentation</label>
<textarea class="form-control" autocomplete="on" name="Dokumentation6" id="dokufeld">@notice0</textarea>
<label for="gb-dokufeld-textarea">Dokumentation</label>
<button type="button" class="btn btn-outline-bewo-dev btn-sm bg-restore-btn" onclick="restoreField('gb-dokufeld-textarea')">
<i class="fas fa-recycle"></i>
</button>
<textarea class="form-control" autocomplete="on" name="Dokumentation6" id="gb-dokufeld-textarea">@notice0</textarea>
</div>
}
else
@@ -334,8 +315,11 @@
var currentDokuType = Model.Dokutypes[i];
<li class="nav-item">
<a href="#doku_@i" id="doku_@i-tab" data-toggle="tab" role="tab" class="nav-link@(i == 0 ? " active" : string.Empty)">
<a href="#gb-doku_@i" id="gb-doku_@i-tab" data-toggle="tab" role="tab" class="nav-link@(i == 0 ? " active" : string.Empty)">
@currentDokuType.DisplayName
<button type="button" class="btn btn-outline-bewo-dev btn-sm gb-restore-btn" onclick="restoreField('gb-doku-textarea-@i')">
<i class="fas fa-recycle"></i>
</button>
</a>
</li>
}
@@ -345,8 +329,8 @@
{
var textareaName = i + 1 < 1 ? "Dokumentation" : "Dokumentation" + (i + 1);
<div class="tab-pane show@(i == 0 ? " active" : string.Empty)" id="doku_@i" role="tabpanel">
<textarea class="form-control doku-form-control" autocomplete="on" id="doku-textarea-@i" name="@textareaName">@noticeList[i]</textarea>
<div class="tab-pane show@(i == 0 ? " active" : string.Empty)" id="gb-doku_@i" role="tabpanel">
<textarea class="form-control doku-form-control" autocomplete="on" id="gb-doku-textarea-@i" name="@textareaName">@noticeList[i]</textarea>
</div>
}
</div>

View File

@@ -13,13 +13,15 @@
}
<script type="text/javascript">
$(document).ready(function () {
$("#hours-minutes-dropdown-btn").on("click", function() {
$("#hours-minutes-dropdown-btn").data("text", $("#hours-minutes-dropdown-btn").text().replaceAll(/\s/g, ""));
$(document).ready(function() {
const groupBookingHoursMinutesDropdownButton = $("#gb-hours-minutes-dropdown-btn");
groupBookingHoursMinutesDropdownButton.on("click", function() {
groupBookingHoursMinutesDropdownButton.data("text", groupBookingHoursMinutesDropdownButton.text().replaceAll(/\s/g, ""));
});
$(".hours-minutes-link").on("click", function () {
const previousText = $("#hours-minutes-dropdown-btn").data("text");
const previousText = groupBookingHoursMinutesDropdownButton.data("text");
const currentText = $(this).text().replaceAll(/\s/g, "");
if(previousText === currentText) {
@@ -27,15 +29,17 @@
}
const buttonText = $(this).text();
$("#hours-minutes-dropdown-btn").text(buttonText);
groupBookingHoursMinutesDropdownButton.text(buttonText);
window.setInputFilter('duration', 'distance', 'hours-minutes-dropdown-btn');
window.setInputFilter('gb-duration-input', 'distance', 'gb-hours-minutes-dropdown-btn');
$.get('@Url.Action("ToggleDurationUnit")', { isInHoursMode: buttonText === "Stunden" });
calculateDuration(true, 'start-time', 'end-time', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker', false, false);
calcDuration("gb", true, false, false);
});
toggleGroupBookingForm();
window.calcPrependWidth();
});

View File

@@ -1,4 +1,5 @@
@using BeWoPlanerMobil.Models;
@using BeWoPlanerMobil.Service
@using BeWoPlanerMobil.Util;
@model MainModel
@@ -53,21 +54,21 @@
try {
(new MoKPasswordSecurity("pw-strength-feedback")).validatePassword($("#new-password").val());
} catch (error) {
showErrorPopup(error);
window.showErrorPopup(error);
}
}
function submitChangePasswordForm() {
try {
showSpinner();
var form = $('#change-password-form');
const form = $('#change-password-form');
var isValid = true;
$.each($(".pw-ch-in-container"),
function (index, item) {
var input = $(item).find("input");
var feedback = $(item).find(".pw-chng-inv-fdb");
const input = $(item).find("input");
const feedback = $(item).find(".pw-chng-inv-fdb");
if (isEmptyOrSpaces(input.val())) {
feedback.addClass("d-block");
@@ -80,17 +81,17 @@
feedback.addClass("was-validated");
});
if (true === isValid) {
if(true === isValid) {
form.submit();
} else {
hideSpinner();
}
} catch (error) {
showErrorPopup(error);
window.showErrorPopup(error);
}
}
function getIsZeiterfassungseinheitInMinutes() {
function getIsZeiterfassungseinheitInMinutes() {
return "@Model.EinheitZeiterfassung" === "0";
}
@@ -152,6 +153,69 @@
}
});
function restoreInputValues() {
const beWoStorage = getBeWoStorage();
for(let i = 0; i < beWoStorage.inputList.length; i++) {
const item = beWoStorage.inputList[i];
$(`#${item.inputId}`).val(item.inputValue);
}
}
function getLocalStorageKey() {
return "@Model.LocalStorageKey";
}
function getBeWoStorage() {
const localStorageKey = getLocalStorageKey();
const unparsedLocalStorageJson = localStorage.getItem(localStorageKey);
let beWoStorage = new LocalBeWoStorage(localStorageKey, []);
if(unparsedLocalStorageJson === null || unparsedLocalStorageJson === undefined || unparsedLocalStorageJson.length === 0) {
localStorage.setItem(localStorageKey, JSON.stringify(beWoStorage));
} else {
const parsedJson = JSON.parse(unparsedLocalStorageJson);
beWoStorage = new LocalBeWoStorage(localStorageKey, parsedJson.inputList);
}
return beWoStorage;
}
window.addEventListener("load", function() {
$("textarea").on("change", function() {
const item = $(this);
const id = item.attr("id");
const type = item.prop("type");
const value = type === "checkbox" ? item.is(":checked").toString() : item.val();
if(value === undefined || value === null || value.length === 0) {
return;
}
const name = item.prop("name");
const beWoStorage = getBeWoStorage();
beWoStorage.addInputValue(id, name, type, value, new Date());
});
});
function restoreField(id) {
const beWoStorage = getBeWoStorage();
const inputObj = beWoStorage.getItemById(id);
if(inputObj === undefined || inputObj === null) {
return;
}
$(`#${id}`).val(inputObj.inputValue);
}
$(document).ready(function() {
try {
$(".collapse").on("shown.bs.collapse", function () {
@@ -179,17 +243,53 @@
$("#single-booking-employee-container").find(".dropdown-toggle").prop("disabled", (isSupportConceptSelected ? false : true));
$("#employeesDropDown, #category-select, #leistung-select, " +
"#start-date, #end-date, #start-time, #end-time, #duration, " +
"#distance, #textbausteine-button, #goals-button, textarea, #reset-button, " +
"#create-button, #statistics-button, #timeFrameSelect, #hours-minutes-dropdown-btn, #marker-cb, #betrag").prop("disabled", (isSupportConceptSelected ? false : true));
$(
"#employeesDropDown, " +
"#category-select, " +
"#leistung-select, " +
"#sb-start-date-input, #sb-end-date-input, #sb-start-time-input, #sb-end-time-input, " +
"#sb-duration-input, #sb-hours-minutes-dropdown-btn, #sb-distance-input, " +
"#gb-start-date-input, #gb-end-date-input, #gb-start-time-input, #gb-end-time-input, " +
"#gb-duration-input, #gb-hours-minutes-dropdown-btn, #gb-distance-input, " +
"#mb-start-date-input, #mb-end-date-input, #mb-start-time-input, #mb-end-time-input, " +
"#mb-duration-input, #mb-hours-minutes-dropdown-btn, #mb-distance-input," +
".sb-restore-btn, .gb-restore-btn, .mb-restore-btn" +
"#textbausteine-button, " +
"#goals-button, " +
"textarea, " +
"#reset-button, " +
"#create-button, " +
"#statistics-button, " +
"#timeFrameSelect, " +
"#marker-cb, " +
"#betrag"
).prop("disabled", (isSupportConceptSelected ? false : true));
if("@Model.IsInGroupBookingMode".toLowerCase() === "true") {
const hasSelectedSupportConcepts = "@Model.SelectedConceptCostBearerRelations.Any()".toLowerCase() === "true";
$("#employees-button, #category-select, #leistung-select, " +
"#start-date, #end-date, #start-time, #end-time, #duration, " +
"#distance, textarea, #reset-button, #create-button, #textbausteine-button, #hours-minutes-dropdown-btn, #marker-cb, #betrag").prop("disabled", (hasSelectedSupportConcepts ? false : true));
$(
"#employees-button, " +
"#category-select, " +
"#leistung-select, " +
"#gb-start-date-input, " +
"#gb-end-date-input, " +
"#gb-start-time-input, " +
"#gb-end-time-input, " +
"#gb-duration-input, " +
"#distance, " +
"textarea, " +
"#reset-button, " +
"#create-button, " +
"#textbausteine-button, " +
"#gb-hours-minutes-dropdown-btn, " +
"#marker-cb, " +
"#betrag," +
".gb-restore-btn"
).prop("disabled", (hasSelectedSupportConcepts ? false : true));
}
$("#fehlerdetail-textarea").prop("disabled", false);
@@ -200,8 +300,6 @@
window.toggleMultiBookingForm(isMultiBookingFormDisabled);
}
initializeTimeInputs();
initializeSignatureImagePopup();
@if(TempData[TempDataConstants.ShowPwChPopupKey] is string passwordWarning && !string.IsNullOrEmpty(passwordWarning))
@@ -211,13 +309,6 @@
</text>
}
@if (Model != null && Model.IsInEditingMode)
{
<text>
$("#start-time-picker").trigger("change");
</text>
}
setInputFilter('duration', 'distance', 'hours-minutes-dropdown-btn');
@if(Model.IsInGroupBookingMode)
@@ -247,109 +338,6 @@
}
});
function initializeTimeInputs() {
try {
var previousStartTime = "";
$("#start-time-picker").on("change.datetimepicker",
() => {
// Von
var startTimeValue = $("#start-time").val();
if(previousStartTime.length === 5 && startTimeValue.length === 0) {
$("#duration").val("");
return;
}
if(startTimeValue.length === 5 || startTimeValue.length === 0) {
previousStartTime = startTimeValue;
}
calculateDuration(false, 'start-time', 'end-time', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker', true, false);
}
);
var previousEndTime = "";
$("#end-time-picker").on("change.datetimepicker",
() => {
// Bis
var endTimeValue = $("#end-time").val();
if(previousEndTime.length === 5 && endTimeValue.length === 0) {
$("#duration").val("");
return;
}
if(endTimeValue.length === 5 || endTimeValue.length === 0) {
previousEndTime = endTimeValue;
}
calculateDuration(false, 'start-time', 'end-time', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker', false, true);
}
);
$("#start-date-picker").on("change.datetimepicker", () => {
calculateDuration(false, 'start-time', 'end-time', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker', true, false);
});
if($("#end-time-picker").length !== 0) {
$("#end-date-picker").on("change.datetimepicker",
() => {
calculateDuration(false, 'start-time', 'end-time', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker', false, true);
});
}
var previousMultiBookingStartTime = "";
$("#mb-start-time-picker").on("change.datetimepicker",
() => {
// Von
var startTimeValue = $("#mb-start-time").val();
if (previousMultiBookingStartTime.length === 5 && startTimeValue.length === 0) {
$("#mb-duration").val("");
return;
}
if (startTimeValue.length === 5 || startTimeValue.length === 0) {
previousMultiBookingStartTime = startTimeValue;
}
calculateDuration(false, 'mb-start-time', 'mb-end-time', 'mb-duration', 'mb-hours-minutes-dropdown-btn', 'mb-start-date-picker', 'mb-end-date-picker', true, false);
}
);
var previousMultiBookingEndTime = "";
$("#mb-end-time-picker").on("change.datetimepicker",
() => {
// Bis
var endTimeValue = $("#mb-end-time").val();
if (previousMultiBookingEndTime.length === 5 && endTimeValue.length === 0) {
$("#mb-duration").val("");
return;
}
if (endTimeValue.length === 5 || endTimeValue.length === 0) {
previousMultiBookingEndTime = endTimeValue;
}
calculateDuration(false, 'mb-start-time', 'mb-end-time', 'mb-duration', 'mb-hours-minutes-dropdown-btn', 'mb-start-date-picker', 'mb-end-date-picker', false, true);
}
);
$("#mb-start-date-picker").on("change.datetimepicker",
() => {
calculateDuration(false, 'mb-start-time', 'mb-end-time', 'mb-duration', 'mb-hours-minutes-dropdown-btn', 'mb-start-date-picker', 'mb-end-date-picker', true, false);
});
if($("#mb-end-time-picker").length !== 0) {
$("#mb-end-date-picker").on("change.datetimepicker",
() => {
calculateDuration(false, 'mb-start-time', 'mb-end-time', 'mb-duration', 'mb-hours-minutes-dropdown-btn', 'mb-start-date-picker', 'mb-end-date-picker', false, true);
});
}
} catch (error) {
window.showErrorPopup(error);
}
}
function initializeSignatureImagePopup() {
$("#signature-img-popup").on("hidden.bs.modal",
function() {
@@ -359,23 +347,25 @@
);
}
function setInputFilter(durationId, distanceId, hoursMinutesDropdownBtnId) {
$(`#${durationId}`).inputFilter(function (value) {
var result = /^\d*$/;
const dropdownButton = $(`#${hoursMinutesDropdownBtnId}`);
function setInputFilter() {
$(`#sb-duration-input, #gb-duration-input, #mb-duration-input`).inputFilter(function(value, id) {
var result = /^\d*$/;
if(dropdownButton.length && dropdownButton.text() === "Stunden" || getIsZeiterfassungseinheitInMinutes() === false) {
const prefix = id.split("-")[0];
const dropdownButton = $(`#${prefix}-hours-minutes-dropdown-btn`);
if(dropdownButton.length && dropdownButton.text().trim() === "Stunden") {
result = /^\d*[.,]?\d*$/;
}
return result.test(value);
});
$(`#${distanceId}`).inputFilter(function(value) {
$(`#sb-distance-input, #gb-distance-input, #mb-distance-input`).inputFilter(function(value, id) {
return /^\d*[.,]?\d*$/.test(value);
});
$(`#betrag`).inputFilter(function (value) {
$(`#sb-betrag-input, #gb-betrag-input, #mb-betrag-input`).inputFilter(function(value, id) {
return /^\d*([.,]?\d{0,2})?$/.test(value);
});
}
@@ -383,7 +373,7 @@
(function($) {
$.fn.inputFilter = function(inputFilter) {
return this.on("input keydown keyup mouseup select mousedown contextmenu drop", function() {
if(inputFilter(this.value)) {
if(inputFilter(this.value, this.id)) {
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
@@ -398,7 +388,7 @@
}(jQuery));
$(window).resize(function() {
resizeCanvas("#sketch-pad", "#canvas-row");
updateCanvasSize($("#sketch-pad"));
});
function getSetServiceRecordEmployeeUrl() {

View File

@@ -7,57 +7,57 @@
{
<text>
<script type="text/javascript">
$("#second-logout-form").submit();
$("#second-logout-form").submit();
</script>
</text>
}
}
<script type="text/javascript">
function addScCbRelsToMultiBooking() {
var selectedGroups = [];
var selectedSupportConcepts = [];
function addScCbRelsToMultiBooking() {
var selectedGroups = [];
var selectedSupportConcepts = [];
$("#multi-booking-supportconcepts input:checked").each(function () {
selectedSupportConcepts.push($(this).attr("value"));
});
$("#multi-booking-supportconcepts input:checked").each(function () {
selectedSupportConcepts.push($(this).attr("value"));
});
$("#multi-booking-groups input:checked").each(function () {
selectedGroups.push($(this).attr("value"));
});
$("#multi-booking-groups input:checked").each(function () {
selectedGroups.push($(this).attr("value"));
});
$("#multi-booking-sc-cb-rel-tab-content").load("@Url.Action("AddScCbRelsToMultiBooking")", {relOids: selectedSupportConcepts, groupOids: selectedGroups}, function() {
$("#multibooking-selection-container").load("@Url.Action("ReloadMultiBookingForm")", function () {
window.toggleMultiBookingForm($(".mb-cb2sc-input:checkbox:checked").length > 0 ? false : true);
$("#multi-booking-sc-cb-rel-tab-content").load("@Url.Action("AddScCbRelsToMultiBooking")", {relOids: selectedSupportConcepts, groupOids: selectedGroups}, function() {
$("#multibooking-selection-container").load("@Url.Action("ReloadMultiBookingForm")", function () {
window.toggleMultiBookingForm($(".mb-cb2sc-input:checkbox:checked").length > 0 ? false : true);
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
});
});
}
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
});
});
}
function removeSupportConceptCostBearerRel(relOid) {
$(`#mb-cb2sc-checkbox-${relOid}`).prop("checked", false);
function removeSupportConceptCostBearerRel(relOid) {
$(`#mb-cb2sc-checkbox-${relOid}`).prop("checked", false);
$("#multibooking-selection-container").load("@Url.Action("RemoveSupportConceptCostbearerRelFromMultiBooking")", {relOid: relOid}
, function () {
$("#goals-tree").load("@Url.Action("ReloadGoals")"
, function () {
window.toggleMultiBookingForm($(".mb-cb2sc-input:checkbox:checked").length > 0 ? false : true);
$("#multibooking-selection-container").load("@Url.Action("RemoveSupportConceptCostbearerRelFromMultiBooking")", {relOid: relOid}
, function () {
$("#goals-tree").load("@Url.Action("ReloadGoals")"
, function () {
window.toggleMultiBookingForm($(".mb-cb2sc-input:checkbox:checked").length > 0 ? false : true);
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
}
);
}
);
}
$("#tree").load("@Url.Action("LoadUpToDateTextModules")");
}
);
}
);
}
</script>
@if(Model != null)
{
using(Html.BeginForm("CreateMultiBooking", "Main", FormMethod.Post, new { id = "multiBookingForm" }))
{
var startDate = Model.SelectedServiceRecord?.Start?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
var endDate = Model.SelectedServiceRecord?.End?.ToShortDateString() ?? DateTime.Today.ToShortDateString();
var startDate = Model.SelectedServiceRecord?.Start?.ToShortDateString() ?? DateTime.Today.ToString("yyyy-MM-dd");
var endDate = Model.SelectedServiceRecord?.End?.ToShortDateString() ?? DateTime.Today.ToString("yyyy-MM-dd");
var distance = Model.SelectedServiceRecord?.DistanceInMeter?.ToString() ?? string.Empty;
@@ -91,7 +91,7 @@
}
@* ----- Betrag ----- *@
@if(Model.ShowBetrag)
@if(AbstractModel.ShowBetrag)
{
<div class="form-row mt-2">
<div class="col-md">
@@ -116,45 +116,34 @@
<hr class="py-0 mt-2 mb-0" />
@* Start- und Enddatum *@
<div class="form-row">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="mb-start-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Startdatum
</div>
</div>
<input type="text" autocomplete="on" id="mb-start-date" name="Datum" class="form-control datetimepicker-input" data-target="#mb-start-date-picker" data-toggle="datetimepicker" value="@startDate" />
<div class="input-group-append" data-target="#mb-start-date-picker" data-toggle="datetimepicker">
<div class="input-group-text">
<i class="fas fa-calendar-alt"></i>
</div>
</div>
</div>
</div>
</div>
@{
var columnWidth = Model.IsEndDateVisible ? "col-md-6" : "col";
}
@if(Model.IsEndDateVisible)
{
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="mb-end-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Enddatum
</div>
</div>
<input type="text" autocomplete="on" id="mb-end-date" name="Enddatum" class="form-control datetimepicker-input" data-target="#mb-end-date-picker" data-toggle="datetimepicker" value="@endDate" />
<div class="input-group-append" data-target="#mb-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="form-row">
<div class="@columnWidth mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
Startdatum
</span>
</div>
<input class="form-control" type="date" name="Datum" id="mb-start-date-input" onchange="calcDuration('mb', false, true, false)" value="@startDate" />
</div>
</div>
@if(Model.IsEndDateVisible)
{
<div class="col-md-6 mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
Enddatum
</span>
</div>
<input class="form-control" type="date" name="Enddatum" id="mb-end-date-input" onchange="calcDuration('mb', false, false, true)" value="@endDate" />
</div>
</div>
}
</div>
@* Start- und Endzeit *@
@@ -167,7 +156,7 @@
var durationValue = string.Empty;
if(!(Model.SelectedServiceRecord is null))
if(Model.SelectedServiceRecord != null)
{
durationValue = (Model.SelectedServiceRecord?.RoundedDuration / divisor).ToString();
}
@@ -184,39 +173,19 @@
}
}
}
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="mb-start-time-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text sm-prepend-input-group-text">
Von
</div>
</div>
<input type="text" autocomplete="on" id="mb-start-time" name="Start" class="form-control datetimepicker-input" data-target="#mb-start-time-picker" value="@startTimeValue" />
<div class="input-group-append" data-target="#mb-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 my-0">
<div class="input-group date mt-2" id="mb-end-time-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text sm-prepend-input-group-text">
Bis
</div>
</div>
<input type="text" autocomplete="on" id="mb-end-time" name="Ende" class="form-control datetimepicker-input" data-target="#mb-end-time-picker" value="@endTimeValue" />
<div class="input-group-append" data-target="#mb-end-time-picker" data-toggle="datetimepicker">
<div class="input-group-text">
<i class="fas fa-clock"></i>
</div>
</div>
</div>
</div>
<div class="col mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
Von
</span>
</div>
<input class="form-control" type="time" name="Start" id="mb-start-time-input" onchange="calcDuration('mb', false, true, false)" value="@startTimeValue" />
<span class="input-group-text rounded-0 border-left-0 border-right-0">
Bis
</span>
<input class="form-control" type="time" name="Ende" id="mb-end-time-input" onchange="calcDuration('mb', false, false, true)" value="@endTimeValue" />
</div>
</div>
</div>
@@ -233,7 +202,7 @@
@labelText
</div>
</div>
<input type="text" autocomplete="on" class="form-control" id="mb-duration" name="Dauer" onchange="onDurationChange('mb-start-time', 'mb-end-time', 'mb-start-date', 'mb-end-date', 'mb-duration', 'mb-hours-minutes-dropdown-btn', 'mb-start-date-picker', 'mb-end-date-picker')" value="@durationValue">
<input type="text" autocomplete="on" class="form-control" id="mb-duration-input" name="Dauer" onchange="beiDaueraenderung('mb')" value="@durationValue">
@if(Model.IsZeiterfassungInStdMin)
{
<div class="input-group-append">
@@ -252,7 +221,7 @@
</div>
@* Gefahrene Kilometer *@
@if(Model.ShowDistanceField)
@if(AbstractModel.ShowDistanceField)
{
<div class="form-row">
<div class="col-md">
@@ -263,7 +232,7 @@
Gefahrene Kilometer
</div>
</div>
<input type="text" autocomplete="on" class="form-control" id="mb-distance" name="Distanz" onchange="validateDistanceInput()" value="@distance">
<input type="text" autocomplete="on" class="form-control" id="mb-distance-input" name="Distanz" onchange="validateDistanceInput()" value="@distance">
</div>
</div>
</div>
@@ -282,12 +251,15 @@
@* Dokumentationsfelder *@
<div class="form-row">
<div class="col-md">
<div class="col-md mt-2">
@if(Model.NumberOfDokuTypes == 0)
{
<div class="form-group mt-2">
<label for="mb-dokufeld">Dokumentation</label>
<textarea class="form-control" autocomplete="on" name="Dokumentation6" id="mb-dokufeld">@notice0</textarea>
<label for="mb-dokufeld">Dokumentation</label>
<button type="button" class="btn btn-outline-bewo-dev btn-sm mb-restore-btn" onclick="restoreField('mb-dokufeld-textarea')">
<i class="fas fa-recycle"></i>
</button>
<textarea class="form-control" autocomplete="on" name="Dokumentation6" id="mb-dokufeld-textarea">@notice0</textarea>
</div>
}
else
@@ -300,6 +272,9 @@
<li class="nav-item">
<a href="#mb-doku_@i" id="mb-doku_@i-tab" data-toggle="tab" role="tab" class="nav-link@(i == 0 ? " active" : string.Empty)">
@currentDokuType.DisplayName
<button type="button" class="btn btn-outline-bewo-dev btn-sm mb-restore-btn" onclick="restoreField('mb-doku-textarea-@i')">
<i class="fas fa-recycle"></i>
</button>
</a>
</li>
}

View File

@@ -31,11 +31,11 @@
const buttonText = $(this).text();
$("#mb-hours-minutes-dropdown-btn").text(buttonText);
window.setInputFilter('mb-duration', 'mb-distance', 'mb-hours-minutes-dropdown-btn');
window.setInputFilter('mb-duration-input', 'mb-distance-input', 'mb-hours-minutes-dropdown-btn');
$.get('@Url.Action("ToggleDurationUnit")', { isInHoursMode: buttonText === "Stunden" });
calculateDuration(true, 'mb-start-time', 'mb-end-time', 'mb-duration', 'mb-hours-minutes-dropdown-btn', 'mb-start-date-picker', 'mb-end-date-picker', false, false);
calcDuration("mb", true, false, false);
});
});

View File

@@ -49,8 +49,7 @@
{
<li class="list-group-item">
@{
long groupOid;
var wasSuccessful = long.TryParse(group.Value, out groupOid);
var wasSuccessful = long.TryParse(group.Value, out var groupOid);
var shouldBeChecked = wasSuccessful ? Model.MultiBookingSelectedGroupOfPeopleOids.Contains(groupOid) : wasSuccessful;

View File

@@ -341,7 +341,7 @@
</tr>
@* Gefahrene Kilometer *@
@if(Model.ShowDistanceField && serviceRecord.DistanceInMeterDecimal != null && serviceRecord.DistanceInMeterDecimal.Value > 0)
@if(AbstractModel.ShowDistanceField && serviceRecord.DistanceInMeterDecimal != null && serviceRecord.DistanceInMeterDecimal.Value > 0)
{
<tr>
<td class="text-secondary">
@@ -407,7 +407,7 @@
Angelegt für:
</td>
<td>
@($"{serviceRecord.Employee.FirstName} {serviceRecord.Employee.LastName}")
@serviceRecord.Employee.FirstNameLastName
</td>
</tr>
@@ -433,7 +433,7 @@
}
@* Betrag *@
@if(Model.ShowBetrag && serviceRecord.Betrag.HasValue && serviceRecord.Betrag.Value > 0)
@if(AbstractModel.ShowBetrag && serviceRecord.Betrag.HasValue && serviceRecord.Betrag.Value > 0)
{
var betrag = serviceRecord.Betrag.Value.ToString("#.00") + " €";

View File

@@ -16,13 +16,15 @@
}
<script type="text/javascript">
$(document).ready(function () {
$("#hours-minutes-dropdown-btn").on("click", function() {
$("#hours-minutes-dropdown-btn").data("text", $("#hours-minutes-dropdown-btn").text().replaceAll(/\s/g, ""));
$(document).ready(function() {
const dropdownBtn = $("#sb-hours-minutes-dropdown-btn");
dropdownBtn.on("click", function() {
dropdownBtn.data("text", dropdownBtn.text().replaceAll(/\s/g, ""));
});
$(".hours-minutes-link").on("click", function () {
const previousText = $("#hours-minutes-dropdown-btn").data("text");
const previousText = dropdownBtn.data("text");
const currentText = $(this).text().replaceAll(/\s/g, "");
if(previousText === currentText) {
@@ -30,13 +32,13 @@
}
const buttonText = $(this).text();
$("#hours-minutes-dropdown-btn").text(buttonText);
dropdownBtn.text(buttonText);
window.setInputFilter('duration', 'distance', 'hours-minutes-dropdown-btn');
window.setInputFilter();
$.get('@Url.Action("ToggleDurationUnit")', { isInHoursMode: buttonText === "Stunden" });
calculateDuration(true, 'start-time', 'end-time', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker', false, false);
calcDuration("sb", true, false, false);
});
@{
@@ -174,7 +176,7 @@
{
<div class="dropdown-divider my-0 py-0"></div>
}
<p class="mb-1 text-left @selectedSuportConceptTimeSpanColorClass" id="selectedSupportConceptInfo">
<p class="mb-1 text-left small @selectedSuportConceptTimeSpanColorClass" id="selectedSupportConceptInfo">
@Model.SelectedCostBearer2SupportConceptRelListObject.SupportConceptTimeSpan
</p>
</a>
@@ -254,318 +256,278 @@
using(Html.BeginForm("CreateOrUpdateServiceRecord", "Main", FormMethod.Post, new { id = "singleBookingForm" }))
{
<div>
@* ----- Einzelbuchung: Mitarbeiter ----- *@
<div class="form-row">
<div class="col-md">
<div class="mt-2" id="single-booking-employee-container">
@Html.PopupWithSearchForIFilterables(Model.Employees, "setSelectedEmployeeForSingleBooking", null, Model.SelectedEmployee?.DetailDescription, "single-booking-employee-modal-popup", false)
</div>
</div>
<div>
@* ----- Einzelbuchung: Mitarbeiter ----- *@
<div class="form-row">
<div class="col-md">
<div class="mt-2" id="single-booking-employee-container">
@Html.PopupWithSearchForIFilterables(Model.Employees, "setSelectedEmployeeForSingleBooking", null, Model.SelectedEmployee?.DetailDescription, "single-booking-employee-modal-popup", false)
</div>
</div>
</div>
@* ----- Einzelbuchung: Ziele ----- *@
@if(Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any())
{
<!-- Einzelbuchung: Ziele -->
<div class="form-row">
<div class="col-md mt-2">
<button type="button" class="btn btn-primary form-control" data-toggle="modal" data-target="#goal-popup" id="goals-button">
Ziele <span class="badge badge-light text-primary">@Model.SelectedGoals.Count</span>
</button>
</div>
</div>
<div class="form-row">
<div class="col-md">
<div class="collapse mt-2 w-100 max-vw-50 @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, "goals-container")" id="goals-container"></div>
</div>
</div>
}
@* ----- Einzelbuchung: Kategorie & Leistung ----- *@
<div id="category-to-description-container">
@Html.Partial("Category2ServiceDescriptionPartial", Model)
</div>
@* ----- Marker ----- *@
@if(Model.ShowMarker)
{
var markerCheckedValue = Model.SelectedServiceRecord?.ServiceRecordType == ServiceRecordTypeId.Content ? "checked" : string.Empty;
<div class="form-row">
<div class="col-md mt-1">
<div class=" custom-control custom-checkbox custom-control-inline my-0">
<input type="checkbox" class="custom-control-input" name="@FormCollectionConstants.MarkerKey" id="marker-cb" @markerCheckedValue />
<label class="custom-control-label" for="marker-cb">Marker</label>
</div>
</div>
</div>
}
@* ----- Einzelbuchung: Ziele ----- *@
@if(Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any())
{
<!-- Einzelbuchung: Ziele -->
<div class="form-row">
<div class="col-md mt-2">
<button type="button" class="btn btn-primary form-control" data-toggle="modal" data-target="#goal-popup" id="goals-button">
Ziele <span class="badge badge-light text-primary">@Model.SelectedGoals.Count</span>
</button>
</div>
</div>
<div class="form-row">
<div class="col-md">
<div class="collapse mt-2 w-100 max-vw-50 @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, "goals-container")" id="goals-container"></div>
</div>
</div>
}
@* ----- Betrag ----- *@
@if(AbstractModel.ShowBetrag)
{
var betrag = string.Empty;
if(Model.SelectedServiceRecord?.Betrag != null && Model.SelectedServiceRecord.Betrag.Value > 0)
{
betrag = Model.SelectedServiceRecord.Betrag.Value.ToString("#.00");
}
@* ----- Einzelbuchung: Kategorie & Leistung ----- *@
<div id="category-to-description-container">
@Html.Partial("Category2ServiceDescriptionPartial", Model)
</div>
@* ----- Marker ----- *@
@if(Model.ShowMarker)
{
var markerCheckedValue = Model.SelectedServiceRecord?.ServiceRecordType == ServiceRecordTypeId.Content ? "checked" : string.Empty;
<div class="form-row">
<div class="col-md">
<div class="mt-1 custom-control custom-checkbox custom-control-inline">
<input type="checkbox" class="custom-control-input" name="@FormCollectionConstants.MarkerKey" id="marker-cb" @markerCheckedValue />
<label class="custom-control-label" for="marker-cb">Marker</label>
<div class="form-row mt-1">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Betrag
</div>
</div>
</div>
}
@* ----- Betrag ----- *@
@if(Model.ShowBetrag)
{
var betrag = string.Empty;
if(Model.SelectedServiceRecord?.Betrag != null && Model.SelectedServiceRecord.Betrag.Value > 0)
{
betrag = Model.SelectedServiceRecord.Betrag.Value.ToString("#.00");
}
<div class="form-row mt-2">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Betrag
</div>
</div>
<input class="form-control" autocomplete="on" type="text" id="betrag" name="betrag" value="@betrag" />
<div class="input-group-append">
<div class="input-group-text">€</div>
</div>
</div>
</div>
<input class="form-control" autocomplete="on" type="text" id="betrag" name="betrag" value="@betrag" />
<div class="input-group-append">
<div class="input-group-text">€</div>
</div>
</div>
}
<hr class="mt-2 mb-0" />
@* ----- Einzelbuchung: Startdatum und gegebenenfalls Enddatum ----- *@
<div class="form-row">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="start-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Startdatum
</div>
</div>
<input type="text" autocomplete="on" 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 px-2">
<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 my-0">
<div class="input-group date mt-2" id="end-date-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text prepend-input-group-text">
Enddatum
</div>
</div>
<input type="text" autocomplete="on" 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 px-2">
<i class="fas fa-calendar-alt"></i>
</div>
</div>
</div>
</div>
</div>
}
</div>
@* ----- Einzelbuchung: Von ----- *@
<div class="form-row">
@{
var startTimeValue = Model.StartTimeToEdit;
var endTimeValue = Model.EndTimeToEdit;
var divisor = Model.SelectedDurationUnit == "Stunden" ? 60 : 1;
var durationValue = Model.DurationToEdit;
var afterValidationState = TempData[TempDataConstants.AfterValidationStateKey];
if (Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode && afterValidationState is bool isAfterValidation && isAfterValidation == false)
{
startTimeValue = Model.NewStartTime;
endTimeValue = Model.NewEndTime;
durationValue = Model.NewDuration?.ToString();
if (Model.NewDuration.HasValue)
{
durationValue = (Model.NewDuration / divisor).ToString();
}
}
}
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="start-time-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text sm-prepend-input-group-text px-2">
Von
</div>
</div>
<input type="text" autocomplete="on" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@startTimeValue" />
<div class="input-group-append" data-target="#start-time-picker" data-toggle="datetimepicker">
<div class="input-group-text px-2">
<i class="fas fa-clock"></i>
</div>
</div>
</div>
</div>
</div>
@* ----- Einzelbuchung: Bis ----- *@
<div class="col-md">
<div class="form-group my-0">
<div class="input-group date mt-2" id="end-time-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text sm-prepend-input-group-text px-2">
Bis
</div>
</div>
<input type="text" autocomplete="on" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@endTimeValue" />
<div class="input-group-append" data-target="#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>
@* ----- Einzelbuchung: Dauer ----- *@
<div class="form-row mt-2">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group">
<div class="input-group-prepend">
@{
var labelText = Model.EinheitZeiterfassung == 1 ? "Dauer (h)" : "Dauer";
}
<div class="input-group-text prepend-input-group-text">
@labelText
</div>
</div>
<input type="number" step="0.01" min="0" class="form-control" id="duration" name="Dauer" onchange="onDurationChange('start-time', 'end-time', 'start-date', 'end-date', 'duration', 'hours-minutes-dropdown-btn', 'start-date-picker', 'end-date-picker')" value="@durationValue">
@if (Model.IsZeiterfassungInStdMin)
{
<div class="input-group-append">
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
@Model.SelectedDurationUnit
</button>
<div class="dropdown-menu">
<a class="dropdown-item hours-minutes-link" href="#">Minuten</a>
<a class="dropdown-item hours-minutes-link" href="#">Stunden</a>
</div>
</div>
}
</div>
</div>
</div>
</div>
@* ----- Einzelbuchung: Distanz ----- *@
@if(Model.ShowDistanceField)
{
<div class="form-row mt-2">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text">
Gefahrene Kilometer
</div>
</div>
<input class="form-control" autocomplete="on" id="distance" name="Distanz" onchange="validateDistanceInput()" value="@Model.DistanceToEdit">
</div>
</div>
</div>
</div>
}
@* ----- Einzelbuchung: Textbausteine ----- *@
@if(AbstractModel.HasRightToSeeTextModules)
{
<script type="text/javascript">
function textModuleButtonOnClick() {
$('#tree').load('@Url.Action("LoadUpToDateTextModules")');
}
</script>
<div class="form-row mt-2" id="textmodule-container">
<div class="col-md">
<button type="button" class="btn btn-primary form-control" data-toggle="modal" data-target="#textbausteine-popup" id="textbausteine-button" onclick="textModuleButtonOnClick()">Textbausteine</button>
</div>
</div>
}
@* ----- Einzelbuchung: Dokumentation ----- *@
<div class="form-row">
<div class="col-md mt-3">
@if (Model.NumberOfDokuTypes == 0)
{
<div class="form-group my-0">
<label for="dokufeld">Dokumentation</label>
<textarea class="form-control" autocomplete="on" style="overflow: scroll;" 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" class="nav-link@(i == 0 ? " active" : string.Empty)">
@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">
<textarea class="form-control doku-form-control" autocomplete="on" style="overflow: scroll;" id="doku-textarea-@i" name="@textareaName">@Model.NoticeListToEdit[i]</textarea>
</div>
}
</div>
}
</div>
</div>
</div>
</div>
}
<hr class="mt-2 mb-0" />
@* ----- Einzelbuchung: Startdatum und gegebenenfalls Enddatum ----- *@
@{
var divisor = Model.SelectedDurationUnit == "Stunden" ? 60 : 1;
var durationValue = Model.DurationToEdit;
var afterValidationState = TempData[TempDataConstants.AfterValidationStateKey];
if(Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode && afterValidationState is bool and false)
{
durationValue = Model.NewDuration?.ToString();
if(Model.NewDuration.HasValue)
{
durationValue = (Model.NewDuration / divisor).ToString();
}
}
<div class="d-flex bd-highlight mt-3">
<div class="mr-auto bd-highlight"></div>
var columnWidth = Model.IsEndDateVisible ? "col-md-6" : "col";
}
@if(Model.IsInEditingMode)
<div class="form-row">
<div class="@columnWidth mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text prepend-input-group-text">
Startdatum
</span>
</div>
<input class="form-control" type="date" name="Datum" id="sb-start-date-input" onchange="calcDuration('sb', false, true, false)" value="@Model.StartDateToEditJSFormat" />
</div>
</div>
@if(Model.IsEndDateVisible)
{
<div class="col-md-6 mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text prepend-input-group-text">
Enddatum
</span>
</div>
<input class="form-control" type="date" name="Enddatum" id="sb-end-date-input" onchange="calcDuration('sb', false, false, true)" value="@Model.EndDateToEditJSFormat" />
</div>
</div>
}
</div>
<div class="form-row">
<div class="col mt-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text prepend-input-group-text">
Von
</span>
</div>
<input class="form-control" type="time" name="Start" id="sb-start-time-input" onchange="calcDuration('sb', false, true, false)" value="@Model.StartTimeToEdit" />
<span class="input-group-text rounded-0 border-left-0 border-right-0">
Bis
</span>
<input class="form-control" type="time" name="Ende" id="sb-end-time-input" onchange="calcDuration('sb', false, false, true)" value="@Model.EndTimeToEdit" />
</div>
</div>
</div>
@* ----- Einzelbuchung: Dauer ----- *@
<div class="form-row mt-2">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group">
<div class="input-group-prepend">
@{
var labelText = Model.EinheitZeiterfassung == 1 ? "Dauer (h)" : "Dauer";
}
<div class="input-group-text prepend-input-group-text">
@labelText
</div>
</div>
<input type="text" class="form-control" id="sb-duration-input" name="Dauer" onchange="beiDaueraenderung('sb')" value="@durationValue">
@if(Model.IsZeiterfassungInStdMin)
{
<div class="input-group-append">
<button id="sb-hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
@Model.SelectedDurationUnit
</button>
<div class="dropdown-menu">
<a class="dropdown-item hours-minutes-link" href="#">Minuten</a>
<a class="dropdown-item hours-minutes-link" href="#">Stunden</a>
</div>
</div>
}
</div>
</div>
</div>
</div>
@* ----- Einzelbuchung: Distanz ----- *@
@if(AbstractModel.ShowDistanceField)
{
<div class="form-row mt-2">
<div class="col-md">
<div class="form-group my-0">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text">
Gefahrene Kilometer
</div>
</div>
<input class="form-control" autocomplete="on" id="sb-distance-input" name="Distanz" onchange="validateDistanceInput()" value="@Model.DistanceToEdit">
</div>
</div>
</div>
</div>
}
@* ----- Einzelbuchung: Textbausteine ----- *@
@if(AbstractModel.HasRightToSeeTextModules)
{
<script type="text/javascript">
function textModuleButtonOnClick() {
$('#tree').load('@Url.Action("LoadUpToDateTextModules")');
}
</script>
<div class="form-row mt-2" id="textmodule-container">
<div class="col-md">
<button type="button" class="btn btn-primary form-control" data-toggle="modal" data-target="#textbausteine-popup" id="textbausteine-button" onclick="textModuleButtonOnClick()">Textbausteine</button>
</div>
</div>
}
@* ----- Einzelbuchung: Dokumentation ----- *@
<div class="form-row">
<div class="col-md mt-3">
@if(Model.NumberOfDokuTypes == 0)
{
<div class="form-group my-0">
<label for="sb-dokufeld-textarea">Dokumentation</label>
<button type="button" class="btn btn-outline-bewo-dev btn-sm sb-restore-btn" onclick="restoreField('sb-dokufeld-textarea')">
<i class="fas fa-recycle"></i>
</button>
<textarea class="form-control" autocomplete="on" style="overflow: scroll;" name="Dokumentation6" id="sb-dokufeld-textarea">@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="#sb-doku_@i" id="sb-doku_@i-tab" data-toggle="tab" role="tab" class="nav-link@(i == 0 ? " active" : string.Empty)">
@currentDokuType.DisplayName
<button type="button" class="btn btn-outline-bewo-dev btn-sm sb-restore-btn" onclick="restoreField('sb-doku-textarea-@i')">
<i class="fas fa-recycle"></i>
</button>
</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="sb-doku_@i" role="tabpanel">
<textarea class="form-control doku-form-control" autocomplete="on" style="overflow: scroll;" id="sb-doku-textarea-@i" name="@textareaName">@Model.NoticeListToEdit[i]</textarea>
</div>
}
</div>
}
</div>
</div>
</div>
}
<div class="w-100 mt-2">
<button type="button" class="btn btn-primary float-right ml-1" id="create-button" onclick="submitSingleBookingForm()">@Model.SubmitButtonValue</button>
@if(Model.IsInEditingMode)
{
using(Html.BeginForm("ResetEditingMode", "Main", FormMethod.Post))
{
<button type="submit" class="btn btn-primary" onclick="showSpinner()">Abbrechen</button>
<button type="submit" class="btn btn-primary float-right" onclick="showSpinner()">Abbrechen</button>
}
}
else if(TempData[TempDataConstants.IsInTransferModeKey] is bool isInTransferMode && isInTransferMode)
{
using(Html.BeginForm("ResetTransferMode", "Main", FormMethod.Post))
{
<button type="submit" class="btn btn-primary" onclick="showSpinner()">Abbrechen</button>
<button type="submit" class="btn btn-primary float-right" 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>
<button type="button" class="btn btn-primary float-right" id="reset-button" onclick="resetSingleBookingForm()">Abbrechen</button>
}
<div class="ml-3 bd-highlight">
<button type="button" class="btn btn-primary" id="create-button" onclick="submitSingleBookingForm()">@Model.SubmitButtonValue</button>
</div>
</div>
}
</div>

View File

@@ -63,6 +63,7 @@
const textAfter = v.substring(cursorPosition, v.length);
focusedDokuFeld.val(textBefore + textModuleText + textAfter);
focusedDokuFeld.trigger("change");
$("#textbausteine-popup").modal("hide");
});

View File

@@ -1,5 +1,7 @@
@using BeWoPlanerMobil.Util
@using BeWoPlanerMobil.Models
@using BeWoPlanerMobil.Util
@using BeWoPlanerMobil.Util.ReportUtils
@using BS.Shared
@model BeWoPlanerMobil.Models.ReportModel
@{
@@ -23,12 +25,6 @@
$(document).ready(function () {
$(".left-col").width(window.getMaxWidth("left-col"));
});
$(".signature-card").ready(function () {
setTimeout(function () {
$(".signature-card").height(window.getMaxElementHeight("signature-card"));
}, 100);
});
</script>
<div class="container-fluid lg-max-width">
@@ -84,14 +80,14 @@
}
@if(message != null)
{
<div class="alert alert-primary d-block w-100 mt-4" role="alert">
<div class="alert alert-primary mt-4 w-auto" role="alert">
@Html.Raw(message)
</div>
}
@if(message2 != null)
{
<div class="alert alert-success d-block w-100 mt-4" role="alert">
<div class="alert alert-success mt-4 mx-auto" style="width: fit-content;" role="alert">
@Html.Raw(message2)
</div>
}
@@ -150,38 +146,312 @@
{
var blubb = $"{(signature.NumberOfServiceRecords == 1 ? "eine" : signature.NumberOfServiceRecords.ToString())} erbrachte Leistung{(signature.NumberOfServiceRecords != 1 ? "en" : string.Empty)}";
<div class="@GetColumnClass()">
<div class="card signature-card mt-4">
<div class="justify-content-center">
<img style="display: block; margin-left: auto; margin-right: auto; max-width: 100% !important;" src="@signature.ImageStr" alt="Unterschrift von @signature.PersonName geleistet am @signature.InsTsStr" />
</div>
<div class="card-body m-0 p-0" style="height: 0 !important;"></div>
<div class="card-footer">
<div class="row">
<div class="col-auto left-col">
Unterschrift von:
</div>
<div class="col">
@signature.PersonName
</div>
</div>
<div class="row">
<div class="col-auto left-col">
Geleistet am:
</div>
<div class="col">
@signature.InsTsStr
</div>
</div>
<div class="row">
<div class="col-auto left-col">
Geleistet für:
</div>
<div class="col">
@blubb
</div>
</div>
</div>
<div class="card signature-card mt-4 mx-1">
<div>
@* max-width: 100% !important; *@
<img style="display: block; margin-left: auto; margin-right: auto;" src="@signature.ImageStr" alt="Unterschrift von @signature.PersonName geleistet am @signature.InsTsStr" />
</div>
<div class="card-body p-1 mb-0 pb-0">
<table class="table table-sm service-record-table my-0">
<tr>
<td class="text-secondary">
Unterschrift von:
</td>
<td>
@signature.PersonName
</td>
</tr>
<tr>
<td class="text-secondary">
Geleistet am:
</td>
<td>
@signature.InsTsStr
</td>
</tr>
</table>
<div class="card w-100">
<div class="card-header" onclick="cardHeaderClick2(this)">
<div class="d-inline-flex">
<i class="fas fa-chevron-down h-100 text-primary" id="chevron-test-collapsible"></i>
</div>
<div class="d-inline-flex text-primary h-100">
<button type="button" class="btn btn-link">
@blubb
</button>
</div>
</div>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, $"c-qb-{signature.Identifier}")" id="c-qb-@signature.Identifier">
<div class="card-body p-1">
<div class="container p-0">
@foreach(var serviceRecord in signature.ServiceRecords)
{
if(serviceRecord.Start is null || serviceRecord.End is 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 massnahmenString = string.Empty;
var zieleString = string.Empty;
if(serviceRecord.Goals != null && serviceRecord.Goals.Count > 0)
{
foreach(var goal in serviceRecord.Goals.Where(g => g.Type == ValueListEntryType.SupportConceptGoalType || g.Type == ValueListEntryType.SupportConceptIndividualGoalType))
{
if(goal.Abbreviation != null && goal.TypeDescription != null)
{
massnahmenString += $"{goal.Abbreviation}: {goal.TypeDescription}";
}
else if(goal.Abbreviation is null && goal.TypeDescription != null)
{
massnahmenString += goal.TypeDescription;
}
else if(goal.Abbreviation != null && goal.TypeDescription is null)
{
massnahmenString += goal.Abbreviation;
}
#if DEBUG
if(goal.RatingTypeOid.HasValue)
{
var goalRating = Model.GoalRatingTypes.FirstOrDefault(g => g.RatingTypeOid.HasValue && g.RatingTypeOid.Equals(goal.RatingTypeOid.Value));
if(goalRating?.DisplayName != null && goalRating.DisplayName.Length > 0)
{
massnahmenString += $" <strong style='color: blue;'>({goalRating.DisplayName})</strong>";
}
}
#endif
if(serviceRecord.Goals.IndexOf(goal) < serviceRecord.Goals.Count - 1)
{
massnahmenString += ", ";
}
}
if(serviceRecord.ServiceRecordOid.HasValue && Model.ServiceRecordOids2GoalHeader.ContainsKey(serviceRecord.ServiceRecordOid.Value))
{
var ziele = serviceRecord.Goals.Where(g => g.Type == ValueListEntryType.SupportConceptIndividualGoalCategoryType || g.Type == ValueListEntryType.SupportConceptGoalCategoryType).ToList();
foreach(var ziel in ziele)
{
if(ziel.Abbreviation != null && ziel.TypeDescription != null)
{
zieleString += $"{ziel.Abbreviation}: {ziel.TypeDescription} ";
}
else if(ziel.Abbreviation is null && ziel.TypeDescription != null)
{
zieleString += ziel.TypeDescription;
}
else if(ziel.Abbreviation != null && ziel.TypeDescription is null)
{
zieleString += ziel.Abbreviation;
}
#if DEBUG
if(ziel.RatingTypeOid.HasValue)
{
var zielbewertung = Model.GoalRatingTypes.FirstOrDefault(goalRatingType => goalRatingType.RatingTypeOid.HasValue && goalRatingType.RatingTypeOid.Equals(ziel.RatingTypeOid.Value));
if(zielbewertung?.DisplayName != null && zielbewertung.DisplayName.Length > 0)
{
zieleString += $" <strong style='color: blue;'>({zielbewertung.DisplayName})</strong>";
}
}
#endif
zieleString += ", ";
}
}
zieleString = zieleString.TrimEnd(' ').TrimEnd(',');
}
<div class="card mt-1">
<div class="card-body p-1">
<div class="card-title m-1 text-primary">
@MainModel.GetServiceRecordTimeHeader(serviceRecord, true)
</div>
<table class="table table-sm table-striped service-record-table" my-0>
<tr>
<td class="text-secondary">
Minuten (gerundet):
</td>
<td class="text-info">
@durationStr
</td>
</tr>
@if(AbstractModel.ShowDistanceField && serviceRecord.DistanceInMeterDecimal != null && serviceRecord.DistanceInMeterDecimal.Value > 0)
{
<tr>
<td class="text-secondary">
Gefahrene Kilometer:
</td>
<td>
@($"{serviceRecord.DistanceInMeterDecimal:0.##}")
</td>
</tr>
}
@if(serviceRecord.Goals != null && serviceRecord.Goals.Count > 0)
{
if(!string.IsNullOrEmpty(zieleString))
{
<tr>
<td class="text-secondary">
Ziele:
</td>
<td>
@(new HtmlString(zieleString))
</td>
</tr>
}
if(serviceRecord.Goals.Any(goal => goal.Type == ValueListEntryType.SupportConceptGoalType || goal.Type == ValueListEntryType.SupportConceptIndividualGoalType))
{
<tr>
<td class="text-secondary">
Maßnahmen:
</td>
<td>
@(new HtmlString(massnahmenString))
</td>
</tr>
}
}
<tr>
<td class="text-secondary">
Leistungskategorie:
</td>
<td>
@serviceRecord.ServiceDescription.CategoryName
</td>
</tr>
<tr>
<td class="text-secondary">
Leistung:
</td>
<td>
@serviceRecord.ServiceDescription.Name
</td>
</tr>
<tr>
<td class="text-secondary">
Angelegt für:
</td>
<td>
@serviceRecord.Employee.FirstNameLastName
</td>
</tr>
@if(AbstractModel.ShowServiceRecordInsertedOn)
{
<tr>
<td class="text-secondary">
Angelegt von:
</td>
<td>
@serviceRecord.InsUser
</td>
</tr>
<tr>
<td class="text-secondary">
Angelegt am:
</td>
<td>
@serviceRecord.InsertedOn
</td>
</tr>
}
@if(AbstractModel.ShowBetrag && serviceRecord.Betrag.HasValue && serviceRecord.Betrag.Value > 0)
{
var betrag = serviceRecord.Betrag.Value.ToString("#.00") + " €";
<tr>
<td class="text-secondary">
Betrag:
</td>
<td>
@betrag
</td>
</tr>
}
@{
var header1 = "Dokumentation";
if(Model.NumberOfDokuTypes >= 1)
{
header1 = Model.Dokutypes[0].TypeDescription;
}
<tr>
<td class="text-secondary">
@header1:
</td>
<td>
@Html.Raw(MobileUtils.ToHtml(serviceRecord.Notice, false))
</td>
</tr>
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;
}
<tr>
<td class="text-secondary">
@header:
</td>
<td>
@Html.Raw(MobileUtils.ToHtml(notice, false))
</td>
</tr>
}
}
<tr>
<td class="text-secondary">
Unterschrieben:
</td>
<td>
@hasSignatureStr
</td>
</tr>
</table>
</div>
</div>
}
</div>
</div>
</div>
</div>
</div>
</div>
}

View File

@@ -69,15 +69,15 @@
$("#qb-sig-canvas-row, #qb-sig-canvas-container, #qb-sig-sketch-pad, #qb-sig-save-btn, #qb-sig-clear-canvas-btn").hide();
}
resizeCanvas("#qb-sig-sketch-pad", "#qb-sig-canvas-row");
updateCanvasSize($("#qb-sig-sketch-pad"));
var canvas = document.getElementById("qb-sig-sketch-pad");
const canvas = document.getElementById("qb-sig-sketch-pad");
var signaturePad = new SignaturePad(canvas, { backgroundColor: "rgba(255, 255, 255, 0)" });
var cancelButton = document.getElementById("qb-sig-cancel-btn");
var saveButton = document.getElementById("qb-sig-save-btn");
var clearButton = document.getElementById("qb-sig-clear-canvas-btn");
const cancelButton = document.getElementById("qb-sig-cancel-btn");
const saveButton = document.getElementById("qb-sig-save-btn");
const clearButton = document.getElementById("qb-sig-clear-canvas-btn");
cancelButton.addEventListener("click",
function() {
@@ -86,16 +86,15 @@
saveButton.addEventListener("click",
function() {
var canvas = document.getElementById("qb-sig-sketch-pad");
var clonedCanvas = cloneCanvas(canvas);
var trimmedCanvas = trimCanvas(clonedCanvas);
const clonedCanvas = cloneCanvas(document.getElementById("qb-sig-sketch-pad"));
const trimmedCanvas = trimCanvas(clonedCanvas);
var context = trimmedCanvas.getContext("2d", {willReadFrequently: true});
const context = trimmedCanvas.getContext("2d", {willReadFrequently: true});
context.globalCompositeOperation = "destination-over";
context.fillStyle = "white";
context.fillRect(0, 0, trimmedCanvas.width, trimmedCanvas.height);
var dataUrl = trimmedCanvas.toDataURL("image/png");
const dataUrl = trimmedCanvas.toDataURL("image/png");
showSpinner();
@@ -114,13 +113,13 @@
$("#report-signature-container").addClass("d-none");
$("#report-form-container").show();
} catch (error) {
showErrorPopup(error);
window.showErrorPopup(error);
}
});
},
true);
} else {
showMessagePopup("Fehler", json);
window.showMessagePopup("Fehler", json);
signaturePad.clear();
}
});

View File

@@ -15,28 +15,6 @@
}
<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"));
@@ -79,26 +57,29 @@
const duration = parseInt($("#interval-duration").val());
const start = getDateTimeFromPicker("scheduler-interval-start", "scheduler-interval-start-time");
const end = getDateTimeFromPicker("scheduler-interval-end", "scheduler-interval-end-time");
const startStr = $("#scheduler-interval-start").val();
const endStr = $("#scheduler-interval-end").val();
const isStartValid = start !== null && isValidDate(new Date(start));
const isEndValid = end !== null && isValidDate(new Date(end));
const start = new Date(startStr);
const end = new Date(endStr);
isValid = isStartValid && isEndValid && duration > 0 && (start !== null && start !== undefined && start.isBefore(end));
const isStartValid = startStr !== null && false === isNaN(start.getTime());
const isEndValid = endStr !== null && false === isNaN(end.getTime());
isValid = isStartValid && isEndValid && duration > 0 && end > start;
if(isValid === false) {
let validationMessage = "";
if(isStartValid === false && isEndValid === false) {
validationMessage = "Das Start- und Endwerte sind ungültig!";
validationMessage = "Das Start- und Enddatum sind ungültig!";
} else if(isStartValid === true && isEndValid === false) {
validationMessage = "Das Enddatum ist ungültig!";
} else if(isStartValid === false && isEndValid === true) {
validationMessage = "Das Startdatum ist ungültig!";
}
if(start !== null && start !== undefined && start.isBefore(end) === false) {
if(end > start) {
if(validationMessage.length === 0) {
validationMessage += "Das Enddatum darf nicht vor dem Startdatum liegen!";
} else {
@@ -124,32 +105,8 @@
}
}
function getDateTimeFromPicker(datePickerId, timePickerId) {
try {
const dateVal = $(`#${datePickerId}`).datetimepicker("viewDate");
const timeVal = $(`#${timePickerId}`).val();
const timeRegEx = new RegExp('^(2[0-3]|[01]?[0-9]):([0-5]?[0-9])$');
if(isValidDate(new Date(dateVal)) && timeRegEx.test(timeVal)) {
const hm = timeVal.split(":");
if(hm.length === 2 && $.isNumeric(hm[0]) && $.isNumeric(hm[1])) {
dateVal.hours(parseInt(hm[0]));
dateVal.minutes(parseInt(hm[1]));
return dateVal;
}
}
return null;
} catch (error) {
window.showErrorPopup(error);
}
}
$("#interval-form-container").ready(function() {
const width = getMaxWidth("prepend-text");
const width = window.getMaxWidth("prepend-text");
$(".prepend-text").width(width);
});
@@ -191,222 +148,184 @@
<div class="alert alert-danger collapse" role="alert" id="interval-finder-validation-alert"></div>
@using(Html.BeginForm("FindFreeIntervals", "Scheduler", FormMethod.Post, new { id = "find-appointment-intervals-form", @class = "needs-validation", novalidate = true }))
{
<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-interval-start-picker" data-target-input="nearest">
<div class="input-group-prepend">
<span class="input-group-text prepend-text px-2">
Von
</span>
</div>
<input value="@Model.IntervalStartDateStr" type="text" autocomplete="on" 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 px-2">
<i class="fas fa-calendar-alt"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-5 mx-0 pl-0">
<div class="form-group mb-1 ml-0 pl-0">
<div class="input-group date" id="scheduler-interval-start-time-picker" data-target-input="nearest">
<input value="@Model.IntervalStartTimeStr" type="text" autocomplete="on" 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 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 ml-0 pl-0">
<div class="input-group date" id="scheduler-interval-end-picker" data-target-input="nearest">
<div class="input-group-prepend">
<div class="input-group-text prepend-text px-2">
Bis
</div>
</div>
<input value="@Model.IntervalEndDateStr" type="text" autocomplete="on" 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 px-2">
<i class="fas fa-calendar-alt"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-5 mx-0 pl-0">
<div class="form-group mb-1 ml-0 pl-0">
<div class="input-group date" id="scheduler-interval-end-time-picker" data-target-input="nearest">
<input value="@Model.IntervalEndTimeStr" type="text" autocomplete="on" 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 px-2">
<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">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text prepend-text px-2">
Dauer
</div>
</div>
<input value="@Model.IntervalDurationStr" type="number" autocomplete="on" min="10" id="interval-duration" name="Duration" class="form-control" />
</div>
</div>
</div>
</div>
<div>
<div class="form-row mt-1">
<div class="col-md">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text prepend-text">
Von
</span>
</div>
<input class="form-control" type="datetime-local" id="scheduler-interval-start" name="IntervalStart" value="@Model.IntervalStartDateStr"/>
</div>
</div>
</div>
<div class="form-row mt-1">
<div class="col-md">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text prepend-text">
Bis
</span>
</div>
<input class="form-control" type="datetime-local" id="scheduler-interval-end" name="IntervalEnd" value="@Model.IntervalEndDateStr"/>
</div>
</div>
</div>
<div class="form-row mt-1">
<div class="col-md">
<div class="form-group mb-1">
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text prepend-text px-2">
Dauer
</div>
</div>
<input value="@Model.IntervalDurationStr" type="number" autocomplete="on" min="10" id="interval-duration" name="Duration" class="form-control"/>
</div>
</div>
</div>
</div>
@if(Model.HasResourcesEmployeesOrCustomers)
{
<!-- Hinzufügen-Buttons -->
<div class="form-row">
@if(AbstractModel.HasRightToViewEmployeeAppointments)
{
<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-interval-finder-popup">Mitarbeiter</button>
</div>
</div>
}
@if(AbstractModel.HasRightToViewCustomerAppointments)
{
<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-interval-finder-popup">Klienten</button>
</div>
</div>
}
@if(AbstractModel.HasRightToViewAllResourceAppointments && 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-interval-finder-popup">Ressourcen</button>
</div>
</div>
}
</div>
@if(Model.HasResourcesEmployeesOrCustomers)
{
<!-- Hinzufügen-Buttons -->
<div class="form-row">
@if(AbstractModel.HasRightToViewEmployeeAppointments)
{
<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-interval-finder-popup">Mitarbeiter</button>
</div>
</div>
}
@if(AbstractModel.HasRightToViewCustomerAppointments)
{
<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-interval-finder-popup">Klienten</button>
</div>
</div>
}
@if(AbstractModel.HasRightToViewAllResourceAppointments && 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-interval-finder-popup">Ressourcen</button>
</div>
</div>
}
</div>
<div class="form-row">
@if(AbstractModel.HasRightToViewEmployeeAppointments)
{
<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;
<div class="form-row">
@if(AbstractModel.HasRightToViewEmployeeAppointments)
{
<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 filterAppointmentsUrl = Url.Action("FetchAppointments", "Scheduler");
var filterAppointmentsUrl = Url.Action("FetchAppointments", "Scheduler");
var onClickParams = $"{oid}, '-interval-finder-checkbox', false, '{url}', 'employees-interval-finder-popup', 'employees-interval-finder-popup', 'related-employee-interval-finder-', '{filterAppointmentsUrl}'";
}
var onClickParams = $"{oid}, '-interval-finder-checkbox', false, '{url}', 'employees-interval-finder-popup', 'employees-interval-finder-popup', 'related-employee-interval-finder-', '{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.HasRightToViewCustomerAppointments)
{
<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;
<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.HasRightToViewCustomerAppointments)
{
<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 filterAppointmentsUrl = Url.Action("FetchAppointments", "Scheduler");
var filterAppointmentsUrl = Url.Action("FetchAppointments", "Scheduler");
var onClickParams = $"{oid}, '-interval-finder-checkbox', false, '{url}', 'customers-interval-finder-popup', 'customers-interval-finder-popup', 'related-customer-interval-finder-', '{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 && 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', '@Url.Action("FetchAppointments", "Scheduler")', 'related-resource-interval-finder-item-', '-interval-finder-checkbox', 'all-resources-for-interval-finder-checkbox')">
<span class="fas fa-times-circle"></span>
</button>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
}
</div>
}
</div>
var onClickParams = $"{oid}, '-interval-finder-checkbox', false, '{url}', 'customers-interval-finder-popup', 'customers-interval-finder-popup', 'related-customer-interval-finder-', '{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 && 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', '@Url.Action("FetchAppointments", "Scheduler")', 'related-resource-interval-finder-item-', '-interval-finder-checkbox', 'all-resources-for-interval-finder-checkbox')">
<span class="fas fa-times-circle"></span>
</button>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
}
</div>
}
</div>
<button type="submit" class="d-none" id="hidden-submit-btn"></button>
}
<div class="d-flex bd-highlight mt-3">

View File

@@ -54,8 +54,8 @@
<script type="text/javascript" src="@Scripts.Url("~/Scripts/tempusdominus-boostrap-4.min.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/mobileUtils.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/view-scripts/main.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/signature.js?v=1.1")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/view-scripts/main.js?v=1.1")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/signature.js?v=1.2")"></script>
<link type="text/css" rel="stylesheet" href="@Url.Content("~/Scripts/bootstrap/bootstrap4-modal-fullscreen.min.css")" />
@@ -72,7 +72,7 @@
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/utils/js-helper.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/utils/logging.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/utils/MoKPasswordSecurity.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/bs-custom-file-input.min.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/bs-custom-file-input.min.js?v=1.1")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/ownSoft-Scripts/utils/dropdown-search.js")"></script>
<script type="text/javascript" src="@Scripts.Url("~/Scripts/devexpress-dependencies/devextreme/dx.all.js")"></script>
@@ -93,10 +93,89 @@
new Script { ExtensionType = ExtensionType.WebDocumentViewer }
)
<script type="text/javascript">
function saveCollapsibleState(id, url) {
const isShown = $(`#${id}`).hasClass("show");
$.get(url, { isOpen: isShown, identifier: id });
<script type="text/javascript">
class LocalBeWoStorage {
id;
inputList;
constructor(id, inputList) {
this.id = id;
this.inputList = inputList;
}
removeItemById(id) {
const newInputList = [];
for (let i = 0; i < this.inputList.length; i++) {
const input = this.inputList[i];
if (input.inputId !== id) {
newInputList.push(input);
}
}
this.inputList = newInputList;
localStorage.setItem(this.id, JSON.stringify(this));
}
removeItemByName(name) {
const newInputList = [];
for (let i = 0; i < this.inputList.length; i++) {
const input = this.inputList[i];
if (input.inputName !== name) {
newInputList.push(input);
}
}
this.inputList = newInputList;
localStorage.setItem(this.id, JSON.stringify(this));
}
addInputValue(inputId, inputName, inputType, inputValue, timeStamp) {
if (inputType === "radio") {
this.removeItemByName(inputName);
}
const obj = {
inputId: inputId,
inputName: inputName,
inputType: inputType,
inputValue: inputValue,
timeStamp: timeStamp
};
this.removeItemById(inputId);
this.inputList.push(obj);
localStorage.setItem(this.id, JSON.stringify(this));
}
getItemById(id) {
return this.inputList.find((element) => element.inputId === id);
}
getItemsByName(name) {
const result = [];
this.inputList.map((item) => {
if (item.inputName === name) {
result.push(item);
}
});
return result;
}
}
function saveCollapsibleState(id, url) {
const isShown = $(`#${id}`).hasClass("show");
$.get(url, { isOpen: isShown, identifier: id });
}
window.addEventListener("error", (event) => {
@@ -172,75 +251,88 @@
}
}
$(document).ready(function() {
$("textarea").each(function () {
const id = this.getAttribute("id");
$.each($("canvas"), function(index, canvasElement) {
updateCanvasSize($(canvasElement));
});
if(id === "fehlerdetail-textarea") {
return;
}
$("textarea").each(function () {
const id = this.getAttribute("id");
this.setAttribute("style", `height:${this.scrollHeight}px;overflow-y:scroll;`);
}).on("input", function () {
this.style.height = 0;
this.style.height = (this.scrollHeight) + "px";
});
if(id === "fehlerdetail-textarea") {
return;
}
const timeoutInMilliseconds = parseInt("@AbstractBaseController.TimeoutLimit", 10) * 60 * 1000;
this.setAttribute("style", `height:${this.scrollHeight}px;overflow-y:scroll;`);
}).on("input", function () {
this.style.height = 0;
this.style.height = (this.scrollHeight) + "px";
});
const timeOfLogin = "@AbstractModel.TimeOfLastAction";
const timeoutInMilliseconds = parseInt("@AbstractBaseController.TimeoutLimit", 10) * 60 * 1000;
if(timeOfLogin.length > 0) {
var countDownDate = new Date().getTime() + timeoutInMilliseconds;
const timeOfLogin = "@AbstractModel.TimeOfLastAction";
var interval = setInterval(function() {
const now = new Date().getTime();
if(timeOfLogin.length > 0) {
var countDownDate = new Date().getTime() + timeoutInMilliseconds;
const distance = countDownDate - now;
var interval = setInterval(function() {
const now = new Date().getTime();
if (distance <= 0) {
clearInterval(interval);
$("#countdown").html("00:00");
const distance = countDownDate - now;
$("#logout-form").submit();
if (distance <= 0) {
clearInterval(interval);
$("#countdown").html("00:00");
return;
}
$("#logout-form").submit();
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
return;
}
var m = minutes.toString();
var s = seconds.toString();
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
if(minutes < 10) {
m = `0${m}`;
}
var m = minutes.toString();
var s = seconds.toString();
if(seconds < 10) {
s = `0${s}`;
}
if(minutes < 10) {
m = `0${m}`;
}
$("#countdown").html(`Abmeldung in ${m}:${s}<span class="fas fa-unlock-alt pl-1"></span>`);
}, 1000);
}
if(seconds < 10) {
s = `0${s}`;
}
calcPrependWidth();
const timePart = minutes <= 5 ? ` class="text-danger"` : "";
@{
var errorAlertMessage = TempData[TempDataConstants.ErrorAlertPopupMessage]?.ToString();
$("#countdown").html(`<span${timePart}>Abmeldung in ${m}:${s}<span class="fas fa-unlock-alt pl-1"></span></span>`);
}, 1000);
}
if(!string.IsNullOrWhiteSpace(errorAlertMessage))
{
<text>
$("#error-alert-popup").modal("show");
</text>
}
}
calcPrependWidth();
@{
var errorAlertMessage = TempData[TempDataConstants.ErrorAlertPopupMessage]?.ToString();
if(!string.IsNullOrWhiteSpace(errorAlertMessage))
{
<text>
$("#error-alert-popup").modal("show");
</text>
}
}
});
$(window).resize(function () {
$.each($("canvas"), function(index, canvasElement) {
updateCanvasSize($(canvasElement));
});
logSize();
calcPrependWidth();
});
@@ -321,17 +413,21 @@
}
function getMaxWidth(elementClassName) {
return Math.max.apply(Math, $(`.${elementClassName}`).map(function() { return $(this).width(); }).get());
return Math.max.apply(Math, $(`.${elementClassName}`).map(function() { return $(this).width(); }).get());
}
function getMaxElementHeight(elementClassName) {
return Math.max.apply(Math, $(`.${elementClassName}`).map(function () { return $(this).height(); }).get());
return Math.max.apply(Math, $(`.${elementClassName}`).map(function () { return $(this).height(); }).get());
}
function toggleMultiBookingForm(shouldDisable) {
$("#multi-booking-employees-button, #category-select, #leistung-select, #mb-start-date, #mb-end-date, #mb-start-time, #mb-end-time, #mb-duration, #mb-distance, textarea, #mb-reset-button, #mb-create-button, #mb-textbausteine-button, #mb-hours-minutes-dropdown-btn, #mb-marker-cb").prop("disabled", shouldDisable);
$("#multi-booking-employees-button, #category-select, #leistung-select, " +
"#mb-start-date-input, #mb-end-date-input, #mb-start-time-input, #mb-end-time-input, #mb-duration-input, " +
"#mb-distance-input, textarea, #mb-reset-button, #mb-create-button, " +
".mb-restore-btn, " +
"#mb-textbausteine-button, #mb-hours-minutes-dropdown-btn, #mb-marker-cb").prop("disabled", shouldDisable);
}
</script>
</script>
</head>
<body>
@@ -377,6 +473,13 @@
@if(Html.IsInDebugMode())
{
<li class="nav-item">
<button class="btn btn-link text-light no-underline" type="button" onclick="localStorage.clear(); logInfo2(`Der lokale Speicher wurde geleert`);">
<i class="fas fa-trash text-danger"></i>
Speicher leeren
</button>
</li>
using(Html.BeginForm("RedirectToDebuggingTools", "Main", FormMethod.Post))
{
<li class="nav-item">