Pārlūkot izejas kodu

Created Country/State/Locality lookup tables
Improved Import Screen progress display
Added [CallerMemberName] to BaseObject.InitializeField()

frankvandenbos 7 mēneši atpakaļ
vecāks
revīzija
4491da25d5

+ 222 - 2
InABox.Core/Classes/Address.cs

@@ -1,13 +1,233 @@
-namespace InABox.Core
+using System;
+using System.ComponentModel;
+using System.Linq;
+
+namespace InABox.Core
 {
+
+    public class CountryLink : EntityLink<Country>
+    {
+        [NullEditor]
+        public override Guid ID { get; set; }
+        
+        [CodeEditor(Editable=Editable.Disabled)]
+        [EditorSequence(1)]
+        public string Code { get; set; }
+        
+        [Caption("Country")]
+        [EditorSequence(2)]
+        public string Name { get; set; }
+    }
+    
+    public class Country : Entity, IRemotable, IPersistent
+    {
+        
+        [UniqueCodeEditor(Editable=Editable.Enabled)]
+        [EditorSequence(1)]
+        public string Code { get; set; }
+        
+        [Caption("Country")]
+        [EditorSequence(2)]
+        public string Name { get; set; }
+        
+        static Country()
+        {
+            DefaultColumns.Add<State>(x => x.Code, 100);
+            DefaultColumns.Add<Country>(x => x.Name, caption: "Country");
+        }
+    }
+
+    public class StateLink : EntityLink<State>
+    {
+        [LookupEditor(typeof(State))]
+        public override Guid ID { get; set; }
+
+        [NullEditor]
+        public CountryLink Country => InitializeField(ref _country);
+        private CountryLink? _country;
+        
+        [CodeEditor(Editable = Editable.Disabled)]
+        [EditorSequence(1)]
+        public string Code { get; set; }
+        
+        [Caption("State")]
+        [EditorSequence(2)]
+        public string Name { get; set; }
+    }
+    
+    public class State : Entity, IRemotable, IPersistent
+    {
+
+        [EntityRelationship(DeleteAction.Cascade)]
+        [EditorSequence(1)]
+        public CountryLink Country => InitializeField(ref _country);
+        private CountryLink? _country;
+        
+        [UniqueCodeEditor(Editable = Editable.Enabled)]
+        [EditorSequence(2)]
+        public string Code { get; set; }
+        
+        [EditorSequence(3)]
+        public string Name { get; set; }
+        
+        static State()
+        {
+            DefaultColumns.Add<State>(x => x.Code, 100);
+            DefaultColumns.Add<State>(x => x.Name, caption: "State");
+        }
+        
+    }
+
+    public class LocalityLink : EntityLink<Locality>
+    {
+        public override Guid ID { get; set; }
+        
+        [EditorSequence(1)]
+        public StateLink State => InitializeField(ref _state);
+        private StateLink? _state;
+        
+        [EditorSequence(3)]
+        public string Name { get; set; }
+        
+        [EditorSequence(4)]
+        public string PostCode { get; set; }
+    }
+
+    public class Locality : Entity, IRemotable, IPersistent
+    {
+        [EntityRelationship(DeleteAction.Cascade)]
+        [EditorSequence(1)]
+        public StateLink State => InitializeField(ref _state);
+        private StateLink? _state;
+        
+        [EditorSequence(3)]
+        public string? Name { get; set; }
+        
+        [EditorSequence(4)]
+        public string? PostCode { get; set; }
+
+        static Locality()
+        {
+            DefaultColumns.Add<Locality>(x => x.Name, caption: "Locality");
+            DefaultColumns.Add<Locality>(x => x.PostCode, 100);
+        }
+    }
+
+    public enum LocalityType
+    {
+        Country,
+        State,
+        Locality
+    }
+    
+    public interface ILocalitySummary
+    {
+        Guid ID { get; set; }
+        Guid ParentID { get; set; }
+        LocalityType Type { get; set; }
+        string CountryCode { get; set; }
+        string CountryName { get; set; }
+        string StateCode { get; set; }
+        string StateName { get; set; }
+        string LocalityCode { get; set; }
+        string LocalityName { get; set; }
+        string Name { get; set; }
+        string Code { get; set; }
+    }
+    
+    public class LocalitySummaryGenerator : AutoEntityUnionGenerator<ILocalitySummary>
+    {
+        protected override void Configure()
+        {
+            AddTable<Locality>()
+                .AliasField(x => x.ParentID, x => x.State.ID)
+                .AliasField(x =>x.CountryCode, x=>x.State.Country.Code)
+                .AliasField(x =>x.CountryName, x=>x.State.Country.Name)
+                .AliasField(x =>x.StateCode, x=>x.State.Code)
+                .AliasField(x =>x.StateName, x=>x.State.Name)
+                .AliasField(x =>x.LocalityCode, x=>x.PostCode)
+                .AliasField(x =>x.LocalityName, x=>x.Name)
+                .AliasField(x =>x.Code, x => x.PostCode)
+                .AddConstant(x=>x.Type, LocalityType.Locality);
+            
+            AddTable<State>()
+                .AliasField(x=>x.ParentID, x => x.Country.ID)
+                .AliasField(x =>x.CountryCode, x=>x.Country.Code)
+                .AliasField(x =>x.CountryName, x=>x.Country.Name)
+                .AliasField(x =>x.StateCode, x=>x.Code)
+                .AliasField(x =>x.StateName, x=>x.Name)
+                .AddConstant(x=>x.LocalityCode, "")
+                .AddConstant(x=>x.LocalityName, "")
+                .AddConstant(x=>x.Type, LocalityType.State);
+            
+            AddTable<Country>()
+                .AddConstant(x => x.ParentID, Guid.Empty)
+                .AliasField(x =>x.CountryCode, x=>x.Code)
+                .AliasField(x =>x.CountryName, x=>x.Name)
+                .AddConstant(x=>x.StateCode, "")
+                .AddConstant(x=>x.StateName, "")
+                .AddConstant(x=>x.LocalityCode, "")
+                .AddConstant(x=>x.LocalityName, "")
+                .AddConstant(x=>x.Type, LocalityType.Country);
+        }
+
+        public override bool Distinct => false;
+
+        public override Column<ILocalitySummary>[] IDColumns => Columns.None<ILocalitySummary>().Add(x => x.ID).ToArray();
+    }
+
+    
+    [AutoEntity(typeof(LocalitySummaryGenerator))]
+    public class LocalitySummary : Entity, IRemotable, IPersistent, ILocalitySummary
+    {
+        [NullEditor]
+        public Guid ParentID { get; set; }
+        
+        [NullEditor]
+        public LocalityType Type { get; set; }
+        
+        [EditorSequence(1)]
+        public string Name { get; set; }
+        
+        [EditorSequence(2)]
+        public string Code { get; set; }
+        
+        [EditorSequence(3)]
+        public string CountryCode { get; set; }
+        
+        [EditorSequence(4)]
+        public string CountryName { get; set; }
+        
+        [EditorSequence(5)]
+        public string StateCode { get; set; }
+        
+        [EditorSequence(6)]
+        public string StateName { get; set; }
+       
+        [EditorSequence(7)]
+        public string LocalityCode { get; set; }
+        
+        [EditorSequence(8)]
+        public string LocalityName { get; set; }
+
+        static LocalitySummary()
+        {
+            DefaultColumns.Add<LocalitySummary>(x=>x.Name, caption: "Locality");
+            DefaultColumns.Add<LocalitySummary>(x => x.Code, 100, "Code");
+        }
+    }
+
     public class Address : EnclosedEntity, IPersistent, IRemotable
     {
         [EditorSequence(1)]
         [MemoEditor]
         public string Street { get; set; } = "";
 
+        [EditorSequence(2)] public LocalityLink LocalityLink => InitializeField(ref _locality);
+        private LocalityLink _locality;
+        
         [EditorSequence(2)]
-        [TextBoxEditor]
+        [TextBoxEditor(Buttons = [])]
         public string City { get; set; } = "";
 
         [EditorSequence(3)]

+ 1 - 1
InABox.Core/Objects/BaseObject.cs

@@ -133,7 +133,7 @@ namespace InABox.Core
 
         private bool _disabledInterceptor;
 
-        protected T InitializeField<T>(ref T? field, string name)
+        protected T InitializeField<T>(ref T? field, [CallerMemberName] string name = "")
             where T : BaseObject, ISubObject, new()
         {
             if(field is null)

+ 17 - 15
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -78,13 +78,13 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
     private readonly DynamicRowMovementColumn? down;
     private readonly Button Edit;
     private readonly Label EditSpacer;
-    private readonly Button Export;
+    private readonly Button ExportButton;
     private readonly Label ExportSpacer;
     private readonly Button DuplicateBtn;
     private readonly Button SwitchViewBtn;
 
     private readonly Button Help;
-    private readonly Button Import;
+    private readonly Button ImportButton;
 
     private readonly Grid Layout;
     private readonly Label Loading;
@@ -275,13 +275,13 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
         ClipboardSpacer = new Label { Width = 5 };
 
-        Export = CreateButton(Wpf.Resources.doc_xls.AsBitmapImage(Color.White), "Export");
-        Export.Margin = new Thickness(0, 2, 2, 0);
-        Export.Click += Export_Click;
+        ExportButton = CreateButton(Wpf.Resources.doc_xls.AsBitmapImage(Color.White), "Export");
+        ExportButton.Margin = new Thickness(0, 2, 2, 0);
+        ExportButton.Click += ExportButtonClick;
 
-        Import = CreateButton(Wpf.Resources.doc_xls.AsBitmapImage(Color.White), "Import");
-        Import.Margin = new Thickness(0, 2, 2, 0);
-        Import.Click += Import_Click;
+        ImportButton = CreateButton(Wpf.Resources.doc_xls.AsBitmapImage(Color.White), "Import");
+        ImportButton.Margin = new Thickness(0, 2, 2, 0);
+        ImportButton.Click += ImportButton_Click;
 
         ExportSpacer = new Label { Width = 5 };
         
@@ -305,8 +305,8 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         LeftButtonStack.Children.Add(Paste);
         LeftButtonStack.Children.Add(ClipboardSpacer);
 
-        LeftButtonStack.Children.Add(Export);
-        LeftButtonStack.Children.Add(Import);
+        LeftButtonStack.Children.Add(ExportButton);
+        LeftButtonStack.Children.Add(ImportButton);
         LeftButtonStack.Children.Add(ExportSpacer);
 
         RightButtonStack = new StackPanel();
@@ -694,8 +694,8 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         Paste.Visibility = ShowSequenceButtons && Options.EditRows ? Visibility.Visible : Visibility.Collapsed;
         ClipboardSpacer.Visibility = ShowSequenceButtons && Options.EditRows ? Visibility.Visible : Visibility.Collapsed;
 
-        Export.Visibility = Options.ExportData ? Visibility.Visible : Visibility.Collapsed;
-        Import.Visibility = Options.ImportData ? Visibility.Visible : Visibility.Collapsed;
+        ExportButton.Visibility = Options.ExportData ? Visibility.Visible : Visibility.Collapsed;
+        ImportButton.Visibility = Options.ImportData ? Visibility.Visible : Visibility.Collapsed;
         ExportSpacer.Visibility = Options.ExportData || Options.ImportData
             ? Visibility.Visible
             : Visibility.Collapsed;
@@ -2258,11 +2258,13 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         Refresh(false, true);
     }
 
-    private void Import_Click(object sender, RoutedEventArgs e)
+    private void ImportButton_Click(object sender, RoutedEventArgs e)
     {
         DoImport();
     }
 
+    public void Import() => DoImport();
+
     protected virtual void CustomiseExportColumns(List<string> columnnames)
     {
     }
@@ -2377,7 +2379,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         });
     }
 
-    private void Export_Click(object sender, RoutedEventArgs e)
+    private void ExportButtonClick(object sender, RoutedEventArgs e)
     {
         DoExport();
     }
@@ -2471,7 +2473,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
             return true;
         /*if (MultiEdit.Visibility != Visibility.Collapsed)
             return true;*/
-        if (Export.Visibility != Visibility.Collapsed)
+        if (ExportButton.Visibility != Visibility.Collapsed)
             return true;
         return false;
     }

+ 32 - 31
inabox.wpf/DynamicGrid/DynamicImportGrid.cs

@@ -206,47 +206,48 @@ namespace InABox.DynamicGrid
                     iimporter.OnLoad += OnLoad;
                     iimporter.OnSave += OnSave;
 
-                    Progress.Show("Importing Data");
-
-                    using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read);
-                    Progress.SetMessage("Opening File");
-                    if (iimporter.Open(stream))
+                    string result = null;
+                    bool bSuccess = false;
+                    var LogFile = Path.ChangeExtension(filename, ".log");
+                    
+                    Progress.ShowModal("Importing Data", (progress) =>
                     {
-                        if (iimporter.ReadHeader())
+                        iimporter.OnNotify += (o, msg) => progress.Report(msg);
+                        using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read);
+                        Progress.SetMessage("Opening File");
+                        if (iimporter.Open(stream))
                         {
-                            var mismatches = iimporter.Mappings.Where(x =>
-                                !string.IsNullOrWhiteSpace(x.Field) &&
-                                !iimporter.Fields.Contains(x.Field)
-                            ).Select(x => x.Field).ToArray();
-                            if (!mismatches.Any())
+                            if (iimporter.ReadHeader())
                             {
-                                var imported = iimporter.Import();
-                                Progress.Close();
-                                MessageBox.Show(string.Format("Imported {0} records!", imported));
-                                var LogFile = Path.ChangeExtension(filename, ".log");
-                                File.AppendAllLines(LogFile, iimporter.Log.ToArray());
-                                Process.Start(new ProcessStartInfo(LogFile) { UseShellExecute = true });
+                                var mismatches = iimporter.Mappings.Where(x =>
+                                    !string.IsNullOrWhiteSpace(x.Field) &&
+                                    !iimporter.Fields.Contains(x.Field)
+                                ).Select(x => x.Field).ToArray();
+                                if (!mismatches.Any())
+                                {
+                                    var imported = iimporter.Import();
+                                    File.AppendAllLines(LogFile, iimporter.Log.ToArray());
+                                    result = $"Imported {imported} records!";
+                                    bSuccess = true;
+                                }
+                                else
+                                {
+                                    result = "Import Mappings do not match file headers!\n\n- " + string.Join("\n- ", mismatches);
+                                }
                             }
                             else
                             {
-                                Progress.Close();
-                                MessageBox.Show("Import Mappings do not match file headers!\n\n- " + string.Join("\n- ", mismatches),
-                                    "Import Failed");
+                                result = $"Unable to Read Headers from {Path.GetFileName(filename)}";
                             }
                         }
                         else
-                        {
-                            Progress.Close();
-                            MessageBox.Show("Unable to Read Headers from {0}", Path.GetFileName(filename));
-                        }
-                    }
-                    else
-                    {
-                        Progress.Close();
-                        MessageBox.Show("Unable to Open {0}", Path.GetFileName(filename));
-                    }
+                            result = $"Unable to Open {Path.GetFileName(filename)}";
 
-                    iimporter.Close();
+                        iimporter.Close();
+                    });
+                    MessageBox.Show(result, (bSuccess ? "Success" : "Error"));
+                    if (File.Exists(LogFile))
+                        Process.Start(new ProcessStartInfo(LogFile) { UseShellExecute = true });
                 }
             }