| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847 | 
							- using Comal.Classes;
 
- using InABox.Clients;
 
- using InABox.Core;
 
- using InABox.DynamicGrid;
 
- using InABox.Reports;
 
- using InABox.Core.Reports;
 
- using InABox.Scripting;
 
- using InABox.WPF;
 
- using InABox.Wpf;
 
- using PRSDesktop.Configuration;
 
- using PRSDesktop.Forms;
 
- using PRSDesktop.WidgetGroups;
 
- using Syncfusion.UI.Xaml.Grid;
 
- using Syncfusion.UI.Xaml.Grid.Converter;
 
- using Syncfusion.XlsIO;
 
- using System;
 
- using System.Collections;
 
- using System.Collections.Generic;
 
- using System.Data;
 
- using System.Diagnostics;
 
- using System.Diagnostics.CodeAnalysis;
 
- using System.Linq;
 
- using System.Linq.Expressions;
 
- using System.Reflection;
 
- using System.Text;
 
- using System.Text.RegularExpressions;
 
- using System.Threading;
 
- using System.Threading.Tasks;
 
- using System.Windows;
 
- using System.Windows.Controls;
 
- using System.Windows.Data;
 
- using System.Windows.Documents;
 
- using System.Windows.Input;
 
- using System.Windows.Media;
 
- using InABox.Configuration;
 
- using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs;
 
- using InABox.Wpf.Reports;
 
- using System.ComponentModel;
 
- using Syncfusion.Windows.Shared;
 
- using System.Globalization;
 
- using System.Windows.Media.Imaging;
 
- using System.Drawing;
 
- using Image = System.Windows.Controls.Image;
 
- using Microsoft.Win32;
 
- using Syncfusion.CompoundFile.DocIO.Net;
 
- using System.IO;
 
- using Columns = InABox.Core.Columns;
 
- using PanelAction = InABox.Wpf.PanelAction;
 
- namespace PRSDesktop;
 
- public enum DateFilterType
 
- {
 
-     Today,
 
-     Yesterday,
 
-     Week,
 
-     SevenDays,
 
-     Month,
 
-     ThirtyDays,
 
-     Year,
 
-     TwelveMonths,
 
-     Custom
 
- }
 
- public class DFFilter : BaseObject
 
- {
 
-     [EditorSequence(1)]
 
-     [TextBoxEditor]
 
-     public string Name { get; set; } = "";
 
-     [EditorSequence(2)]
 
-     [FilterEditor]
 
-     public string Filter { get; set; } = "";
 
- }
 
- public class DigitalFormsDashboardProperties : IUserConfigurationSettings, IDashboardProperties
 
- {
 
-     public bool ShowJobFilter { get; set; } = false;
 
-     public bool ShowDateFilter { get; set; } = true;
 
-     public bool ShowIncompleteForms { get; set; } = false;
 
-     public bool UseIconsForFormTypes { get; set; } = false;
 
-     public string? Category { get; set; }
 
-     public Guid SelectedForm { get; set; }
 
-     public Guid JobID { get; set; }
 
-     public DateFilterType DateFilterType { get; set; } = DateFilterType.Today;
 
-     public DateTime FromDate { get; set; }
 
-     public DateTime ToDate { get; set; }
 
-     public Dictionary<string, List<DFFilter>> Filters { get; set; } = new();
 
- }
 
- public class DigitalFormsDashboardElement : DashboardElement<DigitalFormsDashboard, Common, DigitalFormsDashboardProperties> { }
 
- /// <summary>
 
- /// Interaction logic for DigitalFormsDashboard.xaml
 
- /// </summary>
 
- public partial class DigitalFormsDashboard : UserControl,
 
-     IDashboardWidget<Common, DigitalFormsDashboardProperties>,
 
-     IBasePanel,
 
-     IRequiresSecurity<CanViewDigitalFormsDashbaord>,
 
-     IHeaderDashboard, IActionsDashboard
 
- {
 
-     public DigitalFormsDashboardProperties Properties { get; set; }
 
-     public event LoadSettings<DigitalFormsDashboardProperties>? LoadSettings;
 
-     public event SaveSettings<DigitalFormsDashboardProperties>? SaveSettings;
 
-     private List<DigitalForm> DigitalForms;
 
-     private List<Job> Jobs;
 
-     private List<Tuple<string, Type?, string>> Categories;
 
-     public DashboardHeader Header { get; set; } = new();
 
-     private bool IsQAForm = false;
 
-     private List<QAQuestion> Questions = new();
 
-     private bool IsSetup = false;
 
-     public DigitalFormsDashboard()
 
-     {
 
-         InitializeComponent();
 
-         Grid.OnGetRowStyle = Grid_OnGetRowStyle;
 
-     }
 
-     public void Setup()
 
-     {
 
-         var results = Client.QueryMultiple(
 
-             new KeyedQueryDef<DigitalForm>(new Filter<DigitalForm>(x => x.Active).IsEqualTo(true)),
 
-             new KeyedQueryDef<Job>(
 
-                 LookupFactory.DefineFilter<Job>(),
 
-                 Columns.None<Job>().Add(x => x.ID)
 
-                     .Add(x => x.JobNumber)
 
-                     .Add(x => x.Name)));
 
-         DigitalForms = results.Get<DigitalForm>().ToObjects<DigitalForm>().ToList();
 
-         var categories = new DigitalFormCategoryLookups(null);
 
-         categories.OnAfterGenerateLookups += (sender, entries) => { entries.Insert(0, new LookupEntry("", "Select Category")); };
 
-         Categories = categories.AsTable("AppliesTo")
 
-             .Rows.Select(x =>
 
-             {
 
-                 var appliesTo = x.Get<string>("AppliesTo");
 
-                 if (CategoryToType(appliesTo, out var formType, out var parentType))
 
-                 {
 
-                     return new Tuple<string, Type?, string>(appliesTo, formType, x.Get<string>("Display"));
 
-                 }
 
-                 else
 
-                 {
 
-                     return new Tuple<string, Type?, string>(appliesTo, null, x.Get<string>("Display"));
 
-                 }
 
-             }).ToList();
 
-         Grid.Categories = Categories;
 
-         Jobs = results.Get<Job>().ToObjects<Job>().ToList();
 
-         Jobs.Insert(0, new Job { ID = Guid.Empty, JobNumber = "ALL", Name = "All Jobs" });
 
-         SetupHeader();
 
-         SetupFilters();
 
-         IsSetup = true;
 
-     }
 
-     #region Header
 
-     private StackPanel CategoryButtonPanel;
 
-     private Dictionary<Type, Button> CategoryButtons = new();
 
-     private ComboBox CategoryBox;
 
-     private ComboBox FormBox;
 
-     private ComboBox JobBox;
 
-     private ComboBox IncompleteFormsBox;
 
-     private ComboBox DateTypeBox;
 
-     private Label FromLabel;
 
-     private DatePicker FromPicker;
 
-     private Label ToLabel;
 
-     private DatePicker ToPicker;
 
-     private Button Print;
 
-     private Button FilterBtn;
 
-     private static Dictionary<DateFilterType, string> FilterTypes = new()
 
-     {
 
-         { DateFilterType.Today,         "Today" },
 
-         { DateFilterType.Yesterday,     "Yesterday" },
 
-         { DateFilterType.Week,          "Week to Date" },
 
-         { DateFilterType.SevenDays,     "Last 7 Days" },
 
-         { DateFilterType.Month,         "Month to Date" },
 
-         { DateFilterType.ThirtyDays,    "Last 30 Days" },
 
-         { DateFilterType.Year,          "Year to Date" },
 
-         { DateFilterType.TwelveMonths,  "Last 12 Months" },
 
-         { DateFilterType.Custom,        "Custom" }
 
-     };
 
-     private static readonly SolidColorBrush EnabledBrush = new SolidColorBrush(Colors.LightYellow);
 
-     private static readonly SolidColorBrush DisabledBrush = new SolidColorBrush(Colors.LightGray);
 
-     private static readonly Dictionary<Type, Bitmap> CategoryImages = new()
 
-     {
 
-         { typeof(AssignmentForm), PRSDesktop.Resources.assignments },
 
-         { typeof(KanbanForm), PRSDesktop.Resources.kanban },
 
-         { typeof(JobForm), PRSDesktop.Resources.project },
 
-         { typeof(JobITPForm), PRSDesktop.Resources.checklist },
 
-         { typeof(EmployeeForm), PRSDesktop.Resources.employees },
 
-         { typeof(LeaveRequestForm), PRSDesktop.Resources.leave },
 
-         { typeof(ManufacturingPacketStage), PRSDesktop.Resources.factory },
 
-         { typeof(TimeSheetForm), PRSDesktop.Resources.time },
 
-         { typeof(PurchaseOrderItemForm), PRSDesktop.Resources.purchase },
 
-         { typeof(DeliveryForm), PRSDesktop.Resources.truck },
 
-     };
 
-     public void SetupHeader()
 
-     {
 
-         CategoryBox = new ComboBox
 
-         {
 
-             Width = 150,
 
-             VerticalContentAlignment = VerticalAlignment.Center,
 
-             Margin = new Thickness(0, 0, 5, 0)
 
-         };
 
-         CategoryBox.ItemsSource = Categories;
 
-         CategoryBox.SelectedValuePath = "Item1";
 
-         CategoryBox.DisplayMemberPath = "Item3";
 
-         CategoryBox.SelectedValue = Properties.Category;
 
-         CategoryBox.SelectionChanged += Category_SelectionChanged;
 
-         CategoryButtonPanel = new StackPanel
 
-         {
 
-             Orientation = Orientation.Horizontal,
 
-             Margin = new Thickness(0, 0, 5, 0)
 
-         };
 
-         
 
-         CategoryButtons.Clear();
 
-         foreach(var (appliesTo, category, display) in Categories)
 
-         {
 
-             if(category is null)
 
-             {
 
-                 continue;
 
-             }
 
-             var button = new Button();
 
-             button.Tag = appliesTo;
 
-             button.Margin = new Thickness(0, 0, 2, 0);
 
-             button.BorderBrush = new SolidColorBrush(Colors.Gray);
 
-             button.BorderThickness = new Thickness(0.75);
 
-             button.Width = 25D;
 
-             button.Padding = new Thickness(2);
 
-             button.ToolTip = category.EntityName().Split('.').Last().SplitCamelCase();
 
-             if (CategoryImages.TryGetValue(category, out var image))
 
-             {
 
-                 button.Content = new Image { Source = image.AsBitmapImage() };
 
-             }
 
-             else
 
-             {
 
-                 button.Content = display;
 
-             }
 
-             button.Click += CatagoryButton_Click;
 
-             CategoryButtons.Add(category, button);
 
-             CategoryButtonPanel.Children.Add(button);
 
-         }
 
-         if (Properties.UseIconsForFormTypes)
 
-         {
 
-             CategoryButtonPanel.Visibility = Visibility.Visible;
 
-             CategoryBox.Visibility = Visibility.Collapsed;
 
-         }
 
-         else
 
-         {
 
-             CategoryButtonPanel.Visibility = Visibility.Collapsed;
 
-             CategoryBox.Visibility = Visibility.Visible;
 
-         }
 
-         FormBox = new ComboBox
 
-         {
 
-             Width = 250,
 
-             VerticalContentAlignment = VerticalAlignment.Center,
 
-             Margin = new Thickness(0, 0, 5, 0),
 
-             IsEnabled = false
 
-         };
 
-         FormBox.SelectionChanged += FormBox_SelectionChanged;
 
-         FormBox.ItemsSource = new Dictionary<DigitalForm, string> { };
 
-         JobBox = new ComboBox
 
-         {
 
-             Width = 250,
 
-             Margin = new Thickness(0, 0, 5, 0),
 
-             VerticalContentAlignment = VerticalAlignment.Center
 
-         };
 
-         JobBox.ItemsSource = Jobs.ToDictionary(x => x.ID, x => $"{x.JobNumber} : {x.Name}");
 
-         JobBox.SelectedIndex = 0;
 
-         JobBox.SelectedValuePath = "Key";
 
-         JobBox.DisplayMemberPath = "Value";
 
-         JobBox.SelectionChanged += JobBox_SelectionChanged;
 
-         DateTypeBox = new ComboBox
 
-         {
 
-             Width = 120,
 
-             VerticalContentAlignment = VerticalAlignment.Center
 
-         };
 
-         DateTypeBox.ItemsSource = FilterTypes;
 
-         DateTypeBox.SelectedValuePath = "Key";
 
-         DateTypeBox.DisplayMemberPath = "Value";
 
-         DateTypeBox.SelectedValue = Properties.DateFilterType;
 
-         DateTypeBox.SelectionChanged += DateTypeBox_SelectionChanged;
 
-         FromLabel = new Label { Content = "From", VerticalContentAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 5, 0) };
 
-         FromPicker = new DatePicker
 
-         {
 
-             Width = 100,
 
-             Background = new SolidColorBrush(Colors.LightYellow),
 
-             VerticalContentAlignment = VerticalAlignment.Center,
 
-             FirstDayOfWeek = DayOfWeek.Monday,
 
-             Margin = new Thickness(0, 0, 5, 0)
 
-         };
 
-         FromPicker.SelectedDateChanged += FromPicker_SelectedDateChanged;
 
-         ToLabel = new Label { Content = "To", VerticalContentAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 5, 0) };
 
-         ToPicker = new DatePicker
 
-         {
 
-             Width = 100,
 
-             Background = new SolidColorBrush(Colors.LightYellow),
 
-             VerticalContentAlignment = VerticalAlignment.Center,
 
-             FirstDayOfWeek = DayOfWeek.Monday,
 
-             Margin = new Thickness(0, 0, 5, 0)
 
-         };
 
-         ToPicker.SelectedDateChanged += ToPicker_SelectedDateChanged;
 
-         IncompleteFormsBox = new ComboBox
 
-         {
 
-             Width = 130,
 
-             Margin = new Thickness(0, 0, 5, 0),
 
-             VerticalContentAlignment = VerticalAlignment.Center
 
-         };
 
-         IncompleteFormsBox.ItemsSource = new List<Tuple<string, bool>>
 
-         {
 
-             new Tuple<string, bool>("Completed Forms", false),
 
-             new Tuple<string, bool>("All Forms", true)
 
-         };
 
-         IncompleteFormsBox.DisplayMemberPath = "Item1";
 
-         IncompleteFormsBox.SelectedValuePath = "Item2";
 
-         IncompleteFormsBox.SelectedValue = Properties.ShowIncompleteForms;
 
-         IncompleteFormsBox.SelectionChanged += IncompleteFormsBox_SelectionChanged;
 
-         Print = new Button
 
-         {
 
-             Width = 25,
 
-             Height = 25,
 
-             Content = new Image { Source = PRSDesktop.Resources.printer.AsBitmapImage() }
 
-         };
 
-         Print.Click += Print_Click;
 
-         FilterBtn = new Button
 
-         {
 
-             Width = 25,
 
-             Height = 25,
 
-             Content = new Image { Source = InABox.Wpf.Resources.filter.AsBitmapImage() },
 
-             Margin = new Thickness(0, 0, 5, 0)
 
-         };
 
-         FilterBtn.Click += Filter_Click;
 
-         Header.BeginUpdate()
 
-             .Clear()
 
-             .Add(CategoryBox)
 
-             .Add(CategoryButtonPanel)
 
-             .Add(FormBox)
 
-             .Add(JobBox)
 
-             .Add(DateTypeBox)
 
-             .Add(FromLabel)
 
-             .Add(FromPicker)
 
-             .Add(ToLabel)
 
-             .Add(ToPicker)
 
-             .Add(IncompleteFormsBox)
 
-             .AddRight(FilterBtn)
 
-             .AddRight(Print)
 
-             .EndUpdate();
 
-         UpdateCategory(Properties.Category);
 
-     }
 
-     private void IncompleteFormsBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
 
-     {
 
-         Properties.ShowIncompleteForms = (bool)IncompleteFormsBox.SelectedValue;
 
-         Refresh();
 
-     }
 
-     private void Filter_Click(object sender, RoutedEventArgs e)
 
-     {
 
-         var menu = new ContextMenu();
 
-         menu.AddCheckItem("Use Form Type Icons", ToggleFormTypeIcons, isChecked: Properties.UseIconsForFormTypes);
 
-         menu.AddCheckItem("Show Date Filter", ToggleDateFilter, Properties.ShowDateFilter);
 
-         menu.AddCheckItem("Show Job Filter", ToggleJobFilter, Properties.ShowJobFilter);
 
-         menu.AddSeparator();
 
-         if (ParentType is not null)
 
-         {
 
-             if (Properties.Filters.TryGetValue(ParentType.Name, out var filters))
 
-             {
 
-                 var i = 0;
 
-                 var items = new List<MenuItem>();
 
-                 foreach (var filter in filters)
 
-                 {
 
-                     items.Add(menu.AddCheckItem(
 
-                         filter.Name,
 
-                         new Tuple<int, string, List<MenuItem>>(i, filter.Filter, items),
 
-                         ExecuteFilter,
 
-                         i == CustomFilterIndex));
 
-                     ++i;
 
-                 }
 
-             }
 
-             menu.AddSeparatorIfNeeded();
 
-             menu.AddItem("Manage Filters", InABox.Wpf.Resources.filter, ManageFilters_Click);
 
-         }
 
-         menu.IsOpen = true;
 
-     }
 
-     private void ToggleFormTypeIcons(bool isChecked)
 
-     {
 
-         Properties.UseIconsForFormTypes = !Properties.UseIconsForFormTypes;
 
-         if (Properties.UseIconsForFormTypes)
 
-         {
 
-             CategoryButtonPanel.Visibility = Visibility.Visible;
 
-             CategoryBox.Visibility = Visibility.Collapsed;
 
-         }
 
-         else
 
-         {
 
-             CategoryButtonPanel.Visibility = Visibility.Collapsed;
 
-             CategoryBox.Visibility = Visibility.Visible;
 
-         }
 
-     }
 
-     private void Print_Click(object sender, RoutedEventArgs e)
 
-     {
 
-         var menu = new ContextMenu();
 
-         foreach (var report in ReportUtils.LoadReports(SectionName, DataModel(Selection.None)))
 
-         {
 
-             menu.AddItem(report.Name, PRSDesktop.Resources.printer, report, PrintReport_Click);
 
-         }
 
-         if (Security.IsAllowed<CanDesignReports>())
 
-         {
 
-             menu.AddSeparatorIfNeeded();
 
-             menu.AddItem("Manage Reports", PRSDesktop.Resources.printer, ManageReports_Click);
 
-         }
 
-         menu.IsOpen = true;
 
-     }
 
-     private void PrintReport_Click(ReportTemplate obj)
 
-     {
 
-         Selection selection;
 
-         if (obj.SelectedRecords && obj.AllRecords)
 
-             selection = RecordSelectionDialog.Execute();
 
-         else if (obj.SelectedRecords)
 
-             selection = Selection.Selected;
 
-         else if (obj.AllRecords)
 
-             selection = Selection.All;
 
-         else
 
-             selection = Selection.None;
 
-         ReportUtils.PreviewReport(obj, DataModel(selection), false, Security.IsAllowed<CanDesignReports>());
 
-     }
 
-     private void ManageReports_Click()
 
-     {
 
-         var manager = new ReportManager()
 
-         {
 
-             DataModel = DataModel(Selection.None),
 
-             Section = SectionName,
 
-             Populate = true
 
-         };
 
-         manager.ShowDialog();
 
-     }
 
-     private void Search_KeyUp(object sender, KeyEventArgs e)
 
-     {
 
-         Refresh();
 
-     }
 
-     private void JobBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
 
-     {
 
-         Properties.JobID = (Guid)JobBox.SelectedValue;
 
-         Refresh();
 
-     }
 
-     private void SetDateFilterVisibility(bool visible)
 
-     {
 
-         var visibility = visible ? Visibility.Visible : Visibility.Collapsed;
 
-         FromLabel.Visibility = visibility;
 
-         FromPicker.Visibility = visibility;
 
-         ToLabel.Visibility = visibility;
 
-         ToPicker.Visibility = visibility;
 
-         DateTypeBox.Visibility = visibility;
 
-     }
 
-     private void SetJobFilterVisibility(bool visible)
 
-     {
 
-         var visibility = visible ? Visibility.Visible : Visibility.Collapsed;
 
-         JobBox.Visibility = visibility;
 
-     }
 
-     private void DateTypeBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
 
-     {
 
-         var filterType = (DateFilterType)DateTypeBox.SelectedValue;
 
-         Properties.DateFilterType = filterType;
 
-         if (filterType == DateFilterType.Custom)
 
-         {
 
-             if (FromPicker.SelectedDate == null || FromPicker.SelectedDate == DateTime.MinValue)
 
-             {
 
-                 Properties.FromDate = DateTime.Today;
 
-             }
 
-             else
 
-             {
 
-                 Properties.FromDate = FromPicker.SelectedDate.Value;
 
-             }
 
-             if (ToPicker.SelectedDate == null || ToPicker.SelectedDate == DateTime.MinValue)
 
-             {
 
-                 Properties.ToDate = DateTime.Today;
 
-             }
 
-             else
 
-             {
 
-                 Properties.ToDate = ToPicker.SelectedDate.Value;
 
-             }
 
-         }
 
-         SetupDateFilters();
 
-         Refresh();
 
-     }
 
-     private void FromPicker_SelectedDateChanged(object? sender, SelectionChangedEventArgs e)
 
-     {
 
-         Properties.FromDate = FromPicker.SelectedDate ?? DateTime.Today;
 
-         Refresh();
 
-     }
 
-     private void ToPicker_SelectedDateChanged(object? sender, SelectionChangedEventArgs e)
 
-     {
 
-         Properties.ToDate = ToPicker.SelectedDate ?? DateTime.Today;
 
-         Refresh();
 
-     }
 
-     private bool _changing = false;
 
-     private void UpdateCategory(string? category)
 
-     {
 
-         _changing = true;
 
-         
 
-         Properties.Category = category;
 
-         SetCategory(Properties.Category);
 
-         foreach(var (type, button) in CategoryButtons)
 
-         {
 
-             if(type == FormType)
 
-             {
 
-                 button.Background = EnabledBrush;
 
-             }
 
-             else
 
-             {
 
-                 button.Background = DisabledBrush;
 
-             }
 
-         }
 
-         var jobLink = FormType is not null ? GetJobLink("", FormType,true) : "";
 
-         if (string.IsNullOrWhiteSpace(jobLink))
 
-         {
 
-             var jobID = Properties.JobID;
 
-             JobBox.SelectedValue = Guid.Empty;
 
-             JobBox.IsEnabled = false;
 
-             Properties.JobID = jobID;
 
-             
 
-         }
 
-         else
 
-         {
 
-             JobBox.SelectedValue = Properties.JobID;
 
-             JobBox.IsEnabled = true;
 
-         }
 
-         string changeableJobLink = "";
 
-         string changeableScopeLink = "";
 
-         
 
-         if ((FormType != null) && ChangeableLinks.TryGetValue(FormType, out Tuple<string,string> _tuple))
 
-         {
 
-             changeableJobLink = _tuple.Item1;
 
-             changeableScopeLink = _tuple.Item2;
 
-         }
 
-         
 
-         if (_jobAction != null)
 
-             _jobAction.Visibility = string.IsNullOrWhiteSpace(changeableJobLink) ? Visibility.Collapsed : Visibility.Visible;
 
-         
 
-         if (_jobScopeAction != null)
 
-             _jobScopeAction.Visibility = string.IsNullOrWhiteSpace(changeableScopeLink) ? Visibility.Collapsed : Visibility.Visible;
 
-         if (ParentType is null)
 
-         {
 
-             FormBox.IsEnabled = false;
 
-             FormBox.ItemsSource = new Dictionary<DigitalForm, string> { };
 
-         }
 
-         else
 
-         {
 
-             var forms = DigitalForms.Where(x => x.AppliesTo == ParentType.Name).ToList();
 
-             forms.Insert(0, new DigitalForm { ID = Guid.Empty, Description = "Select Form" });
 
-             FormBox.ItemsSource = forms;
 
-             if (Properties.SelectedForm != Guid.Empty && forms.Where(x => x.ID == Properties.SelectedForm).FirstOrDefault() is DigitalForm form)
 
-             {
 
-                 FormBox.SelectedItem = form;
 
-             }
 
-             else
 
-             {
 
-                 FormBox.SelectedIndex = 0;
 
-             }
 
-             FormBox.DisplayMemberPath = "Description";
 
-             FormBox.IsEnabled = true;
 
-         }
 
-         _changing = false;
 
-         OnUpdateDataModel?.Invoke(SectionName, DataModel(Selection.None));
 
-     }
 
-     private void CatagoryButton_Click(object sender, RoutedEventArgs e)
 
-     {
 
-         UpdateCategory(((sender as Button)!.Tag as string)!);
 
-         Refresh();
 
-     }
 
-     private void Category_SelectionChanged(object sender, SelectionChangedEventArgs e)
 
-     {
 
-         UpdateCategory((CategoryBox.SelectedValue as string)!);
 
-         Refresh();
 
-     }
 
-     private void FormBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
 
-     {
 
-         Form = FormBox.SelectedValue as DigitalForm;
 
-         Properties.SelectedForm = Form?.ID ?? Guid.Empty;
 
-         if (!_changing)
 
-         {
 
-             OnUpdateDataModel?.Invoke(SectionName, DataModel(Selection.None));
 
-         }
 
-         Refresh();
 
-     }
 
-     #endregion
 
-     #region IBasePanel
 
-     public bool IsReady { get; set; }
 
-     public event DataModelUpdateEvent? OnUpdateDataModel;
 
-     private PanelAction? _jobAction = null;
 
-     private PanelAction? _jobScopeAction = null;
 
-     public void CreateToolbarButtons(IPanelHost host)
 
-     {
 
-         host.CreatePanelAction(new PanelAction("Export Forms", PRSDesktop.Resources.disk, action => SaveToFolder_Click()));
 
-         _jobAction ??= new PanelAction("Set Job Number", PRSDesktop.Resources.project, SetJobNumber);
 
-         host.CreatePanelAction(_jobAction);
 
-         _jobScopeAction ??= new PanelAction(
 
-             "Set Job Scope",
 
-             PRSDesktop.Resources.project,
 
-             null,
 
-             LoadJobScopes
 
-         );
 
-         host.CreatePanelAction(_jobScopeAction);
 
-         
 
-     }
 
-     private IPanelActionEntry[] LoadJobScopes(PanelAction arg)
 
-     {
 
-         List<IPanelActionEntry> result = new();
 
-         var linkcolumn = GetJobLink("", FormType, true);
 
-         if (!string.IsNullOrWhiteSpace(linkcolumn))
 
-         {
 
-             linkcolumn = $"{linkcolumn}.ID";
 
-             var jobid = Grid.SelectedRows.Select(x => x[linkcolumn]).FirstOrDefault();
 
-             if (jobid != null && !Guid.Equals(jobid, Guid.Empty))
 
-             {
 
-                 var scopes =Client.Query<JobScope>(
 
-                     new Filter<JobScope>(x => x.Job.ID).IsEqualTo((Guid)jobid),
 
-                     Columns.None<JobScope>()
 
-                         .Add(x => x.ID)
 
-                         .Add(x => x.Number)
 
-                         .Add(x => x.Description)
 
-                 ).ToObjects<JobScope>();
 
-                 foreach (var scope in scopes)
 
-                 {
 
-                     var entry = new PanelActionEntry<Guid>($"{scope.Number}: {scope.Description}",
 
-                         PRSDesktop.Resources.project, scope.ID, SetJobScope);
 
-                     result.Add(entry);
 
-                 }
 
-             }
 
-         }
 
-         return result.ToArray();
 
-     }
 
-     private void SetJobScope(PanelActionEntry<Guid> scopeid)
 
-     {
 
-         Type? _type = FormType == typeof(JobForm)
 
-             ? FormType
 
-             : ParentType;
 
-         if (_type == null)
 
-             return;
 
-         string _idCol = FormType == typeof(JobForm)
 
-             ? "ID"
 
-             : "Parent.ID";
 
-         var _ids = Grid.SelectedRows.Select(x => x[_idCol]).OfType<Guid>().Distinct().ToArray();
 
-         Progress.ShowModal("Updating Job Scopes", progress =>
 
-         {
 
-                 
 
-             var _updates = ClientFactory.CreateClient(_type)
 
-                 .Query(
 
-                     Filter.Create(_type, "ID", Operator.InList, _ids),
 
-                     Columns.Create(_type, ColumnTypeFlags.Required)
 
-                 ).ToObjects(_type).ToArray();
 
-             var _scopelink = GetJobScopeLink("", _type, FormType == typeof(JobForm) ? 0 : 1);
 
-             foreach (var _update in _updates)
 
-                 CoreUtils.SetPropertyValue(_update, _scopelink + ".ID", scopeid.Data);
 
-             ClientFactory.CreateClient(_type).Save(_updates, "Updated Job Number");
 
-         });
 
-         Refresh();
 
-     }
 
-     private void SetJobNumber(PanelAction obj)
 
-     {
 
-         var dlg = new MultiSelectDialog<Job>(
 
-             LookupFactory.DefineFilter<Job>(),
 
-             Columns.None<Job>()
 
-                 .Add(x => x.ID)
 
-                 .Add(x => x.JobNumber)
 
-                 .Add(x => x.Name)
 
-             , false
 
-         );
 
-         if (dlg.ShowDialog())
 
-         {
 
-             Guid _jobID = dlg.IDs().FirstOrDefault();
 
-             
 
-             Type? _type = FormType == typeof(JobForm)
 
-                 ? FormType
 
-                 : ParentType;
 
-             if (_type == null)
 
-                 return;
 
-             string _idCol = FormType == typeof(JobForm)
 
-                 ? "ID"
 
-                 : "Parent.ID";
 
-             
 
-             var _ids = Grid.SelectedRows.Select(x => x[_idCol]).OfType<Guid>().Distinct().ToArray();
 
-             
 
-             Progress.ShowModal("Updating Job Numbers", progress =>
 
-             {
 
-                 
 
-                 var _updates = ClientFactory.CreateClient(_type)
 
-                     .Query(
 
-                         Filter.Create(_type, "ID", Operator.InList, _ids),
 
-                         Columns.Create(_type, ColumnTypeFlags.Required)
 
-                     ).ToObjects(_type).ToArray();
 
-                 var _joblink = GetJobLink("", _type, false);
 
-                 foreach (var _update in _updates)
 
-                     CoreUtils.SetPropertyValue(_update, _joblink + ".ID", _jobID);
 
-                 ClientFactory.CreateClient(_type).Save(_updates, "Updated Job Number");
 
-             });
 
-             Refresh();
 
-         }
 
-     }
 
-     public void Heartbeat(TimeSpan time)
 
-     {
 
-     }
 
-     public Dictionary<string, object[]> Selected()
 
-     {
 
-         return new Dictionary<string, object[]>();
 
-     }
 
-     #endregion
 
-     public string SectionName
 
-     {
 
-         get
 
-         {
 
-             if (Form is null || Form.ID == Guid.Empty)
 
-                 return "Digital Forms";
 
-             return Form.ID.ToString() ?? "Digital Forms";
 
-         }
 
-     }
 
-     public DataModel DataModel(Selection selection)
 
-     {
 
-         if (FormType is null || Form is null || Form.ID == Guid.Empty)
 
-         {
 
-             return new AutoDataModel<DigitalForm>(new Filter<DigitalForm>().None());
 
-         }
 
-         IFilter filter;
 
-         switch (selection)
 
-         {
 
-             case Selection.Selected:
 
-                 var formids = Grid.SelectedRows.ToArray(x => x.Get<Guid>("ID"));
 
-                 filter = Filter.Create<Entity>(FormType, x => x.ID).InList(formids);
 
-                 break;
 
-             case Selection.All:
 
-                 filter = Filter.Create(FormType).All();
 
-                 break;
 
-             case Selection.None:
 
-             default:
 
-                 filter = Filter.Create(FormType).None();
 
-                 break;
 
-         }
 
-         return (Activator.CreateInstance(typeof(DigitalFormReportDataModel<>)!
 
-             .MakeGenericType(FormType), new object?[] { filter, Form.ID }) as DataModel)!;
 
-     }
 
-     public void BuildActionsMenu(ContextMenu menu)
 
-     {
 
-         menu.AddItem("Export", InABox.Wpf.Resources.doc_xls, Export_Click, Form is not null && Form.ID != Guid.Empty);
 
-         var loadingModules = menu.AddItem("Loading Modules...", null, null, false);
 
-         Task.Run(() =>
 
-         {
 
-             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();
 
-             menu.AddItem("Manage Modules", PRSDesktop.Resources.script, ManageModules_Click);
 
-         }
 
-     }
 
-     private void SaveToFolder_Click()
 
-     {
 
-         if (Form is null || FormType is null)
 
-         {
 
-             MessageWindow.ShowMessage("Please select a form first.", "Select form");
 
-             return;
 
-         }
 
-         var model = DataModel(Selection.None);
 
-         
 
-         var reports = ReportUtils.LoadReports(Form.ID.ToString(), model).Where(x => x.Visible).ToList();
 
-         var method = typeof(DigitalFormsDashboard).GetMethod("SaveToFolder", BindingFlags.Instance | BindingFlags.NonPublic)!.MakeGenericMethod(FormType);
 
-         if (reports.Count == 0)
 
-         {
 
-             MessageWindow.ShowMessage("No reports are currently defined for this Digital Form!", "No report found");
 
-             return;
 
-         }
 
-         
 
-         if(reports.Count == 1)
 
-         {
 
-             method.Invoke(this, new object[] { reports[0] });
 
-             return;
 
-         }
 
-         var menu = new ContextMenu();
 
-         foreach (var report in reports)
 
-             menu.AddItem(report.Name, null, report, r => method.Invoke(this, new[] { r }));
 
-         menu.IsOpen = true;
 
-     }
 
-     private void SaveToFolder<TForm>(ReportTemplate report)
 
-         where TForm : Entity, IDigitalFormInstance, IRemotable, IPersistent, new()
 
-     {
 
-         using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
 
-         {
 
-             var result = dialog.ShowDialog();
 
-             if(result == System.Windows.Forms.DialogResult.OK && !string.IsNullOrWhiteSpace(dialog.SelectedPath))
 
-             {
 
-                 var data = Grid.SelectedRows;
 
-                 Progress.ShowModal("Saving forms", progress =>
 
-                 {
 
-                     foreach (var row in data)
 
-                     {
 
-                         var id = row.Get<Guid>("ID");
 
-                         var number = row.Get<string>("Number");
 
-                         progress.Report($"Saving form {number}");
 
-                         var dataModel = new DigitalFormReportDataModel<TForm>(
 
-                             new Filter<TForm>(x => x.ID).IsEqualTo(id),
 
-                             Form!.ID);
 
-                         var pdfData = ReportUtils.ReportToPDF(report, dataModel, true);
 
-                         var expr = dataModel.EvaluateExpression(Form.ExportExpression)?.Trim();
 
-                         var filename = String.IsNullOrWhiteSpace(expr)
 
-                             ? number
 
-                             : $"{number} - {CoreUtils.SanitiseFileName(expr)}";
 
-                         File.WriteAllBytes(Path.Combine(dialog.SelectedPath, Path.ChangeExtension(filename, ".pdf")), pdfData);
 
-                     }
 
-                 });
 
-                 Process.Start("explorer.exe" , dialog.SelectedPath);
 
-             }
 
-         }
 
-     }
 
-     private void Export_Click()
 
-     {
 
-         // var formName = Regex.Replace(Form?.Description ?? "", "[^ a-zA-Z0-9]", "");
 
-         // var filename = string.Format("{0} - {1} - {2:yyyy-MM-dd} - {3:yyyy-MM-dd}.xlsx", ParentType!.Name, formName, From, To);
 
-         // var options = new ExcelExportingOptions();
 
-         // options.ExcelVersion = ExcelVersion.Excel2013;
 
-         // options.ExportStackedHeaders = true;
 
-         // var excelEngine = DataGrid.ExportToExcel(DataGrid.View, options);
 
-         // var workBook = excelEngine.Excel.Workbooks[0];
 
-         // var sheet = workBook.Worksheets[0];
 
-         // sheet.Name = "Summary";
 
-         // sheet.UsedRange.AutofitRows();
 
-         // sheet.UsedRange.AutofitColumns();
 
-         // sheet = workBook.Worksheets.Create("Questions");
 
-         // sheet.Move(0);
 
-         // var questions = new Client<QAQuestion>().Query(new Filter<QAQuestion>(x => x.Form.ID).IsEqualTo(Form!.ID));
 
-         // sheet.Range[1, 1].Text = Form?.Description ?? "";
 
-         // sheet.Range[1, 1, 1, 3].Merge();
 
-         // var i = 1;
 
-         // foreach (var row in questions.Rows)
 
-         //     if (!row.Get<QAQuestion, QAAnswer>(x => x.Answer).Equals(QAAnswer.Comment))
 
-         //     {
 
-         //         sheet.Range[i + 2, 1].Text = string.Format("{0}.", i);
 
-         //         sheet.Range[i + 2, 2].Text = string.Format("{0}", row.Get<QAQuestion, string>(x => x.Question));
 
-         //         sheet.Range[i + 2, 3].Text = string.Format("[{0}]", row.Get<QAQuestion, string>(x => x.Code));
 
-         //         i++;
 
-         //     }
 
-         // sheet.UsedRange.AutofitRows();
 
-         // sheet.UsedRange.AutofitColumns();
 
-         // try
 
-         // {
 
-         //     workBook.SaveAs(filename);
 
-         //     var startInfo = new ProcessStartInfo(filename);
 
-         //     startInfo.Verb = "open";
 
-         //     startInfo.UseShellExecute = true;
 
-         //     Process.Start(startInfo);
 
-         // }
 
-         // catch
 
-         // {
 
-         //     MessageBox.Show(string.Format("Unable to Save/Launch [{0}]!\n\nIs the file already open?", filename));
 
-         // }
 
-     }
 
-     private void ManageFilters_Click()
 
-     {
 
-         var filters = Properties.Filters.GetValueOrDefault(ParentType!.Name) ?? new List<DFFilter>();
 
-         var gridFilters = new CoreFilterDefinitions();
 
-         gridFilters.AddRange(filters.Select(x => new CoreFilterDefinition { Name = x.Name, Filter = x.Filter }));
 
-         var grid = new DynamicGridFilterEditor(gridFilters, FormType!);
 
-         if (grid.ShowDialog() == true)
 
-         {
 
-             Properties.Filters[ParentType!.Name] = grid.Filters.Select(x => new DFFilter { Name = x.Name, Filter = x.Filter }).ToList();
 
-             if (CustomFilterIndex != null)
 
-             {
 
-                 Refresh();
 
-             }
 
-         }
 
-     }
 
-     private void ExecuteFilter(Tuple<int, string, List<MenuItem>> tag, bool isChecked)
 
-     {
 
-         var (index, filter, items) = tag;
 
-         if (isChecked)
 
-         {
 
-             var i = 0;
 
-             foreach (var item in items)
 
-             {
 
-                 item.IsChecked = i == index;
 
-                 ++i;
 
-             }
 
-         }
 
-         if (isChecked)
 
-         {
 
-             CustomFilter = Serialization.Deserialize(typeof(Filter<>).MakeGenericType(FormType!), filter) as IFilter;
 
-             CustomFilterIndex = index;
 
-             Refresh();
 
-         }
 
-         else if (index == CustomFilterIndex)
 
-         {
 
-             CustomFilter = null;
 
-             CustomFilterIndex = null;
 
-             Refresh();
 
-         }
 
-     }
 
-     private void ExecuteModule_Click(CustomModule obj)
 
-     {
 
-         if (!string.IsNullOrWhiteSpace(obj.Script))
 
-             try
 
-             {
 
-                 Selection selection;
 
-                 if (obj.SelectedRecords && obj.AllRecords)
 
-                     selection = RecordSelectionDialog.Execute();
 
-                 else if (obj.SelectedRecords)
 
-                     selection = Selection.Selected;
 
-                 else if (obj.AllRecords)
 
-                     selection = Selection.All;
 
-                 else
 
-                     selection = Selection.None;
 
-                 var result = ScriptDocument.RunCustomModule(DataModel(selection), new Dictionary<string, object[]>(), obj.Script);
 
-                 if (result)
 
-                     Refresh();
 
-             }
 
-             catch (CompileException c)
 
-             {
 
-                 MessageBox.Show(c.Message);
 
-             }
 
-             catch (Exception err)
 
-             {
 
-                 MessageBox.Show(CoreUtils.FormatException(err));
 
-             }
 
-         else
 
-             MessageBox.Show("Unable to load " + obj.Name);
 
-     }
 
-     private void ManageModules_Click()
 
-     {
 
-         var section = SectionName;
 
-         var dataModel = DataModel(Selection.Selected);
 
-         var manager = new CustomModuleManager()
 
-         {
 
-             Section = section,
 
-             DataModel = dataModel
 
-         };
 
-         manager.ShowDialog();
 
-     }
 
-     private void ToggleDateFilter(bool isChecked)
 
-     {
 
-         Properties.ShowDateFilter = isChecked;
 
-         SetDateFilterVisibility(Properties.ShowDateFilter);
 
-     }
 
-     private void ToggleJobFilter(bool isChecked)
 
-     {
 
-         Properties.ShowJobFilter = isChecked;
 
-         SetJobFilterVisibility(Properties.ShowJobFilter);
 
-         Refresh();
 
-     }
 
-     #region Filtering
 
-     private DateTime From { get; set; }
 
-     private DateTime To { get; set; }
 
-     private bool IsEntityForm { get; set; }
 
-     private Type? _parentType;
 
-     private Type? ParentType
 
-     {
 
-         get => _parentType;
 
-         set
 
-         {
 
-             _parentType = value;
 
-             Grid.ParentType = value;
 
-         }
 
-     }
 
-     private Type? _formType;
 
-     private Type? FormType
 
-     {
 
-         get => _formType;
 
-         set
 
-         {
 
-             _formType = value;
 
-             Grid.FormType = value;
 
-         }
 
-     }
 
-     private DigitalForm? Form { get; set; }
 
-     private IFilter? CustomFilter { get; set; }
 
-     private int? CustomFilterIndex { get; set; }
 
-     private static int WeekDay(DateTime date)
 
-     {
 
-         if (date.DayOfWeek == DayOfWeek.Sunday)
 
-             return 7;
 
-         return (int)date.DayOfWeek - 1;
 
-     }
 
-     private void SetupDateFilters()
 
-     {
 
-         switch (Properties.DateFilterType)
 
-         {
 
-             case DateFilterType.Today:
 
-                 From = DateTime.Today;
 
-                 To = DateTime.Today;
 
-                 break;
 
-             case DateFilterType.Yesterday:
 
-                 From = DateTime.Today.AddDays(-1);
 
-                 To = DateTime.Today.AddDays(-1);
 
-                 break;
 
-             case DateFilterType.Week:
 
-                 From = DateTime.Today.AddDays(-WeekDay(DateTime.Today));
 
-                 To = DateTime.Today;
 
-                 break;
 
-             case DateFilterType.SevenDays:
 
-                 From = DateTime.Today.AddDays(-6);
 
-                 To = DateTime.Today;
 
-                 break;
 
-             case DateFilterType.Month:
 
-                 From = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
 
-                 To = DateTime.Today;
 
-                 break;
 
-             case DateFilterType.ThirtyDays:
 
-                 From = DateTime.Today.AddDays(-29);
 
-                 To = DateTime.Today;
 
-                 break;
 
-             case DateFilterType.Year:
 
-                 From = new DateTime(DateTime.Today.Year, 1, 1);
 
-                 To = DateTime.Today;
 
-                 break;
 
-             case DateFilterType.TwelveMonths:
 
-                 From = DateTime.Today.AddYears(-1).AddDays(1);
 
-                 To = DateTime.Today;
 
-                 break;
 
-             case DateFilterType.Custom:
 
-                 From = Properties.FromDate;
 
-                 To = Properties.ToDate;
 
-                 break;
 
-         }
 
-         DateTypeBox.SelectedValue = Properties.DateFilterType;
 
-         FromPicker.SelectedDate = From;
 
-         ToPicker.SelectedDate = To;
 
-         var enabledPicker = Properties.DateFilterType == DateFilterType.Custom;
 
-         FromPicker.IsEnabled = enabledPicker;
 
-         ToPicker.IsEnabled = enabledPicker;
 
-     }
 
-     private void SetupJobFilter()
 
-     {
 
-         JobBox.SelectedValue = Properties.JobID;
 
-     }
 
-     private void SetupFilters()
 
-     {
 
-         SetupDateFilters();
 
-         SetupJobFilter();
 
-         SetDateFilterVisibility(Properties.ShowDateFilter);
 
-         SetJobFilterVisibility(Properties.ShowJobFilter);
 
-     }
 
-     #region Categories
 
-     private static Dictionary<string, Tuple<Type, Type>>? FormInstanceTypes;
 
-     public static readonly Dictionary<Type, List<Tuple<string, string>>> ParentColumns = new()
 
-     {
 
-         { typeof(Kanban), new() { new("Parent.Number", "Task No") } },
 
-         { typeof(JobITP), new() { new("Parent.Code", "Code") } },
 
-         { typeof(Assignment), new() { new("Parent.Number", "Ass. No") } },
 
-         { typeof(Employee), new() { new("Parent.Code", "Employee") } },
 
-         { typeof(PurchaseOrderItem), new() { new("Parent.PONumber", "PO No") } }
 
-     };
 
-     public static Dictionary<Type, Tuple<string, string>> ChangeableLinks = new()
 
-     {
 
-         { typeof(JobForm), new( "Parent.ID", "Scope.ID") },
 
-         { typeof(AssignmentForm), new( "JobLink.ID", "JobScope.ID") },
 
-         { typeof(KanbanForm), new( "JobLink.ID", "") }
 
-     };
 
-     private static bool CategoryToType(string category, [NotNullWhen(true)] out Type? formType, [NotNullWhen(true)] out Type? parentType)
 
-     {
 
-         if (FormInstanceTypes == null)
 
-         {
 
-             var instancetypes = CoreUtils.Entities.Where(
 
-                 x => x.GetInterfaces().Contains(typeof(IDigitalFormInstance))
 
-             ).Select(x =>
 
-             {
 
-                 var inter = x.GetInterfaces()
 
-                     .Where(x => x.IsGenericType && x.GetGenericTypeDefinition().Equals(typeof(IDigitalFormInstance<>)))
 
-                     .FirstOrDefault();
 
-                 if (inter is not null)
 
-                 {
 
-                     var link = inter.GenericTypeArguments[0];
 
-                     var entityLinkDef = link.GetSuperclassDefinition(typeof(EntityLink<>));
 
-                     if (entityLinkDef is not null)
 
-                     {
 
-                         var entityType = entityLinkDef.GenericTypeArguments[0];
 
-                         return new Tuple<string, Type, Type>(entityType.Name, x, entityType);
 
-                     }
 
-                 }
 
-                 return null;
 
-             }).Where(x => x is not null);
 
-             FormInstanceTypes =
 
-                 instancetypes.ToDictionary(x => x!.Item1, x => new Tuple<Type, Type>(x!.Item2, x!.Item3));
 
-         }
 
-         if (!FormInstanceTypes.TryGetValue(category, out var result))
 
-         {
 
-             formType = null;
 
-             parentType = null;
 
-             return false;
 
-         }
 
-         formType = result.Item1;
 
-         parentType = result.Item2;
 
-         return true;
 
-     }
 
-     private void SetCategory(string? category)
 
-     {
 
-         CustomFilter = null;
 
-         CustomFilterIndex = null;
 
-         if (category is null || !CategoryToType(category, out var formType, out var parentType))
 
-         {
 
-             IsEntityForm = false;
 
-             ParentType = null;
 
-             FormType = null;
 
-             return;
 
-         }
 
-         IsEntityForm = formType.IsSubclassOfRawGeneric(typeof(EntityForm<,,>));
 
-         ParentType = parentType;
 
-         FormType = formType;
 
-     }
 
-     #endregion
 
-     private static string GetJobLink(string prefix, Type type, bool recursive)
 
-     {
 
-         if (type == null)
 
-             return "null";
 
-         var props = type.GetProperties().Where(x =>
 
-             x.PropertyType.BaseType != null && x.PropertyType.BaseType.IsGenericType &&
 
-             x.PropertyType.BaseType.GetGenericTypeDefinition() == typeof(EntityLink<>));
 
-         foreach (var prop in props)
 
-         {
 
-             if (prop.PropertyType == typeof(JobLink))
 
-                 return (string.IsNullOrEmpty(prefix) ? "" : prefix + ".") + prop.Name;
 
-             if (recursive)
 
-             {
 
-                 var result = GetJobLink((string.IsNullOrEmpty(prefix) ? "" : prefix + ".") + prop.Name,
 
-                     prop.PropertyType, recursive);
 
-                 if (!string.IsNullOrEmpty(result))
 
-                     return result;
 
-             }
 
-         }
 
-         return "";
 
-     }
 
-     
 
-     private static string GetJobScopeLink(string prefix, Type type, int recurselevel)
 
-     {
 
-         var props = type.GetProperties().Where(x =>
 
-             x.PropertyType.BaseType != null && x.PropertyType.BaseType.IsGenericType &&
 
-             x.PropertyType.BaseType.GetGenericTypeDefinition() == typeof(EntityLink<>));
 
-         foreach (var prop in props)
 
-         {
 
-             if (prop.PropertyType == typeof(JobScopeLink))
 
-                 return (string.IsNullOrEmpty(prefix) ? "" : prefix + ".") + prop.Name;
 
-             if (recurselevel > 0)
 
-             {
 
-                 var result = GetJobScopeLink((string.IsNullOrEmpty(prefix) ? "" : prefix + ".") + prop.Name,
 
-                     prop.PropertyType, recurselevel - 1);
 
-                 if (!string.IsNullOrEmpty(result))
 
-                     return result;
 
-             }
 
-         }
 
-         return "";
 
-     }
 
-     /// <summary>
 
-     /// Find a link from the form type to an associated <see cref="Job"/>, allowing us to filter based on jobs.
 
-     /// </summary>
 
-     /// <returns>The property name of the <see cref="JobLink"/>.</returns>
 
-     private static string GetJobLink<T>(bool recursive) where T : IDigitalFormInstance
 
-         => GetJobLink("", typeof(T), recursive);
 
-     
 
-     private static string GetJobScopeLink<T>(int recurselevel) where T : IDigitalFormInstance
 
-         => GetJobScopeLink("", typeof(T), recurselevel);
 
-     private IKeyedQueryDef GetFormQuery<T>()
 
-         where T : Entity, IRemotable, IPersistent, IDigitalFormInstance, new()
 
-     {
 
-         var sort = LookupFactory.DefineSort<T>();
 
-         var jobLink = GetJobLink<T>(true);
 
-         var jobScopeLink = GetJobScopeLink<T>(typeof(T) == typeof(JobForm) ? 0 : 1);
 
-         var completedFilter = new Filter<T>(x => x.FormCompleted).IsGreaterThanOrEqualTo(From)
 
-             .And(x => x.FormCompleted).IsLessThan(To.AddDays(1));
 
-         if (Properties.ShowIncompleteForms)
 
-         {
 
-             completedFilter.Or(x => x.FormCompleted).IsEqualTo(FilterConstant.Null);
 
-         }
 
-         var filter = new Filter<T>(x => x.Form.ID).IsEqualTo(Form!.ID)
 
-             .And(x => x.FormCancelled).IsEqualTo(DateTime.MinValue)
 
-             .And(completedFilter);
 
-         if (Properties.JobID != Guid.Empty && Properties.ShowJobFilter)
 
-         {
 
-             filter.And(jobLink + ".ID").IsEqualTo(Properties.JobID);
 
-         }
 
-         if (CustomFilter is not null)
 
-         {
 
-             filter.And(CustomFilter);
 
-         }
 
-         var columns = Columns.None<T>().Add(x => x.ID)
 
-             .Add(x => x.Number)
 
-             .Add(x => x.Description)
 
-             .Add(x => x.CreatedBy)
 
-             .Add(x => x.Created)
 
-             .Add(x => x.Form.ID)
 
-             .Add(x => x.FormData)
 
-             .Add(x => x.FormStarted)
 
-             .Add(x => x.FormCompleted)
 
-             .Add(x => x.FormCompletedBy.UserID)
 
-             .Add(x => x.Location.Timestamp)
 
-             .Add(x => x.Location.Latitude)
 
-             .Add(x => x.Location.Longitude);
 
-         if (IsEntityForm)
 
-             columns.Add(x => x.FormProcessed); //"Processed");
 
-         var parentcols = LookupFactory.DefineColumns(ParentType!);
 
-         foreach (var col in parentcols.ColumnNames())
 
-             columns.Add("Parent." + col);
 
-         if (ParentColumns.TryGetValue(ParentType!, out var pColumns))
 
-         {
 
-             foreach (var (field, name) in pColumns)
 
-                 columns.Add(field);
 
-         }
 
-         if (!string.IsNullOrWhiteSpace(jobLink))
 
-         {
 
-             columns.Add(jobLink + ".ID");
 
-             columns.Add(jobLink + ".JobNumber");
 
-         }
 
-         if (!string.IsNullOrWhiteSpace(jobScopeLink))
 
-         {
 
-             columns.Add(jobScopeLink + ".ID");
 
-             columns.Add(jobScopeLink + ".Number");
 
-         }
 
-         return new KeyedQueryDef<T>(filter, columns, sort);
 
-     }
 
-     #endregion
 
-     private void LoadDataIntoGrid(List<DigitalFormVariable> variables, List<QAQuestion> questions, CoreTable formData, List<string> additionalColumns, CoreTable? jobITPs)
 
-     {
 
-         var cData = new CoreTable();
 
-         cData.AddColumn<Guid>("ID");
 
-         cData.AddColumn<Guid>("Form.ID");
 
-         cData.AddColumn<Guid>("Parent.ID");
 
-         cData.AddColumn<DateTime>("Location.Timestamp");
 
-         cData.AddColumn<double>("Location.Latitude");
 
-         cData.AddColumn<double>("Location.Longitude");
 
-         cData.AddColumn<string>("FormData");
 
-         cData.AddColumn<string>("Number");
 
-         if (ParentColumns.TryGetValue(ParentType!, out var pColumns))
 
-         {
 
-             foreach (var (field, name) in pColumns)
 
-                 cData.AddColumn<string>(field);
 
-         }
 
-         
 
-         var jobLink = GetJobLink("",FormType!,true);
 
-         Grid.JobLink = jobLink;
 
-         if (!string.IsNullOrWhiteSpace(jobLink))
 
-         {
 
-             if (!string.Equals(jobLink, "Parent"))
 
-                 cData.AddColumn<Guid>(jobLink + ".ID");
 
-             cData.AddColumn<string>(jobLink + ".JobNumber");
 
-         }
 
-         var jobScopeLink = GetJobScopeLink("",FormType!,FormType == typeof(JobForm) ? 0 : 1);
 
-         Grid.JobScopeLink = jobLink;
 
-         if (!string.IsNullOrWhiteSpace(jobScopeLink))
 
-         {
 
-             cData.AddColumn<Guid>(jobScopeLink + ".ID");
 
-             cData.AddColumn<string>(jobScopeLink + ".Number");
 
-         }
 
-         cData.AddColumn<string>("Description");
 
-         cData.AddColumn<string>("Parent.Description");
 
-         cData.AddColumn<DateTime>("Created");
 
-         cData.AddColumn<string>("Created By");
 
-         cData.AddColumn<DateTime>("Completed");
 
-         cData.AddColumn<string>("Completed By");
 
-         if (IsEntityForm)
 
-             cData.AddColumn<bool>("Processed");
 
-         if (variables.Count != 0)
 
-         {
 
-             foreach (var variable in variables)
 
-             {
 
-                 var code = variable.Code.Replace("/", " ");
 
-                 Grid.QuestionCodes[code] = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(code.ToLower());
 
-                 try
 
-                 {
 
-                     cData.AddColumn<string>(code);
 
-                 }
 
-                 catch (DuplicateNameException e)
 
-                 {
 
-                     MessageWindow.ShowError($"Error: duplicate variable code {code}", e, title: "Duplicate code");
 
-                 }
 
-             }
 
-         }
 
-         else if (questions.Count != 0)
 
-         {
 
-             Questions = questions;
 
-             Progress.SetMessage("Loading Checks");
 
-             QAGrid.Clear();
 
-             QAGrid.LoadChecks(Form!.Description, Questions, new Dictionary<Guid, object>());
 
-             QAGrid.CollapseMargins();
 
-             var i = 1;
 
-             foreach (var question in Questions)
 
-             {
 
-                 var id = question.ID.ToString();
 
-                 if (!question.Answer.Equals(QAAnswer.Comment))
 
-                 {
 
-                     cData.AddColumn<string>(id);
 
-                     var code = question.Code;
 
-                     Grid.QuestionCodes[id] = string.IsNullOrEmpty(code) ? string.Format("{0}.", i) : code;
 
-                     i++;
 
-                 }
 
-             }
 
-         }
 
-         foreach (var row in formData.Rows)
 
-         {
 
-             var form = (row.ToObject(FormType!) as IDigitalFormInstance)!;
 
-             if (true) //(!string.IsNullOrWhiteSpace(form.FormData))
 
-             {
 
-                 var dataRow = cData.NewRow();
 
-                 dataRow["ID"] = form.ID;
 
-                 dataRow["Form.ID"] = form.Form.ID;
 
-                 dataRow["Parent.ID"] = form.ParentID();
 
-                 dataRow["Location.Timestamp"] = form.Location.Timestamp;
 
-                 dataRow["Location.Latitude"] = form.Location.Latitude;
 
-                 dataRow["Location.Longitude"] = form.Location.Longitude;
 
-                 dataRow["FormData"] = form.FormData;
 
-                 dataRow["Number"] = form.Number;
 
-                 dataRow["Description"] = form.Description;
 
-                 
 
-                 var desc = new List<string>();
 
-                 foreach (var col in additionalColumns)
 
-                 {
 
-                     var val = row[col];
 
-                     if (val != null && val is not Guid)
 
-                         desc.Add(val.ToString() ?? "");
 
-                 }
 
-                 dataRow["Parent.Description"] = string.Join(" : ", desc);
 
-                 dataRow["Created"] = (form as Entity)!.Created.IsEmpty()
 
-                     ? form.FormStarted
 
-                     : (form as Entity)!.Created;
 
-                 dataRow["Created By"] = (form as Entity)!.CreatedBy;
 
-                 dataRow["Completed"] = form.FormCompleted;
 
-                 dataRow["Completed By"] = form.FormCompletedBy.UserID;
 
-                 if (IsEntityForm)
 
-                     dataRow["Processed"] = form.FormProcessed > DateTime.MinValue;
 
-                 
 
-                 
 
-                 // if (ParentType == typeof(JobITP))
 
-                 // {
 
-                 //     var jobITP = jobITPs!.Rows.FirstOrDefault(x => x.Get<JobITP, Guid>(x => x.ID) == form.ParentID());
 
-                 //     if (jobITP is not null)
 
-                 //     {
 
-                 //         var jobID = jobITP.Get<JobITP, Guid>(x => x.Job.ID);
 
-                 //         dataRow["Job No"] = Jobs.Where(x => x.ID == jobID).FirstOrDefault()?.JobNumber;
 
-                 //     }
 
-                 // }
 
-                 if (pColumns != null)
 
-                 {
 
-                     foreach (var (field, name) in pColumns)
 
-                         dataRow[field] = $"{row[field]}";
 
-                 }
 
-                 if (!string.IsNullOrWhiteSpace(jobLink))
 
-                 {
 
-                     dataRow[jobLink + ".ID"] = row[jobLink + ".ID"];
 
-                     dataRow[jobLink + ".JobNumber"] = row[jobLink + ".JobNumber"]?.ToString();
 
-                 }
 
-                 if (!string.IsNullOrWhiteSpace(jobScopeLink))
 
-                 {
 
-                     dataRow[jobScopeLink + ".ID"] = row[jobScopeLink + ".ID"];
 
-                     dataRow[jobScopeLink + ".Number"] = row[jobScopeLink + ".Number"]?.ToString();
 
-                 }
 
-                 var bHasData = false;
 
-                 if (variables.Count != 0)
 
-                 {
 
-                     var dict = Serialization.Deserialize<Dictionary<string, object?>>(form.FormData);
 
-                     if (dict is not null)
 
-                     {
 
-                         var storage = new DFLoadStorage(dict, null);
 
-                         foreach (var variable in variables)
 
-                         {
 
-                             var value = variable.Deserialize(storage.GetEntry(variable.Code));
 
-                             var format = variable.FormatValue(value);
 
-                             var sKey = variable.Code.Replace("/", " ");
 
-                             if (cData.HasColumn(sKey))
 
-                             {
 
-                                 dataRow[sKey] = format;
 
-                                 bHasData = true;
 
-                             }
 
-                         }
 
-                     }
 
-                 }
 
-                 else
 
-                 {
 
-                     var dict = Serialization.Deserialize<Dictionary<Guid, object>>(form.FormData);
 
-                     if (dict is not null)
 
-                         foreach (var key in dict.Keys)
 
-                         {
 
-                             var colName = key.ToString();
 
-                             if (cData.HasColumn(colName))
 
-                             {
 
-                                 dataRow[colName] = dict[key];
 
-                                 bHasData = true;
 
-                             }
 
-                         }
 
-                 }
 
-                 cData.Rows.Add(dataRow);
 
-             }
 
-         }
 
-         Grid.ItemsSource = cData;
 
-         IsQAForm = variables.Count == 0 && questions.Count != 0;
 
-         QAGrid.Visibility = IsQAForm ? Visibility.Visible : Visibility.Collapsed;
 
-         Grid.Visibility = Visibility.Visible;
 
-     }
 
-     private void RefreshData<TForm>()
 
-         where TForm : Entity, IRemotable, IPersistent, IDigitalFormInstance, new()
 
-     {
 
-         var formQuery = GetFormQuery<TForm>();
 
-         var queries = new List<IKeyedQueryDef>()
 
-             {
 
-                 new KeyedQueryDef<QAQuestion>(new Filter<QAQuestion>(x => x.Form.ID).IsEqualTo(Form!.ID)),
 
-                 new KeyedQueryDef<DigitalFormVariable>(
 
-                     new Filter<DigitalFormVariable>(x => x.Form.ID).IsEqualTo(Form.ID),
 
-                     null,
 
-                     new SortOrder<DigitalFormVariable>(x => x.Sequence)),
 
-                 formQuery
 
-             };
 
-         if (ParentType == typeof(JobITP))
 
-         {
 
-             queries.Add(new KeyedQueryDef<JobITP>(
 
-                 new Filter<JobITP>(x => x.ID).InQuery((formQuery.Filter as Filter<JobITPForm>)!, x => x.Parent.ID),
 
-                 Columns.None<JobITP>().Add(x => x.ID, x => x.Job.JobNumber)));
 
-         }
 
-         var results = Client.QueryMultiple(queries);
 
-         var questions = results.Get<QAQuestion>().ToObjects<QAQuestion>().ToList();
 
-         var variables = results.Get<DigitalFormVariable>().ToObjects<DigitalFormVariable>().ToList();
 
-         var formData = results.Get(formQuery.Key);
 
-         LoadDataIntoGrid(
 
-             variables, questions,
 
-             formData,
 
-             formQuery.Columns!.ColumnNames().Where(x => x.StartsWith("Parent.")).ToList(),
 
-             ParentType == typeof(JobITP) ? results.Get<JobITP>() : null);
 
-     }
 
-     public void Refresh()
 
-     {
 
-         if (!IsSetup) return;
 
-         Questions.Clear();
 
-         QAGrid.Clear();
 
-         QAGrid.LoadChecks("", Array.Empty<QAQuestion>(), new Dictionary<Guid, object>());
 
-         if (ParentType is null || FormType is null || Form is null || Form.ID == Guid.Empty)
 
-         {
 
-             QAGrid.Visibility = Visibility.Collapsed;
 
-             Grid.Visibility = Visibility.Collapsed;
 
-             return;
 
-         }
 
-         var refreshMethod = typeof(DigitalFormsDashboard).GetMethod(nameof(RefreshData), BindingFlags.Instance | BindingFlags.NonPublic)!.MakeGenericMethod(FormType);
 
-         refreshMethod.Invoke(this, Array.Empty<object?>());
 
-     }
 
-     public void Shutdown(CancelEventArgs? cancel)
 
-     {
 
-     }
 
-     #region DataGrid Configuration
 
-     private DynamicGridStyle Grid_OnGetRowStyle(CoreRow row, DynamicGridStyle defaultstyle)
 
-     {
 
-         if (row.Get<DateTime>("Completed") == DateTime.MinValue)
 
-         {
 
-             return new DynamicGridRowStyle(defaultstyle) { Background = Colors.LightSalmon.ToBrush() };
 
-         }
 
-         else
 
-         {
 
-             return defaultstyle;
 
-         }
 
-     }
 
-     private Entity? GetEntityForm<T>(Guid id) where T : Entity, IDigitalFormInstance, IRemotable, IPersistent, new()
 
-     {
 
-         var columns = DynamicFormEditWindow.FormColumns<T>();
 
-         return new Client<T>().Query(
 
-             new Filter<T>(x => x.ID).IsEqualTo(id),
 
-             columns).Rows.FirstOrDefault()?.ToObject<T>();
 
-     }
 
-     #endregion
 
-     private void Grid_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)
 
-     {
 
-         var linkcolumn = GetJobLink("", FormType, true);
 
-         if (!string.IsNullOrWhiteSpace(linkcolumn) && _jobScopeAction != null)
 
-         {
 
-             linkcolumn = $"{linkcolumn}.ID";
 
-             var jobids = (e.Rows ?? []).Select(x => x[linkcolumn]).Distinct().ToArray();
 
-             _jobScopeAction.IsEnabled = jobids.Length == 1;
 
-         }
 
-     }
 
-     private void Grid_OnCellDoubleClick(object sender, DynamicGridCellClickEventArgs args)
 
-     {
 
-         if (args.Row is null) return;
 
-         var formid = args.Row.Get<Guid>("Form.ID");
 
-         var formdata = args.Row.Get<string>("FormData");
 
-         var id = args.Row.Get<Guid>("ID");
 
-         if (FormType is null) return;
 
-         if (IsQAForm)
 
-         {
 
-             var values = new Dictionary<Guid, object>();
 
-             var formData = Serialization.Deserialize<Dictionary<string, object>>(formdata);
 
-             if (formData is not null)
 
-             {
 
-                 foreach (var (idStr, value) in formData)
 
-                 {
 
-                     if (Guid.TryParse(idStr, out var codeID))
 
-                     {
 
-                         values[codeID] = value;
 
-                     }
 
-                 }
 
-             }
 
-             QAGrid.Clear();
 
-             QAGrid.LoadChecks(Form!.Description, Questions, values);
 
-             QAGrid.CollapseMargins();
 
-             return;
 
-         }
 
-         var entityForm = typeof(DigitalFormsDashboard)
 
-             .GetMethod(nameof(GetEntityForm), BindingFlags.NonPublic | BindingFlags.Instance)!
 
-             .MakeGenericMethod(FormType)
 
-             .Invoke(this, new object[] { id }) as IDigitalFormInstance;
 
-         if (entityForm is not null)
 
-         {
 
-             if (DynamicFormEditWindow.EditDigitalForm(entityForm, out var dataModel))
 
-             {
 
-                 dataModel.Update(null);
 
-                 /*typeof(QADashboard)
 
-                     .GetMethod(nameof(SaveEntityForm), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!
 
-                     .MakeGenericMethod(formType)
 
-                     .Invoke(this, new object[] { entityForm });*/
 
-                 Refresh();
 
-             }
 
-         }
 
-     }
 
- }
 
- public class DigitalFormsDashboardGrid : CoreTableGrid
 
- {
 
-     public string? JobLink { get; set; }
 
-     public string? JobScopeLink { get; set; }
 
-     public Type? ParentType { get; set; }
 
-     public Type? FormType { get; set; }
 
-     public List<Tuple<string, Type?, string>> Categories { get; set; } = new();
 
-     public readonly Dictionary<string, string> QuestionCodes = new();
 
-     protected override void Init()
 
-     {
 
-         base.Init();
 
-         ActionColumns.Add(new DynamicImageColumn(Location_Image, Location_Click) { Position = DynamicActionColumnPosition.Start });
 
-     }
 
-     protected override void DoReconfigure(DynamicGridOptions options)
 
-     {
 
-         base.DoReconfigure(options);
 
-         options.FilterRows = true;
 
-     }
 
-     private bool Location_Click(CoreRow? row)
 
-     {
 
-         if (row is null) return false;
 
-         var timestamp = row.Get<DateTime>("Location.Timestamp");
 
-         if (timestamp == DateTime.MinValue) return false;
 
-         var latitude = row.Get<double>("Location.Latitude");
 
-         var longitude = row.Get<double>("Location.Longitude");
 
-         var form = new MapForm(latitude, longitude, timestamp);
 
-         form.ShowDialog();
 
-         return false;
 
-     }
 
-     private BitmapImage? Location_Image(CoreRow? row)
 
-     {
 
-         return row?.Get<DateTime>("Location.Timestamp") == DateTime.MinValue ? null : PRSDesktop.Resources.milestone.AsBitmapImage();
 
-     }
 
-     public override DynamicGridColumns GenerateColumns()
 
-     {
 
-         var columns = base.GenerateColumns();
 
-         var newCols = new DynamicGridColumns();
 
-         foreach(var column in columns)
 
-         {
 
-             column.Alignment = Alignment.MiddleCenter;
 
-             if (column.ColumnName == "ID" || column.ColumnName == "Form.ID"
 
-                 || column.ColumnName == "Parent.ID" || column.ColumnName == "FormData"
 
-                 || column.ColumnName == "Location.Latitude" || column.ColumnName == "Location.Longitude")
 
-             {
 
-                 continue;
 
-             }
 
-             else if (column.ColumnName == "Number")
 
-             {
 
-                 column.Width = 80;
 
-                 column.Alignment = Alignment.MiddleCenter;
 
-             }
 
-             else if (column.ColumnName == "Description")
 
-             {
 
-                 column.Width = 250;
 
-                 column.Alignment = Alignment.MiddleLeft;
 
-             }
 
-             else if (column.ColumnName == "Location.Timestamp")
 
-             {
 
-                 continue;
 
-             }
 
-             else if (ParentType is not null && DigitalFormsDashboard.ParentColumns.TryGetValue(ParentType, out var pColumns)
 
-                 && pColumns.FirstOrDefault(x => x.Item1 == column.ColumnName)?.Item2 is string header)
 
-             {
 
-                 column.Caption = header;
 
-             }
 
-             else if (column.ColumnName == JobLink + ".JobNumber")
 
-             {
 
-                 column.Width = 60;
 
-                 column.Caption = "Job No";
 
-             }
 
-             else if (column.ColumnName == JobScopeLink + ".Number")
 
-             {
 
-                 column.Width = 50;
 
-                 column.Caption = "Scope";
 
-             }
 
-             else if (column.ColumnName == "Parent.Description")
 
-             {
 
-                 column.Caption = Categories.FirstOrDefault(x => x.Item2 == FormType)?.Item3 ?? "Parent";
 
-                 column.Alignment = Alignment.MiddleLeft;
 
-                 column.Width = 250;
 
-             }
 
-             else if (column.ColumnName == "Completed")
 
-             {
 
-                 column.Width = 100;
 
-                 column.Format = "dd MMM yy hh:mm";
 
-             }
 
-             else if (column.ColumnName == "Completed By")
 
-             {
 
-                 column.Width = 100;
 
-             }
 
-             else if (column.ColumnName == "Processed")
 
-             {
 
-                 column.Width = 100;
 
-             }
 
-             else if (column.ColumnName == "Created By")
 
-             {
 
-                 column.Width = 100;
 
-             }
 
-             else if (column.ColumnName == "Created")
 
-             {
 
-                 column.Width = 100;
 
-                 column.Format = "dd MMM yy hh:mm";
 
-             }
 
-             else if (QuestionCodes.TryGetValue(column.ColumnName, out var questionHeader))
 
-             {
 
-                 column.Width = 100;
 
-                 column.Caption = questionHeader;
 
-             }
 
-             else
 
-             {
 
-                 continue;
 
-             }
 
-             newCols.Add(column);
 
-         }
 
-         return newCols;
 
-     }
 
- }
 
 
  |