123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- using Comal.Classes;
- using FastReport;
- using InABox.Clients;
- using InABox.Configuration;
- using InABox.Core;
- using InABox.Core.Reports;
- using InABox.DynamicGrid;
- using InABox.Scripting;
- using InABox.Wpf;
- using InABox.Wpf.Reports;
- using InABox.WPF;
- using PRSDesktop.Configuration;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- namespace PRSDesktop;
- public interface IPanelHostControl
- {
- void ClearActions();
- void CreatePanelAction(PanelAction action);
- void ClearReports();
- void CreateReport(PanelAction action);
- }
- public class PanelHost : IPanelHost
- {
- public IBasePanel? CurrentPanel { get; private set; }
- public string CurrentModuleName { get; private set; } = "";
- private readonly IPanelHostControl HostControl;
- private readonly List<IPanelActionItem> SetupActions = new();
- public PanelHost(IPanelHostControl hostControl)
- {
- HostControl = hostControl;
- }
- #region Module Tracking
- private int TrackedClicks;
- private int TrackedKeys;
- private DateTime TrackedTicks = DateTime.MinValue;
- public void IncrementTrackingModuleClick()
- {
- if (CurrentPanel is not null)
- TrackedClicks++;
- }
- public void IncrementTrackingModuleKey()
- {
- if (CurrentPanel is not null)
- TrackedKeys++;
- }
- #endregion
- #region IPanelHost
- void IPanelHost.CreatePanelAction(PanelAction action)
- {
- HostControl.CreatePanelAction(action);
- }
- void IPanelHost.CreateReport(PanelAction action)
- {
- HostControl.CreateReport(action);
- }
- void IPanelHost.CreateSetupAction(PanelAction action)
- {
- SetupActions.Add(action);
- }
- void IPanelHost.CreateSetupSeparator()
- {
- SetupActions.Add(new PanelActionSeparator());
- }
- #endregion
- #region Panel Properties
- private void ConfigurePanel()
- {
- if (CurrentPanel is null) return;
- PanelUtils.ConfigurePanel(CurrentPanel);
- }
- #endregion
- #region Actions
- private void ReloadActions(string sectionName, DataModel model)
- {
- ReportUtils.ExportDefinitions.Clear();
- ReportUtils.ExportDefinitions.AddRange(PRSEmailUtils.CreateTemplateDefinitions(model));
- SetupActions.Clear();
- HostControl.ClearActions();
- HostControl.ClearReports();
-
- if (CurrentPanel != null)
- CurrentPanel.CreateToolbarButtons(this);
- CreateModules(sectionName, model);
-
- CreateReports(sectionName, model);
- }
- #endregion
- #region Custom Modules
- private void CreateModules(string section, DataModel model)
- {
- if (ClientFactory.IsSupported<CustomModule>())
- {
- foreach (var (module, image) in CustomModuleUtils.LoadCustomModuleThumbnails(section, model))
- {
- HostControl.CreatePanelAction(new PanelAction
- {
- Caption = module.Name ?? "",
- Image = image,
- OnExecute = (action) =>
- {
- ClickModule(action, module);
- }
- });
- }
- }
- }
- private void ClickModule(PanelAction action, CustomModule code)
- {
- if (CurrentPanel != null)
- {
- if (!string.IsNullOrWhiteSpace(code.Script))
- try
- {
- Selection selection;
- if (code.SelectedRecords && code.AllRecords)
- selection = RecordSelectionDialog.Execute();
- else if (code.SelectedRecords)
- selection = Selection.Selected;
- else if (code.AllRecords)
- selection = Selection.All;
- else
- selection = Selection.None;
- var result = ScriptDocument.RunCustomModule(CurrentPanel.DataModel(selection), CurrentPanel.Selected(), code.Script);
- if (result)
- CurrentPanel.Refresh();
- }
- catch (CompileException c)
- {
- MessageWindow.ShowError(c.Message, c, shouldLog: false);
- }
- catch (Exception err)
- {
- MessageWindow.ShowError($"Unable to load {action.Caption}", err);
- }
- else
- MessageWindow.ShowMessage("Unable to load " + action.Caption, "Error", image: MessageWindow.WarningImage);
- }
- }
- private void ManageModules(PanelAction action)
- {
- if (CurrentPanel != null)
- {
- var section = CurrentPanel.SectionName;
- var dataModel = CurrentPanel.DataModel(Selection.Selected);
- var manager = new CustomModuleManager()
- {
- Section = section,
- DataModel = dataModel
- };
- manager.ShowDialog();
- ReloadActions(section, dataModel);
- }
- }
- #endregion
- #region Reports
- public static PanelAction CreateReportAction(ReportTemplate template, Func<Selection, DataModel> getDataModel)
- {
- var action = new PanelAction
- {
- Caption = template.Name,
- Image = PRSDesktop.Resources.printer,
- OnExecute = (action) =>
- {
- PrintReport(template.ID, getDataModel);
- }
- };
- if (Security.IsAllowed<CanDesignReports>())
- {
- var menu = new ContextMenu();
- menu.AddItem("Design Report", PRSDesktop.Resources.pencil, () => DesignReport(template.ID, getDataModel));
- action.Menu = menu;
- }
- return action;
- }
- private void CreateReports(string section, DataModel model)
- {
- if (CurrentPanel is null) return;
- var client = new Client<ReportTemplate>();
- var templates = ReportUtils.LoadReports(section, model, Columns.None<ReportTemplate>().Add(x => x.ID, x => x.Name));
- foreach (var template in templates)
- {
- HostControl.CreateReport(CreateReportAction(template, CurrentPanel.DataModel));
- }
- }
- private static void DesignReport(Guid templateID, Func<Selection, DataModel> getDataModel)
- {
- var template = new Client<ReportTemplate>().Load(new Filter<ReportTemplate>(x => x.ID).IsEqualTo(templateID)).FirstOrDefault();
- if (template is null)
- {
- Logger.Send(LogType.Error, "", $"No Report Template with ID '{templateID}'");
- MessageWindow.ShowMessage("Report does not exist!", "Error", image: MessageWindow.WarningImage);
- return;
- }
- ReportUtils.DesignReport(template, getDataModel(Selection.None));
- }
- private static void PrintReport(Guid id, Func<Selection, DataModel> getDataModel)
- {
- var template = new Client<ReportTemplate>().Load(new Filter<ReportTemplate>(x => x.ID).IsEqualTo(id)).FirstOrDefault();
- if (template == null)
- {
- Logger.Send(LogType.Error, "", $"No Report Template with ID '{id}'");
- MessageWindow.ShowMessage("Report does not exist!", "Error", image: MessageWindow.WarningImage);
- return;
- }
- var selection = Selection.None;
- if (template.SelectedRecords && template.AllRecords)
- selection = RecordSelectionDialog.Execute();
- else if (template.SelectedRecords)
- selection = Selection.Selected;
- else if (template.AllRecords)
- selection = Selection.All;
- else
- MessageWindow.ShowMessage(
- "Report must have either [Selected Records] or [All Records] checked to display!",
- "Error",
- image: MessageWindow.WarningImage);
- if (selection != Selection.None)
- ReportUtils.PreviewReport(template, getDataModel(selection), false, Security.IsAllowed<CanDesignReports>());
- }
- private void ManageReports(PanelAction action)
- {
- if (CurrentPanel is null)
- return;
- var section = CurrentPanel.SectionName;
- var model = CurrentPanel.DataModel(Selection.None);
- if (model == null)
- {
- MessageWindow.ShowMessage("No DataModel for " + CurrentPanel.SectionName, "No DataModel");
- return;
- }
- var form = new ReportManager { DataModel = model, Section = section, Populate = true };
- form.ShowDialog();
- ReloadActions(section, model);
- }
- private void ManageEmailTemplates(PanelAction action)
- {
- if (CurrentPanel is null)
- return;
- var section = CurrentPanel.SectionName;
- var model = CurrentPanel.DataModel(Selection.None);
- if (model == null)
- {
- MessageWindow.ShowMessage("No DataModel for " + section, "No DataModel");
- return;
- }
- var window = new EmailTemplateManagerWindow(model);
- window.ShowDialog();
- }
- #endregion
- #region Public Interface
- public void InitialiseSetupMenu(ContextMenu menu)
- {
- var items = new List<IPanelActionItem>();
- items.AddRange(SetupActions);
- items.Add(new PanelActionSeparator());
- if (Security.IsAllowed<CanCustomiseModules>())
- {
- items.Add(new PanelAction("Custom Modules", PRSDesktop.Resources.script, ManageModules));
- }
- if (Security.IsAllowed<CanDesignReports>())
- {
- items.Add(new PanelAction("Reports", PRSDesktop.Resources.printer, ManageReports));
- }
- if (Security.IsAllowed<CanDesignReports>())
- {
- items.Add(new PanelAction("Email Templates", PRSDesktop.Resources.email, ManageEmailTemplates));
- }
- for (var i = 0; i < items.Count; ++i)
- {
- var item = items[i];
- if (item is PanelAction setupAction)
- {
- menu.AddItem(setupAction.Caption, setupAction.Image, setupAction, setupAction.OnExecute);
- }
- else if (item is PanelActionSeparator && i > 0 && i < items.Count - 1)
- {
- var last = items[i - 1];
- if (last is not PanelActionSeparator)
- menu.AddSeparator();
- }
- }
- if (CurrentPanel?.GetType().HasInterface(typeof(IPropertiesPanel<>)) == true && Security.IsAllowed<CanConfigurePanels>())
- {
- var securityInterface = CurrentPanel?.GetType().GetInterfaceDefinition(typeof(IPropertiesPanel<,>));
- var canConfigure = false;
- if (securityInterface is not null)
- {
- var token = securityInterface.GenericTypeArguments[1];
- canConfigure = Security.IsAllowed(token);
- }
- else
- {
- canConfigure = Security.IsAllowed<CanConfigurePanels>();
- }
- if (canConfigure)
- {
- menu.AddItem("Configure Panel", PRSDesktop.Resources.edit, ConfigurePanel);
- }
- }
- if (menu.Items.Count == 0)
- {
- menu.AddItem("No Items", null, null, false);
- }
- }
- public IBasePanel LoadPanel(Type T, string moduleName)
- {
- return (LoadPanelMethod.MakeGenericMethod(T).Invoke(this, new object[] { moduleName })
- as IBasePanel)!;
- }
- private static readonly MethodInfo LoadPanelMethod = typeof(PanelHost)
- .GetMethods().First(x => x.Name == nameof(LoadPanel) && x.IsGenericMethod);
- public T LoadPanel<T>(string moduleName) where T : class, IBasePanel, new()
- {
- var panel = PanelUtils.LoadPanel<T>();
- CurrentPanel = panel;
- CurrentModuleName = moduleName;
- TrackedTicks = DateTime.Now;
- CurrentPanel.OnUpdateDataModel += ReloadActions;
- var model = CurrentPanel.DataModel(Selection.None);
- var section = CurrentPanel.SectionName;
- ReloadActions(section, model);
- return panel;
- }
- public void Refresh()
- {
- CurrentPanel?.Refresh();
- }
- private void Heartbeat(TimeSpan time, bool closing)
- {
- if (TrackedTicks == DateTime.MinValue)
- return;
- if (!closing && time.TotalMinutes < 5)
- return;
- TrackedTicks = DateTime.Now;
- if (CurrentPanel is not null)
- {
- //Logger.Send(LogType.Information, "", string.Format("Heartbeat: {0}", CurrentPanel_Label));
- if (ClientFactory.IsSupported<ModuleTracking>())
- {
- var keys = TrackedKeys;
- TrackedKeys = 0;
- var clicks = TrackedClicks;
- TrackedClicks = 0;
- var tracking = new ModuleTracking
- {
- Date = DateTime.Today,
- Module = CurrentModuleName,
- Clicks = clicks,
- Keys = keys,
- ActiveTime = clicks + keys > 0 ? time : new TimeSpan(),
- IdleTime = clicks + keys == 0 ? time : new TimeSpan()
- };
- tracking.User.ID = ClientFactory.UserGuid;
- new Client<ModuleTracking>().Save(tracking, "", (mt, ex) => { });
- }
- CurrentPanel.Heartbeat(time);
- }
- }
- public void Heartbeat()
- {
- Heartbeat(DateTime.Now - TrackedTicks, false);
- }
- public void UnloadPanel(CancelEventArgs? cancel)
- {
- if (CurrentPanel != null)
- {
- Heartbeat(DateTime.Now - TrackedTicks, true);
- PanelUtils.UnloadPanel(CurrentPanel, cancel);
- if (cancel?.Cancel == true)
- {
- return;
- }
- TrackedTicks = DateTime.MinValue;
- CurrentModuleName = "";
- TrackedClicks = 0;
- TrackedKeys = 0;
- }
- }
- #endregion
- }
|