|
|
@@ -3,12 +3,18 @@ using Avalonia.Controls;
|
|
|
using Avalonia.Data.Converters;
|
|
|
using Avalonia.Markup.Xaml;
|
|
|
using Avalonia.Media;
|
|
|
+using Avalonia.Threading;
|
|
|
+using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
using CommunityToolkit.Mvvm.Input;
|
|
|
using InABox.Avalonia;
|
|
|
using InABox.Avalonia.Components;
|
|
|
using InABox.Avalonia.Converters;
|
|
|
+using InABox.Clients;
|
|
|
using InABox.Core;
|
|
|
+using JetBrains.Annotations;
|
|
|
+using PRS.Avalonia.DigitalForms;
|
|
|
using System;
|
|
|
+using System.ComponentModel;
|
|
|
using System.Globalization;
|
|
|
using System.Linq;
|
|
|
using System.Threading.Tasks;
|
|
|
@@ -60,57 +66,82 @@ public class ExistingFormStatusConverter : AbstractConverter<IDigitalFormInstanc
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+public class FormsListSearchEventArgs(IDigitalFormInstanceShell shell)
|
|
|
+{
|
|
|
+ public IDigitalFormInstanceShell Shell { get; set; } = shell;
|
|
|
+}
|
|
|
+public delegate bool FormsListSearchEvent(object sender, FormsListSearchEventArgs args);
|
|
|
+
|
|
|
+// TODO: RefreshRequested, and thus RefreshData; FilterShell
|
|
|
+// FormTapped
|
|
|
+
|
|
|
public partial class FormsList : UserControl
|
|
|
{
|
|
|
public static readonly StyledProperty<bool> SeparateHistoryProperty =
|
|
|
AvaloniaProperty.Register<FormsList, bool>(nameof(SeparateHistory), true);
|
|
|
-
|
|
|
- public static readonly StyledProperty<bool> SelectionMenuVisibleProperty =
|
|
|
- AvaloniaProperty.Register<FormsList, bool>(nameof(SelectionMenuVisible), true);
|
|
|
-
|
|
|
- public string SearchText { get; set; }
|
|
|
+ public static readonly StyledProperty<string> AppliesToProperty =
|
|
|
+ AvaloniaProperty.Register<FormsList, string>(nameof(AppliesTo), "");
|
|
|
+ public static readonly StyledProperty<ICoreRepository?> ModelProperty =
|
|
|
+ AvaloniaProperty.Register<FormsList, ICoreRepository?>(nameof(Model));
|
|
|
+ public static readonly StyledProperty<ICommand?> FormClickedProperty =
|
|
|
+ AvaloniaProperty.Register<FormsList, ICommand?>(nameof(FormClicked));
|
|
|
|
|
|
public bool SeparateHistory
|
|
|
{
|
|
|
get => GetValue(SeparateHistoryProperty);
|
|
|
set => SetValue(SeparateHistoryProperty, value);
|
|
|
}
|
|
|
+ public string AppliesTo
|
|
|
+ {
|
|
|
+ get => GetValue(AppliesToProperty);
|
|
|
+ set => SetValue(AppliesToProperty, value);
|
|
|
+ }
|
|
|
|
|
|
- public bool SelectionMenuVisible
|
|
|
+ private bool SelectionMenuVisible
|
|
|
{
|
|
|
- get => GetValue(SelectionMenuVisibleProperty);
|
|
|
- set => SetValue(SelectionMenuVisibleProperty, value);
|
|
|
+ set => SelectionMenuButton.IsVisible = value;
|
|
|
}
|
|
|
|
|
|
- public static readonly StyledProperty<ICoreRepository?> ModelProperty =
|
|
|
- AvaloniaProperty.Register<FormsList, ICoreRepository?>(nameof(Model));
|
|
|
+ private bool ShowIncomplete { get; set; } = true;
|
|
|
+
|
|
|
+ public event FormsListSearchEvent? Search;
|
|
|
|
|
|
public ICoreRepository? Model
|
|
|
{
|
|
|
get => GetValue(ModelProperty);
|
|
|
set => SetValue(ModelProperty, value);
|
|
|
}
|
|
|
+
|
|
|
+ public ICommand? FormClicked
|
|
|
+ {
|
|
|
+ get => GetValue(FormClickedProperty);
|
|
|
+ set => SetValue(FormClickedProperty, value);
|
|
|
+ }
|
|
|
|
|
|
public FormsList()
|
|
|
{
|
|
|
InitializeComponent();
|
|
|
}
|
|
|
|
|
|
- [RelayCommand]
|
|
|
- private void Search()
|
|
|
+ private bool FilterShell(IShell shell)
|
|
|
{
|
|
|
+ if (shell is not IDigitalFormInstanceShell formShell) return false;
|
|
|
|
|
|
+ return (!SeparateHistory || ShowIncomplete == (formShell.Completed == DateTime.MinValue))
|
|
|
+ && (Search is null || Search.Invoke(this, new(formShell)));
|
|
|
}
|
|
|
|
|
|
- [RelayCommand]
|
|
|
- private void FormClicked(IDigitalFormInstanceShell form)
|
|
|
+ private void TabStrip_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
{
|
|
|
+ if (_tabList is null) return;
|
|
|
+ ShowIncomplete = _tabList.SelectedIndex == 0;
|
|
|
+ Model?.SelectNone();
|
|
|
+ SelectionMenuVisible = false;
|
|
|
}
|
|
|
|
|
|
[RelayCommand]
|
|
|
private void FormChecked(IDigitalFormInstanceShell form)
|
|
|
{
|
|
|
- Model?.ToggleSelection(form);
|
|
|
SelectionMenuVisible = Model?.SelectedItems.OfType<IShell>().Any() == true;
|
|
|
}
|
|
|
|
|
|
@@ -119,31 +150,77 @@ public partial class FormsList : UserControl
|
|
|
{
|
|
|
var menu = new ContextMenu();
|
|
|
AvaloniaMenuItem.LoadMenuItems([
|
|
|
- new CoreMenuItem<IImage>("Complete Forms", null, CompleteForms),
|
|
|
- new CoreMenuItem<IImage>("Re-open Forms", null, ReopenForms),
|
|
|
+ new CoreMenuItem<IImage>("Complete Forms", null, CompleteForms, () => ShowIncomplete),
|
|
|
+ new CoreMenuItem<IImage>("Re-open Forms", null, ReopenForms, () => !ShowIncomplete),
|
|
|
new CoreMenuSeparator(),
|
|
|
new CoreMenuItem<IImage>("Select All", null, SelectAll),
|
|
|
new CoreMenuItem<IImage>("Select None", null, SelectNone),
|
|
|
], menu.Items);
|
|
|
+ menu.Open(SelectionMenuButton);
|
|
|
}
|
|
|
|
|
|
- private async Task<bool> SelectNone()
|
|
|
+ private Task<bool> SelectNone()
|
|
|
{
|
|
|
- return true;
|
|
|
+ Model?.SelectNone();
|
|
|
+ return Task.FromResult(true);
|
|
|
}
|
|
|
|
|
|
- private async Task<bool> SelectAll()
|
|
|
+ private Task<bool> SelectAll()
|
|
|
{
|
|
|
- return true;
|
|
|
+ Model?.SelectAll();
|
|
|
+ return Task.FromResult(true);
|
|
|
}
|
|
|
|
|
|
private async Task<bool> ReopenForms()
|
|
|
{
|
|
|
+ if (Model is null) return true;
|
|
|
+
|
|
|
+ var shells = Model.SelectedItems.OfType<IDigitalFormInstanceShell>().ToArray();
|
|
|
+ foreach(var shell in shells)
|
|
|
+ {
|
|
|
+ shell.Completed = DateTime.MinValue;
|
|
|
+ }
|
|
|
+ await Model.SaveAsync("Re-opened on Mobile Device");
|
|
|
+ Model.SelectNone();
|
|
|
+ SelectionMenuVisible = false;
|
|
|
+ await Model.RefreshAsync(true);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
private async Task<bool> CompleteForms()
|
|
|
{
|
|
|
+ if (Model is null) return true;
|
|
|
+
|
|
|
+ var shells = Model.SelectedItems.OfType<IDigitalFormInstanceShell>().ToArray();
|
|
|
+ foreach(var shell in shells)
|
|
|
+ {
|
|
|
+ shell.Completed = DateTime.Now;
|
|
|
+ }
|
|
|
+ await Model.SaveAsync("Completed on Mobile Device");
|
|
|
+ Model.SelectNone();
|
|
|
+ SelectionMenuVisible = false;
|
|
|
+ await Model.RefreshAsync(true);
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+ public void EditForm<TParent, TParentLink, TForm>(IDigitalFormInstanceShell shell, TParent parent)
|
|
|
+ where TParent : Entity, IRemotable, IPersistent, new()
|
|
|
+ where TParentLink : EntityLink<TParent>, new()
|
|
|
+ where TForm : Entity, IRemotable, IPersistent, IDigitalFormInstance<TParentLink>, new()
|
|
|
+ {
|
|
|
+ Navigation.Navigate<DigitalFormsHostViewModel>(x =>
|
|
|
+ {
|
|
|
+ x.Configure(parent, shell.FormID, shell.ID);
|
|
|
+ x.OnSaved += () =>
|
|
|
+ {
|
|
|
+ Model?.RefreshAsync(true).ContinueWith(task =>
|
|
|
+ {
|
|
|
+ if(task.Exception is not null)
|
|
|
+ {
|
|
|
+ MobileLogging.Log(task.Exception);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|