using System.Collections.Generic; using System.Text; using Centron.BusinessLogic.WebServices.Administration.Employees; using Centron.BusinessLogic.WebServices.Gui.Profiles; using Centron.Data.WebServices.Administration.Employees; using Centron.Interfaces.Administration.Employees; using Centron.Interfaces.BL; using Centron.Interfaces.UI; using Centron.Tests.EndToEnd.Infrastructure; using CentronSoftware.Centron.WebServices.Entities.Gui.Profiles; using Newtonsoft.Json; using Xunit; using Xunit.Abstractions; namespace Centron.Tests.EndToEnd.Tests.CentronUiProfile; public class CentronUiProfileTests : EndToEndTest { public CentronUiProfileTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { this.Verifier.Settings.IgnoreProperties(f => f.CreatedVersion, f => f.ChangedVersion); } public override void Execute() { // The "CentronUiProfileDTO" profiles have a few properties. A profile includes: // - Caption (string) // - CreatedByI3D (AppUser) // - IsGlobal (bool) // - UiProfileType (c-entron.NET, Service-Board, Service-Board-Ticket, or c-entron Nexus Ticket-List) // // Each profile can relate to a specific employee (CreatedByI3D) or be global (IsGlobal). It also has a name (Caption). // // The "EmployeeSettingsProfileNetDTO" is a place where we keep additional data related to the profile. This data varies depending on its use: // In c-entron.NET, the data is layout information from DevExpress controls such as GridControls, DockLayoutManager, and Custom Layout-Data. // In Service-Board, it's also layout information from DevExpress controls, detailing our columns and filters. // We can use it to keep any related data, as long as it's in byte[] form, like visible columns and filters. // // This entity has: // - CentronUiProfileI3D (int) // - ParentType (string) // - ControlName (string) // - Configuration (byte[]) // // The "Configuration" can hold any data. We identify it by using ParentType+ControlName. // For c-entron.NET, ParentType is the module name. ControlName is the control's name in that module. // // We can use "CentronUiProfileDTO" and "EmployeeSettingsProfileNetDTO" to create multiple saved Ticket-Lists for Service-Board-Web. // The CentronUiProfileDTO provides the ticket-list's name and its global status. // We only need one EmployeeSettingsProfileNetDTO to store the columns and filter the user has selected. // To correctly identify each EmployeeSettingsProfileNetDTO, we can use fixed ParentType and ControlName values ('Ticket-List' for both). // The visible columns and filter data is stored in the byte[] Configuration of the EmployeeSettingsProfileNetDTO (probably json serialized). this.PrepareDatabase(); this.VerifyProfilesAndLayouts("Before"); var profileI3D = this.CreateProfileWithData(); this.VerifyProfilesAndLayouts("ProfileCreated"); this.EditProfile(profileI3D); this.VerifyProfilesAndLayouts("ProfileEdited"); this.DeleteProfile(profileI3D); this.VerifyProfilesAndLayouts("ProfileDeleted"); } private void PrepareDatabase() { this.Sql("DELETE FROM EmployeeSettingsProfileNet"); this.Sql("DELETE FROM CentronUiProfiles"); } private void VerifyProfilesAndLayouts(string name) { var profiles = this.WithSession(s => s.GetBL().LoadProfiles(this.GetLoggedInUser().User.I3D, withDeleted: false, profileType: null, includeGlobal:true)).ThrowIfError(); this.Verifier.Verify($"{name}_Profiles", profiles); var layoutDatas = this.WithSession(s => s.GetBL().LoadEmployeeSettingsProfileNets(new LoadEmployeeSettingsProfilesFilter())); this.Verifier.Verify($"{name}_EmployeeSettingsProfileNetDTO", layoutDatas); } private int CreateProfileWithData() { // First, we need to save a CentronUiProfileDTO var profile = new CentronUiProfileDTO { Caption = "Alle Tickets von Kunde c-entron", UiProfileType = UiProfileType.CentronNexusTicketList, IsGlobal = false, // Everything else either doesn't matter to us, or will be set automatically }; var savedProfileI3D = this.WithSession(s => s.GetBL().SaveProfile(this.GetLoggedInUser(), profile)).ThrowIfError(); // Now we can save the visible-columns and filter information for it (in a EmployeeSettingsProfileNetDTO) var layoutData = new EmployeeSettingsProfileNetDTO { ParentType = "Ticket-List", ControlName = "Ticket-List", CentronUiProfileI3D = savedProfileI3D, // For example serializing some info as json (easy and simple), but it could also be some other binary-format Configuration = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new TicketListData{ VisibleColumns = {"ShortDescription", "DueDate"}, CustomerI3D = 100 })), }; this.WithSession(s => s.GetBL().SaveEmployeeSettingProfileNet(layoutData)); return savedProfileI3D; } private void EditProfile(int profileI3D) { // If we want to update the Caption of the profile, we have to modify the CentronUiProfileDTO var profiles = this.WithSession(s => s.GetBL().LoadProfiles(this.GetLoggedInUser().User.I3D, withDeleted: false, UiProfileType.CentronNexusTicketList, includeGlobal: true)).ThrowIfError(); var profile = Assert.Single(profiles); Assert.Equal(profileI3D, profile.I3D); profile.Caption = "Anderer Name"; this.WithSession(s => s.GetBL().SaveProfile(this.GetLoggedInUser(), profile)).ThrowIfError(); // If we want to update the layout-data of the profile, we have to modify the EmployeeSettingsProfileNetDTO var layoutDatas = this.WithSession(s => s.GetBL().LoadEmployeeSettingsProfileNets(new LoadEmployeeSettingsProfilesFilter { CentronUiProfileI3D = profileI3D, })); var layoutData = Assert.Single(layoutDatas); Assert.Equal("Ticket-List", layoutData.ParentType); Assert.Equal("Ticket-List", layoutData.ControlName); // Showing how you can access the TicketListData again, that we stored in "CreateProfileWithData" var loadedTicketListData = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(layoutData.Configuration)); Assert.Equal(new List {"ShortDescription", "DueDate"}, loadedTicketListData.VisibleColumns); Assert.Equal(100, loadedTicketListData.CustomerI3D); loadedTicketListData.HelpdeskTypeI3D = 4; layoutData.Configuration = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(loadedTicketListData)); this.WithSession(s => s.GetBL().SaveEmployeeSettingProfileNet(layoutData)); } private void DeleteProfile(int profileI3D) { // This will also delete all associated EmployeeSettingsProfileNetDTO automatically this.WithSession(s => s.GetBL().DeleteProfile(this.GetLoggedInUser(), profileI3D)).ThrowIfError(); } // Example class to show how we can store any kind of data in the EmployeeSettingsProfileNetDTO private class TicketListData { public List VisibleColumns { get; set; } = new(); // Filters public int? CustomerI3D { get; set; } public int? HelpdeskTypeI3D { get; set; } } }