diff --git a/BeWo/BeWo.csproj b/BeWo/BeWo.csproj
index bfdadcc00..901c45e52 100644
--- a/BeWo/BeWo.csproj
+++ b/BeWo/BeWo.csproj
@@ -109,6 +109,9 @@
+
+
+
@@ -117,6 +120,9 @@
AiConfigView.xaml
+
+ AiPromptbausteinView.xaml
+
RtfEditView.xaml
@@ -136,6 +142,10 @@
Designer
MSBuild:Compile
+
+ MSBuild:Compile
+ Designer
+
MSBuild:Compile
Designer
diff --git a/BeWo/View/Detail/AI/AiPromptbausteinView.xaml b/BeWo/View/Detail/AI/AiPromptbausteinView.xaml
new file mode 100644
index 000000000..31709b097
--- /dev/null
+++ b/BeWo/View/Detail/AI/AiPromptbausteinView.xaml
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BeWo/View/Detail/AI/AiPromptbausteinView.xaml.cs b/BeWo/View/Detail/AI/AiPromptbausteinView.xaml.cs
new file mode 100644
index 000000000..40e7baee9
--- /dev/null
+++ b/BeWo/View/Detail/AI/AiPromptbausteinView.xaml.cs
@@ -0,0 +1,304 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Input;
+
+using BeWo.ServiceProxy;
+using BeWo.ViewModel;
+using BeWo.ViewModel.ListViewModel;
+
+using BS.Shared;
+using BS.Shared.Extensions;
+using BS.Shared.Translation;
+using DevExpress.Xpf.Editors;
+using DevExpress.Xpf.Grid;
+
+namespace BeWo.View.Detail
+{
+ public partial class AiPromptbausteinView
+ {
+ private AiPromptbausteinListVM _ViewModel;
+
+ public AiPromptbausteinListVM ViewModel
+ {
+ get => _ViewModel;
+
+ set
+ {
+ _ViewModel = value;
+ root.DataContext = value;
+ }
+ }
+
+ public override bool IsDirty => ViewModel != null && ViewModel.IsDirty;
+
+ private readonly bool _IsInAdministrationView;
+
+ public AiPromptbausteinView(AiPromptbausteinListVM pViewModel, bool pIsInAdministrationView = false)
+ {
+ InitializeComponent();
+
+ _IsInAdministrationView = pIsInAdministrationView;
+
+ ViewModel = pViewModel;
+ }
+
+ protected override void Save()
+ {
+ Save(null);
+ }
+
+ public void Save(Action pCallBack)
+ {
+ var lToDos = new List>();
+
+ if(ViewModel.ChangedCount == 0 && ViewModel.RemovedCount == 0 && ViewModel.AddedCount == 0)
+ {
+ return;
+ }
+
+ if (ViewModel.AddedCount > 0)
+ {
+ lToDos.Add(s => s.InsertNewAiPromptbausteine(ViewModel.CommitAdded()));
+ }
+
+ if (ViewModel.RemovedCount > 0)
+ {
+ lToDos.Add(s => s.DeleteAiPromptbausteine(ViewModel.GetRemoved().ToDictionary(dc => dc.Oid.Value, dc => dc.Version.Value)));
+ }
+
+ if (ViewModel.ChangedCount > 0)
+ {
+ lToDos.Add(s => s.UpdateAiPromptbausteine(ViewModel.CommitChanged()));
+ }
+
+ ServiceFacade.DoMultipleOperationsServicesAsync(lToDos, () =>
+ {
+ pCallBack?.Invoke();
+ ReloadViewModel();
+ });
+ }
+
+ private void ReloadViewModel()
+ {
+ VMFactory.CreateAiPromptbausteinListVMAsync(r => this.Dispatch(delegate
+ {
+ TreeListControl.BeginDataUpdate();
+
+ ViewModel = r;
+
+ TreeListControl.EndDataUpdate();
+
+ TreeListControl.SelectedItems.Clear();
+
+ }), _IsInAdministrationView);
+ }
+
+ private void DeleteButton_Click(object sender, RoutedEventArgs e)
+ {
+ var focusedNode = TreeListView.FocusedNode;
+ var selectedAiPromptbaustein = (AiPromptbausteinVM) focusedNode.Content;
+
+ String msg = "der ausgewähte KI-Prompt";
+ if (selectedAiPromptbaustein.IsParent)
+ {
+ msg = "die ausgewähte Kategorie";
+ }
+
+ if (MessageBox.Show(Translator.Translate("Sie Sie sicher, dass {0} \"{1}\" gelöscht werden soll?", msg, selectedAiPromptbaustein.Name), "Löschen", MessageBoxButton.YesNo, MessageBoxImage.Exclamation) == MessageBoxResult.Yes)
+ {
+ _ChildrenToDelete.Add(selectedAiPromptbaustein);
+
+ if (selectedAiPromptbaustein.IsParent)
+ {
+ RetrieveChildAiPromptbausteinsFromParent(selectedAiPromptbaustein);
+ }
+
+ ViewModel.VMList.RemoveRange(_ChildrenToDelete);
+ _ChildrenToDelete.Clear();
+ }
+ }
+
+ private readonly List _ChildrenToDelete = new List();
+
+ private void RetrieveChildAiPromptbausteinsFromParent(AiPromptbausteinVM parent)
+ {
+ var children = ViewModel.VMList.Where(w => w.Parent != null && w.Parent.Equals(parent));
+
+ foreach(var child in children)
+ {
+ _ChildrenToDelete.Add(child);
+ RetrieveChildAiPromptbausteinsFromParent(child);
+ }
+ }
+
+ public static bool CheckEditorRights(AiPromptbausteinVM textbausteinVM, object parameter)
+ {
+ if (textbausteinVM != null)
+ {
+ var isOwn = textbausteinVM.Employee != null && textbausteinVM.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid);
+
+ var hasRight2EditAll = BeWoApp.LoggedOnUser.HasRight(UserRightType.TextbausteineAlleBearbeiten);
+ var hasRight2EditOwn = BeWoApp.LoggedOnUser.HasRight(UserRightType.TextbausteineNurEigeneBearbeiten);
+ var hasRight2Create4All = BeWoApp.LoggedOnUser.HasRight(UserRightType.TextbausteineAlleBearbeiten);
+
+ if (parameter != null && parameter.ToString().Equals("IsOnlyForEmployeeCheckBox"))
+ {
+ return isOwn && hasRight2EditOwn && hasRight2Create4All || hasRight2EditAll;
+ }
+
+ return isOwn && hasRight2EditOwn || hasRight2EditAll;
+ }
+
+ return false;
+ }
+
+ private void ContextMenuAiPromptbausteins_Click(object sender, RoutedEventArgs e)
+ {
+ if(e.OriginalSource is MenuItem twi)
+ {
+ var selectedItem = TreeListControl.SelectedItem as AiPromptbausteinVM;
+
+ ViewModel.NewVM.IsParent = twi.Header.Equals("Neue Textbausteinkategorie");
+ ViewModel.NewVM.IsExpanded = twi.Header.Equals("Neue Textbausteinkategorie");
+ ViewModel.NewVM.IsOnlyForEmployee = !_IsInAdministrationView;
+ ViewModel.NewVM.Name = GenerateNewAiPromptbausteinName(twi.Header.ToString());
+
+ if(selectedItem != null)
+ {
+ ViewModel.NewVM.Parent = selectedItem;
+ }
+
+ ViewModel.AddNewVMToList(false);
+ Save();
+ }
+ }
+
+ private string GenerateNewAiPromptbausteinName(string pName)
+ {
+ var newName = pName;
+ var counter = 1;
+
+ while(ViewModel.VMList.Any(a => a.Name != null && a.Name.Equals(newName)))
+ {
+ newName = pName + " " + counter;
+ counter++;
+ }
+
+ return newName;
+ }
+
+ private void ContextMenuAiPromptbausteins_Opened(object sender, RoutedEventArgs e)
+ {
+ if (e.OriginalSource is ContextMenu menu)
+ {
+ var aiPromptbaustein = TreeListControl.SelectedItem as AiPromptbausteinVM;
+
+ foreach (var menuitem in menu.Items.OfType