瀏覽代碼

Made the "edit.png" icon transparent background. DF Dashboard custom modules now load in a separate thread.
Added Favourites to the Dashboards screen and caused a new dashboard to be created if the last one was removed

Kenric Nugteren 2 年之前
父節點
當前提交
dea15ab35e

+ 15 - 3
prs.desktop/Dashboards/DigitalFormsDashboard.xaml.cs

@@ -469,10 +469,22 @@ namespace PRSDesktop
 
             menu.AddSeparatorIfNeeded();
             menu.AddItem("Export", InABox.DynamicGrid.Properties.Resources.doc_xls, Export_Click, Form is not null && Form.ID != Guid.Empty);
-            foreach (var (module, image) in CustomModuleUtils.LoadCustomModuleThumbnails(SectionName, DataModel(Selection.None)))
+            var loadingModules = menu.AddItem("Loading Modules...", null, null, false);
+            Task.Run(() =>
             {
-                menu.AddItem(module.Name, image, module, ExecuteModule_Click);
-            }
+                return CustomModuleUtils.LoadCustomModuleThumbnails(SectionName, DataModel(Selection.None));
+            }).ContinueWith((task) =>
+            {
+                var modules = task.Result;
+                var index = menu.Items.IndexOf(loadingModules);
+                menu.Items.RemoveAt(index);
+                foreach (var (module, image) in modules)
+                {
+                    menu.AddItem(module.Name, image, module, ExecuteModule_Click, index: index);
+                    ++index;
+                }
+            }, TaskScheduler.FromCurrentSynchronizationContext());
+
             if (Security.IsAllowed<CanCustomiseModules>())
             {
                 menu.AddSeparatorIfNeeded();

+ 321 - 166
prs.desktop/Dashboards/UtilityDashboard.xaml.cs

@@ -8,21 +8,75 @@ using System.Windows.Media;
 using InABox.Configuration;
 using InABox.Core;
 using InABox.DynamicGrid;
+using InABox.WPF;
 using InABox.WPF.Themes;
 using Microsoft.Xaml.Behaviors.Core;
 using Syncfusion.Windows.Tools.Controls;
 
 namespace PRSDesktop
 {
+    public class DashboardFavourite : BaseObject
+    {
+        public string Name { get; set; }
+
+        [NullEditor]
+        public string Layout { get; set; }
+    }
+
+    public class DynamicItemsListGrid<T> : DynamicGrid<T>
+        where T : BaseObject, new()
+    {
+        public List<T> Items { get; set; }
+
+        public DynamicItemsListGrid() : this(new()) { }
+
+        public DynamicItemsListGrid(List<T> items) : base()
+        {
+            Items = items;
+        }
+
+        protected override void DeleteItems(params CoreRow[] rows)
+        {
+            foreach (var row in rows.OrderByDescending(x => x.Index))
+            {
+                Items.RemoveAt(row.Index);
+            }
+        }
+
+        protected override T LoadItem(CoreRow row)
+        {
+            return Items[row.Index];
+        }
+
+        protected override void Reload(Filters<T> criteria, Columns<T> columns, ref SortOrder<T>? sort, Action<CoreTable?, Exception?> action)
+        {
+            var result = new CoreTable();
+            result.LoadColumns(typeof(T));
+            result.LoadRows(Items);
+            action.Invoke(result, null);
+        }
+
+        protected override void SaveItem(T item)
+        {
+            if (!Items.Contains(item))
+            {
+                Items.Add(item);
+            }
+        }
+    }
+
     public class UtilityDashboardSettings : UserConfigurationSettings
     {
         public UtilityDashboardSettings()
         {
             Dashboards = new Dictionary<string, string>();
+            Favourites = new();
         }
 
         public Dictionary<string, string> Dashboards { get; set; }
 
+        public List<DashboardFavourite> Favourites { get; set; }
+
         public int Selected { get; set; }
         public bool AutoHide { get; set; }
     }
@@ -33,7 +87,7 @@ namespace PRSDesktop
     public partial class UtilityDashboard : UserControl, IBasePanel
     {
         
-        private Dictionary<string, DynamicFormDesignGrid> _dashboards = new();
+        private readonly Dictionary<string, DynamicFormDesignGrid> _dashboards = new();
 
         private readonly Dictionary<DynamicFormDesignGrid, List<ICorePanel>> _panels = new();
 
@@ -79,180 +133,239 @@ namespace PRSDesktop
             InitializeComponent();
         }
 
-        public bool IsReady { get; set; }
-
-        public event DataModelUpdateEvent OnUpdateDataModel;
-
         public void CreateToolbarButtons(IPanelHost host)
         {
         }
 
-        public string? SectionName => "Utility Dashboard";
-
-        public DataModel? DataModel(Selection selection)
+        private void SaveSettings()
         {
-            return new EmptyDataModel();
+            new UserConfiguration<UtilityDashboardSettings>().Save(_settings);
         }
 
-        public void Heartbeat(TimeSpan time)
+        #region Panel Functions & Properties
+
+        public event DataModelUpdateEvent? OnUpdateDataModel;
+
+        public bool IsReady { get; set; }
+
+        public string SectionName => "Utility Dashboard";
+
+        public DataModel DataModel(Selection selection)
         {
+            return new EmptyDataModel();
         }
 
-        private void SaveDashboard(string name, DynamicFormDesignGrid grid)
+        public void Setup()
         {
-            _settings.Dashboards[name] = grid.Form.SaveLayout();
-            if (IsReady)
-                new UserConfiguration<UtilityDashboardSettings>().Save(_settings);
+            _settings = new UserConfiguration<UtilityDashboardSettings>().Load();
+            if (_settings.Dashboards.Count == 0) _settings.Dashboards["New Dashboard"] = CreateForm("").SaveLayout();
+
+            foreach (var key in _settings.Dashboards.Keys)
+                CreateTab(key);
+
+            if (_settings.Selected >= -1 && _settings.Selected < DashboardsTab.Items.Count)
+                DashboardsTab.SelectedIndex = _settings.Selected;
+
+            //DashboardsTab.FullScreenMode = _settings.AutoHide ? FullScreenMode.ControlMode : FullScreenMode.None;
         }
 
-        private void SaveCurrentDashboard()
+        public Dictionary<string, object[]> Selected()
         {
-            var name = CurrentDashboardName;
-            if (name == null) return;
-            var grid = CurrentDashboard;
-            if (grid == null) return;
-            SaveDashboard(name, grid);
+            return new Dictionary<string, object[]>();
         }
 
-        private void ShutdownDashboard(string name, DynamicFormDesignGrid grid)
+        public void Heartbeat(TimeSpan time)
         {
-            SaveDashboard(name, grid);
-            foreach (var panel in _panels[grid])
-            {
-                panel.Shutdown();
-            }
-            _panels[grid].Clear();
         }
 
-        private void ShutdownDashboard()
+        public void Refresh()
         {
-            var name = CurrentDashboardName;
-            if (name == null) return;
-            var grid = CurrentDashboard;
-            if (grid == null) return;
-            ShutdownDashboard(name, grid);
+            RefreshDashboard(CurrentDashboardName);
         }
 
-        private void RefreshDashboard(string name)
+        public void Shutdown()
         {
-            if (!_dashboards.ContainsKey(name))
-                return;
-            var grid = _dashboards[name];
-            if (_panels.ContainsKey(grid))
+            foreach (var (name, grid) in _dashboards)
             {
-                foreach (var panel in _panels[grid])
-                    panel.Refresh();
+                ShutdownDashboard(name, grid);
             }
+            _panels.Clear();
         }
 
-        public void Refresh()
+        #endregion
+
+        #region Favourites
+
+        private void ManageFavourites_Click()
         {
-            RefreshDashboard(CurrentDashboardName);
+            var grid = new DynamicItemsListGrid<DashboardFavourite>(_settings.Favourites);
+            grid.Options.AddRange(DynamicGridOption.DeleteRows, DynamicGridOption.EditRows, DynamicGridOption.MultiSelect);
+            DynamicGridUtils.CreateGridWindow("Manage Favourites", grid).ShowDialog();
+            SaveSettings();
         }
 
-        public Dictionary<string, object[]> Selected()
+        private void SaveAsFavourite_Click(string dashboardName)
         {
-            return new Dictionary<string, object[]>();
+            _settings.Favourites.Add(new DashboardFavourite
+            {
+                Name = dashboardName,
+                Layout = _dashboards.GetValueOrDefault(dashboardName)?.Form.SaveLayout() ?? _settings.Dashboards[dashboardName]
+            });
+            SaveSettings();
         }
 
-        public void Setup()
+        private void LoadFavourite_Click(DashboardFavourite favourite)
         {
-            _settings = new UserConfiguration<UtilityDashboardSettings>().Load();
-            if (_settings.Dashboards.Count == 0) _settings.Dashboards["New Dashboard"] = CreateForm("").SaveLayout();
+            var name = CreateNewTabName(favourite.Name);
+            _settings.Dashboards[name] = favourite.Layout;
+            SaveSettings();
 
-            foreach (var key in _settings.Dashboards.Keys)
-                CreateTab(key);
+            var tab = CreateTab(name);
+            DashboardsTab.SelectedItem = tab;
+        }
 
-            if (_settings.Selected >= -1 && _settings.Selected < DashboardsTab.Items.Count)
-                DashboardsTab.SelectedIndex = _settings.Selected;
+        #endregion
 
-            //DashboardsTab.FullScreenMode = _settings.AutoHide ? FullScreenMode.ControlMode : FullScreenMode.None;
-        }
+        #region Tabs
 
-        private void InitializeTab(DynamicTabItem tab)
+        private void Tab_OnContextMenuOpening(object sender, DynamicTabItemContextMenuEventArgs args)
         {
-            tab.CanClose = true;
-            tab.OnCloseTab += (sender, args) =>
+            var name = (DashboardsTab.SelectedItem as DynamicTabItem)?.Header?.ToString();
+            if (string.IsNullOrEmpty(name))
+                return;
+
+            DynamicFormDesignGrid grid = _dashboards[name];
+
+            var menu = args.Menu;
+            menu.AddSeparatorIfNeeded();
+
+            menu.Items.Add(new MenuItem()
             {
-                var name = args.TabItem.Header?.ToString();
-                if (name is null)
-                    return;
-                _dashboards.Remove(name);
-                _settings.Dashboards.Remove(name);
-                DashboardsTab.ChangedCommand.Execute(null);
-            };
-            tab.CanRename = true;
-            tab.OnTabRenamed += (sender, args) =>
+                Header = grid.Mode == FormMode.Preview ? "Design Mode" : "Close Design Mode",
+                Command = new ActionCommand(() =>
+                {
+                    if (grid.Mode == FormMode.Designing)
+                    {
+                        grid.Mode = FormMode.Preview;
+                        SaveCurrentDashboard();
+                        DashboardsTab.ChangedCommand.Execute(null);
+                    }
+                    else
+                    {
+                        ShutdownDashboard();
+                        grid.Mode = FormMode.Designing;
+                    }
+                })
+            });
+
+            menu.AddSeparator();
+            menu.AddItem("Save as Favourite", null, name, SaveAsFavourite_Click);
+            if (_settings.Favourites.Any())
             {
-                var oldSettings = _settings.Dashboards[args.OldName];
-                _settings.Dashboards.Remove(args.OldName);
+                menu.AddItem("Manage Favourites", null, ManageFavourites_Click);
 
-                if (_dashboards.TryGetValue(args.OldName, out var dashboard))
-                {
-                    _dashboards.Remove(args.OldName);
-                    _dashboards[args.NewName] = dashboard;
-                    _settings.Dashboards[args.NewName] = dashboard.Form.SaveLayout();
-                }
-                else
+                menu.AddSeparator();
+                foreach (var favourite in _settings.Favourites)
                 {
-                    _settings.Dashboards[args.NewName] = oldSettings;
+                    menu.AddItem(favourite.Name, null, favourite, LoadFavourite_Click);
                 }
+            }
+        }
 
-            };
+        private void Tab_OnCloseTab(object sender, DynamicTabControlEventArgs args)
+        {
+            var name = args.TabItem.Header?.ToString();
+            if (name is null)
+                return;
+            _dashboards.Remove(name);
+            _settings.Dashboards.Remove(name);
 
-            tab.OnContextMenuOpening += (sender, args) =>
+            if (!_settings.Dashboards.Any())
             {
-                String? name = (DashboardsTab.SelectedItem as DynamicTabItem)?.Header?.ToString();
-                if (String.IsNullOrEmpty(name))
-                    return;
+                var tab = new DynamicTabItem();
+                InitializeNewDashboardTab(tab);
+                DashboardsTab.Items.Add(tab);
+            }
+            else
+            {
+                DashboardsTab.ChangedCommand.Execute(null);
+            }
+        }
 
-                DynamicFormDesignGrid grid = _dashboards[name];
+        private void Tab_OnTabRenamed(object sender, DynamicTabItemRenamedEventArgs args)
+        {
+            args.NewName = CreateNewTabName(args.NewName);
 
-                var menu = args.Menu;
-                menu.Items.Add(new Separator());
+            var oldSettings = _settings.Dashboards[args.OldName];
+            _settings.Dashboards.Remove(args.OldName);
 
-                menu.Items.Add(new MenuItem()
-                {
-                    Header = grid.Mode == FormMode.Preview ? "Design Mode" : "Close Design Mode",
-                    Command = new ActionCommand(() =>
-                    {
-                        if (grid.Mode == FormMode.Designing)
-                        {
-                            grid.Mode = FormMode.Preview;
-                            SaveCurrentDashboard();
-                            DashboardsTab.ChangedCommand.Execute(null);
-                        }
-                        else
-                        {
-                            ShutdownDashboard();
-                            grid.Mode = FormMode.Designing;
-                        }
-                    })
-                });
-            };
+            if (_dashboards.TryGetValue(args.OldName, out var dashboard))
+            {
+                _dashboards.Remove(args.OldName);
+                _dashboards[args.NewName] = dashboard;
+                _settings.Dashboards[args.NewName] = dashboard.Form.SaveLayout();
+            }
+            else
+            {
+                _settings.Dashboards[args.NewName] = oldSettings;
+            }
         }
 
-        private void CreateTab(string key)
+        /// <summary>
+        /// Setup events on a new tab.
+        /// </summary>
+        /// <param name="tab"></param>
+        private void InitializeTab(DynamicTabItem tab)
         {
-            var tab = new DynamicTabItem() { Header = key };
-            InitializeTab(tab);
-            DashboardsTab.Items.Add(tab);
+            tab.CanClose = true;
+            tab.OnCloseTab += Tab_OnCloseTab;
+            tab.CanRename = true;
+            tab.OnTabRenamed += Tab_OnTabRenamed;
+            tab.OnContextMenuOpening += Tab_OnContextMenuOpening;
         }
 
-        private void AddDashboard(DynamicTabItem tab)
+        private string CreateNewTabName(string name)
         {
-            var name = "New Dashboard";
-            var i = 0;
-            while (TabNameExists(name))
+            var newName = name;
+            int i = 1;
+            while (TabNameExists(newName))
             {
-                i++;
-                name = string.Format("New Dashboard ({0})", i);
+                newName = $"{name} ({i})";
+                ++i;
             }
+            return newName;
+        }
+
+        private bool TabNameExists(string name)
+        {
+            return _settings.Dashboards.ContainsKey(name);
+        }
+
+        /// <summary>
+        /// Creates a new tab with a given header and adds it to <see cref="DashboardsTab"/>.
+        /// </summary>
+        /// <param name="header"></param>
+        /// <returns></returns>
+        private DynamicTabItem CreateTab(string header)
+        {
+            var tab = new DynamicTabItem() { Header = header };
+            InitializeTab(tab);
+            DashboardsTab.Items.Add(tab);
+            return tab;
+        }
+
+        /// <summary>
+        /// Creates a new dashboard for a tab, and then initializes the tab.
+        /// </summary>
+        /// <param name="tab"></param>
+        private void InitializeNewDashboardTab(DynamicTabItem tab)
+        {
+            var name = CreateNewTabName("New Dashboard");
 
             _settings.Dashboards[name] = CreateForm("").SaveLayout();
             DashboardsTab.ChangedCommand.Execute(null);
 
-            new UserConfiguration<UtilityDashboardSettings>().Save(_settings);
+            SaveSettings();
 
             tab.Header = name;
             InitializeTab(tab);
@@ -260,16 +373,87 @@ namespace PRSDesktop
 
         private void DashboardsTab_OnOnCreateTab(object sender, DynamicTabControlEventArgs args)
         {
-            AddDashboard(args.TabItem);
+            InitializeNewDashboardTab(args.TabItem);
         }
 
-        public void Shutdown()
+        private void DashboardsTab_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
         {
-            foreach (var (name, grid) in _dashboards)
+            if (e.OriginalSource != DashboardsTab)
+                return;
+
+            if (e.AddedItems.Count == 0)
+                return;
+
+            ShutdownDashboard();
+            if (e.AddedItems[0] is DynamicTabItem tab)
             {
-                ShutdownDashboard(name, grid);
+                var name = (tab.Header as string)!;
+                if (tab!.Content == null)
+                    tab.Content = CreateDashboard(name, _settings.Dashboards[name]);
+
+                RefreshDashboard(name);
+                if (IsReady)
+                {
+                    _settings.Selected = tab.TabIndex;
+                    DashboardsTab.ChangedCommand.Execute(null);
+                }
+            }
+        }
+
+        private void DashboardsTab_OnOnTabsChanged(object sender, EventArgs args)
+        {
+            SaveSettings();
+        }
+
+        #endregion
+
+        #region Dashboard & Design
+
+        private void SaveDashboard(string name, DynamicFormDesignGrid grid)
+        {
+            _settings.Dashboards[name] = grid.Form.SaveLayout();
+            if (IsReady)
+                SaveSettings();
+        }
+
+        private void SaveCurrentDashboard()
+        {
+            var name = CurrentDashboardName;
+            if (name == null) return;
+            var grid = CurrentDashboard;
+            if (grid == null) return;
+            SaveDashboard(name, grid);
+        }
+
+        private void ShutdownDashboard(string name, DynamicFormDesignGrid grid)
+        {
+            SaveDashboard(name, grid);
+            foreach (var panel in _panels[grid])
+            {
+                panel.Shutdown();
+            }
+            _panels[grid].Clear();
+        }
+
+        private void ShutdownDashboard()
+        {
+            var name = CurrentDashboardName;
+            if (name == null) return;
+            var grid = CurrentDashboard;
+            if (grid == null) return;
+            ShutdownDashboard(name, grid);
+        }
+
+        private void RefreshDashboard(string name)
+        {
+            if (!_dashboards.ContainsKey(name))
+                return;
+            var grid = _dashboards[name];
+            if (_panels.ContainsKey(grid))
+            {
+                foreach (var panel in _panels[grid])
+                    panel.Refresh();
             }
-            _panels.Clear();
         }
 
         private FrameworkElement CreateElement<TWidget, TGroup, TProperties>(DynamicFormDesignGrid grid, DFLayoutElement<TProperties> element)
@@ -296,22 +480,19 @@ namespace PRSDesktop
             var widgetType = GetVisibleDashboardElements().Where(x => x.DashboardElement == e.Element.GetType()).FirstOrDefault();
             if(widgetType == null)
             {
-                var border = new Border();
-                border.BorderBrush = new SolidColorBrush(Colors.Gray);
-                border.BorderThickness = new Thickness(0.0);
-                border.Margin = new Thickness(0.0);
-                border.Background = ThemeManager.WorkspaceBackgroundBrush; //new SolidColorBrush(Colors.Silver);
+                var border = new Border
+                {
+                    BorderBrush = new SolidColorBrush(Colors.Gray),
+                    BorderThickness = new Thickness(0.0),
+                    Margin = new Thickness(0.0),
+                    Background = ThemeManager.WorkspaceBackgroundBrush //new SolidColorBrush(Colors.Silver);
+                };
                 return border;
             }
             var method = typeof(UtilityDashboard)
-                .GetMethod(nameof(CreateElement), BindingFlags.Instance | BindingFlags.NonPublic)
+                .GetMethod(nameof(CreateElement), BindingFlags.Instance | BindingFlags.NonPublic)!
                 .MakeGenericMethod(widgetType.Widget, widgetType.Group, widgetType.Properties);
-            return method.Invoke(this, new object[] { sender, e.Element }) as FrameworkElement;
-        }
-        
-        private bool TabNameExists(string name)
-        {
-            return _settings.Dashboards.ContainsKey(name);
+            return (method.Invoke(this, new object[] { sender, e.Element }) as FrameworkElement)!;
         }
         
         private static string GetCaption(Type groupType)
@@ -352,6 +533,7 @@ namespace PRSDesktop
             }
             return _dashboardElements;
         }
+
         private static IEnumerable<WidgetDashboardElement> GetVisibleDashboardElements()
         {
             return GetDashboardElements().Where(x =>
@@ -382,12 +564,14 @@ namespace PRSDesktop
             grid.OnAfterRender += OnAfterRender;
 
             grid.Mode = FormMode.Preview;
-            
-            var border = new Border();
-            border.BorderBrush = new SolidColorBrush(Colors.Silver);
-            border.BorderThickness = new Thickness(0.75);
-            border.Child = grid; // scroll;
-            
+
+            var border = new Border
+            {
+                BorderBrush = new SolidColorBrush(Colors.Silver),
+                BorderThickness = new Thickness(0.75),
+                Child = grid // scroll;
+            };
+
             _dashboards[name] = grid;
             _panels[grid] = new List<ICorePanel>();
 
@@ -430,41 +614,12 @@ namespace PRSDesktop
             return form;
         }
         
-
         private void OnAfterDesign(object sender)
         {
             SaveCurrentDashboard();
             RefreshDashboard(CurrentDashboardName);
         }
 
-        private void DashboardsTab_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
-        {
-            if (e.OriginalSource != DashboardsTab)
-                return;
-
-            if (e.AddedItems.Count == 0)
-                return;
-            
-            ShutdownDashboard();
-            var tab = e.AddedItems[0] as DynamicTabItem;
-            if (tab != null)
-            {
-                var name = (tab.Header as string)!;
-                if (tab!.Content == null)
-                    tab.Content = CreateDashboard(name, _settings.Dashboards[name]);
-
-                RefreshDashboard(name);
-                if (IsReady)
-                {
-                    _settings.Selected = tab.TabIndex;
-                    DashboardsTab.ChangedCommand.Execute(null);
-                }
-            }
-        }
-
-        private void DashboardsTab_OnOnTabsChanged(object sender, EventArgs args)
-        {
-            new UserConfiguration<UtilityDashboardSettings>().Save(_settings);
-        }
+        #endregion
     }
 }

+ 3 - 8
prs.desktop/Panels/DailyReports/DailyReportFavouriteGrid.cs

@@ -20,17 +20,12 @@ namespace PRSDesktop
             MasterColumns.Add(new DynamicGridColumn { ColumnName = "JobNumber", Width = 100, Alignment = Alignment.MiddleCenter });
             MasterColumns.Add(new DynamicGridColumn { ColumnName = "ITPCode", Width = 100, Caption = "ITP", Alignment = Alignment.MiddleCenter });
             MasterColumns.Add(new DynamicGridColumn { ColumnName = "ActivityName", Width = 0, Caption = "Activity" });
-            ActionColumns.Add(new DynamicActionColumn(DeleteImage, DeleteClick) { Position = DynamicActionColumnPosition.Start });
+            ActionColumns.Add(new DynamicActionColumn(PRSDesktop.Resources.delete.AsBitmapImage(), DeleteClick) { Position = DynamicActionColumnPosition.Start });
         }
 
         public List<AssignmentFavourite> Items { get; set; }
 
-        private BitmapImage DeleteImage(CoreRow arg)
-        {
-            return PRSDesktop.Resources.delete.AsBitmapImage();
-        }
-
-        private bool DeleteClick(CoreRow arg)
+        private bool DeleteClick(CoreRow? arg)
         {
             if (arg == null)
                 return false;
@@ -54,7 +49,7 @@ namespace PRSDesktop
         }
 
         protected override void Reload(Filters<AssignmentFavourite> criteria, Columns<AssignmentFavourite> columns,
-            ref SortOrder<AssignmentFavourite> sort, Action<CoreTable, Exception> action)
+            ref SortOrder<AssignmentFavourite>? sort, Action<CoreTable, Exception?> action)
         {
             var result = new CoreTable();
             result.LoadColumns(typeof(AssignmentFavourite));

二進制
prs.desktop/Resources/edit.png