From 7ab70c208711cdd742f393dc70100ba15b76eb3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Thu, 3 Aug 2023 09:45:44 -0400 Subject: [PATCH 001/312] Added permission to Android manifest for location. Android database is now saved in sqlite and gpkg in windows. --- GSCFieldApp/GSCFieldApp.csproj | 7 +++++++ .../Platforms/Android/AndroidManifest.xml | 6 ++++++ GSCFieldApp/Platforms/Android/Linker.xml | 19 ++++++++++++++++++ GSCFieldApp/Platforms/iOS/Linker.xml | 20 +++++++++++++++++++ GSCFieldApp/Services/Database/DataAccess.cs | 11 ++++++++-- GSCFieldApp/ViewModel/FieldBookViewModel.cs | 9 +++++++-- 6 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 GSCFieldApp/Platforms/Android/Linker.xml create mode 100644 GSCFieldApp/Platforms/iOS/Linker.xml diff --git a/GSCFieldApp/GSCFieldApp.csproj b/GSCFieldApp/GSCFieldApp.csproj index 5008a61d..bd893d2c 100644 --- a/GSCFieldApp/GSCFieldApp.csproj +++ b/GSCFieldApp/GSCFieldApp.csproj @@ -98,12 +98,19 @@ + + + + + + + diff --git a/GSCFieldApp/Platforms/Android/AndroidManifest.xml b/GSCFieldApp/Platforms/Android/AndroidManifest.xml index de770fa8..990aaa49 100644 --- a/GSCFieldApp/Platforms/Android/AndroidManifest.xml +++ b/GSCFieldApp/Platforms/Android/AndroidManifest.xml @@ -1,5 +1,11 @@  + + + + + + \ No newline at end of file diff --git a/GSCFieldApp/Platforms/Android/Linker.xml b/GSCFieldApp/Platforms/Android/Linker.xml new file mode 100644 index 00000000..3fd5e26d --- /dev/null +++ b/GSCFieldApp/Platforms/Android/Linker.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GSCFieldApp/Platforms/iOS/Linker.xml b/GSCFieldApp/Platforms/iOS/Linker.xml new file mode 100644 index 00000000..4ffe9db3 --- /dev/null +++ b/GSCFieldApp/Platforms/iOS/Linker.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GSCFieldApp/Services/Database/DataAccess.cs b/GSCFieldApp/Services/Database/DataAccess.cs index d8b51089..c619b5d3 100644 --- a/GSCFieldApp/Services/Database/DataAccess.cs +++ b/GSCFieldApp/Services/Database/DataAccess.cs @@ -11,14 +11,21 @@ using BruTile.Wmts.Generated; using GSCFieldApp.Themes; -// Based on code sample from: http://blogs.u2u.be/diederik/post/2015/09/08/Using-SQLite-on-the-Universal-Windows-Platform.aspx -Kaz namespace GSCFieldApp.Services.DatabaseServices { public class DataAccess { public static SQLiteAsyncConnection _dbConnection; - public const string DatabaseFilename = DatabaseLiterals.DBName + DatabaseLiterals.DBTypeSqlite; + //TODO: find why on android .gpkg isn't a valid file type even though the database is sqlite. + +#if WINDOWS + public const string DatabaseFilename = DatabaseLiterals.DBName + DatabaseLiterals.DBTypeSqlite; +#elif ANDROID + public const string DatabaseFilename = DatabaseLiterals.DBName + DatabaseLiterals.DBTypeSqliteDeprecated; +#else + public const string DatabaseFilename = DatabaseLiterals.DBName + DatabaseLiterals.DBTypeSqliteDeprecated; +#endif /// /// Default database patch in the app directory. /// Will be saved as another name once the field book is properly filled and then created. diff --git a/GSCFieldApp/ViewModel/FieldBookViewModel.cs b/GSCFieldApp/ViewModel/FieldBookViewModel.cs index 31ce2852..593a4a0c 100644 --- a/GSCFieldApp/ViewModel/FieldBookViewModel.cs +++ b/GSCFieldApp/ViewModel/FieldBookViewModel.cs @@ -55,8 +55,13 @@ async Task ValidateAndSave() if (Model.isValid || !Model.isValid) { //Make sure current field book database exists +#if WINDOWS da.PreferedDatabasePath = Path.Combine(FileSystem.Current.AppDataDirectory, Model.FieldBookFileName + DatabaseLiterals.DBTypeSqlite); - +#elif ANDROID + da.PreferedDatabasePath = Path.Combine(FileSystem.Current.AppDataDirectory, Model.FieldBookFileName + DatabaseLiterals.DBTypeSqliteDeprecated); +#else + da.PreferedDatabasePath = Path.Combine(FileSystem.Current.AppDataDirectory, Model.FieldBookFileName + DatabaseLiterals.DBTypeSqlite); +#endif //Validate if new entry or update if (model.MetaID > 0) { @@ -96,7 +101,7 @@ async Task Back() await Shell.Current.GoToAsync(".."); } - #endregion +#endregion #region METHODS From 827597aaa72101f337034c7b7b811522a1a8a22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Thu, 3 Aug 2023 13:52:15 -0400 Subject: [PATCH 002/312] Added permission to android manifest and center boxes in fieldbook page on android. --- GSCFieldApp/GSCFieldApp.csproj | 4 ++++ GSCFieldApp/Platforms/Android/AndroidManifest.xml | 1 + GSCFieldApp/Views/FieldBookPage.xaml | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/GSCFieldApp/GSCFieldApp.csproj b/GSCFieldApp/GSCFieldApp.csproj index bd893d2c..8e39aa6f 100644 --- a/GSCFieldApp/GSCFieldApp.csproj +++ b/GSCFieldApp/GSCFieldApp.csproj @@ -44,12 +44,16 @@ False True AAF30D8B-9110-4473-B55B-2C0203C02F92 + False + link False True AAF30D8B-9110-4473-B55B-2C0203C02F92 + link + False diff --git a/GSCFieldApp/Platforms/Android/AndroidManifest.xml b/GSCFieldApp/Platforms/Android/AndroidManifest.xml index 990aaa49..9d20de6c 100644 --- a/GSCFieldApp/Platforms/Android/AndroidManifest.xml +++ b/GSCFieldApp/Platforms/Android/AndroidManifest.xml @@ -7,5 +7,6 @@ + \ No newline at end of file diff --git a/GSCFieldApp/Views/FieldBookPage.xaml b/GSCFieldApp/Views/FieldBookPage.xaml index b4110196..9612948f 100644 --- a/GSCFieldApp/Views/FieldBookPage.xaml +++ b/GSCFieldApp/Views/FieldBookPage.xaml @@ -22,7 +22,7 @@ - + From 9885531fcf023de02d38f605d14e6da8f5d9a77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Thu, 3 Aug 2023 16:47:06 -0400 Subject: [PATCH 003/312] Changed the way the database is saved. Didn't work in Android. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f39853e4..2dc0267a 100644 --- a/.gitignore +++ b/.gitignore @@ -363,4 +363,5 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd +/GSCFieldApp/DevelopmentNotes.md From 073e807015fffd2ffd3b216413e33800a8f3297f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Thu, 3 Aug 2023 16:48:50 -0400 Subject: [PATCH 004/312] Same as last commit. --- GSCFieldApp/Services/Database/DataAccess.cs | 33 ++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/GSCFieldApp/Services/Database/DataAccess.cs b/GSCFieldApp/Services/Database/DataAccess.cs index c619b5d3..f596184d 100644 --- a/GSCFieldApp/Services/Database/DataAccess.cs +++ b/GSCFieldApp/Services/Database/DataAccess.cs @@ -24,7 +24,7 @@ public class DataAccess #elif ANDROID public const string DatabaseFilename = DatabaseLiterals.DBName + DatabaseLiterals.DBTypeSqliteDeprecated; #else - public const string DatabaseFilename = DatabaseLiterals.DBName + DatabaseLiterals.DBTypeSqliteDeprecated; + public const string DatabaseFilename = DatabaseLiterals.DBName + DatabaseLiterals.DBTypeSqlite; #endif /// /// Default database patch in the app directory. @@ -104,32 +104,45 @@ public async Task CreateDatabaseFromResource(string outputDatabasePath) //Need a binary write for geopackage database, else file will be corrupt with //default stream writer/reader - byte[] buffer = new byte[1024]; + byte[] buffer = new byte[16*1024]; using (BinaryWriter fileWriter = new BinaryWriter(outputStream)) { using (BinaryReader fileReader = new BinaryReader(package)) { + //NOTE: On android length isn't a property so we need to count the bytes instead + //https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/storage/file-system-helpers?view=net-maui-7.0&tabs=android#platform-differences + //Read package by block of 1024 bytes. - long readCount = 0; - while (readCount < fileReader.BaseStream.Length) - { - int read = fileReader.Read(buffer, 0, buffer.Length); - readCount += read; + int readCount = 0; + //while (readCount < fileReader.BaseStream.Length) + //{ + // int read = fileReader.Read(buffer, 0, buffer.Length); + // readCount += read; + + // //Write + // fileWriter.Write(buffer, 0, read); + //} - //Write - fileWriter.Write(buffer, 0, read); + while ((readCount = fileReader.BaseStream.Read(buffer, 0, buffer.Length)) > 0) + { + fileWriter.Write(buffer, 0, readCount); } + } } } - + else + { + await Shell.Current.DisplayAlert("Info", "File already exists" + outputDatabasePath, "Ok"); + } return true; } catch (Exception e) { Debug.Write(e.Message); + await Shell.Current.DisplayAlert("Error", e.Message, "Ok"); return false; } From 03f148896bb03868d75baf4043ae7959e2b8b131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Fri, 4 Aug 2023 09:56:08 -0400 Subject: [PATCH 005/312] Better UI management in fieldbooks on android. --- GSCFieldApp/Resources/Styles/Styles.xaml | 1 + GSCFieldApp/Views/FieldBooksPage.xaml | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index c0517843..2069d6da 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -168,6 +168,7 @@ + - + @@ -131,12 +131,10 @@ BindableLayout.ItemsSource="{Binding FieldbookCollection, Mode=TwoWay}"> --> - - - - + From 95cc0b15d4386248769420eb5adfdbb860d34d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Fri, 4 Aug 2023 10:07:18 -0400 Subject: [PATCH 006/312] Forms flexlayout custom style and some clean up. --- GSCFieldApp/Resources/Styles/Styles.xaml | 9 +++++++++ GSCFieldApp/Services/Database/DataAccess.cs | 13 +------------ GSCFieldApp/Views/FieldBookPage.xaml | 2 +- GSCFieldApp/Views/StationPage.xaml | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index 2069d6da..afe20196 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -125,6 +125,15 @@ + + @@ -151,9 +151,9 @@ - + - + @@ -171,12 +171,12 @@ diff --git a/GSCFieldApp/Views/FieldBooksPage.xaml b/GSCFieldApp/Views/FieldBooksPage.xaml index 8adcd062..c1ae8c6d 100644 --- a/GSCFieldApp/Views/FieldBooksPage.xaml +++ b/GSCFieldApp/Views/FieldBooksPage.xaml @@ -131,10 +131,12 @@ BindableLayout.ItemsSource="{Binding FieldbookCollection, Mode=TwoWay}"> --> - + ItemsSource="{Binding FieldbookCollection,Mode=TwoWay}" + SelectionMode="Single" ItemsLayout="{OnPlatform HorizontalList, Android=VerticalList}" + HeightRequest="{OnPlatform WinUI=380}" WidthRequest="{OnPlatform Android=380}"> diff --git a/GSCFieldApp/Views/StationPage.xaml b/GSCFieldApp/Views/StationPage.xaml index 64e39246..1c3cc546 100644 --- a/GSCFieldApp/Views/StationPage.xaml +++ b/GSCFieldApp/Views/StationPage.xaml @@ -77,10 +77,10 @@ SelectedIndex="{Binding StationOutcropQuality.cboxDefaultItemIndex, Mode=TwoWay}" /> - + x:Name="QualityCollectionView" + ItemTemplate="{StaticResource ConcatenatedValueTemplate}" + ItemsSource="{Binding QualityCollection, Mode=TwoWay}"/> + From 20cf06fdea503d1d08c80eb21315e422dbf83de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Mon, 7 Aug 2023 16:12:18 -0400 Subject: [PATCH 012/312] Make location point save available again in Windows. Fails on android though. --- GSCFieldApp/GSCFieldApp.csproj | 1 + GSCFieldApp/Resources/Styles/Styles.xaml | 4 +- .../Services/Database/GeopackageService.cs | 83 ++++++++++--------- 3 files changed, 46 insertions(+), 42 deletions(-) diff --git a/GSCFieldApp/GSCFieldApp.csproj b/GSCFieldApp/GSCFieldApp.csproj index 8e39aa6f..2447578b 100644 --- a/GSCFieldApp/GSCFieldApp.csproj +++ b/GSCFieldApp/GSCFieldApp.csproj @@ -136,6 +136,7 @@ + diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index a8438c90..441b2035 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -128,7 +128,7 @@ + + + + + + @@ -186,7 +186,7 @@ @@ -192,6 +191,10 @@ + + + diff --git a/GSCFieldApp/Views/StationPage.xaml b/GSCFieldApp/Views/StationPage.xaml index 4a27cf2e..72db1073 100644 --- a/GSCFieldApp/Views/StationPage.xaml +++ b/GSCFieldApp/Views/StationPage.xaml @@ -95,7 +95,7 @@ ItemDisplayBinding="{Binding itemName}" SelectedItem="{Binding SelectedStationOutcropQuality}" SelectedIndex="{Binding StationOutcropQuality.cboxDefaultItemIndex, Mode=TwoWay}" /> - From 4eb69efaef9487cb278aac076bfeacbfbcaa0749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Thu, 23 Nov 2023 09:44:06 -0500 Subject: [PATCH 068/312] Some fiddling with station form UI. --- GSCFieldApp/Resources/Styles/Styles.xaml | 6 +++--- GSCFieldApp/Views/StationPage.xaml | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index 197f3151..1a5eb29e 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -45,7 +45,7 @@ - + @@ -234,12 +234,12 @@ diff --git a/GSCFieldApp/Views/StationPage.xaml b/GSCFieldApp/Views/StationPage.xaml index 72db1073..f1bc54a4 100644 --- a/GSCFieldApp/Views/StationPage.xaml +++ b/GSCFieldApp/Views/StationPage.xaml @@ -95,10 +95,13 @@ ItemDisplayBinding="{Binding itemName}" SelectedItem="{Binding SelectedStationOutcropQuality}" SelectedIndex="{Binding StationOutcropQuality.cboxDefaultItemIndex, Mode=TwoWay}" /> - + + + From aff8a352453de2b9e4c1ce44404b3e00774ed3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Thu, 23 Nov 2023 10:53:08 -0500 Subject: [PATCH 069/312] Extra station fidgetting. --- .../Strings/LocalizableStrings.Designer.cs | 18 ++++++++++++++++++ .../Strings/LocalizableStrings.fr-CA.resx | 6 ++++++ .../Resources/Strings/LocalizableStrings.resx | 6 ++++++ GSCFieldApp/Resources/Styles/Styles.xaml | 8 +++++--- GSCFieldApp/Views/StationPage.xaml | 4 +++- 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs index 7252fbe2..c49f177b 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs @@ -492,6 +492,24 @@ internal static string StationPageGeneralTravNo { } } + /// + /// Looks up a localized string similar to Current. + /// + internal static string StationPageNotesCurrent { + get { + return ResourceManager.GetString("StationPageNotesCurrent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Since Last Station. + /// + internal static string StationPageNotesSLS { + get { + return ResourceManager.GetString("StationPageNotesSLS", resourceCulture); + } + } + /// /// Looks up a localized string similar to Quality. /// diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx index 1f050084..77102703 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx @@ -261,6 +261,12 @@ Traverse + + Station actuelle + + + Depuis dernière station + Qualité diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx index a4fac9bf..b83bc248 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx @@ -261,6 +261,12 @@ Traverse # + + Current + + + Since Last Station + Quality diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index 1a5eb29e..98a6e578 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -203,7 +203,7 @@ - + - + From cf3a6ec371bd6d074f325906a54a635015da6407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Mon, 27 Nov 2023 17:25:15 -0500 Subject: [PATCH 071/312] testing double search bars for earth mats lithos. --- .../Strings/LocalizableStrings.Designer.cs | 36 +++ .../Strings/LocalizableStrings.fr-CA.resx | 12 + .../Resources/Strings/LocalizableStrings.resx | 12 + GSCFieldApp/Resources/Styles/Styles.xaml | 14 ++ GSCFieldApp/Services/Database/DataAccess.cs | 3 +- GSCFieldApp/ViewModel/EarthmatViewModel.cs | 222 +++++++++++++++++- GSCFieldApp/Views/EarthmatPage.xaml | 36 +++ GSCFieldApp/Views/EarthmatPage.xaml.cs | 31 +++ 8 files changed, 363 insertions(+), 3 deletions(-) diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs index c49f177b..688263d1 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs @@ -87,6 +87,15 @@ internal static string EarthmatPageContactTitle { } } + /// + /// Looks up a localized string similar to Type in rock type ie. basalt. + /// + internal static string EarthmatPageDetailSearchPlaceholder { + get { + return ResourceManager.GetString("EarthmatPageDetailSearchPlaceholder", resourceCulture); + } + } + /// /// Looks up a localized string similar to General. /// @@ -105,6 +114,15 @@ internal static string EarthmatPageInterpretationTitle { } } + /// + /// Looks up a localized string similar to Detail. + /// + internal static string EarthmatPageLithoDetail { + get { + return ResourceManager.GetString("EarthmatPageLithoDetail", resourceCulture); + } + } + /// /// Looks up a localized string similar to Lithologic Modifiers. /// @@ -123,6 +141,15 @@ internal static string EarthmatPageLithoTitle { } } + /// + /// Looks up a localized string similar to Type. + /// + internal static string EarthmatPageLithoType { + get { + return ResourceManager.GetString("EarthmatPageLithoType", resourceCulture); + } + } + /// /// Looks up a localized string similar to Magnetism. /// @@ -150,6 +177,15 @@ internal static string EarthmatPageMineralogyTitle { } } + /// + /// Looks up a localized string similar to Type in rock group ie. metamorphic. + /// + internal static string EarthmatPageSearchPlaceholder { + get { + return ResourceManager.GetString("EarthmatPageSearchPlaceholder", resourceCulture); + } + } + /// /// Looks up a localized string similar to Earth Material. /// diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx index 77102703..bf452009 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx @@ -126,18 +126,27 @@ Contact + + Tapez une lithologie ie. basalt + Général Interprétation + + Détail + Modificateur de lithologie Lithologie - Cadre et composition + + Type + Magnétisme @@ -147,6 +156,9 @@ Minéralogie + + Tapez un groupe i.e. métamorphique + Matériaux du sol diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx index b83bc248..57b379d4 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx @@ -126,18 +126,27 @@ Contact + + Type in rock type ie. basalt + General Interpretation + + Detail + Lithologic Modifiers Lithology - Setting and composition + + Type + Magnetism @@ -147,6 +156,9 @@ Mineralogy + + Type in rock group ie. metamorphic + Earth Material diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index f63dec1c..4e578877 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -205,9 +205,11 @@ + + + + + + - + + + + + + + + - - + + diff --git a/GSCFieldApp/ViewModel/EarthmatViewModel.cs b/GSCFieldApp/ViewModel/EarthmatViewModel.cs index 93050778..c413f449 100644 --- a/GSCFieldApp/ViewModel/EarthmatViewModel.cs +++ b/GSCFieldApp/ViewModel/EarthmatViewModel.cs @@ -18,6 +18,7 @@ using SQLite; using System.Text.RegularExpressions; using GSCFieldApp.Services; +using static Microsoft.Maui.ApplicationModel.Permissions; namespace GSCFieldApp.ViewModel { @@ -69,11 +70,16 @@ public LocalizationResourceManager LocalizationResourceManager private ComboBox _earthLithColourGeneric = new ComboBox(); private ComboBox _earthLithColourIntensity = new ComboBox(); private ComboBox _earthLithColourQualifier = new ComboBox(); + private ComboBox _earthLithContactUpper = new ComboBox(); + private ComboBox _earthLithContactLower = new ComboBox(); + private ComboBox _earthLithContactType = new ComboBox(); + private ComboBox _earthLithContactRelatedAlias = new ComboBox(); private ComboBoxItem _selectedEarthLithGroup = new ComboBoxItem(); private Models.Colour _earthColourW = new Models.Colour(); private Models.Colour _earthColourF = new Models.Colour(); + private Models.Contacts _earthContact = new Models.Contacts(); //Concatenated fields private ComboBox _earthLithTextureStruct = new ComboBox(); @@ -93,7 +99,7 @@ public LocalizationResourceManager LocalizationResourceManager private ObservableCollection _grainSizeCollection = new ObservableCollection(); private ObservableCollection _bedThickCollection = new ObservableCollection(); private ObservableCollection _defFabCollection = new ObservableCollection(); - + private ObservableCollection _contactRelationCollection = new ObservableCollection(); #endregion @@ -166,6 +172,10 @@ public List LihthoDetailSearchResults public ComboBox EarthLithColourGeneric { get { return _earthLithColourGeneric; } set { _earthLithColourGeneric = value; } } public ComboBox EarthLithColourIntensity { get { return _earthLithColourIntensity; } set { _earthLithColourIntensity = value; } } public ComboBox EarthLithColourQualifier { get { return _earthLithColourQualifier; } set { _earthLithColourQualifier = value; } } + public ComboBox EarthLithContactUpper { get { return _earthLithContactUpper; } set { _earthLithContactUpper = value; } } + public ComboBox EarthLithContactLower { get { return _earthLithContactLower; } set { _earthLithContactLower = value; } } + public ComboBox EarthLithContactType { get { return _earthLithContactType; } set { _earthLithContactType = value; } } + public ComboBox EarthLithContactRelatedAlias { get { return _earthLithContactRelatedAlias; } set { _earthLithContactRelatedAlias = value; } } public ComboBoxItem SelectedEarthLithQualifier { @@ -303,6 +313,7 @@ public ComboBoxItem SelectedEarthLithDefFab public ObservableCollection EarthLithGrainSizeCollection { get { return _grainSizeCollection; } set { _grainSizeCollection = value; OnPropertyChanged(nameof(EarthLithGrainSizeCollection)); } } public ObservableCollection EarthLithBedThickCollection { get { return _bedThickCollection; } set { _bedThickCollection = value; OnPropertyChanged(nameof(EarthLithBedThickCollection)); } } public ObservableCollection EarthLithDefFabCollection { get { return _defFabCollection; } set { _defFabCollection = value; OnPropertyChanged(nameof(EarthLithDefFabCollection)); } } + public ObservableCollection EarthLithContactRelationCollection { get { return _contactRelationCollection; } set { _contactRelationCollection = value; OnPropertyChanged(nameof(EarthLithContactRelationCollection)); } } public string EarthResidualText { get { return _earthResidualText; } set { _earthResidualText = value; } } @@ -452,6 +463,29 @@ public async Task SetWeatheredColour() OnPropertyChanged(nameof(Model)); } + [RelayCommand] + public async Task SetContact() + { + if (_earthLithContactType.cboxItems.Count() > 0 && _earthLithContactType.cboxDefaultItemIndex != -1 && + _earthLithContactRelatedAlias.cboxItems.Count() > 0 && _earthLithContactType.cboxDefaultItemIndex != -1) + { + //Build proper string from selected values + _earthContact.type = _earthLithContactType.cboxItems[_earthLithContactType.cboxDefaultItemIndex].itemValue; + Earthmaterial em = new Earthmaterial(); + em.EarthMatName = _earthLithContactRelatedAlias.cboxItems[_earthLithContactRelatedAlias.cboxDefaultItemIndex].itemValue; + _earthContact.relatedEarthMaterialID = em.GetIDLetter; + + //Add + ComboBoxItem newContact = new ComboBoxItem(); + newContact.itemName = _earthContact.ToString(); + newContact.itemValue = _earthContact.ToString(); + newContact.canRemoveItem = true; + _contactRelationCollection.Add(newContact); + } + + OnPropertyChanged(nameof(EarthLithContactRelationCollection)); + } + #endregion #region METHODS @@ -654,6 +688,9 @@ public async Task FillPickers() _earthLithColourGeneric = await FillAPicker(DatabaseLiterals.KeywordColourGeneric); _earthLithColourIntensity = await FillAPicker(DatabaseLiterals.KeywordColourIntensity); _earthLithColourQualifier = await FillAPicker(DatabaseLiterals.KeywordColourQualifier); + _earthLithContactUpper = await FillAPicker(DatabaseLiterals.FieldEarthMatContactUp); + _earthLithContactLower = await FillAPicker(DatabaseLiterals.FieldEarthMatContactLow); + _earthLithContactType = await FillAPicker(DatabaseLiterals.FieldEarthMatContactUp); OnPropertyChanged(nameof(EarthLithoGroup)); OnPropertyChanged(nameof(EarthLithMapUnit)); @@ -670,6 +707,9 @@ public async Task FillPickers() OnPropertyChanged(nameof(EarthLithColourGeneric)); OnPropertyChanged(nameof(EarthLithColourIntensity)); OnPropertyChanged(nameof(EarthLithColourQualifier)); + OnPropertyChanged(nameof(EarthLithContactUpper)); + OnPropertyChanged(nameof(EarthLithContactLower)); + OnPropertyChanged(nameof(EarthLithContactType)); //There is one picker that needs a parent in bedrock, but doesn't in surficial if (currentProjectType == DatabaseLiterals.ApplicationThemeSurficial) @@ -677,6 +717,13 @@ public async Task FillPickers() _earthLithTextureStruct = await FillAPicker(DatabaseLiterals.FieldEarthMatModTextStruc, _model.EarthMatLithgroup, currentProjectType); OnPropertyChanged(nameof(EarthLithTextureStruct)); } + + //There is one picker that needs all brotha's and sista's listing + if (currentProjectType == DatabaseLiterals.ApplicationThemeBedrock) + { + _earthLithContactRelatedAlias = await FillRelatedEarthmatAsync(); + OnPropertyChanged(nameof(EarthLithContactRelatedAlias)); + } } /// @@ -710,6 +757,56 @@ private async Task FillAPicker(string fieldName, string extraField = " } + /// + /// Will fill with all other earthmaterial associated with parent station/drill hole + /// + public async Task FillRelatedEarthmatAsync() + { + ComboBox relatedCbx = new ComboBox(); + relatedCbx.cboxDefaultItemIndex = -1; + + if (_earthmaterial != null || _station != null) + { + //Find proper parent id (request could come from a mineral or an earthmat selection) + List ems = new List(); + if (_earthmaterial != null) + { + if (_earthmaterial.ParentName == Dictionaries.DatabaseLiterals.TableStation) + { + ems = await currentConnection.Table().Where(i => (i.EarthMatStatID == Earthmaterial.EarthMatStatID || i.EarthMatID <= 1) && (i.EarthMatID != _earthmaterial.EarthMatID)).ToListAsync(); + } + else + { + ems = await currentConnection.Table().Where(i => i.EarthMatDrillHoleID == Earthmaterial.EarthMatDrillHoleID || i.EarthMatID != _earthmaterial.EarthMatID).ToListAsync(); + } + } + else + { + if (_station != null) + { + ems = await currentConnection.Table().Where(i => (i.EarthMatStatID == _station.StationID)).ToListAsync(); + } + } + + if (ems != null && ems.Count > 0) + { + + foreach (Earthmaterial em in ems) + { + Themes.ComboBoxItem newItem = new Themes.ComboBoxItem(); + newItem.itemValue = em.EarthMatName; + newItem.itemName = em.EarthMatName; + relatedCbx.cboxItems.Add(newItem); + } + + relatedCbx.cboxDefaultItemIndex = -1; + } + } + + return relatedCbx; + + } + /// /// Will fill out missing fields for model. Default auto-calculated values /// @@ -784,6 +881,18 @@ private async Task SetModelAsync() { Model.EarthMatInterpConf = EarthLithConfidence.cboxItems[EarthLithConfidence.cboxDefaultItemIndex].itemValue; //process list of values so they are concatenated. } + if (EarthLithContactUpper.cboxItems.Count() > 0 && EarthLithContactUpper.cboxDefaultItemIndex != -1) + { + Model.EarthMatContactUp = EarthLithContactUpper.cboxItems[EarthLithContactUpper.cboxDefaultItemIndex].itemValue; //process list of values so they are concatenated. + } + if (EarthLithContactLower.cboxItems.Count() > 0 && EarthLithContactLower.cboxDefaultItemIndex != -1) + { + Model.EarthMatContactLow = EarthLithContactLower.cboxItems[EarthLithContactLower.cboxDefaultItemIndex].itemValue; //process list of values so they are concatenated. + } + if (EarthLithContactRelationCollection.Count > 0) + { + Model.EarthMatContact = concat.PipeValues(EarthLithContactRelationCollection); //process list of values so they are concatenated. + } } /// @@ -915,6 +1024,36 @@ public async Task Load() } OnPropertyChanged(nameof(EarthLithConfidence)); + foreach (ComboBoxItem cbox in EarthLithContactUpper.cboxItems) + { + if (cbox.itemValue == _earthmaterial.EarthMatContactUp) + { + EarthLithContactUpper.cboxDefaultItemIndex = EarthLithContactUpper.cboxItems.IndexOf(cbox); break; + } + } + OnPropertyChanged(nameof(EarthLithContactUpper)); + + foreach (ComboBoxItem cbox in EarthLithContactLower.cboxItems) + { + if (cbox.itemValue == _earthmaterial.EarthMatContactLow) + { + EarthLithContactLower.cboxDefaultItemIndex = EarthLithContactLower.cboxItems.IndexOf(cbox); break; + } + } + OnPropertyChanged(nameof(EarthLithContactLower)); + + List ecs = concat.UnpipeString(_earthmaterial.EarthMatContact); + _contactRelationCollection.Clear(); //Clear any possible values first + foreach (string ec in ecs) + { + ComboBoxItem new_ec = new ComboBoxItem(); + new_ec.itemValue = ec; + new_ec.itemName = ec; + new_ec.canRemoveItem = true; + _contactRelationCollection.Add(new_ec); + } + OnPropertyChanged(nameof(EarthLithBedThickCollection)); + #endregion if (currentProjectType == DatabaseLiterals.ApplicationThemeSurficial) diff --git a/GSCFieldApp/Views/EarthmatPage.xaml b/GSCFieldApp/Views/EarthmatPage.xaml index 0cd41ce5..6022e4d6 100644 --- a/GSCFieldApp/Views/EarthmatPage.xaml +++ b/GSCFieldApp/Views/EarthmatPage.xaml @@ -255,7 +255,9 @@ [Obsolete] - public async void StartGPS() + public async Task StartGPS() { + try { + this.gpsCancelation?.Dispose(); this.gpsCancelation = new CancellationTokenSource(); @@ -335,7 +364,9 @@ await Application.Current.Dispatcher.DispatchAsync(async () => var location = await Geolocation.GetLocationAsync(request, this.gpsCancelation.Token) .ConfigureAwait(false); if (location != null) - { + { + _isGPSOn = true; + MyLocationPositionChanged(location); } }).ConfigureAwait(false); @@ -346,7 +377,32 @@ await Application.Current.Dispatcher.DispatchAsync(async () => } catch (Exception e) { - Mapsui.Logging.Logger.Log(LogLevel.Error, e.Message, e); + _isGPSOn = false; + + await MainThread.InvokeOnMainThreadAsync(async () => + { + //Manage restricted access to other problems + if (e.Message.ToLower().Contains("denied")) + { + //Tell user app doesn't have access to location + bool answer = await Shell.Current.DisplayAlert(LocalizationResourceManager["DisplayAlertGPSDenied"].ToString(), + LocalizationResourceManager["DisplayAlertGPSMessage"].ToString(), + LocalizationResourceManager["GenericButtonYes"].ToString(), + LocalizationResourceManager["GenericButtonNo"].ToString()); + + if (answer == true) + { + AppInfo.Current.ShowSettingsUI(); + } + } + else + { + //Generic error message regarding GPS + await Shell.Current.DisplayAlert(LocalizationResourceManager["DisplayAlertGPS"].ToString(), e.Message, + LocalizationResourceManager["GenericButtonOk"].ToString()); + } + + }); } } @@ -356,6 +412,7 @@ await Application.Current.Dispatcher.DispatchAsync(async () => public void StopGPS() { this.gpsCancelation?.Cancel(); + _isGPSOn = false; } /// @@ -490,6 +547,7 @@ private SymbolStyle CreateBitmapStyle() } + #endregion } \ No newline at end of file From d425410b563b492b06bf80c5c285c17db09efb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Fri, 5 Jan 2024 15:58:51 -0500 Subject: [PATCH 100/312] gps button tap a bit more functional --- GSCFieldApp/Views/MapPage.xaml.cs | 75 ++++++++++++++++--------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/GSCFieldApp/Views/MapPage.xaml.cs b/GSCFieldApp/Views/MapPage.xaml.cs index b20dc0b6..eb0fd288 100644 --- a/GSCFieldApp/Views/MapPage.xaml.cs +++ b/GSCFieldApp/Views/MapPage.xaml.cs @@ -38,12 +38,13 @@ namespace GSCFieldApp.Views; public partial class MapPage : ContentPage { - private CancellationTokenSource? gpsCancelation; + //private CancellationTokenSource? gpsCancelation; + private CancellationTokenSource _cancelTokenSource; private bool _updateLocation = true; private MapControl mapControl = new Mapsui.UI.Maui.MapControl(); private DataAccess da = new DataAccess(); private int bitmapSymbolId = -1; - private bool _isGPSOn = true; + private bool _isCheckingGeolocation = false; public LocalizationResourceManager LocalizationResourceManager => LocalizationResourceManager.Instance; // Will be used for in code dynamic local strings @@ -64,8 +65,6 @@ public MapPage(MapViewModel vm) mapView.Map = mapControl.Map; - //StartGPS(); - this.Loaded += MapPage_Loaded; } @@ -92,7 +91,7 @@ protected override async void OnNavigatedTo(NavigatedToEventArgs args) } //Manage GPS - if (!_isGPSOn) + if (!_isCheckingGeolocation) { StartGPS(); } @@ -202,9 +201,12 @@ private void ManageLayerButton_Clicked(object sender, EventArgs e) /// private void GPSMode_Clicked(object sender, EventArgs e) { - if (_isGPSOn) + if (_isCheckingGeolocation) { - StopGPS(); + StopGPSAsync(); + + //TODO find a working way of changing button symbol + //tried in map view model like in version 2 Couldn't make it work } else { @@ -312,6 +314,13 @@ public async Task SetMapAccuracyColor(double? accuracy) } } + else if (accuracy == -99) + { + if (App.Current.Resources.TryGetValue("Gray400", out var errorColorvalue)) + { + mapPageGrid.BackgroundColor = errorColorvalue as Microsoft.Maui.Graphics.Color; + } + } //else //{ // if (App.Current.Resources.TryGetValue("White", out var errorColorvalue)) @@ -340,44 +349,31 @@ public async Task AddSymbolToRegistry() /// /// Will start the GPS /// - [Obsolete] public async Task StartGPS() { + _isCheckingGeolocation = true; try { - this.gpsCancelation?.Dispose(); - this.gpsCancelation = new CancellationTokenSource(); + GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(10)); + + if (Application.Current == null) + return; + + _cancelTokenSource = new CancellationTokenSource(); - await Task.Run(async () => + var location = await Geolocation.GetLocationAsync(request, _cancelTokenSource.Token) + .ConfigureAwait(false); + if (location != null) { - while (!gpsCancelation.IsCancellationRequested) - { - var request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(10)); + MyLocationPositionChanged(location); + } - if (Application.Current == null) - return; - await Application.Current.Dispatcher.DispatchAsync(async () => - { - var location = await Geolocation.GetLocationAsync(request, this.gpsCancelation.Token) - .ConfigureAwait(false); - if (location != null) - { - _isGPSOn = true; - - MyLocationPositionChanged(location); - } - }).ConfigureAwait(false); - - await Task.Delay(200).ConfigureAwait(false); - } - }, gpsCancelation.Token).ConfigureAwait(false); } catch (Exception e) { - _isGPSOn = false; await MainThread.InvokeOnMainThreadAsync(async () => { @@ -404,15 +400,24 @@ await Shell.Current.DisplayAlert(LocalizationResourceManager["DisplayAlertGPS"]. }); } + //finally + //{ + // _isCheckingGeolocation = false; + //} } /// /// Will stop the GPS /// - public void StopGPS() + public async Task StopGPSAsync() { - this.gpsCancelation?.Cancel(); - _isGPSOn = false; + if (_isCheckingGeolocation && _cancelTokenSource != null && _cancelTokenSource.IsCancellationRequested == false) + { + await SetMapAccuracyColor(-99); + _isCheckingGeolocation = false; + _cancelTokenSource.Cancel(); + } + } /// From fe5292045dd8f5ddc15c7b8d63393faaf9b1658b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Fri, 5 Jan 2024 17:30:00 -0500 Subject: [PATCH 101/312] Implemented some cache on osm tilelayer. --- GSCFieldApp/GSCFieldApp.csproj | 16 +++++++----- GSCFieldApp/Views/MapPage.xaml.cs | 43 ++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/GSCFieldApp/GSCFieldApp.csproj b/GSCFieldApp/GSCFieldApp.csproj index b5904757..c685ffd0 100644 --- a/GSCFieldApp/GSCFieldApp.csproj +++ b/GSCFieldApp/GSCFieldApp.csproj @@ -310,20 +310,24 @@ - - - - - - + + + + + + + + + + diff --git a/GSCFieldApp/Views/MapPage.xaml.cs b/GSCFieldApp/Views/MapPage.xaml.cs index eb0fd288..3f70728f 100644 --- a/GSCFieldApp/Views/MapPage.xaml.cs +++ b/GSCFieldApp/Views/MapPage.xaml.cs @@ -33,6 +33,9 @@ using Mapsui.UI.Maui.Extensions; using static GSCFieldApp.Models.GraphicPlacement; using GSCFieldApp.Services; +using BruTile.Predefined; +using Mapsui.Extensions.Cache; +using BruTile.Web; namespace GSCFieldApp.Views; @@ -57,11 +60,13 @@ public MapPage(MapViewModel vm) //Initialize grid background mapPageGrid.BackgroundColor = Mapsui.Styles.Color.FromString("White").ToNative(); - //Initialize map control and GPS - var tileLayer = Mapsui.Tiling.OpenStreetMap.CreateTileLayer("NRCan_GSCFieldApp/3.0 Maui.net"); + //Setting map page background default data + SetOpenStreetMap(); - mapControl.Map.Layers.Add(tileLayer); - mapControl.Map.Widgets.Add(new Mapsui.Widgets.ScaleBar.ScaleBarWidget(mapControl.Map) { TextAlignment = Mapsui.Widgets.Alignment.Center, HorizontalAlignment = Mapsui.Widgets.HorizontalAlignment.Left, VerticalAlignment = Mapsui.Widgets.VerticalAlignment.Bottom }); + mapControl.Map.Widgets.Add(new Mapsui.Widgets.ScaleBar.ScaleBarWidget(mapControl.Map) + { TextAlignment = Mapsui.Widgets.Alignment.Center, + HorizontalAlignment = Mapsui.Widgets.HorizontalAlignment.Left, + VerticalAlignment = Mapsui.Widgets.VerticalAlignment.Bottom }); mapView.Map = mapControl.Map; @@ -99,7 +104,6 @@ protected override async void OnNavigatedTo(NavigatedToEventArgs args) private async void MapPage_Loaded(object sender, EventArgs e) { - //Manage symbol and layers await AddSymbolToRegistry(); MemoryLayer ml = await CreatePointLayerAsync(); @@ -207,6 +211,8 @@ private void GPSMode_Clicked(object sender, EventArgs e) //TODO find a working way of changing button symbol //tried in map view model like in version 2 Couldn't make it work + //this.GPSMode.Text = "󰈽"; + //this.GPSMode.FontFamily = "MatDesign"; } else { @@ -220,6 +226,29 @@ private void GPSMode_Clicked(object sender, EventArgs e) #region METHODS + /// + /// Will call open street map tile layers + /// And will also set up a persistant cache mode so user can + /// go offline and still navigate through open street map + /// + /// + public void SetOpenStreetMap(bool withCache = true) + { + if (withCache) + { + var persistentCache = new SqlitePersistentCache("NRCan_GSCFieldApp"); + HttpTileSource source = KnownTileSources.Create(KnownTileSource.OpenStreetMap, "NRCan_GSCFieldApp/3.0 Maui.net", persistentCache: persistentCache); + TileLayer osmLayer = new TileLayer(source); + mapControl.Map.Layers.Add(osmLayer); + } + else + { + TileLayer osmLayer = Mapsui.Tiling.OpenStreetMap.CreateTileLayer("NRCan_GSCFieldApp/3.0 Maui.net"); + mapControl.Map.Layers.Add(osmLayer); + } + + } + /// /// Method to change current location symbol. /// NOTE: not doable for now https://github.com/Mapsui/Mapsui/issues/618 @@ -400,10 +429,6 @@ await Shell.Current.DisplayAlert(LocalizationResourceManager["DisplayAlertGPS"]. }); } - //finally - //{ - // _isCheckingGeolocation = false; - //} } /// From 109600edab18d6eb50920c6d34a6afa98fea51d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Mon, 8 Jan 2024 10:08:01 -0500 Subject: [PATCH 102/312] Testing wheeler and grav wms as default layers. --- GSCFieldApp/Views/MapPage.xaml.cs | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/GSCFieldApp/Views/MapPage.xaml.cs b/GSCFieldApp/Views/MapPage.xaml.cs index 3f70728f..d19c0c26 100644 --- a/GSCFieldApp/Views/MapPage.xaml.cs +++ b/GSCFieldApp/Views/MapPage.xaml.cs @@ -36,6 +36,7 @@ using BruTile.Predefined; using Mapsui.Extensions.Cache; using BruTile.Web; +using BruTile.Wmsc; namespace GSCFieldApp.Views; @@ -62,6 +63,8 @@ public MapPage(MapViewModel vm) //Setting map page background default data SetOpenStreetMap(); + SetWheelerMap(); + SetGravMap(); mapControl.Map.Widgets.Add(new Mapsui.Widgets.ScaleBar.ScaleBarWidget(mapControl.Map) { TextAlignment = Mapsui.Widgets.Alignment.Center, @@ -70,6 +73,7 @@ public MapPage(MapViewModel vm) mapView.Map = mapControl.Map; + this.Loaded += MapPage_Loaded; } @@ -249,6 +253,68 @@ public void SetOpenStreetMap(bool withCache = true) } + /// + /// Will call Canada 3D WMS service to retrieve Wheeler map + /// And will also set up a persistant cache mode so user can + /// go offline and still navigate through it + /// + /// + public void SetWheelerMap(int layerIndex = 1, bool withCache = false) + { + const string url = "https://canada3d-geo.azurewebsites.net/canada3d/wms?version=1.1.0"; + GlobalSphericalMercator schema = new GlobalSphericalMercator { Format = "image/png" }; + WmscRequest request = new WmscRequest(new Uri(url), schema, new[] { "wheeler_3978" }.ToList(), Array.Empty().ToList()); + + if (withCache) + { + var persistentCache = new SqlitePersistentCache("NRCan_GSCFieldAppWheeler"); + HttpTileProvider provider = new HttpTileProvider(request, persistentCache); + TileSource t = new TileSource(provider, schema); + TileLayer tl = new TileLayer(t); + mapControl.Map.Layers.Insert(layerIndex, tl); + } + else + { + + HttpTileProvider provider = new HttpTileProvider(request); + TileSource t = new TileSource(provider, schema); + TileLayer tl = new TileLayer(t); + mapControl.Map.Layers.Insert(layerIndex, tl); + } + + } + + /// + /// Will call Canada 3D WMS service to retrieve Wheeler map + /// And will also set up a persistant cache mode so user can + /// go offline and still navigate through it + /// + /// + public void SetGravMap(int layerIndex = 2, bool withCache = false) + { + const string url = "https://canada3d-geo.azurewebsites.net/ows?version=1.3.0"; + GlobalSphericalMercator schema = new GlobalSphericalMercator { Format = "image/png" }; + WmscRequest request = new WmscRequest(new Uri(url), schema, new[] { "c3d_geophys:Canada_Mag_Res_1000m_8bits_pal" }.ToList(), Array.Empty().ToList()); + + if (withCache) + { + var persistentCache = new SqlitePersistentCache("NRCan_GSCFieldAppGrav"); + HttpTileProvider provider = new HttpTileProvider(request, persistentCache); + TileSource t = new TileSource(provider, schema); + TileLayer tl = new TileLayer(t); + mapControl.Map.Layers.Insert(layerIndex, tl); + } + else + { + + HttpTileProvider provider = new HttpTileProvider(request); + TileSource t = new TileSource(provider, schema); + TileLayer tl = new TileLayer(t); + mapControl.Map.Layers.Insert(layerIndex, tl); + } + + } + /// /// Method to change current location symbol. /// NOTE: not doable for now https://github.com/Mapsui/Mapsui/issues/618 From 24916cf18755551befea563ef00142dceff8e09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Mon, 8 Jan 2024 16:49:29 -0500 Subject: [PATCH 103/312] Custom zoom fit to field data extent in map page and 2 custom wms for wheeler and grav. Uncomment for test. --- GSCFieldApp/ViewModel/MapViewModel.cs | 8 ++++ GSCFieldApp/Views/MapPage.xaml | 5 ++ GSCFieldApp/Views/MapPage.xaml.cs | 69 +++++++++++++++++++++++---- 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/GSCFieldApp/ViewModel/MapViewModel.cs b/GSCFieldApp/ViewModel/MapViewModel.cs index 482ba96d..6271f77c 100644 --- a/GSCFieldApp/ViewModel/MapViewModel.cs +++ b/GSCFieldApp/ViewModel/MapViewModel.cs @@ -32,11 +32,13 @@ public partial class MapViewModel: ObservableObject private ObservableCollection _layerCollection = new ObservableCollection(); private string _gpsModeButtonSymbol = ApplicationLiterals.gpsModeGPS; + private bool _isWaiting = false; #endregion #region PROPERTIES public ObservableCollection layerCollection { get { return _layerCollection; } set { _layerCollection = value; } } public string GPSModeButtonSymbol { get { return _gpsModeButtonSymbol; } set { _gpsModeButtonSymbol = value; } } + public bool IsWaiting { get { return _isWaiting; } set { _isWaiting = value; } } #endregion public MapViewModel() { @@ -70,6 +72,12 @@ await Shell.Current.GoToAsync($"{nameof(StationPage)}", #region METHODS + + public void SetWaitingCursor() + { + _isWaiting = !_isWaiting; + OnPropertyChanged(nameof(IsWaiting)); + } /// /// Will retrieve first metadata record /// diff --git a/GSCFieldApp/Views/MapPage.xaml b/GSCFieldApp/Views/MapPage.xaml index da9ed4f1..a71adf05 100644 --- a/GSCFieldApp/Views/MapPage.xaml +++ b/GSCFieldApp/Views/MapPage.xaml @@ -45,7 +45,9 @@ + + @@ -54,6 +56,9 @@ + + + diff --git a/GSCFieldApp/Views/MapPage.xaml.cs b/GSCFieldApp/Views/MapPage.xaml.cs index d19c0c26..77d293b5 100644 --- a/GSCFieldApp/Views/MapPage.xaml.cs +++ b/GSCFieldApp/Views/MapPage.xaml.cs @@ -37,6 +37,7 @@ using Mapsui.Extensions.Cache; using BruTile.Web; using BruTile.Wmsc; +using Mapsui.Animations; namespace GSCFieldApp.Views; @@ -61,19 +62,20 @@ public MapPage(MapViewModel vm) //Initialize grid background mapPageGrid.BackgroundColor = Mapsui.Styles.Color.FromString("White").ToNative(); + mapControl.Map.Widgets.Add(new Mapsui.Widgets.ScaleBar.ScaleBarWidget(mapControl.Map) + { + TextAlignment = Mapsui.Widgets.Alignment.Center, + HorizontalAlignment = Mapsui.Widgets.HorizontalAlignment.Left, + VerticalAlignment = Mapsui.Widgets.VerticalAlignment.Bottom + }); + //Setting map page background default data SetOpenStreetMap(); - SetWheelerMap(); - SetGravMap(); - - mapControl.Map.Widgets.Add(new Mapsui.Widgets.ScaleBar.ScaleBarWidget(mapControl.Map) - { TextAlignment = Mapsui.Widgets.Alignment.Center, - HorizontalAlignment = Mapsui.Widgets.HorizontalAlignment.Left, - VerticalAlignment = Mapsui.Widgets.VerticalAlignment.Bottom }); + //SetWheelerMap(); + //SetGravMap(); mapView.Map = mapControl.Map; - this.Loaded += MapPage_Loaded; } @@ -85,7 +87,7 @@ protected override async void OnNavigatedTo(NavigatedToEventArgs args) //In case user is coming from field notes //They might have deleted some stations, make sure to refresh - + foreach (var item in mapView.Map.Layers) { if (item.Name == "Stations") @@ -95,6 +97,10 @@ protected override async void OnNavigatedTo(NavigatedToEventArgs args) MemoryLayer ml = await CreatePointLayerAsync(); mapView.Map.Layers.Add(ml); mapView.Map.RefreshData(); + + //Zoom to extent of those poins + SetExtent(ml); + break; } } @@ -102,16 +108,33 @@ protected override async void OnNavigatedTo(NavigatedToEventArgs args) //Manage GPS if (!_isCheckingGeolocation) { - StartGPS(); + await StartGPS(); } + } + /// + /// Once the map is loaded, make a quick check on + /// field data locations, in case something has been deleted while + /// user was away in the notes + /// Make sure to zoom back to the field data location extent. + /// + /// + /// private async void MapPage_Loaded(object sender, EventArgs e) { + + MapViewModel mvm = this.BindingContext as MapViewModel; + mvm.SetWaitingCursor(); + //Manage symbol and layers await AddSymbolToRegistry(); MemoryLayer ml = await CreatePointLayerAsync(); mapView.Map.Layers.Add(ml); + + //Zoom to initial extent of the layer + SetExtent(ml); + } /// @@ -230,6 +253,32 @@ private void GPSMode_Clicked(object sender, EventArgs e) #region METHODS + /// + /// Will zoom to the extent of the incoming memory layer + /// + /// + public void SetExtent(MemoryLayer inMemoryLayer) + { + if (inMemoryLayer.Extent != null) + { + // Extend a bit more the rectangle + var fieldDataExtent = new MRect(inMemoryLayer.Extent.MinX, + inMemoryLayer.Extent.MinY, + inMemoryLayer.Extent.MaxX, + inMemoryLayer.Extent.MaxY).Grow(2500); + + mapView.Map.Navigator.ZoomToBox(box: fieldDataExtent, boxFit: MBoxFit.Fit); + } + else + { + // Extend a bit more the rectangle + var fieldDataExtent = new MRect(-139.649,45.144, -56.288, 72.378).Grow(25000); + mapView.Map.Navigator.ZoomToBox(box: fieldDataExtent, boxFit: MBoxFit.Fit); + } + + + } + /// /// Will call open street map tile layers /// And will also set up a persistant cache mode so user can From 87f203872779eebe97e5548de094a8aba7acc07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Tue, 9 Jan 2024 11:13:46 -0500 Subject: [PATCH 104/312] Replaced hardcoded grav and wheeler wms to new map page button to add wms in general. --- .../Dictionaries/ApplicationLiterals.cs | 7 ++ .../Strings/LocalizableStrings.Designer.cs | 117 ++++++++++++++++++ .../Strings/LocalizableStrings.fr-CA.resx | 39 ++++++ .../Resources/Strings/LocalizableStrings.resx | 39 ++++++ GSCFieldApp/Views/MapPage.xaml | 35 ++++-- GSCFieldApp/Views/MapPage.xaml.cs | 77 +++++------- 6 files changed, 262 insertions(+), 52 deletions(-) diff --git a/GSCFieldApp/Dictionaries/ApplicationLiterals.cs b/GSCFieldApp/Dictionaries/ApplicationLiterals.cs index ce9595d8..5965095f 100644 --- a/GSCFieldApp/Dictionaries/ApplicationLiterals.cs +++ b/GSCFieldApp/Dictionaries/ApplicationLiterals.cs @@ -81,5 +81,12 @@ public static class ApplicationLiterals public const string gpsModeGPS = "󰆤"; #endregion + + #region GIS + + public const string keywordWMS = "NRCan_GSCFieldApp"; //Will be used for WMS caching prefix and token generation + public const string keywordWMSLayers = "&layers="; //Will be used to get wms layer names in the URL + + #endregion } } diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs index 9b12a9a3..7d32d730 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs @@ -825,6 +825,123 @@ internal static string GenericNoteTitle { } } + /// + /// Looks up a localized string similar to Tap to add a new layer.. + /// + internal static string MapPageAddData { + get { + return ResourceManager.GetString("MapPageAddData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to add a quick photo record.. + /// + internal static string MapPageAddPhoto { + get { + return ResourceManager.GetString("MapPageAddPhoto", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to add a quick sample record.. + /// + internal static string MapPageAddSample { + get { + return ResourceManager.GetString("MapPageAddSample", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to add a station record.. + /// + internal static string MapPageAddStation { + get { + return ResourceManager.GetString("MapPageAddStation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to add a quick structure/pflow record.. + /// + internal static string MapPageAddStruc { + get { + return ResourceManager.GetString("MapPageAddStruc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to add a waypoint.. + /// + internal static string MapPageAddWaypoint { + get { + return ResourceManager.GetString("MapPageAddWaypoint", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please enter the WMS web link including the layer to be added.. + /// + internal static string MapPageAddWaypointDialogMessage { + get { + return ResourceManager.GetString("MapPageAddWaypointDialogMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to https://canada3d-geo.azurewebsites.net/canada3d/wms?version=1.1.0. + /// + internal static string MapPageAddWaypointDialogPlaceholder { + get { + return ResourceManager.GetString("MapPageAddWaypointDialogPlaceholder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add WMS . + /// + internal static string MapPageAddWaypointDialogTitle { + get { + return ResourceManager.GetString("MapPageAddWaypointDialogTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to add an URL of an online Web Mapping Server (WMS).. + /// + internal static string MapPageAddWMS { + get { + return ResourceManager.GetString("MapPageAddWMS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to manually create a location record from XY or lat/long.. + /// + internal static string MapPageAddXY { + get { + return ResourceManager.GetString("MapPageAddXY", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to turn on/off GPS.. + /// + internal static string MapPageGPSMode { + get { + return ResourceManager.GetString("MapPageGPSMode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tap to see a list of all loaded layers and more options.. + /// + internal static string MapPageLayer { + get { + return ResourceManager.GetString("MapPageLayer", resourceCulture); + } + } + /// /// Looks up a localized string similar to Field Books. /// diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx index f1e6e143..414f4f11 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx @@ -373,6 +373,45 @@ Aimeriez-vous modifier les droits? Notes + + Ajouter une nouvelle couche de données. + + + Ajouter une nouvelle photo. + + + Ajouter un nouvel échantillon. + + + Ajouter une nouvelle station. + + + Ajouter une nouvelle structure ou paléoflow. + + + Ajouter un point d'intérêt. + + + Veuillez écrire l'adresse complète du service WMS à ajouter. + + + https://canada3d-geo.azurewebsites.net/canada3d/wms?version=1.1.0 + + + Ajouter une couche WMS + + + Ajouter une adresse web d'un service de cartographique (WMS). + + + Ajouter manuellement une coordonnées XY ou Lat/Long. + + + Éteindre/Allumer le GPS. + + + Menu de toutes les couches présentation accessible dans la carte. + Carnets de terrain diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx index 9c4958f3..11835a3b 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx @@ -372,6 +372,45 @@ Notes + + Tap to add a new layer. + + + Tap to add a quick photo record. + + + Tap to add a quick sample record. + + + Tap to add a station record. + + + Tap to add a quick structure/pflow record. + + + Tap to add a waypoint. + + + Please enter the WMS web link including the layer to be added. + + + https://canada3d-geo.azurewebsites.net/canada3d/wms?version=1.1.0 + + + Add WMS + + + Tap to add an URL of an online Web Mapping Server (WMS). + + + Tap to manually create a location record from XY or lat/long. + + + Tap to turn on/off GPS. + + + Tap to see a list of all loaded layers and more options. + Field Books diff --git a/GSCFieldApp/Views/MapPage.xaml b/GSCFieldApp/Views/MapPage.xaml index a71adf05..ab41758f 100644 --- a/GSCFieldApp/Views/MapPage.xaml +++ b/GSCFieldApp/Views/MapPage.xaml @@ -63,22 +63,28 @@ - /// - public void SetExtent(MemoryLayer inMemoryLayer) + public void SetExtent(ILayer inLayer = null) { - if (inMemoryLayer.Extent != null) + if (inLayer != null && inLayer.Extent != null) { // Extend a bit more the rectangle by 2.5km - var fieldDataExtent = new MRect(inMemoryLayer.Extent.MinX, - inMemoryLayer.Extent.MinY, - inMemoryLayer.Extent.MaxX, - inMemoryLayer.Extent.MaxY).Grow(2500); + var fieldDataExtent = new MRect(inLayer.Extent.MinX, + inLayer.Extent.MinY, + inLayer.Extent.MaxX, + inLayer.Extent.MaxY).Grow(2500); mapView.Map.Navigator.ZoomToBox(box: fieldDataExtent, boxFit: MBoxFit.Fit); } else { // Fit to Canada with a 25km buffer - var fieldDataExtent = new MRect(-139.649,45.144, -56.288, 72.378).Grow(25000); + var fieldDataExtent = new MRect(-15658662, 5533994, -5231695, 11534073).Grow(25000); mapView.Map.Navigator.ZoomToBox(box: fieldDataExtent, boxFit: MBoxFit.Fit); } @@ -898,4 +933,5 @@ private SymbolStyle CreateBitmapStyle() #endregion + } \ No newline at end of file From e162320c0cf0bf5c1523a1685a227f07a3edfe5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Mon, 15 Jan 2024 16:16:04 -0500 Subject: [PATCH 116/312] Added text wrap on layer menu labels --- GSCFieldApp/Views/MapPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GSCFieldApp/Views/MapPage.xaml b/GSCFieldApp/Views/MapPage.xaml index 26f32605..7d3b2997 100644 --- a/GSCFieldApp/Views/MapPage.xaml +++ b/GSCFieldApp/Views/MapPage.xaml @@ -25,7 +25,7 @@ - From a3a80310bcd1694e9781f88f8c840129b909cffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gabriel=2Ehuot-v=C3=A9zina?= Date: Tue, 16 Jan 2024 16:33:35 -0500 Subject: [PATCH 117/312] work start on field book deletion --- .../Strings/LocalizableStrings.Designer.cs | 36 ++++++++++++ .../Strings/LocalizableStrings.fr-CA.resx | 12 ++++ .../Resources/Strings/LocalizableStrings.resx | 12 ++++ GSCFieldApp/ViewModel/FieldBooksViewModel.cs | 56 +++++++++++++++++++ GSCFieldApp/ViewModel/MapViewModel.cs | 1 + GSCFieldApp/Views/FieldBooksPage.xaml | 14 ++++- 6 files changed, 128 insertions(+), 3 deletions(-) diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs index 6a79f346..e0b35d63 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs @@ -618,6 +618,24 @@ internal static string FieldBookPageActivtyPlaceholder { } } + /// + /// Looks up a localized string similar to Would you like to do a backup of selected field book?. + /// + internal static string FieldbookPageBackupMessage { + get { + return ResourceManager.GetString("FieldbookPageBackupMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Backup Field Book. + /// + internal static string FieldbookPageBackupTitle { + get { + return ResourceManager.GetString("FieldbookPageBackupTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to First Name. /// @@ -645,6 +663,24 @@ internal static string FieldBookPageChiefMName { } } + /// + /// Looks up a localized string similar to Are you sure you want to remove selected field book from device?. + /// + internal static string FieldbookPageDeleteMessage { + get { + return ResourceManager.GetString("FieldbookPageDeleteMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete Field Book. + /// + internal static string FieldbookPageDeleteTitle { + get { + return ResourceManager.GetString("FieldbookPageDeleteTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to Description. /// diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx index da49103e..4b27fc7a 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx @@ -304,6 +304,12 @@ Aimeriez-vous modifier les droits? Camp terrain 2023 + + Aimeriez-vous effectuer une sauvegarde du carnet de notes présentement sélectionné? + + + Sauvegarde du carnet + Prénom @@ -313,6 +319,12 @@ Aimeriez-vous modifier les droits? Deuxième prénom + + Êtes-vous certain de vouloir supprimer le carnet de note sélectionné de l'appareil? + + + Supprimer le carnet + Description diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx index 9c13eb1b..3cd4d8de 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx @@ -303,6 +303,12 @@ Field Summer 2023 + + Would you like to do a backup of selected field book? + + + Backup Field Book + First Name @@ -312,6 +318,12 @@ Middle Name + + Are you sure you want to remove selected field book from device? + + + Delete Field Book + Description diff --git a/GSCFieldApp/ViewModel/FieldBooksViewModel.cs b/GSCFieldApp/ViewModel/FieldBooksViewModel.cs index ab6ede98..fbe1b4f1 100644 --- a/GSCFieldApp/ViewModel/FieldBooksViewModel.cs +++ b/GSCFieldApp/ViewModel/FieldBooksViewModel.cs @@ -17,6 +17,7 @@ using BruTile.Wmts.Generated; using GSCFieldApp.Themes; using NetTopologySuite.Index.HPRtree; +using GSCFieldApp.Services; namespace GSCFieldApp.ViewModel { @@ -27,6 +28,10 @@ public partial class FieldBooksViewModel: ObservableObject public ObservableCollection _fieldbookCollection = new ObservableCollection(); public FieldBooks _selectedFieldBook; + //Localization + public LocalizationResourceManager LocalizationResourceManager + => LocalizationResourceManager.Instance; // Will be used for in code dynamic local strings + //Data service private DataAccess da = new DataAccess(); @@ -59,6 +64,12 @@ private void FieldBookDialog_newFieldBookSaved(object sender, EventArgs e) #region RELAY COMMANDS + [RelayCommand] + async Task DeleteFieldBook() + { + await DeleteFieldBook(SelectedFieldBook); + } + [RelayCommand] async Task AddFieldBook() { @@ -83,10 +94,55 @@ async Task UpdateFieldBook() await Shell.Current.DisplayAlert("Alert", "Not yet implemented", "OK"); } + [RelayCommand] + public async Task SwipeGestureRecognizer(FieldBooks fieldBook) + { + await DeleteFieldBook(fieldBook); + } #endregion #region METHODS + public async Task DeleteFieldBook(FieldBooks fieldBook) + { + bool deleteDialogResult = await Shell.Current.DisplayAlert(LocalizationResourceManager["FieldbookPageDeleteTitle"].ToString(), + LocalizationResourceManager["FieldbookPageDeleteMessage"].ToString(), + LocalizationResourceManager["GenericButtonYes"].ToString(), + LocalizationResourceManager["GenericButtonNo"].ToString()); + + if (deleteDialogResult) + { + //Make extra validation if user wants to backup his data + ValidateDeleteProject(fieldBook); + } + } + + /// + /// Will ask user if a field book backup is needed then will proceed with deleting + /// the selected field book. + /// + /// + public async void ValidateDeleteProject(FieldBooks fieldBook) + { + + bool backupDialogResult = await Shell.Current.DisplayAlert(LocalizationResourceManager["FieldbookPageBackupTitle"].ToString(), + LocalizationResourceManager["FieldbookPageBackupMessage"].ToString(), + LocalizationResourceManager["GenericButtonYes"].ToString(), + LocalizationResourceManager["GenericButtonNo"].ToString()); + + if (backupDialogResult) + { + //Backup + + //Delete + + } + else + { + //Delete + } + + } /// /// Will fill the project collection with information related to it diff --git a/GSCFieldApp/ViewModel/MapViewModel.cs b/GSCFieldApp/ViewModel/MapViewModel.cs index c75c6b51..47b86498 100644 --- a/GSCFieldApp/ViewModel/MapViewModel.cs +++ b/GSCFieldApp/ViewModel/MapViewModel.cs @@ -36,6 +36,7 @@ public partial class MapViewModel: ObservableObject private bool _isWaiting = false; #endregion + #region PROPERTIES public ObservableCollection layerCollection { get { return _layerCollection; } set { _layerCollection = value; } } private Collection CayerCollection { get { return _customLayerCollection; } set { _customLayerCollection = value; } } diff --git a/GSCFieldApp/Views/FieldBooksPage.xaml b/GSCFieldApp/Views/FieldBooksPage.xaml index 1541636a..d4b1e616 100644 --- a/GSCFieldApp/Views/FieldBooksPage.xaml +++ b/GSCFieldApp/Views/FieldBooksPage.xaml @@ -16,6 +16,13 @@ + + + + + @@ -110,7 +117,7 @@ - private async Task SetModelAsync() { - //Make sure it's for a new field book - _ = InitModel(); //Process concatenated pickers if (StationOutcropQuality.cboxDefaultItemIndex != -1 && QualityCollection != null && StationOutcropQuality.cboxItems.Count > 0) @@ -440,15 +434,15 @@ private async Task ResetModelAsync() //Get current application version Model.LocationID = fieldLocation.LocationID; Model.StationAlias = await idCalculator.CalculateStationAliasAsync(DateTime.Now); - Model.StationVisitDate = CalculateStationDate(); //Calculate new value - Model.StationVisitTime = CalculateStationTime(); //Calculate new value + Model.StationVisitDate = idCalculator.GetDate(); //Calculate new value + Model.StationVisitTime = idCalculator.GetTime(); //Calculate new value } else if (Model.LocationID != null) { // if coming from field notes on a record edit that needs to be saved as a new record with stay/save Model.StationAlias = await idCalculator.CalculateStationAliasAsync(DateTime.Now); - Model.StationVisitDate = CalculateStationDate(); //Calculate new value - Model.StationVisitTime = CalculateStationTime(); //Calculate new value + Model.StationVisitDate = idCalculator.GetDate(); //Calculate new value + Model.StationVisitTime = idCalculator.GetTime(); //Calculate new value } Model.StationID = 0; @@ -486,8 +480,8 @@ public async Task InitModel() //Get current application version Model.LocationID = fieldLocation.LocationID; Model.StationAlias = await idCalculator.CalculateStationAliasAsync(DateTime.Now); - Model.StationVisitDate = CalculateStationDate(); //Calculate new value - Model.StationVisitTime = CalculateStationTime(); //Calculate new value + Model.StationVisitDate = idCalculator.GetDate(); //Calculate new value + Model.StationVisitTime = idCalculator.GetTime(); //Calculate new value OnPropertyChanged(nameof(Model)); @@ -496,20 +490,6 @@ public async Task InitModel() #endregion - #region CALCULATIONS - - public string CalculateStationDate() - { - return String.Format("{0:yyyy-MM-dd}", _dateGeneric); ; - } - - public string CalculateStationTime() - { - return String.Format("{0:HH:mm:ss t}", _dateGeneric); ; - } - - #endregion - #region EVENTS From 9f2f7b130e5ca9adeecb4119a075fbaa2864f149 Mon Sep 17 00:00:00 2001 From: "gabriel.huot-vezina" Date: Thu, 18 Jul 2024 07:48:36 -0400 Subject: [PATCH 229/312] First pass on optimizing field note filling --- GSCFieldApp/Resources/Styles/Styles.xaml | 1 + GSCFieldApp/ViewModel/FieldNotesViewModel.cs | 16 ++++++++++++++++ GSCFieldApp/ViewModel/StationViewModel.cs | 8 +++++++- GSCFieldApp/Views/FieldNotesPage.xaml.cs | 2 +- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index d38cd3af..f28bbaab 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -215,6 +215,7 @@ + + + + + diff --git a/GSCFieldApp/Services/Database/DataIDCalculation.cs b/GSCFieldApp/Services/Database/DataIDCalculation.cs index db05a8ae..1529fbb1 100644 --- a/GSCFieldApp/Services/Database/DataIDCalculation.cs +++ b/GSCFieldApp/Services/Database/DataIDCalculation.cs @@ -24,6 +24,7 @@ public class DataIDCalculation readonly Metadata metadataModel = new Metadata(); readonly MineralAlteration minAlterationModel = new MineralAlteration(); readonly EnvironmentModel envModel = new EnvironmentModel(); + readonly DrillHole drillHoleModel = new DrillHole(); readonly DataAccess dAccess = new DataAccess(); public DataIDCalculation() @@ -85,7 +86,7 @@ public string CalculateTermID() /// The station ID to calculate the alias from /// The datetime object related to the station to get the year from /// - public async Task CalculateStationAliasAsync(DateTime stationDate, string currentGeolcode = "") + public async Task CalculateStationAliasAsync(DateTime stationDate, string currentGeolcode = "", bool followDrillAlias = true) { //Querying with Linq @@ -134,6 +135,23 @@ public async Task CalculateStationAliasAsync(DateTime stationDate, strin } + if (followDrillAlias) + { + List drills = await currentConnection.Table().OrderByDescending(s => s.DrillIDName).ToListAsync(); + if (drills != null && drills.Count > 0) + { + int drillIDNo = 0; + int.TryParse(drills[0].DrillAliasLight, out drillIDNo); + + //Increment only if it's higher then last drill hole + if (stationCount < drillIDNo) + { + stationCount = drillIDNo + 1; + } + + } + } + //Padd current ID with 0 if needed string outputStringID = string.Empty; if (stationCount < 10) @@ -843,6 +861,94 @@ public async Task CalculateEnvironmentAliasAsync(int parentID, string pa return finaleEnvironmentString; } + #endregion + + #region DRILL HOLE + + /// + /// Will calculate a drill alias name from a given parent ID. Results: 16BEB0001DH (Year-Year-Geolcode-three digit number) + /// + /// The field note date + /// The location id + /// If drillhole alias must follow the numbering system from station form + /// + public async Task CalculateDrillAliasAsync(DateTime recordDate, int parentID, bool followStationAlias = true) + { + //Querying with Linq + SQLiteAsyncConnection currentConnection = dAccess.GetConnectionFromPath(dAccess.PreferedDatabasePath); + List drills = await currentConnection.Table().Where(e => e.DrillLocationID == parentID).ToListAsync(); + + //Get current year + string currentDate = recordDate.Year.ToString(); + + //Get officer code + List mets = await currentConnection.QueryAsync(string.Format("select * from {0} limit 1", TableMetadata)); + string currentGeolcode = mets[0].UserCode; + + //Get initial station start number and officer code + int drillCount = drills.Count() + 1; + + //Follow alias system of station to start + string finalDrillAlias = currentDate.Substring(currentDate.Length - 2) + currentGeolcode + drillCount.ToString() + TableDrillHolePrefix; + if (followStationAlias) + { + List stations = await currentConnection.Table().OrderByDescending(s => s.StationAlias).ToListAsync(); + if (stations != null && stations.Count > 0) + { + int stationIDNo = 0; + int.TryParse(stations[0].StationAliasLight, out stationIDNo); + + //Increment only if it's higher then last station + if (drillCount < stationIDNo) + { + drillCount = stationIDNo + 1; + } + + } + } + + //Increment until record doesn't exist + bool processingID = true; + while (processingID) + { + //Padd current ID with 0 if needed + string outputStringID = string.Empty; + if (drillCount < 10) + { + outputStringID = "000" + drillCount.ToString(); + } + else if (drillCount >= 10 && drillCount < 100) + { + outputStringID = "00" + drillCount.ToString(); + } + else if (drillCount >= 100 && drillCount < 1000) + { + outputStringID = "0" + drillCount.ToString(); + } + else + { + outputStringID = drillCount.ToString(); + } + + finalDrillAlias = currentDate.Substring(currentDate.Length - 2) + currentGeolcode + drillCount.ToString() + TableDrillHolePrefix; + + //Find existing + List existingDrill = await currentConnection.Table().Where(e => e.DrillLocationID == parentID && e.DrillIDName == finalDrillAlias).ToListAsync(); + if (existingDrill.Count() == 0 || existingDrill == null) + { + processingID = false; + } + + drillCount++; + + } + + await currentConnection.CloseAsync(); + + return finalDrillAlias; + } + + #endregion #endregion diff --git a/GSCFieldApp/ViewModel/DrillHoleViewModel.cs b/GSCFieldApp/ViewModel/DrillHoleViewModel.cs index 656f94d5..7ca8ee9b 100644 --- a/GSCFieldApp/ViewModel/DrillHoleViewModel.cs +++ b/GSCFieldApp/ViewModel/DrillHoleViewModel.cs @@ -23,6 +23,9 @@ public partial class DrillHoleViewModel: FieldAppPageHelper #region INIT private DrillHole _model = new DrillHole(); + private ComboBox _drillType = new ComboBox(); + private ComboBox _drillUnits = new ComboBox(); + private ComboBox _drillHoleSizes = new ComboBox(); #endregion @@ -60,6 +63,9 @@ public bool DrillHoleGeneralVisibility set { Preferences.Set(nameof(DrillHoleGeneralVisibility), value); } } + public ComboBox DrillType { get { return _drillType; } set { _drillType = value; } } + public ComboBox DrillUnits { get { return _drillUnits; } set { _drillUnits = value; } } + public ComboBox DrilHoleSizes { get { return _drillHoleSizes; } set { _drillHoleSizes = value; } } #endregion #region RELAYS @@ -71,9 +77,182 @@ public async Task Back() } + /// + /// Save button command + /// + /// + [RelayCommand] + async Task Save() + { + //Save + await SetAndSaveModelAsync(); + + //Exit + await NavigateToFieldNotes(TableNames.drill); + } + + /// + /// Save button command + /// + /// + [RelayCommand] + async Task SaveStay() + { + //Save + await SetAndSaveModelAsync(); + + //Show saved message + await Toast.Make(LocalizationResourceManager["ToastSaveRecord"].ToString()).Show(CancellationToken.None); + + //Reset + await ResetModelAsync(); + OnPropertyChanged(nameof(Model)); + + + } + + [RelayCommand] + async Task SaveDelete() + { + if (_model.DrillID != 0) + { + await commandServ.DeleteDatabaseItemCommand(TableNames.drill, _model.DrillIDName, _model.DrillID); + } + + //Exit + await NavigateToFieldNotes(TableNames.drill); + + } + + #endregion #region METHODS + + + public async Task SetAndSaveModelAsync() + { + //Fill out missing values in model + await SetModelAsync(); + + //Validate if new entry or update + if (_drillHole != null && _drillHole.DrillIDName != string.Empty && _model.DrillID != 0) + { + await da.SaveItemAsync(Model, true); + } + else + { + //Insert new record + await da.SaveItemAsync(Model, false); + } + + //Close to be sure + await da.CloseConnectionAsync(); + } + + /// + /// Will fill out missing fields for model. Default auto-calculated values + /// Done before actually saving + /// + private async Task SetModelAsync() + { + + } + + /// + /// Will reset model fields to default just like it's a new record + /// + /// + private async Task ResetModelAsync() + { + + //Reset model + if (_fieldLocation != null) + { + // if coming from em notes, calculate new alias + Model.DrillLocationID = _fieldLocation.LocationID; + DateTime locationDate = DateTime.Parse(_fieldLocation.LocationTimestamp); + Model.DrillIDName = await idCalculator.CalculateDrillAliasAsync(locationDate, _fieldLocation.LocationID); + } + + else if (Model.DrillLocationID != null) + { + // if coming from field notes on a record edit that needs to be saved as a new record with stay/save + SQLiteAsyncConnection currentConnection = da.GetConnectionFromPath(da.PreferedDatabasePath); + List parent = await currentConnection.Table().Where(e => e.LocationID == Model.DrillLocationID).ToListAsync(); + await currentConnection.CloseAsync(); + DateTime locationDate = DateTime.Parse(parent.First().LocationTimestamp); + Model.DrillIDName = await idCalculator.CalculateDrillAliasAsync(locationDate, parent.First().LocationID); + } + + Model.DrillID = 0; + + } + + /// + /// Will refill the form with existing values for update/editing purposes + /// + /// + public async Task Load() + { + if (_drillHole != null && _drillHole.DrillIDName != string.Empty) + { + //Set model like actual record + _model = _drillHole; + + //Refresh + OnPropertyChanged(nameof(Model)); + + } + } + + /// + /// Will fill all picker controls + /// TODO: make sure this whole thing doesn't slow too much form rendering + /// + /// + public async Task FillPickers() + { + + _drillType = await FillAPicker(FieldDrillType); + OnPropertyChanged(nameof(DrillType)); + + _drillUnits = await FillAPicker(FieldDrillUnit); + OnPropertyChanged(nameof(DrillUnits)); + + _drillHoleSizes = await FillAPicker(FieldDrillHoleSize); + OnPropertyChanged(nameof(DrilHoleSizes)); + } + + + /// + /// Generic method to fill a needed picker control with vocabulary + /// + private async Task FillAPicker(string fieldName, string extraField = "") + { + //Make sure to user default database rather then the prefered one. This one will always be there. + return await da.GetComboboxListWithVocabAsync(TableDrillHoles, fieldName, extraField); + + } + + /// + /// Will initialize the model with needed calculated fields + /// + /// + public async Task InitModel() + { + if (Model != null && Model.DrillID == 0 && _fieldLocation != null) + { + //Get current application version + Model.DrillLocationID = _fieldLocation.LocationID; + DateTime parentDate = DateTime.Parse(_fieldLocation.LocationTimestamp); + Model.DrillIDName = await idCalculator.CalculateDrillAliasAsync(parentDate, _fieldLocation.LocationID); + OnPropertyChanged(nameof(Model)); + + } + + } + #endregion } } diff --git a/GSCFieldApp/ViewModel/MineralizationAlterationViewModel.cs b/GSCFieldApp/ViewModel/MineralizationAlterationViewModel.cs index 2512429d..63d3396e 100644 --- a/GSCFieldApp/ViewModel/MineralizationAlterationViewModel.cs +++ b/GSCFieldApp/ViewModel/MineralizationAlterationViewModel.cs @@ -111,7 +111,6 @@ public async Task Back() } - /// /// Save button command /// @@ -155,7 +154,7 @@ async Task SaveDelete() } //Exit - await NavigateToFieldNotes(TableNames.earthmat); + await NavigateToFieldNotes(TableNames.mineralization); } diff --git a/GSCFieldApp/Views/DrillHolePage.xaml b/GSCFieldApp/Views/DrillHolePage.xaml index 438feaba..c63731a2 100644 --- a/GSCFieldApp/Views/DrillHolePage.xaml +++ b/GSCFieldApp/Views/DrillHolePage.xaml @@ -39,6 +39,26 @@ FrameTitle="{local:Localize DrillHoleContextTitle}"> + + + + + + + + + @@ -48,6 +68,63 @@ FrameTitle="{local:Localize DrillHoleMetricsTitle}"> + + + + + + + + + + + + + + + @@ -71,6 +148,12 @@ + + + + diff --git a/GSCFieldApp/Views/DrillHolePage.xaml.cs b/GSCFieldApp/Views/DrillHolePage.xaml.cs index ebbe3f7e..7d756af7 100644 --- a/GSCFieldApp/Views/DrillHolePage.xaml.cs +++ b/GSCFieldApp/Views/DrillHolePage.xaml.cs @@ -13,5 +13,10 @@ public DrillHolePage(DrillHoleViewModel vm) protected override void OnNavigatedTo(NavigatedToEventArgs args) { base.OnNavigatedTo(args); + + DrillHoleViewModel vm2 = BindingContext as DrillHoleViewModel; + vm2.FillPickers(); + vm2.InitModel(); + vm2.Load(); } } \ No newline at end of file From ffcdae0ff8adce2e8360ebee2e28f79a18d94aa2 Mon Sep 17 00:00:00 2001 From: "gabriel.huot-vezina" Date: Mon, 5 Aug 2024 12:47:27 -0400 Subject: [PATCH 281/312] Forced commit, but there is no known changes... --- GSCFieldApp/Views/AboutPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GSCFieldApp/Views/AboutPage.xaml b/GSCFieldApp/Views/AboutPage.xaml index ce1e0d38..a647c9d5 100644 --- a/GSCFieldApp/Views/AboutPage.xaml +++ b/GSCFieldApp/Views/AboutPage.xaml @@ -12,7 +12,7 @@ - + From ff6a0199887b2f7fbcaba4d574105a1aa2cc6db0 Mon Sep 17 00:00:00 2001 From: "gabriel.huot-vezina" Date: Mon, 5 Aug 2024 17:24:15 -0400 Subject: [PATCH 282/312] More work on drill hole form and adapting field notes and childrens to it. --- GSCFieldApp/Dictionaries/DatabaseLiterals.cs | 2 +- GSCFieldApp/Models/DrillHole.cs | 2 +- .../Strings/LocalizableStrings.Designer.cs | 126 ++++++++++++++++ .../Strings/LocalizableStrings.fr-CA.resx | 42 ++++++ .../Resources/Strings/LocalizableStrings.resx | 42 ++++++ GSCFieldApp/Resources/Styles/Styles.xaml | 4 +- .../Services/Database/DataIDCalculation.cs | 2 +- GSCFieldApp/ViewModel/DocumentViewModel.cs | 4 + GSCFieldApp/ViewModel/DrillHoleViewModel.cs | 140 +++++++++++++++++- GSCFieldApp/ViewModel/EarthmatViewModel.cs | 28 ++++ GSCFieldApp/ViewModel/FieldNotesViewModel.cs | 49 ++++-- GSCFieldApp/Views/DrillHolePage.xaml | 114 +++++++++++++- GSCFieldApp/Views/DrillHolePage.xaml.cs | 18 ++- GSCFieldApp/Views/LocationPage.xaml | 1 + 14 files changed, 547 insertions(+), 27 deletions(-) diff --git a/GSCFieldApp/Dictionaries/DatabaseLiterals.cs b/GSCFieldApp/Dictionaries/DatabaseLiterals.cs index faffb6d4..b924e7ca 100644 --- a/GSCFieldApp/Dictionaries/DatabaseLiterals.cs +++ b/GSCFieldApp/Dictionaries/DatabaseLiterals.cs @@ -319,7 +319,7 @@ public static class DatabaseLiterals public const string FieldDrillType = "DRILLHOLE_TYPE"; //Version 1.8 public const string FieldDrillAzimuth = "AZIMUTH"; //Version 1.8 public const string FieldDrillDip = "DIP"; //Version 1.8 - public const string FieldDrillDepth = "DH_DEPTH"; //Version 1.8 + public const string FieldDrillDepth = "DH_LENGTH"; //Version 1.8 public const string FieldDrillUnit = "UNIT"; //Version 1.8 public const string FieldDrillDate = "DRILHOLE_DATE"; //Version 1.8 public const string FieldDrillHoleSize = "DRILLHOLE_SIZE"; //Version 1.8 diff --git a/GSCFieldApp/Models/DrillHole.cs b/GSCFieldApp/Models/DrillHole.cs index 22d8192a..f97e85b9 100644 --- a/GSCFieldApp/Models/DrillHole.cs +++ b/GSCFieldApp/Models/DrillHole.cs @@ -137,7 +137,7 @@ public string DrillAliasLight if (DrillIDName != string.Empty) { int aliasNumber = 0; - int.TryParse(DrillIDName.Substring(DrillIDName.Length - 4), out aliasNumber); + int.TryParse(DrillIDName.Substring(DrillIDName.Length - 6,4), out aliasNumber); if (aliasNumber > 0) { diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs index 4ebd3954..7aee88ee 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.Designer.cs @@ -483,6 +483,51 @@ internal static string DocumentPageTooltipSnapshot { } } + /// + /// Looks up a localized string similar to Context. + /// + internal static string DrillHoleContextTitle { + get { + return ResourceManager.GetString("DrillHoleContextTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to General. + /// + internal static string DrillHoleGeneralTitle { + get { + return ResourceManager.GetString("DrillHoleGeneralTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Date. + /// + internal static string DrillHoleLogDate { + get { + return ResourceManager.GetString("DrillHoleLogDate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Log/Relog. + /// + internal static string DrillHoleLogTitle { + get { + return ResourceManager.GetString("DrillHoleLogTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Metrics. + /// + internal static string DrillHoleMetricsTitle { + get { + return ResourceManager.GetString("DrillHoleMetricsTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to Azimuth. /// @@ -501,6 +546,24 @@ internal static string DrillHolePageCompany { } } + /// + /// Looks up a localized string similar to Core Size. + /// + internal static string DrillHolePageCoreSize { + get { + return ResourceManager.GetString("DrillHolePageCoreSize", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Date. + /// + internal static string DrillHolePageDate { + get { + return ResourceManager.GetString("DrillHolePageDate", resourceCulture); + } + } + /// /// Looks up a localized string similar to Dip. /// @@ -528,6 +591,51 @@ internal static string DrillHolePageLength { } } + /// + /// Looks up a localized string similar to By. + /// + internal static string DrillHolePageLogBy { + get { + return ResourceManager.GetString("DrillHolePageLogBy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to From (m). + /// + internal static string DrillHolePageLogFrom { + get { + return ResourceManager.GetString("DrillHolePageLogFrom", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To (m). + /// + internal static string DrillHolePageLogTo { + get { + return ResourceManager.GetString("DrillHolePageLogTo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type. + /// + internal static string DrillHolePageLogType { + get { + return ResourceManager.GetString("DrillHolePageLogType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Notes. + /// + internal static string DrillHolePageNotes { + get { + return ResourceManager.GetString("DrillHolePageNotes", resourceCulture); + } + } + /// /// Looks up a localized string similar to Original Name. /// @@ -537,6 +645,24 @@ internal static string DrillHolePageOriginalName { } } + /// + /// Looks up a localized string similar to Related To. + /// + internal static string DrillHolePageRelatedTo { + get { + return ResourceManager.GetString("DrillHolePageRelatedTo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Summary. + /// + internal static string DrillHolePageSummary { + get { + return ResourceManager.GetString("DrillHolePageSummary", resourceCulture); + } + } + /// /// Looks up a localized string similar to Drill Hole. /// diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx index 205dfadb..4239d0c7 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.fr-CA.resx @@ -253,12 +253,33 @@ Aimeriez-vous modifier les droits? Prendre une photo avec l'appareil + + Contexte + + + Général + + + Date + + + Journal + + + Mesures + Azimut Entreprise + + Taille de la carotte + + + Date + Pendage @@ -268,9 +289,30 @@ Aimeriez-vous modifier les droits? Longueur + + Par + + + À partir de (m) + + + Jusqu'à (m) + + + Type + + + Notes + Nom d'origine + + En lien avec (ex: une station) + + + Sommaire + Puit de forage diff --git a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx index 1ae33925..4bd6bfbb 100644 --- a/GSCFieldApp/Resources/Strings/LocalizableStrings.resx +++ b/GSCFieldApp/Resources/Strings/LocalizableStrings.resx @@ -264,12 +264,33 @@ Shimamura, Kaz – Senior Advisor Take a snapshot with device + + Context + + + General + + + Date + + + Log/Relog + + + Metrics + Azimuth Company + + Core Size + + + Date + Dip @@ -279,9 +300,30 @@ Shimamura, Kaz – Senior Advisor Length + + By + + + From (m) + + + To (m) + + + Type + + + Notes + Original Name + + Related To + + + Summary + Drill Hole diff --git a/GSCFieldApp/Resources/Styles/Styles.xaml b/GSCFieldApp/Resources/Styles/Styles.xaml index 714e27c7..7355bacb 100644 --- a/GSCFieldApp/Resources/Styles/Styles.xaml +++ b/GSCFieldApp/Resources/Styles/Styles.xaml @@ -383,7 +383,7 @@ - + @@ -491,7 +491,7 @@ - + diff --git a/GSCFieldApp/Services/Database/DataIDCalculation.cs b/GSCFieldApp/Services/Database/DataIDCalculation.cs index 1529fbb1..2d714dc8 100644 --- a/GSCFieldApp/Services/Database/DataIDCalculation.cs +++ b/GSCFieldApp/Services/Database/DataIDCalculation.cs @@ -930,7 +930,7 @@ public async Task CalculateDrillAliasAsync(DateTime recordDate, int pare outputStringID = drillCount.ToString(); } - finalDrillAlias = currentDate.Substring(currentDate.Length - 2) + currentGeolcode + drillCount.ToString() + TableDrillHolePrefix; + finalDrillAlias = currentDate.Substring(currentDate.Length - 2) + currentGeolcode + outputStringID + TableDrillHolePrefix; //Find existing List existingDrill = await currentConnection.Table().Where(e => e.DrillLocationID == parentID && e.DrillIDName == finalDrillAlias).ToListAsync(); diff --git a/GSCFieldApp/ViewModel/DocumentViewModel.cs b/GSCFieldApp/ViewModel/DocumentViewModel.cs index 02d6d470..60f88243 100644 --- a/GSCFieldApp/ViewModel/DocumentViewModel.cs +++ b/GSCFieldApp/ViewModel/DocumentViewModel.cs @@ -19,6 +19,7 @@ namespace GSCFieldApp.ViewModel { [QueryProperty(nameof(Station), nameof(Station))] [QueryProperty(nameof(Document), nameof(Document))] + [QueryProperty(nameof(DrillHole), nameof(DrillHole))] public partial class DocumentViewModel: FieldAppPageHelper { #region INIT @@ -44,6 +45,9 @@ public partial class DocumentViewModel: FieldAppPageHelper [ObservableProperty] private Document _document; + [ObservableProperty] + private DrillHole _drillHole; + public Document Model { get { return _model; } set { _model = value; } } public bool DocumentDescVisibility diff --git a/GSCFieldApp/ViewModel/DrillHoleViewModel.cs b/GSCFieldApp/ViewModel/DrillHoleViewModel.cs index 7ca8ee9b..eeff7077 100644 --- a/GSCFieldApp/ViewModel/DrillHoleViewModel.cs +++ b/GSCFieldApp/ViewModel/DrillHoleViewModel.cs @@ -14,6 +14,7 @@ using SQLite; using CommunityToolkit.Maui.Alerts; using System.Security.Cryptography; +using System.Collections.ObjectModel; namespace GSCFieldApp.ViewModel { [QueryProperty(nameof(DrillHole), nameof(DrillHole))] @@ -26,6 +27,14 @@ public partial class DrillHoleViewModel: FieldAppPageHelper private ComboBox _drillType = new ComboBox(); private ComboBox _drillUnits = new ComboBox(); private ComboBox _drillHoleSizes = new ComboBox(); + private ComboBox _drillHoleLogType = new ComboBox(); + private ComboBox _drillCoreSizes = new ComboBox(); + + private ComboBox _drillCoreSizesAll = new ComboBox(); + + private string _drillHoleLogFrom = string.Empty; + private string _drillHoleLogTo = string.Empty; + private ObservableCollection _drillHoleLogIntervalCollection = new ObservableCollection(); #endregion @@ -65,7 +74,15 @@ public bool DrillHoleGeneralVisibility public ComboBox DrillType { get { return _drillType; } set { _drillType = value; } } public ComboBox DrillUnits { get { return _drillUnits; } set { _drillUnits = value; } } - public ComboBox DrilHoleSizes { get { return _drillHoleSizes; } set { _drillHoleSizes = value; } } + public ComboBox DrillHoleSizes { get { return _drillHoleSizes; } set { _drillHoleSizes = value; } } + public ComboBox DrillHoleLogType { get { return _drillHoleLogType; } set { _drillHoleLogType = value; } } + public ComboBox DrillCoreSizes { get { return _drillCoreSizes; } set { _drillCoreSizes = value; } } + + public string DrillHoleLogFrom { get { return _drillHoleLogFrom; } set { _drillHoleLogFrom = value; } } + public string DrillHoleLogTo { get { return _drillHoleLogTo; } set { _drillHoleLogTo = value; } } + public ObservableCollection DrillHoleLogIntervalCollection { get { return _drillHoleLogIntervalCollection; } set { _drillHoleLogIntervalCollection = value; OnPropertyChanged(nameof(DrillHoleLogIntervalCollection)); } } + + #endregion #region RELAYS @@ -124,6 +141,62 @@ async Task SaveDelete() } + /// + /// Special command to set contact relation with other records + /// + /// + [RelayCommand] + public async Task SetLogInterval() + { + if (_drillHoleLogFrom != string.Empty && _drillHoleLogTo != string.Empty) + { + //Build string + string logInterval = _drillHoleLogFrom + KeywordConcatCharacter2nd + _drillHoleLogTo; + + //Add + ComboBoxItem newInterval = new ComboBoxItem(); + newInterval.itemName = logInterval; + newInterval.itemValue = logInterval; + newInterval.canRemoveItem = true; + _drillHoleLogIntervalCollection.Add(newInterval); + } + + OnPropertyChanged(nameof(DrillHoleLogIntervalCollection)); + } + + [RelayCommand] + async Task AddEarthmat() + { + //Save + await SetAndSaveModelAsync(); + + //Navigate to child + await Shell.Current.GoToAsync($"{nameof(EarthmatPage)}/", + new Dictionary + { + [nameof(Earthmaterial)] = null, + [nameof(Station)] = null, + [nameof(DrillHole)] = Model + } + ); + } + + [RelayCommand] + async Task AddDocument() + { + //Save + await SetAndSaveModelAsync(); + + //Navigate to child + await Shell.Current.GoToAsync($"{nameof(DocumentPage)}/", + new Dictionary + { + [nameof(Station)] = null, + [nameof(Document)] = null, + [nameof(DrillHole)] = Model + } + ); + } #endregion @@ -200,6 +273,19 @@ public async Task Load() //Set model like actual record _model = _drillHole; + + List dris = ConcatenatedCombobox.UnpipeString(_drillHole.DrillRelogIntervals); + _drillHoleLogIntervalCollection.Clear(); //Clear any possible values first + foreach (string dri in dris) + { + ComboBoxItem new_dri = new ComboBoxItem(); + new_dri.itemValue = dri; + new_dri.itemName = dri; + new_dri.canRemoveItem = true; + _drillHoleLogIntervalCollection.Add(new_dri); + } + OnPropertyChanged(nameof(DrillHoleLogIntervalCollection)); + //Refresh OnPropertyChanged(nameof(Model)); @@ -221,7 +307,15 @@ public async Task FillPickers() OnPropertyChanged(nameof(DrillUnits)); _drillHoleSizes = await FillAPicker(FieldDrillHoleSize); - OnPropertyChanged(nameof(DrilHoleSizes)); + OnPropertyChanged(nameof(DrillHoleSizes)); + + _drillHoleLogType = await FillAPicker(FieldDrillRelogType); + OnPropertyChanged(nameof(DrillHoleLogType)); + + _drillCoreSizesAll = await FillAPicker(FieldDrillCoreSize); + + //Not a picker but still needs initialization + await FillLogBy(); } @@ -253,6 +347,48 @@ public async Task InitModel() } + /// + /// Will fill log by with default value of fieldbook geologist + /// + private async Task FillLogBy() + { + SQLiteAsyncConnection currentConnection = da.GetConnectionFromPath(da.PreferedDatabasePath); + List mets = await currentConnection.QueryAsync(string.Format("select * from {0} limit 1", TableMetadata)); + + if (mets != null && mets.Count == 1) + { + _model.DrillRelogBy = mets[0].Geologist; + + //Update UI + OnPropertyChanged(nameof(Model)); + } + await currentConnection.CloseAsync(); + } + + /// + /// Will autofill the core size based on selected hole size. + /// structure class/type + /// + /// + public async Task FillCoreSize() + { + //Push value to a text box. + if (_model != null && _model.DrillHoleSize != null && _model.DrillHoleSize != string.Empty && _drillCoreSizesAll != null && _drillCoreSizesAll.cboxItems.Count > 0) + { + ComboBoxItem getParent = _drillCoreSizesAll.cboxItems.Where(f => f.itemParent != null && f.itemParent.Contains(_model.DrillHoleSize)).ToList().FirstOrDefault(); + + if (getParent != null) + { + _model.DrillCoreSize = getParent.itemValue; + + OnPropertyChanged(nameof(Model)); + } + + } + + } + + #endregion } } diff --git a/GSCFieldApp/ViewModel/EarthmatViewModel.cs b/GSCFieldApp/ViewModel/EarthmatViewModel.cs index 2e3006ae..71c5c109 100644 --- a/GSCFieldApp/ViewModel/EarthmatViewModel.cs +++ b/GSCFieldApp/ViewModel/EarthmatViewModel.cs @@ -28,6 +28,7 @@ namespace GSCFieldApp.ViewModel { [QueryProperty(nameof(Earthmaterial), nameof(Earthmaterial))] [QueryProperty(nameof(Station), nameof(Station))] + [QueryProperty(nameof(DrillHole), nameof(DrillHole))] public partial class EarthmatViewModel : FieldAppPageHelper { #region INIT @@ -107,6 +108,9 @@ public partial class EarthmatViewModel : FieldAppPageHelper [ObservableProperty] private Station _station; + [ObservableProperty] + private DrillHole _drillHole; + public Earthmaterial Model { get { return _model; } set { _model = value; } } public bool EMLithoVisibility { @@ -1107,6 +1111,21 @@ private async Task ResetModelAsync() Model.EarthMatName = await idCalculator.CalculateEarthmatAliasAsync(Model.EarthMatStatID.Value, parentAlias.First().StationAlias); } + if (_drillHole != null) + { + // if coming from station notes, calculate new alias + Model.EarthMatDrillHoleID = _drillHole.DrillID; + Model.EarthMatName = await idCalculator.CalculateEarthmatAliasAsync(_drillHole.DrillID, _drillHole.DrillIDName); + } + else if (Model.EarthMatDrillHoleID != null) + { + // if coming from field notes on a record edit that needs to be saved as a new record with stay/save + SQLiteAsyncConnection currentConnection = da.GetConnectionFromPath(da.PreferedDatabasePath); + List parentAlias = await currentConnection.Table().Where(e => e.DrillID == Model.EarthMatDrillHoleID.Value).ToListAsync(); + await currentConnection.CloseAsync(); + Model.EarthMatName = await idCalculator.CalculateEarthmatAliasAsync(Model.EarthMatDrillHoleID.Value, parentAlias.First().DrillIDName); + } + Model.EarthMatID = 0; } @@ -1287,6 +1306,15 @@ public async Task InitModel() Model.EarthMatName = await idCalculator.CalculateEarthmatAliasAsync(_station.StationID, _station.StationAlias); OnPropertyChanged(nameof(Model)); } + + //Might be coming from a less known parent + if (Model != null && Model.EarthMatID == 0 && _drillHole != null) + { + //Get current application version + Model.EarthMatDrillHoleID = _drillHole.DrillID; + Model.EarthMatName = await idCalculator.CalculateEarthmatAliasAsync(_drillHole.DrillID, _drillHole.DrillIDName); + OnPropertyChanged(nameof(Model)); + } } public async Task SetAndSaveModelAsync() diff --git a/GSCFieldApp/ViewModel/FieldNotesViewModel.cs b/GSCFieldApp/ViewModel/FieldNotesViewModel.cs index 02331120..2801dcfe 100644 --- a/GSCFieldApp/ViewModel/FieldNotesViewModel.cs +++ b/GSCFieldApp/ViewModel/FieldNotesViewModel.cs @@ -874,8 +874,8 @@ public async Task FillTraverseDates(SQLiteAsyncConnection inConnection) //Get all dates from key TableNames List stats = await inConnection.QueryAsync(string.Format("select distinct({0}) from {1} order by {0} desc", FieldStationVisitDate, TableStation)); - List drills = await inConnection.QueryAsync(string.Format("select distinct({0}) from {1} order by {0} desc", - FieldDrillRelogDate, TableDrillHoles)); + List locs = await inConnection.QueryAsync(string.Format("select distinct(SUBSTRING({0}, 1, 10)) as {0} from {1} order by {0} desc", + FieldLocationTimestamp, TableLocation)); //Get all dates from database if (stats != null && stats.Count > 0) @@ -897,16 +897,16 @@ public async Task FillTraverseDates(SQLiteAsyncConnection inConnection) } } - if (drills != null && drills.Count > 0) + if (locs != null && locs.Count > 0) { - foreach (DrillHole dr in drills) + foreach (FieldLocation dr in locs) { string dDate = LocalizationResourceManager["FieldNotesEmptyDate"].ToString(); - if (dr.DrillRelogDate != null && dr.DrillRelogDate != string.Empty) + if (dr.LocationTimestamp != null && dr.LocationTimestamp != string.Empty) { - dDate = dr.DrillRelogDate; + dDate = dr.LocationTimestamp; } if (!_dates.Contains(dDate)) @@ -1436,14 +1436,14 @@ public async Task FillLocationNotes(SQLiteAsyncConnection inConnection) Math.Round(loc.LocationLat, 8), Math.Round(loc.LocationLong, 8)); FieldNotes[TableNames.location].Add(new FieldNote { - Display_text_1 = loc.LocationAliasLight, + Display_text_1 = loc.LocationAlias, Display_text_2 = coordinatesFormat, Display_text_3 = loc.locationNTS, GenericTableName = TableLocation, GenericID = loc.LocationID, ParentID = loc.MetaID, isValid = loc.isValid, - Date = loc.LocationTimestamp + Date = loc.LocationTimestamp.Substring(0, 10) }); } @@ -1584,13 +1584,38 @@ public async Task FilterRecordsOnDate(string inDate) { FieldNotes[TableNames.location] = new ObservableCollection(FieldNotesAll[TableNames.location].Where(x => x.Date == inDate).ToList()); OnPropertyChanged(nameof(Locations)); - } - if (FieldNotesAll.ContainsKey(TableNames.drill)) - { - FieldNotes[TableNames.drill] = new ObservableCollection(FieldNotesAll[TableNames.drill].Where(x => x.Date == inDate).ToList()); + //Children + List locIds = new List(); + foreach (FieldNote lids in FieldNotes[TableNames.location]) + { + locIds.Add(lids.GenericID); + } + + FieldNotes[TableNames.drill] = new ObservableCollection(FieldNotesAll[TableNames.drill].Where(x => locIds.Contains(x.ParentID)).ToList()); OnPropertyChanged(nameof(DrillHoles)); + + + #region drill First order children + + List drillIds = new List(); + foreach (FieldNote ds in FieldNotes[TableNames.drill]) + { + drillIds.Add(ds.GenericID); + } + + FieldNotes[TableNames.earthmat] = new ObservableCollection(FieldNotesAll[TableNames.earthmat].Where(x => drillIds.Contains(x.ParentID)).ToList()); + OnPropertyChanged(nameof(EarthMats)); + + + FieldNotes[TableNames.document] = new ObservableCollection(FieldNotesAll[TableNames.document].Where(x => drillIds.Contains(x.ParentID)).ToList()); + OnPropertyChanged(nameof(Documents)); + + #endregion + + } + } } diff --git a/GSCFieldApp/Views/DrillHolePage.xaml b/GSCFieldApp/Views/DrillHolePage.xaml index c63731a2..03b5343a 100644 --- a/GSCFieldApp/Views/DrillHolePage.xaml +++ b/GSCFieldApp/Views/DrillHolePage.xaml @@ -19,7 +19,7 @@ - + @@ -117,13 +117,24 @@ SelectedIndex="{Binding DrillUnits.cboxDefaultItemIndex, Mode=TwoWay}" /> + SelectedIndex="{Binding DrillHoleSizes.cboxDefaultItemIndex, Mode=TwoWay}" /> + + + + + + + @@ -134,6 +145,68 @@ FrameTitle="{local:Localize DrillHoleLogTitle}"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +