Merge branch 'feature_rene_18_ai'

# Conflicts:
#	BeWo/View/Controls/AI/AiPromptbausteinButton.xaml.cs
#	Service/ServiceImplementations/Enhanced/StatusServiceImp.cs
This commit is contained in:
2026-06-16 12:01:30 +02:00
164 changed files with 6790 additions and 3569 deletions

View File

@@ -68,6 +68,7 @@ namespace BeWo.ViewModel
protected abstract DCType MapToDataContract(DCType pDataContract, bool doCommit);
// Methode dient dem aktualiseren eines existierendes VM mit einem neuen DC (z.B. Serverupdate)
public virtual void UpdateByDataContract(DCType pDataContract)
{
throw new NotImplementedException();

View File

@@ -7,6 +7,7 @@ using BeWo.ServiceProxy;
using BeWo.ViewModel.ListViewModel;
using BS.Shared;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.Extensions;
using DevExpress.Mvvm;
using DevExpress.Xpf.Core.Native;
using Newtonsoft.Json;
@@ -73,7 +74,7 @@ namespace BeWo.ViewModel
public string Context => DataContract.Context;
public Dictionary<TableID, long[]> ContextBeWoObjects => DataContract.ContextBeWoObjects;
public AiDataContextType Context_Type => DataContract.ContextType;
public UIContext UIContext => (UIContext)DataContract.UIContext;
public AiActionType AiActionType => DataContract.ActionType;
protected override void InitByDataContract(AiConversationDC pDataContract)
{
@@ -115,6 +116,12 @@ namespace BeWo.ViewModel
return new AiConversationMessageListVM(messages);
}
public void AddMessages(List<AiConversationMessageDC> messages)
{
var filter = getFilter(messages);
Messages.VMList.AddRange(filter.VMList);
}
public void ResetDisplayname()
{
Displayname = DataContract.Displayname;

View File

@@ -19,9 +19,15 @@ namespace BeWo.ViewModel
private bool _IsPublic;
private int _Position;
private bool _IsExpanded;
private bool _IsSelected;
private AiActionType _ActionType;
private AiPromptbausteinFolderListVM _SubFolders;
private AiPromptbausteinPromptListVM _SubPrompts;
private AiPromptbausteinRoutineListVM _SubRoutines;
private bool _CanAddFolder;
private bool _CanAddPrompt;
private bool _CanAddRoutine;
private bool _CanEdit;
public AiPromptbausteinFolderVM(AiPromptbausteinFolderDC dc) : base(dc, dc.Oid)
{
@@ -36,8 +42,6 @@ namespace BeWo.ViewModel
var success = SetProperty(ref _Title, value, nameof(Title), () => DataContract.Title);
if (!success)
return;
FirePropertyChanged(nameof(Displayname));
}
}
@@ -55,7 +59,7 @@ namespace BeWo.ViewModel
public CompactEmployeeDC Creator
{
get => DataContract.Creator;
get => _Creator;
set => SetProperty(ref _Creator, value, nameof(Creator), () => DataContract.Creator);
}
@@ -77,16 +81,60 @@ namespace BeWo.ViewModel
set => SetProperty(ref _IsExpanded, value, nameof(IsExpanded));
}
public bool IsSelected
{
get => _IsSelected;
set => SetProperty(ref _IsSelected, value, nameof(IsSelected));
}
public AiActionType ActionType
{
get => _ActionType;
set => SetProperty(ref _ActionType, value, nameof(ActionType), () => DataContract.ActionType);
}
public bool CanAddFolder
{
get => _CanAddFolder;
set => SetProperty(ref _CanAddFolder, value, nameof(CanAddFolder));
}
public bool CanAddPrompt
{
get => _CanAddPrompt;
set => SetProperty(ref _CanAddPrompt, value, nameof(CanAddPrompt));
}
public bool CanAddRoutine
{
get => _CanAddRoutine;
set => SetProperty(ref _CanAddRoutine, value, nameof(CanAddRoutine));
}
public bool CanEdit
{
get => _CanEdit;
set => SetProperty(ref _CanEdit, value && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteineEdit), nameof(CanEdit));
}
public AiPromptbausteinFolderListVM SubFolders
{
get => _SubFolders;
set => SetProperty(ref _SubFolders, value, nameof(SubFolders));
set
{
var success = SetProperty(ref _SubFolders, value, nameof(SubFolders));
if (!success)
return;
_SubFolders.VMList.ListChanged += (s, e) => {
FirePropertyChanged(nameof(TotalPromptCount));
FirePropertyChanged(nameof(TotalRoutineCount));
FirePropertyChanged(nameof(AlleFolderItems));
if (e.ListChangedType == System.ComponentModel.ListChangedType.ItemChanged)
return;
FirePropertyChanged(nameof(Prompts));
FirePropertyChanged(nameof(Routines));
};
}
}
public AiPromptbausteinPromptListVM SubPrompts
@@ -99,7 +147,8 @@ namespace BeWo.ViewModel
return;
_SubPrompts.VMList.ListChanged += (s, e) => {
FirePropertyChanged(nameof(Displayname));
FirePropertyChanged(nameof(TotalPromptCount));
FirePropertyChanged(nameof(AlleFolderItems));
if (e.ListChangedType == System.ComponentModel.ListChangedType.ItemChanged)
return;
@@ -109,6 +158,40 @@ namespace BeWo.ViewModel
}
}
public AiPromptbausteinRoutineListVM SubRoutines
{
get => _SubRoutines;
set
{
var success = SetProperty(ref _SubRoutines, value, nameof(SubRoutines));
if (!success)
return;
_SubRoutines.VMList.ListChanged += (s, e) => {
FirePropertyChanged(nameof(TotalRoutineCount));
FirePropertyChanged(nameof(AlleFolderItems));
if (e.ListChangedType == System.ComponentModel.ListChangedType.ItemChanged)
return;
FirePropertyChanged(nameof(Routines));
};
}
}
public List<AbstractBaseVM> AlleFolderItems
{
get
{
var l1 = Prompts.Cast<AbstractBaseVM>();
var l2 = Routines.Cast<AbstractBaseVM>();
var l12 = l1.Union(l2);
return l12.ToList();
}
}
public List<AiPromptbausteinPromptVM> Prompts
{
get
@@ -126,20 +209,21 @@ namespace BeWo.ViewModel
}
}
public bool CanAddFolder
public List<AiPromptbausteinRoutineVM> Routines
{
get => DataContract.CanAddFolder;
set => DataContract.CanAddFolder = value;
}
public bool CanAddPrompt
{
get => DataContract.CanAddPrompt;
set => DataContract.CanAddPrompt = value;
}
public bool CanEdit
{
get => DataContract.CanEdit && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteineEdit);
set => DataContract.CanEdit = value;
get
{
var res = new List<AiPromptbausteinRoutineVM>();
res.AddRange(SubRoutines.VMList);
foreach (var folder in SubFolders.VMList)
{
res.AddRange(folder.Routines);
}
return res;
}
}
public bool IsNewFeature
@@ -151,22 +235,15 @@ namespace BeWo.ViewModel
get => !IsNewFeature;
}
public bool CanShareEdit
{
get => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteinShare) && Creator?.EmployeeOid is long owner && owner == BeWoApp.CompactLoggedOnEmployee.EmployeeOid;
}
public AiPromptbausteinFolderVM Parent { get; set; }
public FontWeight FontWeight => !IsNew && Parent is null ? FontWeights.SemiBold : FontWeights.Medium;
public bool HasSubFolders => SubFolders is object && SubFolders.Count > 0;
public string Displayname
{
get
{
if (TotalPromptCount > 0)
{
return $"{Title} ({TotalPromptCount})";
}
return Title;
}
}
public int TotalPromptCount
{
@@ -183,6 +260,21 @@ namespace BeWo.ViewModel
}
}
public int TotalRoutineCount
{
get
{
var total = SubRoutines.Count;
foreach (var folder in SubFolders.VMList)
{
total += folder.TotalRoutineCount;
}
return total;
}
}
protected override void InitByDataContract(AiPromptbausteinFolderDC pDataContract)
{
_Title = pDataContract.Title;
@@ -193,8 +285,13 @@ namespace BeWo.ViewModel
_Position = pDataContract.Position;
_IsExpanded = pDataContract.IsExpanded;
_ActionType = pDataContract.ActionType;
_SubFolders = new AiPromptbausteinFolderListVM(pDataContract.SubFolders, this);
_CanAddFolder = pDataContract.CanAddFolder;
_CanAddPrompt = pDataContract.CanAddPrompt;
_CanAddRoutine = pDataContract.CanAddRoutine;
_CanEdit = pDataContract.CanEdit;
SubFolders = new AiPromptbausteinFolderListVM(pDataContract.SubFolders, this);
SubPrompts = new AiPromptbausteinPromptListVM(pDataContract.SubPrompts);
SubRoutines = new AiPromptbausteinRoutineListVM(pDataContract.SubRoutines);
}
protected override AiPromptbausteinFolderDC MapToDataContract(AiPromptbausteinFolderDC pDataContract, bool doCommit)
@@ -208,12 +305,18 @@ namespace BeWo.ViewModel
pDataContract.ActionType = _ActionType;
pDataContract.SubFolders = _SubFolders.CopyToDCList(doCommit);
pDataContract.SubPrompts = _SubPrompts.CopyToDCList(doCommit);
pDataContract.SubRoutines = _SubRoutines.CopyToDCList(doCommit);
return pDataContract;
}
public override void UpdateByDataContract(AiPromptbausteinFolderDC pDataContract)
{
if(IsNew)
IsNew = false;
DataContract = pDataContract;
Title = pDataContract.Title;
Description = pDataContract.Description;
IsPublic = pDataContract.IsPublic;

View File

@@ -19,7 +19,6 @@ namespace BeWo.ViewModel
private bool _ShowPromptByTenant;
private bool _IsOwnsoftPrompt;
private string _OwnsoftRefLink;
private bool _IsSelected;
private bool _IsFavorite;
private AiActionType _ActionType;
@@ -106,26 +105,15 @@ namespace BeWo.ViewModel
set => SetProperty(ref _IsFavorite, value, nameof(IsFavorite), () => DataContract.IsFavorite, nameof(FontWeight));
}
public bool CanShareEdit
{
get => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteinShare);
}
public bool CanEdit
{
get => DataContract.CanEdit && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteineEdit);
set => DataContract.CanEdit = value;
}
public bool IsSelected
{
get => _IsSelected;
set => SetProperty(ref _IsSelected, value, nameof(IsSelected), nameof(IsInfoVisible));
}
public bool IsInfoVisible
{
get => IsOwnsoftPrompt && !string.IsNullOrWhiteSpace(OwnsoftRefLink) && IsSelected;
get => IsOwnsoftPrompt && !string.IsNullOrWhiteSpace(OwnsoftRefLink);
}
public FontWeight FontWeight
@@ -138,6 +126,8 @@ namespace BeWo.ViewModel
get => ShowPrompt && ShowPromptByTenant;
}
public string FavoritenHeader => IsFavorite ? "Favorit entfernen" : "Favorit hinzufügen";
protected override void InitByDataContract(AiPromptbausteinPromptDC pDataContract)
{
_Title = pDataContract.Title;
@@ -176,6 +166,9 @@ namespace BeWo.ViewModel
public override void UpdateByDataContract(AiPromptbausteinPromptDC pDataContract)
{
if (IsNew)
IsNew = false;
Title = pDataContract.Title;
Description = pDataContract.Description;
ParentFolderOid = pDataContract.ParentFolderOid;
@@ -189,6 +182,10 @@ namespace BeWo.ViewModel
OwnsoftRefLink = pDataContract.OwnsoftRefLink;
IsFavorite = pDataContract.IsFavorite;
ActionType = pDataContract.ActionType;
DataContract = pDataContract;
SetDirty(false);
}
public override bool IsDirty

View File

@@ -26,7 +26,7 @@ namespace BeWo.ViewModel
public AiPromptbausteinPromptDC PromptReference
{
get => _PromptReference;
set => SetProperty(ref _PromptReference, value, nameof(PromptReference), () => DataContract.PromptReference);
set => SetProperty(ref _PromptReference, value, nameof(PromptReference), () => DataContract.ReferencePrompt);
}
public long ReferenceVersion
@@ -35,20 +35,40 @@ namespace BeWo.ViewModel
set => SetProperty(ref _ReferenceVersion, value, nameof(ReferenceVersion), () => DataContract.ReferenceVersion);
}
public bool IsValid
{
get => DataContract.IsValid;
}
protected override void InitByDataContract(AiPromptbausteinRoutineStepDC pDataContract)
{
_Position = pDataContract.Position;
_PromptReference = pDataContract.PromptReference;
_PromptReference = pDataContract.ReferencePrompt;
_ReferenceVersion = pDataContract.ReferenceVersion;
}
protected override AiPromptbausteinRoutineStepDC MapToDataContract(AiPromptbausteinRoutineStepDC pDataContract, bool doCommit)
{
pDataContract.Position = _Position;
pDataContract.PromptReference = _PromptReference;
pDataContract.ReferencePrompt = _PromptReference;
pDataContract.ReferenceVersion = _ReferenceVersion;
return pDataContract;
}
public override void UpdateByDataContract(AiPromptbausteinRoutineStepDC pDataContract)
{
DataContract = pDataContract;
Position = pDataContract.Position;
PromptReference = pDataContract.ReferencePrompt;
ReferenceVersion = pDataContract.ReferenceVersion;
}
public void SetIsValid(bool isValid)
{
DataContract.IsValid = isValid;
FirePropertyChanged(nameof(IsValid));
}
}
}

View File

@@ -1,9 +1,11 @@
using System;
using System.Linq;
using BeWo.ViewModel.ListViewModel;
using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.Extensions;
namespace BeWo.ViewModel
{
@@ -17,6 +19,7 @@ namespace BeWo.ViewModel
private int _Position;
private bool _IsFavorite;
private AiActionType _ActionType;
private AiRoutineType _RoutineType;
private bool _CanEdit;
private AiPromptbausteinRoutineStepListVM _Steps;
@@ -73,6 +76,12 @@ namespace BeWo.ViewModel
set => SetProperty(ref _ActionType, value, nameof(ActionType), () => DataContract.ActionType);
}
public AiRoutineType RoutineType
{
get => _RoutineType;
set => SetProperty(ref _RoutineType, value, nameof(RoutineType), () => DataContract.RoutineType);
}
public bool CanEdit
{
get => _CanEdit;
@@ -85,6 +94,14 @@ namespace BeWo.ViewModel
set => SetProperty(ref _Steps, value, nameof(Steps));
}
public string FavoritenHeader => IsFavorite ? "Favorit entfernen" : "Favorit hinzufügen";
public override bool IsDirty => base.IsDirty || Steps.IsDirty;
public bool IsValid
{
get => Steps.Count > 0 && Steps.VMList.All(x => x.IsValid);
}
protected override void InitByDataContract(AiPromptbausteinRoutineDC pDataContract)
{
_Title = pDataContract.Title;
@@ -95,6 +112,7 @@ namespace BeWo.ViewModel
_Position = pDataContract.Position;
_IsFavorite = pDataContract.IsFavorite;
_ActionType = pDataContract.ActionType;
_RoutineType = pDataContract.RoutineType;
_CanEdit = pDataContract.CanEdit;
_Steps = new AiPromptbausteinRoutineStepListVM(pDataContract.Steps);
@@ -110,11 +128,27 @@ namespace BeWo.ViewModel
pDataContract.Position = _Position;
pDataContract.IsFavorite = _IsFavorite;
pDataContract.ActionType = _ActionType;
pDataContract.RoutineType = _RoutineType;
pDataContract.CanEdit = _CanEdit;
pDataContract.Steps = _Steps.CopyToDCList(doCommit);
pDataContract.Steps = _Steps.CopyToDCList(true);
return pDataContract;
}
public override void UpdateByDataContract(AiPromptbausteinRoutineDC pDataContract)
{
if (IsNew)
IsNew = false;
DataContract = pDataContract;
Title = pDataContract.Title;
Description = pDataContract.Description;
IsPublic = pDataContract.IsPublic;
IsFavorite = pDataContract.IsFavorite;
RoutineType = pDataContract.RoutineType;
Steps.UpdateByDataContracts(pDataContract.Steps);
}
}
}

View File

@@ -0,0 +1,207 @@
using BeWo.ServiceProxy;
using BeWo.View.Controls.AI;
using BeWo.View.Detail.AI;
using BeWo.ViewModel.View.AI;
using BS.Shared;
using BS.Shared.DataContracts.Feature.AI;
using DevExpress.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
namespace BeWo.ViewModel.Controls.AI
{
public enum AiChatButtonState
{
Hidden,
Normal,
Loading,
Warning,
Disabled
}
public class AiChatButtonViewModel : AbstractBaseVM
{
private bool isVisible;
private bool canExecute;
private AiChatButtonState buttonState;
public AiActionType ActionType { get; protected set; }
public bool IsFavoritenOpen { get; set; }
public List<AiMenuItemTemplate> AssistentCommands { get; protected set; }
public virtual bool IsHistoryEnabled => false;
public virtual bool IsHistoryVisible => false;
public bool IsEnabled => BeWoApp.AppSettings.ShowAI && BeWoApp.HasLoggedOnUserRight(GetUserRightType());
public bool IsVisible
{
get => isVisible;
set => SetProperty(ref isVisible, value, nameof(IsVisible));
}
public bool CanExecute
{
get => canExecute;
set => SetProperty(ref canExecute, value, nameof(CanExecute));
}
public AiChatButtonState ButtonState
{
get => buttonState;
set
{
if (!SetProperty(ref buttonState, value, nameof(ButtonState)))
return;
FirePropertyChanged(nameof(IsContextSizeTooBig));
FirePropertyChanged(nameof(CanSendNewMessage));
FirePropertyChanged(nameof(CanOpenConversation));
CommandManager.InvalidateRequerySuggested();
}
}
public Func<AiViewContextDC> GetAiVisualContext { get; set; }
public AiPromptbausteinSelectionComplexViewModel AllPromptsViewModel { get; set; }
public DelegateCommand OpenConversationPopupCommand { get; protected set; }
public DelegateCommand OpenAllPromptsPopupCommand { get; protected set; }
public DelegateCommand OpenFavoritePromptsPopupCommand { get; protected set; }
public bool IsContextSizeTooBig => ButtonState == AiChatButtonState.Warning;
public virtual bool CanSendNewMessage => ButtonState == AiChatButtonState.Normal;
public bool CanOpenConversation => ButtonState == AiChatButtonState.Normal || ButtonState == AiChatButtonState.Warning;
public AiChatButtonViewModel(AiActionType aiActionType)
{
ActionType = aiActionType;
if (!IsEnabled)
return;
canExecute = false;
isVisible = false;
OpenConversationPopupCommand = new DelegateCommand(OpenConversationPopup, () => CanOpenConversation);
OpenAllPromptsPopupCommand = new DelegateCommand(OpenAllPromptsPopup, () => CanSendNewMessage);
OpenFavoritePromptsPopupCommand = new DelegateCommand(OpenFavoritePromptsPopup, () => CanSendNewMessage);
ButtonState = AiChatButtonState.Loading;
}
public void CheckContextSize()
{
if (!IsEnabled)
return;
ButtonState = AiChatButtonState.Loading;
var context = GetAiVisualContext();
if (context != null)
{
if (context.Primary is null)
{
IsVisible = false;
ButtonState = AiChatButtonState.Disabled;
return;
}
IsVisible = true;
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.CheckContextSize(ActionType, context),
isValid =>
{
if (isValid)
ButtonState = AiChatButtonState.Normal;
else
ButtonState = AiChatButtonState.Warning;
},
(exp) => ButtonState = AiChatButtonState.Disabled);
}
}
public void ReloadData(bool value, Action<AiActionType, List<AiPromptbausteinFolderDC>> initPromptbausteine)
{
if (!IsEnabled)
return;
var actionType = ActionType;
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiPromptbausteinFolder(actionType), folders => initPromptbausteine(actionType, folders),
null,
true);
}
public void ItemAccepted(AbstractBaseVM e)
{
if (e is AiPromptbausteinPromptVM prompt)
{
var vm = GetConversationViewModel();
vm.InputItem = prompt;
BeWoApp.WindowService.Show(vm);
return;
}
else if (e is AiPromptbausteinRoutineVM routine)
{
var vm = GetConversationViewModel();
vm.InputItem = routine;
BeWoApp.WindowService.Show(vm);
return;
}
throw new NotImplementedException();
}
private protected AiConversationChatViewModel GetConversationViewModel()
{
var context = GetAiVisualContext();
var chat_viewmodel = VMFactory.CreateAiConversationChatViewModel(ActionType, context, AssistentCommands, CanSendNewMessage);
return chat_viewmodel;
}
private protected void OpenConversationPopup()
{
BeWoApp.WindowService.Show(GetConversationViewModel());
}
private protected void OpenAllPromptsPopup()
{
BeWoApp.WindowService.Show(AllPromptsViewModel);
}
private protected void OpenFavoritePromptsPopup()
{
IsFavoritenOpen = true;
FirePropertyChanged(nameof(IsFavoritenOpen));
}
private UserRightType GetUserRightType()
{
switch (ActionType)
{
case AiActionType.ServiceRecord:
break;
case AiActionType.ServiceRecordConversation:
return UserRightType.AiModuleServiceRecordChat;
case AiActionType.ServiceRecordDocumentation:
return UserRightType.AiModuleServiceRecordDocu;
default:
break;
}
throw new InvalidOperationException($"UserRightType '{ActionType}' not implemented");
}
}
public class AiMenuItemTemplate
{
public string Icon { get; set; }
public string Name { get; set; }
public DelegateCommand<AiConversationMessageVM> Command { get; set; }
}
}

View File

@@ -0,0 +1,153 @@
using BS.Shared;
using BS.Shared.Interface;
using DevExpress.Mvvm;
using DevExpress.XtraPrinting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.ViewModel.Controls.AI
{
public class AiChatButtonWithHistoryViewModel : AiChatButtonViewModel
{
private readonly ITextProvider _provider;
private readonly string _key;
private int _currentIndex;
public List<string> History { get; set; }
public string CurrentValue
{
get => _provider.GetText(_key);
set => _provider.SetText(_key, value);
}
public int CurrentIndex
{
get => _currentIndex;
set {
if(SetProperty(ref _currentIndex, value, nameof(CurrentIndex)))
{
FirePropertyChanged(nameof(IsUndoButtonVisible));
FirePropertyChanged(nameof(IsRedoButtonVisible));
}
}
}
public override bool IsHistoryEnabled => true;
public override bool IsHistoryVisible => History.Count > 1;
public bool IsUndoButtonVisible => CurrentIndex > 0;
public bool IsRedoButtonVisible => CurrentIndex < History.Count - 1;
public DelegateCommand UndoAiActionCommand { get; protected set; }
public DelegateCommand RedoAiActionCommand { get; protected set; }
public AiChatButtonWithHistoryViewModel(AiActionType aiActionType, ITextProvider provider, string key) : base(aiActionType)
{
History = new List<string>();
CurrentIndex = 0;
AssistentCommands = new List<AiMenuItemTemplate>()
{
new AiMenuItemTemplate()
{
Command = new DelegateCommand<AiConversationMessageVM>(x => AddValue(x.Message)),
Icon = null,
Name = "Anfügen"
},
new AiMenuItemTemplate()
{
Command = new DelegateCommand<AiConversationMessageVM>(x => ReplaceValue(x.Message)),
Icon = null,
Name = "Ersetzen"
},
};
UndoAiActionCommand = new DelegateCommand(UndoAiAction);
RedoAiActionCommand = new DelegateCommand(RedoAiAction);
_provider = provider;
_key = key;
}
public override bool CanSendNewMessage => base.CanSendNewMessage && !string.IsNullOrEmpty(CurrentValue);
public void ClearHistory()
{
History.Clear();
History.Add(CurrentValue);
CurrentIndex = 0;
FirePropertyChanged(nameof(IsHistoryVisible));
}
public void UndoAiAction()
{
if (CurrentIndex <= 0)
return;
CurrentIndex--;
CurrentValue = History[CurrentIndex];
}
public void RedoAiAction()
{
if (CurrentIndex >= History.Count - 1)
return;
CurrentIndex++;
CurrentValue = History[CurrentIndex];
}
public void AddValue(string s)
{
var sb = new StringBuilder();
sb.AppendLine("Antwort:");
sb.AppendLine(s);
sb.AppendLine();
sb.AppendLine("Original:");
sb.AppendLine(CurrentValue);
var str = sb.ToString();
accept(str);
}
public void ReplaceValue(string str)
{
accept(str);
}
private void accept(string str)
{
var idx = CurrentIndex;
var count = History.Count;
var last_idx = count - 1;
if (last_idx > idx)
{
History.RemoveRange(idx + 1, last_idx - idx);
}
if (History.Count == 0)
{
History.Add(CurrentValue);
}
else if (CurrentValue != History[CurrentIndex])
{
History.Add(CurrentValue);
CurrentIndex++;
}
History.Add(str);
CurrentIndex++;
CurrentValue = str;
FirePropertyChanged(nameof(IsHistoryVisible));
}
}
}

View File

@@ -0,0 +1,18 @@
using DevExpress.Mvvm;
namespace BeWo.ViewModel
{
/// <summary>
/// Gemeinsamer Vertrag der Promptbaustein-ViewModels (Verwaltung + Auswahl),
/// gegen den das AiPromptbausteinLibraryControl im Code-Behind arbeitet.
/// </summary>
public interface IAiPromptbausteinComplexViewModel
{
AiPromptbausteinFolderVM SelectedFolder { get; set; }
DelegateCommand OpenEditFolderDialogCommand { get; }
void UpdateFolderCommands();
void UpdatePromptCommands();
}
}

View File

@@ -291,5 +291,10 @@ namespace BeWo.ViewModel.ListViewModel
{
return null;
}
}
public virtual void UpdateByDataContracts(List<DCType> pDataContracts)
{
throw new NotImplementedException();
}
}
}

View File

@@ -90,7 +90,7 @@ namespace BeWo.ViewModel.ListViewModel
Displayname = "Displayname Megamegalange Deluxe Op 3000",
Messages = messages_dc,
Modell = model,
UIContext = AiContextType.ServiceRecord,
ActionType = AiActionType.ServiceRecordDocumentation,
Updated = DateTime.Now,
};
@@ -116,7 +116,7 @@ namespace BeWo.ViewModel.ListViewModel
Created = DateTime.Now,
Displayname = "Dummy Num " + i.ToString(),
Modell = model,
UIContext = AiContextType.ServiceRecord,
ActionType = AiActionType.ServiceRecordDocumentation,
Updated = DateTime.Now,
};

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.Extensions;
namespace BeWo.ViewModel.ListViewModel
{
@@ -13,5 +14,43 @@ namespace BeWo.ViewModel.ListViewModel
{
}
public override void UpdateByDataContracts(List<AiPromptbausteinRoutineStepDC> pDataContracts)
{
var count_a = Count;
var count_b = pDataContracts.Count;
// 1-k updaten
var count_toupdate = Math.Min(count_a, count_b);
for ( var i = 0; i < count_toupdate; i++)
{
var a = VMList[i];
var b = pDataContracts[i];
a.UpdateByDataContract(b);
}
if (count_a == count_b)
return;
if(count_a > count_b)
{
for (var i = count_a - 1; i > count_toupdate - 1; i--)
{
VMList.RemoveAt(i);
}
}
else
{
for (int i = count_toupdate; i < count_b; i++)
{
var dc = pDataContracts[i];
var vm = new AiPromptbausteinRoutineStepVM(dc);
VMList.Add(vm);
}
}
FirePropertyChanged(nameof(Count));
}
}
}

View File

@@ -79,7 +79,7 @@ namespace BeWo.ViewModel.ListViewModel
// Holt bereits geladene
if (invoice_base.XRechnungStoredFileVM is StoredFileVM vm && vm.Data is byte[] bytes)
{
BeWoApp.MainControl.WindowService.ShowERechnungWindow(new MemoryStream(bytes));
BeWoApp.WindowService.ShowERechnungWindow(new MemoryStream(bytes));
return;
}
@@ -103,7 +103,7 @@ namespace BeWo.ViewModel.ListViewModel
invoice_base.XRechnungStoredFileVM.Data = bytes;
BeWoApp.MainControl.WindowService.ShowERechnungWindow(new MemoryStream(bytes));
BeWoApp.WindowService.ShowERechnungWindow(new MemoryStream(bytes));
}
else
{

View File

@@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
@@ -13,6 +14,7 @@ using BeWo.Core.Commands;
using BeWo.Core.Service;
using BeWo.ServiceProxy;
using BeWo.View.Controls.AI;
using BeWo.ViewModel.Controls.AI;
using BeWo.ViewModel.View.AI;
using BS.Shared;
using BS.Shared.Core;
@@ -20,7 +22,9 @@ using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.DataContracts.Feature.AI.Functions.ServiceRecords;
using BS.Shared.Exceptions;
using BS.Shared.Extensions;
using BS.Shared.Interface;
using BS.Shared.Services;
using DevExpress.Mvvm;
using DevExpress.Xpf.Editors.ExpressionEditor;
@@ -30,7 +34,7 @@ using DispatcherObject = System.Windows.Threading.DispatcherObject;
namespace BeWo.ViewModel.ListViewModel
{
public class ServiceRecordListVM : AbstractDCListMapperVM<ServiceRecordDC, ServiceRecordVM>
public class ServiceRecordListVM : AbstractDCListMapperVM<ServiceRecordDC, ServiceRecordVM>, ITextProvider
{
public static string PropertyName_CustomerNodes = "CustomerNodes";
public static string PropertyName_Information = "Information";
@@ -100,21 +104,12 @@ namespace BeWo.ViewModel.ListViewModel
//private static List<DarreichungsformDC> _AllDosageForms;
private List<string> _AiActionHistory;
private int _AiActionHistoryIndex;
private AiConversationButtonState _AiConversationButtonState;
public ICommand UndoAiActionCommand { get; set; }
public ICommand RedoAiActionCommand { get; set; }
private List<string> _EditAiActionHistory;
private int _EditAiActionHistoryIndex;
public ICommand UndoEditAiActionCommand { get; set; }
public ICommand RedoEditAiActionCommand { get; set; }
public AiUserSettingVM AiUserSetting { get; set; }
public AiChatButtonViewModel AiChatButtonConversationViewModel { get; set; }
public AiChatButtonWithHistoryViewModel AiChatButtonDocumentationViewModel { get; set; }
public AiChatButtonWithHistoryViewModel AiChatButtonDocumentationEditViewModel { get; set; }
public ServiceRecordListVM(
Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> pCategory2Services,
IEnumerable<ValueListEntryDC> pAllGoalCategories,
@@ -187,42 +182,14 @@ namespace BeWo.ViewModel.ListViewModel
private void InitAiStuff()
{
//var vm_doku = new AiPromptbausteinSelectionComplexViewModel(AiActionType.ServiceRecordDocumentation);
AiChatButtonConversationViewModel
= new AiChatButtonViewModel(AiActionType.ServiceRecordConversation);
//vm_doku.PromptAccepted += PromptAccepted;
AiChatButtonDocumentationViewModel
= new AiChatButtonWithHistoryViewModel(AiActionType.ServiceRecordDocumentation, this, "docu");
//OpenAiPromptSelectionCommand = CommandFactory.GetAiViewCommand(
// () => BeWoApp.MainControl.WindowService.Show(vm_doku),
// null,
// () => !string.IsNullOrWhiteSpace(AktuellerDokutext));
UndoAiActionCommand = new DelegateCommand(UndoAiAction);
RedoAiActionCommand = new DelegateCommand(RedoAiAction);
//var vm_edit_doku = new AiPromptbausteinSelectionComplexViewModel(AiActionType.ServiceRecordDocumentation);
//vm_edit_doku.PromptAccepted += EditPromptAccepted;
//OpenEditAiPromptSelectionCommand = CommandFactory.GetAiViewCommand(() =>
//{
// _EditAiActionHistory = new List<string>();
// _EditAiActionHistory.Add(AktuellerEditDokutext);
// _EditAiActionHistoryIndex = 0;
// BeWoApp.MainControl.WindowService.Show(vm_edit_doku);
//},
//null,
//() => !string.IsNullOrWhiteSpace(AktuellerEditDokutext));
UndoEditAiActionCommand = new DelegateCommand(UndoEditAiAction);
RedoEditAiActionCommand = new DelegateCommand(RedoEditAiAction);
_AiActionHistory = new List<string>();
_AiActionHistory.Add(AktuellerDokutext);
_AiActionHistoryIndex = 0;
_EditAiActionHistory = new List<string>();
_EditAiActionHistory.Add(AktuellerEditDokutext);
_EditAiActionHistoryIndex = 0;
AiChatButtonDocumentationEditViewModel
= new AiChatButtonWithHistoryViewModel(AiActionType.ServiceRecordDocumentation, this, "edit_docu");
}
private void InitAiTranscriptionStuff()
@@ -240,12 +207,6 @@ namespace BeWo.ViewModel.ListViewModel
FirePropertyChanged(nameof(AiUserSetting));
}
public AiConversationButtonState AiConversationButtonState
{
get => _AiConversationButtonState;
set => SetProperty(ref _AiConversationButtonState, value, nameof(AiConversationButtonState));
}
public IEnumerable<ServiceRecordVM> CurrentVisibleVMs { get; set; }
public string AktuellerDokutext
{
@@ -253,9 +214,6 @@ namespace BeWo.ViewModel.ListViewModel
set
{
PrototypeVM.Notice = value;
FirePropertyChanged(nameof(IsAiDocuButtonCanExecute));
FirePropertyChanged(nameof(IsRedoButtonVisible));
FirePropertyChanged(nameof(IsUndoButtonVisible));
}
}
public string AktuellerEditDokutext
@@ -264,8 +222,6 @@ namespace BeWo.ViewModel.ListViewModel
set
{
EditVM.Notice = value;
FirePropertyChanged(nameof(IsEditUndoButtonVisible));
FirePropertyChanged(nameof(IsEditRedoButtonVisible));
}
}
@@ -273,269 +229,13 @@ namespace BeWo.ViewModel.ListViewModel
public bool IsAiChatButtonVisible => SelectedCustomerNode is object && IsAiModuleEnabled && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleServiceRecordChat);
public bool IsAiDocuButtonVisible => SelectedCustomerNode is object && IsAiModuleEnabled && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleServiceRecordDocu);
public bool IsAiRowVisible => IsAiDocuButtonVisible || VoiceToTextButtonControl.HasRightToUseAIVoice;
public bool IsAiDocuButtonCanExecute => !string.IsNullOrWhiteSpace(AktuellerDokutext);
public bool IsUndoButtonVisible => _AiActionHistoryIndex > 0;
public bool IsRedoButtonVisible => _AiActionHistoryIndex < _AiActionHistory.Count - 1;
public bool IsEditUndoButtonVisible => _EditAiActionHistoryIndex > 0;
public bool IsEditRedoButtonVisible => _EditAiActionHistoryIndex < (_EditAiActionHistory?.Count ?? 0) - 1;
public void PromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
{
if (prompt is null)
throw new NotImplementedException();
// 1. Information aufbereiten
// 1.1 Prompt
var prompt_oid = prompt.DataContract.Oid.Value;
var prompt_version = prompt.DataContract.Version;
// 1.2 Hilfeplan
var support_concept = SelectedCustomerNode.SupportConceptTreeNodeDC.SupportConcept;
var support_concept_oid = support_concept.SupportConceptOid;
var support_concept_version = support_concept.SupportConceptVersion;
// 1.3 Aktuelles Doku Feld
var doku_feld = AktuellerDokutext;
// 1.4 Sichtbaren Zeiterfassungseinträge
var service_records = CurrentVisibleVMs;
var sr_refs = service_records.Select(x => new BeWoRefDC(x.DataContract.ServiceRecordOid.Value, x.DataContract.ServiceRecordVersion));
// 1.5 Costbearer
var costbearer = SelectedCustomerNode.SupportConceptTreeNodeDC.CostBearer;
var cb_oid = costbearer.CostBearerOid.Value;
var cb_ver = costbearer.CostBearerVersion;
// Service Aufruf
var req = new AiFunctionDocRequest()
{
AiPromptbausteinPrompt = new BeWoRefDC(prompt_oid, prompt_version),
SupportConcept = new BeWoRefDC(support_concept_oid, support_concept_version),
ServiceRecords = sr_refs,
CostBearer = new BeWoRefDC(cb_oid, cb_ver),
Dokumentation = doku_feld,
};
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.ExecuteAiFunctionServiceRecordDocumentation(req),
callback =>
{
var viewModel = new AiPromptbausteinActionResultViewModel();
viewModel.Result = callback.Result;
viewModel.Accept_Button_Clicked += (s, e) =>
{
var sb = new StringBuilder();
sb.AppendLine("AI Antwort:");
sb.AppendLine(viewModel.Result);
sb.AppendLine();
sb.AppendLine("Original:");
sb.AppendLine(AktuellerDokutext);
var str = sb.ToString();
var idx = _AiActionHistoryIndex;
var count = _AiActionHistory.Count;
if (count - 1 > idx)
{
_AiActionHistory.RemoveRange(idx + 1, count - idx - 1);
}
if (AktuellerDokutext != _AiActionHistory[_AiActionHistoryIndex])
{
_AiActionHistory.Add(AktuellerDokutext);
_AiActionHistoryIndex++;
}
_AiActionHistory.Add(str);
_AiActionHistoryIndex++;
AktuellerDokutext = str;
};
viewModel.Replace_Button_Clicked += (s, e) =>
{
var str = viewModel.Result;
var idx = _AiActionHistoryIndex;
var count = _AiActionHistory.Count;
if (count - 1 > idx)
{
_AiActionHistory.RemoveRange(idx + 1, count - idx - 1);
}
if (AktuellerDokutext != _AiActionHistory[_AiActionHistoryIndex])
{
_AiActionHistory.Add(AktuellerDokutext);
_AiActionHistoryIndex++;
}
_AiActionHistory.Add(str);
_AiActionHistoryIndex++;
AktuellerDokutext = str;
};
viewModel.Retry_Button_Clicked += (s, e) =>
{
PromptAccepted(sender, prompt);
};
BeWoApp.MainControl.WindowService.Show(viewModel);
}
);
}
public void EditPromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
{
if (prompt is null)
throw new NotImplementedException();
// 1. Information aufbereiten
// 1.1 Prompt
var prompt_oid = prompt.DataContract.Oid.Value;
var prompt_version = prompt.DataContract.Version;
// 1.2 Hilfeplan
var support_concept = SelectedCustomerNode.SupportConceptTreeNodeDC.SupportConcept;
var support_concept_oid = support_concept.SupportConceptOid;
var support_concept_version = support_concept.SupportConceptVersion;
// 1.3 Aktuelles Doku Feld
var doku_feld = AktuellerEditDokutext;
// 1.4 Sichtbaren Zeiterfassungseinträge
var service_records = CurrentVisibleVMs;
var sr_refs = service_records.Select(x => new BeWoRefDC(x.DataContract.ServiceRecordOid.Value, x.DataContract.ServiceRecordVersion));
// 1.5 Costbearer
var costbearer = SelectedCustomerNode.SupportConceptTreeNodeDC.CostBearer;
var cb_oid = costbearer.CostBearerOid.Value;
var cb_ver = costbearer.CostBearerVersion;
// Service Aufruf
var req = new AiFunctionDocRequest()
{
AiPromptbausteinPrompt = new BeWoRefDC(prompt_oid, prompt_version),
SupportConcept = new BeWoRefDC(support_concept_oid, support_concept_version),
ServiceRecords = sr_refs,
CostBearer = new BeWoRefDC(cb_oid, cb_ver),
Dokumentation = doku_feld,
};
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.ExecuteAiFunctionServiceRecordDocumentation(req),
callback =>
{
var viewModel = new AiPromptbausteinActionResultViewModel();
viewModel.Result = callback.Result;
viewModel.Accept_Button_Clicked += (s, e) =>
{
var sb = new StringBuilder();
sb.AppendLine("AI Antwort:");
sb.AppendLine(viewModel.Result);
sb.AppendLine();
sb.AppendLine("Original:");
sb.AppendLine(AktuellerEditDokutext);
var str = sb.ToString();
var idx = _EditAiActionHistoryIndex;
var count = _EditAiActionHistory.Count;
if (count - 1 > idx)
{
_EditAiActionHistory.RemoveRange(idx + 1, count - idx - 1);
}
if (AktuellerEditDokutext != _EditAiActionHistory[_EditAiActionHistoryIndex])
{
_EditAiActionHistory.Add(AktuellerEditDokutext);
_EditAiActionHistoryIndex++;
}
_EditAiActionHistory.Add(str);
_EditAiActionHistoryIndex++;
AktuellerEditDokutext = str;
};
viewModel.Replace_Button_Clicked += (s, e) =>
{
var str = viewModel.Result;
var idx = _EditAiActionHistoryIndex;
var count = _EditAiActionHistory.Count;
if (count - 1 > idx)
{
_EditAiActionHistory.RemoveRange(idx + 1, count - idx - 1);
}
if (AktuellerEditDokutext != _EditAiActionHistory[_EditAiActionHistoryIndex])
{
_EditAiActionHistory.Add(AktuellerEditDokutext);
_EditAiActionHistoryIndex++;
}
_EditAiActionHistory.Add(str);
_EditAiActionHistoryIndex++;
AktuellerEditDokutext = str;
};
viewModel.Retry_Button_Clicked += (s, e) =>
{
PromptAccepted(sender, prompt);
};
BeWoApp.MainControl.WindowService.Show(viewModel);
}
);
}
public void UpdateViewYearFilter(IEnumerable<ServiceRecordVM> enumerable)
{
if (!IsAiChatButtonVisible)
{
AiConversationButtonState = AiConversationButtonState.Hidden;
return;
}
AiConversationButtonState = AiConversationButtonState.Loading;
var context = GetVisibleInformationReferences(enumerable);
if (context != null)
{
var context2 = context.ToDictionary(kv => kv.Key, kv => kv.Value.ToList());
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.CheckContextSize(AiContextType.ServiceRecord, context2, null),
isValid =>
{
if (isValid)
AiConversationButtonState = AiConversationButtonState.Normal;
else
AiConversationButtonState = AiConversationButtonState.Warning;
},
(exp) => AiConversationButtonState = AiConversationButtonState.Disabled);
}
AiChatButtonConversationViewModel.CheckContextSize();
AiChatButtonDocumentationViewModel.CheckContextSize();
}
public void ResetAiAction()
{
_AiActionHistory.Clear();
_AiActionHistory.Add(AktuellerDokutext);
_AiActionHistoryIndex = 0;
FirePropertyChanged(nameof(IsRedoButtonVisible));
FirePropertyChanged(nameof(IsUndoButtonVisible));
}
public void ResetEditAiAction()
{
_EditAiActionHistory.Clear();
_EditAiActionHistory.Add(AktuellerDokutext);
_EditAiActionHistoryIndex = 0;
FirePropertyChanged(nameof(IsEditRedoButtonVisible));
FirePropertyChanged(nameof(IsEditUndoButtonVisible));
}
public Dictionary<TableID, long[]> GetVisibleInformationReferences(IEnumerable<ServiceRecordVM> selected_records)
{
var current = SelectedCustomerNode;
@@ -973,42 +673,6 @@ namespace BeWo.ViewModel.ListViewModel
private DateTime? enddate;
public void UndoAiAction()
{
if (_AiActionHistoryIndex <= 0)
return;
_AiActionHistoryIndex--;
AktuellerDokutext = _AiActionHistory[_AiActionHistoryIndex];
}
public void RedoAiAction()
{
if (_AiActionHistoryIndex >= _AiActionHistory.Count - 1)
return;
_AiActionHistoryIndex++;
AktuellerDokutext = _AiActionHistory[_AiActionHistoryIndex];
}
public void UndoEditAiAction()
{
if (_EditAiActionHistoryIndex <= 0)
return;
_EditAiActionHistoryIndex--;
AktuellerEditDokutext = _EditAiActionHistory[_EditAiActionHistoryIndex];
}
public void RedoEditAiAction()
{
if (_EditAiActionHistoryIndex >= _EditAiActionHistory.Count - 1)
return;
_EditAiActionHistoryIndex++;
AktuellerEditDokutext = _EditAiActionHistory[_EditAiActionHistoryIndex];
}
public List<ServiceRecordVM> CreateFromPrototype()
{
var lResult = new List<ServiceRecordVM>();
@@ -2353,5 +2017,37 @@ namespace BeWo.ViewModel.ListViewModel
return json;
}
public string GetText(string key)
{
if (key == "docu")
{
return AktuellerDokutext;
}
else if(key == "edit_docu")
{
return AktuellerEditDokutext;
}
else
{
throw new BeWoNotImplementedException($"key '{key}' unbekannt");
}
}
public void SetText(string key, string value)
{
if (key == "docu")
{
AktuellerDokutext = value;
}
else if (key == "edit_docu")
{
AktuellerEditDokutext = value;
}
else
{
throw new BeWoNotImplementedException($"key '{key}' unbekannt");
}
}
}
}

View File

@@ -5,6 +5,7 @@ using System.Windows.Threading;
using BeWo.Core.Service;
using BeWo.SchulbegleitenderDienst.ViewModel;
using BeWo.ServiceProxy;
using BeWo.ViewModel.Controls.AI;
using BeWo.ViewModel.ListViewModel;
using BeWo.ViewModel.View.AI;
using BS.Shared;
@@ -912,32 +913,38 @@ namespace BeWo.ViewModel
einheit_vm_list.VMList.Sort(WohneinheitVM.Compare);
}
public static AiConversationChatViewModel CreateAiConversationChatViewModel(AiContextType uIContext, Dictionary<TableID, long[]> bewoObjects,
long? reference_oid = null, bool canSendNewMessage = true)
public static AiConversationChatViewModel CreateAiConversationChatViewModel(AiActionType actionType, AiViewContextDC view_context, List<AiMenuItemTemplate> assistentCommands = null, bool canSendNewMessage = true)
{
var vm = new AiConversationChatViewModel();
vm.AiContext = uIContext;
vm.ContextBeWoObjects = bewoObjects;
vm.ReferenceObjectOid = reference_oid;
vm.ActionType = actionType;
vm.ViewContext = view_context;
vm.CanSendNewMessage = canSendNewMessage;
if (assistentCommands is object)
{
foreach (var command in assistentCommands)
{
vm.ImportAssistentCommand(command);
}
}
return vm;
}
public static AiConversationListVM CreateAiConversationListVM(AiContextType uIContext, long? reference_oid)
public static AiConversationListVM CreateAiConversationListVM(AiActionType actionType, long? reference_oid)
{
var list = ServiceFacade.DoAiEnhancedServiceSnyc(s => s.GetAiConversations(uIContext, reference_oid));
var list = ServiceFacade.DoAiEnhancedServiceSnyc(s => s.GetAiConversations(actionType, reference_oid));
list.Reverse();
return new AiConversationListVM(list);
}
public static void CreateAiConversationListVMAsync(AiContextType uIContext, long? reference_oid, Action<AiConversationListVM> callback)
public static void CreateAiConversationListVMAsync(AiActionType actionType, long? reference_oid, Action<AiConversationListVM> callback)
{
ServiceFacade.DoAiEnhancedServiceAsnyc(
s => s.GetAiConversations(uIContext, reference_oid),
s => s.GetAiConversations(actionType, reference_oid),
cb =>
{
cb.Reverse();
@@ -994,6 +1001,12 @@ namespace BeWo.ViewModel
if (prompt.IsFavorite)
favoriten.SubPrompts.VMList.Add(prompt);
}
foreach (var routine in folder.SubRoutines.VMList)
{
if (routine.IsFavorite)
favoriten.SubRoutines.VMList.Add(routine);
}
}
}
}

View File

@@ -14,6 +14,11 @@ using DevExpress.Mvvm;
using BeWo.ServiceProxy;
using BS.Shared.Extensions;
using System.Diagnostics;
using DevExpress.XtraCharts.Native;
using static DevExpress.Utils.Drawing.Helpers.NativeMethods;
using System.Security.Cryptography;
using BeWo.ViewModel.Controls.AI;
using DevExpress.Charts.Native;
namespace BeWo.ViewModel.View.AI
{
@@ -24,7 +29,6 @@ namespace BeWo.ViewModel.View.AI
private bool _IsSending;
private string _MessageInput;
private string _ContextInput;
private AiModelDC _SelectedModel;
private AiConfigVM _Config;
@@ -36,7 +40,7 @@ namespace BeWo.ViewModel.View.AI
Models = new ObservableSortCollection<AiModelDC>();
SendNewMessageCommand = new DelegateCommand(SendNewMessage, () => ListVM.SelectedVM is object && !string.IsNullOrWhiteSpace(MessageInput) && !IsSending);
OpenNewConversationCommand = new DelegateCommand(OpenNewConversation, () => CanSendNewMessage && BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleServiceRecordChat));
OpenNewConversationCommand = new DelegateCommand(OpenNewConversation, () => CanSendNewMessage && ListVM.SelectedVM is object);
StartConversationWithMessageCommand = new DelegateCommand(StartConversationWithMessage, () => CanSendNewMessage && !string.IsNullOrWhiteSpace(MessageInput) && !IsSending);
ReloadConfigCommand = new DelegateCommand(ReloadConfig);
@@ -44,11 +48,11 @@ namespace BeWo.ViewModel.View.AI
ReloadModelsCommand = new DelegateCommand(ReloadModels);
OpenSettingCommand = new DelegateCommand(OpenSetting, () => BeWoApp.AppSettings?.ModuleAiSettingsEnabled ?? false);
RenameCommand = new DelegateCommand(Rename, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleServiceRecordChat) && ListVM.SelectedVM is object);
RenameCommand = new DelegateCommand(Rename, () => ListVM.SelectedVM is object);
OpenCloneCommand = new DelegateCommand(OpenClone, () => ListVM.SelectedVM is object && BeWoAppInfo.IsInAiDeveloperMode);
CloneCommand = new DelegateCommand(Clone);
AskDeleteCommand = new DelegateCommand(AskDelete, () => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModuleServiceRecordChat) && ListVM.SelectedVM is object);
AskDeleteCommand = new DelegateCommand(AskDelete, () => ListVM.SelectedVM is object);
SavePromptCommand = new DelegateCommand<AiConversationMessageVM>(SavePrompt, vm => BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteineEdit));
AcceptSavePromptCommand = new DelegateCommand(AcceptSavePrompt, () => !string.IsNullOrWhiteSpace(SavePromptVM?.Title));
@@ -56,6 +60,8 @@ namespace BeWo.ViewModel.View.AI
ListVM = new AiConversationListVM();
ListVM.SelectedVMChanged += (s, e) => FirePropertyChanged(nameof(IsNewConversationVisible));
AssistentCommands = new List<AiMenuItemTemplate>();
}
public event EventHandler SendNewMessageSuccess;
@@ -63,8 +69,6 @@ namespace BeWo.ViewModel.View.AI
public ICommand SendNewMessageCommand { get; set; }
public ICommand OpenNewConversationCommand { get; set; }
public ICommand StartConversationWithMessageCommand { get; set; }
public ICommand RequestNewConversationCommand { get; set; }
public ICommand TestCommand { get; set; }
public ICommand AskDeleteCommand { get; set; }
public ICommand ReloadConfigCommand { get; set; }
public ICommand ReloadConversationsCommand { get; set; }
@@ -79,8 +83,10 @@ namespace BeWo.ViewModel.View.AI
public ICommand AcceptSavePromptCommand { get; set; }
public ICommand CancelSavePromptCommand { get; set; }
public AiActionType ActionType { get; set; }
public AiViewContextDC ViewContext { get; set; }
public bool CanSendNewMessage { get; set; }
public bool SendAfterLoaded { get; set; }
public AiConversationListVM ListVM { get; set; }
public ObservableCollection<AiModelDC> Models { get; set; }
@@ -121,18 +127,9 @@ namespace BeWo.ViewModel.View.AI
FirePropertyChanged(nameof(MessageInput));
}
}
public string ContextInput
{
get { return _ContextInput; }
set
{
if (ContextInput == value)
return;
public AbstractBaseVM InputItem { get; set; }
_ContextInput = value;
FirePropertyChanged(nameof(ContextInput));
}
}
public List<AiMenuItemTemplate> AssistentCommands { get; protected set; }
public bool IsSettingsOpen
{
@@ -163,10 +160,6 @@ namespace BeWo.ViewModel.View.AI
}
public bool IsNewConversationVisible => ListVM.SelectedVM is null;
public AiContextType AiContext { get; set; }
public long? ReferenceObjectOid { get; set; }
public Dictionary<TableID, long[]> ContextBeWoObjects { get; set; }
public AiPromptbausteinPromptVM SavePromptVM
{
get => _SavePromptVM;
@@ -188,6 +181,10 @@ namespace BeWo.ViewModel.View.AI
}
}
private void OpenNewConversation()
{
ListVM.SelectedVM = null;
}
private void StartConversationWithMessage()
{
StartSending();
@@ -200,8 +197,7 @@ namespace BeWo.ViewModel.View.AI
conv.Created = DateTime.Now;
conv.Updated = DateTime.Now;
conv.UIContext = AiContext;
conv.ContextBeWoObjects = ContextBeWoObjects;
conv.ActionType = ActionType;
conv.Messages = new List<AiConversationMessageDC>()
{
new AiConversationMessageDC()
@@ -214,7 +210,7 @@ namespace BeWo.ViewModel.View.AI
var vm = InsertConverstion(conv);
ServiceFacade.DoAiEnhancedServiceAsnyc(
x => x.CreateAiConversationWithMessage(conv, Config.SelectedModel.Oid.Value, message),
x => x.CreateAiConversationWithMessage(conv, ViewContext, message),
dc => UpdateConverstion(vm, dc),
e =>
{
@@ -228,10 +224,7 @@ namespace BeWo.ViewModel.View.AI
EndSending();
}
}
private void OpenNewConversation()
{
ListVM.SelectedVM = null;
}
private void SendNewMessage()
{
StartSending();
@@ -261,11 +254,7 @@ namespace BeWo.ViewModel.View.AI
conv.Messages.VMList.Add(new AiConversationMessageVM(messages[1]));
MessageInput = string.Empty;
EndSending();
SendNewMessageSuccess?.Invoke(this, EventArgs.Empty);
FinishSending();
},
(exception) =>
{
@@ -286,6 +275,7 @@ namespace BeWo.ViewModel.View.AI
throw new InvalidOperationException("Sendet bereits");
IsSending = true;
IsWaiting = true;
}
private void EndSending()
{
@@ -293,6 +283,7 @@ namespace BeWo.ViewModel.View.AI
throw new InvalidOperationException("Sendet nicht");
IsSending = false;
IsWaiting = false;
}
private AiConversationVM InsertConverstion(AiConversationDC dc)
@@ -308,6 +299,10 @@ namespace BeWo.ViewModel.View.AI
{
vm.UpdateByDataContract(dc);
FinishSending();
}
private void FinishSending()
{
MessageInput = string.Empty;
EndSending();
@@ -355,8 +350,8 @@ namespace BeWo.ViewModel.View.AI
}
private void ReloadConversations()
{
var ui_context = AiContext;
var reference = ReferenceObjectOid;
var ui_context = ActionType;
var reference = ViewContext.Primary;
var list = VMFactory.CreateAiConversationListVM(ui_context, reference);
@@ -453,11 +448,199 @@ namespace BeWo.ViewModel.View.AI
}
public void AcceptSavePrompt()
{
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinPrompt(new List<AiPromptbausteinPromptDC>() { SavePromptVM.CommitToDataContract() }), cb => SavePromptVM = null, exc => SavePromptVM = null);
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinPrompt(SavePromptVM.CommitToDataContract()), cb => SavePromptVM = null, exc => SavePromptVM = null);
}
public void CancelSavePrompt()
{
SavePromptVM = null;
}
public void ImportAssistentCommand(AiMenuItemTemplate origin)
{
var origin_command = origin.Command;
var new_command = new DelegateCommand<AiConversationMessageVM>(x =>
{
origin_command.Execute(x);
Close();
});
var imported_menu_item = new AiMenuItemTemplate()
{
Command = new_command,
Icon = origin.Icon,
Name = origin.Name
};
AssistentCommands.Add(imported_menu_item);
}
internal void Start()
{
if (InputItem is null)
return;
if (InputItem is AiPromptbausteinPromptVM prompt)
{
StartPrompt(prompt);
}
else if (InputItem is AiPromptbausteinRoutineVM routine)
{
StartRoutine(routine);
}
else
{
throw new ArgumentOutOfRangeException(nameof(InputItem));
}
InputItem = null;
}
private void StartPrompt(AiPromptbausteinPromptVM prompt)
{
StartSending();
try
{
var conv = new AiConversationDC();
conv.Created = DateTime.Now;
conv.Updated = DateTime.Now;
conv.ActionType = ActionType;
var vm = InsertConverstion(conv);
Action<Exception> error = (e) =>
{
EndSending();
ListVM.VMList.Remove(vm);
ServiceFacade.EndManuelWaiting();
};
ServiceFacade.StartManuelWaiting();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.CreateAiConversation(conv, ViewContext), cb =>
{
vm.UpdateByDataContract(cb);
var msg = prompt.Prompt;
var msg_dc = new AiConversationMessageDC();
msg_dc.Message = msg;
msg_dc.Role = BS.Shared.AiConversationMessageRole.User;
msg_dc.Created = DateTime.Now;
var msg_vm = new AiConversationMessageVM(msg_dc);
vm.Messages.VMList.Add(msg_vm);
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.ExecuteAiConversationWithPrompt(cb.Oid.Value, ViewContext, prompt.DataContract.Oid.Value),
cb2 =>
{
FinishSending();
ServiceFacade.EndManuelWaiting();
vm.Messages.VMList.Remove(msg_vm);
vm.AddMessages(cb2);
}, error);
},
error);
}
catch (Exception ex)
{
EndSending();
}
}
private void StartRoutine(AiPromptbausteinRoutineVM routine)
{
StartSending();
try
{
var conv = new AiConversationDC();
conv.Created = DateTime.Now;
conv.Updated = DateTime.Now;
conv.ActionType = ActionType;
var vm = InsertConverstion(conv);
Action<Exception> error = (e) =>
{
EndSending();
ListVM.VMList.Remove(vm);
ServiceFacade.EndManuelWaiting();
};
ServiceFacade.StartManuelWaiting();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.CreateAiConversation(conv, ViewContext), cb =>
{
vm.UpdateByDataContract(cb);
ExecuteChain(routine, 0, error);
}, error);
}
catch (Exception ex)
{
EndSending();
}
}
private void ExecuteChain(AiPromptbausteinRoutineVM routine, int step, Action<Exception> error)
{
if (step >= routine.Steps.Count)
{
FinishSending();
ServiceFacade.EndManuelWaiting();
return;
}
var conv = ListVM.SelectedVM;
var custom_viewContext = new AiViewContextDC
{
References = ViewContext.References,
Primary = ViewContext.Primary
};
if (step > 0 && routine.RoutineType == AiRoutineType.Chain)
{
custom_viewContext.Secondary = conv.Messages.VMList.Last().Message;
}
else
{
custom_viewContext.Secondary = ViewContext.Secondary;
}
var msg = routine.Steps.VMList[step].PromptReference.Prompt;
var msg_dc = new AiConversationMessageDC
{
Message = msg,
Role = AiConversationMessageRole.User,
Created = DateTime.Now
};
var msg_vm = new AiConversationMessageVM(msg_dc);
conv.Messages.VMList.Add(msg_vm);
ServiceFacade.DoAiEnhancedServiceAsnyc(
x => x.ExecuteAiConversationWithRoutine(conv.Oid, custom_viewContext, routine.DataContract.Oid.Value, step),
cb =>
{
conv.Messages.VMList.Remove(msg_vm);
conv.AddMessages(cb);
ExecuteChain(routine, step + 1, error);
}, error);
}
}
}

View File

@@ -4,8 +4,6 @@ using BeWo.ViewModel.ListViewModel;
using BeWo.ViewModel.View.Administration;
using BS.Shared;
using BS.Shared.DataContracts.Compact;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.Extensions.CustomInterfaces;
using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using System;
@@ -20,17 +18,20 @@ using MessageBox = System.Windows.MessageBox;
namespace BeWo.ViewModel.View.AI
{
public class AiPromptbausteinSelectionComplexViewModel : DialogViewModel
public class AiPromptbausteinSelectionComplexViewModel : DialogViewModel, IAiPromptbausteinComplexViewModel
{
public event EventHandler<AiPromptbausteinPromptVM> PromptAccepted;
public event EventHandler<AbstractBaseVM> ItemAccepted;
public event EventHandler VMListReloaded;
private AiPromptbausteinFolderVM _SelectedFolder;
private AiPromptbausteinPromptVM _SelectedPrompt;
private AiPromptbausteinRoutineVM _SelectedRoutine;
private AbstractBaseVM _SelectedItem;
private IBeWoWindowService WindowService { get; set; }
public bool IsFavorite { get; set; }
public DelegateCommand SendCommand { get; set; }
public AiActionType AiActionType { get; set; }
public AiPromptbausteinFolderVM Favoriten { get; set; }
public AiPromptbausteinFolderVM CopiedFolder { get; set; }
public AiPromptbausteinPromptVM CopiedPrompt { get; set; }
@@ -53,11 +54,18 @@ namespace BeWo.ViewModel.View.AI
public DelegateCommand DeleteRoutineCommand { get; private set; }
public DelegateCommand ChangeFavoritenStateRoutineCommand { get; private set; }
public DelegateCommand OpenEditItemDialogCommand { get; private set; }
public DelegateCommand DeleteItemCommand { get; private set; }
public DelegateCommand ChangeFavoritenStateItemCommand { get; private set; }
public bool CanEditPromptbausteine { get; set; }
public bool HasCopiedFolder => CopiedFolder is object;
public bool HasCopiedPrompt => CopiedPrompt is object;
public CompactEmployeeDC CurrentEmployee => BeWoApp.CompactLoggedOnEmployee;
public bool CanOpenContextMenu { get; set; }
public string AcceptButtonText => CanOpenContextMenu ? "Absenden" : "Hinzufügen";
public AiPromptbausteinSelectionComplexViewModel()
{
SendCommand = new DelegateCommand(Send, CanSend, true);
@@ -70,14 +78,15 @@ namespace BeWo.ViewModel.View.AI
public AiPromptbausteinSelectionComplexViewModel(AiActionType aiActionType) : this()
{
AiActionType = aiActionType;
WindowService = BeWoApp.MainControl.WindowService;
WindowService = BeWoApp.WindowService;
InitCommands();
}
public AiPromptbausteinSelectionComplexViewModel(AiActionType aiActionType, AiPromptbausteinFolderListVM viewModel, bool isFavorite = false) : this(aiActionType)
public AiPromptbausteinSelectionComplexViewModel(AiActionType aiActionType, AiPromptbausteinFolderListVM viewModel, bool isFavorite = false, bool canOpen = true) : this(aiActionType)
{
LoadedActionType = aiActionType;
Folders = viewModel;
IsFavorite = isFavorite;
CanOpenContextMenu = canOpen;
}
private void InitCommands()
@@ -88,51 +97,58 @@ namespace BeWo.ViewModel.View.AI
OpenAddPromptDialogCommand = new DelegateCommand(OpenAddPromptDialog, canOpenAddPromptDialog, false);
OpenEditPromptDialogCommand = new DelegateCommand(OpenEditPromptDialog, canOpenEditPromptDialog, false);
CopyPromptCommand = new DelegateCommand(CopyPrompt, canCopyPrompt, false);
PastePromptCommand = new DelegateCommand(PastePrompt, canPastePrompt, false);
DeletePromptCommand = new DelegateCommand(OpenDeletePromptDialog, canOpenDeletePromptDialog, false);
ChangeFavoritenStatePromptCommand = new DelegateCommand(ChangeFavoritenStatePrompt, canChangeFavoritenStatePrompt, false);
OpenAddRoutineDialogCommand = new DelegateCommand(OpenAddRoutineDialog, canOpenAddRoutineDialog, false);
OpenEditRoutineDialogCommand = new DelegateCommand(OpenEditRoutineDialog, canOpenEditRoutineDialog, false);
DeleteRoutineCommand = new DelegateCommand(OpenDeleteRoutineDialog, canOpenDeleteRoutineDialog, false);
ChangeFavoritenStateRoutineCommand = new DelegateCommand(ChangeFavoritenStateRoutine, canChangeFavoritenStateRoutine, false);
Action executeEditItem = () => ExecuteItem(OpenEditPromptDialog, OpenEditRoutineDialog);
Func<bool> canExecuteEditItem = () => canExecuteItem(canOpenEditPromptDialog, canOpenEditRoutineDialog);
OpenEditItemDialogCommand = new DelegateCommand(executeEditItem, canExecuteEditItem, true);
Action executeDeleteItem = () => ExecuteItem(OpenDeletePromptDialog, OpenDeleteRoutineDialog);
Func<bool> canExecuteDeleteItem = () => canExecuteItem(canOpenDeletePromptDialog, canOpenDeleteRoutineDialog);
DeleteItemCommand = new DelegateCommand(executeDeleteItem, canExecuteDeleteItem, true);
Action executeFavoriteItem = () => ExecuteItem(ChangeFavoritenStatePrompt, ChangeFavoritenStateRoutine);
Func<bool> canExecuteFavoriteItem = () => canExecuteItem(canChangeFavoritenStatePrompt, canChangeFavoritenStateRoutine);
ChangeFavoritenStateItemCommand = new DelegateCommand(executeFavoriteItem, canExecuteFavoriteItem, true);
CanEditPromptbausteine = BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteineEdit);
}
public bool IsFavorite { get; set; }
public DelegateCommand SendCommand { get; set; }
public AiActionType AiActionType { get; set; }
public AiPromptbausteinFolderVM SelectedFolder
{
get => _SelectedFolder;
set
{
SetProperty(ref _SelectedFolder, value, nameof(SelectedFolder));
if (SelectedPrompt is object)
var success = SetProperty(ref _SelectedFolder, value, nameof(SelectedFolder));
if (SelectedItem is AiPromptbausteinPromptVM vm)
{
SelectedPrompt.IsSelected = false;
SelectedPrompt = null;
SelectedItem = null;
}
if (!success)
return;
UpdateFolderCommands();
UpdatePromptCommands();
}
}
public AiPromptbausteinPromptVM SelectedPrompt
public AbstractBaseVM SelectedItem
{
get => _SelectedPrompt;
get => _SelectedItem;
set
{
SetProperty(ref _SelectedPrompt, value, nameof(SelectedPrompt));
SetProperty(ref _SelectedItem, value, nameof(SelectedItem));
SendCommand.RaiseCanExecuteChanged();
}
}
public AiPromptbausteinRoutineVM SelectedRoutine
{
get => _SelectedRoutine;
set
{
SetProperty(ref _SelectedRoutine, value, nameof(SelectedRoutine));
UpdateItemCommands();
}
}
public AiPromptbausteinFolderListVM Folders { get; private set; }
@@ -147,28 +163,40 @@ namespace BeWo.ViewModel.View.AI
return true;
#endif
return Folders.Count > 3 && Folders.VMList[0].Prompts.Count > 0;
return Folders.Count > 3 && (Folders.VMList[0].Prompts.Count > 0 || Folders.VMList[0].Routines.Count > 0);
}
}
public void ResetSelection()
{
// Bisherige Tree-Selektion zurücknehmen, damit nicht zwei Knoten als selektiert markiert sind.
if (SelectedFolder != null)
SelectedFolder.IsSelected = false;
SelectedFolder = null;
if (IsFavorite)
SelectedFolder = Folders.VMList[0];
// Favoriten-Popup: Favoriten (VMList[0]), sonst "Eigene" (VMList[1]) vorauswählen.
var target = IsFavorite
? (Folders.VMList.Count > 0 ? Folders.VMList[0] : null)
: (Folders.VMList.Count > 1 ? Folders.VMList[1] : null);
if (target != null)
{
target.IsSelected = true;
SelectedFolder = target;
}
}
public void Send()
{
var selected_prompt = SelectedPrompt;
var selected_prompt = SelectedItem;
CloseDialogCommand.Execute(null);
Close();
PromptAccepted?.Invoke(this, selected_prompt);
ItemAccepted?.Invoke(this, selected_prompt);
}
public bool CanSend()
{
return SelectedPrompt is object;
return SelectedItem is AiPromptbausteinPromptVM || (SelectedItem is AiPromptbausteinRoutineVM routine && routine.IsValid);
}
public void InitVMList()
{
@@ -200,6 +228,10 @@ namespace BeWo.ViewModel.View.AI
SelectedFolder = Favoriten;
}
// "Eigene" (VMList[1]) im normalen Modus vorauswählen.
if (!IsFavorite && Folders.VMList.Count > 1)
Folders.VMList[1].IsSelected = true;
FirePropertyChanged(nameof(HasFavoriten));
}
@@ -225,6 +257,12 @@ namespace BeWo.ViewModel.View.AI
DeleteRoutineCommand?.RaiseCanExecuteChanged();
ChangeFavoritenStateRoutineCommand?.RaiseCanExecuteChanged();
}
public void UpdateItemCommands()
{
OpenEditItemDialogCommand?.RaiseCanExecuteChanged();
DeleteItemCommand?.RaiseCanExecuteChanged();
ChangeFavoritenStateItemCommand?.RaiseCanExecuteChanged();
}
// --- Folder Commands ---
@@ -238,17 +276,15 @@ namespace BeWo.ViewModel.View.AI
new_vm.ParentFolderOid = sel_folder?.DataContract?.Oid;
new_vm.CanAddFolder = true;
new_vm.CanAddPrompt = true;
new_vm.CanAddRoutine = true;
new_vm.CanEdit = true;
new_vm.ActionType = AiActionType;
var vm = new AiPromptbausteinFolderViewModel(new_vm, true);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, new_dc) =>
{
var new_dc = new_vm.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinFolder(new List<AiPromptbausteinFolderDC> { new_dc }),
(new_dcs) => ReloadVMList());
ReloadVMList();
};
Close();
@@ -266,12 +302,9 @@ namespace BeWo.ViewModel.View.AI
var vm = new AiPromptbausteinFolderViewModel(edit_vm, false);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, new_dc) =>
{
var edit_dc = edit_vm.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinFolder(new List<AiPromptbausteinFolderDC> { edit_dc }),
(update_dc) => ReloadVMList());
ReloadVMList();
};
Close();
@@ -287,12 +320,9 @@ namespace BeWo.ViewModel.View.AI
if (result != MessageBoxResult.OK)
return;
var oid2version = new Dictionary<long, long>()
{
{sel_folder.DataContract.Oid.Value, sel_folder.DataContract.Version.Value}
};
var delete_dc = sel_folder.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinFolder(oid2version),
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinFolder(delete_dc),
() => ReloadVMList());
}
@@ -301,7 +331,6 @@ namespace BeWo.ViewModel.View.AI
bool canDeleteFolder() => CanEditPromptbausteine && (SelectedFolder?.CanEdit ?? false);
// --- Prompt Commands ---
void OpenAddPromptDialog()
{
var sel_folder = SelectedFolder;
@@ -314,14 +343,11 @@ namespace BeWo.ViewModel.View.AI
new_vm.CanEdit = true;
new_vm.ActionType = AiActionType;
var vm = new AiPromptbausteinPromptViewModel(new_vm, true);
var vm = new AiPromptbausteinPromptViewModel(new_vm);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, e) =>
{
var new_dc = new_vm.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinPrompt(new List<AiPromptbausteinPromptDC> { new_dc }),
(new_dcs) => ReloadVMList());
ReloadVMList();
};
Close();
@@ -330,81 +356,232 @@ namespace BeWo.ViewModel.View.AI
}
void OpenEditPromptDialog()
{
var sel_prompt = SelectedPrompt;
var sel_prompt = SelectedItem as AiPromptbausteinPromptVM;
if (SelectedItem is null)
throw new Exception("invalid operation");
var sel_dc = sel_prompt.CopyToEmptyDataContract();
sel_dc.CanEdit = SelectedPrompt.CanEdit;
sel_dc.CanEdit = sel_prompt.CanEdit;
sel_dc.Oid = sel_prompt.DataContract.Oid;
sel_dc.Version = sel_prompt.DataContract.Version;
var edit_vm = new AiPromptbausteinPromptVM(sel_dc);
var vm = new AiPromptbausteinPromptViewModel(edit_vm, false);
var vm = new AiPromptbausteinPromptViewModel(edit_vm);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, e) =>
{
var edit_dc = edit_vm.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinPrompt(new List<AiPromptbausteinPromptDC> { edit_dc }),
(update_dc) => ReloadVMList());
ReloadVMList();
};
Close();
WindowService.Show(vm);
}
void CopyPrompt()
{
CopiedPrompt = SelectedItem as AiPromptbausteinPromptVM;
}
void PastePrompt()
{
var copied_dc = CopiedPrompt.CommitToDataContract();
copied_dc.Creator = CurrentEmployee;
copied_dc.CanEdit = true;
copied_dc.IsPublic = false;
copied_dc.IsFavorite = false;
copied_dc.Oid = null;
copied_dc.Version = null;
copied_dc.ParentFolderOid = SelectedFolder.DataContract.Oid;
copied_dc.ActionType = AiActionType;
copied_dc.PromptId = null;
copied_dc.ShowPrompt = true;
copied_dc.ShowPromptByTenant = true;
copied_dc.IsOwnsoftPrompt = false;
var copied_vm = new AiPromptbausteinPromptVM(copied_dc);
SelectedFolder.SubPrompts.VMList.Add(copied_vm);
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinPrompt(copied_dc),
new_dc =>
{
copied_vm.UpdateByDataContract(new_dc);
SelectedFolder.SubPrompts.VMList.Add(copied_vm);
SelectedItem = copied_vm;
});
}
void OpenDeletePromptDialog()
{
var sel_prompt = SelectedPrompt;
var sel_prompt = SelectedItem as AiPromptbausteinPromptVM;
var folder = SelectedFolder;
var result = MessageBox.Show("Möchten Sie den ausgewählten Prompt wirklich löschen?", "Hinweis", MessageBoxButton.OKCancel);
var txt = "Möchten Sie den ausgewählten Prompt wirklich löschen?";
var result = MessageBox.Show(txt, "Hinweis", MessageBoxButton.OKCancel);
if (result != MessageBoxResult.OK)
return;
var oid2version = new Dictionary<long, long>()
if (sel_prompt.IsFavorite)
{
{sel_prompt.DataContract.Oid.Value, sel_prompt.DataContract.Version.Value}
};
sel_prompt.IsFavorite = false;
}
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinPrompt(oid2version),
() => ReloadVMList());
var delete_dc = sel_prompt.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinPrompt(delete_dc),
() =>
{
ReloadVMList();
});
}
void ChangeFavoritenStatePrompt()
{
var sel_prompt = SelectedPrompt;
var sel_prompt = SelectedItem as AiPromptbausteinPromptVM;
sel_prompt.IsFavorite = !sel_prompt.IsFavorite;
var edit_dc = sel_prompt.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinPrompt(new List<AiPromptbausteinPromptDC> { edit_dc }),
(update_dc) => ReloadVMList());
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinPrompt(edit_dc),
new_dc =>
{
ReloadVMList();
});
}
bool canOpenAddPromptDialog() => CanEditPromptbausteine && (SelectedFolder?.CanAddPrompt ?? false);
bool canOpenEditPromptDialog() => SelectedPrompt is object;
bool canOpenDeletePromptDialog() => CanEditPromptbausteine && (SelectedPrompt?.CanEdit ?? false);
bool canChangeFavoritenStatePrompt() => SelectedPrompt is object;
bool canOpenAddPromptDialog()
{
return CanEditPromptbausteine && (SelectedFolder?.CanAddPrompt ?? false);
}
bool canOpenEditPromptDialog()
{
return SelectedItem as AiPromptbausteinPromptVM is object;
}
bool canCopyPrompt()
{
return CanEditPromptbausteine && SelectedItem is AiPromptbausteinPromptVM prompt && prompt.ShowPrompt;
}
bool canPastePrompt()
{
return canOpenAddPromptDialog() && HasCopiedPrompt;
}
bool canOpenDeletePromptDialog()
{
return CanEditPromptbausteine && ((SelectedItem as AiPromptbausteinPromptVM)?.CanEdit ?? false);
}
bool canChangeFavoritenStatePrompt()
{
return SelectedItem as AiPromptbausteinPromptVM is object;
}
// --- Routine Commands
void OpenAddRoutineDialog()
{
var sel_folder = SelectedFolder;
var new_vm = sel_folder.SubRoutines.CreateNewVM();
new_vm.Creator = CurrentEmployee;
new_vm.ParentFolderOid = sel_folder.DataContract.Oid;
new_vm.CanEdit = true;
new_vm.ActionType = AiActionType;
var vm = new AiPromptbausteinRoutineViewModel(new_vm, Folders);
vm.DataSaved += (s, e) =>
{
ReloadVMList();
};
Close();
WindowService.Show(vm);
}
void OpenEditRoutineDialog()
{
var sel_prompt = SelectedItem as AiPromptbausteinRoutineVM;
if (SelectedItem is null)
throw new Exception("invalid operation");
var sel_dc = sel_prompt.CopyToEmptyDataContract();
sel_dc.CanEdit = sel_prompt.CanEdit;
sel_dc.Oid = sel_prompt.DataContract.Oid;
sel_dc.Version = sel_prompt.DataContract.Version;
var edit_vm = new AiPromptbausteinRoutineVM(sel_dc);
var vm = new AiPromptbausteinRoutineViewModel(edit_vm, Folders);
vm.DataSaved += (s, e) =>
{
ReloadVMList();
};
Close();
WindowService.Show(vm);
}
void OpenDeleteRoutineDialog()
{
var sel_prompt = SelectedItem as AiPromptbausteinRoutineVM;
var folder = SelectedFolder;
var txt = "Möchten Sie die ausgewählte Routine wirklich löschen?";
var result = MessageBox.Show(txt, "Hinweis", MessageBoxButton.OKCancel);
if (result != MessageBoxResult.OK)
return;
if (sel_prompt.IsFavorite)
{
sel_prompt.IsFavorite = false;
}
var delete_dc = sel_prompt.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinRoutine(delete_dc),
() =>
{
ReloadVMList();
});
}
void ChangeFavoritenStateRoutine()
{
var sel_routine = SelectedItem as AiPromptbausteinRoutineVM;
sel_routine.IsFavorite = !sel_routine.IsFavorite;
var edit_dc = sel_routine.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinRoutine(edit_dc),
new_dc =>
{
ReloadVMList();
});
}
bool canOpenAddRoutineDialog() => CanEditPromptbausteine && (SelectedFolder?.CanAddPrompt ?? false);
bool canOpenEditRoutineDialog() => SelectedRoutine is object;
bool canOpenDeleteRoutineDialog() => CanEditPromptbausteine && (SelectedRoutine?.CanEdit ?? false);
bool canChangeFavoritenStateRoutine() => SelectedRoutine is object;
bool canOpenEditRoutineDialog() => SelectedItem is AiPromptbausteinRoutineVM;
bool canOpenDeleteRoutineDialog() => CanEditPromptbausteine && ((SelectedItem as AiPromptbausteinRoutineVM)?.CanEdit ?? false);
bool canChangeFavoritenStateRoutine() => SelectedItem is AiPromptbausteinRoutineVM;
void ExecuteItem(Action prompt_action, Action routine_action)
{
if (SelectedItem is AiPromptbausteinPromptVM)
prompt_action();
else if (SelectedItem is AiPromptbausteinRoutineVM)
routine_action();
else
throw new NotImplementedException("item is not AiPromptbausteinPromptVM or AiPromptbausteinRoutineVM");
}
bool canExecuteItem(Func<bool> prompt_func, Func<bool> routine_func)
{
if (SelectedItem is AiPromptbausteinPromptVM)
return prompt_func();
else if (SelectedItem is AiPromptbausteinRoutineVM)
return routine_func();
return false;
}
}
}

View File

@@ -5,44 +5,69 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace BeWo.ViewModel.View
{
public class AcceptCancelDialogViewModel : DialogViewModel
public abstract class AcceptCancelDialogViewModel : DialogViewModel
{
public event EventHandler Accept_Button_Clicked;
public event EventHandler Cancel_Button_Clicked;
public DelegateCommand SaveCommand { get; set; }
public AcceptCancelDialogViewModel() : base()
protected AcceptCancelDialogViewModel() : base()
{
AcceptCommand = new DelegateCommand(Accept, canAccept, false);
CancelCommand = new DelegateCommand(Cancel, canCancel, false);
SaveCommand = new DelegateCommand(Save, canSave, false);
}
public DelegateCommand AcceptCommand { get; set; }
public DelegateCommand CancelCommand { get; set; }
public void Accept()
protected virtual void Save()
{
Accept_Button_Clicked?.Invoke(this, EventArgs.Empty);
throw new NotImplementedException();
}
protected virtual bool canSave()
{
return false;
}
}
public class AcceptCancelDialogViewModel<DCType, VMType> : AcceptCancelDialogViewModel where VMType : AbstractDCMapperVM<DCType> where DCType : new()
{
public event EventHandler<DCType> DataSaved;
public VMType ViewModel { get; set; }
public string AcceptButtonText => ViewModel.IsNew ? "Hinzufügen" : "Speichern";
public AcceptCancelDialogViewModel(VMType viewModel) : base()
{
ViewModel = viewModel;
ViewModel.PropertyChanged += (s, e) =>
{
SaveCommand.RaiseCanExecuteChanged();
};
}
protected void DataSave(DCType dCType)
{
DataSaved?.Invoke(this, dCType);
Close();
}
public void Cancel()
protected override void Close()
{
Cancel_Button_Clicked?.Invoke(this, EventArgs.Empty);
Close();
base.Close();
}
protected virtual bool canAccept()
protected override bool canSave()
{
return true;
return ViewModel.IsNew || ViewModel.IsDirty;
}
protected virtual bool canCancel()
protected virtual bool isDirty()
{
return true;
return false;
}
}
}

View File

@@ -4,8 +4,9 @@ using BeWo.ViewModel.ListViewModel;
using BS.Shared;
using BS.Shared.DataContracts.Compact;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.Extensions.CustomInterfaces;
using DevExpress.DataProcessing;
using DevExpress.Mvvm;
using DevExpress.Utils.Extensions;
using DevExpress.Xpf.Layout.Core;
using System;
using System.Collections.Generic;
@@ -15,12 +16,14 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using static DevExpress.Utils.Drawing.Helpers.NativeMethods;
namespace BeWo.ViewModel.View.Administration
{
public class AiPromptbausteinComplexTreeViewModel : WindowViewModel
public class AiPromptbausteinComplexTreeViewModel : WindowViewModel, IAiPromptbausteinComplexViewModel
{
private AiPromptbausteinFolderVM _SelectedFolder;
private AbstractBaseVM _SelectedItem;
private IBeWoWindowService WindowService { get; set; }
private AiActionType AiActionType { get; set; }
@@ -28,7 +31,6 @@ namespace BeWo.ViewModel.View.Administration
public AiPromptbausteinFolderListVM Folders { get; set; }
public AiPromptbausteinFolderVM Favoriten { get; set; }
public AiPromptbausteinPromptVM SelectedPrompt { get; set; }
public AiPromptbausteinFolderVM CopiedFolder { get; set; }
public AiPromptbausteinPromptVM CopiedPrompt { get; set; }
@@ -45,20 +47,56 @@ namespace BeWo.ViewModel.View.Administration
public DelegateCommand DeletePromptCommand { get; private set; }
public DelegateCommand ChangeFavoritenStatePromptCommand { get; private set; }
public DelegateCommand OpenAddRoutineDialogCommand { get; private set; }
public DelegateCommand OpenEditRoutineDialogCommand { get; private set; }
public DelegateCommand DeleteRoutineCommand { get; private set; }
public DelegateCommand ChangeFavoritenStateRoutineCommand { get; private set; }
public DelegateCommand OpenEditItemDialogCommand { get; private set; }
public DelegateCommand DeleteItemCommand { get; private set; }
public DelegateCommand ChangeFavoritenStateItemCommand { get; private set; }
public bool CanEditPromptbausteine { get; set; }
public AiPromptbausteinFolderVM SelectedFolder
{
get => _SelectedFolder;
set => SetProperty(ref _SelectedFolder, value, nameof(SelectedFolder));
set
{
var success = SetProperty(ref _SelectedFolder, value, nameof(SelectedFolder));
if (SelectedItem is AiPromptbausteinPromptVM vm)
{
SelectedItem = null;
}
if (!success)
return;
UpdateFolderCommands();
UpdatePromptCommands();
}
}
public AbstractBaseVM SelectedItem
{
get => _SelectedItem;
set {
var success = SetProperty(ref _SelectedItem, value, nameof(SelectedItem));
if (!success)
return;
UpdateItemCommands();
}
}
public AiPromptbausteinComplexTreeViewModel() : this(null, AiActionType.ServiceRecordConversation)
{
if (BeWoApp.IsInDesignMode)
{
ReloadVMList();
//ReloadVMList();
InitDesigner();
SelectedFolder = Folders.VMList.FirstOrDefault();
return;
}
@@ -81,6 +119,23 @@ namespace BeWo.ViewModel.View.Administration
DeletePromptCommand = new DelegateCommand(OpenDeletePromptDialog, canOpenDeletePromptDialog, false);
ChangeFavoritenStatePromptCommand = new DelegateCommand(ChangeFavoritenStatePrompt, canChangeFavoritenStatePrompt, false);
OpenAddRoutineDialogCommand = new DelegateCommand(OpenAddRoutineDialog, canOpenAddRoutineDialog, false);
OpenEditRoutineDialogCommand = new DelegateCommand(OpenEditRoutineDialog, canOpenEditRoutineDialog, false);
DeleteRoutineCommand = new DelegateCommand(OpenDeleteRoutineDialog, canOpenDeleteRoutineDialog, false);
ChangeFavoritenStateRoutineCommand = new DelegateCommand(ChangeFavoritenStateRoutine, canChangeFavoritenStateRoutine, false);
Action executeEditItem = () => ExecuteItem(OpenEditPromptDialog, OpenEditRoutineDialog);
Func<bool> canExecuteEditItem = () => canExecuteItem(canOpenEditPromptDialog, canOpenEditRoutineDialog);
OpenEditItemDialogCommand = new DelegateCommand(executeEditItem, canExecuteEditItem, true);
Action executeDeleteItem = () => ExecuteItem(OpenDeletePromptDialog, OpenDeleteRoutineDialog);
Func<bool> canExecuteDeleteItem = () => canExecuteItem(canOpenDeletePromptDialog, canOpenDeleteRoutineDialog);
DeleteItemCommand = new DelegateCommand(executeDeleteItem, canExecuteDeleteItem, true);
Action executeFavoriteItem = () => ExecuteItem(ChangeFavoritenStatePrompt, ChangeFavoritenStateRoutine);
Func<bool> canExecuteFavoriteItem = () => canExecuteItem(canChangeFavoritenStatePrompt, canChangeFavoritenStateRoutine);
ChangeFavoritenStateItemCommand = new DelegateCommand(executeFavoriteItem, canExecuteFavoriteItem, true);
CanEditPromptbausteine = BeWoApp.HasLoggedOnUserRight(UserRightType.AiModulePromptbausteineEdit);
}
@@ -88,11 +143,11 @@ namespace BeWo.ViewModel.View.Administration
{
get
{
return Folders?.ContainsDirtyObject() ?? false;
return false;
}
}
public bool HasCopiedFolder => CopiedFolder is object;
public bool HasCopiedPrompt => CopiedPrompt is object;
public bool HasCopiedPrompt => CopiedPrompt is object;
public CompactEmployeeDC CurrentEmployee => BeWoApp.CompactLoggedOnEmployee;
public void UpdateFolderCommands()
@@ -102,7 +157,7 @@ namespace BeWo.ViewModel.View.Administration
CopyFolderCommand.RaiseCanExecuteChanged();
PasteFolderCommand.RaiseCanExecuteChanged();
DeleteFolderCommand.RaiseCanExecuteChanged();
}
}
public void UpdatePromptCommands()
{
OpenAddPromptDialogCommand.RaiseCanExecuteChanged();
@@ -111,63 +166,18 @@ namespace BeWo.ViewModel.View.Administration
PastePromptCommand.RaiseCanExecuteChanged();
DeletePromptCommand.RaiseCanExecuteChanged();
ChangeFavoritenStatePromptCommand.RaiseCanExecuteChanged();
OpenAddRoutineDialogCommand.RaiseCanExecuteChanged();
OpenEditRoutineDialogCommand.RaiseCanExecuteChanged();
DeleteRoutineCommand.RaiseCanExecuteChanged();
ChangeFavoritenStateRoutineCommand.RaiseCanExecuteChanged();
}
public void SaveVMList()
public void UpdateItemCommands()
{
if (!IsDirty)
return;
// DFS -> 1. Sobald Knoten gefunden wird mit IsNew=true: Teilbaum als neu markieren
// 2. Sobald Knoten gefunden wird mit IsNew=false && IsDirty=true: Knoten als update markieren
// 3. Checken, welche Knoten gelöscht wurden
var toadd_folder = new List<AiPromptbausteinFolderVM>();
var toadd_prompts = new List<AiPromptbausteinPromptDC>();
var toupdate_folder = new List<AiPromptbausteinFolderVM>();
var toupdate_prompt = new List<AiPromptbausteinPromptDC>();
DFS_Search_AddUpdate(Folders, ref toadd_folder, ref toadd_prompts, ref toupdate_folder, ref toupdate_prompt);
var todelete_folder = new List<AiPromptbausteinFolderDC>();
var todelete_prompt = new List<AiPromptbausteinPromptDC>();
DFS_Search_Delete(Folders, ref todelete_folder, ref todelete_prompt);
var toadd_folder_dcs = toadd_folder.Select(x => x.CommitToDataContract());
var toupdate_folder_dcs = toupdate_folder.Select(x => x.CommitToDataContract());
var actions = new List<Action<IAiEnhancedService>>();
if (toadd_folder.Any())
actions.Add(x => x.InsertAiPromptbausteinFolder(toadd_folder_dcs.ToList()));
if (toadd_prompts.Any())
actions.Add(x => x.InsertAiPromptbausteinPrompt(toadd_prompts.ToList()));
if (toupdate_folder_dcs.Any())
{
foreach (var folder_dc in toupdate_folder_dcs)
{
folder_dc.SubPrompts = null;
folder_dc.SubFolders = null;
}
actions.Add(x => x.UpdateAiPromptbausteinFolder(toupdate_folder_dcs.ToList()));
}
if (toupdate_prompt.Any())
actions.Add(x => x.UpdateAiPromptbausteinPrompt(toupdate_prompt.ToList()));
if (todelete_folder.Any())
actions.Add(x => x.DeleteAiPromptbausteinFolder(todelete_folder.ToDictionary(x1 => x1.Oid.Value, x2 => x2.Version.Value)));
if (todelete_prompt.Any())
actions.Add(x => x.DeleteAiPromptbausteinPrompt(todelete_prompt.ToDictionary(x1 => x1.Oid.Value, x2 => x2.Version.Value)));
ServiceFacade.DoMultipleAiEnhancedServicesAsync(actions, () =>
{
ReloadVMList();
});
OpenEditItemDialogCommand.RaiseCanExecuteChanged();
DeleteItemCommand.RaiseCanExecuteChanged();
ChangeFavoritenStateItemCommand.RaiseCanExecuteChanged();
}
internal void ReloadVMList()
{
VMFactory.CreateAiPromptbausteinFolderListVMAsync(
@@ -179,80 +189,14 @@ namespace BeWo.ViewModel.View.Administration
{
Favoriten = Folders.VMList[0];
}
if (Folders.VMList.Count > 1)
Folders.VMList[1].IsSelected = true;
FirePropertyChanged(nameof(Folders));
});
}
void DFS_Search_AddUpdate(AiPromptbausteinFolderListVM folders, ref List<AiPromptbausteinFolderVM> toadd_Folder, ref List<AiPromptbausteinPromptDC> toadd_Prompts, ref List<AiPromptbausteinFolderVM> toupdate_Folder, ref List<AiPromptbausteinPromptDC> toupdate_Prompt)
{
foreach (var node in folders.VMList)
{
// Favoriten ignorieren
if (node.DataContract.Oid is long oid && oid < -4)
continue;
// Öffentlich
if (node.DataContract.Oid is long oid2 && oid2 < -1){
DFS_Search_UpdatePromptFavorite(node.SubFolders, ref toadd_Folder, ref toadd_Prompts, ref toupdate_Folder, ref toupdate_Prompt);
if (node.SubPrompts.ChangedCount > 0)
toupdate_Prompt.AddRange(node.SubPrompts.CommitChanged());
continue;
}
// Eigene
if (node.IsNew)
{
toadd_Folder.Add(node);
}
else
{
if (node.IsDirty)
toupdate_Folder.Add(node);
if (node.HasSubFolders)
DFS_Search_AddUpdate(node.SubFolders, ref toadd_Folder, ref toadd_Prompts, ref toupdate_Folder, ref toupdate_Prompt);
if (node.SubPrompts.AddedCount > 0)
toadd_Prompts.AddRange(node.SubPrompts.CommitAdded());
if (node.SubPrompts.ChangedCount > 0)
toupdate_Prompt.AddRange(node.SubPrompts.CommitChanged());
}
}
}
void DFS_Search_UpdatePromptFavorite(AiPromptbausteinFolderListVM folders, ref List<AiPromptbausteinFolderVM> toadd_Folder, ref List<AiPromptbausteinPromptDC> toadd_Prompts, ref List<AiPromptbausteinFolderVM> toupdate_Folder, ref List<AiPromptbausteinPromptDC> toupdate_Prompt)
{
foreach (var node in folders.VMList)
{
if (node.HasSubFolders)
DFS_Search_UpdatePromptFavorite(node.SubFolders, ref toadd_Folder, ref toadd_Prompts, ref toupdate_Folder, ref toupdate_Prompt);
if (node.SubPrompts.ChangedCount > 0)
toupdate_Prompt.AddRange(node.SubPrompts.CommitChanged());
}
}
void DFS_Search_Delete(AiPromptbausteinFolderListVM folders, ref List<AiPromptbausteinFolderDC> todelete_Folder, ref List<AiPromptbausteinPromptDC> todelete_Prompt)
{
foreach (var node_dc in folders.DCBackup)
{
if (node_dc.Oid is long oid && oid < -1)
continue;
if (folders.VMList.FirstOrDefault(vm => vm.DataContract == node_dc) is AiPromptbausteinFolderVM node_vm)
{
if (node_vm.SubFolders.DCBackup is object && node_vm.SubFolders.DCBackup.Count > 0)
DFS_Search_Delete(node_vm.SubFolders, ref todelete_Folder, ref todelete_Prompt);
if (node_vm.SubPrompts.RemovedCount > 0)
todelete_Prompt.AddRange(node_vm.SubPrompts.GetRemoved());
}
else
{
todelete_Folder.Add(node_dc);
}
}
}
void OpenAddFolderDialog()
{
var sel_folder = SelectedFolder;
@@ -263,13 +207,15 @@ namespace BeWo.ViewModel.View.Administration
new_vm.ParentFolderOid = sel_folder?.DataContract?.Oid;
new_vm.CanAddFolder = true;
new_vm.CanAddPrompt = true;
new_vm.CanAddRoutine = true;
new_vm.CanEdit = true;
new_vm.ActionType = AiActionType;
var vm = new AiPromptbausteinFolderViewModel(new_vm, true);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, new_dc) =>
{
new_vm.UpdateByDataContract(new_dc);
sel_folder.SubFolders.VMList.Add(new_vm);
sel_folder.IsExpanded = true;
};
@@ -281,14 +227,15 @@ namespace BeWo.ViewModel.View.Administration
var sel_folder = SelectedFolder;
var sel_dc = sel_folder.CopyToEmptyDataContract();
sel_dc.CanEdit = SelectedFolder.CanEdit;
sel_dc.Oid = sel_folder.DataContract.Oid;
sel_dc.Version = sel_folder.DataContract.Version;
var edit_vm = new AiPromptbausteinFolderVM(sel_dc);
var vm = new AiPromptbausteinFolderViewModel(edit_vm, false);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, new_dc) =>
{
var edit_dc = edit_vm.CommitToDataContract();
sel_folder.UpdateByDataContract(edit_dc);
sel_folder.UpdateByDataContract(new_dc);
};
WindowService.Show(vm);
@@ -312,12 +259,14 @@ namespace BeWo.ViewModel.View.Administration
if (result != MessageBoxResult.OK)
return;
parent.SubFolders.VMList.Remove(sel_folder);
var delete_dc = sel_folder.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinFolder(delete_dc),
() => parent.SubFolders.VMList.Remove(sel_folder));
}
bool canOpenAddFolderDialog()
{
return CanEditPromptbausteine && (SelectedFolder?.CanAddFolder ?? true);
return CanEditPromptbausteine && (SelectedFolder?.CanAddFolder ?? false);
}
bool canOpenEditFolderDialog()
{
@@ -350,31 +299,36 @@ namespace BeWo.ViewModel.View.Administration
new_vm.CanEdit = true;
new_vm.ActionType = AiActionType;
var vm = new AiPromptbausteinPromptViewModel(new_vm, true);
var vm = new AiPromptbausteinPromptViewModel(new_vm);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, new_dc) =>
{
new_vm.UpdateByDataContract(new_dc);
sel_folder.SubPrompts.VMList.Add(new_vm);
SelectedPrompt = new_vm;
SelectedItem = new_vm;
};
WindowService.Show(vm);
}
void OpenEditPromptDialog()
{
var sel_prompt = SelectedPrompt;
var sel_prompt = SelectedItem as AiPromptbausteinPromptVM;
if (SelectedItem is null)
throw new Exception("invalid operation");
var sel_dc = sel_prompt.CopyToEmptyDataContract();
sel_dc.CanEdit = SelectedPrompt.CanEdit;
sel_dc.CanEdit = sel_prompt.CanEdit;
sel_dc.Oid = sel_prompt.DataContract.Oid;
sel_dc.Version = sel_prompt.DataContract.Version;
var edit_vm = new AiPromptbausteinPromptVM(sel_dc);
var vm = new AiPromptbausteinPromptViewModel(edit_vm, false);
var vm = new AiPromptbausteinPromptViewModel(edit_vm);
vm.Accept_Button_Clicked += (s, e) =>
vm.DataSaved += (s, new_dc) =>
{
var edit_dc = edit_vm.CommitToDataContract();
sel_prompt.UpdateByDataContract(edit_dc);
UpdateSelectedPromptFavorite(sel_prompt);
sel_prompt.UpdateByDataContract(new_dc);
UpdateSelectedPromptFavorite(sel_prompt);
};
WindowService.Show(vm);
@@ -383,7 +337,7 @@ namespace BeWo.ViewModel.View.Administration
private void UpdateSelectedPromptFavorite(AiPromptbausteinPromptVM sel_prompt = null)
{
if (sel_prompt is null)
sel_prompt = SelectedPrompt;
sel_prompt = SelectedItem as AiPromptbausteinPromptVM;
if (sel_prompt.IsFavorite && !Favoriten.SubPrompts.VMList.Contains(sel_prompt))
Favoriten.SubPrompts.VMList.Add(sel_prompt);
@@ -391,7 +345,27 @@ namespace BeWo.ViewModel.View.Administration
{
Favoriten.SubPrompts.VMList.Remove(sel_prompt);
if (Favoriten.SubPrompts.Count == 0)
if (Favoriten.SubRoutines.Count == 0 && Favoriten.SubPrompts.Count == 0)
{
var selected_folder = SelectedFolder;
SelectedFolder = null;
SelectedFolder = selected_folder;
}
}
}
private void UpdateSelectedRoutineFavorite(AiPromptbausteinRoutineVM sel_routine = null)
{
if (sel_routine is null)
sel_routine = SelectedItem as AiPromptbausteinRoutineVM;
if (sel_routine.IsFavorite && !Favoriten.SubRoutines.VMList.Contains(sel_routine))
Favoriten.SubRoutines.VMList.Add(sel_routine);
else if (!sel_routine.IsFavorite && Favoriten.SubRoutines.VMList.Contains(sel_routine))
{
Favoriten.SubRoutines.VMList.Remove(sel_routine);
if (Favoriten.SubRoutines.Count == 0 && Favoriten.SubPrompts.Count == 0)
{
var selected_folder = SelectedFolder;
SelectedFolder = null;
@@ -402,7 +376,7 @@ namespace BeWo.ViewModel.View.Administration
void CopyPrompt()
{
CopiedPrompt = SelectedPrompt;
CopiedPrompt = SelectedItem as AiPromptbausteinPromptVM;
}
void PastePrompt()
{
@@ -410,18 +384,29 @@ namespace BeWo.ViewModel.View.Administration
copied_dc.Creator = CurrentEmployee;
copied_dc.CanEdit = true;
copied_dc.IsPublic = false;
copied_dc.IsFavorite = false;
copied_dc.Oid = null;
copied_dc.Version = 0;
copied_dc.Version = null;
copied_dc.ParentFolderOid = SelectedFolder.DataContract.Oid;
copied_dc.ActionType = AiActionType;
copied_dc.PromptId = null;
copied_dc.ShowPrompt = true;
copied_dc.ShowPromptByTenant = true;
copied_dc.IsOwnsoftPrompt = false;
var copied_vm = new AiPromptbausteinPromptVM(copied_dc);
SelectedFolder.SubPrompts.VMList.Add(copied_vm);
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinPrompt(copied_dc),
new_dc =>
{
copied_vm.UpdateByDataContract(new_dc);
SelectedFolder.SubPrompts.VMList.Add(copied_vm);
SelectedItem = copied_vm;
});
}
void OpenDeletePromptDialog()
{
var sel_prompt = SelectedPrompt;
var sel_prompt = SelectedItem as AiPromptbausteinPromptVM;
var folder = SelectedFolder;
var txt = "Möchten Sie den ausgewählten Prompt wirklich löschen?";
@@ -430,16 +415,41 @@ namespace BeWo.ViewModel.View.Administration
if (result != MessageBoxResult.OK)
return;
folder.SubPrompts.VMList.Remove(SelectedPrompt);
if (sel_prompt.IsFavorite)
{
sel_prompt.IsFavorite = false;
UpdateSelectedPromptFavorite();
}
var delete_dc = sel_prompt.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinPrompt(delete_dc),
() =>
{
if (folder.SubPrompts.VMList.Contains(sel_prompt))
{
folder.SubPrompts.VMList.Remove(sel_prompt);
}
else
{
ReloadVMList();
}
});
}
void ChangeFavoritenStatePrompt()
{
var sel_prompt = SelectedPrompt;
var sel_prompt = SelectedItem as AiPromptbausteinPromptVM;
sel_prompt.IsFavorite = !sel_prompt.IsFavorite;
UpdateSelectedPromptFavorite(sel_prompt);
var edit_dc = sel_prompt.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinPrompt(edit_dc),
new_dc =>
{
sel_prompt.UpdateByDataContract(new_dc);
UpdateSelectedPromptFavorite(sel_prompt);
});
}
bool canOpenAddPromptDialog()
@@ -448,11 +458,11 @@ namespace BeWo.ViewModel.View.Administration
}
bool canOpenEditPromptDialog()
{
return SelectedPrompt is object;
return SelectedItem as AiPromptbausteinPromptVM is object;
}
bool canCopyPrompt()
{
return CanEditPromptbausteine && SelectedPrompt is object;
return CanEditPromptbausteine && SelectedItem as AiPromptbausteinPromptVM is object;
}
bool canPastePrompt()
{
@@ -460,36 +470,138 @@ namespace BeWo.ViewModel.View.Administration
}
bool canOpenDeletePromptDialog()
{
return CanEditPromptbausteine && (SelectedPrompt?.CanEdit ?? false);
return CanEditPromptbausteine && ((SelectedItem as AiPromptbausteinPromptVM)?.CanEdit ?? false);
}
bool canChangeFavoritenStatePrompt()
{
return SelectedPrompt is object;
return SelectedItem as AiPromptbausteinPromptVM is object;
}
// --- Routine Commands
void OpenAddRoutineDialog()
{
var sel_folder = SelectedFolder;
var new_vm = sel_folder.SubRoutines.CreateNewVM();
new_vm.Creator = CurrentEmployee;
new_vm.ParentFolderOid = sel_folder.DataContract.Oid;
new_vm.CanEdit = true;
new_vm.ActionType = AiActionType;
var vm = new AiPromptbausteinRoutineViewModel(new_vm, Folders);
vm.DataSaved += (s, new_dc) =>
{
new_vm.UpdateByDataContract(new_dc);
sel_folder.SubRoutines.VMList.Add(new_vm);
SelectedItem = new_vm;
};
WindowService.Show(vm);
}
void OpenEditRoutineDialog()
{
var sel_prompt = SelectedItem as AiPromptbausteinRoutineVM;
if (SelectedItem is null)
throw new Exception("invalid operation");
var sel_dc = sel_prompt.CopyToEmptyDataContract();
sel_dc.CanEdit = sel_prompt.CanEdit;
sel_dc.Oid = sel_prompt.DataContract.Oid;
sel_dc.Version = sel_prompt.DataContract.Version;
var edit_vm = new AiPromptbausteinRoutineVM(sel_dc);
var vm = new AiPromptbausteinRoutineViewModel(edit_vm, Folders);
vm.DataSaved += (s, new_dc) =>
{
sel_prompt.UpdateByDataContract(new_dc);
UpdateSelectedRoutineFavorite(sel_prompt);
};
WindowService.Show(vm);
}
void OpenDeleteRoutineDialog()
{
var sel_prompt = SelectedItem as AiPromptbausteinRoutineVM;
var folder = SelectedFolder;
var txt = "Möchten Sie die ausgewählte Routine wirklich löschen?";
var result = MessageBox.Show(txt, "Hinweis", MessageBoxButton.OKCancel);
if (result != MessageBoxResult.OK)
return;
if (sel_prompt.IsFavorite)
{
sel_prompt.IsFavorite = false;
UpdateSelectedRoutineFavorite();
}
var delete_dc = sel_prompt.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.DeleteAiPromptbausteinRoutine(delete_dc),
() =>
{
if (folder.SubRoutines.VMList.Contains(sel_prompt))
{
folder.SubRoutines.VMList.Remove(sel_prompt);
}
else
{
ReloadVMList();
}
});
}
void ChangeFavoritenStateRoutine()
{
var sel_routine = SelectedItem as AiPromptbausteinRoutineVM;
sel_routine.IsFavorite = !sel_routine.IsFavorite;
var edit_dc = sel_routine.CommitToDataContract();
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinRoutine(edit_dc),
new_dc =>
{
sel_routine.UpdateByDataContract(new_dc);
UpdateSelectedRoutineFavorite(sel_routine);
});
}
//bool canOpenAddRoutineDialog() => CanEditPromptbausteine && (SelectedFolder?.CanAddPrompt ?? false);
//bool canOpenEditRoutineDialog() => SelectedRoutine is object;
//bool canOpenDeleteRoutineDialog() => CanEditPromptbausteine && (SelectedRoutine?.CanEdit ?? false);
//bool canChangeFavoritenStateRoutine() => SelectedRoutine is object;
bool canOpenAddRoutineDialog() => CanEditPromptbausteine && (SelectedFolder?.CanAddPrompt ?? false);
bool canOpenEditRoutineDialog() => SelectedItem is AiPromptbausteinRoutineVM;
bool canOpenDeleteRoutineDialog() => CanEditPromptbausteine && ((SelectedItem as AiPromptbausteinRoutineVM)?.CanEdit ?? false);
bool canChangeFavoritenStateRoutine() => SelectedItem is AiPromptbausteinRoutineVM;
void ExecuteItem(Action prompt_action, Action routine_action)
{
if (SelectedItem is AiPromptbausteinPromptVM)
prompt_action();
else if (SelectedItem is AiPromptbausteinRoutineVM)
routine_action();
else
throw new NotImplementedException("item is not AiPromptbausteinPromptVM or AiPromptbausteinRoutineVM");
}
bool canExecuteItem(Func<bool> prompt_func, Func<bool> routine_func)
{
if (SelectedItem is AiPromptbausteinPromptVM)
return prompt_func();
else if (SelectedItem is AiPromptbausteinRoutineVM)
return routine_func();
return false;
}
void InitDesigner()
{
var root = PredefinedAiPromptbausteinFolders.CreateSubTree(AiActionType.ServiceRecordConversation);
var root_vm = new AiPromptbausteinFolderListVM(root);
Folders = root_vm;
}
}
}

View File

@@ -1,4 +1,6 @@
using DevExpress.DataProcessing.InMemoryDataProcessor;
using BeWo.ServiceProxy;
using BS.Shared.DataContracts.Feature.AI;
using DevExpress.DataProcessing.InMemoryDataProcessor;
using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using DevExpress.XtraBars.Docking2010.Views.WindowsUI;
@@ -11,28 +13,30 @@ using System.Windows.Input;
namespace BeWo.ViewModel.View.Administration
{
public class AiPromptbausteinFolderViewModel : AcceptCancelDialogViewModel
public class AiPromptbausteinFolderViewModel : AcceptCancelDialogViewModel<AiPromptbausteinFolderDC, AiPromptbausteinFolderVM>
{
private readonly bool _IsNew;
public AiPromptbausteinFolderViewModel(AiPromptbausteinFolderVM viewModel, bool isNew) : base()
public AiPromptbausteinFolderViewModel(AiPromptbausteinFolderVM viewModel, bool isNew) : base(viewModel)
{
ViewModel = viewModel;
_IsNew = isNew;
ViewModel.PropertyChanged += (s, e) =>
{
AcceptCommand.RaiseCanExecuteChanged();
};
}
public AiPromptbausteinFolderVM ViewModel { get; set; }
public string AcceptButtonText => _IsNew ? "Hinzufügen" : "Speichern";
protected override bool canAccept()
protected override void Save()
{
return (_IsNew || ViewModel.IsDirty) && !string.IsNullOrWhiteSpace(ViewModel.Title);
var dc = ViewModel.CommitToDataContract();
if (ViewModel.IsNew)
{
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinFolder(dc), DataSave);
}
else
{
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinFolder(dc), DataSave);
}
}
protected override bool canSave()
{
return base.canSave() && !string.IsNullOrWhiteSpace(ViewModel.Title);
}
}
}

View File

@@ -1,4 +1,6 @@
using System;
using BeWo.ServiceProxy;
using BS.Shared.DataContracts.Feature.AI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -6,28 +8,32 @@ using System.Threading.Tasks;
namespace BeWo.ViewModel.View.Administration
{
public class AiPromptbausteinPromptViewModel : AcceptCancelDialogViewModel
public class AiPromptbausteinPromptViewModel : AcceptCancelDialogViewModel<AiPromptbausteinPromptDC, AiPromptbausteinPromptVM>
{
private readonly bool _IsNew;
public AiPromptbausteinPromptViewModel(AiPromptbausteinPromptVM viewModel, bool isNew) : base()
public AiPromptbausteinPromptViewModel(AiPromptbausteinPromptVM viewModel) : base(viewModel)
{
ViewModel = viewModel;
_IsNew = isNew;
ViewModel.PropertyChanged += (s, e) =>
{
AcceptCommand.RaiseCanExecuteChanged();
};
}
public AiPromptbausteinPromptVM ViewModel { get; private set; }
public string AcceptButtonText => _IsNew ? "Hinzufügen" : "Speichern";
protected override bool canAccept()
protected override bool canSave()
{
return (_IsNew || ViewModel.IsDirty) && !string.IsNullOrWhiteSpace(ViewModel.Title);
return base.canSave() && !string.IsNullOrWhiteSpace(ViewModel.Title) && !string.IsNullOrWhiteSpace(ViewModel.Prompt);
}
protected override void Save()
{
var dc = ViewModel.CommitToDataContract();
if (ViewModel.IsNew)
{
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinPrompt(dc),
DataSave);
}
else
{
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinPrompt(dc),
DataSave);
}
}
}
}

View File

@@ -0,0 +1,122 @@
using BeWo.ServiceProxy;
using BeWo.ViewModel.ListViewModel;
using BS.Shared.DataContracts.Feature.AI;
using DevExpress.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BeWo.ViewModel.View.Administration
{
public class AiPromptbausteinRoutineViewModel : AcceptCancelDialogViewModel<AiPromptbausteinRoutineDC, AiPromptbausteinRoutineVM>
{
private readonly bool _IsNew;
public AiPromptbausteinRoutineStepVM _SelectedStep;
public AiPromptbausteinFolderListVM FolderListVM { get; set; }
public ICommand DeleteStepCommand { get; private set; }
public ICommand MoveStepUpCommand { get; private set; }
public ICommand MoveStepDownCommand { get; private set; }
public AiPromptbausteinRoutineStepVM SelectedStep
{
get => _SelectedStep;
set => SetProperty(ref _SelectedStep, value, nameof(SelectedStep));
}
public AiPromptbausteinRoutineViewModel(AiPromptbausteinRoutineVM viewModel, AiPromptbausteinFolderListVM folders) : base(viewModel)
{
FolderListVM = folders;
ViewModel.Steps.VMList.ListChanged += (s, e) =>
{
SaveCommand.RaiseCanExecuteChanged();
};
DeleteStepCommand = new DelegateCommand<AiPromptbausteinRoutineStepVM>(DeleteStep, canDeleteStep);
MoveStepUpCommand = new DelegateCommand<AiPromptbausteinRoutineStepVM>(MoveStepUp, canMoveStepUp);
MoveStepDownCommand = new DelegateCommand<AiPromptbausteinRoutineStepVM>(MoveStepDown, canMoveStepDown);
}
void DeleteStep(AiPromptbausteinRoutineStepVM step)
{
ViewModel.Steps.VMList.Remove(step);
}
void MoveStepUp(AiPromptbausteinRoutineStepVM step)
{
swap(step, -1);
}
void MoveStepDown(AiPromptbausteinRoutineStepVM step)
{
swap(step, 1);
}
bool canDeleteStep(AiPromptbausteinRoutineStepVM step)
{
return step is object;
}
bool canMoveStepUp(AiPromptbausteinRoutineStepVM step)
{
return step is object && ViewModel.Steps.Count > 1 && ViewModel.Steps.VMList.First() != step;
}
bool canMoveStepDown(AiPromptbausteinRoutineStepVM step)
{
return step is object && ViewModel.Steps.Count > 1 && ViewModel.Steps.VMList.Last() != step;
}
protected override bool canSave()
{
return base.canSave() && !string.IsNullOrWhiteSpace(ViewModel.Title) && (ViewModel.Steps?.VMList.Any() ?? false);
}
protected override void Save()
{
var dc = ViewModel.CommitToDataContract();
if (ViewModel.IsNew)
{
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.InsertAiPromptbausteinRoutine(dc),
DataSave);
}
else
{
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.UpdateAiPromptbausteinRoutine(dc),
DataSave);
}
}
private void swap(AiPromptbausteinRoutineStepVM step_x, int offset_y)
{
var id_x = ViewModel.Steps.VMList.IndexOf(step_x);
var id_y = id_x + offset_y;
var step_y = ViewModel.Steps.VMList[id_y];
var prompt_x = step_x.PromptReference;
var version_x = step_x.ReferenceVersion;
var valid_x = step_x.IsValid;
var prompt_y = step_y.PromptReference;
var version_y = step_y.ReferenceVersion;
var valid_y = step_y.IsValid;
step_x.PromptReference = prompt_y;
step_x.ReferenceVersion = version_y;
step_x.SetIsValid(valid_y);
step_y.PromptReference = prompt_x;
step_y.ReferenceVersion = version_x;
step_y.SetIsValid(valid_x);
SelectedStep = step_y;
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.ViewModel.View.Developer
{
public class DesignDeveloperViewModel : DeveloperViewModel
{
public DesignDeveloperViewModel()
{
KeyboardFocus = "Button";
LogicalFocus = "Button";
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
using System.Windows;
namespace BeWo.ViewModel.View.Developer
{
public class DeveloperViewModel : WindowViewModel
{
private string _keyboardFocus;
private string _logicalFocus;
public string KeyboardFocus
{
get => _keyboardFocus;
set => SetProperty(ref _keyboardFocus, value, nameof(KeyboardFocus));
}
public string LogicalFocus
{
get => _logicalFocus;
set => SetProperty(ref _logicalFocus, value, nameof(LogicalFocus));
}
public DeveloperViewModel()
{
var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
timer.Tick += (s, e) => Refresh();
timer.Start();
}
private void Refresh()
{
// Keyboard Focus globaler Input-Fokus, nur ein Element systemweit
var keyboard = Keyboard.FocusedElement;
KeyboardFocus = FormatElement(keyboard);
// Logical Focus pro FocusScope, kann vom Keyboard Focus abweichen
// z.B. wenn ein Menü oder Toolbar aktiv ist
var mainWindow = Application.Current.MainWindow;
var logical = mainWindow != null
? FocusManager.GetFocusedElement(mainWindow)
: null;
LogicalFocus = FormatElement(logical);
}
private static string FormatElement(object element)
{
if (element is null)
return "(kein Fokus)";
if (element is FrameworkElement fe)
{
var name = string.IsNullOrEmpty(fe.Name) ? "(kein Name)" : fe.Name;
var dc = fe.DataContext?.GetType().Name ?? "";
return $"{fe.GetType().Name} | Name: {name} | DC: {dc}";
}
return element.GetType().Name;
}
}
}

View File

@@ -10,18 +10,16 @@ namespace BeWo.ViewModel.View
{
public class DialogViewModel : WindowViewModel
{
public event EventHandler RequestClose;
public event EventHandler RequestCloseFinal;
public DialogViewModel() : base()
{
CloseDialogCommand = new DelegateCommand(Close);
}
public ICommand CloseDialogCommand { get; set; }
protected void Close()
protected virtual void Close()
{
RequestClose?.Invoke(this, EventArgs.Empty);
RequestCloseFinal?.Invoke(this, EventArgs.Empty);
}
}
}