Ver código fonte

Improvements to context menus on Planned Maintenance; added built in filter

Kenric Nugteren 4 meses atrás
pai
commit
5bcede32b8

+ 12 - 20
prs.desktop/Dashboards/Equipment/EquipmentSchedulesDashboard.xaml

@@ -39,8 +39,9 @@
                 <ItemsControl.ItemTemplate>
                     <DataTemplate DataType="local:EquipmentScheduleViewModel">
                         <Border BorderThickness="0,0,0,1" BorderBrush="LightGray"
-                            Background="WhiteSmoke">
-                            <Grid>
+                                Background="WhiteSmoke"
+                                Tag="{Binding ID}" ContextMenuOpening="Grid_ContextMenuOpening">
+                            <Grid x:Name="EquipmentGrid">
                                 <Grid.ColumnDefinitions>
                                     <ColumnDefinition Width="250"/>
                                     <ColumnDefinition Width="*"/>
@@ -49,7 +50,9 @@
                                 <Border Grid.Column="0" Background="White"
                                         BorderThickness="0,0,1,0" BorderBrush="LightGray">
                                     <Border BorderBrush="Gray" BorderThickness="1" CornerRadius="3"
-                                            Padding="5" Margin="2.5">
+                                            Padding="5" Margin="2.5"
+                                            Tag="{Binding ID}"
+                                            ContextMenuOpening="Border_ContextMenuOpening">
                                         <Grid>
                                             <Grid.ColumnDefinitions>
                                                 <ColumnDefinition Width="Auto"/>
@@ -92,11 +95,6 @@
                                             </ToolTip>
                                         </Border.ToolTip>
                                     </Border>
-                                    <Border.ContextMenu>
-                                        <ContextMenu>
-                                            <MenuItem Tag="{Binding ID}" Header="View Equipment" Click="ViewEquipment_Click"/>
-                                        </ContextMenu>
-                                    </Border.ContextMenu>
                                 </Border>
 
                                 <ItemsControl Grid.Column="1" ItemsSource="{Binding Schedules}">
@@ -110,7 +108,9 @@
                                             <Border Background="{Binding DueDate, Converter={StaticResource scheduleBackgroundConverter}}"
                                                     BorderBrush="Gray" BorderThickness="1" CornerRadius="3"
                                                     Padding="5" Margin="5,2.5,0,2.5"
-                                                    Width="150">
+                                                    Width="150"
+                                                    Tag="{Binding ID}"
+                                                    ContextMenuOpening="Schedule_ContextMenuOpening">
                                                 <Grid>
                                                     <Grid.ColumnDefinitions>
                                                         <ColumnDefinition Width="Auto"/>
@@ -118,7 +118,9 @@
                                                     </Grid.ColumnDefinitions>
                                                     <Border Width="30" Height="30" CornerRadius="15"
                                                             Margin="0,0,5,0"
-                                                            BorderThickness="1" BorderBrush="Black">
+                                                            BorderThickness="1" BorderBrush="Black"
+                                                            Tag="{Binding EmployeeID}"
+                                                            ContextMenuOpening="Employee_ContextMenuOpening">
                                                         <Border.Background>
                                                             <ImageBrush ImageSource="{Binding EmployeeImage}" Stretch="UniformToFill"/>
                                                         </Border.Background>
@@ -131,11 +133,6 @@
                                                                 </StackPanel>
                                                             </ToolTip>
                                                         </Border.ToolTip>
-                                                        <Border.ContextMenu>
-                                                            <ContextMenu Style="{StaticResource employeeMenuStyle}">
-                                                                <MenuItem Tag="{Binding EmployeeID}" Header="View Employee" Click="ViewEmployee_Click"/>
-                                                            </ContextMenu>
-                                                        </Border.ContextMenu>
                                                     </Border>
                                                     <StackPanel Grid.Column="1">
                                                         <TextBlock Text="{Binding Title}"
@@ -164,11 +161,6 @@
                                                         </Grid>
                                                     </ToolTip>
                                                 </Border.ToolTip>
-                                                <Border.ContextMenu>
-                                                    <ContextMenu>
-                                                        <MenuItem Header="View Schedule" Tag="{Binding ID}" Click="ViewSchedule_Click"/>
-                                                    </ContextMenu>
-                                                </Border.ContextMenu>
                                             </Border>
 
                                         </DataTemplate>

+ 64 - 33
prs.desktop/Dashboards/Equipment/EquipmentSchedulesDashboard.xaml.cs

@@ -228,6 +228,7 @@ public partial class EquipmentSchedulesDashboard : UserControl, IDashboardWidget
             Height = 25,
             Padding = new()
         };
+        FilterBtn.BuiltInFilters.Add(new("Exclude Disposed", () => new Filter<Equipment>(x => x.Disposed).IsEqualTo(null)));
         FilterBtn.SetSettings(Properties.Filters, false);
         FilterBtn.OnFiltersSelected += FilterBtn_OnFiltersSelected;
         FilterBtn.OnFilterRefresh += FilterBtn_OnFilterRefresh;
@@ -387,54 +388,84 @@ public partial class EquipmentSchedulesDashboard : UserControl, IDashboardWidget
     {
     }
 
-    private void ViewEquipment_Click(object sender, System.Windows.RoutedEventArgs e)
+    private void Border_ContextMenuOpening(object sender, ContextMenuEventArgs e)
     {
-        var equipmentID = (Guid)(sender as MenuItem)!.Tag;
+        if (sender is not FrameworkElement element || element.Tag is not Guid equipmentID) return;
 
-        var equipment = new Client<Equipment>().Load(
-            new Filter<Equipment>(x => x.ID).IsEqualTo(equipmentID)).FirstOrDefault();
-        if(equipment != null)
+        var menu = new ContextMenu();
+        menu.AddItem("View Equipment", null, equipmentID, ViewEquipment_Click);
+        menu.AddItem("Add Schedule", null, equipmentID, CreateSchedule_Click);
+        menu.IsOpen = true;
+
+        e.Handled = true;
+    }
+
+    private void CreateSchedule_Click(Guid equipmentID)
+    {
+        var schedule = new Schedule();
+        schedule.DocumentClass = typeof(Equipment).EntityName();
+        schedule.DocumentID = equipmentID;
+
+        if (DynamicGridUtils.EditEntity(schedule))
         {
-            var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(Equipment));
-            if(grid.EditItems(new[] { equipment }))
-            {
-                new Client<Equipment>().Save(equipment, "Edited by user from schedules dashboard");
-                Refresh();
-            }
+            Refresh();
         }
     }
 
-    private void ViewSchedule_Click(object sender, System.Windows.RoutedEventArgs e)
+    private void Grid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
     {
-        var scheduleID = (Guid)(sender as MenuItem)!.Tag;
+        if (sender is not FrameworkElement element || element.Tag is not Guid equipmentID) return;
+
+        var menu = new ContextMenu();
+        menu.AddItem("Add Schedule", null, equipmentID, CreateSchedule_Click);
+        menu.IsOpen = true;
+
+        e.Handled = true;
+    }
+
+    private void Schedule_ContextMenuOpening(object sender, ContextMenuEventArgs e)
+    {
+        if (sender is not FrameworkElement element || element.Tag is not Guid scheduleID) return;
+
+        var menu = new ContextMenu();
+        menu.AddItem("View Schedule", null, scheduleID, ViewSchedule_Click);
+        menu.IsOpen = true;
+
+        e.Handled = true;
+    }
 
-        var schedule = new Client<Schedule>().Load(
-            new Filter<Schedule>(x => x.ID).IsEqualTo(scheduleID)).FirstOrDefault();
-        if (schedule != null)
+    private void Employee_ContextMenuOpening(object sender, ContextMenuEventArgs e)
+    {
+        if (sender is not FrameworkElement element || element.Tag is not Guid employeeID) return;
+
+        var menu = new ContextMenu();
+        menu.AddItem("View Employee", null, employeeID, ViewEmployee_Click);
+        menu.IsOpen = true;
+
+        e.Handled = true;
+    }
+
+    private void ViewEquipment_Click(Guid equipmentID)
+    {
+        if (DynamicGridUtils.EditEntity<Equipment>(equipmentID))
         {
-            var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(Schedule));
-            if (grid.EditItems(new[] { schedule }))
-            {
-                new Client<Schedule>().Save(schedule, "Edited by user from schedules dashboard");
-                Refresh();
-            }
+            Refresh();
         }
     }
 
-    private void ViewEmployee_Click(object sender, System.Windows.RoutedEventArgs e)
+    private void ViewSchedule_Click(Guid scheduleID)
     {
-        var employeeID = (Guid)(sender as MenuItem)!.Tag;
+        if (DynamicGridUtils.EditEntity<Schedule>(scheduleID))
+        {
+            Refresh();
+        }
+    }
 
-        var employee = new Client<Employee>().Load(
-            new Filter<Employee>(x => x.ID).IsEqualTo(employeeID)).FirstOrDefault();
-        if (employee != null)
+    private void ViewEmployee_Click(Guid employeeID)
+    {
+        if (DynamicGridUtils.EditEntity<Employee>(employeeID))
         {
-            var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(Employee));
-            if (grid.EditItems(new[] { employee }))
-            {
-                new Client<Employee>().Save(employee, "Edited by user from schedules dashboard");
-                Refresh();
-            }
+            Refresh();
         }
     }
 

+ 211 - 212
prs.shared/Grids/ScheduleItemGrid.cs

@@ -16,277 +16,276 @@ using MessageBox = System.Windows.MessageBox;
 using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
 using SaveFileDialog = Microsoft.Win32.SaveFileDialog;
 
-namespace PRS.Shared
+namespace PRS.Shared;
+
+internal class ScheduleItemGrid : DynamicDataGrid<Schedule>//, IDefaultGrid
 {
-    internal class ScheduleItemGrid : DynamicDataGrid<Schedule>
+    private readonly BitmapImage disabled = PRS.Shared.Resources.disabled.AsBitmapImage();
+
+    private readonly BitmapImage tick = PRS.Shared.Resources.tick.AsBitmapImage();
+
+    protected override void Init()
+    {
+        base.Init();
+        ActionColumns.Add(new DynamicTickColumn<Schedule, bool>(x => x.Active, tick, tick, disabled, CheckClick));
+        HiddenColumns.Add(x => x.Active);
+        HiddenColumns.Add(x => x.Title);
+        HiddenColumns.Add(x => x.DocumentClass);
+
+        AddButton("Export", PRS.Shared.Resources.download.AsBitmapImage(), SaveSchedules);
+        AddButton("Import", PRS.Shared.Resources.upload.AsBitmapImage(), LoadSchedules);
+    }
+
+    protected override void DoReconfigure(DynamicGridOptions options)
     {
-        private readonly BitmapImage disabled = PRS.Shared.Resources.disabled.AsBitmapImage();
+        base.DoReconfigure(options);
+        options.RecordCount = true;
+        options.SelectColumns = true;
+        options.MultiSelect = true;
+    }
 
-        private readonly BitmapImage tick = PRS.Shared.Resources.tick.AsBitmapImage();
+    public CoreTable Schedules { get; set; }
 
-        protected override void Init()
-        {
-            base.Init();
-            ActionColumns.Add(new DynamicTickColumn<Schedule, bool>(x => x.Active, tick, tick, disabled, CheckClick));
-            HiddenColumns.Add(x => x.Active);
-            HiddenColumns.Add(x => x.Title);
-            HiddenColumns.Add(x => x.DocumentClass);
-
-            AddButton("Export", PRS.Shared.Resources.download.AsBitmapImage(), SaveSchedules);
-            AddButton("Import", PRS.Shared.Resources.upload.AsBitmapImage(), LoadSchedules);
-        }
+    public Type DocumentType { get; set; }
+    public Guid DocumentID { get; set; }
 
-        protected override void DoReconfigure(DynamicGridOptions options)
+    private bool LoadSchedules(Button sender, CoreRow[] rows)
+    {
+        if (rows.Length != 1)
         {
-            base.DoReconfigure(options);
-            options.RecordCount = true;
-            options.SelectColumns = true;
-            options.MultiSelect = true;
+            MessageBox.Show("Please select only one row to process");
+            return false;
         }
 
-        public CoreTable Schedules { get; set; }
-
-        public Type DocumentType { get; set; }
-        public Guid DocumentID { get; set; }
+        var row = rows.First();
 
-        private bool LoadSchedules(Button sender, CoreRow[] rows)
+        var dlg = new OpenFileDialog();
+        dlg.Filter = "PRS Schedule Files (*.schedule)|*.schedule";
+        if (dlg.ShowDialog() == true)
         {
-            if (rows.Length != 1)
+            Progress.Show("");
+            var json = File.ReadAllText(dlg.FileName);
+            Schedule[] schedules = { };
+            try
             {
-                MessageBox.Show("Please select only one row to process");
-                return false;
+                schedules = Serialization.Deserialize<Schedule[]>(json);
             }
-
-            var row = rows.First();
-
-            var dlg = new OpenFileDialog();
-            dlg.Filter = "PRS Schedule Files (*.schedule)|*.schedule";
-            if (dlg.ShowDialog() == true)
+            catch
             {
-                Progress.Show("");
-                var json = File.ReadAllText(dlg.FileName);
-                Schedule[] schedules = { };
-                try
-                {
-                    schedules = Serialization.Deserialize<Schedule[]>(json);
-                }
-                catch
-                {
-                    Progress.Close();
-                    MessageBox.Show("[" + Path.GetFileName(dlg.FileName) + "] is not a valid schedule file!");
-                    return false;
-                }
-
-                if (!schedules.Any())
-                {
-                    Progress.Close();
-                    MessageBox.Show("[" + Path.GetFileName(dlg.FileName) + "] does not contain any schedules!");
-                    return false;
-                }
-
-                foreach (var schedule in schedules)
-                {
-                    schedule.DocumentID = DocumentID;
-                    schedule.DocumentClass = DocumentType.EntityName();
-                    schedule.ID = Guid.Empty;
-                    schedule.Active = false;
-                    schedule.DueDate = DateTime.MinValue;
-                }
-
-                new Client<Schedule>().Save(schedules, "Imported from [" + Path.GetFileName(dlg.FileName) + "]");
                 Progress.Close();
-                MessageBox.Show(string.Format("{0} schedules loaded from [{1}]", schedules.Length, Path.GetFileName(dlg.FileName)));
+                MessageBox.Show("[" + Path.GetFileName(dlg.FileName) + "] is not a valid schedule file!");
+                return false;
             }
 
-            return true;
-        }
-
-        private bool SaveSchedules(Button sender, CoreRow[] rows)
-        {
-            if (rows.Any())
+            if (!schedules.Any())
             {
-                MessageBox.Show("Please select at least one schedule before Exporting!");
+                Progress.Close();
+                MessageBox.Show("[" + Path.GetFileName(dlg.FileName) + "] does not contain any schedules!");
                 return false;
             }
 
-            var names = new List<string>();
-            rows.ForEach(r => names.Add(r.Get<Schedule, string>(c => c.Title)));
-            var filename = DocumentType.Name + " (" + string.Join(" + ", names) + ")";
-            Path.GetInvalidFileNameChars().ForEach(c => filename = filename.Replace(c.ToString(), ""));
-            Path.GetInvalidPathChars().ForEach(c => filename = filename.Replace(c.ToString(), ""));
-
-            var dlg = new SaveFileDialog();
-            dlg.Filter = "PRS Schedule Files (*.schedule)|*.schedule";
-            dlg.FileName = filename + ".schedule";
-            dlg.AddExtension = false;
-            if (dlg.ShowDialog() == true)
+            foreach (var schedule in schedules)
             {
-                Progress.Show("");
-
-                Filter<Schedule> filter = null;
-                foreach (var schedule in SelectedRows)
-                    if (filter == null)
-                        filter = new Filter<Schedule>(x => x.ID).IsEqualTo(schedule.Get<Schedule, Guid>(x => x.ID));
-                    else
-                        filter = filter.Or(x => x.ID).IsEqualTo(schedule.Get<Schedule, Guid>(x => x.ID));
-
-                var schedules = new Client<Schedule>().Load(filter);
-                foreach (var schedule in schedules)
-                {
-                    schedule.DocumentID = DocumentID;
-                    schedule.DocumentClass = DocumentType.EntityName();
-                    schedule.ID = Guid.Empty;
-                    schedule.Active = false;
-                    schedule.DueDate = DateTime.MinValue;
-                }
-
-                var json = Serialization.Serialize(schedules);
-                File.WriteAllText(dlg.FileName + ".schedule", json);
-                Progress.Close();
-                MessageBox.Show(string.Format("{0} schedules saved to [{1}]", SelectedRows.Length, Path.GetFileName(dlg.FileName)));
+                schedule.DocumentID = DocumentID;
+                schedule.DocumentClass = DocumentType.EntityName();
+                schedule.ID = Guid.Empty;
+                schedule.Active = false;
+                schedule.DueDate = DateTime.MinValue;
             }
 
+            new Client<Schedule>().Save(schedules, "Imported from [" + Path.GetFileName(dlg.FileName) + "]");
+            Progress.Close();
+            MessageBox.Show(string.Format("{0} schedules loaded from [{1}]", schedules.Length, Path.GetFileName(dlg.FileName)));
+        }
+
+        return true;
+    }
+
+    private bool SaveSchedules(Button sender, CoreRow[] rows)
+    {
+        if (rows.Any())
+        {
+            MessageBox.Show("Please select at least one schedule before Exporting!");
             return false;
         }
 
-        private bool CheckClick(CoreRow row)
+        var names = new List<string>();
+        rows.ForEach(r => names.Add(r.Get<Schedule, string>(c => c.Title)));
+        var filename = DocumentType.Name + " (" + string.Join(" + ", names) + ")";
+        Path.GetInvalidFileNameChars().ForEach(c => filename = filename.Replace(c.ToString(), ""));
+        Path.GetInvalidPathChars().ForEach(c => filename = filename.Replace(c.ToString(), ""));
+
+        var dlg = new SaveFileDialog();
+        dlg.Filter = "PRS Schedule Files (*.schedule)|*.schedule";
+        dlg.FileName = filename + ".schedule";
+        dlg.AddExtension = false;
+        if (dlg.ShowDialog() == true)
         {
-            var Due = row.Get<Schedule, DateTime>(x => x.DueDate);
-            if (Due.Equals(DateTime.MinValue))
-            {
-                MessageBox.Show("Schedule must have a due date!");
-                return false;
-            }
+            Progress.Show("");
 
-            using (var client = new Client<Schedule>())
+            Filter<Schedule> filter = null;
+            foreach (var schedule in SelectedRows)
+                if (filter == null)
+                    filter = new Filter<Schedule>(x => x.ID).IsEqualTo(schedule.Get<Schedule, Guid>(x => x.ID));
+                else
+                    filter = filter.Or(x => x.ID).IsEqualTo(schedule.Get<Schedule, Guid>(x => x.ID));
+
+            var schedules = new Client<Schedule>().Load(filter);
+            foreach (var schedule in schedules)
             {
-                var schedule = client.Query(
-                    new Filter<Schedule>(x => x.ID).IsEqualTo(row.Get<Schedule, Guid>(x => x.ID)),
-                    Columns.Required<Schedule>().Add(x => x.Active))
-                    .ToObjects<Schedule>().First();
-                schedule.Active = !schedule.Active;
-                client.Save(schedule, schedule.Active ? "Activated Schedule" : "Disabled Schedule");
+                schedule.DocumentID = DocumentID;
+                schedule.DocumentClass = DocumentType.EntityName();
+                schedule.ID = Guid.Empty;
+                schedule.Active = false;
+                schedule.DueDate = DateTime.MinValue;
             }
 
-            return true;
+            var json = Serialization.Serialize(schedules);
+            File.WriteAllText(dlg.FileName + ".schedule", json);
+            Progress.Close();
+            MessageBox.Show(string.Format("{0} schedules saved to [{1}]", SelectedRows.Length, Path.GetFileName(dlg.FileName)));
         }
 
-        protected override void Reload(
-        	Filters<Schedule> criteria, Columns<Schedule> columns, ref SortOrder<Schedule>? sort,
-        	CancellationToken token, Action<CoreTable?, Exception?> action)
+        return false;
+    }
+
+    private bool CheckClick(CoreRow row)
+    {
+        var Due = row.Get<Schedule, DateTime>(x => x.DueDate);
+        if (Due.Equals(DateTime.MinValue))
         {
-            criteria.Add(new Filter<Schedule>(x => x.DocumentID).IsEqualTo(DocumentID));
-            sort = new SortOrder<Schedule>(x => x.DueDate);
-            base.Reload(criteria, columns, ref sort, token, action);
+            MessageBox.Show("Schedule must have a due date!");
+            return false;
         }
 
-        public override Schedule CreateItem()
+        using (var client = new Client<Schedule>())
         {
-            if(DocumentType is null)
-            {
-                throw new Exception("Cannot create item when DocumentType is null.");
-            }
-
-            var schedule = base.CreateItem();
-            schedule.DocumentClass = DocumentType.EntityName();
-            schedule.DocumentID = DocumentID;
-            if (DocumentType == typeof(CustomModule) || DocumentType == typeof(ScheduledScript))
-                schedule.ScheduleType = ScheduleType.None;
-            return schedule;
+            var schedule = client.Query(
+                new Filter<Schedule>(x => x.ID).IsEqualTo(row.Get<Schedule, Guid>(x => x.ID)),
+                Columns.Required<Schedule>().Add(x => x.Active))
+                .ToObjects<Schedule>().First();
+            schedule.Active = !schedule.Active;
+            client.Save(schedule, schedule.Active ? "Activated Schedule" : "Disabled Schedule");
         }
 
-        public override void SaveItem(Schedule item)
+        return true;
+    }
+
+    protected override void Reload(
+    	Filters<Schedule> criteria, Columns<Schedule> columns, ref SortOrder<Schedule>? sort,
+    	CancellationToken token, Action<CoreTable?, Exception?> action)
+    {
+        criteria.Add(new Filter<Schedule>(x => x.DocumentID).IsEqualTo(DocumentID));
+        sort = new SortOrder<Schedule>(x => x.DueDate);
+        base.Reload(criteria, columns, ref sort, token, action);
+    }
+
+    public override Schedule CreateItem()
+    {
+        if(DocumentType is null)
         {
-            if(DocumentType is not null)
-            {
-                item.DocumentClass = DocumentType.EntityName();
-            }
-            else
-            {
-                if (string.IsNullOrWhiteSpace(item.DocumentClass))
-                {
-                    throw new Exception("Cannot save item when DocumentType is null.");
-                }
-            }
-            base.SaveItem(item);
+            throw new Exception("Cannot create item when DocumentType is null.");
         }
 
-        protected override void DoReconfigureEditors(DynamicEditorGrid grid, Schedule[] items)
-        {
-            base.DoReconfigureEditors(grid, items);
+        var schedule = base.CreateItem();
+        schedule.DocumentClass = DocumentType.EntityName();
+        schedule.DocumentID = DocumentID;
+        if (DocumentType == typeof(CustomModule) || DocumentType == typeof(ScheduledScript))
+            schedule.ScheduleType = ScheduleType.None;
+        return schedule;
+    }
 
-            var frequency = grid.FindEditor("Frequency");
-            if (frequency != null)
+    public override void SaveItem(Schedule item)
+    {
+        if(DocumentType is not null)
+        {
+            item.DocumentClass = DocumentType.EntityName();
+        }
+        else
+        {
+            if (string.IsNullOrWhiteSpace(item.DocumentClass))
             {
-                var freq = (int)frequency.GetValue("Frequency");
-                var period = grid.FindEditor("Period");
-                period?.SetEnabled(freq > 0);
-                var due = grid.FindEditor("DueDate");
-                due?.SetEnabled(freq > 0);
+                throw new Exception("Cannot save item when DocumentType is null.");
             }
+        }
+        base.SaveItem(item);
+    }
 
-            var threshold = grid.FindEditor("Threshold");
-            if (threshold != null)
-            {
-                var thresh = (int)threshold.GetValue("Threshold");
-                var trigger = grid.FindEditor("Trigger");
-                trigger?.SetEnabled(thresh > 0);
-                var next = grid.FindEditor("DueThreshold");
-                next?.SetEnabled(thresh > 0);
-            }
+    protected override void DoReconfigureEditors(DynamicEditorGrid grid, Schedule[] items)
+    {
+        base.DoReconfigureEditors(grid, items);
 
-            var scheduleTypeEditor = grid.FindEditor("ScheduleType");
-            if(scheduleTypeEditor != null)
-            {
-                var scheduleType = (ScheduleType)scheduleTypeEditor.GetValue("ScheduleType");
-                var taskTypeEditor = grid.FindEditor(nameof(Schedule.KanbanType));
-                taskTypeEditor?.SetEnabled(scheduleType == ScheduleType.Task);
-            }
+        var frequency = grid.FindEditor("Frequency");
+        if (frequency != null)
+        {
+            var freq = (int)frequency.GetValue("Frequency");
+            var period = grid.FindEditor("Period");
+            period?.SetEnabled(freq > 0);
+            var due = grid.FindEditor("DueDate");
+            due?.SetEnabled(freq > 0);
         }
 
-        protected override BaseEditor? GetEditor(object item, DynamicGridColumn column)
+        var threshold = grid.FindEditor("Threshold");
+        if (threshold != null)
         {
-            var types = new List<Type> { typeof(CustomModule), typeof(ScheduledScript), typeof(Employee), typeof(Equipment) };
+            var thresh = (int)threshold.GetValue("Threshold");
+            var trigger = grid.FindEditor("Trigger");
+            trigger?.SetEnabled(thresh > 0);
+            var next = grid.FindEditor("DueThreshold");
+            next?.SetEnabled(thresh > 0);
+        }
 
-            var columns = new List<string> { "ScheduleType" };
-            var schedule = (Schedule)item;
+        var scheduleTypeEditor = grid.FindEditor("ScheduleType");
+        if(scheduleTypeEditor != null)
+        {
+            var scheduleType = (ScheduleType)scheduleTypeEditor.GetValue("ScheduleType");
+            var taskTypeEditor = grid.FindEditor(nameof(Schedule.KanbanType));
+            taskTypeEditor?.SetEnabled(scheduleType == ScheduleType.Task);
+        }
+    }
 
-            var documentType = schedule.DocumentType();
-            if (documentType == typeof(CustomModule) || documentType == typeof(ScheduledScript))
-                columns.AddRange(new[]
-                {
-                    "Description", "LeadTime", "EmployeeLink.ID", "ManagerLink.ID", "Report.ID", "Threshold", "Trigger", "DueThreshold", "Rollover",
-                    "QAForm"
-                });
+    protected override BaseEditor? GetEditor(object item, DynamicGridColumn column)
+    {
+        var types = new List<Type> { typeof(CustomModule), typeof(ScheduledScript), typeof(Employee), typeof(Equipment) };
 
-            else if (documentType == typeof(Employee))
-                columns.AddRange(new[] { "Description", "EmployeeLink.ID", "Threshold", "Trigger", "DueThreshold" });
+        var columns = new List<string> { "ScheduleType" };
+        var schedule = (Schedule)item;
 
-            else if (documentType == typeof(Customer))
-                columns.AddRange(new[] { "Threshold", "Trigger", "DueThreshold" });
+        var documentType = schedule.DocumentType();
+        if (documentType == typeof(CustomModule) || documentType == typeof(ScheduledScript))
+            columns.AddRange(new[]
+            {
+                "Description", "LeadTime", "EmployeeLink.ID", "ManagerLink.ID", "Report.ID", "Threshold", "Trigger", "DueThreshold", "Rollover",
+                "QAForm"
+            });
 
+        else if (documentType == typeof(Employee))
+            columns.AddRange(new[] { "Description", "EmployeeLink.ID", "Threshold", "Trigger", "DueThreshold" });
 
-            if (types.Contains(documentType) && columns.Contains(column.ColumnName))
-                return new NullEditor();
-            return base.GetEditor(item, column);
-        }
+        else if (documentType == typeof(Customer))
+            columns.AddRange(new[] { "Threshold", "Trigger", "DueThreshold" });
 
-        public override DynamicEditorPages LoadEditorPages(Schedule item)
-        {
-            var pages = base.LoadEditorPages(item);
-            foreach (var page in pages.ToArray())
-            {
-                if (page is IDynamicOneToManyGrid<Schedule, Kanban> && item.ScheduleType != ScheduleType.Task)
-                    pages = new DynamicEditorPages(pages.Where(x => x != page));
-                else if (page is IDynamicOneToManyGrid<Schedule, Job> && item.ScheduleType != ScheduleType.Job)
-                    pages = new DynamicEditorPages(pages.Where(x => x != page));
-            }
-            return pages;
-        }
 
-        protected override void DefineLookups(ILookupEditorControl sender, Schedule[] items, bool async = true)
+        if (types.Contains(documentType) && columns.Contains(column.ColumnName))
+            return new NullEditor();
+        return base.GetEditor(item, column);
+    }
+
+    public override DynamicEditorPages LoadEditorPages(Schedule item)
+    {
+        var pages = base.LoadEditorPages(item);
+        foreach (var page in pages.ToArray())
         {
-            base.DefineLookups(sender, items, async);
+            if (page is IDynamicOneToManyGrid<Schedule, Kanban> && item.ScheduleType != ScheduleType.Task)
+                pages = new DynamicEditorPages(pages.Where(x => x != page));
+            else if (page is IDynamicOneToManyGrid<Schedule, Job> && item.ScheduleType != ScheduleType.Job)
+                pages = new DynamicEditorPages(pages.Where(x => x != page));
         }
+        return pages;
+    }
+
+    protected override void DefineLookups(ILookupEditorControl sender, Schedule[] items, bool async = true)
+    {
+        base.DefineLookups(sender, items, async);
     }
 }