diff --git a/README.md b/README.md index 64c3a9d9b..38a9e6684 100644 --- a/README.md +++ b/README.md @@ -13,37 +13,38 @@ Documenation =========== Documentation can be found in the [TicketDesk GitHub Wiki](https://github.com/StephenRedd/TicketDesk/wiki) -Project Status: +Project Status =========== -[TicketDesk 2.5 is in beta](https://github.com/StephenRedd/TicketDesk/releases/tag/td2-v2.5.0). Development should resume in December 2015 towards a stable release version. +[TicketDesk 2.5 has been released](https://github.com/StephenRedd/TicketDesk/releases/tag/td2-v2.5.2) -View a working [demo of TicketDesk 2.5 here](http://ticketdesk2.azurewebsites.net/). The demo is automatically deployed by continuous integration from the development branch. +The previous version is also available +[TicektDesk 2.1](https://github.com/StephenRedd/TicketDesk/releases/tag/td2-v2.1.3). -The current stable version is [TicektDesk 2.1](https://github.com/StephenRedd/TicketDesk/releases/tag/td2-v2.1.3). +- TicketDesk 2.5 requires Visual Studio 2015 with .Net Framework 4.6.2 or higher. + - Visual Studio 2017 also supported +- TicketDesk 2.1 requires Visual Studio 2012 or higher with .Net Framework 4.5 or higher -- TicketDesk 2.5 requires Visual Studio 2013 with .Net Framework 4.5.2 or higher. - - Visual Studio 2013 with Update 4 or higher is required for Azure publishing - -- TicketDesk 2.1 requires Visual Studio 2012 or higher with .Net Framework 4.5 - -Getting started: +Getting started =========== Development ----------- -Getting started with TicketDesk development should be a "clone, open, and run" experience. You need Visual Studio 2013 with Update 4 or higher, SQL 2012 LocalDB, and Git. +Getting started with TicketDesk development should be a "clone, open, and run" experience. +- You need Visual Studio 2015 with the latest update, or Visual Studio 2017. +- By default, TicketDesk will use SQL Server Express **LocalDB Edition** 2014 or 2016. - Clone the github repository -- Switch to the desired branch (development has the latest version, master has latest release ready version) -- Open the project in Visual Studio 2013 or higher -- Hit F5 to run/debug the application +- Switch to the desired branch + - development has the latest version + - master has latest release ready version +- Open the project in Visual Studio +- Hit CTRL+F5 to run (F5 to debug) the application +- The site should open to the first-run-setup screen - Code, Contribute, and Enjoy! Deployment ----------- -Please visit the [wiki](https://github.com/NullDesk/TicketDesk/wiki) for comprehensive documentation on how to deploy TicketDesk to production IIS server or Azure. - -For experienced server admins, please see the [Quick Setup Instructions](https://github.com/NullDesk/TicketDesk/wiki/Quick-Setup-Instructions) for an abbreviated overview. \ No newline at end of file +TicketDesk is a straight forward ASP.Net and SQL server application. Please see the [Quick Setup Instructions](https://github.com/NullDesk/TicketDesk/wiki/Quick-Setup-Instructions) for an abbreviated overview of deploying TicketDesk. diff --git a/TicketDesk/S22.Mail/S22.Mail.csproj b/TicketDesk/S22.Mail/S22.Mail.csproj index 08ed81f58..2aab9f71a 100644 --- a/TicketDesk/S22.Mail/S22.Mail.csproj +++ b/TicketDesk/S22.Mail/S22.Mail.csproj @@ -10,7 +10,7 @@ Properties S22.Mail S22.Mail - v4.6.1 + v4.6.2 512 @@ -22,7 +22,7 @@ DEBUG;TRACE prompt 4 - bin\Debug\S22.Mail.XML + bin\Debug\S22.Mail.xml false diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateView.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateView.cs index 57ea1f490..e1a31ce9f 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateView.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateView.cs @@ -2,6 +2,7 @@ using System.IO; using System.Net.Mail; using System.Net.Mime; +#pragma warning disable 1591 namespace S22.Mail { [Serializable] @@ -61,3 +62,4 @@ public static byte[] GetBytesFromStream(Stream input) } } } +#pragma warning restore 1591 diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateViewCollection.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateViewCollection.cs index 7844eea0d..83ad4e092 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateViewCollection.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableAlternateViewCollection.cs @@ -1,5 +1,6 @@ using System; using System.Collections.ObjectModel; +#pragma warning disable 1591 namespace S22.Mail { [Serializable] @@ -7,3 +8,4 @@ public class SerializableAlternateViewCollection : Collection, IDisposable { public void Dispose() { } } } +#pragma warning restore 1591 diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentDisposition.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentDisposition.cs index d64678bde..7158b6c64 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentDisposition.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentDisposition.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Specialized; using System.Net.Mime; +#pragma warning disable 1591 namespace S22.Mail { [Serializable] @@ -51,3 +52,4 @@ private SerializableContentDisposition(ContentDisposition disposition) { public long Size { get; set; } } } +#pragma warning restore 1591 diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentType.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentType.cs index 4076d7778..401edd5f3 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentType.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableContentType.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Specialized; using System.Net.Mime; +#pragma warning disable 1591 namespace S22.Mail { [Serializable] @@ -44,3 +45,4 @@ private SerializableContentType(ContentType contentType) { public StringDictionary Parameters { get; private set; } } } +#pragma warning restore 1591 diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResource.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResource.cs index 490568d4c..a81fc2266 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResource.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResource.cs @@ -5,6 +5,7 @@ namespace S22.Mail { [Serializable] +#pragma warning disable 1591 public class SerializableLinkedResource { public static implicit operator LinkedResource(SerializableLinkedResource resource) { if (resource == null) @@ -39,4 +40,6 @@ private SerializableLinkedResource(LinkedResource resource) { public SerializableContentType ContentType { get; set; } public TransferEncoding TransferEncoding { get; set; } } +#pragma warning restore 1591 + } diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResourceCollection.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResourceCollection.cs index 389703dd7..4e1afe1bf 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResourceCollection.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableLinkedResourceCollection.cs @@ -3,7 +3,10 @@ namespace S22.Mail { [Serializable] +#pragma warning disable 1591 public class SerializableLinkedResourceCollection : Collection, IDisposable { public void Dispose() { } } +#pragma warning restore 1591 + } diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddress.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddress.cs index 0abc2cb96..af8ff34f4 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddress.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddress.cs @@ -1,10 +1,12 @@ using System; using System.Net.Mail; +#pragma warning disable 1591 namespace S22.Mail { [Serializable] public class SerializableMailAddress { - public static implicit operator MailAddress(SerializableMailAddress address) { + + public static implicit operator MailAddress(SerializableMailAddress address) { if (address == null) return null; return new MailAddress(address.Address, address.DisplayName); @@ -25,3 +27,5 @@ private SerializableMailAddress(MailAddress address) { public string DisplayName { get; private set; } } } +#pragma warning restore 1591 + diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddressCollection.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddressCollection.cs index 787213098..8b87f215f 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddressCollection.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailAddressCollection.cs @@ -3,6 +3,8 @@ namespace S22.Mail { [Serializable] +#pragma warning disable 1591 public class SerializableMailAddressCollection : Collection { +#pragma warning restore 1591 } } diff --git a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailMessage.cs b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailMessage.cs index 96b7dc3b1..6042a6120 100644 --- a/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailMessage.cs +++ b/TicketDesk/S22.Mail/SerializableMailMessage/SerializableMailMessage.cs @@ -2,6 +2,7 @@ using System.Collections.Specialized; using System.Net.Mail; using System.Text; +#pragma warning disable 1591 namespace S22.Mail { /// @@ -98,3 +99,4 @@ private SerializableMailMessage(MailMessage m) { public SerializableMailAddressCollection To { get; private set; } } } +#pragma warning restore 1591 diff --git a/TicketDesk/TicketDesk.Domain.Legacy/App.config b/TicketDesk/TicketDesk.Domain.Legacy/App.config index 6adb689b9..54f73d951 100644 --- a/TicketDesk/TicketDesk.Domain.Legacy/App.config +++ b/TicketDesk/TicketDesk.Domain.Legacy/App.config @@ -14,4 +14,4 @@ - + diff --git a/TicketDesk/TicketDesk.Domain.Legacy/TicketDesk.Domain.Legacy.csproj b/TicketDesk/TicketDesk.Domain.Legacy/TicketDesk.Domain.Legacy.csproj index 2042848d9..20017160b 100644 --- a/TicketDesk/TicketDesk.Domain.Legacy/TicketDesk.Domain.Legacy.csproj +++ b/TicketDesk/TicketDesk.Domain.Legacy/TicketDesk.Domain.Legacy.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.Domain.Legacy TicketDesk.Domain.Legacy - v4.6.1 + v4.6.2 512 ..\ diff --git a/TicketDesk/TicketDesk.Domain/App.config b/TicketDesk/TicketDesk.Domain/App.config index 6015362bf..a3cbef6ee 100644 --- a/TicketDesk/TicketDesk.Domain/App.config +++ b/TicketDesk/TicketDesk.Domain/App.config @@ -44,6 +44,6 @@ - + diff --git a/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.Designer.cs b/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.Designer.cs new file mode 100644 index 000000000..d6d46d5d2 --- /dev/null +++ b/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.Designer.cs @@ -0,0 +1,29 @@ +// +namespace TicketDesk.Domain.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")] + public sealed partial class Td25019 : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(Td25019)); + + string IMigrationMetadata.Id + { + get { return "201707150459325_Td2.5.019"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.cs b/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.cs new file mode 100644 index 000000000..76779e98b --- /dev/null +++ b/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.cs @@ -0,0 +1,18 @@ +namespace TicketDesk.Domain.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class Td25019 : DbMigration + { + public override void Up() + { + AddColumn("dbo.TicketEvents", "ForActivity", c => c.Int(nullable: false, defaultValue: 16384)); + } + + public override void Down() + { + DropColumn("dbo.TicketEvents", "ForActivity"); + } + } +} diff --git a/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.resx b/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.resx new file mode 100644 index 000000000..77c5aa501 --- /dev/null +++ b/TicketDesk/TicketDesk.Domain/Migrations/201707150459325_Td2.5.019.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Domain/Model/TicketEvent.cs b/TicketDesk/TicketDesk.Domain/Model/TicketEvent.cs index 6c58cc6c6..73cb66675 100644 --- a/TicketDesk/TicketDesk.Domain/Model/TicketEvent.cs +++ b/TicketDesk/TicketDesk.Domain/Model/TicketEvent.cs @@ -62,6 +62,8 @@ public TicketEvent() public virtual ICollection TicketEventNotifications { get; set; } + public TicketActivity ForActivity { get; set; } + /// /// Creates the activity event. @@ -81,6 +83,7 @@ public static TicketEvent CreateActivityEvent( { var tc = new TicketEvent { + ForActivity = activity, Comment = comment, EventBy = eventByUserId, EventDate = DateTime.Now, @@ -95,6 +98,7 @@ public static TicketEvent CreateActivityEvent( /// public void CreateSubscriberEventNotifications() { + foreach (var subscriber in Ticket.TicketSubscribers) { var isSubscriberEvent = EventBy == subscriber.SubscriberId; diff --git a/TicketDesk/TicketDesk.Domain/TdDomainContext.cs b/TicketDesk/TicketDesk.Domain/TdDomainContext.cs index e070d01b4..f8eb8e730 100644 --- a/TicketDesk/TicketDesk.Domain/TdDomainContext.cs +++ b/TicketDesk/TicketDesk.Domain/TdDomainContext.cs @@ -39,27 +39,30 @@ public sealed class TdDomainContext : DbContext /// public static event EventHandler> TicketsChanged; + public static event EventHandler> TicketsCreated; + + private static void RaiseTicketsCreated(TdDomainContext sender, IEnumerable tickets) + { + //TODO: Static events have their (rare) uses, but this should use a service bus or formal pub/sub mechanism eventually + TicketsCreated?.Invoke(sender, tickets); + } + private static void RaiseTicketsChanged(TdDomainContext sender, IEnumerable tickets) { //TODO: Static events have their (rare) uses, but this should use a service bus or formal pub/sub mechanism eventually - if (TicketsChanged != null) - { - TicketsChanged(sender, tickets); - } + TicketsChanged?.Invoke(sender, tickets); } public static event EventHandler> NotificationsCreated; + private static void RaiseNotificationsCreated(TdDomainContext sender, IEnumerable notifications) { //TODO: Static events have their (rare) uses, but this should use a service bus or formal pub/sub mechanism eventually - if (NotificationsCreated != null) - { - NotificationsCreated(sender, notifications); - } + NotificationsCreated?.Invoke(sender, notifications); } - public TdDomainSecurityProviderBase SecurityProvider { get; private set; } + public TicketActionManager TicketActions { get; private set; } @@ -244,15 +247,18 @@ public override int SaveChanges() private void RaiseEntityChangeEvents(PendingEventEntities pendingEntityChanges) { + RaiseTicketsCreated(this, pendingEntityChanges.PendingNewTickets); RaiseTicketsChanged(this, pendingEntityChanges.PendingTicketChanges); RaiseNotificationsCreated(this, pendingEntityChanges.PendingEventNotificationChanges); } private PendingEventEntities OnSaving() { - var pending = new PendingEventEntities(); - pending.PendingTicketChanges = GetTicketChanges(); - + var pending = new PendingEventEntities + { + PendingTicketChanges = GetTicketChanges(), + PendingNewTickets = GetNewTickets() + }; if (SecurityProvider != null) { ProcessDeletedProjects(); @@ -385,7 +391,16 @@ private void PrePopulateNewTicket(Ticket newTicket) newTicket.EnsureSubscribers(); } - + private IEnumerable GetNewTickets() + { + + return ChangeTracker.Entries() + .Where(t => t.State == EntityState.Added) + .Select(t => t.Entity) + .ToArray(); //execute now, because after save changes this query will return no results + } + + private IEnumerable GetTicketChanges() { @@ -420,6 +435,8 @@ private IEnumerable GetTicketEventNotificationChanges() private class PendingEventEntities { + + public IEnumerable PendingNewTickets { get; set; } public IEnumerable PendingTicketChanges { get; set; } public IEnumerable PendingEventNotificationChanges { get; set; } diff --git a/TicketDesk/TicketDesk.Domain/TicketDesk.Domain.csproj b/TicketDesk/TicketDesk.Domain/TicketDesk.Domain.csproj index 6d5dee271..ae519131b 100644 --- a/TicketDesk/TicketDesk.Domain/TicketDesk.Domain.csproj +++ b/TicketDesk/TicketDesk.Domain/TicketDesk.Domain.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.Domain TicketDesk.Domain - v4.6.1 + v4.6.2 512 ..\ @@ -46,9 +46,8 @@ ..\packages\Lucene.Net.3.0.3\lib\NET40\Lucene.Net.dll - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll @@ -131,6 +130,10 @@ 201506240309537_Td2.5.018.cs + + + 201707150459325_Td2.5.019.cs + @@ -246,6 +249,9 @@ 201506240309537_Td2.5.018.cs + + 201707150459325_Td2.5.019.cs + diff --git a/TicketDesk/TicketDesk.Domain/packages.config b/TicketDesk/TicketDesk.Domain/packages.config index e04d1fae6..9d7adaaf3 100644 --- a/TicketDesk/TicketDesk.Domain/packages.config +++ b/TicketDesk/TicketDesk.Domain/packages.config @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.IO/TicketDesk.IO.csproj b/TicketDesk/TicketDesk.IO/TicketDesk.IO.csproj index a2fd960d2..9ff908550 100644 --- a/TicketDesk/TicketDesk.IO/TicketDesk.IO.csproj +++ b/TicketDesk/TicketDesk.IO/TicketDesk.IO.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.IO TicketDesk.IO - v4.6.1 + v4.6.2 512 ..\ @@ -36,40 +36,32 @@ ..\packages\BlobFileSystem.Azure.0.0.7\lib\net45\AzureBlobFileSystem.dll True - - ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll - True + + ..\packages\Microsoft.Azure.KeyVault.Core.2.0.4\lib\net45\Microsoft.Azure.KeyVault.Core.dll - - ..\packages\Microsoft.Data.Edm.5.7.0\lib\net40\Microsoft.Data.Edm.dll - True + + ..\packages\Microsoft.Data.Edm.5.8.2\lib\net40\Microsoft.Data.Edm.dll - - ..\packages\Microsoft.Data.OData.5.7.0\lib\net40\Microsoft.Data.OData.dll - True + + ..\packages\Microsoft.Data.OData.5.8.2\lib\net40\Microsoft.Data.OData.dll - - ..\packages\Microsoft.Data.Services.Client.5.7.0\lib\net40\Microsoft.Data.Services.Client.dll - True + + ..\packages\Microsoft.Data.Services.Client.5.8.2\lib\net40\Microsoft.Data.Services.Client.dll - ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.2.1\lib\net40\Microsoft.WindowsAzure.Configuration.dll - True + ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.2.3\lib\net40\Microsoft.WindowsAzure.Configuration.dll - - ..\packages\WindowsAzure.Storage.7.2.0\lib\net40\Microsoft.WindowsAzure.Storage.dll - True + + ..\packages\WindowsAzure.Storage.8.2.0\lib\net45\Microsoft.WindowsAzure.Storage.dll - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - ..\packages\System.Spatial.5.7.0\lib\net40\System.Spatial.dll - True + + ..\packages\System.Spatial.5.8.2\lib\net40\System.Spatial.dll diff --git a/TicketDesk/TicketDesk.IO/app.config b/TicketDesk/TicketDesk.IO/app.config index feba4661f..b39c76640 100644 --- a/TicketDesk/TicketDesk.IO/app.config +++ b/TicketDesk/TicketDesk.IO/app.config @@ -16,12 +16,16 @@ - + - + + + + + - + diff --git a/TicketDesk/TicketDesk.IO/packages.config b/TicketDesk/TicketDesk.IO/packages.config index 509c7fc03..e5721c007 100644 --- a/TicketDesk/TicketDesk.IO/packages.config +++ b/TicketDesk/TicketDesk.IO/packages.config @@ -1,12 +1,16 @@  - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.Designer.cs b/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.Designer.cs index 6e001cdf4..ffe9a3537 100644 --- a/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.Designer.cs +++ b/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.Designer.cs @@ -78,6 +78,51 @@ public static string ApiKey_Description { } } + /// + /// Looks up a localized string similar to Enable background notification queues. + /// + public static string BackgroundQueueEnabled { + get { + return ResourceManager.GetString("BackgroundQueueEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enables background queuing of notifications.<br><br>Affects localizaton! When background queue is enabled, all email notificaitons are localized using the server's default culture and language. When disabled, the user's language choices will be used to generate emails.. + /// + public static string BackgroundQueueEnabled_Description { + get { + return ResourceManager.GetString("BackgroundQueueEnabled_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enabled. + /// + public static string BackgroundQueueEnabled_Prompt { + get { + return ResourceManager.GetString("BackgroundQueueEnabled_Prompt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Broadcast Mode. + /// + public static string BroadcastMode { + get { + return ResourceManager.GetString("BroadcastMode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Send new ticket notifications to a custom email distrubution list, or to all TicketDesk admin and staff users.. + /// + public static string BroadcastMode_Description { + get { + return ResourceManager.GetString("BroadcastMode_Description", resourceCulture); + } + } + /// /// Looks up a localized string similar to Click Tracking. /// @@ -294,6 +339,24 @@ public static string InitialRetryInterval_Description { } } + /// + /// Looks up a localized string similar to New Ticket Notificatons Enabled. + /// + public static string IsBroadcastEnabled { + get { + return ResourceManager.GetString("IsBroadcastEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enabled. + /// + public static string IsBroadcastEnabled_Prompt { + get { + return ResourceManager.GetString("IsBroadcastEnabled_Prompt", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum consolidation delay (minutes). /// @@ -393,6 +456,24 @@ public static string Provider_Prompt { } } + /// + /// Looks up a localized string similar to Send to all administrators and help desk staff. + /// + public static string PushNotificationBroadcastModeAllStaff { + get { + return ResourceManager.GetString("PushNotificationBroadcastModeAllStaff", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Send to specified email address. + /// + public static string PushNotificationBroadcastModeCustomAddress { + get { + return ResourceManager.GetString("PushNotificationBroadcastModeCustomAddress", resourceCulture); + } + } + /// /// Looks up a localized string similar to SendGrid Provider (Email). /// @@ -402,6 +483,42 @@ public static string SendGridProvider { } } + /// + /// Looks up a localized string similar to To Email Address. + /// + public static string SendToCustomEmailAddress { + get { + return ResourceManager.GetString("SendToCustomEmailAddress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The email recipient address. Used only when the mode is set to use a custom email address. + /// + public static string SendToCustomEmailAddress_Description { + get { + return ResourceManager.GetString("SendToCustomEmailAddress_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To Email Display Name. + /// + public static string SendToCustomEmailDisplayName { + get { + return ResourceManager.GetString("SendToCustomEmailDisplayName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The display name for the email recipient. Used only when the mode is set to use a custom email address. + /// + public static string SendToCustomEmailDisplayName_Description { + get { + return ResourceManager.GetString("SendToCustomEmailDisplayName_Description", resourceCulture); + } + } + /// /// Looks up a localized string similar to Send to Sink. /// diff --git a/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.pt-BR.resx b/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.pt-BR.resx index c8f65240b..c0cbe44b9 100644 --- a/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.pt-BR.resx +++ b/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.pt-BR.resx @@ -273,4 +273,43 @@ Deixe em branco se a autenticação não for necessária + + Permite a fila em segundo plano de notificações. + + + Ativado + + + Permite fila em segundo plano de notificações<br><br>Afeta localizaton! Quando a fila de fundo está ativada, todas as notificações de email são localizadas usando a cultura e o idioma padrão do servidor. Quando desativado, as opções de idioma do usuário serão usadas para gerar emails. + + + Modo + + + Envie novas notificações de ingresso para uma lista de distribuição de e-mail personalizada ou para todos os usuários do administrador e da equipe do TicketDesk. + + + Novas notificações de boletim habilitadas + + + Ativado + + + Enviar para todos os administradores e funcionários da mesa de ajuda + + + Enviar para o endereço de e-mail especificado + + + Para endereço de e-mail + + + O endereço do destinatário do e-mail. Usado somente quando o modo está configurado para usar um endereço de e-mail personalizado + + + Para Nome de exibição de e-mail + + + O nome de exibição para o destinatário do e-mail. Usado somente quando o modo está configurado para usar um endereço de e-mail personalizado + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.resx b/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.resx index 032e5d80d..a05ebbdae 100644 --- a/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.resx +++ b/TicketDesk/TicketDesk.Localization/PushNotifications/Strings.resx @@ -273,4 +273,43 @@ Leave empty if authentication is not required + + Enable background notification queues + + + Enables background queuing of notifications.<br><br>Affects localizaton! When background queue is enabled, all email notificaitons are localized using the server's default culture and language. When disabled, the user's language choices will be used to generate emails. + + + Enabled + + + Broadcast Mode + + + Send new ticket notifications to a custom email distrubution list, or to all TicketDesk admin and staff users. + + + New Ticket Notificatons Enabled + + + Enabled + + + Send to all administrators and help desk staff + + + Send to specified email address + + + To Email Address + + + The email recipient address. Used only when the mode is set to use a custom email address + + + To Email Display Name + + + The display name for the email recipient. Used only when the mode is set to use a custom email address + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Localization/TicketDesk.Localization.csproj b/TicketDesk/TicketDesk.Localization/TicketDesk.Localization.csproj index a5a588357..ca70d8de4 100644 --- a/TicketDesk/TicketDesk.Localization/TicketDesk.Localization.csproj +++ b/TicketDesk/TicketDesk.Localization/TicketDesk.Localization.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.Localization TicketDesk.Localization - v4.6.1 + v4.6.2 512 diff --git a/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.Designer.cs b/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.Designer.cs index 25f3fe794..d16c23f5b 100644 --- a/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.Designer.cs +++ b/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.Designer.cs @@ -87,6 +87,15 @@ public static string Details { } } + /// + /// Looks up a localized string similar to New. + /// + public static string New { + get { + return ResourceManager.GetString("New", resourceCulture); + } + } + /// /// Looks up a localized string similar to Owner: {0}. /// diff --git a/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.pt-BR.resx b/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.pt-BR.resx index e830bea4b..fd8b25881 100644 --- a/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.pt-BR.resx +++ b/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.pt-BR.resx @@ -126,6 +126,9 @@ Detalhes + + Novo + Solicitante: {0} diff --git a/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.resx b/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.resx index 5492293c9..51a6b1501 100644 --- a/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.resx +++ b/TicketDesk/TicketDesk.Localization/Views/Emails/Strings.resx @@ -126,6 +126,9 @@ Details + + New + Owner: {0} diff --git a/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.Designer.cs b/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.Designer.cs index b6e3dd8cb..3209e7600 100644 --- a/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.Designer.cs +++ b/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.Designer.cs @@ -69,6 +69,15 @@ public static string AntiNoise_Header { } } + /// + /// Looks up a localized string similar to New Ticket Notifications. + /// + public static string BroadcastNotification_Header { + get { + return ResourceManager.GetString("BroadcastNotification_Header", resourceCulture); + } + } + /// /// Looks up a localized string similar to Delivery providers. /// @@ -115,6 +124,15 @@ public static string RequiredProvider { } } + /// + /// Looks up a localized string similar to Settings saved!. + /// + public static string Saved_Alert { + get { + return ResourceManager.GetString("Saved_Alert", resourceCulture); + } + } + /// /// Looks up a localized string similar to Save. /// diff --git a/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.pt-BR.resx b/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.pt-BR.resx index fdc1de4d7..f2bfaefa6 100644 --- a/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.pt-BR.resx +++ b/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.pt-BR.resx @@ -120,6 +120,9 @@ Configurações de anti-ruído + + Novas Notificações de Bilhetes + Provedores de entrega @@ -136,6 +139,9 @@ Pelo menos um provedor deve estar habilitado para que as mensagens sejam enviadas. + + Configurações salvas! + Salvar diff --git a/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.resx b/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.resx index fa044cfc4..e57493d44 100644 --- a/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.resx +++ b/TicketDesk/TicketDesk.Localization/Views/PushNotificationSettings/Index.resx @@ -120,6 +120,9 @@ Anti-noise settings + + New Ticket Notifications + Delivery providers @@ -136,6 +139,9 @@ At least one provider must be enabled in order for messages to be sent. + + Settings saved! + Save diff --git a/TicketDesk/TicketDesk.PushNotifications.Job/App.config b/TicketDesk/TicketDesk.PushNotifications.Job/App.config index 32b078b25..79a43ba38 100644 --- a/TicketDesk/TicketDesk.PushNotifications.Job/App.config +++ b/TicketDesk/TicketDesk.PushNotifications.Job/App.config @@ -16,17 +16,17 @@ - + - + - + @@ -40,6 +40,10 @@ + + + + diff --git a/TicketDesk/TicketDesk.PushNotifications.Job/TicketDesk.PushNotifications.Job.csproj b/TicketDesk/TicketDesk.PushNotifications.Job/TicketDesk.PushNotifications.Job.csproj index 678095f4c..86f614ef4 100644 --- a/TicketDesk/TicketDesk.PushNotifications.Job/TicketDesk.PushNotifications.Job.csproj +++ b/TicketDesk/TicketDesk.PushNotifications.Job/TicketDesk.PushNotifications.Job.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.PushNotifications.Job TicketDesk.PushNotifications.Job - v4.6.1 + v4.6.2 512 @@ -41,49 +41,39 @@ ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll True - - ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll - True + + ..\packages\Microsoft.Azure.KeyVault.Core.2.0.4\lib\net45\Microsoft.Azure.KeyVault.Core.dll - - ..\packages\Microsoft.Azure.WebJobs.Core.1.1.2\lib\net45\Microsoft.Azure.WebJobs.dll - True + + ..\packages\Microsoft.Azure.WebJobs.Core.2.0.0\lib\net45\Microsoft.Azure.WebJobs.dll - - ..\packages\Microsoft.Azure.WebJobs.1.1.2\lib\net45\Microsoft.Azure.WebJobs.Host.dll - True + + ..\packages\Microsoft.Azure.WebJobs.2.0.0\lib\net45\Microsoft.Azure.WebJobs.Host.dll - - ..\packages\Microsoft.Data.Edm.5.7.0\lib\net40\Microsoft.Data.Edm.dll - True + + ..\packages\Microsoft.Data.Edm.5.8.2\lib\net40\Microsoft.Data.Edm.dll - - ..\packages\Microsoft.Data.OData.5.7.0\lib\net40\Microsoft.Data.OData.dll - True + + ..\packages\Microsoft.Data.OData.5.8.2\lib\net40\Microsoft.Data.OData.dll - - ..\packages\Microsoft.Data.Services.Client.5.7.0\lib\net40\Microsoft.Data.Services.Client.dll - True + + ..\packages\Microsoft.Data.Services.Client.5.8.2\lib\net40\Microsoft.Data.Services.Client.dll - ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.2.1\lib\net40\Microsoft.WindowsAzure.Configuration.dll - True + ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.2.3\lib\net40\Microsoft.WindowsAzure.Configuration.dll - - ..\packages\WindowsAzure.Storage.7.2.0\lib\net40\Microsoft.WindowsAzure.Storage.dll - True + + ..\packages\WindowsAzure.Storage.8.2.0\lib\net45\Microsoft.WindowsAzure.Storage.dll - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - ..\packages\System.Spatial.5.7.0\lib\net40\System.Spatial.dll - True + + ..\packages\System.Spatial.5.8.2\lib\net40\System.Spatial.dll @@ -112,7 +102,7 @@ - + - + - + - - + + - + diff --git a/TicketDesk/TicketDesk.PushNotifications/Delivery/SmtpDeliveryProvider.cs b/TicketDesk/TicketDesk.PushNotifications/Delivery/SmtpDeliveryProvider.cs index c06e8626b..2999c0289 100644 --- a/TicketDesk/TicketDesk.PushNotifications/Delivery/SmtpDeliveryProvider.cs +++ b/TicketDesk/TicketDesk.PushNotifications/Delivery/SmtpDeliveryProvider.cs @@ -35,15 +35,14 @@ public SmtpDeliveryProvider(JToken configuration) public override Task SendNotificationAsync(PushNotificationItem notificationItem, object message, CancellationToken ct) { - var cfg = (SmtpDeliveryProviderConfiguration)Configuration; - var sent = false; - - var smsg = message as SerializableMailMessage; - if (smsg != null) + SmtpDeliveryProviderConfiguration cfg = (SmtpDeliveryProviderConfiguration)Configuration; + bool sent = false; + + if (message is SerializableMailMessage smsg) { try { - var client = new SmtpClient() + SmtpClient client = new SmtpClient() { Host = cfg.SmtpServer, Port = cfg.SmtpPort ?? 25, diff --git a/TicketDesk/TicketDesk.PushNotifications/Migrations/Configuration.cs b/TicketDesk/TicketDesk.PushNotifications/Migrations/Configuration.cs index fd3f2c44e..e1344910b 100644 --- a/TicketDesk/TicketDesk.PushNotifications/Migrations/Configuration.cs +++ b/TicketDesk/TicketDesk.PushNotifications/Migrations/Configuration.cs @@ -34,33 +34,10 @@ protected override void Seed(TdPushNotificationContext context) { DemoPushNotificationDataManager.SetupDemoPushNotificationData(context); } - else - { - InitializeStockUserSettings(context); - } + base.Seed(context); } - public static void InitializeStockUserSettings(TdPushNotificationContext context) - { - - if (!context.SubscriberPushNotificationSettings.Any(s => s.SubscriberId == "64165817-9cb5-472f-8bfb-6a35ca54be6a")) - { - context.SubscriberPushNotificationSettings.Add(new SubscriberNotificationSetting() - { - SubscriberId = "64165817-9cb5-472f-8bfb-6a35ca54be6a", - IsEnabled = true, - PushNotificationDestinations = new[] - { - new PushNotificationDestination() - { - SubscriberName = "Admin User", - DestinationAddress = "admin@example.com", - DestinationType = "email" - } - } - }); - } - } + } } diff --git a/TicketDesk/TicketDesk.PushNotifications/Migrations/DemoPushNotificationDataManager.cs b/TicketDesk/TicketDesk.PushNotifications/Migrations/DemoPushNotificationDataManager.cs index 9dac78df7..4020ea12c 100644 --- a/TicketDesk/TicketDesk.PushNotifications/Migrations/DemoPushNotificationDataManager.cs +++ b/TicketDesk/TicketDesk.PushNotifications/Migrations/DemoPushNotificationDataManager.cs @@ -29,13 +29,15 @@ public static void RemoveAllPushNotificationData(TdPushNotificationContext conte context.SaveChanges(); - Configuration.InitializeStockUserSettings(context); - context.SaveChanges(); + } public static void SetupDemoPushNotificationData(TdPushNotificationContext context) { - if (!context.SubscriberPushNotificationSettings.Any( - s => s.SubscriberId == "64165817-9cb5-472f-8bfb-6a35ca54be6a")) + if (!context.SubscriberPushNotificationSettings.Any(s => + s.SubscriberId == "64165817-9cb5-472f-8bfb-6a35ca54be6a" + || s.PushNotificationDestinations.Any(d => + d.DestinationAddress == "admin@example.com" + && d.DestinationType == "email"))) { context.SubscriberPushNotificationSettings.Add(new SubscriberNotificationSetting() { @@ -52,8 +54,11 @@ public static void SetupDemoPushNotificationData(TdPushNotificationContext conte } }); } - if (!context.SubscriberPushNotificationSettings.Any( - s => s.SubscriberId == "72bdddfb-805a-4883-94b9-aa494f5f52dc")) + if (!context.SubscriberPushNotificationSettings.Any(s => + s.SubscriberId == "72bdddfb-805a-4883-94b9-aa494f5f52dc" + || s.PushNotificationDestinations.Any(d => + d.DestinationAddress == "staff@example.com" + && d.DestinationType == "email"))) { context.SubscriberPushNotificationSettings.Add(new SubscriberNotificationSetting() { @@ -71,8 +76,11 @@ public static void SetupDemoPushNotificationData(TdPushNotificationContext conte }); } - if (!context.SubscriberPushNotificationSettings.Any( - s => s.SubscriberId == "17f78f38-fa68-445f-90de-38896140db28")) + if (!context.SubscriberPushNotificationSettings.Any(s => + s.SubscriberId == "17f78f38-fa68-445f-90de-38896140db28" + || s.PushNotificationDestinations.Any(d => + d.DestinationAddress == "user@example.com" + && d.DestinationType == "email"))) { context.SubscriberPushNotificationSettings.Add(new SubscriberNotificationSetting() { diff --git a/TicketDesk/TicketDesk.PushNotifications/Model/ApplicationPushNotificationSetting.cs b/TicketDesk/TicketDesk.PushNotifications/Model/ApplicationPushNotificationSetting.cs index 4ecee7119..306d87fa7 100644 --- a/TicketDesk/TicketDesk.PushNotifications/Model/ApplicationPushNotificationSetting.cs +++ b/TicketDesk/TicketDesk.PushNotifications/Model/ApplicationPushNotificationSetting.cs @@ -30,11 +30,14 @@ public ApplicationPushNotificationSetting() { ApplicationName = "TicketDesk"; IsEnabled = false; + IsBackgroundQueueEnabled = true; DeliveryIntervalMinutes = 2; AntiNoiseSettings = new AntiNoiseSetting(); RetryAttempts = 5; RetryIntervalMinutes = 2; - DeliveryProviderSettings = new List { }; + // ReSharper disable once VirtualMemberCallInConstructor + DeliveryProviderSettings = new List(); + BroadcastSettings = new BroadcastSetting(); } [Key] @@ -48,7 +51,7 @@ public ApplicationPushNotificationSetting() [ScaffoldColumn(false)] public string Serialized { - get { return JsonConvert.SerializeObject(this); } + get => JsonConvert.SerializeObject(this); set { if (string.IsNullOrEmpty(value)) @@ -58,22 +61,30 @@ public string Serialized var jsettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }; var jData = JsonConvert.DeserializeObject(value, jsettings); IsEnabled = jData.IsEnabled; + IsBackgroundQueueEnabled = jData.IsBackgroundQueueEnabled; DeliveryIntervalMinutes = jData.DeliveryIntervalMinutes; RetryAttempts = jData.RetryAttempts; RetryIntervalMinutes = jData.RetryIntervalMinutes; DeliveryProviderSettings = jData.DeliveryProviderSettings; AntiNoiseSettings = jData.AntiNoiseSettings; + BroadcastSettings = jData.BroadcastSettings; } } [NotMapped] [Display(Name = "DeliveryProviders", ResourceType = typeof(Strings))] public virtual ICollection DeliveryProviderSettings { get; set; } - + [NotMapped] [Display(Name = "NotificationsEnabled", Prompt = "NotificationsEnabled_Prompt", ResourceType = typeof(Strings))] public bool IsEnabled { get; set; } + [NotMapped] + [Display(Name = "BackgroundQueueEnabled", Prompt = "BackgroundQueueEnabled_Prompt", + ResourceType = typeof(Strings))] + [LocalizedDescription("BackgroundQueueEnabled_Description", NameResourceType = typeof(Strings))] + public bool IsBackgroundQueueEnabled { get; set; } + [NotMapped] [Display(Name = "DeliveryAttemptInterval", ResourceType = typeof(Strings))] [LocalizedDescription("DeliveryAttemptInterval_Description", NameResourceType = typeof(Strings))] @@ -92,6 +103,38 @@ public string Serialized [NotMapped] public AntiNoiseSetting AntiNoiseSettings { get; set; } + [NotMapped] + public BroadcastSetting BroadcastSettings { get; set; } + + + public class BroadcastSetting + { + public BroadcastSetting() + { + BroadcastMode = PushNotificationBroadcastMode.AllStaff; + IsBroadcastEnabled = true; + } + + [NotMapped] + [Display(Name = "BroadcastMode", ResourceType = typeof(Strings))] + [LocalizedDescription("BroadcastMode_Description", NameResourceType = typeof(Strings))] + public PushNotificationBroadcastMode BroadcastMode { get; set; } + + [NotMapped] + [Display(Name = "IsBroadcastEnabled", Prompt = "IsBroadcastEnabled_Prompt", ResourceType = typeof(Strings))] + public bool IsBroadcastEnabled { get; set; } + + [NotMapped] + [EmailAddress] + [Display(Name = "SendToCustomEmailAddress", ResourceType = typeof(Strings))] + [LocalizedDescription("SendToCustomEmailAddress_Description", NameResourceType = typeof(Strings))] + public string SendToCustomEmailAddress { get; set; } + + [NotMapped] + [Display(Name = "SendToCustomEmailDisplayName", ResourceType = typeof(Strings))] + [LocalizedDescription("SendToCustomEmailDisplayName_Description", NameResourceType = typeof(Strings))] + public string SendToCustomEmailDisplayName { get; set; } + } public class PushNotificationDeliveryProviderSetting { @@ -127,8 +170,8 @@ public class AntiNoiseSetting public AntiNoiseSetting() { IsConsolidationEnabled = true; - InitialConsolidationDelayMinutes = 6; - MaxConsolidationDelayMinutes = 16; + InitialConsolidationDelayMinutes = 2; + MaxConsolidationDelayMinutes = 10; ExcludeSubscriberEvents = true; } @@ -152,5 +195,14 @@ public AntiNoiseSetting() [LocalizedDescription("ExcludeSubscribersOwnEvents_Description", NameResourceType = typeof(Strings))] public bool ExcludeSubscriberEvents { get; set; } } + + public enum PushNotificationBroadcastMode + { + [Display(Name = "PushNotificationBroadcastModeAllStaff", ResourceType = typeof(Strings))] + AllStaff, + [Display(Name = "PushNotificationBroadcastModeCustomAddress", ResourceType = typeof(Strings))] + + CustomAddress + } } } diff --git a/TicketDesk/TicketDesk.PushNotifications/Model/NewTicketPushNotificationInfo.cs b/TicketDesk/TicketDesk.PushNotifications/Model/NewTicketPushNotificationInfo.cs new file mode 100644 index 000000000..18af649f7 --- /dev/null +++ b/TicketDesk/TicketDesk.PushNotifications/Model/NewTicketPushNotificationInfo.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TicketDesk.PushNotifications.Model +{ + public class NewTicketPushNotificationInfo + { + public int TicketId { get; set; } + + + public string MessageContent { get; set; } + + internal IEnumerable ToPushNotificationItems( + SubscriberNotificationSetting userSettings + ) + { + var now = DateTimeOffset.Now; + return userSettings.PushNotificationDestinations.Select(dest => + new PushNotificationItem() + { + ContentSourceId = TicketId, + ContentSourceType = "new ticket", + SubscriberId = "new ticket broadcast", + Destination = dest, + DestinationId = dest.DestinationId, + DeliveryStatus = userSettings.IsEnabled + ? PushNotificationItemStatus.Scheduled + : PushNotificationItemStatus.Disabled, + RetryCount = 0, + CreatedDate = now, + ScheduledSendDate = now, + MessageContent = MessageContent + } + ).ToList(); + + } + } +} diff --git a/TicketDesk/TicketDesk.PushNotifications/Model/PushNotificationDestination.cs b/TicketDesk/TicketDesk.PushNotifications/Model/PushNotificationDestination.cs index 234b211d2..d0b5b8538 100644 --- a/TicketDesk/TicketDesk.PushNotifications/Model/PushNotificationDestination.cs +++ b/TicketDesk/TicketDesk.PushNotifications/Model/PushNotificationDestination.cs @@ -35,6 +35,7 @@ public class PushNotificationDestination [StringLength(50, ErrorMessageResourceName = "FieldMaximumLength", ErrorMessageResourceType = typeof(Validation))] public string DestinationType { get; set; } + [Index("IX_SubscriberDestination", 3, IsUnique = true)] [StringLength(256, ErrorMessageResourceName = "FieldMaximumLength", ErrorMessageResourceType = typeof(Validation))] public string SubscriberId { get; set; } diff --git a/TicketDesk/TicketDesk.PushNotifications/Model/SubscriberNotificationSetting.cs b/TicketDesk/TicketDesk.PushNotifications/Model/SubscriberNotificationSetting.cs index dfd58fa5f..21be42684 100644 --- a/TicketDesk/TicketDesk.PushNotifications/Model/SubscriberNotificationSetting.cs +++ b/TicketDesk/TicketDesk.PushNotifications/Model/SubscriberNotificationSetting.cs @@ -25,6 +25,7 @@ public class SubscriberNotificationSetting public SubscriberNotificationSetting() { IsEnabled = true; + PushNotificationDestinations = new List(); } [Key] diff --git a/TicketDesk/TicketDesk.PushNotifications/TdPushNotificationContext.cs b/TicketDesk/TicketDesk.PushNotifications/TdPushNotificationContext.cs index 96b7ff63a..a214e952e 100644 --- a/TicketDesk/TicketDesk.PushNotifications/TdPushNotificationContext.cs +++ b/TicketDesk/TicketDesk.PushNotifications/TdPushNotificationContext.cs @@ -98,14 +98,26 @@ public ApplicationPushNotificationSetting TicketDeskPushNotificationSettings } } + public bool AddNotifications(IEnumerable infoItems) + { + var userSettings = SubscriberPushNotificationSettings.GetSettingsForUser("new ticket broadcast"); + + foreach (var item in infoItems) + { + PushNotificationItems.AddRange(item.ToPushNotificationItems(userSettings)); + } + return true; + } + public bool AddNotifications(IEnumerable infoItems) { + var appSettings = TicketDeskPushNotificationSettings; + foreach (var item in infoItems) { var citem = item; //foreach closure workaround var userSettings = SubscriberPushNotificationSettings.GetSettingsForUser(citem.SubscriberId); - var appSettings = TicketDeskPushNotificationSettings; - + //get items already in db that haven't been sent yet var existingItems =TicketPushNotificationItems .Include(t => t.PushNotificationItem) diff --git a/TicketDesk/TicketDesk.PushNotifications/TicketDesk.PushNotifications.csproj b/TicketDesk/TicketDesk.PushNotifications/TicketDesk.PushNotifications.csproj index d65f35de1..f2a14fc00 100644 --- a/TicketDesk/TicketDesk.PushNotifications/TicketDesk.PushNotifications.csproj +++ b/TicketDesk/TicketDesk.PushNotifications/TicketDesk.PushNotifications.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.PushNotifications TicketDesk.PushNotifications - v4.6.1 + v4.6.2 512 ..\ @@ -40,21 +40,20 @@ ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll True - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll ..\packages\Sendgrid.6.3.4\lib\SendGrid.dll - True - - ..\packages\SendGrid.SmtpApi.1.3.1\lib\net40\SendGrid.SmtpApi.dll - True + + ..\packages\SendGrid.CSharp.HTTP.Client.3.3.0\lib\SendGrid.CSharp.HTTP.Client.dll + + + ..\packages\SendGrid.SmtpApi.1.3.3\lib\SendGrid.SmtpApi.dll ..\packages\Sendgrid.6.3.4\lib\SendGridMail.dll - True @@ -65,6 +64,7 @@ ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll True + @@ -77,6 +77,7 @@ + diff --git a/TicketDesk/TicketDesk.PushNotifications/packages.config b/TicketDesk/TicketDesk.PushNotifications/packages.config index 1771c1e0d..6eac45e6d 100644 --- a/TicketDesk/TicketDesk.PushNotifications/packages.config +++ b/TicketDesk/TicketDesk.PushNotifications/packages.config @@ -2,7 +2,8 @@ - - - + + + + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Search.Azure/TicketDesk.Search.Azure.csproj b/TicketDesk/TicketDesk.Search.Azure/TicketDesk.Search.Azure.csproj index f415b6ff7..2cd63b29b 100644 --- a/TicketDesk/TicketDesk.Search.Azure/TicketDesk.Search.Azure.csproj +++ b/TicketDesk/TicketDesk.Search.Azure/TicketDesk.Search.Azure.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.Search.Azure TicketDesk.Search.Azure - v4.6.1 + v4.6.2 512 ..\ @@ -32,9 +32,8 @@ 4 - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll ..\packages\RedDog.Search.0.5.2.0\lib\net45\RedDog.Search.dll diff --git a/TicketDesk/TicketDesk.Search.Azure/app.config b/TicketDesk/TicketDesk.Search.Azure/app.config index a2fbbb710..2de1d4cd8 100644 --- a/TicketDesk/TicketDesk.Search.Azure/app.config +++ b/TicketDesk/TicketDesk.Search.Azure/app.config @@ -8,7 +8,7 @@ - + @@ -24,8 +24,12 @@ - + + + + + - + diff --git a/TicketDesk/TicketDesk.Search.Azure/packages.config b/TicketDesk/TicketDesk.Search.Azure/packages.config index f3ab0ced5..b205cc876 100644 --- a/TicketDesk/TicketDesk.Search.Azure/packages.config +++ b/TicketDesk/TicketDesk.Search.Azure/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Search.Common/TicketDesk.Search.Common.csproj b/TicketDesk/TicketDesk.Search.Common/TicketDesk.Search.Common.csproj index 694b455ae..7a345f675 100644 --- a/TicketDesk/TicketDesk.Search.Common/TicketDesk.Search.Common.csproj +++ b/TicketDesk/TicketDesk.Search.Common/TicketDesk.Search.Common.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.Search.Common TicketDesk.Search.Common - v4.6.1 + v4.6.2 512 diff --git a/TicketDesk/TicketDesk.Search.Lucene/TicketDesk.Search.Lucene.csproj b/TicketDesk/TicketDesk.Search.Lucene/TicketDesk.Search.Lucene.csproj index f6900ad0f..696090bf8 100644 --- a/TicketDesk/TicketDesk.Search.Lucene/TicketDesk.Search.Lucene.csproj +++ b/TicketDesk/TicketDesk.Search.Lucene/TicketDesk.Search.Lucene.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.Search.Lucene TicketDesk.Search.Lucene - v4.6.1 + v4.6.2 512 ..\ diff --git a/TicketDesk/TicketDesk.Web.Client/App_Start/Startup.PushNotifications.cs b/TicketDesk/TicketDesk.Web.Client/App_Start/Startup.PushNotifications.cs index cfdcc3c87..f4c4d0713 100644 --- a/TicketDesk/TicketDesk.Web.Client/App_Start/Startup.PushNotifications.cs +++ b/TicketDesk/TicketDesk.Web.Client/App_Start/Startup.PushNotifications.cs @@ -16,6 +16,7 @@ using System.Configuration; using System.Data.Entity; using System.Linq; +using System.Threading; using System.Web.Hosting; using System.Web.Mvc; using TicketDesk.Domain; @@ -24,13 +25,15 @@ using TicketDesk.PushNotifications.Migrations; using TicketDesk.PushNotifications.Model; using TicketDesk.Web.Client.Infrastructure; +using TicketDesk.Web.Identity; +using TicketDesk.Web.Identity.Model; namespace TicketDesk.Web.Client { public partial class Startup { /// - /// Configures the push notifications. + /// Configures the push notifications. /// public static void ConfigurePushNotifications() { @@ -50,62 +53,208 @@ public static void ConfigurePushNotifications() DemoPushNotificationDataManager.SetupDemoPushNotificationData(context); } + if (context.TicketDeskPushNotificationSettings.IsEnabled) { + EnsureBroadcastNotificaitonsConfiguration(context); + //TODO: poor man's detection of appropriate scheduler var siteName = Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"); var isAzureWebSite = !string.IsNullOrEmpty(siteName); if (!isAzureWebSite) { - InProcessPushNotificationScheduler.Start(context.TicketDeskPushNotificationSettings.DeliveryIntervalMinutes); + InProcessPushNotificationScheduler.Start(context.TicketDeskPushNotificationSettings + .DeliveryIntervalMinutes); } - context.Dispose();//ensure that no one accidentally holds a reference to this in closure - //register for static notifications created event handler - TdDomainContext.NotificationsCreated += (sender, notifications) => + if (context.TicketDeskPushNotificationSettings.IsBackgroundQueueEnabled) { - HostingEnvironment.QueueBackgroundWorkItem(ct => + //register for static notifications created event handler + TdDomainContext.NotificationsCreated += (sender, notifications) => { - // ReSharper disable once EmptyGeneralCatchClause - try - { - var notificationIds = notifications.Select(n => n.EventId).ToArray(); - var domainContext = DependencyResolver.Current.GetService(); - var multiProject = domainContext.Projects.Count() > 1; - //fetch these back and make sure all dependent entities we need are loaded - var notes = domainContext.TicketEventNotifications - .Include(t => t.TicketEvent) - .Include(t => t.TicketEvent.Ticket) - .Include(t => t.TicketEvent.Ticket.Project) - .Include(t => t.TicketSubscriber) - .Where(t => notificationIds.Contains(t.EventId)) - .ToArray(); - - if (notes.Any()) - { - using (var noteContext = new TdPushNotificationContext()) - { - var subscriberExclude = - noteContext.TicketDeskPushNotificationSettings.AntiNoiseSettings - .ExcludeSubscriberEvents; + HostingEnvironment.QueueBackgroundWorkItem(CreateTicketEventNotifications(notifications)); + }; - var noteEvents = notes.ToNotificationEventInfoCollection(subscriberExclude, - multiProject); + TdDomainContext.TicketsCreated += (sender, tickets) => + { + HostingEnvironment.QueueBackgroundWorkItem(CreateNewTicketBroadcastNotification(tickets)); + }; + } + else + { + TdDomainContext.NotificationsCreated += (sender, notifications) => + { + CreateTicketEventNotifications(notifications)(CancellationToken.None); + }; + TdDomainContext.TicketsCreated += (sender, tickets) => + { + CreateNewTicketBroadcastNotification(tickets)(CancellationToken.None); + }; + } + } + context.Dispose(); //ensure that no one accidentally holds a reference to this in closure + } - noteContext.AddNotifications(noteEvents); + private static void EnsureBroadcastNotificaitonsConfiguration(TdPushNotificationContext context) + { + var broadcastUserSettings = context.SubscriberPushNotificationSettingsManager + .GetSettingsForSubscriberAsync("new ticket broadcast").Result; - noteContext.SaveChanges(); - } + var broadcastAppSettings = context.TicketDeskPushNotificationSettings.BroadcastSettings; + if (broadcastUserSettings == null) + { + broadcastUserSettings = new SubscriberNotificationSetting + { + SubscriberId = "new ticket broadcast" + }; + context.SubscriberPushNotificationSettingsManager.AddSettingsForSubscriber(broadcastUserSettings); + } + if + ( + broadcastAppSettings.BroadcastMode == + ApplicationPushNotificationSetting.PushNotificationBroadcastMode.CustomAddress + && + !string.IsNullOrEmpty(broadcastAppSettings.SendToCustomEmailAddress) + ) + { + broadcastUserSettings.PushNotificationDestinations.Add( + new PushNotificationDestination + { + SubscriberId = "new ticket broadcast", + DestinationAddress = broadcastAppSettings.SendToCustomEmailAddress, + DestinationType = "email", + SubscriberName = broadcastAppSettings.SendToCustomEmailDisplayName + } + ); + } + else + { + + + var userManager = DependencyResolver.Current.GetService(); + var roleManager = DependencyResolver.Current.GetService(); + var usersForNotification = roleManager.GetTdHelpDeskUsers(userManager) + .Union(roleManager.GetTdTdAdministrators(userManager)) + .Distinct(new UniqueNameEmailDisplayUserEqualityComparer()).ToArray(); + + + var existingDestinations = broadcastUserSettings + .PushNotificationDestinations + .Where(pnd => pnd.DestinationType == "email" && pnd.SubscriberId == "new ticket broadcast") + .ToArray(); + //remove users not in list anymore + var usersToRemove = existingDestinations + .Where(us => !usersForNotification + .Any(un => un.Email == us.DestinationAddress && un.DisplayName == us.SubscriberName)) + .ToList(); + foreach (var us in usersToRemove) + { + broadcastUserSettings.PushNotificationDestinations.Remove(us); + } + + //add users in list, but not already in destinations + foreach (var nu in usersForNotification) + { + if (!existingDestinations.Any(ed => nu.Email == ed.DestinationAddress && + nu.DisplayName == ed.SubscriberName)) + { + broadcastUserSettings.PushNotificationDestinations.Add( + new PushNotificationDestination + { + SubscriberId = "new ticket broadcast", + DestinationAddress = nu.Email, + DestinationType = "email", + SubscriberName = nu.DisplayName } - } - catch + ); + } + } + } + broadcastUserSettings.IsEnabled = broadcastAppSettings.IsBroadcastEnabled; + context.SaveChanges(); + } + + + private static Action CreateNewTicketBroadcastNotification(IEnumerable tickets) + { + return ct => + { + try + { + var notificationIds = tickets.Select(t => + t.TicketEvents.First(te => te.ForActivity == TicketActivity.Create || + te.ForActivity == TicketActivity.CreateOnBehalfOf).EventId) + .ToArray(); + + var domainContext = DependencyResolver.Current.GetService(); + var multiProject = domainContext.Projects.Count() > 1; + var notes = domainContext.TicketEventNotifications + .Include(t => t.TicketEvent) + .Include(t => t.TicketEvent.Ticket) + .Include(t => t.TicketEvent.Ticket.Project) + .Where(t => notificationIds.Contains(t.EventId)) + .ToArray(); + + if (notes.Any()) + { + using (var noteContext = new TdPushNotificationContext()) { - //TODO: Log this somewhere + var newNoteEvents = notes.ToNewTicketPushNotificationInfoCollection(multiProject); + noteContext.AddNotifications(newNoteEvents); + + noteContext.SaveChanges(); } - }); - }; - } + } + } + catch + { + //TODO: Log this somewhere + } + }; } + private static Action CreateTicketEventNotifications( + IEnumerable notifications) + { + return ct => + { + // ReSharper disable once EmptyGeneralCatchClause + try + { + var notificationIds = notifications.Select(n => n.EventId).ToArray(); + var domainContext = DependencyResolver.Current.GetService(); + var multiProject = domainContext.Projects.Count() > 1; + //fetch these back and make sure all dependent entities we need are loaded + var notes = domainContext.TicketEventNotifications + .Include(t => t.TicketEvent) + .Include(t => t.TicketEvent.Ticket) + .Include(t => t.TicketEvent.Ticket.Project) + .Include(t => t.TicketSubscriber) + .Where(t => notificationIds.Contains(t.EventId)) + .ToArray(); + + if (notes.Any()) + { + using (var noteContext = new TdPushNotificationContext()) + { + var subscriberExclude = + noteContext.TicketDeskPushNotificationSettings.AntiNoiseSettings + .ExcludeSubscriberEvents; + + var noteEvents = notes.ToNotificationEventInfoCollection(subscriberExclude, + multiProject); + + noteContext.AddNotifications(noteEvents); + + noteContext.SaveChanges(); + } + } + } + catch + { + //TODO: Log this somewhere + } + }; + } } } \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Web.Client/ApplicationInsights.config b/TicketDesk/TicketDesk.Web.Client/ApplicationInsights.config index 563f27798..d59969c0a 100644 --- a/TicketDesk/TicketDesk.Web.Client/ApplicationInsights.config +++ b/TicketDesk/TicketDesk.Web.Client/ApplicationInsights.config @@ -3,8 +3,42 @@ b27f9308-72c1-4c8c-96f9-0a7c47956a7d + + + + + + + + + search|spider|crawl|Bot|Monitor|AlwaysOn + + + + + + + + + - + + + + core.windows.net + core.chinacloudapi.cn + core.cloudapi.de + core.usgovcloudapi.net + localhost + 127.0.0.1 + + + - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + --> \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Web.Client/Controllers/DataManagementController.cs b/TicketDesk/TicketDesk.Web.Client/Controllers/DataManagementController.cs index 13421c1e0..d6a7425cb 100644 --- a/TicketDesk/TicketDesk.Web.Client/Controllers/DataManagementController.cs +++ b/TicketDesk/TicketDesk.Web.Client/Controllers/DataManagementController.cs @@ -11,6 +11,7 @@ // attribution must remain intact, and a copy of the license must be // provided to the recipient. +using System.Threading.Tasks; using System.Web.Mvc; using Microsoft.AspNet.Identity; using TicketDesk.Domain; @@ -56,6 +57,8 @@ public ActionResult RemoveDemoData() DemoIdentityDataManager.RemoveIdentity(IdentityContext, User.Identity.GetUserId()); DemoPushNotificationDataManager.RemoveAllPushNotificationData(PushNotificationContext); ViewBag.DemoDataRemoved = true; + Task.Delay(500).ContinueWith(t => System.Web.HttpRuntime.UnloadAppDomain()).ConfigureAwait(false); + return View("Demo"); } @@ -69,6 +72,8 @@ public ActionResult CreateDemoData() DemoIdentityDataManager.SetupDemoIdentityData(IdentityContext, User.Identity.GetUserId()); DemoPushNotificationDataManager.SetupDemoPushNotificationData(PushNotificationContext); ViewBag.DemoDataCreated = true; + Task.Delay(500).ContinueWith(t => System.Web.HttpRuntime.UnloadAppDomain()).ConfigureAwait(false); + return View("Demo"); } } diff --git a/TicketDesk/TicketDesk.Web.Client/Controllers/FirstRunSetupController.cs b/TicketDesk/TicketDesk.Web.Client/Controllers/FirstRunSetupController.cs index 6401964b9..c6309ab2b 100644 --- a/TicketDesk/TicketDesk.Web.Client/Controllers/FirstRunSetupController.cs +++ b/TicketDesk/TicketDesk.Web.Client/Controllers/FirstRunSetupController.cs @@ -23,6 +23,7 @@ using TicketDesk.Domain.Migrations; using TicketDesk.Domain.Model; using TicketDesk.PushNotifications; +using TicketDesk.PushNotifications.Model; using TicketDesk.Search.Common; using TicketDesk.Web.Client.Models; using TicketDesk.Web.Identity; @@ -83,11 +84,11 @@ public async Task UpgradeDatabase() - + return RedirectToAction("CheckUpgradeProgress"); } - + [Route("check-upgrade-progress")] @@ -174,9 +175,9 @@ public async Task CreateDatabase(string email, string password, st new MigrateDatabaseToLatestVersion(true)); ctx.Database.Initialize(true); } - - + + var filter = GlobalFilters.Filters.FirstOrDefault(f => f.Instance is DbSetupFilter); if (filter != null) @@ -186,11 +187,14 @@ public async Task CreateDatabase(string email, string password, st Database.SetInitializer(new TdIdentityDbInitializer()); var existingUser = UserManager.FindByName(email); + TicketDeskUser newUser = null; if (existingUser == null) { - var user = new TicketDeskUser {UserName = email, Email = email, DisplayName = displayName}; - await UserManager.CreateAsync(user, password); - await UserManager.AddToRoleAsync(user.Id, "TdAdministrators"); + newUser = new TicketDeskUser { UserName = email, Email = email, DisplayName = displayName }; + await UserManager.CreateAsync(newUser, password); + await UserManager.AddToRoleAsync(newUser.Id, "TdAdministrators"); + + } else { @@ -208,6 +212,28 @@ public async Task CreateDatabase(string email, string password, st Database.SetInitializer(new TdPushNotificationDbInitializer()); Startup.ConfigurePushNotifications(); + if (newUser != null) + { + using (var notificationContext = new TdPushNotificationContext()) + { + notificationContext.SubscriberPushNotificationSettingsManager.AddSettingsForSubscriber( + new SubscriberNotificationSetting + { + SubscriberId = newUser.Id, + IsEnabled = true, + PushNotificationDestinations = new[] + { + new PushNotificationDestination() + { + DestinationType = "email", + DestinationAddress = newUser.Email, + SubscriberName = newUser.DisplayName + } + } + }); + notificationContext.SaveChanges(); + } + } UpdateSearchIndex(); return RedirectToAction("Index"); } @@ -270,7 +296,7 @@ public ActionResult LegacySecurity() public ActionResult SetupCompleteInfo() { HttpContext.GetOwinContext().Authentication.SignOut(); - + if (!Model.DatabaseStatus.IsDatabaseReady || !Model.DatabaseStatus.IsCompatibleWithEfModel || Model.DatabaseStatus.HasLegacySecurityObjects) { return new EmptyResult(); diff --git a/TicketDesk/TicketDesk.Web.Client/Controllers/PushNotificationSettingsController.cs b/TicketDesk/TicketDesk.Web.Client/Controllers/PushNotificationSettingsController.cs index a25886a92..25b9b3131 100644 --- a/TicketDesk/TicketDesk.Web.Client/Controllers/PushNotificationSettingsController.cs +++ b/TicketDesk/TicketDesk.Web.Client/Controllers/PushNotificationSettingsController.cs @@ -36,6 +36,8 @@ public class PushNotificationSettingsController : Controller public PushNotificationSettingsController(TdPushNotificationContext noteContext, TdDomainContext domainContext) { + ViewBag.Saved = false; + NoteContext = noteContext; DomainContext = domainContext; } @@ -60,9 +62,13 @@ public ActionResult Index(ApplicationPushNotificationSetting settings, string si NoteContext.SaveChanges(); DomainContext.TicketDeskSettings.ClientSettings.Settings["DefaultSiteRootUrl"] = siteRootUrl.TrimEnd('/'); DomainContext.SaveChanges(); + ViewBag.Saved = true; } ViewBag.CurrentRootUrl = GetCurrentRootUrl(); ViewBag.SiteRootUrl = GetRootUrlSetting(); + + Task.Delay(500).ContinueWith(t => System.Web.HttpRuntime.UnloadAppDomain()).ConfigureAwait(false); + return View(dbSetting); } diff --git a/TicketDesk/TicketDesk.Web.Client/Controllers/UserAdministrationController.cs b/TicketDesk/TicketDesk.Web.Client/Controllers/UserAdministrationController.cs index 6926da472..10e23794e 100644 --- a/TicketDesk/TicketDesk.Web.Client/Controllers/UserAdministrationController.cs +++ b/TicketDesk/TicketDesk.Web.Client/Controllers/UserAdministrationController.cs @@ -101,6 +101,14 @@ public async Task Edit(UserAccountInfoViewModel model) //get role changes var roleIdsToRemove = user.Roles.Select(ur => ur.RoleId).Except(model.Roles).ToList(); + + if (User.Identity.GetUserId() == user.Id) + { + //stop current user from removing their own admin role + roleIdsToRemove = roleIdsToRemove.Except(RoleManager.Roles.Where(r => r.Name == "tdAdministrators").Select(r => r.Id)).ToList(); + } + + var roleIdsToAdd = model.Roles.Except(user.Roles.Select(ur => ur.RoleId)).ToList(); //do role removes if (await RemoveRoles(roleIdsToRemove, user)) diff --git a/TicketDesk/TicketDesk.Web.Client/Controllers/UserController.cs b/TicketDesk/TicketDesk.Web.Client/Controllers/UserController.cs index 1aa8162b7..127278ae4 100644 --- a/TicketDesk/TicketDesk.Web.Client/Controllers/UserController.cs +++ b/TicketDesk/TicketDesk.Web.Client/Controllers/UserController.cs @@ -119,6 +119,8 @@ public ActionResult SignIn(string returnUrl) [Route("sign-in")] public async Task SignIn(UserSignInViewModel model, string returnUrl) { + ViewBag.IsDemoMode = (ConfigurationManager.AppSettings["ticketdesk:DemoModeEnabled"] ?? "false").Equals("true", StringComparison.InvariantCultureIgnoreCase); + if (!ModelState.IsValid) { return View(model); diff --git a/TicketDesk/TicketDesk.Web.Client/Models/Extensions/TicketEventNotificationExtensions.cs b/TicketDesk/TicketDesk.Web.Client/Models/Extensions/TicketEventNotificationExtensions.cs index c49499db7..5fc1baed8 100644 --- a/TicketDesk/TicketDesk.Web.Client/Models/Extensions/TicketEventNotificationExtensions.cs +++ b/TicketDesk/TicketDesk.Web.Client/Models/Extensions/TicketEventNotificationExtensions.cs @@ -43,30 +43,45 @@ private static string RootUrl } + public static IEnumerable ToNewTicketPushNotificationInfoCollection( + this IEnumerable eventNotifications, + bool multiProject + ) + { + return eventNotifications.Select(note => new NewTicketPushNotificationInfo() + { + TicketId = note.TicketId, + MessageContent = GetEmailForNote(note, multiProject, true) + }); + } + public static IEnumerable ToNotificationEventInfoCollection( - this IEnumerable eventNotifications, bool subscriberExclude, bool multiProject) + this IEnumerable eventNotifications, + bool subscriberExclude, + bool multiProject) { - return eventNotifications.Select(note => + return eventNotifications.Select(note => new TicketPushNotificationEventInfo() { - - return new TicketPushNotificationEventInfo() - { - TicketId = note.TicketId, - SubscriberId = note.SubscriberId, - EventId = note.EventId, - CancelNotification = subscriberExclude && note.IsRead, - MessageContent = GetEmailForNote(note, multiProject) - }; - + TicketId = note.TicketId, + SubscriberId = note.SubscriberId, + EventId = note.EventId, + CancelNotification = subscriberExclude && note.IsRead, + MessageContent = GetEmailForNote(note, multiProject) }); } - private static string GetEmailForNote(TicketEventNotification note, bool multiProject) + private static string GetEmailForNote(TicketEventNotification note, bool multiProject, bool forNewTicket = false) { - var email = new TicketEmail { Ticket = note.TicketEvent.Ticket, SiteRootUrl = RootUrl, IsMultiProject = multiProject }; + var email = new TicketEmail + { + Ticket = note.TicketEvent.Ticket, + SiteRootUrl = RootUrl, + IsMultiProject = multiProject, + ForNewTicket = forNewTicket + }; var mailService = new EmailService(); SerializableMailMessage message = mailService.CreateMailMessage(email); using (var ms = new MemoryStream()) diff --git a/TicketDesk/TicketDesk.Web.Client/Models/TicketEmail.cs b/TicketDesk/TicketDesk.Web.Client/Models/TicketEmail.cs index a5ab4dfbe..308a71f2e 100644 --- a/TicketDesk/TicketDesk.Web.Client/Models/TicketEmail.cs +++ b/TicketDesk/TicketDesk.Web.Client/Models/TicketEmail.cs @@ -13,5 +13,7 @@ public class TicketEmail : Email public string SiteRootUrl { get; set; } public bool IsMultiProject { get; set; } + + public bool ForNewTicket { get; set; } } } \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/edit-ticket.js b/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/edit-ticket.js index b818c2d25..a2bcaee53 100644 --- a/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/edit-ticket.js +++ b/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/edit-ticket.js @@ -104,7 +104,21 @@ }); if (config.isEditorDefaultHtml) { jelem = $('#wmd-input-activity'); - jelem.summernote({ height: 200, lang: window.currentCulture }); + jelem.summernote({ + height: 200, + lang: window.currentCulture, + toolbar: [ + ['style', ['style']], + ['font', ['bold', 'italic']], + ['fontname', ['fontname']], + ['fontsize', ['fontsize']], + ['color', ['color']], + ['para', ['ul', 'ol', 'paragraph']], + ['insert', ['link', 'hr']], + ['view', ['fullscreen']], + ['help', ['help']] + ] + }); if (jelem.length > 0) { if (jelem.data('is-required')) { diff --git a/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/ticket-details.js b/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/ticket-details.js index 10d2f7c07..8697f47a2 100644 --- a/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/ticket-details.js +++ b/TicketDesk/TicketDesk.Web.Client/Scripts/ticketdesk/ticket-details.js @@ -21,7 +21,21 @@ ignore: "" }); if (config.isHtml) { - $('#wmd-input-ticketDetails').summernote({ height: 200, lang: window.currentCulture }); + $('#wmd-input-ticketDetails').summernote({ + height: 200, + lang: window.currentCulture, + toolbar: [ + ['style', ['style']], + ['font', ['bold', 'italic']], + ['fontname', ['fontname']], + ['fontsize', ['fontsize']], + ['color', ['color']], + ['para', ['ul', 'ol', 'paragraph']], + ['insert', ['link', 'hr']], + ['view', ['fullscreen']], + ['help', ['help']] + ] + }); } else { configureMarkdownEditor(); diff --git a/TicketDesk/TicketDesk.Web.Client/TicketDesk.Web.Client.csproj b/TicketDesk/TicketDesk.Web.Client/TicketDesk.Web.Client.csproj index dac341687..e1b039562 100644 --- a/TicketDesk/TicketDesk.Web.Client/TicketDesk.Web.Client.csproj +++ b/TicketDesk/TicketDesk.Web.Client/TicketDesk.Web.Client.csproj @@ -1,1026 +1,1017 @@  - - - Debug - AnyCPU - - - 2.0 - {4DE41C1E-3E56-480E-9C88-0A4D6BACC798} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TicketDesk.Web.Client - TicketDesk.Web.Client - v4.6.1 - false - true - 44373 - - - - ..\ - - - - /subscriptions/f96911eb-9288-41c5-afd8-30e2a9b16f96/resourcegroups/Default-Web-CentralUS/providers/microsoft.insights/components/ticketdesk2 - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - ..\packages\AngleSharp.0.9.5\lib\net45\AngleSharp.dll - True - - - False - ..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll - - - ..\packages\CsQuery.1.3.4\lib\net40\CsQuery.dll - True - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - True - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll - True - - - ..\packages\HtmlSanitizer.3.2.103\lib\net45\HtmlSanitizer.dll - True - - - ..\packages\MarkdownSharp.1.13.0.0\lib\35\MarkdownSharp.dll - - - ..\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.0.1\lib\net45\Microsoft.AI.Agent.Intercept.dll - True - - - ..\packages\Microsoft.ApplicationInsights.DependencyCollector.2.1.0\lib\net45\Microsoft.AI.DependencyCollector.dll - True - - - ..\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.1.0\lib\net45\Microsoft.AI.PerfCounterCollector.dll - True - - - ..\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.1.0\lib\net45\Microsoft.AI.ServerTelemetryChannel.dll - True - - - ..\packages\Microsoft.ApplicationInsights.Web.2.1.0\lib\net45\Microsoft.AI.Web.dll - True - - - ..\packages\Microsoft.ApplicationInsights.WindowsServer.2.1.0\lib\net45\Microsoft.AI.WindowsServer.dll - True - - - ..\packages\Microsoft.ApplicationInsights.2.1.0\lib\net46\Microsoft.ApplicationInsights.dll - True - - - False - ..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll - - - False - ..\packages\Microsoft.AspNet.Identity.EntityFramework.2.2.1\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll - - - False - ..\packages\Microsoft.AspNet.Identity.Owin.2.2.1\lib\net45\Microsoft.AspNet.Identity.Owin.dll - - - - ..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.28\lib\net40\Microsoft.Diagnostics.Tracing.EventSource.dll - True - - - False - ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll - - - False - ..\packages\Microsoft.Owin.Host.SystemWeb.3.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll - - - False - ..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll - - - False - ..\packages\Microsoft.Owin.Security.Cookies.3.0.1\lib\net45\Microsoft.Owin.Security.Cookies.dll - - - False - ..\packages\Microsoft.Owin.Security.OAuth.3.0.1\lib\net45\Microsoft.Owin.Security.OAuth.dll - - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll - True - - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll - - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll - - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True - - - ..\packages\Owin.1.0\lib\net40\Owin.dll - - - ..\packages\Postal.Mvc5.1.2.0\lib\net45\Postal.dll - True - - - ..\packages\RazorEngine.3.8.1\lib\net45\RazorEngine.dll - True - - - ..\packages\SimpleInjector.4.0.2\lib\net45\SimpleInjector.dll - True - - - ..\packages\SimpleInjector.Integration.Web.4.0.2\lib\net40\SimpleInjector.Integration.Web.dll - True - - - ..\packages\SimpleInjector.Integration.Web.Mvc.4.0.2\lib\net40\SimpleInjector.Integration.Web.Mvc.dll - True - - - - - - - - - - - - False - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - - - False - ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - - - False - ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - - - - False - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - - - False - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - - - False - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - - - - - - True - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - - - - - ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - - - False - ..\packages\WebGrease.1.6.0\lib\WebGrease.dll - - - ..\packages\X.PagedList.1.24.1.320\lib\net451\X.PagedList.dll - True - - - ..\packages\X.PagedList.Mvc.4.9.1.310\lib\net45\X.PagedList.Mvc.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jquery.clickable-0.1.9.min.js - - - - jquery.clickable-0.1.9.js - - - - - - - - - - ticketcenter.js - - - - - - Designer - - - Web.config - - - Web.config - - - - - - - - - - - - - - - ticketcenter.min.js - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Web.config - Designer - - - - - - - - - - - - {ca72a1aa-6f1a-4d5f-b98b-fd73f5407563} - S22.Mail - - - {a85d9882-1db3-40ec-a23e-6b4562f48bcf} - TicketDesk.Domain.Legacy - - - {dbd5279b-9f1c-4915-86a9-6a8f1cf0622d} - TicketDesk.Domain - - - {d9477c13-68c4-43e0-a30b-f06f444c5358} - TicketDesk.IO - - - {be8715f9-e858-473e-a2b6-561c9edca416} - TicketDesk.Localization - - - {6e3b1af8-762d-4b69-84c3-c79e74aa9c82} - TicketDesk.PushNotifications - - - {be284cb5-bf8b-4b51-a865-f2ab7bea2d02} - TicketDesk.Search.Azure - - - {f8c97321-f0cc-4af9-86e6-95e0e4840430} - TicketDesk.Search.Common - - - {54390f7f-a440-40f7-8b1a-28ab599a5213} - TicketDesk.Search.Lucene - - - {bd3617c2-a91e-40f3-a441-b085d2491399} - TicketDesk.Web.Identity - - - - - - - 12.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - - - - True - True - 52771 - / - https://localhost:44373/ - False - False - - - False - - - - - - + - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + true + Debug + AnyCPU + + + 2.0 + {4DE41C1E-3E56-480E-9C88-0A4D6BACC798} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TicketDesk.Web.Client + TicketDesk.Web.Client + v4.6.2 + false + true + 44373 + + + + ..\ + + + + /subscriptions/f96911eb-9288-41c5-afd8-30e2a9b16f96/resourcegroups/Default-Web-CentralUS/providers/microsoft.insights/components/ticketdesk2 + - - - - - - + - - - + - + @@ -46,7 +46,7 @@ - + @@ -56,7 +56,7 @@ - + @@ -72,23 +72,23 @@ - + - + - + - + - + @@ -96,7 +96,7 @@ - + @@ -140,12 +140,16 @@ - + + + + + @@ -160,6 +164,8 @@ + + @@ -171,9 +177,7 @@ - - - + diff --git a/TicketDesk/TicketDesk.Web.Client/packages.config b/TicketDesk/TicketDesk.Web.Client/packages.config index 78587d4c7..276af7b37 100644 --- a/TicketDesk/TicketDesk.Web.Client/packages.config +++ b/TicketDesk/TicketDesk.Web.Client/packages.config @@ -14,19 +14,20 @@ - - - + + + - - - - + + + + + @@ -35,25 +36,27 @@ - - - - - + + + + + - + - + - + - - - + + + + + - - + + \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Web.Identity/App.config b/TicketDesk/TicketDesk.Web.Identity/App.config index 6adb689b9..54f73d951 100644 --- a/TicketDesk/TicketDesk.Web.Identity/App.config +++ b/TicketDesk/TicketDesk.Web.Identity/App.config @@ -14,4 +14,4 @@ - + diff --git a/TicketDesk/TicketDesk.Web.Identity/Model/UserEqualityComparer.cs b/TicketDesk/TicketDesk.Web.Identity/Model/UserEqualityComparer.cs new file mode 100644 index 000000000..2ebea0664 --- /dev/null +++ b/TicketDesk/TicketDesk.Web.Identity/Model/UserEqualityComparer.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using TicketDesk.Web.Identity.Model; + +namespace TicketDesk.Web.Identity.Model +{ + public class StandardUserEqualityComparer : IEqualityComparer + { + public bool Equals(TicketDeskUser x, TicketDeskUser y) + { + return x.Id == y.Id; + } + + public int GetHashCode(TicketDeskUser obj) + { + return obj.Id.GetHashCode(); + } + } + + public class UniqueNameEmailDisplayUserEqualityComparer : IEqualityComparer + { + public bool Equals(TicketDeskUser x, TicketDeskUser y) + { + return x.DisplayName == y.DisplayName && x.Email == y.Email; + } + + public int GetHashCode(TicketDeskUser obj) + { + return obj.DisplayName.GetHashCode() + obj.Email.GetHashCode(); + } + } + +} \ No newline at end of file diff --git a/TicketDesk/TicketDesk.Web.Identity/TicketDesk.Web.Identity.csproj b/TicketDesk/TicketDesk.Web.Identity/TicketDesk.Web.Identity.csproj index cac4b660b..c4ff8622b 100644 --- a/TicketDesk/TicketDesk.Web.Identity/TicketDesk.Web.Identity.csproj +++ b/TicketDesk/TicketDesk.Web.Identity/TicketDesk.Web.Identity.csproj @@ -9,7 +9,7 @@ Properties TicketDesk.Web.Identity TicketDesk.Web.Identity - v4.6.1 + v4.6.2 512 ..\ @@ -66,6 +66,7 @@ +