using Comal.Classes; using InABox.Clients; using InABox.Core; using InABox.Core.Postable; using InABox.DynamicGrid; using InABox.Wpf; using InABox.WPF; using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; namespace PRSDesktop; public static class PostUtils { private static readonly Inflector.Inflector inflector = new(new CultureInfo("en")); public static void PostEntities(IDataModel model, Action refresh, Action? configurePost = null) where T : Entity, IPostable, IRemotable, IPersistent, new() { try { var result = PosterUtils.Process(model); if(result is null) { MessageWindow.ShowMessage($"Processing failed", "Processing failed"); refresh(); } else { var failedMessages = new List(); var successCount = 0; foreach(var entity in result.PostedEntities) { if(entity.PostedStatus == PostedStatus.PostFailed) { failedMessages.Add(entity.PostedNote); } else { successCount++; } } if(successCount == 0) { MessageWindow.ShowMessage($"Processing failed:\n - {string.Join("\n - ", failedMessages)}", "Processing failed."); } else if(failedMessages.Count == 0) { MessageWindow.ShowMessage($"Processing successful; {successCount} items processed", "Processing successful."); } else { MessageWindow.ShowMessage($"{successCount} items succeeded, but {failedMessages.Count} failed:\n - {string.Join("\n - ", failedMessages)}", "Partial success"); } refresh(); } } catch (EmptyPostException) { MessageWindow.ShowMessage($"Please select at least one {typeof(T).Name}.", "Select items"); } catch (PostFailedMessageException e) { MessageWindow.ShowMessage(e.Message, "Post failed"); } catch (RepostedException) { MessageWindow.ShowMessage("At least one of the items you selected has already been processed. Processing cancelled.", "Already processed"); } catch (PostCancelledException) { MessageWindow.ShowMessage("Processing cancelled.", "Cancelled"); } catch (MissingSettingsException) { if (configurePost is not null && Security.CanConfigurePost()) { if (MessageWindow.ShowYesNo($"Processing has not been configured for {inflector.Pluralize(typeof(T).Name)}. Would you like to configure this now?", "Configure Processing?")) { configurePost(); } else { MessageWindow.ShowMessage("Processing cancelled.", "Cancelled"); } } else { MessageWindow.ShowMessage($"Processing has not been configured for {inflector.Pluralize(typeof(T).Name)}!", "Unconfigured"); } } catch (Exception e) { MessageWindow.ShowError("Processing failed.", e); refresh(); } } public static void CreateToolbarButtons(IPanelHost host, Func> model, Action refresh, Action? configurePost = null) where T : Entity, IPostable, IRemotable, IPersistent, new() { var postSettings = PosterUtils.LoadPostableSettings(); if (Security.CanPost() && !postSettings.PosterType.IsNullOrWhiteSpace()) { Bitmap? image = null; if (postSettings.Thumbnail.ID != Guid.Empty) { var icon = new Client() .Load(new Filter(x => x.ID).IsEqualTo(postSettings.Thumbnail.ID)).FirstOrDefault(); if (icon?.Data?.Any() == true) image = new ImageConverter().ConvertFrom(icon.Data) as Bitmap; } host.CreatePanelAction(new PanelAction { Caption = postSettings.ButtonName.NotWhiteSpaceOr($"Process {inflector.Pluralize(typeof(T).Name)}"), Image = image ?? PRSDesktop.Resources.edit, OnExecute = action => { PostEntities( model(), refresh, configurePost); } }); if (postSettings.ShowClearButton) { host.CreatePanelAction(new PanelAction { Caption = "Clear Posted Flag", Image = image ?? PRSDesktop.Resources.refresh, OnExecute = action => { var dataModel = model(); foreach(var (key, table) in dataModel.ModelTables) { table.IsDefault = false; } dataModel.SetColumns(Columns.Required().Add(x => x.PostedStatus).Add(x => x.PostedReference).Add(x => x.PostedNote).Add(x => x.Posted)); dataModel.SetIsDefault(true); dataModel.LoadModel(); var items = dataModel.GetTable().ToArray(); foreach(var item in items) { item.PostedStatus = PostedStatus.NeverPosted; item.PostedReference = ""; item.PostedNote = ""; item.Posted = DateTime.MinValue; } Client.Save(items, "Cleared posted flag"); refresh(); } }); } } if (configurePost is not null && Security.CanConfigurePost()) { host.CreateSetupAction(new PanelAction { Caption = $"Configure {CoreUtils.Neatify(typeof(T).Name)} Processing", OnExecute = action => { configurePost(); } }); } } public static void ConfigurePost() where T : Entity, IPostable, IRemotable, IPersistent, new() { var postSettings = PosterUtils.LoadPostableSettings(); var grid = (DynamicGridUtils.CreateDynamicGrid(typeof(DynamicGrid<>), typeof(PostableSettings)) as DynamicGrid)!; if (grid.EditItems(new PostableSettings[] { postSettings })) { PosterUtils.SavePostableSettings(postSettings); } } public static void CreateToolbarButtons(IPanelHost host, Func> model, Action refresh, bool allowConfig) where T : Entity, IPostable, IRemotable, IPersistent, new() { CreateToolbarButtons(host, model, refresh, allowConfig ? ConfigurePost : null); } #region PostColumn private static readonly BitmapImage? post = PRSDesktop.Resources.post.AsBitmapImage(); private static readonly BitmapImage? tick = PRSDesktop.Resources.tick.AsBitmapImage(); private static readonly BitmapImage? warning = PRSDesktop.Resources.warning.AsBitmapImage(); private static readonly BitmapImage? refresh = PRSDesktop.Resources.refresh.AsBitmapImage(); public static void AddPostColumn(DynamicGrid grid) where T : Entity, IPostable, IRemotable, IPersistent, new() { grid.HiddenColumns.Add(x => x.PostedStatus); grid.HiddenColumns.Add(x => x.PostedNote); grid.ActionColumns.Add(new DynamicImageColumn( row => { if (row is null) return post; return row.Get(x => x.PostedStatus) switch { PostedStatus.PostFailed => warning, PostedStatus.Posted => tick, PostedStatus.RequiresRepost => refresh, PostedStatus.NeverPosted or _ => null, }; }, null) { ToolTip = (column, row) => { if (row is null) { return column.TextToolTip($"{CoreUtils.Neatify(typeof(T).Name)} Processed Status"); } return column.TextToolTip(row.Get(x => x.PostedStatus) switch { PostedStatus.PostFailed => "Post failed: " + row.Get(x => x.PostedNote), PostedStatus.RequiresRepost => "Repost required: " + row.Get(x => x.PostedNote), PostedStatus.Posted => "Processed", PostedStatus.NeverPosted or _ => "Not posted yet", }); } }); } #endregion }