Zeitberechnung überarbeitet. Diverse Bugs gefixt
This commit is contained in:
2022-09-07 13:19:08 +02:00
parent da7da608f3
commit 269f75fe41
20 changed files with 614 additions and 372 deletions

View File

@@ -683,7 +683,8 @@
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource CheckBoxConverter}" ConverterParameter="Mitarbeiter">
<Binding Path="EmployeeOid" Mode="OneWay" />
<Binding Path="SelectedEmployees" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type view:NewSchedulerView}}" />
<Binding Path="SelectedEmployees" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type view:NewSchedulerView}}" />
</MultiBinding>
</CheckBox.IsChecked>
@@ -868,7 +869,8 @@
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource CheckBoxConverter}" ConverterParameter="Ressourcen" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True">
<Binding Path="ResourceOid" Mode="OneWay" />
<Binding Path="SelectedResources" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type view:NewSchedulerView}}" />
<Binding Path="SelectedResources" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type view:NewSchedulerView}}" />
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>

View File

@@ -2031,7 +2031,9 @@ namespace BeWo.Scheduler.View
w.EmployeeList.Count > 0 && w.EmployeeList.Any(a => a.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)) ||
BeWoUtils.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen)) && (!w.EmployeeList.TrueForAll(e2a => e2a.ParticipationAnswer == ParticipationAnswer.Absage) || w.EmployeeList == null || w.EmployeeList.Count == 0)).ToList();
var editableAppointments = appointments.Where(w => w.CanBeEdited).ToList();
var anonymizedAppointments = appointments.Where(w => w.CanBeEdited == false && w.IsTask == false).ToList();
prefilteredAppointments.AddRangeIfElementsNotIn(anonymizedAppointments);
if(!IsTasksVisible)
{

View File

@@ -19,90 +19,90 @@
<converter:NewCalendarBackgroundConverter x:Key="NewCalendarBackgroundConverter" />
<bewoConverter:BoolVisibilityConverter x:Key="BoolVisibilityConverter" />
<bewoConverter:ParticipationBrushConverter x:Key="ParticipationBrushConverter" />
<localSchView:RemoveElementVisibilityConverter x:Key="RemoveElementVisibilityConverter" />
<localSchView:RemoveElementVisibilityConverter x:Key="RemoveElementVisibilityConverter" />
<localSchView:InformationVisibilityConverter x:Key="InformationVisibilityConverter" />
<Style x:Key="MultiSupportConceptSelectionControlStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" />
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" />
<Setter Property="Margin" Value="2,2,2,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border x:Name="ItemBorder" CornerRadius="5" MinHeight="25" Background="#FF000000">
<Border.OpacityMask>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#19000000" Offset="0" />
<GradientStop Color="#26000000" Offset="1" />
</LinearGradientBrush>
</Border.OpacityMask>
</Border>
<Style x:Key="MultiSupportConceptSelectionControlStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" />
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" />
<Setter Property="Margin" Value="2,2,2,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border x:Name="ItemBorder" CornerRadius="5" MinHeight="25" Background="#FF000000">
<Border.OpacityMask>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#19000000" Offset="0" />
<GradientStop Color="#26000000" Offset="1" />
</LinearGradientBrush>
</Border.OpacityMask>
</Border>
<Border x:Name="ItemContent" CornerRadius="5" MinHeight="25" Background="{StaticResource SupportConceptContentBrush}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,3,5,3" OpacityMask="{x:Null}" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border x:Name="ItemContent" CornerRadius="5" MinHeight="25" Background="{StaticResource SupportConceptContentBrush}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,3,5,3" OpacityMask="{x:Null}" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock x:Name="txtDetail1" Grid.Column="0" Grid.Row="0" Text="{Binding Path=CustomerName}" FontSize="12" Foreground="#FFD2D2D2" FontFamily="Microsoft Sans Serif" />
<TextBlock x:Name="txtDetail2" Grid.Column="0" Grid.Row="1" ToolTip="{Binding Path=FirstCostBearerDetailString}" Text="{Binding Path=FirstCostBearerDetailString}" FontSize="10" Foreground="{Binding ForegroundBrush}" FontFamily="Microsoft Sans Serif" />
<Button x:Name="btnRemoveSupportConcept" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Width="20" Height="20" ToolTip="Hilfeplan aus der Liste entfernen" Tag="{Binding}" Style="{DynamicResource CloseButtonStyle}" Click="BtnRemoveSupportConcept_Click" Margin="3,0,0,0" />
</Grid>
</Border>
</Grid>
<TextBlock x:Name="txtDetail1" Grid.Column="0" Grid.Row="0" Text="{Binding Path=CustomerName}" FontSize="12" Foreground="#FFD2D2D2" FontFamily="Microsoft Sans Serif" />
<TextBlock x:Name="txtDetail2" Grid.Column="0" Grid.Row="1" ToolTip="{Binding Path=FirstCostBearerDetailString}" Text="{Binding Path=FirstCostBearerDetailString}" FontSize="10" Foreground="{Binding ForegroundBrush}" FontFamily="Microsoft Sans Serif" />
<Button x:Name="btnRemoveSupportConcept" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Width="20" Height="20" ToolTip="Hilfeplan aus der Liste entfernen" Tag="{Binding}" Style="{DynamicResource CloseButtonStyle}" Click="BtnRemoveSupportConcept_Click" Margin="3,0,0,0" />
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsArchived}" Value="True">
<Setter Property="Foreground" TargetName="txtDetail1" Value="#FF808080" />
<Setter Property="Foreground" TargetName="txtDetail2" Value="#FF808080" />
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="OpacityMask" TargetName="ItemBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#33000000" Offset="0" />
<GradientStop Color="#66000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsArchived}" Value="True">
<Setter Property="Foreground" TargetName="txtDetail1" Value="#FF808080" />
<Setter Property="Foreground" TargetName="txtDetail2" Value="#FF808080" />
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="OpacityMask" TargetName="ItemBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#33000000" Offset="0" />
<GradientStop Color="#66000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ListBoxItem.IsSelected" Value="True">
<Setter Property="OpacityMask" TargetName="ItemBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#99000000" Offset="0" />
<GradientStop Color="#CC000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ListBoxItem.IsSelected" Value="True" />
<Condition Property="Selector.IsSelectionActive" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="OpacityMask" TargetName="ItemBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#99000000" Offset="0" />
<GradientStop Color="#B2000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Trigger Property="ListBoxItem.IsSelected" Value="True">
<Setter Property="OpacityMask" TargetName="ItemBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#99000000" Offset="0" />
<GradientStop Color="#CC000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ListBoxItem.IsSelected" Value="True" />
<Condition Property="Selector.IsSelectionActive" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="OpacityMask" TargetName="ItemBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#99000000" Offset="0" />
<GradientStop Color="#B2000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MultiElementSelectionControlStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" />

View File

@@ -1329,6 +1329,7 @@
<Content Include="Scripts\umd\popper.min.js" />
<Content Include="Scripts\utils\list-utils.js" />
<Content Include="Scripts\utils\resources-list-utils.js" />
<Content Include="Scripts\utils\service-record-time-calc.js" />
<Content Include="Scripts\utils\trimCanvas.js" />
<Content Include="Scripts\utils\dateUtils.js" />
<Content Include="Scripts\view-scripts\report.js" />

View File

@@ -68,7 +68,7 @@ namespace BeWoPlanerMobil.Controllers
}
[Authorize]
public ActionResult UpdateSettings(string pKey, string pValue)
public ActionResult UpdateApplicationSettings(string pKey, string pValue)
{
var userSettings = GetUser().Settings;
@@ -83,5 +83,20 @@ namespace BeWoPlanerMobil.Controllers
return RedirectToAction("Main");
}
[Authorize]
public void UpdateUserSettingsWithoutReload(string key, string value)
{
var userSettings = GetUser().Settings;
UserSettingsUtils.SetSettingValue(SettingsType.ApplicationSettings, key, value, userSettings);
var loggedInUser = GetUser();
if(loggedInUser?.UserOid.HasValue ?? false)
{
UserService.UpdateUserSettings(loggedInUser.UserOid.Value, userSettings);
}
}
}
}

View File

@@ -162,7 +162,7 @@ namespace BeWoPlanerMobil.Controllers
customerFilter = CustomerFilterEnum.MyCustomer;
}
UpdateSettings(SettingsKeys.CustomerFilterCustomers, customerFilter.ToString());
UpdateApplicationSettings(SettingsKeys.CustomerFilterCustomers, customerFilter.ToString());
return RedirectToActionPermanent("Customer");
}

View File

@@ -94,6 +94,8 @@ namespace BeWoPlanerMobil.Controllers
var mandator = GetMandator();
var mandatorSettings = mandator.Settings;
Model.SetStartTimeToEndTimeAfterSave = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.SetStartTimeToEndTimeAfterSave);
var userSettings = AbstractModel.UserSettings;
Model.ShowExpiredSupportConcepts = UserSettingsUtils.GetSettingValueAsBool(userSettings, SettingsKeys.ShowExpiredSupportConcepts);
@@ -253,6 +255,12 @@ namespace BeWoPlanerMobil.Controllers
Model.IsEndDateVisible = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.IsEndDateVisible);
Model.IsZeiterfassungInStdMin = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.IsZeiterfassungInStdMin);
if(Model.IsZeiterfassungInStdMin)
{
var x = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.LetzteZeiterfassungsDauer);
Model.IsShowingDurationInHours = x == 1;
}
}
catch(Exception e)
{
@@ -319,7 +327,7 @@ namespace BeWoPlanerMobil.Controllers
Model.ShowExpiredSupportConcepts = newValue;
return UpdateSettings(SettingsKeys.ShowExpiredSupportConcepts, newValue ? "1" : "0");
return UpdateApplicationSettings(SettingsKeys.ShowExpiredSupportConcepts, newValue ? "1" : "0");
}
[HttpPost]
@@ -457,7 +465,7 @@ namespace BeWoPlanerMobil.Controllers
return goalTree;
}
private void SortGoals(GoalTreeItem goalTreeItem)
private static void SortGoals(GoalTreeItem goalTreeItem)
{
goalTreeItem.Children = goalTreeItem.Children.OrderBy(s => s.ValueListEntryOid).ToList();
foreach(var test in goalTreeItem.Children)
@@ -916,14 +924,13 @@ namespace BeWoPlanerMobil.Controllers
}
Model.NewServiceRecord.IP = Request.UserHostAddress;
// ToDo: Funktioniert noch nicht zu 100 %
Model.NewServiceRecord.Goals = Model.SelectedGoals;
Model.NewServiceRecord.Start = zeitenFeld[0];
Model.NewServiceRecord.End = zeitenFeld[1];
Model.NewServiceRecord.DistanceInMeter = distanceInMeters;
if(Model.Employee.EmployeeOid != null)
if(Model.Employee.EmployeeOid.HasValue)
{
if(!Model.IsInEditingMode)
{
@@ -931,7 +938,7 @@ namespace BeWoPlanerMobil.Controllers
}
else
{
if(Model.SelectedEmployee != null)
if(!(Model.SelectedEmployee is null))
{
Model.NewServiceRecord.Employee = Model.SelectedEmployee;
}
@@ -939,9 +946,9 @@ namespace BeWoPlanerMobil.Controllers
var sc = Model.SupportConcepts.FirstOrDefault(fod => fod.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && a.CostBearer2SupportConceptOid.Value.Equals(selectedCostbearerSCRelOid)));
if(sc != null)
if(!(sc is null))
{
if(sc.SupportConceptOid != null)
if(sc.SupportConceptOid.HasValue)
{
Model.NewServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(sc.SupportConceptOid.Value, Model.Employee.EmployeeOid);
}
@@ -1028,6 +1035,20 @@ namespace BeWoPlanerMobil.Controllers
OperationsService.UpdateServiceRecords(new List<ServiceRecordDC> { Model.NewServiceRecord });
}
if(Model.SetStartTimeToEndTimeAfterSave)
{
var previousStartDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.Start : Model.NewServiceRecord?.Start;
var previousEndDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.End : Model.NewServiceRecord?.End;
if(!(previousStartDate is null) && !(previousEndDate is null))
{
var duration = (previousEndDate - previousStartDate).Value.TotalMinutes;
Model.NewStartDate = previousEndDate;
Model.NewEndDate = previousEndDate.Value.AddMinutes(duration);
}
}
Model.NewServiceRecord = new ServiceRecordDC();
if(selectedCostbearerSCRelOid.HasValue)
@@ -2353,6 +2374,8 @@ namespace BeWoPlanerMobil.Controllers
Model.SelectedServiceCategoryOid = firstServiceDescription.Category.ServiceCategoryOid;
}
return RedirectToActionPermanent("Main");
}
@@ -2522,7 +2545,7 @@ namespace BeWoPlanerMobil.Controllers
customerFilter = CustomerFilterEnum.MyCustomer;
}
UpdateSettings(SettingsKeys.CustomerFilterInZeiterfassung, customerFilter.ToString());
UpdateApplicationSettings(SettingsKeys.CustomerFilterInZeiterfassung, customerFilter.ToString());
return RedirectToActionPermanent("Main");
}
@@ -2662,19 +2685,19 @@ namespace BeWoPlanerMobil.Controllers
Model.NewServiceRecord.DistanceInMeter = distanceInMeters;
if(Model.Employee.EmployeeOid != null)
if(Model.Employee.EmployeeOid.HasValue)
{
if(Model.SelectedEmployee != null)
if(!(Model.SelectedEmployee is null))
{
Model.NewServiceRecord.Employee = Model.SelectedEmployee;
}
var sc = Model.SupportConcepts.FirstOrDefault(fod => fod.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && a.CostBearer2SupportConceptOid.Value.Equals(selectedCostbearer2SupportConceptRelOid)));
if(sc != null)
if(!(sc is null))
{
if(sc.SupportConceptOid != null)
if(sc.SupportConceptOid.HasValue)
{
Model.NewServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(sc.SupportConceptOid.Value, Model.Employee.EmployeeOid);
}
@@ -2739,6 +2762,19 @@ namespace BeWoPlanerMobil.Controllers
Model.NewServiceRecord.InsUser = $"{MobileSessionFacade.LoggedInEmployee.FirstName} {MobileSessionFacade.LoggedInEmployee.LastName}";
Model.NewServiceRecord.IsCreatedInMobileClient = true;
if(Model.SetStartTimeToEndTimeAfterSave)
{
var previousStartDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.Start : Model.NewServiceRecord?.Start;
var previousEndDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.End : Model.NewServiceRecord?.End;
if(!(previousStartDate is null) && !(previousEndDate is null))
{
var duration = (previousEndDate - previousStartDate).Value.TotalMinutes;
Model.NewStartDate = previousEndDate;
Model.NewEndDate = previousEndDate.Value.AddMinutes(duration);
}
}
return Model.IsInEditingMode ? UpdateGroupBooking() : SaveGroupBooking();
}
@@ -2749,5 +2785,21 @@ namespace BeWoPlanerMobil.Controllers
return ResetEditingMode();
}
[Authorize]
public string ToggleDurationUnit(bool isInHoursMode)
{
if(Model is null)
{
Logout();
return _LeerzeichenFuerGetMethoden;
}
Model.IsShowingDurationInHours = isInHoursMode;
UpdateUserSettingsWithoutReload(SettingsKeys.LetzteZeiterfassungsDauer, Model.IsShowingDurationInHours ? "1" : "0");
return _LeerzeichenFuerGetMethoden;
}
}
}

View File

@@ -587,6 +587,59 @@ namespace BeWoPlanerMobil.Models
public List<GoalTreeItem> GoalTree { get; set; } = new List<GoalTreeItem>();
public List<TextbausteinDisplayItem> AllTextModules { get; set; } = new List<TextbausteinDisplayItem>();
public bool SetStartTimeToEndTimeAfterSave { get; set; }
public DateTime? NewStartDate { get; set; }
public string NewStartTime
{
get
{
var start = NewStartDate;
if(start.HasValue && !start.Value.GetServiceRecordNoDateTimeDate().Equals(start))
{
return start.Value.ToString("HH:mm");
}
return string.Empty;
}
}
public string NewStartDateStr => NewStartDate?.ToShortDateString();
public DateTime? NewEndDate { get; set; }
public string NewEndTime
{
get
{
var start = NewEndDate;
if(start != null && !start.Value.GetServiceRecordNoDateTimeDate().Equals(start))
{
return start.Value.ToString("HH:mm");
}
return string.Empty;
}
}
public string NewEndDateStr => NewEndDate?.ToShortDateString();
public int? NewDuration
{
get
{
if(NewStartDate.HasValue && NewEndDate.HasValue)
{
return (int?) (NewEndDate.Value - NewStartDate.Value).TotalMinutes;
}
return null;
}
}
public bool IsShowingDurationInHours { get; set; }
public string SelectedDurationUnit => IsShowingDurationInHours ? "Stunden" : "Minuten";
}
public class CustomSelectListItem

View File

@@ -317,7 +317,7 @@ function showCollapsable(collapsableElement) {
collapsableElement.addClass("show");
}
} catch (error) {
logError(error.message);
logError(error);
}
}
@@ -335,3 +335,79 @@ function hideCollapsable(collapsableElement) {
}
}
function treeSearchOnChange(searchInputId, textClass, cardClass, nameLabelClass, itemListClass) {
try {
var text = $("#" + searchInputId).val().toLowerCase();
var entries = $("." + textClass);
if (text.length === 0 || !text.replace(/\s\g/, '').length) {
resetTreeSearch(searchInputId, textClass, cardClass);
return;
}
$.each(entries, function (index, entry) {
var checkbox = $(entry);
var treeCard = checkbox.closest("." + cardClass);
var header = treeCard.find("h5");
var list = treeCard.find(".collapse");
var treeItemName = checkbox.find("." + nameLabelClass).text().toLowerCase();
var includesText = treeItemName.includes(text) || header.html().toLowerCase().includes(text);
if (includesText) {
checkbox.show();
treeCard.show();
showCollapsable($(list));
} else {
checkbox.hide();
}
});
var lists = $("." + itemListClass);
var cardsToHide = [];
$.each(lists, function (index, item) {
var children = $(item).children();
var hasAtLeastOneVisibleChild = false;
var card = $(item).parent().parent();
for (var i = 0; i < children.length; i++) {
var child = children[i];
hasAtLeastOneVisibleChild = $(child).css("display") === "block";
if (hasAtLeastOneVisibleChild === true) {
break;
}
}
if (hasAtLeastOneVisibleChild === false) {
cardsToHide.push(card);
}
});
$.each(cardsToHide, function (index, item) {
$(item).hide();
});
} catch (error) {
logError(error);
}
}
function resetTreeSearch(searchInputId, textClass, cardClass) {
try {
$("#" + searchInputId).val("");
var entries = $("." + textClass);
var treeCard = $("." + cardClass);
var collapsable = treeCard.find(".collapse");
entries.show();
treeCard.show();
hideCollapsable(collapsable);
} catch (error) {
logError(error);
}
}

View File

@@ -0,0 +1,153 @@
function calculateTimeWithDuration(timeInputValue, timeElement, startDate, duration) {
var hoursToMinutes = parseTimeInputToIntegerArray(timeInputValue);
var hours = parseInt(hoursToMinutes[0]);
var minutes = parseInt(hoursToMinutes[1]);
startDate.hours(hours);
startDate.minutes(minutes);
var durationFormat = $("#hours-minutes-dropdown-btn").length && $("#hours-minutes-dropdown-btn").text().replaceAll(/\s/g, "") === "Stunden" ? "h" : "m";
startDate.add(duration, durationFormat);
timeInputValue = startDate.format("HH:mm");
timeElement.val(timeInputValue);
}
function onDurationChange() {
var startTime = $("#start-time").val();
var endTime = $("#end-time").val();
var duration = $("#duration").val();
var hoursMinutesDropdownButton = $("#hours-minutes-dropdown-btn");
var hoursMinutesText = hoursMinutesDropdownButton.length ? hoursMinutesDropdownButton.text().replaceAll(/\s/g, "") : "";
var startTimeCondition = startTime !== undefined && startTime !== null && startTime.length > 0;
var endTimeCondition = endTime !== undefined && endTime !== null && endTime.length > 0;
var durationNumber = parseFloat(duration.replace(",", "."));
var durationCondition = !isNaN(durationNumber);
if ((false === startTimeCondition && false === endTimeCondition) || durationCondition === false) {
return;
}
var startDateString = $("#start-date-picker").datetimepicker("date");
var endDate = moment(new Date());
var startDate = moment(new Date());
if (startDateString.length !== 0) {
startDate = moment(startDateString);
endDate = startDate.clone();
}
if ($("#end-date-picker").length !== 0) {
var endDateString = $("#end-date-picker").datetimepicker("date");
endDate = moment(endDateString);
}
var h2m = [0, 0];
var durationFormat = hoursMinutesText === "Stunden" ? "h" : "m";
if (startTimeCondition === true) {
h2m = parseTimeInputToIntegerArray(startTime);
startDate = startDate.hours(h2m[0]).minutes(h2m[1]);
endDate = startDate.clone().add(durationNumber, durationFormat);
$("#end-time").val(endDate.format("HH:mm"));
$("#end-date").val(endDate.format("DD.MM.yyyy"));
} else {
h2m = parseTimeInputToIntegerArray(endTime);
endDate = endDate.hours(h2m[0]).minutes(h2m[1]);
startDate = endDate.clone().add(durationNumber * -1, durationFormat);
$("#start-time").val(startDate.format("HH:mm"));
$("#start-date").val(startDate.format("DD.MM.yyyy"));
}
}
function calculateDuration(isInvocatedByHoursMinutesButton) {
var startTime = $("#start-time").val();
var endTime = $("#end-time").val();
var duration = $("#duration").val();
var hoursMinutesDropdownButton = $("#hours-minutes-dropdown-btn");
var hoursMinutesText = hoursMinutesDropdownButton.length ?
hoursMinutesDropdownButton.text().replaceAll(/\s/g, "") :
"";
if ((startTime.length > 0 && startTime.length < 5) || (endTime.length > 0 && endTime.length < 5)) {
return;
}
var startTimeCondition = startTime !== undefined && startTime !== null && startTime.length > 0;
var endTimeCondition = endTime !== undefined && endTime !== null && endTime.length > 0;
var durationNumber = parseFloat(duration.replace(",", "."));
var durationCondition = !isNaN(durationNumber);
var startDateString = $("#start-date-picker").datetimepicker("date");
var endDate = moment(new Date());
var startDate = moment(new Date());
if (startDateString !== null && startDateString.length !== 0) {
startDate = moment(startDateString);
endDate = startDate.clone();
}
// Es gibt ein Enddatumsfeld
if ($("#end-date-picker").length !== 0) {
var endDateString = $("#end-date-picker").datetimepicker("date");
if (endDateString !== null && endDateString.length !== 0) {
endDate = moment(endDateString);
}
}
var newDurationValue = 0;
if (startTimeCondition && endTimeCondition && isInvocatedByHoursMinutesButton === false) {
var startHHmm = parseTimeInputToIntegerArray(startTime);
var endHHmm = parseTimeInputToIntegerArray(endTime);
startDate.hours(startHHmm[0]);
startDate.minutes(startHHmm[1]);
endDate.hours(endHHmm[0]);
endDate.minutes(endHHmm[1]);
var momentDuration = moment.duration(endDate.diff(startDate));
if (hoursMinutesDropdownButton.length && hoursMinutesText === "Stunden") {
newDurationValue = momentDuration.asHours();
} else {
newDurationValue = momentDuration.asMinutes();
}
$("#duration").val(newDurationValue);
} else if (startTimeCondition && durationCondition) {
if (hoursMinutesDropdownButton.length) {
if (hoursMinutesText === "Stunden") {
durationNumber /= 60;
} else {
durationNumber *= 60;
}
$("#duration").val(durationNumber);
}
calculateTimeWithDuration(startTime, $("#end-time"), startDate, durationNumber);
} else if (endTimeCondition && durationCondition) {
if (hoursMinutesDropdownButton.length) {
if (hoursMinutesText === "Stunden") {
durationNumber /= 60;
} else {
durationNumber *= 60;
}
$("#duration").val(durationNumber);
}
calculateTimeWithDuration(endTime, $("#start-time"), startDate, durationNumber * -1);
}
}

View File

@@ -36,137 +36,6 @@ function showAlertMessage(message) {
$("#form-alert").show();
}
function calculateDuration(isInvocatedByHoursMinutesButton) {
var startTime = $("#start-time").val();
var endTime = $("#end-time").val();
var duration = $("#duration").val();
var hoursMinutesDropdownButton = $("#hours-minutes-dropdown-btn");
if((startTime.length > 0 && startTime.length < 5) || (endTime.length > 0 && endTime.length < 5)) {
return;
}
var startTimeCondition = startTime !== undefined && startTime !== null && startTime.length > 0;
var endTimeCondition = endTime !== undefined && endTime !== null && endTime.length > 0;
var durationNumber = hoursMinutesDropdownButton.length && hoursMinutesDropdownButton.text() === "Stunden" ? parseFloat(duration.replace(",", ".")) : parseInt(duration, 10);
var durationCondition = !isNaN(durationNumber);
var startDateString = $("#start-date-picker").datetimepicker("date");
var endDate = moment(new Date());
var startDate = moment(new Date());
if(startDateString.length !== 0) {
startDate = moment(startDateString);
endDate = startDate.clone();
}
// Es gibt ein Enddatumsfeld
if ($("#end-date-picker").length !== 0) {
var endDateString = $("#end-date-picker").datetimepicker("date");
if (endDateString.length !== 0) {
endDate = moment(endDateString);
}
}
var newDurationValue = 0;
if(startTimeCondition && endTimeCondition && isInvocatedByHoursMinutesButton === false) {
var startHHmm = parseTimeInputToIntegerArray(startTime);
var endHHmm = parseTimeInputToIntegerArray(endTime);
startDate.hours(startHHmm[0]);
startDate.minutes(startHHmm[1]);
endDate.hours(endHHmm[0]);
endDate.minutes(endHHmm[1]);
var momentDuration = moment.duration(endDate.diff(startDate));
if (hoursMinutesDropdownButton.length && hoursMinutesDropdownButton.text() === "Stunden") {
newDurationValue = momentDuration.asHours();
} else {
newDurationValue = momentDuration.asMinutes();
}
$("#duration").val(newDurationValue);
} else if(startTimeCondition && durationCondition) {
if(hoursMinutesDropdownButton.length && hoursMinutesDropdownButton.text() === "Stunden") {
durationNumber *= 60;
}
calculateTimeWithDuration(startTime, $("#end-time"), startDate, durationNumber);
} else if(endTimeCondition && durationCondition) {
if(hoursMinutesDropdownButton.length && hoursMinutesDropdownButton.text() === "Stunden") {
durationNumber *= 60;
}
calculateTimeWithDuration(endTime, $("#start-time"), startDate, durationNumber * -1);
}
}
function onDurationChange() {
var startTime = $("#start-time").val();
var endTime = $("#end-time").val();
var duration = $("#duration").val();
var hoursMinutesDropdownButton = $("#hours-minutes-dropdown-btn");
var startTimeCondition = startTime !== undefined && startTime !== null && startTime.length > 0;
var endTimeCondition = endTime !== undefined && endTime !== null && endTime.length > 0;
var durationNumber = hoursMinutesDropdownButton.length && hoursMinutesDropdownButton.text() === "Stunden" ? parseFloat(duration.replace(",", ".")) : parseInt(duration, 10);
var durationCondition = !isNaN(durationNumber);
if((false === startTimeCondition && false === endTimeCondition) || durationCondition === false) {
return;
}
var startDateString = $("#start-date-picker").datetimepicker("date");
var endDate = moment(new Date());
var startDate = moment(new Date());
if (startDateString.length !== 0) {
startDate = moment(startDateString);
endDate = startDate.clone();
}
if ($("#end-date-picker").length !== 0) {
var endDateString = $("#end-date-picker").datetimepicker("date");
endDate = moment(endDateString);
}
var h2m = [0, 0];
if(hoursMinutesDropdownButton.length && hoursMinutesDropdownButton.text() === "Stunden") {
durationNumber *= 60;
}
if (startTimeCondition === true) {
h2m = parseTimeInputToIntegerArray(startTime);
startDate.hours(h2m[0]).minutes(h2m[1]).add(durationNumber, "m");
$("#end-time").val(startDate.format("HH:mm"));
} else {
h2m = parseTimeInputToIntegerArray(endTime);
endDate.hours(h2m[0]).minutes(h2m[1]).add(durationNumber * -1, "m");
$("#start-time").val(endDate.format("HH:mm"));
}
}
function calculateTimeWithDuration(timeInputValue, timeElement, startDate, duration) {
var hoursToMinutes = parseTimeInputToIntegerArray(timeInputValue);
var hours = parseInt(hoursToMinutes[0]);
var minutes = parseInt(hoursToMinutes[1]);
startDate.hours(hours);
startDate.minutes(minutes);
startDate.add(duration, "m");
timeInputValue = startDate.format("HH:mm");
timeElement.val(timeInputValue);
}
function resetCreateForm() {
$("#serviceRecordCreationForm").trigger("reset");
@@ -232,11 +101,11 @@ function submitGroupBookingForm() {
}
function deactivateGroupBookingForm() {
$("#employees-button, #category-select, #leistung-select, #start-date, #end-date, #start-time, #end-time, #duration, #distance, textarea, #reset-button, #create-button, #textbausteine-button").prop("disabled", 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").prop("disabled", true);
}
function activateGroupBookingForm() {
$("#employees-button, #category-select, #leistung-select, #start-date, #end-date, #start-time, #end-time, #duration, #distance, textarea, #reset-button, #create-button, #textbausteine-button").prop("disabled", false);
$("#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").prop("disabled", false);
}
function deleteServiceRecord(serviceRecordOid) {
@@ -455,7 +324,6 @@ function getCheckedGoals() {
return selectedGoals.substr(0, selectedGoals.length - 1);
}
// ToDo: Durch RenderAction ersetzen
function updateSelectedGoals() {
var selectedGoals = getCheckedGoals();
@@ -474,6 +342,7 @@ function checkNumberInput(inputId) {
return isNum;
}
// Wird bei der Validierung des Formulars benutzt
function getStartAndEndDate() {
var startTimePicker = $("#start-time-picker");
var endTimePicker = $("#end-time-picker");
@@ -537,17 +406,6 @@ function getStartAndEndDate() {
return [startDate, endDate];
}
function toggleHoursMinutesDropdownButton(element) {
var hoursMinutesDropdownButton = $("#hours-minutes-dropdown-btn");
var buttonText = $(element).text();
hoursMinutesDropdownButton.text(buttonText);
setInputFilter();
calculateDuration(true);
}
function textCategoryOnClick(categoryId) {
var childrenContainer = $("#" + categoryId + "-children-container");
var iconSpan = $("#" + categoryId + "-icon-span");

View File

@@ -251,82 +251,4 @@ function resetSearch(searchInputId, entryClass) {
} catch (error) {
logError(error.message);
}
}
function resourceSearchOnChange(searchInputId) {
try {
var text = $("#" + searchInputId).val().toLowerCase();
var entries = $(".resource-text");
if (text.length === 0 || !text.replace(/\s\g/, '').length) {
resetResourceSearch(searchInputId);
return;
}
$.each(entries, function (index, entry) {
var checkbox = $(entry);
var categoryCard = checkbox.closest(".category-card");
var list = categoryCard.find(".collapse");
var resourceName = checkbox.find(".resource-name-label").text().toLowerCase();
var includesText = resourceName.includes(text);
if (includesText) {
checkbox.show();
categoryCard.show();
showCollapsable($(list));
} else {
checkbox.hide();
}
});
var lists = $(".resource-list");
var cardsToHide = [];
$.each(lists, function (index, item) {
var children = $(item).children();
var hasAtLeastOneVisibleChild = false;
var card = $(item).parent().parent();
for (var i = 0; i < children.length; i++) {
var child = children[i];
hasAtLeastOneVisibleChild = $(child).css("display") === "block";
if (hasAtLeastOneVisibleChild === true) {
break;
}
}
if (hasAtLeastOneVisibleChild === false) {
cardsToHide.push(card);
}
});
$.each(cardsToHide, function (index, item) {
$(item).hide();
});
} catch (error) {
logError(error.message);
}
}
function resetResourceSearch(searchInputId) {
try {
logDebug("reset resource search: " + searchInputId);
$("#" + searchInputId).val("");
var entries = $(".resource-text");
var categoryCard = $(".category-card");
var collapsable = categoryCard.find(".collapse");
entries.show();
categoryCard.show();
hideCollapsable(collapsable);
} catch(error) {
logError(error.message);
}
}

View File

@@ -7,17 +7,17 @@
{
if(!goalTreeItem.IsLeaf) // Ziel
{
<div class="card w-100 mb-3" id="c-@goalTreeItem.ValueListEntryOid">
<div class="card w-100 mb-3 goal-card" id="c-@goalTreeItem.ValueListEntryOid">
<div class="card-header px-2" data-toggle="collapse" data-target="#collapsable-goal-tree-branch-@goalTreeItem.ValueListEntryOid">
<div class="d-flex align-items-center">
<h5 class="mr-auto">@goalTreeItem.Header</h5>
<h5 class="mr-auto goal-card-header">@goalTreeItem.Header</h5>
<div class="btn-group" role="group">
<span class="fas fa-chevron-down text-primary"></span>
</div>
</div>
</div>
<div class="collapse" id="collapsable-goal-tree-branch-@goalTreeItem.ValueListEntryOid">
<div class="card-body p-1">
<div class="card-body p-1 goal-list">
@foreach(var child in goalTreeItem.Children)
{
@BuildGoalTreeBranch(child)
@@ -43,9 +43,9 @@
}
}
<div class="custom-control custom-checkbox">
<div class="custom-control custom-checkbox goal-text">
<input type="checkbox" class="custom-control-input" id="@goalTreeItem.ValueListEntryOid" @isCheckedValue onchange="updateSelectedGoals()">
<label for="@goalTreeItem.ValueListEntryOid" class="custom-control-label">@goalTreeItem.Header</label>
<label for="@goalTreeItem.ValueListEntryOid" class="custom-control-label goal-name-label">@goalTreeItem.Header</label>
<span id="goal-rating-@goalTreeItem.ValueListEntryOid" class="badge badge-bewo-goal-rating goal-rating-badge ml-1" onclick="showGoalRatingPopup(@goalTreeItem.ValueListEntryOid)">
@(ratingType?.DisplayName ?? goalTreeItem.RatingName)
</span>

View File

@@ -1,6 +1,32 @@
@using BeWoPlanerMobil.Models
@model BeWoPlanerMobil.Models.MainModel
<script>
$(document).ready(function () {
$("#hours-minutes-dropdown-btn").on("click", function() {
$("#hours-minutes-dropdown-btn").data("text", $("#hours-minutes-dropdown-btn").text().replaceAll(/\s/g, ""));
});
$(".hours-minutes-link").on("click", function () {
var previousText = $("#hours-minutes-dropdown-btn").data("text");
var currentText = $(this).text().replaceAll(/\s/g, "");
if(previousText === currentText) {
return;
}
var buttonText = $(this).text();
$("#hours-minutes-dropdown-btn").text(buttonText);
setInputFilter();
$.get('@Url.Action("ToggleDurationUnit")', { isInHoursMode: buttonText === "Stunden" });
calculateDuration(true);
});
});
</script>
<div class="row">
<div class="col col-12">
@if(Model != null)
@@ -133,11 +159,35 @@
</div>
<div class="form-row">
@{
var startTimeValue = Model.StartTimeToEdit;
var endTimeValue = Model.EndTimeToEdit;
// ToDo: Berechnen!
var divisor = Model.SelectedDurationUnit == "Stunden" ? 60 : 1;
var durationValue = "0";
if(!(Model.SelectedServiceRecord is null))
{
durationValue = (Model.SelectedServiceRecord?.RoundedDuration / divisor).ToString();
}
if(Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode)
{
startTimeValue = Model.NewStartTime;
endTimeValue = Model.NewEndTime;
if(Model.NewDuration.HasValue)
{
durationValue = (Model.NewDuration / divisor).ToString();
}
}
}
<div class="col-md">
<div class="form-group mb-1">
<label for="start-time">Von</label>
<div class="input-group date" id="start-time-picker" data-target-input="nearest">
<input type="text" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@startTime" />
<input type="text" 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>
@@ -148,7 +198,7 @@
<div class="form-group mb-1">
<label for="end-time">Bis</label>
<div class="input-group date" id="end-time-picker" data-target-input="nearest">
<input type="text" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@endTime" />
<input type="text" 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>
@@ -161,21 +211,22 @@
<div class="col-md">
<div class="form-group mb-1">
<label for="duration">Dauer</label>
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@duration">
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@durationValue">
</div>
</div>
@if (Model.IsZeiterfassungInStdMin)
{
@* ToDo: Ist disabled *@
<div class="col-md">
<div class="form-group mb-1">
<label for="hours-minutes-dropdown-btn">Minuten/Stunden</label>
<div class="dropdown">
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
Minuten
@Model.SelectedDurationUnit
</button>
<div class="dropdown-menu w-100">
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Minuten</a>
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Stunden</a>
<a class="dropdown-item hours-minutes-link" href="#">Minuten</a>
<a class="dropdown-item hours-minutes-link" href="#">Stunden</a>
</div>
</div>
</div>

View File

@@ -59,19 +59,6 @@
$.get(getSetServiceDescriptionUrl(), { pServiceDescriptionOid: selectedOid });
}
// TODO: Hier load vom Textbausteinecontainer aufrufen!
//$.get(getLoadTextbausteineForServiceCategoryUrl(), { pServiceCategoryOid: selectedCategoryOid }).done(function(result) {
// if(result.length <= 2) {
// $("#textmodule-container").hide();
// return;
// }
// $("#textmodule-container").show();
// $("#tree").html(result);
//});
$("#textmodule-container").show();
$("#tree").load('@Url.Action("LoadUpToDateTextModules")');
});
@@ -106,12 +93,17 @@
var isSupportConceptSelected = supportConceptOid !== -1;
$("#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").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").prop("disabled", (isSupportConceptSelected ? false : true));
if(getIsInGroupBookingMode()) {
var 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").prop("disabled", (hasSelectedSupportConcepts ? false : 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").prop("disabled", (hasSelectedSupportConcepts ? false : true));
}
loadServiceDescriptions();
@@ -250,10 +242,6 @@
return "@Url.Action("SetServiceDescription")";
}
function getLoadTextbausteineForServiceCategoryUrl() {
return "@Url.Action("LoadTextbausteineForServiceCategory")";
}
function getLoadCompleteTextbausteinByOidUrl() {
return "@Url.Action("LoadCompleteTextbausteinByOid")";
}
@@ -401,7 +389,6 @@
</div>
<!-- Textbausteine-Popup-->
<!-- ToDo: Durch Partial/RenderAction ersetzen -->
<div class="modal" tabindex="-1" role="dialog" id="textbausteine-popup">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-content">

View File

@@ -2,6 +2,32 @@
@using BeWoPlanerMobil.Util
@model MainModel
<script>
$(document).ready(function () {
$("#hours-minutes-dropdown-btn").on("click", function() {
$("#hours-minutes-dropdown-btn").data("text", $("#hours-minutes-dropdown-btn").text().replaceAll(/\s/g, ""));
});
$(".hours-minutes-link").on("click", function () {
var previousText = $("#hours-minutes-dropdown-btn").data("text");
var currentText = $(this).text().replaceAll(/\s/g, "");
if(previousText === currentText) {
return;
}
var buttonText = $(this).text();
$("#hours-minutes-dropdown-btn").text(buttonText);
setInputFilter();
$.get('@Url.Action("ToggleDurationUnit")', { isInHoursMode: buttonText === "Stunden" });
calculateDuration(true);
});
});
</script>
<div class="row">
<!-- Einzelbuchungsformular -->
<div class="col col-12 col-md-5">
@@ -168,11 +194,28 @@
</div>
<div class="form-row">
<!-- Einzelbuchung: Von -->
@{
var startTimeValue = Model.StartTimeToEdit;
var endTimeValue = Model.EndTimeToEdit;
var divisor = Model.SelectedDurationUnit == "Stunden" ? 60 : 1;
var durationValue = Model.DurationToEdit;
if(Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode)
{
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 mb-1">
<label for="start-time">Von</label>
<div class="input-group date" id="start-time-picker" data-target-input="nearest">
<input type="text" id="start-time" name="Start" class="form-control datetimepicker-input" data-target="#start-time-picker" value="@Model.StartTimeToEdit" />
<input type="text" 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>
@@ -184,7 +227,7 @@
<div class="form-group mb-1">
<label for="end-time">Bis</label>
<div class="input-group date" id="end-time-picker" data-target-input="nearest">
<input type="text" id="end-time" name="Ende" class="form-control datetimepicker-input" data-target="#end-time-picker" value="@Model.EndTimeToEdit" />
<input type="text" 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>
@@ -197,7 +240,7 @@
<div class="col-md">
<div class="form-group mb-1">
<label for="duration">Dauer</label>
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@Model.DurationToEdit">
<input type="text" class="form-control" id="duration" name="Dauer" onchange="onDurationChange()" value="@durationValue">
</div>
</div>
@if(Model.IsZeiterfassungInStdMin)
@@ -207,11 +250,11 @@
<label for="hours-minutes-dropdown-btn">Minuten/Stunden</label>
<div class="dropdown">
<button id="hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
Minuten
@Model.SelectedDurationUnit
</button>
<div class="dropdown-menu w-100">
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Minuten</a>
<a class="dropdown-item" href="#" onclick="toggleHoursMinutesDropdownButton(this)">Stunden</a>
<a class="dropdown-item hours-minutes-link" href="#">Minuten</a>
<a class="dropdown-item hours-minutes-link" href="#">Stunden</a>
</div>
</div>
</div>
@@ -565,18 +608,27 @@
}
</div>
<!-- /Liste mit den Einträgen und dem Auswahl-Select -->
<!-- Ziele und Maßnahmen Popup -->
<div class="modal" tabindex="-1" role="dialog" id="goal-popup">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
<h6 class="modal-title">Ziele und Maßnahmen</h6>
<button type="button" class="close" data-dismiss="modal">
<button type="button" class="close" data-dismiss="modal" onclick="resetTreeSearch('goal-search-input', 'goal-text', 'goal-card')">
<span>&times;</span>
</button>
</div>
<div class="modal-body pb-0">
<div class="container-fluid">
<div class="input-group mb-3">
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="treeSearchOnChange('goal-search-input', 'goal-text', 'goal-card', 'goal-name-label', 'goal-list')" id="goal-search-input" />
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" onclick="resetTreeSearch('goal-search-input', 'goal-text', 'goal-card')">
<span class="fas fa-times-circle"></span>
</button>
</div>
</div>
</div>
<div id="goals-tree">
@Html.Partial("GoalTreePartial", Model)
</div>

View File

@@ -254,16 +254,16 @@
<div class="modal-content">
<div class="modal-header">
<h6 class="modal-title text-center w-100">Ressourcen</h6>
<button type="button" class="close" data-dismiss="modal" onclick="resetResourceSearch('resource-search-input')">
<button type="button" class="close" data-dismiss="modal" onclick="resetTreeSearch('resource-search-input', 'resource-text', 'category-card')">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="input-group mb-3">
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="resourceSearchOnChange('resource-search-input')" id="resource-search-input" />
<input class="form-control w-100" type="text" placeholder="Suchen..." oninput="treeSearchOnChange('resource-search-input', 'resource-text', 'category-card', 'resource-name-label', 'resource-list')" id="resource-search-input" />
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" onclick="resetResourceSearch('resource-search-input')">
<button class="btn btn-outline-secondary" type="button" onclick="resetTreeSearch('resource-search-input', 'resource-text', 'category-card')">
<span class="fas fa-times-circle"></span>
</button>
</div>

View File

@@ -29,7 +29,7 @@
<script src="~/Scripts/moment.min.js"></script>
<script src="~/Scripts/locale/de.js?v=1.11"></script>
<script src="~/Scripts/group-booking.js?v=1.11"></script>
<script src="~/Scripts/view-scripts/main.js?v=1.11"></script>
<script src="~/Scripts/view-scripts/main.js?v=1.13"></script>
<script src="~/Scripts/signature.js?v=1.11"></script>
<script src="~/Scripts/tempusdominus-boostrap-4.min.js"></script>
<link rel="stylesheet" href="~/Content/tempusdominus-bootstrap-4.min.css" />
@@ -43,6 +43,7 @@
<script src="~/Scripts/utils/trimCanvas.js?v=1.11"></script>
<script src="~/Scripts/utils/resources-list-utils.js?v=1.11"></script>
<script src="~/Scripts/utils/list-utils.js?v=1.12"></script>
<script src="~/Scripts/utils/service-record-time-calc.js?v=1.0"></script>
@*@Html.DevExpress().GetStyleSheets(
new StyleSheet { ExtensionSuite = ExtensionSuite.NavigationAndLayout },

View File

@@ -2747,6 +2747,7 @@ namespace BeWo.Data.Access
return criteria.List<SchedulerAppointment>();
}
// ToDo: zu anonymisierende Termine nicht herausfiltern! Also sämtliche, aktive Termine mit den ausgewählten Ressourcen laden!
// KALENDER
public IEnumerable<SchedulerAppointment> LoadFilteredAppointmentsForEmployee(bool pHasRightToSeeAllEmployeeAppointments, long? pEmployeeOid, DateTime pIntervalStart, DateTime pIntervalEnd, List<long> pSelectedEmployees, List<long> pSelectedCustomers, List<long> pSelectedResources, bool pEmployeesOnly, bool pCustomersOnly, bool pResourcesOnly, bool pPrivateAppointmentsOnly, bool pOnlyMyAppointments, bool pIncludeInactiveOnes)
{
@@ -2850,13 +2851,16 @@ namespace BeWo.Data.Access
resourceCriterion
};
if(!pHasRightToSeeAllEmployeeAppointments && pSelectedEmployees.Count == 0)
if(pSelectedResources.Count == 0)
{
mainCriteria.Add(ownAppointmentCriterion);
}
else
{
listOfCriterias.Add(ownAppointmentCriterion);
if(!pHasRightToSeeAllEmployeeAppointments && pSelectedEmployees.Count == 0)
{
mainCriteria.Add(ownAppointmentCriterion);
}
else
{
listOfCriterias.Add(ownAppointmentCriterion);
}
}
var orCriteria = CreateOrCriteria(listOfCriterias);
@@ -2868,6 +2872,8 @@ namespace BeWo.Data.Access
var appointments = mainCriteria.List<SchedulerAppointment>();
#region Serientermine
var exceptionalRecurrenceInfos = appointments.Where(w => w.RecurrenceInfo != null && w.Type == 3).ToList();
var exceptionIds = new List<long>();
@@ -2923,6 +2929,8 @@ namespace BeWo.Data.Access
appointments.AddRangeIfElementsNotIn(changedOrDeletedOccurences);
#endregion
var deletedAppointments = appointments.Where(a => a.IsActive != ActivationTypeId.Active).ToList();
return appointments;

View File

@@ -1148,8 +1148,8 @@ namespace BeWo.Service.ServiceImplementations
ownerOid = null;
}
//Wenn man kein Recht hat alle zu sehen, muss immer auf Owner gefiltert werden
if(!pHasRightToSeeAllEmployeeAppointments)
//Wenn man kein Recht hat alle zu sehen, muss immer auf Owner gefiltert werden, außer es sind Ressourcen vorhanden. Dann wird anonymisiert.
if(!pHasRightToSeeAllEmployeeAppointments && pSelectedResources?.Count == 0)
{
ownerOid = pEmployeeOid;
}
@@ -1202,6 +1202,7 @@ namespace BeWo.Service.ServiceImplementations
}
}
var test = result.Count;
// Ausnahmen immer laden. Entsprechen die Ausnahmen nicht den Filterkriterien, werden sie als gelöscht markiert, um nicht auf dem Client angezeigt zu werden.
var ausnahmen = MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDCs(DAOFactory.SearchDAO.FindAppointmentsByRecurrenecInfo(result.Where(w => w.Type == 1).Select(s => s.RecurrenceInfo).ToList(), true));
var demFilterEntsprechendeTermine = FilterAppointments(ausnahmen, pEmployeeOid, filteredEmployeeOids, pSelectedCustomer, pSelectedResources, pCustomersOnly, pResourcesOnly, pShowTasks);
@@ -1236,7 +1237,10 @@ namespace BeWo.Service.ServiceImplementations
if(user != null)
{
// Bei ausgewählten Ressourcen oder auch "Nur Ressourcen" werden auch Termine mit den ausgewählten Ressourcen geladen und anonymisiert angezeigt, die der angemeldete Mitarbeiter nicht sehen darf.
var appointmentsToCheckForAnonymization = pSelectedResources.Any() || pResourcesOnly ? result.Where(w => w.ResourceList.Any() && false == SUtils.CheckSchedulerRights(w, SchedulerRightsCheckType.View, user)).ToList() : new List<SchedulerAppointmentDC>();
// ToDo: Hat man das Rechte "Alles Ansehen", wird nicht anonymisiert, da CheckSchedulerRights true zurückgibt!
var hasRightToSeeAll = user.HasRight(UserRightType.ViewAll);
var appointmentsToCheckForAnonymization = pSelectedResources.Any() || pResourcesOnly ? result.Where(w => w.ResourceList.Any() && (false == SUtils.CheckSchedulerRights(w, SchedulerRightsCheckType.View, user) || hasRightToSeeAll)).ToList() : new List<SchedulerAppointmentDC>();
if(appointmentsToCheckForAnonymization.Any())
{
@@ -1431,7 +1435,12 @@ namespace BeWo.Service.ServiceImplementations
foreach(var app in pAppointments)
{
var add = true;
if(app.ResourceList.Any(a => pSelectedResources?.Any(r => r == a.ResourceOid) ?? false))
{
result.AddIfNotIn(app);
continue;
}
if(app.Originator != null && app.Originator.EmployeeOid == pEmployeeOid)
{