Quality Profile now uses jQuery UI Selectable instead of Sortable.

pull/3113/head
Mark McDowall 14 years ago
parent 72e73b7513
commit 556d5d9fb3

@ -138,14 +138,14 @@ namespace NzbDrone.Web.Controllers
var defaultQualityQualityProfileId = Convert.ToInt32(_configProvider.DefaultQualityProfile); var defaultQualityQualityProfileId = Convert.ToInt32(_configProvider.DefaultQualityProfile);
var downloadPropers = _configProvider.DownloadPropers; var downloadPropers = _configProvider.DownloadPropers;
var selectList = new SelectList(profiles, "QualityProfileId", "Name"); var qualityProfileSelectList = new SelectList(profiles, "QualityProfileId", "Name");
var model = new QualityModel var model = new QualityModel
{ {
Profiles = profiles, Profiles = profiles,
DefaultQualityProfileId = defaultQualityQualityProfileId, DefaultQualityProfileId = defaultQualityQualityProfileId,
DownloadPropers = downloadPropers, DownloadPropers = downloadPropers,
SelectList = selectList QualityProfileSelectList = qualityProfileSelectList
}; };
return View("Index", model); return View("Index", model);
@ -208,7 +208,7 @@ namespace NzbDrone.Web.Controllers
qualityTypes.Add(qual); qualityTypes.Add(qual);
} }
ViewData["Qualities"] = qualityTypes; ViewData["Qualities"] = new SelectList(qualityTypes);
var qualityProfile = new QualityProfile var qualityProfile = new QualityProfile
{ {
@ -234,6 +234,7 @@ namespace NzbDrone.Web.Controllers
{ {
qualityTypes.Add(qual); qualityTypes.Add(qual);
} }
ViewData["Qualities"] = qualityTypes; ViewData["Qualities"] = qualityTypes;
ViewData["ProfileId"] = profile.QualityProfileId; ViewData["ProfileId"] = profile.QualityProfileId;
@ -286,7 +287,7 @@ namespace NzbDrone.Web.Controllers
Convert.ToInt32(_configProvider.GetValue("DefaultQualityProfile", profiles[0].QualityProfileId, true)); Convert.ToInt32(_configProvider.GetValue("DefaultQualityProfile", profiles[0].QualityProfileId, true));
var selectList = new SelectList(profiles, "QualityProfileId", "Name"); var selectList = new SelectList(profiles, "QualityProfileId", "Name");
return new QualityModel { DefaultQualityProfileId = defaultQualityQualityProfileId, SelectList = selectList }; return new QualityModel { DefaultQualityProfileId = defaultQualityQualityProfileId, QualityProfileSelectList = selectList };
} }
public JsonResult DeleteQualityProfile(int profileId) public JsonResult DeleteQualityProfile(int profileId)
@ -470,6 +471,10 @@ namespace NzbDrone.Web.Controllers
Logger.Debug(String.Format("Updating Profile: {0}", profile)); Logger.Debug(String.Format("Updating Profile: {0}", profile));
profile.Allowed = new List<QualityTypes>(); profile.Allowed = new List<QualityTypes>();
//Remove the extra comma from the end and replace double commas with a single one (the Javascript gets a little crazy)
profile.AllowedString = profile.AllowedString.Replace(",,", ",").Trim(',');
foreach (var quality in profile.AllowedString.Split(',')) foreach (var quality in profile.AllowedString.Split(','))
{ {
var qType = (QualityTypes)Enum.Parse(typeof(QualityTypes), quality); var qType = (QualityTypes)Enum.Parse(typeof(QualityTypes), quality);

@ -17,6 +17,6 @@ namespace NzbDrone.Web.Models
[Description("Should NzbDrone download proper releases (to replace non-proper files)?")] [Description("Should NzbDrone download proper releases (to replace non-proper files)?")]
public bool DownloadPropers { get; set; } public bool DownloadPropers { get; set; }
public SelectList SelectList { get; set; } public SelectList QualityProfileSelectList { get; set; }
} }
} }

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NzbDrone.Core.Repository.Quality;
namespace NzbDrone.Web.Models
{
public class QualityTypeModel
{
public int Id { get; set; }
public QualityTypes Name { get; set; }
}
}

@ -237,6 +237,7 @@
<Compile Include="Models\AddExistingManualModel.cs" /> <Compile Include="Models\AddExistingManualModel.cs" />
<Compile Include="Models\AddExistingSeriesModel.cs" /> <Compile Include="Models\AddExistingSeriesModel.cs" />
<Compile Include="Models\AddNewSeriesModel.cs" /> <Compile Include="Models\AddNewSeriesModel.cs" />
<Compile Include="Models\QualityTypeModel.cs" />
<Compile Include="Models\RootDirModel.cs" /> <Compile Include="Models\RootDirModel.cs" />
<Compile Include="Models\SabnzbdSettingsModel.cs" /> <Compile Include="Models\SabnzbdSettingsModel.cs" />
<Compile Include="Models\EpisodeSortingModel.cs" /> <Compile Include="Models\EpisodeSortingModel.cs" />

@ -62,7 +62,7 @@
<div class="config-section"> <div class="config-section">
<div class="config-group"> <div class="config-group">
<div class="config-title">@Html.LabelFor(m => m.DefaultQualityProfileId)</div> <div class="config-title">@Html.LabelFor(m => m.DefaultQualityProfileId)</div>
<div class="config-value">@Html.DropDownListFor(m => m.DefaultQualityProfileId, Model.SelectList)</div> <div class="config-value">@Html.DropDownListFor(m => m.DefaultQualityProfileId, Model.QualityProfileSelectList)</div>
</div> </div>
<div class="config-group2"> <div class="config-group2">
<div class="config-validation">@Html.ValidationMessageFor(m => m.DefaultQualityProfileId)</div> <div class="config-validation">@Html.ValidationMessageFor(m => m.DefaultQualityProfileId)</div>

@ -1,4 +1,5 @@
@model NzbDrone.Core.Repository.Quality.QualityProfile @model NzbDrone.Core.Repository.Quality.QualityProfile
@using System.Collections
@using NzbDrone.Core.Repository.Quality @using NzbDrone.Core.Repository.Quality
@using NzbDrone.Web.Helpers @using NzbDrone.Web.Helpers
@ -17,123 +18,92 @@
var idClean = ViewData.TemplateInfo.HtmlFieldPrefix.Replace('[', '_').Replace(']', '_'); var idClean = ViewData.TemplateInfo.HtmlFieldPrefix.Replace('[', '_').Replace(']', '_');
var ugly = ViewData.TemplateInfo.HtmlFieldPrefix; var ugly = ViewData.TemplateInfo.HtmlFieldPrefix;
string sortable1 = String.Format("{0}_sortable1", idClean); string selectable = String.Format("{0}_selectable", idClean);
string sortable2 = String.Format("{0}_sortable2", idClean);
string allowedStringName = String.Format("{0}_AllowedString", idClean); string allowedStringName = String.Format("{0}_AllowedString", idClean);
string connectedSortable = String.Format("connected{0}", idClean);
string title = String.Format("{0}_Title", idClean); string title = String.Format("{0}_Title", idClean);
string nameBox = String.Format("{0}_Name", idClean); string nameBox = String.Format("{0}_Name", idClean);
string cutoff = String.Format("{0}.Cutoff", ugly); string cutoff = String.Format("{0}.Cutoff", ugly);
<style type="text/css"> <style>
.sortable1, .sortable2 { list-style-type: none; margin-right: 10px; background: #eee; padding-left: 5px; padding-right: 5px; padding-top: 0px; padding-bottom: 6px; width: 117px; margin-bottom: 3px; } .selectableList .ui-selecting { background: #85AEF9; }
.allowedQualities, .otherQualities { list-style-type: none; float: left; margin-right: 10px; background: #eee; padding-left: 5px; padding-right: 5px; padding-top:6px; width: 122px; -khtml-border-radius:8px;border-radius:8px;-moz-border-radius:8px;-webkit-border-radius:8px; } .selectableList .ui-selected { background: #065EFE; color: white; }
.sortable1 li, .sortable2 li { margin: 5px; margin-left: 0px; padding: 0px; font-size: 1.2em; width: 110px; -khtml-border-radius:8px;border-radius:8px;-moz-border-radius:8px;-webkit-border-radius:8px; } .selectableList { list-style-type: none; margin: 0; padding: 0; }
.sortable1 li { background: #ddd; } .selectableList li { margin: 3px; margin-left: 10px; padding-left: 0.4em; padding-bottom: 1.5em; padding-top: 0em; float: left; font-size: 1.2em; width: 110px; height: 6px; }
.sortable2 li { background: #DAA2A2; }
.sortableHeader { margin:2px; margin-left:12px }
.sortable1 li.ui-state-highlight, .sortable2 li.ui-state-highlight { background: #fbf5d0; border-color: #065EFE; }
.removeDiv { float: left; display:block; }
.ui-state-highlight { height: 1.5em; line-height: 1.2em; }
</style> </style>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$("#@sortable1, #@sortable2").sortable({ $("#@selectable").selectable({
connectWith: ".@connectedSortable", create: function () {
placeholder: "ui-state-highlight", var result = "";
dropOnEmpty: true, $(".ui-selected", this).each(function () {
result += this.id + ",";
create: function (event, ui) { });
var order = $('#@sortable1').sortable("toArray"); $("#@allowedStringName").empty().val(result);
$("#@allowedStringName").val(order);
}, },
update: function (event, ui) { stop: function () {
var order = $('#@sortable1').sortable("toArray"); var result = "";
$("#@allowedStringName").val(order); $(".ui-selected", this).each(function () {
result += this.id + ",";
//If this is the first QualityType added to the Profile select it as the cutoff value (in-case the user forgets) });
var $list = $('#@sortable1 li'); $("#@allowedStringName").empty().val(result);
if ($list.length == 1) {
var $radios = $('input[name="@cutoff"]');
$radios.filter('[value=' + order + ']').attr('checked', true);
}
} }
}).disableSelection(); });
}); })
</script> </script>
<div class="profileSectionEditor" id="div_@(ViewData["ProfileId"])"> <div class="profileSectionEditor" id="div_@(ViewData["ProfileId"])">
<fieldset style="width:285px; max-width:285px; margin:5px; margin-top: 0px; border-color:#CCCCCD"> <fieldset style="width:264px; margin:5px; margin-top: 0px; border-color:#CCCCCD">
<div id="tester"></div> <div class="header">
<div id="qualityHeader" style="padding-bottom: 5px; margin: 0px;">
<h2 style="display:inline; padding-right: 4px; margin-left: 4px;" id="@title">@{Html.DisplayTextFor(m => m.Name);}</h2>
<a href="#" id="@Model.QualityProfileId" class="deleteRow" onclick="deleteProfile('@ViewData["ProfileId"]'); return false;" style="float:right; padding-top:15px; padding-right: 5px;"><img src="../../Content/Images/X.png" alt="Delete"/></a>
</div>
<div id="qualityHeader" style="padding-bottom: 5px; margin: 0px;"> <div class="config-group" style="width: 255px; margin-bottom: 5px; margin-left: 5px;">
<h2 style="display:inline; padding-right: 4px; margin-left: 4px;" id="@title">@{Html.DisplayTextFor(m => m.Name);}</h2> <div class="config-title">@Html.LabelFor(x => x.Name)</div>
<a href="#" id="@Model.QualityProfileId" class="deleteRow" onclick="deleteProfile('@ViewData["ProfileId"]'); return false;" style="float:right; padding-top:15px;"><img src="../../Content/Images/X.png" alt="Delete"/></a> <div class="config-value">@Html.TextBoxFor(x => x.Name, new { maxlength = 16 })</div>
</div> <div class="config-validation">@Html.ValidationMessageFor(x => x.Name)</div>
</div>
<div class="config-group" style="width: 270px; margin-bottom: 5px; margin-left: 5px;"> <div class="config-group" style="width: 255px; margin-bottom: 5px; margin-left: 5px;">
<div class="config-title">@Html.LabelFor(x => x.Name)</div> <div class="config-title">@Html.LabelFor(x => x.Cutoff)</div>
<div class="config-value">@Html.TextBoxFor(x => x.Name, new { maxlength = 16})</div> <div class="config-value">@Html.DropDownListFor(m => m.Cutoff, new SelectList(ViewData["Qualities"] as IEnumerable, Model.Cutoff))</div>
<div class="config-validation">@Html.ValidationMessageFor(x => x.Name)</div> <div class="config-validation">@Html.ValidationMessageFor(x => x.Cutoff)</div>
</div>
</div> </div>
<div id="sortablesDiv" style="margin: 0px;"> <div class="selectableDiv" style="margin-top: 30px;">
<div class="allowedQualities"> <ol id="@selectable" class="selectableList">
<h4 class="sortableHeader">Allowed</h4>
<ul id="@sortable1" class="@connectedSortable sortable1"> @{var qualitiesList = (List<QualityTypes>)ViewData["Qualities"];}
@if (Model.Allowed != null)
@for (int i = 0; i < qualitiesList.Count(); i++)
{
if (Model.Allowed != null)
{ {
for (int i = 0; i < Model.Allowed.Count(); i++) if (Model.Allowed.Contains(qualitiesList[i]))
{ {
<li class="ui-state-default" id="@Model.Allowed[i].ToString()"> <li class="ui-widget-content ui-selected" id="@qualitiesList[i].ToString()">
@Html.RadioButtonFor(x => x.Cutoff, Model.Allowed[i]) @Html.Label(qualitiesList[i].ToString())
@Html.DisplayTextFor(c => c.Allowed[i])
</li> </li>
continue;
} }
} }
</ul>
</div>
<div class="otherQualities"> <li class="ui-widget-content" id="@qualitiesList[i].ToString()">
<h4 class="sortableHeader">Not-Allowed</h4> @Html.Label(qualitiesList[i].ToString())
<ul id="@sortable2" class="@connectedSortable sortable2"> </li>
}
@{var qualitiesList = (List<QualityTypes>)ViewData["Qualities"];} </ol>
@for (int i = 0; i < qualitiesList.Count(); i++)
{
//Skip Unknown and any item that is in the allowed list
//if (qualitiesList[i].ToString() == "Unknown")
//{
// continue;
//}
if (Model.Allowed != null)
{
if (Model.Allowed.Contains(qualitiesList[i]))
{
continue;
}
}
<li class="ui-state-default" id="@qualitiesList[i].ToString()">
@Html.RadioButtonFor(x => x.Cutoff, qualitiesList[i])
@Html.Label(qualitiesList[i].ToString())
</li>
}
</ul>
</div>
</div> </div>
@Html.ValidationMessageFor(x => x.Cutoff) <div class="hiddenProfileDetails2">
@Html.HiddenFor(x => x.QualityProfileId)
<div class="hiddenProfileDetails"> @Html.HiddenFor(x => x.UserProfile)
@Html.TextBoxFor(x => x.QualityProfileId, new { @style = "display:none" }) @Html.HiddenFor(m => m.AllowedString)
@Html.CheckBoxFor(x => x.UserProfile, new { @style = "display:none" })
@Html.TextBoxFor(m => m.AllowedString, new { @style = "display:none" })
</div> </div>
</fieldset> </fieldset>
</div> </div>

@ -1 +1,58 @@
Hello World Hello World
<input type="checkbox" id="id_chk1" class="chkbox" value="1" />Check 1<br/>
<input type="checkbox" id="id_chk2" class="chkbox" value="2" />Check 2<br/>
<input type="checkbox" id="id_chk3" class="chkbox" value="3" />Check 3<br/>
<input type="checkbox" id="id_chk4" class="chkbox" value="4" />Check 4<br/>
<input type="checkbox" id="id_chk5" class="chkbox" value="5" />Check 5<br/>
<input type="checkbox" id="id_chk6" class="chkbox" value="6" />Check 6<br/>
<input type="checkbox" id="id_chk7" class="chkbox" value="7" />Check 7<br/>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
var lastChecked = null;
$(document).ready(function () {
$('.chkbox').click(function (event) {
if (!lastChecked) {
lastChecked = this;
return;
}
if (event.shiftKey) {
var start = $('.chkbox').index(this);
var end = $('.chkbox').index(lastChecked);
for (i = Math.min(start, end); i <= Math.max(start, end); i++) {
$('.chkbox')[i].checked = lastChecked.checked;
}
}
lastChecked = this;
});
});
</script>
<style>
#selectable .ui-selecting { background: #85AEF9; }
#selectable .ui-selected { background: #065EFE; color: white; }
#selectable { list-style-type: none; margin: 0; padding: 0; width: 110px; }
#selectable li { margin: 3px; padding-left: 0.4em; padding-bottom: 1.5em; padding-top: 0em; font-size: 1.2em; height: 6px; }
</style>
<script type="text/javascript">
$(function () {
$("#selectable").selectable();
});
</script>
<ol id="selectable">
<li class="ui-widget-content">Unknown</li>
<li class="ui-widget-content">SDTV</li>
<li class="ui-widget-content">DVD</li>
<li class="ui-widget-content">HDTV</li>
<li class="ui-widget-content">WEBDL</li>
<li class="ui-widget-content">Bluray720p</li>
<li class="ui-widget-content">Bluray1080p</li>
</ol>
Loading…
Cancel
Save