Bläddra i källkod

avalonia: added KanbanForms screen

Kenric Nugteren 2 månader sedan
förälder
incheckning
6194e7a1b7

+ 45 - 29
PRS.Avalonia/PRS.Avalonia/Components/FormsEditor/DigitalFormsHostViewModel.cs

@@ -129,8 +129,21 @@ public partial class DigitalFormsHostViewModel<TModel, TShell, TParent, TParentL
         ProgressVisible = true;
     }
 
-    public void Configure(TParent parent, Guid formID, Entity instance)
+    private void BaseConfigure()
     {
+        Model = DigitalFormModel.CreateModel(DataAccess, Parent.GetType().Name);
+        Documents = new DigitalFormDocumentModel(DataAccess,
+            () => new Filter<DigitalFormDocument>(x => x.EntityLink.ID).IsEqualTo(FormID),
+            () => $"{nameof(DigitalFormDocument)}.{FormID}");
+    }
+
+    public void Configure(TParent parent, Guid formID, TForm instance)
+    {
+        Parent = parent;
+        FormID = formID;
+        InstanceID = instance.ID;
+        Form = instance;
+        BaseConfigure();
     }
 
     public void Configure(TParent parent, Guid formID, Guid instanceID)
@@ -139,10 +152,7 @@ public partial class DigitalFormsHostViewModel<TModel, TShell, TParent, TParentL
         FormID = formID;
         InstanceID = instanceID;
 
-        Model = DigitalFormModel.CreateModel(DataAccess, Parent.GetType().Name);
-        Documents = new DigitalFormDocumentModel(DataAccess,
-            () => new Filter<DigitalFormDocument>(x => x.EntityLink.ID).IsEqualTo(FormID),
-            () => $"{nameof(DigitalFormDocument)}.{FormID}");
+        BaseConfigure();
     }
 
     protected override async Task<TimeSpan> OnRefresh()
@@ -155,29 +165,35 @@ public partial class DigitalFormsHostViewModel<TModel, TShell, TParent, TParentL
 
         if(DataAccess.Status == ConnectionStatus.Connected)
         {
-            Parent = Client.Query(
-                new Filter<TParent>(x => x.ID).IsEqualTo(Parent.ID),
-                DFUtils.EntityColumns<TParent>(Variables))
-                .ToObjects<TParent>()
-                .First();
-            Form = Client.Query(
-                new Filter<TForm>(x => x.ID).IsEqualTo(InstanceID),
-                Columns.None<TForm>()
-                    .Add(
-                        x => x.ID,
-                        x => x.Number,
-                        x => x.FormData,
-                        x => x.Form.ID,
-                        x => x.Form.Description,
-                        x => x.Form.DescriptionExpression,
-                        x => x.FormCompleted,
-                        x => x.FormCompletedBy.ID,
-                        x => x.Created,
-                        x => x.FormStarted,
-                        x => x.FormOpen,
-                        x => x.BlobData))
-                .ToObjects<TForm>()
-                .First();
+            if(Parent.ID != Guid.Empty)
+            {
+                Parent = Client.Query(
+                    new Filter<TParent>(x => x.ID).IsEqualTo(Parent.ID),
+                    DFUtils.EntityColumns<TParent>(Variables))
+                    .ToObjects<TParent>()
+                    .First();
+            }
+            if(InstanceID != Guid.Empty)
+            {
+                Form = Client.Query(
+                    new Filter<TForm>(x => x.ID).IsEqualTo(InstanceID),
+                    Columns.None<TForm>()
+                        .Add(
+                            x => x.ID,
+                            x => x.Number,
+                            x => x.FormData,
+                            x => x.Form.ID,
+                            x => x.Form.Description,
+                            x => x.Form.DescriptionExpression,
+                            x => x.FormCompleted,
+                            x => x.FormCompletedBy.ID,
+                            x => x.Created,
+                            x => x.FormStarted,
+                            x => x.FormOpen,
+                            x => x.BlobData))
+                    .ToObjects<TForm>()
+                    .First();
+            }
             CacheManager.SaveBinary<DigitalFormCacheModel<TParent, TParentLink, TForm>>(CacheFileName, new()
             {
                 Parent = Parent,
@@ -297,7 +313,7 @@ public partial class DigitalFormsHostViewModel<TModel, TShell, TParent, TParentL
     {
         Navigation.Navigate<DigitalFormsHostViewModel<TModel, TShell, TParent, TParentLink, TForm>>(x =>
         {
-            x.Configure(parent, shell.FormID, shell.ID);
+            x.Configure(parent, shell.FormID, shell.Entity);
             x.OnSaved += () =>
             {
                 model.RefreshAsync(true).ContinueWith(task =>

+ 13 - 0
PRS.Avalonia/PRS.Avalonia/Components/SelectionView/SelectionViewModel.cs

@@ -74,6 +74,19 @@ public partial class SelectionViewModel : PopupViewModel<object?[]>, IModuleView
         PrimaryMenu.Add(new(Images.tick, Tick_Click));
     }
 
+    private void DoAddFilters(IEnumerable<string> filters)
+    {
+        foreach(var filter in filters)
+        {
+            FilterButtons.Add(new()
+            {
+                Text = filter
+            });
+        }
+    }
+    public void AddFilters(IEnumerable<string> filters) => DoAddFilters(filters);
+    public void AddFilters(params string[] filters) => DoAddFilters(filters);
+
     private Task<bool> Tick_Click()
     {
         Selected?.Invoke(_selectedItems);

+ 6 - 2
PRS.Avalonia/PRS.Avalonia/Modules/DigitalForms/FormsView.axaml

@@ -2,7 +2,11 @@
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:avComponents="using:PRS.Avalonia.Components"
+			 xmlns:local="using:PRS.Avalonia.Modules"
              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
-             x:Class="PRS.Avalonia.Modules.FormsView">
-    Welcome to Avalonia!
+             x:Class="PRS.Avalonia.Modules.FormsView"
+			 x:DataType="local:FormsViewModel">
+	<avComponents:FormsList Model="{Binding Forms}"
+							FormClicked="{Binding FormClickedCommand}"/>
 </UserControl>

+ 118 - 1
PRS.Avalonia/PRS.Avalonia/Modules/DigitalForms/FormsViewModel.cs

@@ -1,6 +1,123 @@
+using Avalonia.Controls;
+using Comal.Classes;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using DynamicData;
+using InABox.Avalonia;
+using InABox.Avalonia.Components;
+using InABox.Clients;
+using InABox.Core;
+using PRS.Avalonia.Components;
+using PRS.Avalonia.DigitalForms;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
 namespace PRS.Avalonia.Modules;
 
-public class FormsViewModel : ModuleViewModel
+public partial class FormsViewModel : ModuleViewModel
 {
     public override string Title => "Forms";
+
+    [ObservableProperty]
+    private KanbanModel _kanbans;
+
+    [ObservableProperty]
+    private KanbanFormModel _forms;
+
+    [ObservableProperty]
+    private DigitalFormModel _digitalForms;
+
+    public FormsViewModel()
+    {
+        Kanbans = new KanbanModel(DataAccess,
+            () => new Filter<Kanban>(x => x.ID).InQuery(new Filter<KanbanSubscriber>(x => x.Employee.ID).IsEqualTo(Repositories.Me.ID), x => x.Kanban.ID)
+                .And(new Filter<Kanban>(x => x.Status).IsNotEqualTo(KanbanStatus.Complete)
+                    .Or(x => x.Completed).IsGreaterThanOrEqualTo(DateTime.Today.AddDays(-7))),
+            () => DefaultCacheFileName<KanbanShell>());
+
+        Forms = new KanbanFormModel(DataAccess,
+            () => new Filter<KanbanForm>(x => x.Parent.EmployeeLink.ID).IsEqualTo(Repositories.Me.ID)
+                .And(new Filter<KanbanForm>(x => x.FormCompleted).IsEqualTo(DateTime.MinValue)
+                    .Or(x => x.FormCompleted).IsGreaterThanOrEqualTo(DateTime.Today.AddDays(-7))),
+            () => DefaultCacheFileName<KanbanFormShell>());
+
+        DigitalForms = new DigitalFormModel(DataAccess,
+            () => new Filter<DigitalForm>(x => x.ID).InQuery(new Filter<EmployeeDigitalForm>(x => x.Employee.ID).IsEqualTo(Repositories.Me.ID), x => x.Form.ID)
+                .And(x => x.Active).IsEqualTo(true),
+            () => DefaultCacheFileName<DigitalFormShell>());
+
+        PrimaryMenu.Add(new AvaloniaMenuItem(Images.plus, AddForm));
+    }
+
+    private async Task<bool> AddForm()
+    {
+        var form = (await SelectionViewModel.ExecutePopup<DigitalFormShell>(model =>
+        {
+            model.AddFilters(DigitalForms.AvailableFilters.Select(x => x.Name).NotNull());
+            model.Columns.BeginUpdate()
+                .Add(new AvaloniaDataGridTextColumn<DigitalFormShell>
+                {
+                    Column = x => x.Code,
+                    Width = GridLength.Auto
+                })
+                .Add(new AvaloniaDataGridTextColumn<DigitalFormShell>
+                {
+                    Column = x => x.Description,
+                    Width = GridLength.Star
+                })
+                .EndUpdate();
+        }, args =>
+        {
+            DigitalForms.SelectFilter(args.Filter);
+            DigitalForms.Search(x => x.AppliesTo == nameof(Kanban));
+            return DigitalForms.Refresh(args.Force);
+        }))?.FirstOrDefault();
+        if (form is null) return true;
+        
+        var kanban = Kanbans.CreateItem();
+        kanban.EmployeeID = Repositories.Me.ID;
+        kanban.ManagerID = Repositories.Me.ID;
+        kanban.Title = form.Description;
+
+        var kanbanForm = Forms.CreateItem();
+        kanbanForm.FormID = form.ID;
+        kanbanForm.FormCode = form.Code;
+        kanbanForm.FormDescription = form.Description;
+
+        DigitalFormsHostViewModel<KanbanFormModel, KanbanFormShell, Kanban, KanbanLink, KanbanForm>.EditForm(Forms, kanbanForm, kanban.Entity);
+
+        return true;
+    }
+
+    protected override async Task<TimeSpan> OnRefresh()
+    {
+        await Forms.RefreshAsync(false);
+        return TimeSpan.Zero;
+    }
+
+    [RelayCommand]
+    private async Task FormClicked(KanbanFormShell shell)
+    {
+        var kanban = Kanbans.FirstOrDefault(x => x.ID == shell.ParentID)?.Entity;
+        if(kanban is null)
+        {
+            // Need to go to the database, because this task isn't in our list.
+            ProgressVisible = true;
+
+            kanban = (await Client.QueryAsync(new Filter<Kanban>(x => x.ID).IsEqualTo(shell.ParentID), new KanbanShell().Columns.Columns))
+                .ToObjects<Kanban>().FirstOrDefault();
+
+            ProgressVisible = false;
+
+            if(kanban is null)
+            {
+                MobileLogging.Log($"ERROR: Could not find kanban with ID {shell.ParentID} for editing form.");
+                await MessageDialog.ShowMessage("Sorry, but we could not load this form.");
+                return;
+            }
+        }
+
+        DigitalFormsHostViewModel<KanbanFormModel, KanbanFormShell, Kanban, KanbanLink, KanbanForm>.EditForm(Forms, shell, kanban);
+    }
 }

+ 0 - 2
PRS.Avalonia/PRS.Avalonia/Repositories/DigitalForm/DigitalFormModel.cs

@@ -81,6 +81,4 @@ public class DigitalFormModel : CoreRepository<DigitalFormModel, DigitalFormShel
     {
         return CreateModel(host, typeof(TParent).Name);
     }
-
-
 }

+ 1 - 1
PRS.Avalonia/PRS.Avalonia/Repositories/Kanban/BaseKanbanModel.cs

@@ -11,7 +11,7 @@ public abstract class BaseKanbanModel<TModel, TShell> : CoreRepository<TModel, T
     where TShell : Shell<TModel, Kanban>, IKanbanShell, new()
 
 {
-    protected BaseKanbanModel(IModelHost host, Func<Filter<Kanban>> filter) : base(host, filter)
+    protected BaseKanbanModel(IModelHost host, Func<Filter<Kanban>> filter, Func<string>? filename = null) : base(host, filter, filename)
     {
     }
 

+ 1 - 1
PRS.Avalonia/PRS.Avalonia/Repositories/Kanban/KanbanModel.cs

@@ -7,7 +7,7 @@ namespace PRS.Avalonia;
 
 public class KanbanModel : BaseKanbanModel<KanbanModel, KanbanShell>
 {
-    public KanbanModel(IModelHost host, Func<Filter<Kanban>> filter) : base(host, filter)
+    public KanbanModel(IModelHost host, Func<Filter<Kanban>> filter, Func<string>? filename = null) : base(host, filter, filename)
     {
     }
 }

+ 1 - 1
PRS.Avalonia/PRS.Avalonia/Repositories/KanbanForm/KanbanFormModel.cs

@@ -8,7 +8,7 @@ namespace PRS.Avalonia;
 
 public class KanbanFormModel : DigitalFormInstanceModel<KanbanFormModel, KanbanFormShell, KanbanForm>
 {
-    public KanbanFormModel(IModelHost host, Func<Filter<KanbanForm>> filter) : base(host, filter)
+    public KanbanFormModel(IModelHost host, Func<Filter<KanbanForm>> filter, Func<string>? filename = null) : base(host, filter, filename)
     {
     }