From 9f10eeeb70efc52335212c56c53a9f5d932d2f06 Mon Sep 17 00:00:00 2001 From: Gary Sharp Date: Wed, 18 Dec 2024 18:40:23 +1100 Subject: [PATCH] qol: make attachment comments optional --- .../Extensions/DocumentTemplateExtensions.cs | 34 +- Disco.Data/Disco.Data.csproj | 7 + .../202412180604170_DBv25.Designer.cs | 27 ++ .../Migrations/202412180604170_DBv25.cs | 22 ++ .../Migrations/202412180604170_DBv25.resx | 123 +++++++ .../Repository/Device/DeviceAttachment.cs | 2 +- Disco.Models/Repository/Job/JobAttachment.cs | 2 +- .../Repository/User/UserAttachment.cs | 2 +- .../Areas/API/Controllers/DeviceController.cs | 15 +- .../Areas/API/Controllers/JobController.cs | 15 +- .../Areas/API/Controllers/UserController.cs | 14 +- .../API/Models/Attachment/_AttachmentModel.cs | 2 +- .../Modules/Disco-AttachmentUploader.js | 71 ++--- .../Modules/Disco-AttachmentUploader.min.js | 2 +- .../disco-attachmentuploader.js | 71 ++--- .../Device/DeviceParts/_Resources.cshtml | 12 +- .../DeviceParts/_Resources.generated.cs | 217 +++++++------ Disco.Web/Views/Job/JobParts/Resources.cshtml | 21 +- .../Views/Job/JobParts/Resources.generated.cs | 300 +++++++++--------- .../Views/User/UserParts/_Resources.cshtml | 31 +- .../User/UserParts/_Resources.generated.cs | 278 ++++++++-------- 21 files changed, 741 insertions(+), 527 deletions(-) create mode 100644 Disco.Data/Migrations/202412180604170_DBv25.Designer.cs create mode 100644 Disco.Data/Migrations/202412180604170_DBv25.cs create mode 100644 Disco.Data/Migrations/202412180604170_DBv25.resx diff --git a/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs b/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs index ab338651..962fff10 100644 --- a/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs +++ b/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs @@ -127,30 +127,20 @@ namespace Disco.BI.Extensions public static void Delete(this DocumentTemplate dt, DiscoDataContext Database) { // Find & Rename all references - foreach (DeviceAttachment a in Database.DeviceAttachments.Where(a => a.DocumentTemplateId == dt.Id)) + void updateAttachment(IAttachment a) { - a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments); - if (a.Comments.Length > 500) - a.Comments = a.Comments.Substring(0, 500); + var comments = $"{dt.Description} - {a.Comments}"; + if (comments.Length > 500) + comments = comments.Substring(0, 500); + a.Comments = comments; a.DocumentTemplateId = null; - a.DocumentTemplate = null; - } - foreach (JobAttachment a in Database.JobAttachments.Where(a => a.DocumentTemplateId == dt.Id)) - { - a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments); - if (a.Comments.Length > 500) - a.Comments = a.Comments.Substring(0, 500); - a.DocumentTemplateId = null; - a.DocumentTemplate = null; } + foreach (var a in Database.DeviceAttachments.Where(a => a.DocumentTemplateId == dt.Id)) + updateAttachment(a); + foreach (var a in Database.JobAttachments.Where(a => a.DocumentTemplateId == dt.Id)) + updateAttachment(a); foreach (UserAttachment a in Database.UserAttachments.Where(a => a.DocumentTemplateId == dt.Id)) - { - a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments); - if (a.Comments.Length > 500) - a.Comments = a.Comments.Substring(0, 500); - a.DocumentTemplateId = null; - a.DocumentTemplate = null; - } + updateAttachment(a); // Remove Linked Group ActiveDirectory.Context.ManagedGroups.Remove(DocumentTemplateDevicesManagedGroup.GetKey(dt)); @@ -161,8 +151,8 @@ namespace Disco.BI.Extensions // Delete Template string templateRepositoryFilename = dt.RepositoryFilename(Database); - if (System.IO.File.Exists(templateRepositoryFilename)) - System.IO.File.Delete(templateRepositoryFilename); + if (File.Exists(templateRepositoryFilename)) + File.Delete(templateRepositoryFilename); // Remove from Cache dt.FilterExpressionInvalidateCache(); diff --git a/Disco.Data/Disco.Data.csproj b/Disco.Data/Disco.Data.csproj index 7a1b34a0..04a4c91b 100644 --- a/Disco.Data/Disco.Data.csproj +++ b/Disco.Data/Disco.Data.csproj @@ -183,6 +183,10 @@ 202403030134280_DBv24.cs + + + 202412180604170_DBv25.cs + @@ -270,6 +274,9 @@ 202403030134280_DBv24.cs + + 202412180604170_DBv25.cs + ResXFileCodeGenerator Resources.Designer.cs diff --git a/Disco.Data/Migrations/202412180604170_DBv25.Designer.cs b/Disco.Data/Migrations/202412180604170_DBv25.Designer.cs new file mode 100644 index 00000000..d5d4c707 --- /dev/null +++ b/Disco.Data/Migrations/202412180604170_DBv25.Designer.cs @@ -0,0 +1,27 @@ +// +namespace Disco.Data.Migrations +{ + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + public sealed partial class DBv25 : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(DBv25)); + + string IMigrationMetadata.Id + { + get { return "202412180604170_DBv25"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Disco.Data/Migrations/202412180604170_DBv25.cs b/Disco.Data/Migrations/202412180604170_DBv25.cs new file mode 100644 index 00000000..42d55b0c --- /dev/null +++ b/Disco.Data/Migrations/202412180604170_DBv25.cs @@ -0,0 +1,22 @@ +namespace Disco.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class DBv25 : DbMigration + { + public override void Up() + { + AlterColumn("dbo.UserAttachments", "Comments", c => c.String(maxLength: 500)); + AlterColumn("dbo.JobAttachments", "Comments", c => c.String(maxLength: 500)); + AlterColumn("dbo.DeviceAttachments", "Comments", c => c.String(maxLength: 500)); + } + + public override void Down() + { + AlterColumn("dbo.DeviceAttachments", "Comments", c => c.String(nullable: false, maxLength: 500)); + AlterColumn("dbo.JobAttachments", "Comments", c => c.String(nullable: false, maxLength: 500)); + AlterColumn("dbo.UserAttachments", "Comments", c => c.String(nullable: false, maxLength: 500)); + } + } +} diff --git a/Disco.Data/Migrations/202412180604170_DBv25.resx b/Disco.Data/Migrations/202412180604170_DBv25.resx new file mode 100644 index 00000000..349de617 --- /dev/null +++ b/Disco.Data/Migrations/202412180604170_DBv25.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + H4sIAAAAAAAEAO1923Ict5Lg+0bsPyj4tDsRI0qyLMsn5JmgKcmmRhJ1SNl+ZJS6QbLmVFf1qaqWxfNr+7CftL+wQF1xycStUJdu94vELiQSmYlEInHL/H//5/+++s9vm+TRV5IXcZb+dPL08ZOTRyRdZes4vfvpZFfe/vvLk//8j//5P169WW++Pfq9hfuOwdGaafHTyX1Zbv92elqs7skmKh5v4lWeFdlt+XiVbU6jdXb67MmTH0+fPj0lFMUJxfXo0aurXVrGG1L9oD/Ps3RFtuUuSj5ka5IUzXdacl1hffQx2pBiG63ITyev42KVPX4dldHjK7LNirjM8oeTR2dJHFFirklye/Jo+/xvvxXkusyz9O56G5VxlHx+2BJafhslBWlI/9v2uS31T54x6k+jNM1Kii5Lvbg/6fiinL2hEigfGFkVdz+dUCHcxne7vMJ/URIBnFb4L/IgfKCfPuXZluTlwxW5bZBcr+iXk0enZkiKToZ7dSq30dUT0TOq6Y8yp1py8uht/I2s35P0rrzvBPwh+tZ+eUlV5bc0pjpF65T5jpZ+3CVJ9CUhHfipttWK1Inb/D1Kdq6c0j81zda/+VZfnfZKoFWN19lqtyFp+ZlstklUEh/NuFi7dzer4ySB7wbL/TUpVnm8rceYU9vPvh/cuI96vxja6Ns4KUn+5ts2J0Xhzrar0qkEXKa/kJRQu0NmJeJis83y8qwso9U9U/YFEEMnkfxtEt1d7RJSTE4FbbksSfo2yzdt2z9nWUKi1GNUfY1XpHgfp/8g61/ybLednBsmy1kJuCh+jddrkjrL8mP0Nb6rZmUJ47vsy/XuS+VZnDy6IkkFU9zH29oPeSyb7Ruhwts821xlCWDeebib62yXr5hRyiyAP0f5HSk9Z5keUZj5BQSjjbAWJpmNng2eEDhqnVr+fr5p8OkTd65RDe+t8cha3iqulZa3Q8KWi9r6nWfUpqcUJ8KGCIRygYOpTGhgXXmgdf++IzukD9pSjGqoXCEXBPKgs7IgCJWsTEOkXAzRqMB4kIhKUUObiS4jTfbuvqg303v7F2n53TPAbNB19TVdbpPWX1x/Yh5KnrK6pOLCzhGpVvma5mym87EspE3b51lRto2+Jqt4EyUnjz7l9K9mG+XlyaPrVcTQQWJ0s1uVsDQmqyq/UW2cbLNgOMRoIcAeQ03vIQ03uop/ZGGgB4zKujcOakT6jqPvB4+jD1G6u41W5S4nubNvN7jxelzN0Wo9Qzq1/Hxow6/JbbRLyk90tNxHBXnNtpFaE0b//hxvPFDWQ83PGDoQ/UeU51FaPtDSr/HaWVdCye6KbKM4n4yIEP7swMkBNq6GmcSNDR31N8IMKNPMlyLTmAASwCfz2pIneRwlH3ebL0xnnHfchdpuO5ODl79nRUFKr7YHD7n32SoKvglsb9TCeKgME/14GyfEPJXbIPs5Klf3Qch6nW2iOHXf2BgqXqpS8V1K1mw7cPrW30dF+ZGUf2b5P95nd1kaYhY8S5Lsz9/SaFfeM49rxbywN2medb6F76bteU4YLhONVrgqghIzMlshVvjC+BCrbLOJq33+MOTxGK9IVHA2pJ5Z5OJi6ExsWqE5TGPwhAvOdG40NmZIQ2UDcdNNyzKhEgAy5cpQfpt1laHTEFuV46QKxQihIowrmbwd03W9CKf0PV+Mdb4A49f7rGqNZmNwGEXIRjwq4SAYImgY1k8vXpMyihMdAzUESrhQjBAswvgR2u+c64jtoVCCFRCEaBXOc5ucfolvq2lMu2fTg6GkqzDYFrkKGGxTt8FXlyvjj33Gxl1V5jfe2KGx3XgTIVFRgmCINGHYAKufdg45oN0v9u8EB2zyou4+y0uvpuc7Vxy+29fsolzmd1EaF9VwOFuv2R2PQesZtgOxo73OfnUXpEJeLrATbFzQtr7sGFfC9l411KXCwhk9L7QooaSWQVm0kfOb9DbL6w2fVtznWfqVjbPM/VIFjBxn0xdxtVvHfP2z12erVbZLB2Pk3TG2S5GcrTfxYAE0q0jaEQW1Y1ck3kR3hM5A1UKL2fEDuALES25WQjh/o93Ndb3eNfwkgCPibFfSGSHuN7inp+aPOCcJNcXNHD8hIQP2h52XrLCnhy1sB7hK9fr1r+0oDfcYbA+r7Jyu3XabxDMcNHZctGvXiaXIptExD+kY/r/vokaNBu1MVw5iuB349tzw9yiJ13RyjROdFrlg9OvLAJdY02KXh9knrVBF6YrMNjAaZoJ0TMfNXD1D/eJmrT9xw39px07jPMi2xGI3Wa2CbSzLkIhngYL7bStV6Ox2FiXQG2FbHeQKBtZtniM1/PYdjczY7vbreyKsh9dL4JB8PbuzZiun6zNZ3Yc/6rV9V0XS0F6rVcsf6PzlccUrQMts5izKaLMd7C17Tmc+PIQ4Cgxh6TSGw2AbbRlqR4MDN30VEystpCUfHfggW1iR5mH6Wpvgav5msiWv42KbRA8ei+DhXvL1LvcwY8Pb/SX+StJZOP50n6XE69rZ8Kv9bzZ09SAdS9g27n49CbUUTM91Z919+Y1sHaQixYGTy13dteo43+CDijAgiVIxSKYM4+dZel9+0N/d0ADbXYQA734MPu+usMmn3d1HZXLoS1wns/ZxtEm0KhyoDwAIqBMQ3KCz7X48hJvI4IvA48bmmGlq9ImZEOAI3T0mSIBGpwgKYhpyQ6cDyABA04X3WDrMNfE895WPy+fj8tlxN1h6OB82hI8NBb9G6TrxUNlQDVNbQnKSrjyiNgSigAUnW+os4eiVQ7MF5rkH2QWRGoC2PxAQE63aDQ/tKkKOvmVBt1oHpV8JdWHgQ4EPsJktrkx85u0aj+6tG1itXQPVB5quEz/U6PRP5DgGBs4a8z6O+i2NLJlxs0eWTyWCLb7h/U+b5brbvsJYryis6JdugHuNfbrsPyQXfcZgTWOaIdvgatMbjMst7av1jGuUmoAwDyS/bcmKat15khVh7tfUmMaRjn37IThhW279Sqb1dj5EaXRHmDFqyn2urfxKkvVQ8npM8wm7p8Hz4frwk4uahCsSrR/eZnQVVO7yNIxoRZxzC7mmItRbYR7jfJz9EcUlbYjKuJrmV7wCDXfADDHZbrpyJd4Z+6z4I3yZq+dkCgjlEIINIUsb7GmQU6d9Q4jEHxHOXIIs4DVnO9BxiR8F4syO9pQMJnaWWAr2lwTi2mXiFIuSKYOJZIqlIJkSiJ9m8RMUSioEKpKrQoAkA2B+ZMPG38AAVgliBYbVMIVU8GVPtP1GxmRwmCURSsuMBOphUU2n8QIIMwgS1WIhFNtSgvA4rDZEq+IhAAqFMohAEcCDvvfZHUoZLQNoar5C1LRF4wR5bSY6KL5rU4SGdm3LPQj7QMqou2SP0ScAAUQq5RClKpAnue1jDR21LQxCLF+M0SrAeJL6MUttqOXAEIIlCIxmGWzQDYrWf5x8L2nfo3E7u/Em37nyyR3CKwPzkgIzdIvxMO8DUMaOd+OPh/vHw/3j4f6kh/vVrD/cxwcMP7IKCHKqL6JHFk82Z/oI2ChH+mJbuhN9PaSBibDn+fxa6DjfLmW+nTPs0kTJCjSGyX5lD4wUeOkfyir12BGjpALoiQzzrKreQziO36WM39l9R58IZT5DVb/VBWi+vAsWamAyvMiQ5IswkoINw3bb7MDGYsXW0AEZYEyfrdeh7s4xTDOZh6rtZmRPHnzjimyyr2GOwxtU85yBN43PJcbr92dvvm3jnBQhJPkpj6uAbsKtmXbc9YVDTHiFSp8NrjVecC64rhTPBNeDeOxrDz3EAEw7eMhhfQ+1tRBGwjhImLwOQEtkD+VKKjcQjcQKsDC5HIiWYB4uyMR5SLPmR/f90gBPDudcOV6sPPKvDGWYNXqeJVRLnYU9XNZVnKZ2JhgWzC7QDCDPUrsv/01W5cV6gjhjQw6i3LORYnZp0J0ubgIMMU+iNKpTqa/ZFI/ZPcxn45S7WtAAvvz7rCgu89cRi1wcwod6w2JL++aBCnCd1tfwDvdFP9/HOZ2g6IfzaFeQrl98Yz/L+DymsuEClYn44971Bf+LAFGOy5QUBSnYz6IJ80KcA70MF8bPu/wuifKHz/fktqRj/j5bX95Se5C7yiRAtJ3mJ0vrdE1IkJxYn7IkXpGPGQtwPVx9RWzX5TwGQaQivJTOc4riimxZaojMkbvng7m7Iivq+udXZL1bEfECuiUNLwfTcFnek5zOPYSOyspDz8vYeXAGOGWn3Xl520ZtHv4MKIo3b7N8c01nszDvijiE82zV1IF75woY3F8CGJ8An/0N90uQgF+J35S0vxwv6YkdvUA1DfUKtJkXtUoIn7m7PblXLvObb2wPIkqC7y1Y+ddN4++zu7swE1qL0XeAhuOJHcgmxCJ7ZtBR73KZGBkn4OXdIQODv1m8V2PjouhsRmUyhnqRTfofqofn90yuV+SfuzhQLH0M9zzTs0yN1SGbN+Jl8PgpikdhkeGdh8PWAb3M19TlieJAj7kBtEvgz9ulC0lFKBddQTqXm/41q56YrUgc6IRYQjnXSfE2otY1n8VrahsP5zW1GOfzmloKRvKadLOj7WsnPQ7tMyhdVcwNs67vfAiNTaG+gsDOqq3r+YjA/2Qbm1992e/rO3HfVvNhvqvryjsy9dqyjlbXco7UsmEcqzqIb5vdCJQIzZ6EsY4zx9r9CR2/wCRpyy1YVcsrUMOGU6iax9PzsI9VLegevCxmnIoxxA/pkkrL3dDF95wXKff+Ouih3MicLaXdZdqPzjfftuyQllqYK1Lskukvhl6mbWDMecgxJmBwybpQwxszL7BPYBxaDNYneUTobBGW9Aa+Nwq0ArrkOjgb0se7TAo0htwp1UPacBHshmmnzAc0eR9vmB76DVOmtbNmamUELCBhLDzBL2ZqX8Ck7plVyWV+t8yuJPgCXra6Vjj/HEueseVHzre0gODzx9xLUyaUNoQHbZIoYbHehWIkxrsIEyCvw2HGXpo/3voxdNOkLc/+/P4YuukYumn8GUTJMq3OIgoIMpOocCPkqrZKU22foXqywE6qiDSxnYzAFj0wQsamc8p0fBuvGLUHNLXTn1/jtYeVevF86CTTNZ2uybdhpyc+76teDt6sT0subsLPcRqxx0Qmx/zFdy+fO1+yTRns4Gc91SPbamwGubiXJOypYMi8EJN6mP7TBmcK0HlDhUHMFgAYwFod7oFrz9/QI9cF7Cccj1+Px6/kePzqYpfRA1jI8N3wdWQTjYIilhqHD575BmzKkgMX6gMfzYItgYezekg7FsY7oAWbQ45oTbB2vAQ7puUU/oAm/eNB7aEf1C7gjLRP+3o8ql3kUS1kOeHD2oC+AJxnzuw7eFnvs115n+Xxvyp+WHtHIz74yHbCAF5QQIDiXTH6oMH1a7cRfIMVXeHEjTcfUbqoTC6KKptsR8Zv6ZrkyQMlk9cHkc8PhK2Wu82p9eXt+/iW1q2OjH86eaIIRqhwnbEUtA3sUxNwSUdB2oE/M4C/r2KvN8DfGYDryFk9Lc9N8FnKFL+D/94A36aa6yq8eKL2W91Dul6LC6o1X3bMJLDPIfrsMiWfsw9R+mDbZ1UF+k/fbx6csKlVSWLc8VKrNcDKi+c6Vi7SWzamKpQ3zZ7sL7SkwEi1QXCRJOSOhe1v1c4dxe8xU9xVL7Hn7jg+ZXma3eXR9r7vqJcOaH6NVv+o7E0riRcOlakx+/bw88OWOgH9iHIRxM85idipEu3vs7uckDrKcDsUXMRRY3obp1G6iqNExfb0mUEsTKDRijJ1n3FK/PzZj89/fPHDsx8Ncmlrv9mwC1VdT3z/8scfv3v+/Y8GobS1L9JP1LXMemP29IenP/z48sWPT18ahNFiuP5w3XfF8+++//GH715+98KS9Q887S9e/vD0x+c/vPjhuxceA1mNqmmySD8/KMdmkt3+09YUfczyDTc0DaP71/juHhvGMK/UrcuoljFzK/idH+hk3F4V4pJrim3TyfAR7yfClfo9gYcuUikHT32BXVLG2yReUeFSgTx+rHJp2VLnvsot9UlrpNb+TWmquUhQxizMS0pnoyhOS9UPjeng3EaJA/8SDktvlnVc15pc8ppsScocUgfh2JDB4YEp6hqWPG+T8F6dcgpno4c3vKbodYIHxXXOrABavKiG2evyAAWDSJlMrSD57pcyUdpu46RlxGTNJGhcpRpAufPNVkxuAVWuUa0WwudkeoVIwV61GgQzK9fPUbm6v2mCfNtbLawarm5VDXczhjY0r0kzkTWZGpo6wk4f5dpLUErltl6tQRbqAtc0qCZ3K9xPSZFWUT0FB0R4JdWTNa2e6jvG3nRW1WbT0fq5WPUooTpoxHRDgoP0rwdxUToZMaBi9QnoKLqFtG7Te+2VkQHahAh1WOsTKQ2n/kbFkWAx5fGzWlADlkoUbiLVEDGhLiFy3jd96q6aW3a5eut8BL1SLqxPZ6A0VMyjXLLAbajgH1QtQcmUFwGWeoA/DhhB6dB3BbwDpjxtmMjIYcRN4IZZ9omVEwY825pxtVBxxl05q/5sLoHp/XZNTXy1IFZyXyzoGp18ErYmaSKrad0vNvTw9Zalo83+mJOiyDdHR9ZL6fKpcXNvTIUUabHpekNchIEKKXaF/brVRNUE6vguq7LGCVnoML0AYCH1a8BcNpIhzICm9cUjbSVrOJxgStZIwab1pvpslq1JOVt1j6ajWxhEdVwMFY8NVhc7RfTVFbnxaXREFuAe6YaNibEwLx46EsSsODJ8ScVK1saluAoaiG0J6bSrbpyAiVxHXKw2BIg1Zx0350lWWKqRCBpIjSSkk69JcBom1CRYsjYEiDVn1aTa6/yVJHbapIIH0igA8SxahdMxoWbhUrZfSPC1F6BhVyRaP7zN8voytYOuwRWDah3SxIz6p6dock3U94G9TsJ4FqGd9RV/J70UqwTWSAn5rLoI0zKDFsISd9E/EcOcmsdttDM10eiECInomd/BiIodXguNtyCAm59m1QwL1nLtvBDdsbFYloe6gbRovsXl/Ce6emHbELEw02R9nquvNqK6Lesw1462yc3bQRzlUpa6Rx+mOVMARLTP4emMBvfUEybY+jQKBQp1D6bLnm6b2VKFHk1/5psqcRqmmylxQe/LRPk+uzMZogYEUSFa6qg8Lb6pzY7U7jQGRxLeHpgaRrGNkeHhgurGfCYFan06YwIJdF/MSPUI2/YsVAFG1KeCc1QgFfd0R6N129W/9JeFCDpQFwEYbpzImGH22/LxbpwgHE5jdREhWFrfqt7so6k54jdqUQOnUyH3TVwB89QTNdT4hHojCXQPpuyO7D7CpU3fAlEug+qOGhZzspkcp2G6+RyXsw0NQhjl2RWLDzlq0/Vg2NGgygXFKZ3yaElHyAw6BgjchgopyvVcesZSfV+kxS6P0hUxzXoKMKJhApxjJBuwmannQZSCaSZDVM57MCOKtFfhD99m+eaaNmCyYYaqPspmsGmmFucwb5Y0TWfpLLvFhiCl8tya+keUU7bKBxvLx8NqdLEF87N7QiNzmD2IgOmsHiTjPTF6H7O0o/5stcp2FHl6d37PRHhF/rmLc7MX54JHo4IcCg+DaE3AXNbRlcBpTaVr/1ktSTR4lqz3VqtiaySzaLzzUnpSdZ9xke3cbT6Kvoi1uInTT1E8WMlbHLPoeNf4ElVcJm45Gi73mY+CtziWpN+fKDf3UUEu8zXJr6K4cLfhCIpJtBtrewnKbaBtPt02dJgNYQiKxWq27ZaEEcH0Wj37BoU1ZQvRaJ/NChDBkrT5Iv2aVQ8TViS2OCKwqD6JJkPtLkGPNXTNp8WaTrLalVGrL0mDLXbdJHA/DbXbe5ObmmP7DaFhuh04RN5L34SrBsY73d2fDgILD+eoND0+Oz0JdMFHYWMi26SwO6zdiVRCytHWftIqCVIHUxspzbZjZEGsMWRCrDPXjRbW0kDNBFbIogNsFa/ND74k5XNVvMmUboYYqhoqJrRpGqHvo4Uz77jrKk2ibnNdTrMhZT7F29OragAnNjfW9NUmUcNZr7HZ0TOfNu7xpTY4H4TxXY2+2oTJPWZ6hGNHzEQaadcZNsTM/kRHTKNjk2FLgHVMeGSVJlBsYJ70WiCTE6wvNBKwaX0J+WGa6MAOccgtI497JAFcQnTx+eOJH0IE8SbpjVXkcAEW1yf3zEMQ+nkihIM02HTpddjI4KCo7S2ViZrJ1EtJzWVQMQUeV7MhzpfajLW6hTZjKCkzaB0q/f3WPMtFgJP/H0j7ZvX6l+LwH4av7xMBy1hzfPO3qFBY1uRNtmQ4tIBYNVfnlLr4Nl4xLqzmZbUCrpkcrLtqAg3NNjXjtMwwN+M9sIeTs/7InoOxX7VabYHMcHAPMDOD9jgf4S9MYaR96v6jQYnQerhi+Z82mJpEDdmIx/uWNE02nxo7xF45Zz3o13Djo5ITq+NMuytaWmawitqu2H8rab4UoK82mVLOdTXAjphJ18KHcT0A5MXmgoCp4mQqOes1AVuK5tTMvb8qIEQmNkZR1NTRrIR9ov3qWpootKKy02ElIU0lUESGXSWtjHRtjSKkN1TzygeqeSXVO5K3goqLVfY6KiNWQL6VinBYpWtStnFQsvQ2vtvlFfaLkmyKk0c1DEerAgTIQUQrSwPCqkrbgJTvchUdL1ATdaI+g8TJo8UK5YdsTRIcXVVsiQrHYomAGrrbONHgaQAs0VU3DTTYmksg9rj6bUwDUn5b2YCe2XAIWz03WlSuDzkxFO0xsgUiPXcihKXUqkrdbIcLTYSzGVXIcLKpqhmNVkPxHZ/gAUHkIKl3XDx2BJv9mH5XxWNG0FRxrc0I+kjAIJY+AqIlKh0eGyRCCC0EmRTHzA5p81Qr1iHtH8XZ4exfgGnRCs/tLMam6DZi41P23i0R69BZDnTcCIm3WayQ2ZhZZ1PE7fxrJk/+0MUKrblj4IWVNXI9SiOis115n+Xxvyo/iLl9ED4FSEHL+XOgA3Gj+idcFdWjUOHlJYzsysPVOpe441v2a5S1kSXi1v9VEPM8SlI6FcVkLcIbwdfCBCdAmbjigXEh2chHwIRKBRa3t0QaR6+79IsKRQY0cSPB46LpfVGjhGScqJDCyae9g3sb0XWYlfagNUzcYRVx0XV+t1FyKO6p9Ey+JS8sDLSiRCpZcQzXNQhUmBXtJIu0gwoX6TgP6fZLj/rlJiBLGQTnSIKE5CQshDTCkVEBomgWZEFEwHWATgwymJ5+CRoTh62+QCinE0t3q9AsGvgCoo4X5QJiGBEp1w3HF5O68WQUl/76nI4/9PpcGPGhl+V4e6RuxgWy+OJWg/gQBLX4ukomS6ypi1t8ZePEaPB1zYyop2Dj7aafpTihA38zh9KRf3gRSof8o3hzzZ6TcDQAiA0Cw7kBoCEx9VthGslAuACJCPSHkMpNtxsHSqMr1lLeQiHcGznv6sMcB2bXoAD2nW/R8VasT9vhl1vCJYjHhCBB6XkQgb1FIaEZ0Zqy1s6TrDDLQYLSMyACe8tBQjOyHGoj+ytJjLIAIPWMqBW8ZQKgmkQuVyRaP7zN8itS7vLUTkJIHRsG4aoDpYYgnUh+rE3zOEOg7dgTKw2WloRuXDlxDnt12AOKRwLSsiHCIsKwXVKo+OA5KrwwDArjtl6FKwSVzfTqYrNWNdSwZc5mpeotubnWqe+kfO+I/EQYLVNg+nhJRvixhh7bqOMOyB9vEobdqNOkmh8ulomGXJsDHZYImCFdplnOkS7yXt8k0HMtZ0UfRQ2E3N44u3ZdDyYA92N8oo5Ws1TDMjBks5Y5wPNZi9JoL3Ho5YFnsB5z1SjnrtYJBslwDTOi5rj2F4qa1RrAFW60CGmYNQJpQcwcvJNyNVuSr8U1qsEAMgsbBIG88kBZUJ93DBWK+nxjRGvyTkqOa5AO+ugA5QZ6bTBUQtBrgnFkpCZ2hQVkSAArc4KngBVFI99408sHz/g6ytgy5Si1kZQhs6meQzy3aTgp4tlMx1M4IbA/LkU8/j/EEhj+X5UTf2fRLCcw0P9oymadGxKXmV96SYh15wSTqqylK6JmcTvnlBxPR+3yFfp1hOUU7J7xcOQumGrits6k5yd+OBGfqzCUVHwjC1/JvjeN7LEsb3ait8oRZ5KEKUtcYMGbEsPNIHcLl8Mxf5mTECzcj3ASn9APMWXJspO2Mb+WiX1dhq3AktYl1ZpGznqXT5v1ycSc3vEbJLdx3b+qG7Bdnb4Qp7iDwS6wma+tiaGOxuERS7ODcG2VlUdhxJSXR5KM8qzFICdTJh4A/YjicxCdu9hGFNnYF0rRyCZ28rJx0HXVRpLcJP430K5h/8xQw4lFw25aACFOtLcGP07Qne0YauBM6iuO+thiinMh8QGN4ZWUJoMCxo75hZT7M5/JnkdZXut2u8hteXXb6k3d2aTXs8Xw9Kg4NFHsAR7gOPaKOGxe5UAIJ9ASNaw6KhpDBHaAGzwGu8KRm7HBo65PIyqzsfax004m2ltg0xlmx/tQ5kouamFxK2qo5s36hgcIvIzK1BSkGeBTE6ZZkaAYVsAoQk1g5jGnQ2wVzRcb5yxsJe0w7Y28mq5bwaPcohKwDIwLsGQOjatIysVTNzWCKk+oFbaGAEdx+olydDFOMf5c1t2GGo48atfegeQ4yfobbNmwAjfWcWTUsAoPJM5JV+Jw+EZ8MjVHe4QmPW28R3VKtbtyq8M9+tVDbWxHSHzWsSBFHm2iQbq4XPbYg4nw1WmNoov62JW9Or1e3ZNN1Hx4dUpBVmRb7qKkDvPRFnyItts4vSv6ms2XR9fbaEU5Of/365NH3zZJWvx0cl+W27+dnhYV6uLxJl7lWZHdlo9X2eY0Wmenz548+fH06dPTTY3jdCX0wCuJ2q6lMsujOyKVsmiUa/I2zouSBbD8EhW0Q87XGwXMNsZl2xwa6lLtzjaYU1uV/c0F1nzMWn18RbZZEVMeHoDQmBLOXr5vKctMQyruCacKFjgolutVlER5G762jT6+ytiz3vMs2W1S4ZOsqjiO/yIPIobqg33936NkJ9HQfFJxvDqVhCH3wKnSBdLQkDvXquvVoTy8502LSouON6PAZM4CFfMChwIX47Vfk2KVx1umbiIaocAeXwgtfBsnJcnffNvmhE7fMmFqqT3my/QXQs0GlS+GHYZwaeGCTpx52a/p8ZZ0kO4ttocPV7squhbUlATi0CNUJUuSsoubUmfwBS5aVy0E3sfpP8j6lzzbbWXlU8vtsVeuHIpbLbXHfFH8GlOvXOrJ/utirJzeDXK1bz02D8umqzyOTXtXh5CQkXCfx7ePc81usqcfYHITUfrMbSYMY01trNnK45URSUXzTZfnWVGKiOovC1OoJjpgKGUCAyRaKxJSez/8ow9RuruNVuUuZ3srPEKxxAFjHZ9SQAUFlzfiqMMCKXig2N16iVVRJ9tblq+rkxlRcgCA67BWBw7/3Zna9uodLf0ar+WuQYGc26FDIYpzbSsyyMJMQTgr4G0AHNbEQu4rYVGizYqFYzwrClJCCIUCe3zvs1WkGpf+69zTHavYxOGFsXKFrnir6ysw1q7IFefrbBPFqYyU+R47umpkvxx7u7tOIuOUyxz6PCrKj6T8M8v/8T67y1LVRMIQDnQnSfbnb2m0K+/pMKqORddv0jyT5gkNmIMLkxNWT2VCKLDHVxGQQAjFEjd5V3VhQXNFLtq2yjabuFqtQ7RC5X7Yr0hUqM6HWr6weaKL8x1qumhz1PjOGmj9cRzH2tTw9V2Nz/V9lpcqGu7zfG5s46tc5ndRGhfVXHW2XrPdK9CnAeFcVkm9+e5v+2AGHksipeUnLso8/rJjBKp+sFrqsD3HsR4lv6Wx5LZC5S7G8jbL67V1y/55ln5l1lzuaQOoc5smxjRg9m1VbjCzcmevmxeKYiNQud/0zlyu5Gy9iVN8mudhnCfjMt8VdDq8IvEmumNxF6p5hxkscFLWgS9lo5WXDd4GDuVgAfr7Xe3KSLI0MIRXC03aln6hhzcFgdq3+UecEzpFFs3UhDSHQy1sym8vroea8cHMD9bzPVJ7qbM9vl/iu1Fyvdtuk1hZ+HZfPWhr75yD5GEX0nG8bDZQN3L6r26Y/r6LKh1QsfUlzh6OdlUNQTiM/mY76fcoidfU4MfS6gwqd8cO9plS6HAExmK5QCseocARH4sNA6srUOxMKyBbscSDWlCsaqmTj9tcbJP8WuS6m05z92vOn3/O4q/rB528uGx6g6YxHZ4xD8/C7tC1r0RkhPx3p1siJFWm3f6rw+lHTBeN6uFH99WBQ1qnKKONNBq4z2MahJkGUn1zdvi4ga4OWwwTuJrubsjAkREX2yR6UD0+ocDFTctVNe4+2uP5JaZreZUq7rODw3efpQQ65RAKHLYMNnQ6BDeIxJJF6XQ7iYfR7CZTq59+Y5VdtNzdwh5vlFrrSlgPQsToqTPT+wxhtO7oJcy0bJBuICtuH1Buj/3XKF0naqdyn51xXZFbkhO62kKQCuXO2NmYBNHWBYuxPrU3Xg147nVUqFWMiNd7EWNCo1+F4Lc4oHL3pay6lyGWzH1f4Lc0QimVyxajl8jbZ4+rx353jvfzsvGY6h5mehaTtsn41FJXzKqK898dlhzftmRVknWdXA24TAKUO0y7Qso25bqRUuqKGbhN40Vn81xderIBZeEwaSVLxQZpY/3dBxsmPRjCpwX4ch1U7opdTLEG4ZchhrWglxUO695qnQwNutCklvtiN3GjQrmce8QsijGVRuV0rNT+hyGWNHEGfLfj/2hnyhc7e/bK5p2Y+ixIRw1a7xvqj+b5AF7PcbF/XOwfF/vjGZ6gb/t4fH5mZ/JXfcuzOn+5N4Hvmkx+QfSPYvLTPLDiX0Xn/pIHzUJysyDK16Lz00C89mhqWDUJ6GL3fVqlrkKUAdun/WdHXODGKV/giK/RYgBhV2KPsYkgpvIrFDjjg3iWipxxgnzLZQ4nwe/P3nzbxjkpVOblMpfL/XF1d1q+0t9+XZzhCWl1Bpic/bnUHNo1uljJiOovbhho/Wwn3zPlvjtfEm6HwIPMpFw65thAx+7uy3+TVXmxliZ4/vuSRpqUXjLIiBNw+o08A4oxZ9n3WVFc0qUoewgEPGFVSh0OSdjzL3iXXCqab8x/vo/z9aeIfjiPdgWR3Wel1B+zau9gCP8W/rh/0DdQAbg8ICpTUhSkYD+L5hqdHP0LBbJv5+ddfke/Pny+J7clHQn32frylo4P2eLp4Jwe/VU/2ePsa0KA9/EwhEMLWRKvyMeMPeOSNUou88V6XQKjCgHxbQOQDFDui/08p8tJZkjz8mOma0YCdPFWV9Qjza/Ierci0FkNCOBwpFzeUwc6LQlV+ZJUAy1WguMhMA4Wj0r58rZ9ByUZPanM5SCYS5UMnQcrxZ644RNsAMD14Q30lMfnAU+/uQsi5EqX5sdwKQCD+THt2y1/NwbHMKYX8+YbHWJplKizrFjijvF9dncHX/FQy92xI8oHFLvjZrvnCQGjpyAgS9NwMc9lMCXnsmH667kWyZiqflF0K4XKkEpmSyl12NRC0pQDe3BayOEtgjt1Blj/VrGNRhxsYFs27PluTAKpts2s9VDDWrJhjIdzcB7VTNb4Y3YFaFA7EFMaMN+24JkAg/FsBXb3EJABbRhl5uv6CTmfoXfiAIA3fvA9HwzisixhIRjbcHHieoQvcceIuSpQuTt2REGBYnfcGlcFAVmMqwKlcR3uqahYPR9qmZCMs7nftgzdCG+/T323fMnHiftw+Bfufthl2mtkn5bgihS7RI5fpoV0abF9ymLTph52cZYnpL0ZYGWOB4dLOTgcL0VF/VxcHwEGgxlqH2wsQwibYGcNFmQHmtjEwQIK8Pi8H2W6BhUY93XaMdiAgyaNEbAoQKyiucIUjaWTx9cJx9cJVriOrxP6wSZk7g5lnDik/gmIdDjGMU+fmlityj4b990DW7om3xCEddGUrnqVeFO+atp9dDgTS6MviXwZo/vocra2jev8meCjb6HMYTshSbIVnOdAKpp68pp1sIffVoPweg/5ebbW+rbhB87u22sjx0E5brsdt90OadutH2ZhLdIgO3TcfFvK5tu4AZL7iFemFoZs8x034JwsQpOn4V+V73eVhclLpCD1sA8WOJZqJvwelqCTKLsKVbxTUl3x36dXJzqAslVcdQ50A+6Gz7Nsc7dNrADcW8OzJVMFXat31XiEN9fUEILvW6z0h2GDdIjJqGvZnajP7EYR5MLbEtVgAmnD0OBR2VpsmgBtOMOvTkGFcNKZ6gmfs+IAtTQvkp1USEE9XI9qlGGUSSXvqFHqplsbhsNNsbSVDWm8ndRM09BAbZMxB1A6HbFH3eN1T9qHd1Q+bW1F+yRoN/XTNDVU/2TUIRRQR+5fSwNbB41tKEdxSnIZpPMAmy/d76L9wDQpumty2Pf1rlf3ZBNV/BXbaFXt2KzJ2zgv2N3a6EtUkBrk5FG7u05924eiJJtala//mZwncbXL3QJ8iNL4lhTl5+wfJP3p5NmTJy9PHp0lcVSwjNPJ7cmjb5skpT/uy3L7t9PTomqgeLyJV3lWZLfl41W2OY3W2Smt+uPp06enZL05LYq1cEzPLVX6Pfjb+G5Xb21fUApF9Xj1X0TRurY/rsiteAKv9J4KCRyrvzqV23glqVCDnlH900n6NWI3jemy/UP07T1J78r7n05ePjl59HGXJGzL/6eT2yhRH8zJSCtKwqJsTvxFpP9rE3373zyqMpevBfBLDW1nyaPbp6/UYWbuAFZHI6rv3EUl7AdpUD/73h23WV1eOON8GyclyfkNCudeVpFepr8QapdoRwZHfLFhT2r7WxUjNdBeD7zaJe28PRAzxVaWJGUPSFt8X1jiV2f9UjfiAlCn7rsFQHpR/Bqv1yS159faYGCujq+pAMHQ+XuwYXnmPvg5YjSIvx/NYD19YqLZ3tqLi4npjX3MHJTKm27t1PoTG515yqBIRa/nyOySXnItuY0azw6xQV0HTaxxrskq3kQJc9ToX8yAUpTUNWO+Li1+FrazK7EcTEfbddD37h1EneXdbbQq66AAWgPijrvqgjGQ1jfsNIifO+Nt4kSJeX4bxaV/lzHbl3dFWVsdvyHgQHT7wLpdAY0jmvqFWZA2HMey10JKcw/DYp0k1Nb5v+7zKl1tk9ICtXtH9ZGi7NcB9oocYqJheD7VKdRRTA5zX5f/1Jsk5hPsyvYtqda2uqKWcw0FRc6CLn0k5Z9Z/o/32V17lW6YvWJ36P78LY125T2bqKrrdG/SPEuGLB/Oc9Jfy8Pps8JVEZOYkdkKsMIXxtKvss0mrlaFYcjjMV6RqOgHtVHJHY1rMxwPxFUyjmPzqgKYDe5ZUC0z5iU5ds2kfZnfRWlcVNNCl+E1iLXsds5MC3c7ScRFmcdfdoxO3rvzmRt4nqPktzQujTTaMP8mvc3yehXZyuA8S1mERq77fExkgxgn2wdp5acx63H2uoksMgQbP5cxLyM5W2/iQUw3kw0VPAv4dkViFjrzXfalssl1aOTF7VnxUgiOnHsZ0frYyj7g0MUT10Zz56lfNARv7I84Jwm1N80EE6gdx9mt8hD/KnObxzRhu961myd3220Sh99I6Ihs3u4GlgEztWOu0hn+v++iptMHrJ6qGT3UYqzdNPg9SuI1NcRxMtRnbTEi3eS3o1+FlwziUncB38ZS04bWILLsiA0pzP41RABky59jfaYK7PX03k4aNhslVoj499bWWxm2J8LN62t7u26FuH+MHRgx9zR74JSJDUlHEq1VnfXgQu46eGgKXSXSNeeD0RHyMN7Xu9yogx5of4npAnEMej/dZymx2EX2OLR7s6EzjrRZAOM27Vs6qSUUCsVOObHXgtPfrxrHQJqv4fjsapmubfngHP3eVpUt+NDm6FFOCI7z9VLmaytvGoimYn1P0KYBLrLKGHiF4CpB9VgIszL2GqAyL0isAjvzYhMFAKjWLnugp/Rm+wQ1GvzQmqNv4CAa9WS0fQbrs2ngchvwQOae8W75DVBJ2wukwZXnckslux5v6qzxhzkM/7YlK6oC50lWhNkgqzF5MW+PPgShdVCJ7nzozvsqyq8kWQ8lpsc0muT6Jqxu+Hgs+eoWrki0fnib0cm8pKvhMIIRcY4sorqRUDcweIyjEf5HFLOcD1RCle+x4ns3/KRVedcL2f6Z6uL4MIkd3GKzSaRz3Ag+LiyPC8sJFpZ0vB3aw5MFm5ARb9TN8ZaFSvp9dndUm7HVZnw7bnMt0kUt2igzh6MbFUfDFGSwhnHhNofucfGhNsMqa4W60bMgdy6EMJ7DVk1S/M6gE3aDOyTn1+/PqnDEpAjB/Kc8rq5Utnjowu7BrIXOo/5AhrzxVNznAHLE+b+Ol6k7xXdf0vKxM7WS8BBEdVuwVfAhFw/91BoYbFxMwlH9bZZ3trtA5zNawGSz5gEzePp5nxXFJV2RsLvwIQzSG/Y6we5VoM+eITrUvGzx5/s4rzK/P5xHu4J0gvR5ACDjGuMGjtzGH/f6+xQvfK7QlykpClKwn0VzJUcNDyLaCg9Wft7ld0mUP3y+J7clHT332frylo6sXM+Rz7Wl5id7fndNSJB3i5+yJF6Rjxl72jBMbURM1+Uo40ZsJLwAznOKgoV4y8uPmZb45+7EX5EV9cHyK7LerYi4W43EfnI/gyvvWQ4N6l2QonI08iqteeh9MSrry9v2ZcHwo7Mo3rBIO31W4IAIR/Gm69vqI12C59PcDsHvOuvDqeaXPem/+cYc6Shx9YetHIAGN5/SeKBL0WC06+ABJEuJjMc6EWNa8zFL91FxLorOya3MxZCZT84+f0X+uYsDPbzBcI9i1uTGrHZ0vBFPwsKnKB6FA4Z3FAaEDPZXURzo2geAdgLyLSeyQY2E8hoUpCN5Dl+z6mrEisSBtg0llCNtH7L4RRahXjwmrRZ3uHm2xTjaPNs2MMU82wa3HHa1doF7mC1jwybyEY8Jln6WsSdHD0FfzurThgVpQJ8jbLzNVzjJ/d4O7+MRxZhHFKOEUalfEo7yNB1L5TXiiB3/xYv/q0vPly4jv8Ac/ynM8TWmpEIHd0V29Lcrxyu0xyu0xyu0ruHbCZI6fm/tzCcuA73Ovjz3x1ynovdfmpoPzl+6r6WatPQ1Vor0S5xG+YNnUEYGO+jQV85HP3CTVUxEPwxZ4InIccAd5I6NmP3df2BM8OT6uH9z3L+ZeP8Gy5S+t8P9uIMz7iXTUTZasMzsxz0cebwaMpcfh22w+8fAnMIlRR+vhzXpyK1vp8DpUEFQXV5SfY0BuctaEv29MYly65N6V+RhoqX4vPMapgGaXOCLUoOezqMu6HPYDVMJq4Tdy9EMiNyjghhS2g7UEKuU2gtSEYhe693Uv5DecMm++6bbdrvU7yKtb9L1I+Zd9jFkGspYPu3H3bcPdHUab5N4RZulLprCsoCm1U0JU/dZRPZvCrJmV7uM2VXhtCjziNoCVdvidBVvo0QiX4KzdIuZUDuMcslrsiUp83dVFm1a06Zu73BLg8IkAyG1u14JuLQCN5K5xbWBT7XJ96PwXezIJ48f6xRDztSqYuXKRlERNH3oOGqiTU2LNCmlgJhRX27wZKvjawmA7JB0Ys9U4VOd5qfRCJPNaKCBLuxK7GeTedThE5Q4byEK8anPsTmjSlRZJywVok7UpHZh830PzAOQamoh2tBl/5hzpuCD/qK6UBXy/VZ/WHTvqwzN3u1ygOUF2AA5d9Xk3oKTgdlnv8HeDsEZxeZWlv464Q2ew29Q71oqC3evEUHMQxzOzKJNhIWq0lImGlmH2ruWw+ac/VGZaacjH13hb7/Ooih9tqGbcTWDS2sko2k/77UOYGmbkNZm73TOLIzuhkqZimRsB2MHdBmZ9kAPxp8ejoqAtriImYD3N6VDJNzplAGF2V4p3CvDoRfCYnQHepUxo9spZo6aerdDylul+p4ywF5bGnOuLqTdBe2LSPoCbe747Gnti6o4bGYZXphOoDZWL12nUB12UQ7O4jLGCb2M4iDO5PfiMJ7186WQimw893S6jp5qerDtZVHCs3a2mHptVIfhr9vfan672fpbTRp37PNR+hzOzjdzv8M58Y4aMKIG4GkIZ9cFMcHgUQtG1QI1m+Ns+07Mk8dvxRy7e0h3L2CBr+9e6wX9Yrp4jhW72+hexgKd205W03M5dZyh35E9YqlkrCX7RKPdcVMYDMU9S99PsnCfUQUmtPj7dqgkKsIizpTm1ZU5TpTc9WYxB0p8xtiR5xD4oY1YsOcziNvTmpknkL7fJ5k/Zuv+CWcPt/5fwuTxPrsbediznMIShurTng91JVUy0tLMg5z17yTDe9JunnBI2/bzEgZzHdGijeKhfVhdJ3eVOqz56NTvXW5oCNeoB7lAftrRtADOgI00947LLz2rKjRH+CMa9/l6f6Edv4g+72IwjmrxZ+r7CW2/U+cLgS9nVwEuwOXY2/5HPRCak0KLzqUJQl7qkWcBMQe2hEsqtNCuhU8JmozfSJszzwuiKijZXse2D/7asX+Wwl03wOS7c2pKm510ApvRJUIFlKIvOwyLASd9RZpcgMHg8tTe6JKqTmE9+Jy5gKoIxYdgQdAcwUirpqS3S9WjQOuUoxKNoUSLWM+YNKhNK3xUoOUpEJ/yeSn6g6R1PqrP/Oqjybi9SO2Zcvl01B0H3VnKQorXHCDn+FFv5tcbJBX8UrRm/BW4v4Ls6zrcVUXmXIozfRQTo920n7TWowKQLUj90S2UiJSVDUI5yUN/leNxdARgyqbVttrSFGXcODNLUY6FK8aSlGKCg+GjZuzJaTGgHlMdGh91ZG9OkuvXTk0Aw+kCxwCBDMWCg3l2JrBl0/Ji3p/VhCgRdEd/hii3C2CcKFbuHJriFSt3idoyVazceRVlqinGSzlmv7OsmpAlPGBbgt7M8YzNz8As5SVbk9yIUhffxiuWlW3S+YhrGEokxZce2IzE87aHU5K0BkKzkssdrmyy8Z9dJynNaggGGFGHptpsAxmzV6BZN9w0qjPF8mhJ6jKHyfFWmqVanQk25pakOdN6xXu5PQeqyVQbdEdd2bNtuualX5tS9+Y62+Waqcjq8Fjm4zJ9TRJSkkdnK9byTyfnUbGK1mq24VPakKbld2g+3ncTpOSd6Kj5nXNGXjiF9RzK85nd3it1yuOWT/lQVcmlg6HOxTQBDwc9rgbqcqmb6mjJnvL1u5sVdHkGP5YSt68LEU1Wig/pPb2jhtZdvCwl2x9ruRRFW7bd9FTNfTaezT4eHwfM1oZKVaGtTyy800iKLrWK6LsGasS9Erf4UEEWNBCL9vslvU4sUjn3xPYuUyWXbYmHae++G2TpUM3JIg85GR1rAEjNYiNAA3Y4p6w4k1Z2WVaNZSrpvljmhSrmwm3zMBXeK+P8htYpH2idktYgeRu1I1uTt3FelK+jMvoSFao5ZrWuSdnBp7fx3S6v0F+UZHPyqAbhlAyAuV7dk03008n6S0b1MfqSyKiAPXyxYdXgK+2qIFCzMlRhbJofJEqjfCHUHGdLzDzK6wyVRRkC5FAEsm33A1WFBG2zKcXbqwBs20Kb0bVgi5wOuts4wdvoyvGmGhDbFquE7mh7TSneWgXg1hh/b0vXLA9nIKAHNVNSH8UpDdefoXZYiR3a9mI0iLwtxJqoy+0a0opQBsAadBEanCkU6T0ZDO88EdLKnMF2DDVgVjhx+6g1jnaW8Z0YcB9qxdRbAohVizpDLBYj7TmY4HdNlGGooaoAaYKWWSHvYxhCLfSlSDN9KF7btjQN6VuxakKKtgY1JYEgTQpQ1k33b4mxlnsITcMNUGzfsPCOGWtbANI038PZUAA9ZgLNpgyEmU4Rzp4ATbP6xmwtNDoDicW4RbadhdQr2EiTdrO4+1wk3ObFnE0eRuNu9mC2rRu1CQbDaXDVKP6iq6ZxU5Pmhs525X2Wx/+qljps6Qm0B8BAzSpgVrbDtISxWMUU/LaIy5SjbVgB0k4NTiRotqFN6yoTQfIKy40uzR6McU1rpExe3WpJ47YKFF9OrMhBio6dACbvYgj7ZDyHtDXum7L7Ae+viVW7z/IumciUBcPc+vVGXTurnGvhcVaAVXbFi/BdIwpkd4DDwZUFEsqNQBwmCgFqbAEAVYOx2yz7b7r9BoxjGdBEtLQlwdHelczKeLUBYGZbBDMRLOyKcFQ332dl+Kb2E5oryLhmC2A4wfx+SEVu/WERfXob7ZLSahyjNcYe006aMkwgyjPvpg2tTJBKYw8AZKdPxsRDjCSq7o2ztZzgV9FBBs0cYuk3F28wOcggIRlXN0a7eu3nICxyHahjUwYLzSrSuXJRaJZ1Wo6BHgjr6tmZUQSmOwfaqxz8kFUKFyIiaHvd0m/QVQpvEOEjBc4eygDjiKb1XyyFAr+69HGRFiGSd/Xjk3pNCi6Xu+JRlslynUAsXW4JVVydZQSgQqr4eKydJ1lhZk2C2g/Wah3/lSRG9gDIfWLxikTrh7dZfkXKXZ7aMYvU2S+2Gelm5UWgl88qa/amPnCEHZG6cPmMNPsIGCt8ceiZcDQl5JzACieoexLQIDJleMQDlEoCs2oYa2MvDuZi22ZlYKgxxcJgUvEIjzgQgYgwQdUfPgMQC8KyadB9ADCw6k/FcptGHuYTTDI/tDe5ez9tlepTKHYMfYcnVh/ea2OyJucIh7nTZhKXyRUuLrUENx/1jMrXq4TKweZdIRe2ht93ULrsoWo6MYt9ICEDo0jEoeHKOzHDfEgcA8to9Jx9YVrN6QtzbMj9O1SlwVuEbWWpMDzbav5aGyEYst4O14A5hCIkisGlgOeTCaEJ8sVKnue+LBTL1mlJcXH4ZTYNoyHARVReXkLxFCIzTReeGTwPU1hdskk/WcG5Kg9DVFheRTtJWWVlPEBBWcxgjukHD0NIULY8OxEZ8+wdhoD08702hVyIKX9S9tU3D30SNGST2ypnmqIJ/IX2Thvqj4aTdfhGvoAj6JkpwqODOILfv1iACLS+jBb+AIVhWBYbauy7QPj3RMb7FZrkRgFOk6C3UVzdYNfQ5LdMRrYNiXuCsa69cTjCxSOn65fT3LycUQQ2x1DmSlOcRM0jKiBfCCohU26RYEMGeF/IIRBKA4kBT4KBSsMybwbAnuJo8Z+NwtHMJTDAmCJyFM9I+rIQkWgdMEON8EZ3IUIxOGLGOocgmHdwdHr8uqc21t3QFew79G3ku5DPI2VWmohoFkxDsdNkJtxed84nAjQot+7c2VUDhh9AI9JQiscRiVY17CJOh9WPycUiPcS1VBiLWkZXy+ddsA4PIjUN1KjCw1XLotZYGrYAkVkEWIVk5hqXday1kjEWAohzOhFq1M41amhIvZtQbCzsKMPYRY7syl6d1hEomg/0Z5nl0V0TCbD6+ur0ip0cbkj96zWp3kG1KF5RnCmpop72SFuYi/Q2a8NnShS1IG1x05Fsy34dldEZW1ZGq5IWrwh1/1K6Gvs9SnYU5M3mC1lfpJe7crsrKctk8yUR9vZZ4E1d+69OFZpfXW7ZryIEC5TMmLJALtOfd3Gy7uh+GyWF1GkYChbR8xdCv9d9WdL/yd1Dh+kjtUF2iBrxdYFIu5Ail+l19JXgtJllKErs1es4usujTdHg6OvTn1T91ptv//H/AXrVQ6nonwMA + + \ No newline at end of file diff --git a/Disco.Models/Repository/Device/DeviceAttachment.cs b/Disco.Models/Repository/Device/DeviceAttachment.cs index feede63e..66c9aa33 100644 --- a/Disco.Models/Repository/Device/DeviceAttachment.cs +++ b/Disco.Models/Repository/Device/DeviceAttachment.cs @@ -16,7 +16,7 @@ namespace Disco.Models.Repository [Required, StringLength(500)] public string MimeType { get; set; } public DateTime Timestamp { get; set; } - [Required, StringLength(500)] + [StringLength(500)] public string Comments { get; set; } public string DocumentTemplateId { get; set; } diff --git a/Disco.Models/Repository/Job/JobAttachment.cs b/Disco.Models/Repository/Job/JobAttachment.cs index 6445dac6..690154be 100644 --- a/Disco.Models/Repository/Job/JobAttachment.cs +++ b/Disco.Models/Repository/Job/JobAttachment.cs @@ -17,7 +17,7 @@ namespace Disco.Models.Repository [Required, StringLength(500)] public string MimeType { get; set; } public DateTime Timestamp { get; set; } - [StringLength(500), Required] + [StringLength(500)] public string Comments { get; set; } public string DocumentTemplateId { get; set; } diff --git a/Disco.Models/Repository/User/UserAttachment.cs b/Disco.Models/Repository/User/UserAttachment.cs index 6c4b9584..7be3c5a7 100644 --- a/Disco.Models/Repository/User/UserAttachment.cs +++ b/Disco.Models/Repository/User/UserAttachment.cs @@ -16,7 +16,7 @@ namespace Disco.Models.Repository [StringLength(500), Required] public string MimeType { get; set; } public DateTime Timestamp { get; set; } - [Required, StringLength(500)] + [StringLength(500)] public string Comments { get; set; } public string DocumentTemplateId { get; set; } diff --git a/Disco.Web/Areas/API/Controllers/DeviceController.cs b/Disco.Web/Areas/API/Controllers/DeviceController.cs index 717acbaf..3e235852 100644 --- a/Disco.Web/Areas/API/Controllers/DeviceController.cs +++ b/Disco.Web/Areas/API/Controllers/DeviceController.cs @@ -512,8 +512,8 @@ namespace Disco.Web.Areas.API.Controllers return HttpNotFound("Invalid Attachment Number"); } - [DiscoAuthorize(Claims.Device.Actions.AddAttachments)] - public virtual ActionResult AttachmentUpload(string id, string Comments) + [DiscoAuthorize(Claims.Device.Actions.AddAttachments), ValidateAntiForgeryToken] + public virtual ActionResult AttachmentUpload(string id, string comments) { var d = Database.Devices.Find(id); if (d != null) @@ -527,6 +527,9 @@ namespace Disco.Web.Areas.API.Controllers if (string.IsNullOrEmpty(contentType) || contentType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase)) contentType = MimeTypes.ResolveMimeType(file.FileName); + if (string.IsNullOrWhiteSpace(comments)) + comments = null; + var da = new DeviceAttachment() { DeviceSerialNumber = d.SerialNumber, @@ -534,7 +537,7 @@ namespace Disco.Web.Areas.API.Controllers Filename = file.FileName, MimeType = contentType, Timestamp = DateTime.Now, - Comments = Comments + Comments = comments }; Database.DeviceAttachments.Add(da); Database.SaveChanges(); @@ -554,10 +557,12 @@ namespace Disco.Web.Areas.API.Controllers [DiscoAuthorize(Claims.Device.ShowAttachments)] public virtual ActionResult Attachment(int id) { - var da = Database.DeviceAttachments.Include("DocumentTemplate").Include("TechUser").Where(m => m.Id == id).FirstOrDefault(); + var da = Database.DeviceAttachments + .Include(a => a.DocumentTemplate) + .Include(a => a.TechUser) + .Where(m => m.Id == id).FirstOrDefault(); if (da != null) { - var m = new Models.Attachment.AttachmentModel() { Attachment = Models.Attachment._AttachmentModel.FromAttachment(da), diff --git a/Disco.Web/Areas/API/Controllers/JobController.cs b/Disco.Web/Areas/API/Controllers/JobController.cs index 978639d8..70b917fc 100644 --- a/Disco.Web/Areas/API/Controllers/JobController.cs +++ b/Disco.Web/Areas/API/Controllers/JobController.cs @@ -1919,8 +1919,8 @@ namespace Disco.Web.Areas.API.Controllers return HttpNotFound("Invalid Attachment Number"); } - [DiscoAuthorize(Claims.Job.Actions.AddAttachments)] - public virtual ActionResult AttachmentUpload(int id, string Comments) + [DiscoAuthorize(Claims.Job.Actions.AddAttachments), ValidateAntiForgeryToken] + public virtual ActionResult AttachmentUpload(int id, string comments) { var j = Database.Jobs.Find(id); if (j != null) @@ -1934,6 +1934,9 @@ namespace Disco.Web.Areas.API.Controllers if (string.IsNullOrEmpty(contentType) || contentType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase)) contentType = MimeTypes.ResolveMimeType(file.FileName); + if (string.IsNullOrWhiteSpace(comments)) + comments = null; + var ja = new JobAttachment() { JobId = j.Id, @@ -1941,7 +1944,7 @@ namespace Disco.Web.Areas.API.Controllers Filename = file.FileName, MimeType = contentType, Timestamp = DateTime.Now, - Comments = Comments + Comments = comments }; Database.JobAttachments.Add(ja); Database.SaveChanges(); @@ -1961,10 +1964,12 @@ namespace Disco.Web.Areas.API.Controllers [DiscoAuthorize(Claims.Job.ShowAttachments)] public virtual ActionResult Attachment(int id) { - var ja = Database.JobAttachments.Include("DocumentTemplate").Include("TechUser").Where(m => m.Id == id).FirstOrDefault(); + var ja = Database.JobAttachments + .Include(a => a.DocumentTemplate) + .Include(a => a.TechUser) + .Where(m => m.Id == id).FirstOrDefault(); if (ja != null) { - var m = new Models.Attachment.AttachmentModel() { Attachment = Models.Attachment._AttachmentModel.FromAttachment(ja), diff --git a/Disco.Web/Areas/API/Controllers/UserController.cs b/Disco.Web/Areas/API/Controllers/UserController.cs index 46df4d8e..15f251fe 100644 --- a/Disco.Web/Areas/API/Controllers/UserController.cs +++ b/Disco.Web/Areas/API/Controllers/UserController.cs @@ -56,8 +56,8 @@ namespace Disco.Web.Areas.API.Controllers return HttpNotFound("Invalid Attachment Number"); } - [DiscoAuthorize(Claims.User.Actions.AddAttachments)] - public virtual ActionResult AttachmentUpload(string id, string Domain, string Comments) + [DiscoAuthorize(Claims.User.Actions.AddAttachments), ValidateAntiForgeryToken] + public virtual ActionResult AttachmentUpload(string id, string Domain, string comments) { id = ActiveDirectory.ParseDomainAccountId(id, Domain); @@ -73,6 +73,9 @@ namespace Disco.Web.Areas.API.Controllers if (string.IsNullOrEmpty(contentType) || contentType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase)) contentType = MimeTypes.ResolveMimeType(file.FileName); + if (string.IsNullOrWhiteSpace(comments)) + comments = null; + var ua = new Disco.Models.Repository.UserAttachment() { UserId = u.UserId, @@ -80,7 +83,7 @@ namespace Disco.Web.Areas.API.Controllers Filename = file.FileName, MimeType = contentType, Timestamp = DateTime.Now, - Comments = Comments + Comments = comments }; Database.UserAttachments.Add(ua); Database.SaveChanges(); @@ -100,7 +103,10 @@ namespace Disco.Web.Areas.API.Controllers [DiscoAuthorize(Claims.User.ShowAttachments)] public virtual ActionResult Attachment(int id) { - var ua = Database.UserAttachments.Include("DocumentTemplate").Include("TechUser").Where(m => m.Id == id).FirstOrDefault(); + var ua = Database.UserAttachments + .Include(a => a.DocumentTemplate) + .Include(a => a.TechUser) + .Where(m => m.Id == id).FirstOrDefault(); if (ua != null) { diff --git a/Disco.Web/Areas/API/Models/Attachment/_AttachmentModel.cs b/Disco.Web/Areas/API/Models/Attachment/_AttachmentModel.cs index bd88172a..f07270d9 100644 --- a/Disco.Web/Areas/API/Models/Attachment/_AttachmentModel.cs +++ b/Disco.Web/Areas/API/Models/Attachment/_AttachmentModel.cs @@ -20,7 +20,7 @@ namespace Disco.Web.Areas.API.Models.Attachment if (DocumentTemplateId != null && DocumentTemplateDescription != null) return DocumentTemplateDescription; else - return Comments; + return Comments ?? Filename; } } public string Filename { get; set; } diff --git a/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.js b/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.js index 9b216f21..984757d8 100644 --- a/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.js +++ b/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.js @@ -1,12 +1,13 @@ (function (window, document, $) { "use strict"; - var attachmentUploader = function (uploadUrl, dropTarget, uploadProgressContainer) { + var attachmentUploader = function ($host) { var self = this; - self.uploadUrl = uploadUrl; - self.dropTarget = dropTarget; - self.uploadProgressContainer = uploadProgressContainer; + self.$host = $host; + self.uploadUrl = $host.attr('data-uploadurl'); + self.dropTarget = $host.find('.Disco-AttachmentUpload-DropTarget'); + self.uploadProgressContainer = $host.find('.Disco-AttachmentUpload-Progress'); // #region File Selection Support self._uploadFilesInput = null; @@ -168,7 +169,7 @@ title: 'Upload File', 'class': 'dialog Disco-AttachmentUpload-CommentDialog' }); - dialog.html('
File Name:
Comments:
'); + dialog.html('
File Name:
Comments:
'); if (!!thumbnailHandler) { var td = dialog.find('td.thumbnail'); @@ -181,10 +182,8 @@ var comments = dialog.find('input.comments') .keypress(function (e) { if (e.which === 13) { - if (!!comments.val()) { - result = true; - dialog.dialog("close"); - } + result = true; + dialog.dialog("close"); } }); @@ -195,15 +194,11 @@ autoOpen: true, buttons: { "Upload": function () { - if (!!comments.val()) { - result = true; - dialog.dialog("close"); - window.setTimeout(function () { - comments.focus(); - }, 1); - } else { - alert('Please provide a comment for this attachment.'); - } + result = true; + dialog.dialog("close"); + window.setTimeout(function () { + comments.focus(); + }, 1); }, Cancel: function () { dialog.dialog("close"); @@ -262,29 +257,33 @@ processNextFile(); }; - self._uploadFile = function (fileData, fileName, comments) { - var formData = new FormData(); - var xhr = new XMLHttpRequest(); - var progress = $('
') + self._uploadFile = async function (fileData, fileName, comments) { + const formData = new FormData(); + + const progress = $('
') .append($('').addClass('fa fa-cog fa-spin')) .append($('').text('Uploading: ' + fileName)) .appendTo(self.uploadProgressContainer); - formData.append('Comments', comments); - formData.append('File', fileData, fileName); + formData.append('__RequestVerificationToken', self.$host.find('input[name="__RequestVerificationToken"]').val()); + formData.append('comments', comments); + formData.append('file', fileData, fileName); - xhr.open("POST", self.uploadUrl, true); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - if (xhr.status !== 200) { - alert('Error Uploading [' + fileName + ']: ' + xhr.statusText); - } - progress.slideUp(400, function () { - progress.remove(); - }); - } - }; - xhr.send(formData); + const result = await fetch(self.uploadUrl, { + method: 'POST', + body: formData + }); + + progress.slideUp(400, function () { + progress.remove(); + }); + + if (!result.ok) { + alert('Error Uploading [' + fileName + ']: ' + result.statusText); + + const errorText = await result.text(); + console.error('Failed to upload file [' + fileName + ']: ' + errorText); + } }; // #endregion diff --git a/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.min.js b/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.min.js index 8af932b6..f55e78c8 100644 --- a/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.min.js +++ b/Disco.Web/ClientSource/Scripts/Modules/Disco-AttachmentUploader.min.js @@ -1 +1 @@ -(function(n,t,i){"use strict";var r=function(r,u,f){var e=this;if(e.uploadUrl=r,e.dropTarget=u,e.uploadProgressContainer=f,e._uploadFilesInput=null,e.uploadFiles=function(){!e._uploadFilesInput||e._uploadFilesInput.remove();e._uploadFilesInput=i("");e._uploadFilesInput.attr({type:"file",multiple:"multiple",title:"Disco ICT File Uploading"}).hide().change(function(n){var t=n.target.files;!!t&&t.length>0&&e._uploadFiles(t);e._uploadFilesInput.remove()}).appendTo(e.uploadProgressContainer).click()},!!e.dropTarget){var h=i(t),o=!1,s=null;h.on("dragover",function(){e.dropTarget.addClass("dragHighlight");e.dropTarget.removeClass("dragHover");o=!1});h.on("dragleave",function(){!s||n.clearInterval(s);o=!0;n.setTimeout(function(){o&&e.dropTarget.removeClass("dragHighlight");s=null},200)});e.dropTarget.on("dragover",function(n){n.stopPropagation();n.preventDefault();e.dropTarget.addClass("dragHover");o=!1;n.originalEvent.dataTransfer.dropEffect="copy"});e.dropTarget.on("drop",function(n){n.stopPropagation();n.preventDefault();o=!0;e.dropTarget.removeClass("dragHighlight");var t=n.originalEvent.dataTransfer.files;e._uploadFiles(t)})}return e.uploadImage=function(){let f=null,o=!1;var u=i("