Merge remote-tracking branch 'remotes/origin/feature_rene_12_massnahme_undo'

This commit is contained in:
2023-09-11 12:46:59 +02:00
7 changed files with 760 additions and 151 deletions

View File

@@ -1062,6 +1062,9 @@
<Compile Include="View\Detail\DebugMessageLogView.xaml.cs">
<DependentUpon>DebugMessageLogView.xaml</DependentUpon>
</Compile>
<Compile Include="View\Detail\MassnahmenHistoryRecord.cs" />
<Compile Include="View\Detail\MassnahmenHistory.cs" />
<Compile Include="View\Detail\MassnahmenTreeTrimmer.cs" />
<Compile Include="View\Detail\Zeiterfassung\ServiceRecordCreationView.xaml.cs">
<DependentUpon>ServiceRecordCreationView.xaml</DependentUpon>
</Compile>

View File

@@ -56,7 +56,6 @@ namespace BeWo.View.Controls
private void UpdateControls()
{
bool zeigeKatalogAuswahl = RBtnKatalog.IsChecked.HasValue && RBtnKatalog.IsChecked.Value;
LabelKatalog.Visibility = zeigeKatalogAuswahl ? Visibility.Visible : Visibility.Collapsed;
CboCatalog.Visibility = zeigeKatalogAuswahl ? Visibility.Visible : Visibility.Collapsed;

View File

@@ -0,0 +1,136 @@
using BeWo.Core;
using BeWo.ViewModel.ListViewModel;
using BS.Shared.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static BeWo.View.Detail.MassnahmenHistoryRecord;
namespace BeWo.View.Detail
{
//public class MassnahmenTreeViewHistoryManager
//{
// public MassnahmenTreeViewHistoryManager()
// {
// History = new Stack<MassnahmenActionParameters>();
// }
// public Stack<MassnahmenActionParameters> History { get; set; }
// internal void RecordAction(MassnahmenActionParameters param)
// {
// History.Push(param);
// }
// internal void UndoAction()
// {
// }
// internal void UndoAddAction()
// {
// }
// internal void UndoDeleteAction()
// {
// }
// internal void UndoMoveAction()
// {
// }
// internal void UndoCopyAction()
// {
// }
//}
public class MassnahmenHistory
{
public Action RefreshTree { get; set; }
public Action RefreshButton { get; set; }
public MassnahmenHistoryRecordOrigin Origin { get; set; }
public LinkedList<MassnahmenHistoryRecord> History { get; set; }
public LinkedListNode<MassnahmenHistoryRecord> LastChange { get; set; }
public MassnahmenTreeTrimmer TreeTrimmer { get; set; }
public MassnahmenHistory(MassnahmenTreeTrimmer trimmer, Action refresh, Action button)
{
Origin = new MassnahmenHistoryRecordOrigin();
History = new LinkedList<MassnahmenHistoryRecord>();
History.AddLast(Origin);
LastChange = History.Last;
TreeTrimmer = trimmer;
RefreshTree = refresh;
RefreshButton = button;
}
public bool GotPrevAction => LastChange is object && LastChange.Value != Origin;
public bool GotNextAction => LastChange is object && LastChange.Next is object;
public bool GotChanges => LastChange is object && (GotNextAction || GotPrevAction);
public void RecordAdd(NodeRelation param) => RecordAction(new MassnahmenHistoryRecordAdd(param));
public void RecordMove(MassnahmenHistoryRecordMove move) => RecordAction(move);
public void RecordImport(List<NodeRelation> param) => RecordAction(new MassnahmenHistoryRecordImport(param));
public void RecordDelete(MassnahmenHistoryRecordDelete del) => RecordAction(del);
public void RecordCopy(NodeRelation root, List<NodeRelation> param) => RecordAction(new MassnahmenHistoryRecordCopy(root, param));
public void RecordEdit(MassnahmenHistoryRecordEdit edit) => RecordAction(edit);
private void RecordAction(MassnahmenHistoryRecord val)
{
while (LastChange != History.Last)
{
History.RemoveLast();
}
History.AddLast(val);
LastChange = History.Last;
RefreshTree();
RefreshButton();
}
public void ClearHistory()
{
while(History.Last != History.First)
{
History.RemoveLast();
}
LastChange = History.Last;
RefreshButton();
}
public void UndoPrevAction()
{
var action = LastChange.Value;
TreeTrimmer.UndoAction(action);
LastChange = LastChange.Previous;
RefreshButton();
RefreshTree();
}
public void RedoNextAction()
{
var action = LastChange.Next.Value;
TreeTrimmer.RedoAction(action);
LastChange = LastChange.Next;
RefreshButton();
RefreshTree();
}
}
}

View File

@@ -0,0 +1,129 @@
using BeWo.Core;
using BeWo.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.View.Detail
{
public abstract class MassnahmenHistoryRecord
{
public struct NodeRelation
{
public SupportConceptGoalTreeItem Current { get; set; }
public SupportConceptGoalTreeItem Parent { get; set; }
public NodeRelation(SupportConceptGoalTreeItem newitem, SupportConceptGoalTreeItem parent)
{
Current = newitem;
Parent = parent;
}
public NodeRelation(SupportConceptGoalTreeItem newitem)
{
Current = newitem;
Parent = newitem.ParentGoal as SupportConceptGoalTreeItem;
}
}
public struct NodeEditInformation
{
public string Abbreviation { get; set; }
public string Description { get; set; }
public string Notice { get; set; }
}
}
public class MassnahmenHistoryRecordOrigin : MassnahmenHistoryRecord
{
}
public class MassnahmenHistoryRecordAdd : MassnahmenHistoryRecord
{
public NodeRelation Parameter { get; set; }
public MassnahmenHistoryRecordAdd(SupportConceptGoalTreeItem newitem, SupportConceptGoalTreeItem parent)
{
Parameter = new NodeRelation(newitem, parent);
}
public MassnahmenHistoryRecordAdd(NodeRelation param)
{
Parameter = param;
}
}
public class MassnahmenHistoryRecordImport : MassnahmenHistoryRecord
{
public List<NodeRelation> Parameters { get; set; }
public List<NodeRelation> ParametersReversed { get; set; }
public MassnahmenHistoryRecordImport(List<NodeRelation> list)
{
Parameters = list;
ParametersReversed = new Stack<NodeRelation>(list).ToList();
}
}
public class MassnahmenHistoryRecordDelete : MassnahmenHistoryRecord
{
public NodeRelation ExNode { get; set; }
public List<NodeRelation> Parameters { get; set; }
public MassnahmenHistoryRecordDelete(NodeRelation exnode, List<NodeRelation> list)
{
Parameters = list;
ExNode = exnode;
}
}
public class MassnahmenHistoryRecordMove : MassnahmenHistoryRecord
{
public SupportConceptGoalTreeItem Child { get; set; }
public SupportConceptGoalTreeItem ExParent { get; set; }
public SupportConceptGoalTreeItem Parent { get; set; }
public MassnahmenHistoryRecordMove(SupportConceptGoalTreeItem child, SupportConceptGoalTreeItem exparent, SupportConceptGoalTreeItem parent)
{
Child = child;
ExParent = exparent;
Parent = parent;
}
}
public class MassnahmenHistoryRecordCopy : MassnahmenHistoryRecord
{
public NodeRelation CurrentNode { get; set; }
public List<NodeRelation> Parameters { get; set; }
public MassnahmenHistoryRecordCopy(NodeRelation root, List<NodeRelation> list)
{
Parameters = list;
CurrentNode = root;
}
}
public class MassnahmenHistoryRecordEdit : MassnahmenHistoryRecord
{
public ValueListEntryVM VM { get; set; }
public NodeEditInformation Before { get; set; }
public NodeEditInformation After { get; set; }
public MassnahmenHistoryRecordEdit(ValueListEntryVM vm, NodeEditInformation b, NodeEditInformation a)
{
Before = b;
After = a;
VM = vm;
}
public void SetVM(NodeEditInformation info)
{
VM.Abbreviation = info.Abbreviation;
VM.Description = info.Description;
VM.Notice = info.Notice;
VM.CommitToDataContract();
}
}
}

View File

@@ -0,0 +1,342 @@
using BeWo.Core;
using BeWo.ViewModel;
using BeWo.ViewModel.ListViewModel;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.ClientPartials;
using System;
using System.Collections.Generic;
using System.Linq;
using static BeWo.View.Detail.MassnahmenHistoryRecord;
namespace BeWo.View.Detail
{
public class MassnahmenTreeTrimmer
{
public Dictionary<Type, Tuple<Action<MassnahmenHistoryRecord>, Action<MassnahmenHistoryRecord>>> Type2Actions { get; set; }
public MassnahmenTreeViewView View { get; set; }
public GenericValueListEntryListVM ViewModel => View.ViewModel;
public ObservableSortCollection<SupportConceptGoalTreeItem> GoalTree => View.GoalTree;
public MassnahmenTreeTrimmer(MassnahmenTreeViewView view)
{
View = view;
Type2Actions = new Dictionary<Type, Tuple<Action<MassnahmenHistoryRecord>, Action<MassnahmenHistoryRecord>>>
{
{ typeof(MassnahmenHistoryRecordAdd), GetTuple<MassnahmenHistoryRecordAdd>(UndoAddAction, RedoAddAction) },
{ typeof(MassnahmenHistoryRecordCopy), GetTuple<MassnahmenHistoryRecordCopy>(UndoCopyAction, RedoCopyAction) },
{ typeof(MassnahmenHistoryRecordDelete), GetTuple<MassnahmenHistoryRecordDelete>(UndoDeleteAction, RedoDeleteAction) },
{ typeof(MassnahmenHistoryRecordImport), GetTuple<MassnahmenHistoryRecordImport>(UndoImportAction, RedoImportAction) },
{ typeof(MassnahmenHistoryRecordMove), GetTuple<MassnahmenHistoryRecordMove>(UndoMoveAction, RedoMoveAction) },
{ typeof(MassnahmenHistoryRecordEdit), GetTuple<MassnahmenHistoryRecordEdit>(UndoEditAction, RedoEditAction) },
};
}
public void UndoAction(MassnahmenHistoryRecord action)
{
Type2Actions[action.GetType()].Item1(action);
}
public void RedoAction(MassnahmenHistoryRecord action)
{
Type2Actions[action.GetType()].Item2(action);
}
public NodeRelation DoAddAction(SupportConceptGoalTreeItem parent, ValueListEntryType valueListEntryType,
string description, string abbreviation, string notice)
{
if (!valueListEntryType.HasFlag(ValueListEntryType.SupportConceptGoalCategoryType) &&
!valueListEntryType.HasFlag(ValueListEntryType.SupportConceptGoalType))
throw new ArgumentOutOfRangeException();
var vm = ViewModel.NewVM;
vm.Type = valueListEntryType;
if (description is object) vm.Description = description;
if (abbreviation is object) vm.Abbreviation = abbreviation;
if (notice is object) vm.Notice = notice;
var newItem = new SupportConceptGoalTreeItem
{
GoalEntryVM = vm,
GoalEntryDC = vm.CommitToDataContract(),
ParentGoal = parent
};
var rtn = new NodeRelation(newItem, parent);
ViewModel.AddNewVMToList();
if (parent == null)
{
GoalTree.Add(newItem);
return rtn;
}
vm.ParentEntry = parent.GoalEntryDC ?? parent.GoalEntryVM.CommitToDataContract();
parent.Items.Add(newItem);
parent.IsExpanded = true;
return rtn;
}
private void UndoAddAction(MassnahmenHistoryRecordAdd record)
{
DeactivateNode(record.Parameter);
}
private void RedoAddAction(MassnahmenHistoryRecordAdd param) => RedoAddAction(param.Parameter);
private void RedoAddAction(NodeRelation addParam)
{
ActivateNode(addParam);
}
public List<NodeRelation> DoCopyAction(SupportConceptGoalTreeItem parent, SupportConceptGoalTreeItem source,
MassnahmenTreeCopyType copyType, bool force_deep_copy,
out NodeRelation current, Stack<NodeRelation> records = null)
{
if (records is null)
records = new Stack<NodeRelation>();
if (source == null || parent == null)
throw new NotImplementedException("#43298467891364987");
var wm = source.GoalEntryVM;
var childs = source.Items.ToList();
var param = DoAddAction(parent, wm.Type, wm.Description, wm.Abbreviation, wm.Notice);
var node = param.Current;
var parameter = new NodeRelation(node, parent);
current = parameter;
records.Push(parameter);
if (copyType == MassnahmenTreeCopyType.Subtree || force_deep_copy)
{
foreach (var child in childs)
{
DoCopyAction(node, child, copyType, force_deep_copy, out var item, records);
}
}
return records.ToList();
}
private void UndoCopyAction(MassnahmenHistoryRecordCopy record)
{
DeactivateSubtree(record.CurrentNode, record.Parameters);
}
private void RedoCopyAction(MassnahmenHistoryRecordCopy record)
{
ActivateSubtree(record.CurrentNode, record.Parameters);
}
public MassnahmenHistoryRecordDelete DoDeleteAction(NodeRelation param)
{
// Delete Full Subtree
var stack = new Stack<NodeRelation>();
var queue = new Queue<NodeRelation>();
DoDeleteActionRec(param.Current, ref stack, ref queue);
// Queue löschen
DeactivateSubtree(param, queue);
//var list = stack.Select(x => new MassnahmenHistoryNodeParameter(x, View.GetParent(x))).ToList();
var node = new NodeRelation(param.Current, param.Parent);
return new MassnahmenHistoryRecordDelete(node, stack.ToList());
}
public void DoDeleteActionRec(SupportConceptGoalTreeItem item, ref Stack<NodeRelation> stack, ref Queue<NodeRelation> queue)
{
foreach (var child in item.Items)
{
DoDeleteActionRec(child, ref stack, ref queue);
}
var param = new NodeRelation(item);
stack.Push(param);
queue.Enqueue(param);
}
private void UndoDeleteAction(MassnahmenHistoryRecordDelete param)
{
ActivateSubtree(param.ExNode, param.Parameters);
}
private void RedoDeleteAction(MassnahmenHistoryRecordDelete param)
{
DeactivateSubtree(param.ExNode, param.Parameters);
}
public List<NodeRelation> DoImportAction(SupportConceptGoalDC goal, List<NodeRelation> records = null)
{
if (goal == null)
return null;
if (records == null)
records = new List<NodeRelation>();
goal.Children?.ForEach(x => DoImportAction(x, records));
if (goal.IsChecked)
AddIcf(goal, records);
return records;
}
private void UndoImportAction(MassnahmenHistoryRecordImport param)
{
foreach (var item in param.ParametersReversed)
{
DeactivateNode(item);
}
}
private void RedoImportAction(MassnahmenHistoryRecordImport param)
{
foreach (var item in param.Parameters)
{
ActivateNode(item);
}
}
public MassnahmenHistoryRecordMove DoMoveAction(SupportConceptGoalTreeItem child, SupportConceptGoalTreeItem ex_parent, SupportConceptGoalTreeItem parent)
{
// Entferne child aus Ex-Parent
if (ex_parent is object)
ex_parent.Items.Remove(child);
else
GoalTree.Remove(child);
// Füge child parent hinzu
if (parent is object)
parent.Items.Add(child);
else
GoalTree.Add(child);
// Setze child Parent Entry
child.GoalEntryVM.ParentEntry = parent?.GoalEntryDC;
child.ParentGoal = parent;
return new MassnahmenHistoryRecordMove(child, ex_parent, parent);
}
private void UndoMoveAction(MassnahmenHistoryRecordMove move)
{
DoMoveAction(move.Child, move.Parent, move.ExParent);
}
private void RedoMoveAction(MassnahmenHistoryRecordMove move)
{
DoMoveAction(move.Child, move.ExParent, move.Parent);
}
public MassnahmenHistoryRecordEdit DoEditAction(ValueListEntryDC b, ValueListEntryVM a)
{
var before = new NodeEditInformation { Abbreviation = b.Abbreviation, Description = b.TypeDescription, Notice = b.Notice };
var after = new NodeEditInformation { Abbreviation = a.Abbreviation, Description = a.Description, Notice = a.Notice };
return new MassnahmenHistoryRecordEdit(a, before, after);
}
private void UndoEditAction(MassnahmenHistoryRecordEdit edit)
{
edit.SetVM(edit.Before);
}
private void RedoEditAction(MassnahmenHistoryRecordEdit edit)
{
edit.SetVM(edit.After);
}
private Tuple<Action<MassnahmenHistoryRecord>, Action<MassnahmenHistoryRecord>> GetTuple<T1>(Action<T1> a, Action<T1> b) where T1 : MassnahmenHistoryRecord
=> new Tuple<Action<MassnahmenHistoryRecord>, Action<MassnahmenHistoryRecord>>(x => a(x as T1), x => b(x as T1));
private SupportConceptGoalTreeItem AddIcf(SupportConceptGoalDC goal, List<NodeRelation> records)
{
if (goal == null) return null;
// Schaut, ob das Child bereits existiert
var similarGoal = GoalTree.FirstOrDefault(x => MassnahmenTreeViewView.SearchGoalTreeItem(x, goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice) != null);
if (similarGoal != null)
return similarGoal;
// Schaut, ob das Goal ein Parent hat
if (goal.ParentGoal == null)
{
// Ist Root Element
var record = DoAddAction(null, ValueListEntryType.SupportConceptGoalCategoryType,
goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice);
records.Add(record);
//GoalTree.Sort((x, y) => x.GoalEntryVM?.DisplayName?.CompareTo(y.GoalEntryVM?.DisplayName) ?? string.Compare(string.Empty, y.GoalEntryVM?.DisplayName, StringComparison.Ordinal));
return record.Current;
}
// Schaut, ob das ParentGoal bereits existiert
foreach (var goalTreeItem in GoalTree)
{
var similarParentGoal = MassnahmenTreeViewView.SearchGoalTreeItem(goalTreeItem, goal.ParentGoal.GoalEntryDC.TypeDescription, goal.ParentGoal.GoalEntryDC.Abbreviation, goal.ParentGoal.GoalEntryDC.Notice);
if (similarParentGoal == null)
continue;
var record = DoAddAction(similarParentGoal, ValueListEntryType.SupportConceptGoalCategoryType, goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice);
records.Add(record);
return record.Current;
}
// Fügt den Parent hinzu
var parent = AddIcf(goal.ParentGoal, records);
var record2 = DoAddAction(parent, ValueListEntryType.SupportConceptGoalCategoryType,
goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice);
records.Add(record2);
return record2.Current;
}
private void ActivateSubtree(NodeRelation currentNode, List<NodeRelation> param)
{
foreach (var item in param)
{
ViewModel.VMList.Add(item.Current.GoalEntryVM);
}
if (currentNode.Parent is object)
currentNode.Parent.Items.Add(currentNode.Current);
else
GoalTree.Add(currentNode.Current);
}
private void ActivateNode(NodeRelation currentNode)
{
var newItem = currentNode.Current;
var parent = currentNode.Parent;
ViewModel.VMList.Add(newItem.GoalEntryVM);
if (parent != null)
parent.Items.Add(newItem);
else
GoalTree.Add(newItem);
}
private void DeactivateSubtree(NodeRelation currentNode, IEnumerable<NodeRelation> param)
{
foreach (var item in param)
{
ViewModel.VMList.Remove(item.Current.GoalEntryVM);
}
if (currentNode.Parent is object)
currentNode.Parent.Items.Remove(currentNode.Current);
else
GoalTree.Remove(currentNode.Current);
}
private void DeactivateNode(NodeRelation currentNode)
{
var newItem = currentNode.Current;
var parent = currentNode.Parent;
ViewModel.VMList.Remove(newItem.GoalEntryVM);
if (parent != null)
parent.Items.Remove(newItem);
else
GoalTree.Remove(newItem);
}
}
}

View File

@@ -11,7 +11,7 @@
<view:ValueListEntryTypeToFontWeightConverter x:Key="ValueListEntryTypeToFontWeightConverter" />
</ResourceDictionary>
</localView:BeWoView.Resources>
<GroupBox Name="groupbox_root" Header="Ziele und Maßnahmen" Style="{StaticResource ObjectEditGroupBox}">
<GroupBox Name="groupbox_root" Header="Ziele und Maßnahmen" Style="{StaticResource ObjectEditGroupBox}" KeyDown="Groupbox_root_KeyDown">
<GroupBox.Resources>
<ContextMenu x:Key="cmGoals" MenuItem.Click="ContextMenuGoals_Click" Opened="ContextMenuGoals_Opened">
<MenuItem Header="Neue Maßnahme">
@@ -70,13 +70,23 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Column="0" Content="Neues Ziel" />
<TextBox Grid.Column="1" Margin="1" VerticalContentAlignment="Center" Text="{Binding ViewModel.NewVM.Description, UpdateSourceTrigger=PropertyChanged}" />
<Button Grid.Column="2" Height="25" Content="Hinzufügen" Margin="3" Click="ZielHinzufuegenButton_Click" />
<Button Grid.Column="3" Height="25" Content="Icf Importieren" Margin="3" Click="IcfImport_Click" />
<ToggleButton Grid.Column="4" Height="25" Content="Bearbeiten" Margin="3" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="10" HorizontalAlignment="Right">
<Button x:Name="PrevButton" Height="25" Content="Prev" Margin="3" Click="PrevButton_Click" />
<Button x:Name="NextButton" Height="25" Content="Next" Margin="3" Click="NextButton_Click" />
</StackPanel>
</Grid>
<GroupBox Grid.Row="1" Style="{StaticResource ObjectEditGroupBox}">
<TreeView x:Name="TreeView" Margin="3 3 7 3" Grid.Row="1" Padding="0 5 10 5"
@@ -116,7 +126,7 @@
</StackPanel>
</TextBox.ToolTip>
</TextBox>
</Grid>
</HierarchicalDataTemplate>
</TreeView.Resources>

View File

@@ -35,7 +35,6 @@ namespace BeWo.View.Detail
private TreeViewItem _SelectedGoalTreeNode;
private GenericValueListEntryListVM _ViewModel;
private List<ValueListEntryDC> _Children2Delete;
private List<SupportConceptGoalTreeItem> _TreeViewItemsList;
private MassnahmenTreeCopyType _CopyType;
@@ -44,6 +43,9 @@ namespace BeWo.View.Detail
private SupportConceptGoalTreeItem _draggedItem;
private SupportConceptGoalTreeItem _parent;
private MassnahmenHistory _History;
private MassnahmenTreeTrimmer _TreeTrimmer;
public MassnahmenTreeViewView(GenericValueListEntryListVM pViewModel)
{
InitializeComponent();
@@ -53,8 +55,25 @@ namespace BeWo.View.Detail
DataContext = this;
Bearbeitungsmodus = false;
InitHistoryMode();
}
public void InitHistoryMode()
{
_TreeTrimmer = new MassnahmenTreeTrimmer(this);
_History = new MassnahmenHistory(_TreeTrimmer, SortGoalTree, UpdateHistoryButton);
UpdateHistoryButton();
}
public void UpdateHistoryButton()
{
PrevButton.Visibility = _History.GotPrevAction ? Visibility.Visible : Visibility.Hidden;
NextButton.Visibility = _History.GotNextAction ? Visibility.Visible : Visibility.Hidden;
}
public ObservableSortCollection<SupportConceptGoalTreeItem> GoalTree { get; private set; }
public override bool IsDirty => ViewModel != null && ViewModel.IsDirty || (_History?.GotChanges ?? false);
public static bool IsAllowedToEditGoals => BeWoApp.LoggedOnUser.HasRight(UserRightType.SupportConcept_AllowEditGoals);
public GenericValueListEntryListVM ViewModel
@@ -67,7 +86,6 @@ namespace BeWo.View.Detail
TreeView.ItemsSource = GoalTree;
}
}
public bool Bearbeitungsmodus
{
get
@@ -86,10 +104,6 @@ namespace BeWo.View.Detail
}
}
public ObservableSortCollection<SupportConceptGoalTreeItem> GoalTree { get; private set; }
public override bool IsDirty => ViewModel != null && ViewModel.IsDirty;
private void GoalTreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
var source = e.OriginalSource as DependencyObject;
@@ -160,7 +174,7 @@ namespace BeWo.View.Detail
break;
case "Bearbeiten":
if (selectedItem != null)
EditTreeItem(selectedItem.GoalEntryVM);
StartEditTreeItem(selectedItem.GoalEntryVM);
break;
case "Einzelnes Element kopieren":
if (selectedItem != null)
@@ -198,6 +212,8 @@ namespace BeWo.View.Detail
foreach (var menuitem in menu.Items.OfType<MenuItem>().Select(item => item))
{
menuitem.IsEnabled = goal != null;
if (menuitem.Header.Equals("Neue Maßnahme"))
{
menuitem.IsEnabled = goal != null && !goal.IsGoal;
@@ -256,16 +272,7 @@ namespace BeWo.View.Detail
}
private void ZielHinzufuegenButton_Click(object sender, RoutedEventArgs e)
{
var newItem = new SupportConceptGoalTreeItem();
var vm = ViewModel.NewVM;
vm.Type = ValueListEntryType.SupportConceptGoalCategoryType;
newItem.GoalEntryVM = vm;
ViewModel.AddNewVMToList();
GoalTree.Add(newItem);
GoalTree.Sort((x, y) => x.GoalEntryVM?.DisplayName?.CompareTo(y.GoalEntryVM?.DisplayName) ?? string.Compare(string.Empty, y.GoalEntryVM?.DisplayName, StringComparison.Ordinal));
AddTreeItem(null, ValueListEntryType.SupportConceptGoalCategoryType);
}
private void IcfImport_Click(object sender, RoutedEventArgs e)
{
@@ -291,7 +298,8 @@ namespace BeWo.View.Detail
control2.ButtonImportClicked += () =>
{
ImportIcf(control2.TreeViewGoalItem);
ImportTreeItem(control2.TreeViewGoalItem);
beWoWindow2.Close();
};
@@ -344,8 +352,9 @@ namespace BeWo.View.Detail
if (ContainsTreeItem(_copy, _item))
MessageBox.Show("Kopieren in tiefere Ziele/Maßnamhen nicht möglich!");
else
{
CopyTreeItem(_item, _copy, false);
}
}
private void StartMoveItem(SupportConceptGoalTreeItem _draggedItem, SupportConceptGoalTreeItem _parent)
{
@@ -381,7 +390,7 @@ namespace BeWo.View.Detail
if ((finalDropEffect == DragDropEffects.Move) && (_parent != null) && _parent != _draggedItem)
{
StartMoveItem(_draggedItem, _parent);
//var origin_parent = _draggedItem.ParentGoal as SupportConceptGoalTreeItem;
//var parent = _parent;
@@ -451,6 +460,45 @@ namespace BeWo.View.Detail
}
}
private void SortGoalTree()
{
foreach (var item in GoalTree)
{
SortRec(item);
}
GoalTree.Sort(CompareToCustom);
//GoalTree.Sort((x, y) => x.GoalEntryVM?.DisplayName?.CompareTo(y.GoalEntryVM?.DisplayName) ?? string.Compare(string.Empty, y.GoalEntryVM?.DisplayName, StringComparison.Ordinal));
}
private void SortRec(SupportConceptGoalTreeItem item)
{
if (item is object && item.Items is object && item.Items.Any())
{
foreach (var child in item.Items)
{
SortRec(child);
}
item.Items.Sort(CompareToCustom);
//item.Items.Sort((x, y) => x.GoalEntryVM?.DisplayName?.CompareTo(y.GoalEntryVM?.DisplayName) ?? string.Compare(string.Empty, y.GoalEntryVM?.DisplayName, StringComparison.Ordinal));
}
}
private int CompareToCustom(SupportConceptGoalTreeItem a, SupportConceptGoalTreeItem b)
{
var res = a.GoalEntryVM?.DisplayName?.CompareTo(b.GoalEntryVM?.DisplayName);
if (res.HasValue && res.Value != 0)
return res.Value;
if (a.Items is object && b.Items is object)
{
return a.Items.Count.CompareTo(b.Items.Count);
}
return string.Compare(string.Empty, b.GoalEntryVM?.DisplayName, StringComparison.Ordinal);
}
public List<ValueListEntryDC> GetAllChildren(SupportConceptGoalTreeItem treeItem, SupportConceptGoalDC dcItem)
{
List<ValueListEntryDC> returnThis = new List<ValueListEntryDC>();
@@ -495,7 +543,6 @@ namespace BeWo.View.Detail
{
var neueVMs = ViewModel.VMList.Where(w => w.IsNew).ToList();
_TreeViewItemsList = new List<SupportConceptGoalTreeItem>();
GetAllTreeViewItems();
var obersteZiele = neueVMs.Where(w => w.IsNew && (w.ParentEntry != null && w.ParentEntry.ValueListEntryOid != null) || w.ParentEntry == null);
@@ -512,8 +559,10 @@ namespace BeWo.View.Detail
if (ViewModel.RemovedCount > 0)
{
var entfernte = _Children2Delete.Where(w => w.ValueListEntryOid != null).ToList();
var entfernteDic = entfernte.ToDictionary(k => k.ValueListEntryOid.Value, v => v.ValueListEntryVersion.Value);
var ent = ViewModel.GetRemoved();
//var entfernte = _Children2Delete.Where(w => w.ValueListEntryOid != null).ToList();
//var entfernteDic = entfernte.ToDictionary(k => k.ValueListEntryOid.Value, v => v.ValueListEntryVersion.Value);
var entfernteDic = ent.ToDictionary(k => k.ValueListEntryOid.Value, v => v.ValueListEntryVersion.Value);
entfernteDic.AddAndIgnoreDuplicates(ViewModel.GetRemoved().ToDictionary(dc => dc.ValueListEntryOid.Value, dc => dc.ValueListEntryVersion.Value));
lToDos.Add(s => s.DeactivateValueListEntries(entfernteDic));
@@ -522,8 +571,10 @@ namespace BeWo.View.Detail
ServiceFacade.DoMultipleValueListServicesAsync(lToDos, ReloadViewModel);
Cache.GetInstance().ClearAllValueListEntries();
_History.ClearHistory();
}
private static void EditTreeItem(ValueListEntryVM valueListEntry)
private void StartEditTreeItem(ValueListEntryVM valueListEntry)
{
if (valueListEntry == null) return;
if (valueListEntry.IsNew)
@@ -544,7 +595,14 @@ namespace BeWo.View.Detail
beWoWindow.Close();
};
control.SaveButtonClicked += () => beWoWindow.Close();
control.SaveButtonClicked += () =>
{
EditTreeItem(valueListEntry);
valueListEntry.CommitToDataContract();
beWoWindow.Close();
};
beWoWindow.Height = 200;
beWoWindow.Width = 500;
@@ -593,7 +651,7 @@ namespace BeWo.View.Detail
textBox.Padding = new Thickness(1, 3, 1, 3);
}
}
private static SupportConceptGoalTreeItem SearchGoalTreeItem(SupportConceptGoalTreeItem supportConceptGoalTreeItem,
public static SupportConceptGoalTreeItem SearchGoalTreeItem(SupportConceptGoalTreeItem supportConceptGoalTreeItem,
string description, string abbreviation, string notice)
{
if (supportConceptGoalTreeItem?.GoalEntryVM == null) return null;
@@ -694,9 +752,10 @@ namespace BeWo.View.Detail
GoalTree = iGoalList;
}
private void GetAllTreeViewItems()
{
_TreeViewItemsList = new List<SupportConceptGoalTreeItem>();
foreach (var parent in GoalTree)
{
TraverseTreeViewItem(parent);
@@ -710,51 +769,6 @@ namespace BeWo.View.Detail
TraverseTreeViewItem(child);
}
}
private void ImportIcf(SupportConceptGoalDC goal)
{
if (goal == null) return;
goal.Children?.ForEach(ImportIcf);
if (goal.IsChecked)
AddIcf(goal);
}
private SupportConceptGoalTreeItem AddIcf(SupportConceptGoalDC goal)
{
if (goal == null) return null;
// Schaut, ob das Child bereits existiert
var similarGoal = GoalTree.FirstOrDefault(x => SearchGoalTreeItem(x, goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice) != null);
if (similarGoal != null)
return similarGoal;
// Schaut, ob das Goal ein Parent hat
if (goal.ParentGoal == null)
{
var treeItem = AddTreeItem(null, ValueListEntryType.SupportConceptGoalCategoryType,
goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice);
GoalTree.Add(treeItem);
GoalTree.Sort((x, y) => x.GoalEntryVM?.DisplayName?.CompareTo(y.GoalEntryVM?.DisplayName) ?? string.Compare(string.Empty, y.GoalEntryVM?.DisplayName, StringComparison.Ordinal));
return treeItem;
}
// Schaut, ob das ParentGoal bereits existiert
foreach (var goalTreeItem in GoalTree)
{
var similarParentGoal = SearchGoalTreeItem(goalTreeItem, goal.ParentGoal.GoalEntryDC.TypeDescription, goal.ParentGoal.GoalEntryDC.Abbreviation, goal.ParentGoal.GoalEntryDC.Notice);
if (similarParentGoal == null)
continue;
return AddTreeItem(similarParentGoal, ValueListEntryType.SupportConceptGoalCategoryType, goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice);
}
// Fügt den Parent hinzu
var parent = AddIcf(goal.ParentGoal);
return AddTreeItem(parent, ValueListEntryType.SupportConceptGoalCategoryType,
goal.GoalEntryDC.TypeDescription, goal.GoalEntryDC.Abbreviation, goal.GoalEntryDC.Notice);
}
public void AddTreeItemWithControl(SupportConceptGoalTreeItem parent, ValueListEntryType valueListEntryType, string viewHeader)
{
@@ -776,7 +790,9 @@ namespace BeWo.View.Detail
control.SaveButtonClicked += () =>
{
var vm = control.ValueListEntry;
AddTreeItem(parent, valueListEntryType, vm.Description, vm.Abbreviation, vm.Notice);
beWoWindow.Close();
};
@@ -788,77 +804,30 @@ namespace BeWo.View.Detail
beWoWindow.rootGroupBox.Header = viewHeader;
beWoWindow.ShowDialog();
}
private SupportConceptGoalTreeItem AddTreeItem(SupportConceptGoalTreeItem parent, ValueListEntryType valueListEntryType, string description, string abbreviation, string notice)
private void AddTreeItem(SupportConceptGoalTreeItem parent, ValueListEntryType valueListEntryType, string description = null, string abbreviation = null, string notice = null)
{
if (!valueListEntryType.HasFlag(ValueListEntryType.SupportConceptGoalCategoryType) &&
!valueListEntryType.HasFlag(ValueListEntryType.SupportConceptGoalType))
throw new ArgumentOutOfRangeException();
var param = _TreeTrimmer.DoAddAction(parent, valueListEntryType, description, abbreviation, notice);
var vm = ViewModel.NewVM;
vm.Type = valueListEntryType;
vm.Description = description;
vm.Abbreviation = abbreviation;
vm.Notice = notice;
_History.RecordAdd(param);
}
private void ImportTreeItem(SupportConceptGoalDC goal)
{
var param = _TreeTrimmer.DoImportAction(goal);
var newItem = new SupportConceptGoalTreeItem
{
GoalEntryVM = vm,
GoalEntryDC = vm.CommitToDataContract(),
ParentGoal = parent
};
ViewModel.AddNewVMToList();
if (parent == null) return newItem;
vm.ParentEntry = parent.GoalEntryDC ?? parent.GoalEntryVM.CommitToDataContract();
parent.GoalEntryVM = parent.GoalEntryVM;
parent.Items.Add(newItem);
parent.IsExpanded = true;
return newItem;
_History.RecordImport(param);
}
private void DeleteTreeItem(SupportConceptGoalTreeItem selectedItem)
{
_Children2Delete = new List<ValueListEntryDC>();
DeleteTreeItemRec(selectedItem);
var del = _TreeTrimmer.DoDeleteAction(new MassnahmenHistoryRecord.NodeRelation(selectedItem));
var parent = selectedItem.ParentGoal as SupportConceptGoalTreeItem;
if (parent != null && parent.Items != null)
parent.Items.Remove(selectedItem);
else
GoalTree.Remove(selectedItem);
ViewModel.VMList.Remove(selectedItem.GoalEntryVM);
}
private void DeleteTreeItemRec(SupportConceptGoalTreeItem item)
{
var result = new List<ValueListEntryDC> { item.GoalEntryDC ?? item.GoalEntryVM.CommitToDataContract() };
foreach (var child in item.Items)
{
DeleteTreeItemRec(child);
}
_Children2Delete.AddRange(result);
_History.RecordDelete(del);
}
private void CopyTreeItem(SupportConceptGoalTreeItem parent, SupportConceptGoalTreeItem source, bool force_deep_copy)
{
if (source == null || parent == null)
throw new NotImplementedException("#43298467891364987");
var param = _TreeTrimmer.DoCopyAction(parent, source, _CopyType, force_deep_copy, out var current);
var wm = source.GoalEntryVM;
var childs = source.Items.ToList();
var node = AddTreeItem(parent, wm.Type, wm.Description, wm.Abbreviation, wm.Notice);
if (_CopyType == MassnahmenTreeCopyType.Subtree || force_deep_copy)
{
foreach (var child in childs)
{
CopyTreeItem(node, child, force_deep_copy);
}
}
_History.RecordCopy(current, param);
}
private void MoveTreeItem(SupportConceptGoalTreeItem child, SupportConceptGoalTreeItem parent)
{
@@ -867,20 +836,15 @@ namespace BeWo.View.Detail
if (ex_parent == parent)
return;
// Entferne child aus Ex-Parent
ex_parent.Items.Remove(child);
// Füge child parent hinzu
parent.Items.Add(child);
var record = _TreeTrimmer.DoMoveAction(child, ex_parent, parent);
// Setze child Parent Entry
parent.GoalEntryDC = parent.GoalEntryVM.CommitToDataContract();
child.GoalEntryVM.ParentEntry = parent.GoalEntryDC;
child.ParentGoal = parent;
_History.RecordMove(record);
}
private void EditTreeItem(ValueListEntryVM valueListEntry)
{
var param = _TreeTrimmer.DoEditAction(valueListEntry.DataContract, valueListEntry);
//CopyTreeItem(parent, child, true);
//DeleteIndividualGoal(child);
_History.RecordEdit(param);
}
private SupportConceptGoalTreeItem GetNearestContainer(UIElement element)
@@ -933,8 +897,7 @@ namespace BeWo.View.Detail
return false;
}
private SupportConceptGoalTreeItem GetParent(SupportConceptGoalTreeItem lostchild)
public SupportConceptGoalTreeItem GetParent(SupportConceptGoalTreeItem lostchild)
{
if (lostchild.ParentGoal is SupportConceptGoalTreeItem item)
return item;
@@ -953,7 +916,7 @@ namespace BeWo.View.Detail
foreach (var current_child in current.Items)
{
if(FindParent(current, current_child, lostchild, out foundchild))
if (FindParent(current, current_child, lostchild, out foundchild))
{
return true;
}
@@ -962,6 +925,33 @@ namespace BeWo.View.Detail
foundchild = null;
return false;
}
private void PrevButton_Click(object sender, RoutedEventArgs e)
{
if (!_History.GotPrevAction)
return;
_History.UndoPrevAction();
}
private void NextButton_Click(object sender, RoutedEventArgs e)
{
if (!_History.GotNextAction)
return;
_History.RedoNextAction();
}
private void Groupbox_root_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Right)
{
NextButton_Click(this, new RoutedEventArgs());
}
else if (e.Key == Key.Left)
{
PrevButton_Click(this, new RoutedEventArgs());
}
}
}
public class ValueListEntryTypeToFontWeightConverter : IValueConverter