UtilityDashboard.xaml.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Media;
  9. using Comal.Classes;
  10. using InABox.Configuration;
  11. using InABox.Core;
  12. using InABox.DynamicGrid;
  13. using InABox.WPF;
  14. using InABox.Wpf;
  15. using InABox.WPF.Themes;
  16. using Microsoft.Xaml.Behaviors.Core;
  17. using Syncfusion.Windows.Tools.Controls;
  18. using PRSDesktop.Dashboards;
  19. using InABox.Wpf.Dashboard.Editor;
  20. using InABox.Wpf.Dashboard;
  21. namespace PRSDesktop
  22. {
  23. public class DashboardFavourite : BaseObject
  24. {
  25. [TextBoxEditor]
  26. [EditorSequence(1)]
  27. public string Name { get; set; }
  28. [CheckBoxEditor]
  29. [EditorSequence(2)]
  30. public bool IsGlobal { get; set; }
  31. [NullEditor]
  32. public string Layout { get; set; }
  33. }
  34. public class CustomDashboard : BaseObject
  35. {
  36. public string Name { get; set; }
  37. [NullEditor]
  38. public string Layout { get; set; }
  39. }
  40. public class GlobalUtilityDashboardSettings : IGlobalConfigurationSettings
  41. {
  42. public List<DashboardFavourite> Favourites { get; set; }
  43. public List<CustomDashboard> CustomDashboards { get; set; }
  44. public GlobalUtilityDashboardSettings()
  45. {
  46. Favourites = new();
  47. CustomDashboards = new();
  48. }
  49. }
  50. public class UtilityDashboardSettings : IUserConfigurationSettings
  51. {
  52. public UtilityDashboardSettings()
  53. {
  54. Dashboards = new Dictionary<string, string>();
  55. Favourites = new();
  56. }
  57. public Dictionary<string, string> Dashboards { get; set; }
  58. public List<DashboardFavourite> Favourites { get; set; }
  59. public int Selected { get; set; }
  60. public bool AutoHide { get; set; }
  61. }
  62. /// <summary>
  63. /// Interaction logic for UtilityDashboard.xaml
  64. /// </summary>
  65. public partial class UtilityDashboard : UserControl, IBasePanel
  66. {
  67. private readonly Dictionary<string, DynamicFormDesignGrid> _dashboards = new();
  68. private readonly Dictionary<DynamicFormDesignGrid, List<ICorePanel>> _panels = new();
  69. private class WidgetDashboardElement
  70. {
  71. public Type DashboardElement { get; set; }
  72. public Type Widget { get; set; }
  73. public Type Group { get; set; }
  74. public Type Properties { get; set; }
  75. public string GroupCaption { get; set; }
  76. public string WidgetCaption { get; set; }
  77. public Type[] SecurityTokens { get; set; }
  78. public WidgetDashboardElement(Type dashboardElement, Type widget, Type group, Type properties, Type[] securityTokens)
  79. {
  80. DashboardElement = dashboardElement;
  81. Widget = widget;
  82. Group = group;
  83. Properties = properties;
  84. SecurityTokens = securityTokens;
  85. GroupCaption = UtilityDashboard.GetCaption(group);
  86. WidgetCaption = UtilityDashboard.GetCaption(widget);
  87. }
  88. }
  89. private static List<WidgetDashboardElement>? _dashboardElements;
  90. private string? CurrentDashboardName => DashboardsTab.SelectedTab?.Header?.ToString();
  91. private DynamicFormDesignGrid? CurrentDashboard => CurrentDashboardName != null ? _dashboards.GetValueOrDefault(CurrentDashboardName) : null;
  92. private UtilityDashboardSettings _settings = new();
  93. public UtilityDashboard()
  94. {
  95. InitializeComponent();
  96. }
  97. public void CreateToolbarButtons(IPanelHost host)
  98. {
  99. }
  100. private void SaveSettings()
  101. {
  102. new UserConfiguration<UtilityDashboardSettings>().Save(_settings);
  103. }
  104. #region Panel Functions & Properties
  105. public event DataModelUpdateEvent? OnUpdateDataModel;
  106. public bool IsReady { get; set; }
  107. public string SectionName => "Utility Dashboard";
  108. public DataModel DataModel(Selection selection)
  109. {
  110. return new EmptyDataModel();
  111. }
  112. public void Setup()
  113. {
  114. _settings = new UserConfiguration<UtilityDashboardSettings>().Load();
  115. if (_settings.Dashboards.Count == 0) _settings.Dashboards["New Dashboard"] = CreateForm("").SaveLayout();
  116. foreach (var key in _settings.Dashboards.Keys)
  117. CreateTab(key);
  118. if (_settings.Selected >= -1 && _settings.Selected < DashboardsTab.Items.Count)
  119. DashboardsTab.SelectedIndex = _settings.Selected;
  120. //DashboardsTab.FullScreenMode = _settings.AutoHide ? FullScreenMode.ControlMode : FullScreenMode.None;
  121. }
  122. public Dictionary<string, object[]> Selected()
  123. {
  124. return new Dictionary<string, object[]>();
  125. }
  126. public void Heartbeat(TimeSpan time)
  127. {
  128. }
  129. public void Refresh()
  130. {
  131. if(CurrentDashboardName is string name)
  132. {
  133. RefreshDashboard(name);
  134. }
  135. }
  136. public void Shutdown(CancelEventArgs? cancel)
  137. {
  138. foreach (var (name, grid) in _dashboards)
  139. {
  140. ShutdownDashboard(name, grid);
  141. }
  142. _panels.Clear();
  143. }
  144. #endregion
  145. #region Favourites
  146. private IEnumerable<DashboardFavourite> GetFavourites()
  147. {
  148. foreach(var favourite in _settings.Favourites)
  149. {
  150. yield return favourite;
  151. }
  152. var global = new GlobalConfiguration<GlobalUtilityDashboardSettings>().Load(false).Favourites;
  153. foreach (var favourite in global)
  154. {
  155. yield return favourite;
  156. }
  157. }
  158. private void ManageFavourites_Click()
  159. {
  160. var favourites = GetFavourites().ToList();
  161. var grid = new DynamicItemsListGrid<DashboardFavourite>() { Items = favourites };
  162. grid.Reconfigure(options =>
  163. {
  164. options.DeleteRows = true;
  165. options.EditRows = true;
  166. options.MultiSelect = true;
  167. });
  168. grid.OnCustomiseEditor += FavouritesGrid_OnCustomiseEditor;
  169. DynamicGridUtils.CreateGridWindow("Manage Favourites", grid).ShowDialog();
  170. _settings.Favourites = favourites.Where(x => !x.IsGlobal).ToList();
  171. SaveSettings();
  172. if (Security.IsAllowed<CanSetGlobalDashboardFavourites>())
  173. {
  174. var config = new GlobalConfiguration<GlobalUtilityDashboardSettings>();
  175. var global = config.Load();
  176. global.Favourites = favourites.Where(x => x.IsGlobal).ToList();
  177. config.Save(global);
  178. }
  179. }
  180. private void FavouritesGrid_OnCustomiseEditor(IDynamicEditorForm sender, DashboardFavourite[]? items, DynamicGridColumn column, BaseEditor editor)
  181. {
  182. if(column.ColumnName == "IsGlobal")
  183. {
  184. editor.Editable = Security.IsAllowed<CanSetGlobalDashboardFavourites>() ? Editable.Enabled : Editable.Disabled;
  185. }
  186. }
  187. private void SaveAsFavourite_Click(string dashboardName)
  188. {
  189. _settings.Favourites.Add(new DashboardFavourite
  190. {
  191. Name = dashboardName,
  192. Layout = _dashboards.GetValueOrDefault(dashboardName)?.Form.SaveLayout() ?? _settings.Dashboards[dashboardName]
  193. });
  194. SaveSettings();
  195. }
  196. private void LoadFavourite_Click(DashboardFavourite favourite)
  197. {
  198. var name = CreateNewTabName(favourite.Name);
  199. _settings.Dashboards[name] = favourite.Layout;
  200. SaveSettings();
  201. var tab = CreateTab(name);
  202. DashboardsTab.SelectedItem = tab;
  203. }
  204. #endregion
  205. #region Tabs
  206. private void Tab_OnContextMenuOpening(object sender, DynamicTabItemContextMenuEventArgs args)
  207. {
  208. var name = (DashboardsTab.SelectedItem as DynamicTabItem)?.Header?.ToString();
  209. if (string.IsNullOrEmpty(name))
  210. return;
  211. DynamicFormDesignGrid grid = _dashboards[name];
  212. var menu = args.Menu;
  213. menu.AddSeparatorIfNeeded();
  214. var isDesigning = grid.Mode != FormMode.Preview;
  215. menu.Items.Add(new MenuItem()
  216. {
  217. Header = isDesigning ? "Close Design Mode" : "Design Mode",
  218. Command = new ActionCommand(() =>
  219. {
  220. if (grid.Mode == FormMode.Designing)
  221. {
  222. grid.Mode = FormMode.Preview;
  223. SaveCurrentDashboard();
  224. DashboardsTab.ChangedCommand.Execute(null);
  225. }
  226. else
  227. {
  228. ShutdownDashboard();
  229. grid.Mode = FormMode.Designing;
  230. }
  231. }),
  232. Icon = new Image() { Source = (isDesigning ? InABox.Wpf.Resources.delete : PRSDesktop.Resources.pencil).AsBitmapImage(24, 24) }
  233. });
  234. var index = 0;
  235. var favourites = GetFavourites().ToList();
  236. if (favourites.Any())
  237. {
  238. foreach (var favourite in favourites)
  239. {
  240. menu.AddItem(favourite.Name, null, favourite, LoadFavourite_Click, index: index++);
  241. }
  242. menu.AddSeparatorIfNeeded(index: index++);
  243. menu.AddItem("Manage Favourites", null, ManageFavourites_Click, index: index++);
  244. }
  245. menu.AddItem("Save as Favourite", null, name, SaveAsFavourite_Click, index: index++);
  246. menu.AddSeparator(index: index++);
  247. }
  248. private void Tab_OnCloseTab(object sender, DynamicTabControlEventArgs args)
  249. {
  250. var name = args.TabItem.Header?.ToString();
  251. if (name is null)
  252. return;
  253. _dashboards.Remove(name);
  254. _settings.Dashboards.Remove(name);
  255. if (!_settings.Dashboards.Any())
  256. {
  257. var tab = new DynamicTabItem();
  258. InitializeNewDashboardTab(tab);
  259. DashboardsTab.Items.Add(tab);
  260. }
  261. else
  262. {
  263. DashboardsTab.ChangedCommand.Execute(null);
  264. }
  265. }
  266. private void Tab_OnTabRenamed(object sender, DynamicTabItemRenamedEventArgs args)
  267. {
  268. var oldSettings = _settings.Dashboards[args.OldName];
  269. _settings.Dashboards.Remove(args.OldName);
  270. args.NewName = CreateNewTabName(args.NewName);
  271. if (_dashboards.TryGetValue(args.OldName, out var dashboard))
  272. {
  273. _dashboards.Remove(args.OldName);
  274. _dashboards[args.NewName] = dashboard;
  275. _settings.Dashboards[args.NewName] = dashboard.Form.SaveLayout();
  276. }
  277. else
  278. {
  279. _settings.Dashboards[args.NewName] = oldSettings;
  280. }
  281. }
  282. /// <summary>
  283. /// Setup events on a new tab.
  284. /// </summary>
  285. /// <param name="tab"></param>
  286. private void InitializeTab(DynamicTabItem tab)
  287. {
  288. tab.CanClose = true;
  289. tab.OnCloseTab += Tab_OnCloseTab;
  290. tab.CanRename = true;
  291. tab.OnTabRenamed += Tab_OnTabRenamed;
  292. tab.OnContextMenuOpening += Tab_OnContextMenuOpening;
  293. }
  294. private string CreateNewTabName(string name)
  295. {
  296. var newName = name;
  297. int i = 1;
  298. while (TabNameExists(newName))
  299. {
  300. newName = $"{name} ({i})";
  301. ++i;
  302. }
  303. return newName;
  304. }
  305. private bool TabNameExists(string name)
  306. {
  307. return _settings.Dashboards.ContainsKey(name);
  308. }
  309. /// <summary>
  310. /// Creates a new tab with a given header and adds it to <see cref="DashboardsTab"/>.
  311. /// </summary>
  312. /// <param name="header"></param>
  313. /// <returns></returns>
  314. private DynamicTabItem CreateTab(string header)
  315. {
  316. var tab = new DynamicTabItem() { Header = header };
  317. InitializeTab(tab);
  318. DashboardsTab.Items.Add(tab);
  319. return tab;
  320. }
  321. /// <summary>
  322. /// Creates a new dashboard for a tab, and then initializes the tab.
  323. /// </summary>
  324. /// <param name="tab"></param>
  325. private void InitializeNewDashboardTab(DynamicTabItem tab)
  326. {
  327. var name = CreateNewTabName("New Dashboard");
  328. _settings.Dashboards[name] = CreateForm("").SaveLayout();
  329. DashboardsTab.ChangedCommand.Execute(null);
  330. SaveSettings();
  331. tab.Header = name;
  332. InitializeTab(tab);
  333. }
  334. private void DashboardsTab_OnOnCreateTab(object sender, DynamicTabControlEventArgs args)
  335. {
  336. InitializeNewDashboardTab(args.TabItem);
  337. }
  338. private void DashboardsTab_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  339. {
  340. if (e.OriginalSource != DashboardsTab)
  341. return;
  342. if (e.AddedItems.Count == 0)
  343. return;
  344. ShutdownDashboard();
  345. if (e.AddedItems[0] is DynamicTabItem tab)
  346. {
  347. var name = (tab.Header as string)!;
  348. if (tab!.Content == null)
  349. tab.Content = CreateDashboard(name, _settings.Dashboards[name]);
  350. else
  351. {
  352. RefreshDashboard(name);
  353. }
  354. if (IsReady)
  355. {
  356. _settings.Selected = tab.TabIndex;
  357. DashboardsTab.ChangedCommand.Execute(null);
  358. }
  359. }
  360. }
  361. private void DashboardsTab_OnOnTabsChanged(object sender, EventArgs args)
  362. {
  363. SaveSettings();
  364. }
  365. #endregion
  366. #region Dashboard & Design
  367. private void SaveDashboard(string name, DynamicFormDesignGrid grid)
  368. {
  369. _settings.Dashboards[name] = grid.Form.SaveLayout();
  370. if (IsReady)
  371. SaveSettings();
  372. }
  373. private void SaveCurrentDashboard()
  374. {
  375. var name = CurrentDashboardName;
  376. if (name == null) return;
  377. var grid = CurrentDashboard;
  378. if (grid == null) return;
  379. SaveDashboard(name, grid);
  380. }
  381. private void ShutdownDashboard(string name, DynamicFormDesignGrid grid)
  382. {
  383. SaveDashboard(name, grid);
  384. var cancel = new CancelEventArgs();
  385. foreach (var panel in _panels[grid])
  386. {
  387. panel.Shutdown(cancel);
  388. if (cancel.Cancel)
  389. {
  390. return;
  391. }
  392. }
  393. _panels[grid].Clear();
  394. }
  395. private void ShutdownDashboard()
  396. {
  397. var name = CurrentDashboardName;
  398. if (name == null) return;
  399. var grid = CurrentDashboard;
  400. if (grid == null) return;
  401. ShutdownDashboard(name, grid);
  402. }
  403. private void RefreshDashboard(string name)
  404. {
  405. if (!_dashboards.ContainsKey(name))
  406. return;
  407. var grid = _dashboards[name];
  408. if (_panels.ContainsKey(grid))
  409. {
  410. foreach (var panel in _panels[grid])
  411. panel.Refresh();
  412. }
  413. }
  414. private FrameworkElement CreateElement<TWidget, TProperties>(DynamicFormDesignGrid grid, DFLayoutElement<TProperties> element)
  415. where TWidget : FrameworkElement, IDashboardWidget<TProperties>, new()
  416. where TProperties : IConfigurationSettings, IDashboardProperties, new()
  417. {
  418. if (!_panels.ContainsKey(grid))
  419. _panels[grid] = new List<ICorePanel>();
  420. string dashboardName;
  421. if(element is CustomDashboardElement custom)
  422. {
  423. dashboardName = custom.Properties.DashboardName;
  424. }
  425. else
  426. {
  427. dashboardName = GetDashboardElements()
  428. .Where(x => x.DashboardElement == element.GetType())
  429. .FirstOrDefault()?.WidgetCaption ?? "Unknown Dashboard";
  430. }
  431. var container = DashboardContainer.Create<TWidget, TProperties>(element, dashboardName);
  432. _panels[grid].Add(container.Panel);
  433. return container;
  434. }
  435. private FrameworkElement OnCreateElement(object sender, DynamicFormCreateElementArgs e)
  436. {
  437. var method = typeof(UtilityDashboard).GetMethod(nameof(CreateElement), BindingFlags.Instance | BindingFlags.NonPublic)!;
  438. if(e.Element is CustomDashboardElement custom)
  439. {
  440. method = method.MakeGenericMethod(typeof(CustomDashboardWidget), typeof(CustomDashboardProperties));
  441. }
  442. else
  443. {
  444. var widgetType = GetVisibleDashboardElements().Where(x => x.DashboardElement == e.Element.GetType()).FirstOrDefault();
  445. if(widgetType == null)
  446. {
  447. var border = new Border
  448. {
  449. BorderBrush = new SolidColorBrush(Colors.Gray),
  450. BorderThickness = new Thickness(0.0),
  451. Margin = new Thickness(0.0),
  452. Background = ThemeManager.WorkspaceBackgroundBrush //new SolidColorBrush(Colors.Silver);
  453. };
  454. return border;
  455. }
  456. method = method.MakeGenericMethod(widgetType.Widget, widgetType.Properties);
  457. }
  458. return (method.Invoke(this, new object[] { sender, e.Element }) as FrameworkElement)!;
  459. }
  460. private static string GetCaption(Type groupType)
  461. {
  462. var caption = groupType.GetCustomAttribute<Caption>();
  463. if(caption != null)
  464. {
  465. return caption.Text;
  466. }
  467. return CoreUtils.Neatify(groupType.Name);
  468. }
  469. private static List<WidgetDashboardElement> GetDashboardElements()
  470. {
  471. if (_dashboardElements == null)
  472. {
  473. _dashboardElements = new();
  474. var types = CoreUtils.Entities.Where(x => x.IsClass && !x.IsGenericType && x.GetInterfaces().Contains(typeof(IDashboardElement)));
  475. foreach (var type in types)
  476. {
  477. var dashboardElementDef = type.GetSuperclassDefinition(typeof(DashboardElement<,,>));
  478. if (dashboardElementDef != null)
  479. {
  480. var dashboard = dashboardElementDef.GenericTypeArguments[0];
  481. var group = dashboardElementDef.GenericTypeArguments[1];
  482. var properties = dashboardElementDef.GenericTypeArguments[2];
  483. var requires = dashboard.GetInterfaces(typeof(IRequiresSecurity<>)).Select(x => x.GenericTypeArguments[0]);
  484. _dashboardElements.Add(new(type, dashboard, group, properties, requires.ToArray()));
  485. }
  486. }
  487. }
  488. return _dashboardElements;
  489. }
  490. private static IEnumerable<WidgetDashboardElement> GetVisibleDashboardElements()
  491. {
  492. return GetDashboardElements().Where(x =>
  493. {
  494. foreach (var require in x.SecurityTokens)
  495. {
  496. if (!Security.IsAllowed(require))
  497. return false;
  498. }
  499. return true;
  500. });
  501. }
  502. private Border CreateDashboard(string name, string layout)
  503. {
  504. var form = CreateForm(layout);
  505. var grid = new DynamicFormDesignGrid();
  506. foreach(var widget in GetVisibleDashboardElements())
  507. {
  508. grid.AddElement(widget.DashboardElement, widget.WidgetCaption, widget.GroupCaption, true);
  509. }
  510. var customDashboards = new GlobalConfiguration<GlobalUtilityDashboardSettings>().Load().CustomDashboards;
  511. grid.AddElement(typeof(CustomDashboardElement), "Custom", "Custom", visible: false);
  512. foreach(var customDashboard in customDashboards)
  513. {
  514. grid.AddElementAction(customDashboard.Name, null, "Custom", customDashboard, AddCustom_Click);
  515. }
  516. grid.AddElementAction<object?>("Create New", InABox.Wpf.Resources.add, "Custom", null, CreateNewCustom_Click);
  517. grid.ShowBorders = false;
  518. grid.OnCreateElement += OnCreateElement;
  519. grid.OnAfterDesign += OnAfterDesign;
  520. grid.OnAfterRender += OnAfterRender;
  521. grid.Mode = FormMode.Preview;
  522. var border = new Border
  523. {
  524. BorderBrush = new SolidColorBrush(Colors.Silver),
  525. BorderThickness = new Thickness(0.75),
  526. Child = grid // scroll;
  527. };
  528. _dashboards[name] = grid;
  529. _panels[grid] = new List<ICorePanel>();
  530. grid.Form = form;
  531. grid.Initialize();
  532. return border;
  533. }
  534. private DFLayoutElement? AddCustom_Click(CustomDashboard dashboard)
  535. {
  536. var element = new CustomDashboardElement();
  537. element.Properties = new CustomDashboardProperties
  538. {
  539. DashboardName = dashboard.Name
  540. };
  541. return element;
  542. }
  543. private DFLayoutElement? CreateNewCustom_Click(object? tag)
  544. {
  545. var grid = new Grid();
  546. grid.AddRow(GridUnitType.Auto);
  547. grid.AddRow(GridUnitType.Auto);
  548. grid.AddRow(GridUnitType.Star);
  549. grid.AddColumn(GridUnitType.Auto);
  550. grid.AddColumn(GridUnitType.Star);
  551. grid.AddChild(new Label
  552. {
  553. Content = "Dashboard Name:",
  554. VerticalAlignment = VerticalAlignment.Center
  555. }, 0, 0);
  556. var textBox = new TextBox
  557. {
  558. Background = Colors.LightYellow.ToBrush(),
  559. Padding = new Thickness(5),
  560. VerticalContentAlignment = VerticalAlignment.Center
  561. };
  562. grid.AddChild(textBox, 0, 1);
  563. grid.AddChild(new Separator
  564. {
  565. Margin = new(5)
  566. }, 1, 0, colSpan: 2);
  567. var dashboard = new DynamicDashboard();
  568. var editor = new DynamicDashboardEditor(dashboard);
  569. grid.AddChild(editor, 2, 0, colSpan: 2);
  570. var dlg = new DynamicContentDialog(grid)
  571. {
  572. Title = "Create new dashboard",
  573. SizeToContent = SizeToContent.Height
  574. };
  575. textBox.TextChanged += (o, e) =>
  576. {
  577. dlg.CanSave = !textBox.Text.IsNullOrWhiteSpace();
  578. };
  579. if(dlg.ShowDialog() == true)
  580. {
  581. var config = new GlobalConfiguration<GlobalUtilityDashboardSettings>();
  582. var settings = config.Load();
  583. settings.CustomDashboards.Add(new CustomDashboard
  584. {
  585. Layout = DynamicDashboardUtils.Serialize(editor.GetDashboard()),
  586. Name = textBox.Text
  587. });
  588. config.Save(settings);
  589. var element = new CustomDashboardElement();
  590. element.Properties = new CustomDashboardProperties
  591. {
  592. DashboardName = textBox.Text
  593. };
  594. return element;
  595. }
  596. else
  597. {
  598. return null;
  599. }
  600. }
  601. private void OnAfterRender(DynamicFormDesignGrid sender)
  602. {
  603. if (!sender.IsDesigning)
  604. {
  605. if (_panels.TryGetValue(sender, out var panels))
  606. {
  607. foreach (var panel in panels)
  608. panel.Refresh();
  609. }
  610. }
  611. }
  612. private static DFLayout CreateForm(string layout)
  613. {
  614. var form = new DFLayout();
  615. if (string.IsNullOrWhiteSpace(layout))
  616. {
  617. form.ColumnWidths.Add("*");
  618. form.ColumnWidths.Add("*");
  619. form.ColumnWidths.Add("*");
  620. form.RowHeights.Add("*");
  621. form.RowHeights.Add("*");
  622. form.RowHeights.Add("*");
  623. }
  624. else
  625. {
  626. form.LoadLayout(layout);
  627. }
  628. return form;
  629. }
  630. private void OnAfterDesign(object sender)
  631. {
  632. SaveCurrentDashboard();
  633. if(CurrentDashboardName is string name) // Null-check
  634. {
  635. RefreshDashboard(name);
  636. }
  637. }
  638. #endregion
  639. }
  640. }