diff --git a/Ombi.Core/SettingModels/CustomizationSettings.cs b/Ombi.Core/SettingModels/CustomizationSettings.cs index 6225861ad..2fa664f35 100644 --- a/Ombi.Core/SettingModels/CustomizationSettings.cs +++ b/Ombi.Core/SettingModels/CustomizationSettings.cs @@ -35,5 +35,23 @@ namespace Ombi.Core.SettingModels /// The CSS name of the theme we want /// public string ThemeName { get; set; } + + /// + /// Admin Only. + /// + /// + /// The default filter. + /// + public int DefaultFilter { get; set; } + /// + /// Admin only. + /// + /// + /// The default sort. + /// + public int DefaultSort { get; set; } + + public int DefaultLang { get; set; } + } } \ No newline at end of file diff --git a/Ombi.Helpers/EnumHelper.cs b/Ombi.Helpers/EnumHelper.cs index 316de8ec7..db1ced9da 100644 --- a/Ombi.Helpers/EnumHelper.cs +++ b/Ombi.Helpers/EnumHelper.cs @@ -82,6 +82,19 @@ namespace Ombi.Helpers if (descriptionAttributes == null) return string.Empty; return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString(); } + public static string GetDisplayDescription(T value) + { + var fieldInfo = value.GetType().GetField(value.ToString()); + + var descriptionAttributes = fieldInfo.GetCustomAttributes( + typeof(DisplayAttribute), false) as DisplayAttribute[]; + + if (descriptionAttributes[0].ResourceType != null) + return LookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Description); + + if (descriptionAttributes == null) return string.Empty; + return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Description : value.ToString(); + } public static T GetValueFromName(string name) { diff --git a/Ombi.UI/Content/requests.js b/Ombi.UI/Content/requests.js index 7af2631ed..31a5a3761 100644 --- a/Ombi.UI/Content/requests.js +++ b/Ombi.UI/Content/requests.js @@ -17,8 +17,26 @@ var tvLoaded = false; var albumLoaded = false; var isAdmin = $('#isAdmin').text(); + + var defaultFiler = isAdmin == 'True' ? '.approved-fase' : 'all'; +var url = createBaseUrl(base, '/requests/UpdateFilters'); +$.ajax({ + type: 'GET', + url: url, + dataType: "json", + success: function (response) { + + mixItUpDefault.load.filter = response.defaultFilter; + mixItUpDefault.load.sort = response.defaultSort; + }, + error: function (e) { + console.log(e); + generateNotify("Something went wrong saving your filter!", "danger"); + } +}); + var mixItUpDefault = { animation: { enable: true }, load: { @@ -30,26 +48,6 @@ var mixItUpDefault = { }, callbacks: { onMixStart: function (state, futureState) { - //futureState.activeSort // sort - //futureState.activeFilter // next filter - - // The below is TODO for saving the users filter and sort order - //var url = createBaseUrl(base, '/requests/UpdateFilters'); - //$.ajax({ - // type: 'post', - // url: url, - // data: {sort:futureState.activeSort, filter:futureState.activeFilte}, - // dataType: "json", - // success: function (response) { - // console.log("saved filter and sort order"); - // }, - // error: function (e) { - // console.log(e); - // generateNotify("Something went wrong saving your filter!", "danger"); - // } - //}); - - $('.mix', this).removeAttr('data-bound').removeData('bound'); // fix for animation issues in other tabs } } diff --git a/Ombi.UI/Models/Admin/CustomizationViewModel.cs b/Ombi.UI/Models/Admin/CustomizationViewModel.cs new file mode 100644 index 000000000..1c6082af3 --- /dev/null +++ b/Ombi.UI/Models/Admin/CustomizationViewModel.cs @@ -0,0 +1,91 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: CustomizationViewModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using Ombi.Core.SettingModels; +using Ombi.UI.Models.UI; + +namespace Ombi.UI.Models.Admin +{ + public class CustomizationViewModel + { + public CustomizationSettings Settings { get; set; } + public List> LanguageDropdown { get; set; } = new List>(); + public List> FilterOptions { get; set; } = new List>(); + public List> SortOptions { get; set; } = new List>(); + } + + public enum FilterOptions + { + [Display(Name = ".available-true", Description = "Available")] + Available, + [Display(Name = ".available-false", Description = "Not Available")] + NotAvailable, + [Display(Name = ".released-true", Description = "Released")] + Released, + [Display(Name = ".released-false", Description = "Not Released")] + NotReleased + } + + public enum SortOptions + { + [Display(Name = "requestorder:desc", Description = "Latest Requests")] + LatestRequests, + [Display(Name = "requestorder:asc", Description = "Oldest Requests")] + OldestRequests, + [Display(Name = "releaseorder:desc", Description = "Latest Releases")] + LatestRelease, + [Display(Name = "releaseorder:asc", Description = "Oldest Releases")] + OldestRelease + } + + public enum Languages + { + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_English")] + en, + + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_French")] + fr, + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_Dutch")] + nl, + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_Spanish")] + es, + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_German")] + de, + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_Danish")] + da, + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_Portuguese")] + pt, + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_Swedish")] + sv, + [Display(ResourceType = typeof(Resources.UI), Name = "Layout_Italian")] + it + } +} \ No newline at end of file diff --git a/Ombi.UI/Models/UI/Dropdown.cs b/Ombi.UI/Models/UI/Dropdown.cs new file mode 100644 index 000000000..834a7cf61 --- /dev/null +++ b/Ombi.UI/Models/UI/Dropdown.cs @@ -0,0 +1,35 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: Dropdown.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace Ombi.UI.Models.UI +{ + public class Dropdown + { + public bool Selected { get; set; } + public string Name { get; set; } + public T Value { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.UI/Modules/Admin/CustomizationModule.cs b/Ombi.UI/Modules/Admin/CustomizationModule.cs index a368e66f4..d34e41ee2 100644 --- a/Ombi.UI/Modules/Admin/CustomizationModule.cs +++ b/Ombi.UI/Modules/Admin/CustomizationModule.cs @@ -1,4 +1,5 @@ #region Copyright + // /************************************************************************ // Copyright (c) 2016 Jamie Rees // File: CustomizationModule.cs @@ -23,43 +24,94 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ + #endregion +using System; +using System.Collections.Generic; using System.Threading.Tasks; using Nancy; using Nancy.ModelBinding; using Nancy.Responses.Negotiation; using Ombi.Core; using Ombi.Core.SettingModels; +using Ombi.Helpers; using Ombi.Helpers.Permissions; using Ombi.UI.Models; +using Ombi.UI.Models.Admin; +using Ombi.UI.Models.UI; +using TMDbLib.Utilities; using ISecurityExtensions = Ombi.Core.ISecurityExtensions; namespace Ombi.UI.Modules.Admin { public class CustomizationModule : BaseModule { - public CustomizationModule(ISettingsService settingsService, ISettingsService cust, ISecurityExtensions security) : base("admin", settingsService, security) + public CustomizationModule(ISettingsService settingsService, + ISettingsService cust, ISecurityExtensions security) + : base("admin", settingsService, security) { Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx); Settings = cust; - Get["/customization", true] = async (x,ct) => await Index(); - Post["/customization", true] = async (x,ct) => await Save(); + Get["/customization", true] = async (x, ct) => await Index(); + Post["/customization", true] = async (x, ct) => await Save(); } - + private ISettingsService Settings { get; } private async Task Index() { var model = await Settings.GetSettingsAsync(); - return View["customization", model]; + var viewModel = new CustomizationViewModel + { + Settings = model, + SortOptions = new List>() + }; + + + + + foreach (var value in EnumHelper.GetValues(SortOptions.LatestRelease)) + { + viewModel.SortOptions.Add(new Dropdown + { + Value = value, + Name = EnumHelper.GetDisplayDescription(value), + Selected = model.DefaultSort == (int) value + }); + } + + foreach (var value in EnumHelper.GetValues(FilterOptions.Available)) + { + viewModel.FilterOptions.Add(new Dropdown + { + Value = value, + Name = EnumHelper.GetDisplayDescription(value), + Selected = model.DefaultFilter == (int) value + }); + } + + foreach (var value in EnumHelper.GetValues(Languages.en)) + { + viewModel.LanguageDropdown.Add(new Dropdown + { + Value = value, + Name = EnumHelper.GetDisplayValue(value), + Selected = model.DefaultLang == (int) value + }); + } + + return View["customization", viewModel]; } private async Task Save() { + try + { + var model = this.Bind(); var result = await Settings.SaveSettingsAsync(model); @@ -67,6 +119,12 @@ namespace Ombi.UI.Modules.Admin return Response.AsJson(result ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "We could not save to the database, please try again" }); + } + catch (Exception e) + { + + throw; + } } } } \ No newline at end of file diff --git a/Ombi.UI/Modules/RequestsModule.cs b/Ombi.UI/Modules/RequestsModule.cs index e304120e5..5d9d8596f 100644 --- a/Ombi.UI/Modules/RequestsModule.cs +++ b/Ombi.UI/Modules/RequestsModule.cs @@ -43,6 +43,7 @@ using Ombi.Services.Interfaces; using Ombi.Services.Notification; using Ombi.Store; using Ombi.UI.Models; +using Ombi.UI.Models.Admin; using Action = Ombi.Helpers.Analytics.Action; using ISecurityExtensions = Ombi.Core.ISecurityExtensions; @@ -64,7 +65,8 @@ namespace Ombi.UI.Modules ICacheProvider cache, IAnalytics an, INotificationEngine engine, - ISecurityExtensions security) : base("requests", prSettings, security) + ISecurityExtensions security, + ISettingsService customSettings) : base("requests", prSettings, security) { Service = service; PrSettings = prSettings; @@ -79,6 +81,7 @@ namespace Ombi.UI.Modules Cache = cache; Analytics = an; NotificationEngine = engine; + CustomizationSettings = customSettings; Get["/", true] = async (x, ct) => await LoadRequests(); Get["/movies", true] = async (x, ct) => await GetMovies(); @@ -92,7 +95,7 @@ namespace Ombi.UI.Modules Post["/changeavailability", true] = async (x, ct) => await ChangeRequestAvailability((int)Request.Form.Id, (bool)Request.Form.Available); - Post["/UpdateFilters", true] = async (x, ct) => await UpdateFilters(); + Get["/UpdateFilters", true] = async (x, ct) => await GetFilterAndSortSettings(); } private static Logger Log = LogManager.GetCurrentClassLogger(); @@ -104,6 +107,7 @@ namespace Ombi.UI.Modules private ISettingsService SonarrSettings { get; } private ISettingsService SickRageSettings { get; } private ISettingsService CpSettings { get; } + private ISettingsService CustomizationSettings { get; } private ISonarrApi SonarrApi { get; } private ISickRageApi SickRageApi { get; } private ICouchPotatoApi CpApi { get; } @@ -408,11 +412,20 @@ namespace Ombi.UI.Modules : new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" }); } - private async Task UpdateFilters() + private async Task GetFilterAndSortSettings() { + var s = await CustomizationSettings.GetSettingsAsync(); + var sortVal = EnumHelper.GetDisplayValue((SortOptions)s.DefaultSort); + var filterVal = EnumHelper.GetDisplayValue((FilterOptions)s.DefaultFilter); - return Response.AsJson(""); + var vm = new + { + DefaultSort = sortVal, + DefaultFilter = filterVal + }; + + return Response.AsJson(vm); } } } diff --git a/Ombi.UI/Ombi.UI.csproj b/Ombi.UI/Ombi.UI.csproj index 74904233c..0a151d769 100644 --- a/Ombi.UI/Ombi.UI.csproj +++ b/Ombi.UI/Ombi.UI.csproj @@ -118,6 +118,7 @@ True + @@ -233,6 +234,7 @@ + @@ -247,6 +249,7 @@ + diff --git a/Ombi.UI/Views/Customization/Customization.cshtml b/Ombi.UI/Views/Customization/Customization.cshtml index 112fb6e44..ff2e7a296 100644 --- a/Ombi.UI/Views/Customization/Customization.cshtml +++ b/Ombi.UI/Views/Customization/Customization.cshtml @@ -1,14 +1,14 @@ @using Ombi.UI.Helpers -@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase +@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase @Html.Partial("Shared/Partial/_Sidebar") @{ var plexTheme = string.Empty; var originalTheme = string.Empty; - if (!string.IsNullOrEmpty(Model.ThemeName)) + if (!string.IsNullOrEmpty(Model.Settings.ThemeName)) { - plexTheme = Model.ThemeName.Equals(Themes.PlexTheme) ? "selected=\"selected\"" : string.Empty; - originalTheme = Model.ThemeName.Equals(Themes.OriginalTheme) ? "selected=\"selected\"" : string.Empty; + plexTheme = Model.Settings.ThemeName.Equals(Themes.PlexTheme) ? "selected=\"selected\"" : string.Empty; + originalTheme = Model.Settings.ThemeName.Equals(Themes.OriginalTheme) ? "selected=\"selected\"" : string.Empty; } else { @@ -26,7 +26,7 @@
- +
@@ -39,6 +39,69 @@ + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
@@ -60,10 +123,17 @@ e.preventDefault(); var theme = $("#themes option:selected").val(); + var lang = $('#langSelect option:selected').val(); + var sort = $('#sortSelect option:selected').val(); + var filter = $('#filterSelect option:selected').val(); var $form = $("#mainForm"); var data = $form.serialize(); - data = data + "&themeName=" + theme; + data = data + + "&themeName=" + theme + + "&DefaultLang=" + lang + + "&DefaultSort=" + sort + + "&DefaultFilter=" + filter; $.ajax({ type: $form.prop("method"), diff --git a/Ombi.UI/Views/Shared/Partial/_Navbar.cshtml b/Ombi.UI/Views/Shared/Partial/_Navbar.cshtml index 9d3e24893..f801cc9a4 100644 --- a/Ombi.UI/Views/Shared/Partial/_Navbar.cshtml +++ b/Ombi.UI/Views/Shared/Partial/_Navbar.cshtml @@ -1,4 +1,4 @@ -ab@using Nancy.Security +@using Nancy.Security @using Nancy.Session @using Nancy; @using Ombi.Helpers