Kategorie
This commit is contained in:
@@ -160,13 +160,13 @@
|
||||
Margin="0 10 0 0"
|
||||
Foreground="{DynamicResource FontColor.Menu.Categories}" />
|
||||
</StackPanel>
|
||||
<local:ComboBoxPageable x:Name="CategorySelectionControl"
|
||||
Margin="0 5 0 0"
|
||||
SelectedItem="{Binding SelectedCategory, ElementName=CloseCaseDialogUc, Mode=TwoWay}"
|
||||
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
|
||||
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
|
||||
PreviewKeyDown="Combobox_PreviewKeyDown"
|
||||
/>
|
||||
<local:HierarchicalSelectionControl x:Name="CategorySelectionControl"
|
||||
Margin="0 5 0 0"
|
||||
SelectedItem="{Binding SelectedCategory, ElementName=CloseCaseDialogUc, Mode=TwoWay}"
|
||||
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
|
||||
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
|
||||
SearchPlaceholderText="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Placeholder}"
|
||||
PreviewKeyDown="Combobox_PreviewKeyDown" />
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Template}"
|
||||
FontWeight="Bold"
|
||||
|
||||
@@ -59,13 +59,21 @@ namespace FasdDesktopUi.Basics.UserControls
|
||||
Infos = new Dictionary<string, string> { ["Special"] = "NoTicket" }
|
||||
};
|
||||
|
||||
private readonly cF4sdApiSearchResultRelation _removeAffectedAssetEntry = new cF4sdApiSearchResultRelation()
|
||||
{
|
||||
DisplayName = cMultiLanguageSupport.GetItem("Dialog.CloseCase.RemoveAffectedAssetEntry"),
|
||||
Type = enumF4sdSearchResultClass.Computer,
|
||||
Identities = null,
|
||||
Infos = new Dictionary<string, string> { ["Special"] = "RemoveAffectedAssetEntry" }
|
||||
};
|
||||
private readonly cF4sdApiSearchResultRelation _removeAffectedAssetEntry = new cF4sdApiSearchResultRelation()
|
||||
{
|
||||
DisplayName = cMultiLanguageSupport.GetItem("Dialog.CloseCase.RemoveAffectedAssetEntry"),
|
||||
Type = enumF4sdSearchResultClass.Computer,
|
||||
Identities = null,
|
||||
Infos = new Dictionary<string, string> { ["Special"] = "RemoveAffectedAssetEntry" }
|
||||
};
|
||||
|
||||
private const string CategoryTableNamePrimary = "M42Wpm-Ticket-Categories";
|
||||
private const string CategoryTableNameLegacy = "M42Wpm-Ticket-CloseCase-Categories";
|
||||
private string activeCategoryTableName = CategoryTableNamePrimary;
|
||||
|
||||
private ObservableCollection<HierarchicalSelectionItem> categoryHierarchy = new ObservableCollection<HierarchicalSelectionItem>();
|
||||
private readonly Dictionary<string, HierarchicalSelectionItem> categoryLookup = new Dictionary<string, HierarchicalSelectionItem>(StringComparer.OrdinalIgnoreCase);
|
||||
private bool isCategoryLoading;
|
||||
|
||||
public bool IsTicket
|
||||
{
|
||||
@@ -139,17 +147,17 @@ namespace FasdDesktopUi.Basics.UserControls
|
||||
ShowAssetWarningTicketAction = IsTicket;
|
||||
ValidateProperty("SelectedTicket");
|
||||
EnableHoldTicketAction = _selectedTicket == null || SelectedTicket == _selectTicketRelation || selectedTicketIsNewTicket;
|
||||
if (_selectedTicket != null && _selectedTicket.Infos.TryGetValue("StatusId", out var statusIdString))
|
||||
{
|
||||
object parsedStatusId = Enum.Parse(typeof(enumTicketStatus), statusIdString);
|
||||
if (parsedStatusId is enumTicketStatus statusId)
|
||||
{
|
||||
EnableHoldTicketAction = statusId != enumTicketStatus.OnHold;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (_selectedTicket != null && _selectedTicket.Infos.TryGetValue("StatusId", out var statusIdString))
|
||||
{
|
||||
object parsedStatusId = Enum.Parse(typeof(enumTicketStatus), statusIdString);
|
||||
if (parsedStatusId is enumTicketStatus statusId)
|
||||
{
|
||||
EnableHoldTicketAction = statusId != enumTicketStatus.OnHold;
|
||||
}
|
||||
}
|
||||
TrySelectTicketCategoryFromTicketInfos();
|
||||
}
|
||||
}
|
||||
|
||||
private bool selectedTicketIsNewTicket
|
||||
{
|
||||
@@ -207,26 +215,22 @@ namespace FasdDesktopUi.Basics.UserControls
|
||||
|
||||
#region SelectedCategory DependencyProperty
|
||||
|
||||
public static readonly DependencyProperty SelectedCategoryProperty = DependencyProperty.Register(
|
||||
"SelectedCategory",
|
||||
typeof(KeyValuePair<string, object>),
|
||||
typeof(CloseCaseDialogWithTicket),
|
||||
new PropertyMetadata(default(KeyValuePair<string, object>), OnSelectedCategoryChanged));
|
||||
|
||||
public KeyValuePair<string, object> SelectedCategory
|
||||
{
|
||||
get { return (KeyValuePair<string, object>)GetValue(SelectedCategoryProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(SelectedCategoryProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnSelectedCategoryChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = (CloseCaseDialogWithTicket)d;
|
||||
var newValue = (KeyValuePair<string, object>)e.NewValue;
|
||||
}
|
||||
public static readonly DependencyProperty SelectedCategoryProperty = DependencyProperty.Register(
|
||||
"SelectedCategory",
|
||||
typeof(HierarchicalSelectionItem),
|
||||
typeof(CloseCaseDialogWithTicket),
|
||||
new PropertyMetadata(null, OnSelectedCategoryChanged));
|
||||
|
||||
public HierarchicalSelectionItem SelectedCategory
|
||||
{
|
||||
get { return (HierarchicalSelectionItem)GetValue(SelectedCategoryProperty); }
|
||||
set { SetValue(SelectedCategoryProperty, value); }
|
||||
}
|
||||
|
||||
private static void OnSelectedCategoryChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// Reserved for future use when additional reactions are required.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -373,19 +377,15 @@ namespace FasdDesktopUi.Basics.UserControls
|
||||
me.UpdateAffectedServiceLabel();
|
||||
me.UpdateAffectedAssetComboBox();
|
||||
|
||||
me.ServiceSelectionControl.SearchDataChanged = me.HandleServiceSearchDataChanged;
|
||||
me.ServiceSelectionControl.ParentElement = me.MainStack;
|
||||
me.ServiceSelectionControl.ParentIndex = me.MainStack.Children.IndexOf(me.ServiceSelectionControl);
|
||||
|
||||
me.CategorySelectionControl.ParentElement = me.MainStack;
|
||||
me.CategorySelectionControl.ParentIndex = me.MainStack.Children.IndexOf(me.CategorySelectionControl);
|
||||
|
||||
me.CategorySelectionControl.SearchDataChanged = me.HandleCategorySearchDataChanged;
|
||||
|
||||
me.AddNewOrExistingOrNoneTicketSelection();
|
||||
me.UpdateCaseNotesPreview();
|
||||
me.UpdateTicketComponentVisibility();
|
||||
await me.UpdateQuickCallsComboBoxAsync();
|
||||
me.ServiceSelectionControl.SearchDataChanged = me.HandleServiceSearchDataChanged;
|
||||
me.ServiceSelectionControl.ParentElement = me.MainStack;
|
||||
me.ServiceSelectionControl.ParentIndex = me.MainStack.Children.IndexOf(me.ServiceSelectionControl);
|
||||
|
||||
me.AddNewOrExistingOrNoneTicketSelection();
|
||||
me.UpdateCaseNotesPreview();
|
||||
me.UpdateTicketComponentVisibility();
|
||||
await me.InitializeCategorySelectionAsync();
|
||||
await me.UpdateQuickCallsComboBoxAsync();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
@@ -412,13 +412,8 @@ namespace FasdDesktopUi.Basics.UserControls
|
||||
|
||||
dpd?.AddValueChanged(CaseNotesPreview, TicketCaseNotesTextBlock_TextChanged);
|
||||
|
||||
#if !IsNewFeature
|
||||
CategoryLabelPanel.Visibility = Visibility.Collapsed;
|
||||
CategorySelectionControl.Visibility = Visibility.Collapsed;
|
||||
#endif
|
||||
|
||||
SupportNotepad = true;
|
||||
}
|
||||
SupportNotepad = true;
|
||||
}
|
||||
|
||||
private void CloseCaseDialogWithTicket_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
@@ -886,95 +881,193 @@ namespace FasdDesktopUi.Basics.UserControls
|
||||
|
||||
return null;
|
||||
}
|
||||
private string lastCategorySearch;
|
||||
|
||||
private async void HandleCategorySearchDataChanged(object sender, cF4sdHealthSelectionDataRequest e)
|
||||
{
|
||||
await UpdateCategorySelectionControlAsync(e);
|
||||
}
|
||||
|
||||
private async Task UpdateCategorySelectionControlAsync(cF4sdHealthSelectionDataRequest requestData)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
requestData.Identities = DataProvider.Identities;
|
||||
requestData.Table = "M42Wpm-Ticket-CloseCase-Categories";
|
||||
requestData.ResetFilter = CategorySelectionControl.ResetFilter;
|
||||
|
||||
if (string.IsNullOrEmpty(lastCategorySearch) ||
|
||||
!lastCategorySearch.Equals(requestData.Search, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
var resCategoryCount = await cFasdCockpitCommunicationBase.Instance.GetPagedDataCount(requestData);
|
||||
CategorySelectionControl.TotalItemCount = resCategoryCount;
|
||||
lastCategorySearch = requestData.Search;
|
||||
}
|
||||
|
||||
var categoryData = await cFasdCockpitCommunicationBase.Instance.GetPagedData(requestData);
|
||||
var categoriesList = GetCategorySelectionData(categoryData) ?? new ObservableCollection<KeyValuePair<string, object>>();
|
||||
|
||||
// Aktuell am Ticket gesetzte Kategorie ggf. sicherstellen
|
||||
string categoryId = null;
|
||||
string categoryName = null;
|
||||
|
||||
if (SelectedTicket != null && SelectedTicket.Infos != null)
|
||||
{
|
||||
var catIdPair = SelectedTicket.Infos.FirstOrDefault(x => x.Key == "CategoryId");
|
||||
categoryId = catIdPair.Value;
|
||||
|
||||
var catNamePair = SelectedTicket.Infos.FirstOrDefault(x => x.Key == "CategoryName");
|
||||
categoryName = catNamePair.Value;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(categoryId) && Guid.Empty.ToString() != categoryId)
|
||||
{
|
||||
bool exists = categoriesList.Any(kvp => kvp.Value != null && kvp.Value.ToString() == categoryId);
|
||||
if (!exists)
|
||||
{
|
||||
categoriesList.Add(new KeyValuePair<string, object>(
|
||||
string.IsNullOrEmpty(categoryName) ? categoryId : categoryName,
|
||||
categoryId));
|
||||
}
|
||||
}
|
||||
|
||||
CategorySelectionControl.ItemData = categoriesList;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<KeyValuePair<string, object>> GetCategorySelectionData(cF4SDHealthCardRawData.cHealthCardTable dataTable)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dataTable == null || dataTable.Name != "M42Wpm-Ticket-CloseCase-Categories")
|
||||
return null;
|
||||
|
||||
if (!dataTable.Columns.TryGetValue("id", out var idColumn))
|
||||
return null;
|
||||
|
||||
if (!dataTable.Columns.TryGetValue("Name", out var nameColumn))
|
||||
return null;
|
||||
|
||||
var zippedKeyValuePairs =
|
||||
idColumn.Values.Zip(nameColumn.Values, (id, display) =>
|
||||
new KeyValuePair<string, object>(display != null ? display.ToString() : string.Empty, id));
|
||||
|
||||
return new ObservableCollection<KeyValuePair<string, object>>(zippedKeyValuePairs);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private async Task UpdateQuickCallsComboBoxAsync()
|
||||
{
|
||||
private async Task InitializeCategorySelectionAsync()
|
||||
{
|
||||
if (isCategoryLoading)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (DataProvider == null || CategorySelectionControl == null)
|
||||
return;
|
||||
|
||||
isCategoryLoading = true;
|
||||
|
||||
var tableCandidates = new[] { CategoryTableNamePrimary, CategoryTableNameLegacy };
|
||||
bool initialized = false;
|
||||
|
||||
foreach (var tableName in tableCandidates)
|
||||
{
|
||||
if (await TryPopulateCategoryHierarchyAsync(tableName))
|
||||
{
|
||||
activeCategoryTableName = tableName;
|
||||
initialized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
CategorySelectionControl.ItemsSource = categoryHierarchy;
|
||||
TrySelectTicketCategoryFromTicketInfos();
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isCategoryLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> TryPopulateCategoryHierarchyAsync(string tableName)
|
||||
{
|
||||
try
|
||||
{
|
||||
const int defaultPageSize = 250;
|
||||
|
||||
var requestData = new cF4sdHealthSelectionDataRequest
|
||||
{
|
||||
Identities = DataProvider.Identities,
|
||||
Table = tableName,
|
||||
Page = 0,
|
||||
PageSize = defaultPageSize,
|
||||
Search = string.Empty
|
||||
};
|
||||
|
||||
var totalCount = await cFasdCockpitCommunicationBase.Instance.GetPagedDataCount(requestData);
|
||||
var effectivePageSize = requestData.PageSize > 0 ? requestData.PageSize : defaultPageSize;
|
||||
var pageCount = Math.Max(1, (int)Math.Ceiling((double)totalCount / Math.Max(1, effectivePageSize)));
|
||||
|
||||
var flatItems = new Dictionary<string, HierarchicalSelectionItem>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++)
|
||||
{
|
||||
requestData.Page = pageIndex;
|
||||
requestData.PageSize = effectivePageSize;
|
||||
|
||||
var categoryTable = await cFasdCockpitCommunicationBase.Instance.GetPagedData(requestData);
|
||||
bool rowAdded = false;
|
||||
|
||||
foreach (var item in ConvertCategoryTable(categoryTable))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(item.Id))
|
||||
continue;
|
||||
|
||||
flatItems[item.Id] = item;
|
||||
rowAdded = true;
|
||||
}
|
||||
|
||||
if (!rowAdded && categoryTable == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
var hierarchy = HierarchicalSelectionItem.BuildTree(flatItems.Values);
|
||||
if (hierarchy == null || hierarchy.Count == 0)
|
||||
return false;
|
||||
|
||||
categoryHierarchy = hierarchy;
|
||||
UpdateCategoryLookup();
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<HierarchicalSelectionItem> ConvertCategoryTable(cF4SDHealthCardRawData.cHealthCardTable dataTable)
|
||||
{
|
||||
if (dataTable == null || dataTable.Columns == null)
|
||||
yield break;
|
||||
|
||||
if (!dataTable.Columns.TryGetValue("id", out var idColumn))
|
||||
yield break;
|
||||
|
||||
if (!dataTable.Columns.TryGetValue("Name", out var nameColumn))
|
||||
yield break;
|
||||
|
||||
cF4SDHealthCardRawData.cHealthCardTableColumn parentIdColumn = null;
|
||||
cF4SDHealthCardRawData.cHealthCardTableColumn parentNameColumn = null;
|
||||
if (!dataTable.Columns.TryGetValue("parentValue", out parentIdColumn))
|
||||
dataTable.Columns.TryGetValue("Parent_Value", out parentIdColumn);
|
||||
if (!dataTable.Columns.TryGetValue("parent", out parentNameColumn))
|
||||
dataTable.Columns.TryGetValue("Parent", out parentNameColumn);
|
||||
|
||||
for (int index = 0; index < idColumn.Values.Count; index++)
|
||||
{
|
||||
var id = idColumn.Values[index]?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
continue;
|
||||
|
||||
var displayName = index < nameColumn.Values.Count ? nameColumn.Values[index]?.ToString() : string.Empty;
|
||||
|
||||
string parentId = null;
|
||||
if (parentIdColumn != null && index < parentIdColumn.Values.Count)
|
||||
parentId = parentIdColumn.Values[index]?.ToString();
|
||||
|
||||
if (Guid.TryParse(parentId, out var parsedParentId) && parsedParentId == Guid.Empty)
|
||||
parentId = null;
|
||||
|
||||
var parentDisplayName = parentNameColumn != null && index < parentNameColumn.Values.Count
|
||||
? parentNameColumn.Values[index]?.ToString()
|
||||
: null;
|
||||
|
||||
yield return new HierarchicalSelectionItem
|
||||
{
|
||||
Id = id,
|
||||
DisplayName = string.IsNullOrWhiteSpace(displayName) ? parentDisplayName ?? id : displayName,
|
||||
ParentId = parentId,
|
||||
ParentDisplayName = parentDisplayName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCategoryLookup()
|
||||
{
|
||||
categoryLookup.Clear();
|
||||
|
||||
if (categoryHierarchy == null)
|
||||
return;
|
||||
|
||||
foreach (var node in categoryHierarchy.SelectMany(item => item.SelfAndDescendants()))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(node.Id))
|
||||
categoryLookup[node.Id] = node;
|
||||
}
|
||||
}
|
||||
|
||||
private void TrySelectTicketCategoryFromTicketInfos()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (SelectedTicket?.Infos == null)
|
||||
{
|
||||
SelectedCategory = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SelectedTicket.Infos.TryGetValue("CategoryId", out var categoryId) || string.IsNullOrWhiteSpace(categoryId))
|
||||
{
|
||||
SelectedCategory = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (categoryLookup.TryGetValue(categoryId, out var categoryNode))
|
||||
SelectedCategory = categoryNode;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateQuickCallsComboBoxAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
cF4sdHealthSelectionDataRequest requestData = new cF4sdHealthSelectionDataRequest
|
||||
|
||||
Reference in New Issue
Block a user