123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Diagnostics.CodeAnalysis;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Windows;
- using System.Windows.Controls;
- using InABox.Clients;
- using InABox.Core;
- using InABox.Wpf;
- using InABox.Wpf.Reports;
- using InABox.WPF;
- namespace InABox.DynamicGrid;
- public class DynamicFormEditButton : INotifyPropertyChanged
- {
- public delegate void DynamicFormEditButtonDelegate(DynamicFormEditWindow window, DynamicFormEditButton button);
- private object? _content;
- public object? Content
- {
- get => _content;
- set
- {
- _content = value;
- OnPropertyChanged();
- }
- }
- public DynamicFormEditButtonDelegate Action { get; set; }
- public DynamicFormEditButton(object? content, DynamicFormEditButtonDelegate action)
- {
- Content = content;
- Action = action;
- }
- public event PropertyChangedEventHandler? PropertyChanged;
- protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- /// <summary>
- /// Interaction logic for FormDesigner.xaml
- /// </summary>
- public partial class DynamicFormEditWindow : Window, IDynamicFormWindow
- {
- public delegate void CustomiseDynamicFormEditWindow(DynamicFormEditWindow window);
- public enum FormResult
- {
- None,
- Cancel,
- Save,
- Complete
- }
- public DynamicFormEditWindow()
- {
- InitializeComponent();
- Grid.OnChanged += Grid_OnChanged;
- //Complete.IsEnabled = Security.IsAllowed<CanChangeDigitalFormCompletion>();
- }
- public DynamicFormDesignGrid Grid => Preview;
- public FormMode Mode
- {
- get => Grid.Mode;
- private set => Grid.Mode = value;
- }
- public FormResult Result = FormResult.None;
- public IDigitalFormDataModel? DataModel
- {
- get => Grid.DataModel;
- set
- {
- Grid.DataModel = value;
- RefreshEnabled();
- }
- }
- public ObservableCollection<DynamicFormEditButton> CustomButtons { get; set; } = new ObservableCollection<DynamicFormEditButton>();
- private bool IsReopening = false;
- private bool HasChanged = false;
- private bool HasUnsavedChanges => Grid.IsChanged || HasChanged || DataModel!.Instance.ID == Guid.Empty;
- private DFLayoutType _type;
- public DFLayoutType Type
- {
- get => _type;
- set
- {
- _type = value;
- Width = _type == DFLayoutType.Mobile ? 600 : 1000;
- Height = 800;
- }
- }
- public DFSaveStorage SaveValues() => Grid.SaveValues();
- public void LoadValues(DFLoadStorage storage)
- {
- Grid.LoadValues(storage);
- RefreshEnabled();
- }
- private void RefreshEnabled()
- {
- var formInstance = DataModel!.Instance;
- var completed = formInstance.FormCompleted;
- CompletedDate.Content = !completed.IsEmpty() ? $"Completed {completed:d MMM yyyy} at {completed:hh:mm tt}" : "Not completed yet";
- if (completed.IsEmpty()
- && DFUtils.CanEditForm(formInstance.GetType(), formInstance, DataModel.Entity))
- {
- Mode = FormMode.Filling;
- }
- else
- {
- Mode = Security.IsAllowed<CanEditCompletedForms>()
- ? FormMode.Editing
- : FormMode.ReadOnly;
- }
- if (Mode == FormMode.Editing || Mode == FormMode.Filling || Mode == FormMode.Preview)
- {
- SaveForm.IsEnabled = HasUnsavedChanges;
- if(Mode == FormMode.Editing)
- {
- SaveForm.Content = "Save Form";
- }
- else
- {
- SaveForm.Content = "Save Progress";
- }
- }
- else
- {
- if (Security.IsAllowed<CanChangeDigitalFormCompletion>())
- {
- SaveForm.IsEnabled = HasUnsavedChanges;
- SaveForm.Content = "Save Form";
- }
- else
- {
- SaveForm.IsEnabled = false;
- SaveForm.Content = "Save Progress";
- }
- }
- if (!completed.IsEmpty() && Security.IsAllowed<CanChangeDigitalFormCompletion>())
- {
- CompleteForm.Content = "Re-open form";
- CompleteForm.IsEnabled = true;
- IsReopening = true;
- }
- else
- {
- CompleteForm.Content = "Complete form";
- CompleteForm.IsEnabled = (Mode == FormMode.Filling || Security.IsAllowed<CanChangeDigitalFormCompletion>()) && DataModel?.Instance.FormCompleted == DateTime.MinValue;
- IsReopening = false;
- }
- }
- private void Grid_OnChanged(DynamicFormDesignGrid sender, string fieldName)
- {
- if (Mode == FormMode.Editing || Mode == FormMode.Filling || Mode == FormMode.Preview)
- {
- SaveForm.IsEnabled = true;
- }
- }
- protected override void OnClosing(CancelEventArgs e)
- {
- if (DialogResult == null)
- {
- Result = FormResult.Cancel;
- DialogResult = false;
- }
- base.OnClosing(e);
- }
- private void Complete()
- {
- if (!Grid.Validate(out var messages))
- {
- MessageBox.Show(string.Join('\n', messages));
- return;
- }
- if (MessageBox.Show("Are you sure you want to complete this form?", "Confirm Completion", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
- {
- Result = FormResult.Complete;
- DialogResult = true;
- }
- }
- private void Reopen()
- {
- HasChanged = true;
- DataModel!.Instance.FormCompleted = DateTime.MinValue;
- DataModel!.Instance.FormCompletedBy.Clear();
- RefreshEnabled();
- }
- private void CompleteForm_Click(object sender, RoutedEventArgs e)
- {
- if (IsReopening)
- Reopen();
- else
- Complete();
- }
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- if (sender is not Button btn || btn.Tag is not DynamicFormEditButton button) return;
- button.Action(this, button);
- }
- private DataModel? GetReportDataModel()
- {
- var dataModel = DataModel;
- if (dataModel is null) return null;
- var formType = dataModel.Instance.GetType();
- var filter = Filter.Create<Entity>(formType, x => x.ID).IsEqualTo(dataModel.Instance.ID);
- return (Activator.CreateInstance(typeof(DigitalFormReportDataModel<>)!
- .MakeGenericType(formType), new object?[] { filter, dataModel.Instance.Form.ID }) as DataModel)!;
- }
- private void PrintForm_Click(object sender, RoutedEventArgs e)
- {
- var model = GetReportDataModel();
- var dataModel = DataModel;
- if (model is null || dataModel is null) return;
- (model as IDigitalFormReportDataModel)!.AddFormData(dataModel.Instance.ID, SaveValues().ToLoadStorage());
- var menu = new ContextMenu();
- ReportUtils.PopulateMenu(menu, dataModel.Instance.Form.ID.ToString(), model, false);
- if(menu.Items.Count == 0)
- {
- menu.AddItem("No reports", null, null, enabled: false);
- }
- menu.IsOpen = true;
- }
- private void SaveForm_Click(object sender, RoutedEventArgs e)
- {
- if (DataModel?.Instance.FormCompleted.IsEmpty() == false && !Grid.Validate(out var messages))
- {
- MessageBox.Show(string.Join('\n', messages));
- return;
- }
- if (MessageBox.Show("Are you sure you want to save this form?", "Confirm Save", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
- {
- Result = FormResult.Save;
- DialogResult = true;
- }
- }
- public static Columns<TForm> FormColumns<TForm>() where TForm : IDigitalFormInstance
- {
- return (FormColumns(typeof(TForm)) as Columns<TForm>)!;
- }
- public static IColumns FormColumns(Type TForm)
- {
- return Columns.Create<IDigitalFormInstance>(TForm, ColumnTypeFlags.None)
- .Add<IDigitalFormInstance>(x => x.ID)
- .Add<IDigitalFormInstance>(x=>x.Number)
- .Add<IDigitalFormInstance>(x=>x.Description)
- .Add<IDigitalFormInstance>(x => x.FormCompleted)
- .Add<IDigitalFormInstance>(x => x.FormData)
- .Add<IDigitalFormInstance>(x => x.BlobData)
- .Add<IDigitalFormInstance>(x => x.Form.ID)
- .Add<IDigitalFormInstance>(x => x.Form.Description)
- .Add<IDigitalFormInstance>(x => x.Form.DescriptionExpression)
- .Add("Parent.ID");
- }
- public static bool EditDigitalForm(
- IDigitalFormInstance formInstance,
- [NotNullWhen(true)] out IDigitalFormDataModel? dataModel,
- Entity? parent = null,
- CustomiseDynamicFormEditWindow? customise = null)
- {
- dataModel = null;
- DigitalFormLayout layout = null;
- DigitalFormVariable[] variables = null;
- DFLoadStorage? values = null;
- String error = "";
- Progress.ShowModal("Loading Form", (progress) =>
- {
- var formid = formInstance.Form.ID;
- values = DigitalForm.DeserializeFormData(formInstance);
- var results = Client.QueryMultiple(
- new KeyedQueryDef<DigitalFormVariable>(new Filter<DigitalFormVariable>(x => x.Form.ID).IsEqualTo(formid)),
- new KeyedQueryDef<DigitalFormLayout>(
- new Filter<DigitalFormLayout>(x => x.Form.ID).IsEqualTo(formid)
- .And(x => x.Active).IsEqualTo(true)
- .And(x => x.Layout).IsNotEqualTo("")));
- variables = results[nameof(DigitalFormVariable)].Rows.Select(x => x.ToObject<DigitalFormVariable>()).ToArray();
- var desktopLayout = results[nameof(DigitalFormLayout)]
- .Rows.FirstOrDefault(x => x.Get<DigitalFormLayout, DFLayoutType>(x => x.Type) == DFLayoutType.Desktop)
- ?.ToObject<DigitalFormLayout>();
- layout = desktopLayout ?? results[nameof(DigitalFormLayout)].ToObjects<DigitalFormLayout>().FirstOrDefault();
- if (layout != null)
- {
- if (parent is null)
- {
- var parentlink = CoreUtils.HasProperty(formInstance.GetType(), "Parent")
- ? CoreUtils.GetPropertyValue(formInstance, "Parent") as IEntityLink
- : null;
- var parenttype = parentlink?.GetType().BaseType?.GetGenericArguments().FirstOrDefault();
- if (parenttype != null && parentlink != null)
- {
- var parentid = parentlink.ID;
- var filter = Filter.Create(parenttype);
- filter.Expression = CoreUtils.GetMemberExpression(parenttype, "ID");
- filter.Operator = Operator.IsEqualTo;
- filter.Value = parentid;
- var client = (Activator.CreateInstance(typeof(Client<>).MakeGenericType(parenttype)) as Client)!;
- parent = client.Query(filter, null, null).Rows.FirstOrDefault()?.ToObject(parenttype) as Entity;
- }
- if (parent == null)
- {
- Logger.Send(LogType.Error, "",
- $"Form parent is null; Form Type: {formInstance.GetType()}; Parent Type: {parenttype}; Form ID: {formInstance.ID}");
- error = "An error occurred while loading the form: Form Entity is null";
- }
- }
- }
- else
- error = "No layout found for form!";
- });
- if (!String.IsNullOrWhiteSpace(error))
- {
- MessageBox.Show(error);
- return false;
- }
- var form = new DynamicFormEditWindow
- {
- Type = layout.Type,
- Title = string.Format("Viewing {0}", formInstance.Form.Description)
- };
- form.LoadLayout(layout, variables);
- try
- {
- dataModel = formInstance.CreateDataModel(parent!);
- dataModel.Variables = variables;
- dataModel.OnModelSaved += (model) =>
- {
- DFUtils.OnSave(formInstance.GetType(), formInstance, parent!);
- };
- form.DataModel = dataModel;
- }
- catch (Exception e)
- {
- Logger.Send(LogType.Error, ClientFactory.UserID, $"Error during Edit Form / CreateDataModel: {CoreUtils.FormatException(e)}");
- }
- form.Initialize();
- if (values is not null)
- form.LoadValues(values);
- customise?.Invoke(form);
- if (form.ShowDialog() == true)
- {
- if (form.Result == FormResult.Complete)
- {
- formInstance.FormCompleted = DateTime.Now;
- formInstance.FormCompletedBy.ID = ClientFactory.UserGuid;
- formInstance.FormCompletedBy.UserID = ClientFactory.UserID;
- /*formInstance.FormCompleted = form.Completed
- ? formInstance.FormCompleted.IsEmpty()
- ? DateTime.Now
- : formInstance.FormCompleted
- : DateTime.MinValue;
- formInstance.FormCompletedBy.ID = form.Completed
- ? !formInstance.FormCompletedBy.IsValid()
- ? ClientFactory.UserGuid
- : formInstance.FormCompletedBy.ID
- : Guid.Empty;
- formInstance.FormCompletedBy.UserID = form.Completed
- ? string.IsNullOrWhiteSpace(formInstance.FormCompletedBy.UserID)
- ? ClientFactory.UserID
- : formInstance.FormCompletedBy.UserID
- : "";*/
- }
- DigitalForm.SerializeFormData(formInstance, variables, form.SaveValues());
- }
- return form.Result == FormResult.Save || form.Result == FormResult.Complete;
- }
- public static bool EditDigitalForm<TForm>(Guid formID, [NotNullWhen(true)] out IDigitalFormDataModel? dataModel)
- where TForm : Entity, IDigitalFormInstance, IRemotable, IPersistent, new()
- {
- var form = (new Client<TForm>()
- .Query(
- new Filter<TForm>(x => x.ID).IsEqualTo(formID),
- FormColumns<TForm>())
- .Rows.FirstOrDefault()?.ToObject<TForm>())
- ?? throw new Exception($"{typeof(TForm)} {formID} does not exist");
- return EditDigitalForm(form, out dataModel);
- }
- private void DynamicFormWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
- {
- if (DialogResult != true && HasUnsavedChanges)
- {
- if (MessageBox.Show("This form has unsaved changes. Do you wish to discard them?", "Discard Changes?", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
- {
- e.Cancel = true;
- }
- }
- }
- }
|