parent
be6bdbc483
commit
6d790f8939
@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Web.Mvc;
|
||||
using System.Web;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Web.Helpers
|
||||
{
|
||||
public static class HtmlPrefixScopeExtensions
|
||||
{
|
||||
private const string idsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_";
|
||||
|
||||
public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName)
|
||||
{
|
||||
var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
|
||||
string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();
|
||||
|
||||
// autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync.
|
||||
html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, itemIndex));
|
||||
|
||||
return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
|
||||
}
|
||||
|
||||
public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix)
|
||||
{
|
||||
return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
|
||||
}
|
||||
|
||||
private static Queue<string> GetIdsToReuse(HttpContextBase httpContext, string collectionName)
|
||||
{
|
||||
// We need to use the same sequence of IDs following a server-side validation failure,
|
||||
// otherwise the framework won't render the validation error messages next to each item.
|
||||
string key = idsToReuseKey + collectionName;
|
||||
var queue = (Queue<string>)httpContext.Items[key];
|
||||
if (queue == null) {
|
||||
httpContext.Items[key] = queue = new Queue<string>();
|
||||
var previouslyUsedIds = httpContext.Request[collectionName + ".index"];
|
||||
if (!string.IsNullOrEmpty(previouslyUsedIds))
|
||||
foreach (string previouslyUsedId in previouslyUsedIds.Split(','))
|
||||
queue.Enqueue(previouslyUsedId);
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
private class HtmlFieldPrefixScope : IDisposable
|
||||
{
|
||||
private readonly TemplateInfo templateInfo;
|
||||
private readonly string previousHtmlFieldPrefix;
|
||||
|
||||
public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
|
||||
{
|
||||
this.templateInfo = templateInfo;
|
||||
|
||||
previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
|
||||
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,87 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NzbDrone.Core.Repository.Quality.QualityProfile>" %>
|
||||
<%@ Import Namespace="NzbDrone.Web.Helpers" %>
|
||||
<%@ Import Namespace="NzbDrone.Core.Repository.Quality" %>
|
||||
|
||||
<% using (Html.BeginCollectionItem("UserProfiles"))
|
||||
{ %>
|
||||
|
||||
<style type="text/css">
|
||||
#sortable1, #sortable2 { list-style-type: none; margin: 0; padding: 0; float: left; margin-right: 10px; background: #eee; padding: 5px; width: 143px;}
|
||||
#sortable1 li, #sortable2 li { margin: 5px; padding: 5px; font-size: 1.2em; width: 120px; }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$("#sortable1, #sortable2").sortable({
|
||||
connectWith: ".connectedSortable",
|
||||
placeholder: "ui-state-highlight",
|
||||
dropOnEmpty: true,
|
||||
update: function (event, ui) {
|
||||
|
||||
var order = $('#sortable1').sortable("toArray");
|
||||
$("#allowedString").val(order);
|
||||
}
|
||||
}).disableSelection();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="userProfileSectionEditor">
|
||||
|
||||
<fieldset>
|
||||
|
||||
<%= Html.TextBoxFor(m => m.AllowedString, new { @id = "allowedString", @style = "display:none" })%>
|
||||
<%--<%= Html.TextBoxFor(m => m.AllowedString, new { @id = "allowedString" })%>--%>
|
||||
|
||||
<label><%= Model.Name %></label>
|
||||
<div class="removeDiv"><a href="#" class="deleteRow">Remove</a></div>
|
||||
|
||||
<div class="editor-label">
|
||||
<%= Html.LabelFor(m => m.Name) %>
|
||||
<%= Html.LabelFor(x => x.Name)%>
|
||||
</div>
|
||||
<div class="editor-field">
|
||||
<%: Html.TextBoxFor(m => m.Name)%>
|
||||
<%= Html.ValidationMessageFor(m => m.Name)%>
|
||||
<%= Html.TextBoxFor(x => x.Name) %>
|
||||
<%= Html.ValidationMessageFor(x => x.Name)%>
|
||||
</div>
|
||||
|
||||
<div class="hiddenProfileDetails">
|
||||
<%= Html.TextBoxFor(x => x.ProfileId, new { @style = "display:none" })%>
|
||||
<%= Html.CheckBoxFor(x => x.UserProfile, new { @style = "display:none" })%>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div class="allowedQualities">
|
||||
<ul id="sortable1" class="connectedSortable" title="Allowed">
|
||||
<%for (int i = 0; i < Model.Allowed.Count(); i++){%>
|
||||
<li class="ui-state-default" id="<%= Model.Allowed[i].ToString() %>">
|
||||
<%= Html.DisplayTextFor(c => c.Allowed[i]) %>
|
||||
</li>
|
||||
<%}%>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="otherQualities">
|
||||
<ul id="sortable2" class="connectedSortable">
|
||||
<% var qualitiesList = (List<QualityTypes>) ViewData["Qualities"]; %>
|
||||
|
||||
<%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.Contains(qualitiesList[i]))
|
||||
continue;
|
||||
%>
|
||||
|
||||
<li class="ui-state-default" id="<%= qualitiesList[i].ToString() %>">
|
||||
<%= Html.Label(qualitiesList[i].ToString()) %>
|
||||
<%--<%= Html.RenderPartial("ProfileAllowedQualities", Model.Allowed[i]) %>--%>
|
||||
</li>
|
||||
|
||||
<% } %>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<% } %>
|
Loading…
Reference in new issue