--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-11-02 11:23:27 -07:00
32 changed files with 147 additions and 217 deletions

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Orchard.UI.Navigation;
using Orchard.UI;
namespace Orchard.Tests.UI.Navigation {
[TestFixture]
@@ -10,7 +10,7 @@ namespace Orchard.Tests.UI.Navigation {
[SetUp]
public void Init() {
_comparer = new PositionComparer();
_comparer = new FlatPositionComparer();
}
@@ -47,6 +47,22 @@ namespace Orchard.Tests.UI.Navigation {
AssertSame("007", "7");
}
[Test]
public void NegativeNumericValuesAreLessThanPositive() {
AssertLess("-5", "5");
AssertSame("-5", "-5");
AssertMore("42", "-42");
}
[Test]
public void NegativeNumericValuesShouldCompareNumerically() {
AssertMore("-3", "-5");
AssertLess("-8", "-5");
AssertSame("-5", "-5");
AssertLess("-100", "-5");
AssertSame("-007", "-7");
}
[Test]
public void DotsSplitParts() {
AssertLess("0500.3", "0500.5");

View File

@@ -21,14 +21,18 @@ namespace Orchard.Core.Contents {
public void GetNavigation(NavigationBuilder builder) {
var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name);
builder.Add(T("Content"), "2", menu => {
menu.Add(T("Manage Content"), "1", item => item.Action("List", "Admin", new { area = "Contents", id = "" }));
foreach (var contentTypeDefinition in contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable)) {
builder.Add(T("Content"), "2",
menu => menu.Add(T("Content Items"), "1", item => item.Action("List", "Admin", new {area = "Contents", id = ""})));
builder.Add(T("New"), "-1", menu => {
menu.Add(T("Content Item"), "1", item => item.Action("List", "Admin", new { area = "Contents", id = "" }));
foreach (var contentTypeDefinition in contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable).OrderBy(ctd => ctd.DisplayName)) {
var ci = _contentManager.New(contentTypeDefinition.Name);
var cim = _contentManager.GetItemMetadata(ci);
var createRouteValues = cim.CreateRouteValues;
// review: the display name should be a LocalizedString
if (createRouteValues.Any())
menu.Add(T("Create {0}", contentTypeDefinition.DisplayName), "1.3", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
menu.Add(T(contentTypeDefinition.DisplayName), "5", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
}
});
}

View File

@@ -8,8 +8,9 @@ namespace Orchard.Core.Dashboard {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Orchard"), "0",
menu => menu.Add(T("Dashboard"), "0", item => item.Action("Index", "Admin", new { area = "Dashboard" }).Permission(StandardPermissions.AccessAdminPanel)));
builder.Add(T("Dashboard"), "0",
menu => menu.Add(T("Orchard"), "0", item => item.Action("Index", "Admin", new { area = "Dashboard" })
.Permission(StandardPermissions.AccessAdminPanel)));
}
}
}

View File

@@ -9,8 +9,8 @@ namespace Orchard.Core.Navigation {
public void GetNavigation(NavigationBuilder builder) {
//todo: - add new menu? and list menus? ...and remove hard-coded menu name here
builder.Add(T("Navigation"), "8",
menu => menu
.Add(T("Main Menu"), "6.0", item => item.Action("Index", "Admin", new { area = "Navigation" }).Permission(Permissions.ManageMainMenu)));
menu => menu.Add(T("Main Menu"), "0", item => item.Action("Index", "Admin", new { area = "Navigation" })
.Permission(Permissions.ManageMainMenu)));
}
}
}

View File

@@ -8,6 +8,7 @@ using Orchard.Core.Navigation.ViewModels;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc.AntiForgery;
using Orchard.UI;
using Orchard.UI.Navigation;
using Orchard.Utility;
@@ -41,7 +42,7 @@ namespace Orchard.Core.Navigation.Controllers {
model = new NavigationManagementViewModel();
if (model.MenuItemEntries == null || model.MenuItemEntries.Count() < 1)
model.MenuItemEntries = _menuService.Get().Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.MenuItem.Position, new PositionComparer()).ToList();
model.MenuItemEntries = _menuService.Get().Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.MenuItem.Position, new FlatPositionComparer()).ToList();
// need action name as this action is referenced from another action
return View("Index", model);

View File

@@ -8,8 +8,9 @@ namespace Orchard.Core.Reports {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu.Add(T("Reports"), "15", item => item.Action("Index", "Admin", new { area = "Reports" }).Permission(StandardPermissions.AccessAdminPanel)));
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Reports"), "20", item => item.Action("Index", "Admin", new { area = "Reports" })
.Permission(StandardPermissions.AccessAdminPanel)));
}
}
}

View File

@@ -7,9 +7,9 @@ namespace Orchard.Core.Settings {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu
.Add(T("Settings"), "10", item => item.Action("Index", "Admin", new { area = "Settings" }).Permission(Permissions.ManageSettings)));
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Settings"), "10", item => item.Action("Index", "Admin", new { area = "Settings" })
.Permission(Permissions.ManageSettings)));
}
}
}

View File

@@ -16,7 +16,7 @@ namespace Orchard.Blogs {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Blogs"), "1", BuildMenu);
builder.Add(T("Blogs"), "2.5", BuildMenu);
}
private void BuildMenu(NavigationItemBuilder menu) {
@@ -24,14 +24,13 @@ namespace Orchard.Blogs {
var blogCount = blogs.Count();
var singleBlog = blogCount == 1 ? blogs.ElementAt(0) : null;
if (blogCount > 0 && singleBlog == null)
menu.Add(T("Manage Blogs"), "1.0",
item =>
item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs));
if (blogCount > 0 && singleBlog == null) {
menu.Add(T("List"), "3",
item => item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs));
}
else if (singleBlog != null)
menu.Add(T("Manage Blog"), "1.0",
item =>
item.Action("Item", "BlogAdmin", new {area = "Orchard.Blogs", blogSlug = singleBlog.Slug}).Permission(Permissions.MetaListBlogs));
item => item.Action("Item", "BlogAdmin", new { area = "Orchard.Blogs", blogSlug = singleBlog.Slug }).Permission(Permissions.MetaListBlogs));
if (singleBlog != null)
menu.Add(T("Create New Post"), "1.1",

View File

@@ -8,10 +8,9 @@ namespace Orchard.Comments {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Comments"), "3",
menu => menu
.Add(T("Manage Comments"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" }).Permission(Permissions.ManageComments))
);
builder.Add(T("Comments"), "10",
menu => menu.Add(T("List"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" })
.Permission(Permissions.ManageComments)));
}
}
}

View File

@@ -10,7 +10,7 @@ namespace Orchard.ContentTypes {
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Content"), "2",
menu => menu.Add(T("Manage Content Types"), "1.1", item => item.Action("Index", "Admin", new { area = "Orchard.ContentTypes" })));
menu => menu.Add(T("Content Types"), "3", item => item.Action("Index", "Admin", new {area = "Orchard.ContentTypes"})));
}
}
}

View File

@@ -8,10 +8,8 @@ namespace Orchard.Experimental {
public Localizer T { get; set; }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu
.Add(T("Experimental"), "10.0", item => item.Action("Index", "Home", new { area = "Orchard.Experimental" })
));
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Experimental"), "50", item => item.Action("Index", "Home", new { area = "Orchard.Experimental" })));
}
}
}

View File

@@ -7,9 +7,8 @@ namespace Orchard.Indexing {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu
.Add(T("Search Index"), "10.0", item => item.Action("Index", "Admin", new {area = "Orchard.Indexing"})
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Search Index"), "15", item => item.Action("Index", "Admin", new {area = "Orchard.Indexing"})
.Permission(Permissions.ManageSearchIndex)));
}
}

View File

@@ -8,10 +8,9 @@ namespace Orchard.Media {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Media"), "4",
menu => menu
.Add(T("Manage Media"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" }).Permission(Permissions.ManageMediaFiles))
);
builder.Add(T("Media"), "6",
menu => menu.Add(T("Media"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" })
.Permission(Permissions.ManageMediaFiles)));
}
}
}

View File

@@ -7,9 +7,8 @@ namespace Orchard.Migrations {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Developer"), "10",
menu => menu
.Add(T("Migration"), "1.0", item => item.Action("Index", "DatabaseUpdate", new { area = "Orchard.Migrations" })));
builder.Add(T("Developer"), "1",
menu => menu.Add(T("Migration"), "1.0", item => item.Action("Index", "DatabaseUpdate", new { area = "Orchard.Migrations" })));
}
}
}

View File

@@ -8,11 +8,11 @@ namespace Orchard.Modules {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
builder.Add(T("Configuration"), "50",
menu => menu
.Add(T("Features"), "5.0", item => item.Action("Features", "Admin", new { area = "Orchard.Modules" })
.Add(T("Features"), "0", item => item.Action("Features", "Admin", new { area = "Orchard.Modules" })
.Permission(Permissions.ManageFeatures))
.Add(T("Modules"), "5.1", item => item.Action("Index", "Admin", new { area = "Orchard.Modules" })
.Add(T("Modules"), "5", item => item.Action("Index", "Admin", new { area = "Orchard.Modules" })
.Permission(Permissions.ManageModules)));
}
}

View File

@@ -18,10 +18,9 @@ namespace Orchard.MultiTenancy {
if ( _shellSettings.Name != "Default" )
return;
builder.Add(T("Tenants"), "22",
menu => menu
.Add(T("Manage Tenants"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.MultiTenancy" }).Permission(Permissions.ManageTenants))
.Add(T("Add New Tenant"), "1.1", item => item.Action("Add", "Admin", new { area = "Orchard.MultiTenancy" }).Permission(Permissions.ManageTenants)));
builder.Add(T("Tenants"), "100",
menu => menu.Add(T("List"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.MultiTenancy" })
.Permission(Permissions.ManageTenants)));
}
}
}

View File

@@ -10,12 +10,12 @@ namespace Orchard.Packaging {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Gallery"), "5", menu => menu
.Add(T("Browse Modules"), "1.0", item => item
builder.Add(T("Gallery"), "30", menu => menu
.Add(T("Modules"), "1.0", item => item
.Action("ModulesIndex", "Gallery", new { area = "Orchard.Packaging" }))
.Add(T("Browse Themes"), "2.0", item => item
.Add(T("Themes"), "2.0", item => item
.Action("ThemesIndex", "Gallery", new { area = "Orchard.Packaging" }))
.Add(T("Gallery Feeds"), "3.0", item => item
.Add(T("Feeds"), "3.0", item => item
.Action("Sources", "Gallery", new { area = "Orchard.Packaging" })));
}
}

View File

@@ -7,9 +7,9 @@ namespace Orchard.Roles {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Users"), "9",
menu => menu
.Add(T("Manage Roles"), "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Roles" }).Permission(Permissions.ManageRoles)));
builder.Add(T("Users"), "40",
menu => menu.Add(T("Roles"), "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Roles" })
.Permission(Permissions.ManageRoles)));
}
}
}

View File

@@ -7,10 +7,9 @@ namespace Orchard.Tags {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Tags"), "3",
menu => menu
.Add(T("Manage Tags"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Tags" }).Permission(Permissions.ManageTags))
);
builder.Add(T("Tags"), "20",
menu => menu.Add(T("List"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.Tags" })
.Permission(Permissions.ManageTags)));
}
}
}

View File

@@ -7,10 +7,10 @@ namespace Orchard.Themes {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Design"), "10",
menu => menu
.Add(T("Themes"), "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Themes" })
.Permission(Permissions.ManageThemes).Permission(Permissions.ApplyTheme)));
builder.Add(T("Themes"), "25",
menu => menu.Add(T("List"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.Themes" })
.Permission(Permissions.ManageThemes)
.Permission(Permissions.ApplyTheme)));
}
}
}

View File

@@ -7,9 +7,9 @@ namespace Orchard.Users {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Users"), "9",
menu => menu
.Add(T("Manage Users"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Users" }).Permission(Permissions.ManageUsers)));
builder.Add(T("Users"), "40",
menu => menu.Add(T("Users"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Users" })
.Permission(Permissions.ManageUsers)));
}
}
}

View File

@@ -1,7 +1,12 @@
@model Orchard.Users.ViewModels.LogOnViewModel
@using Orchard.ContentManagement;
@{
var userCanRegister = @WorkContext.CurrentSite.As<Orchard.Users.Models.RegistrationSettingsPart>().UsersCanRegister;
}
<h1 class="page-title">@Html.TitleForPage(Model.Title)</h1>
<p>@T("Please enter your username and password.") @Html.ActionLink("Register", "Register") @T(" if you don't have an account.")</p>
<p>@T("Please enter your username and password.") @if(userCanRegister) { <text> </text> @Html.ActionLink("Register", "Register") @T(" if you don't have an account.") }</p>
@Html.ValidationSummary(T("Login was unsuccessful. Please correct the errors and try again.").ToString())
@using (Html.BeginFormAntiForgeryPost(Url.Action("LogOn", new {ReturnUrl = Request.QueryString["ReturnUrl"]}))) {

View File

@@ -7,9 +7,9 @@ namespace Orchard.Widgets {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Widgets"), "10",
menu => menu
.Add(T("Manage Widgets"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Widgets" }).Permission(Permissions.ManageWidgets)));
builder.Add(T("Widgets"), "4",
menu => menu.Add(T("Configure"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.Widgets" })
.Permission(Permissions.ManageWidgets)));
}
}
}

View File

@@ -116,7 +116,7 @@ number of columns: 24; actual width: 946; column width: 26; gutter width:14
float:right;
width:83.08%;
}
#navigation {
#menu .menu-admin {
display:inline;
float:left;
width:15.401%;
@@ -238,20 +238,20 @@ form.link button:hover {
overflow:hidden;
width:0;
}
#navigation li {
#menu .menu-admin li {
margin:5px 0 17px 4px;
}
#navigation ul li {
#menu .menu-admin ul li {
border:0;
margin:0;
}
#navigation li h3 {
#menu .menu-admin li h3 {
padding:0 0 0 8px;
}
#navigation li h3 a, #navigation li h3 span {
#menu .menu-admin li h3 a, #menu .menu-admin li h3 span {
line-height:1.2em;
}
#navigation ul a, #navigation ul a:link, #navigation ul a:visited {
#menu .menu-admin ul a, #menu .menu-admin ul a:link, #menu .menu-admin ul a:visited {
color:#2d2f25;
display:block;
font-size:1.4em;
@@ -259,7 +259,7 @@ form.link button:hover {
padding:.4em 0 .4em 12px;
text-decoration:none;
}
#navigation ul a:hover, #navigation ul a:active, #navigation ul a:focus {
#menu .menu-admin ul a:hover, #menu .menu-admin ul a:active, #menu .menu-admin ul a:focus {
background:#f5f5f5;
color: #000;
text-decoration:underline;

View File

@@ -1,17 +1,24 @@
@using System.Web.Routing;
@using Orchard.Utility.Extensions;
@{
Script.Require("jQuery");
Script.Include("admin.js");
IEnumerable<dynamic> firstLevelMenuItems = Model;
Model.Attributes.Add("role", "navigation");
var tag = Tag(Model, "ul");
}
<ul id="navigation" role="navigation">
@tag.StartElement
@foreach(var firstLevelMenuItem in Model) {
IEnumerable<dynamic> secondLevelMenuItems = firstLevelMenuItem;
string sectionHeaderText = firstLevelMenuItem.Text;
var firstOfTheSecond = secondLevelMenuItems.FirstOrDefault();
var sectionHeaderMarkup = firstOfTheSecond != null
? Html.ActionLink((string)firstLevelMenuItem.Text, (string)firstOfTheSecond.RouteValues["action"], (RouteValueDictionary)firstOfTheSecond.RouteValues)
: new HtmlString(string.Format("<span>{0}</span>", Html.Encode(firstLevelMenuItem.Text)));
var sectionHeaderMarkup = firstLevelMenuItem.RouteValues != null || HasText(firstLevelMenuItem.Url)
? Html.Link(sectionHeaderText, (string)firstLevelMenuItem.Href)
: firstOfTheSecond != null
? Html.Link(sectionHeaderText, (string)firstOfTheSecond.Href)
: new HtmlString(string.Format("<span>{0}</span>", Html.Encode(sectionHeaderText)));
if (firstLevelMenuItem == firstLevelMenuItems.First()) {
firstLevelMenuItem.Classes.Add("first");
@@ -20,9 +27,11 @@
firstLevelMenuItem.Classes.Add("last");
}
firstLevelMenuItem.Classes.Add("section-" + sectionHeaderText.HtmlClassify());
var firstLevelTag = Tag(firstLevelMenuItem, "li");
@firstLevelTag.StartElement
<h3>@sectionHeaderMarkup</h3>
if (secondLevelMenuItems.Count() > 1) {
<ul class="menuItems">
@foreach(var secondLevelMenuItem in secondLevelMenuItems) {
<li>
@@ -30,14 +39,15 @@
</li>
}
</ul>
}
@firstLevelTag.EndElement
}
</ul>
@tag.EndElement
@using(Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
(function ($) {
$("#navigation h3").expandoControl(function(controller) { return controller.next(); }, { key: "N42", path: "@Url.Content("~/")" });
$("@string.Format(".{0} h3", string.Join(".", Model.Classes))").expandoControl(function(controller) { return controller.next(); }, { key: "N42", path: "@Url.Content("~/")" });
})(jQuery);
//]]>
</script>

View File

@@ -43,7 +43,7 @@ namespace Orchard.Mvc.Html {
return null;
return html.ActionLink(
NonNullOrEmpty(linkText, metadata.DisplayText, "edit"),
NonNullOrEmpty(linkText, metadata.DisplayText, content.ContentItem.TypeDefinition.DisplayName),
Convert.ToString(metadata.EditorRouteValues["action"]),
metadata.EditorRouteValues.Merge(additionalRouteValues));
}

View File

@@ -3,7 +3,7 @@ using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using Orchard.ContentManagement.ViewModels;
using Orchard.UI.Navigation;
using Orchard.UI;
namespace Orchard.Mvc.Html {
public static class TemplateViewModelExtensions {
@@ -11,7 +11,7 @@ namespace Orchard.Mvc.Html {
if (templates == null)
return;
foreach (var template in templates.OrderByDescending(t => t.Position, new PositionComparer())) {
foreach (var template in templates.OrderByDescending(t => t.Position, new FlatPositionComparer())) {
html.RenderTemplates(template);
}
}

View File

@@ -791,7 +791,6 @@
<Compile Include="UI\Navigation\MenuItem.cs" />
<Compile Include="UI\Navigation\MenuItemComparer.cs" />
<Compile Include="UI\Navigation\NavigationManager.cs" />
<Compile Include="UI\Navigation\PositionComparer.cs" />
<Compile Include="UI\Notify\Notifier.cs" />
<Compile Include="UI\Notify\NotifierExtensions.cs" />
<Compile Include="UI\Notify\NotifyEntry.cs" />

View File

@@ -8,27 +8,33 @@ namespace Orchard.UI {
if (x == y)
return 0;
// "" == "5"
x = string.IsNullOrWhiteSpace(x) ? "5" : x.TrimStart(':'); // ':' is _sometimes_ used as a partition identifier
y = string.IsNullOrWhiteSpace(y) ? "5" : y.TrimStart(':');
// null == "before; "" == "0"
x = x == null
? "before"
: x.Trim() == "" ? "0" : x.Trim(':').TrimEnd('.'); // ':' is _sometimes_ used as a partition identifier
y = y == null
? "before"
: y.Trim() == "" ? "0" : y.Trim(':').TrimEnd('.');
var xParts = x.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
var yParts = y.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
var xParts = x.Split(new[] { '.', ':' });
var yParts = y.Split(new[] { '.', ':' });
for (var i = 0; i < xParts.Count(); i++) {
if (yParts.Length < i+1) // x is further defined meaning it comes after y (e.g. x == 1.2.3 and y == 1.2)
return 1;
int xPos;
int yPos;
var xPart = string.IsNullOrWhiteSpace(xParts[i]) ? "before" : xParts[i];
var yPart = string.IsNullOrWhiteSpace(yParts[i]) ? "before" : yParts[i];
xParts[i] = NormalizeKnownPartitions(xParts[i]);
yParts[i] = NormalizeKnownPartitions(yParts[i]);
xPart = NormalizeKnownPartitions(xPart);
yPart = NormalizeKnownPartitions(yPart);
var xIsInt = int.TryParse(xParts[i], out xPos);
var yIsInt = int.TryParse(yParts[i], out yPos);
var xIsInt = int.TryParse(xPart, out xPos);
var yIsInt = int.TryParse(yPart, out yPos);
if (!xIsInt && !yIsInt)
return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
return string.Compare(string.Join(".", xParts), string.Join(".", yParts), StringComparison.OrdinalIgnoreCase);
if (!xIsInt || (yIsInt && xPos > yPos)) // non-int after int or greater x pos than y pos (which is an int)
return 1;
if (!yIsInt || xPos < yPos)

View File

@@ -92,7 +92,7 @@ namespace Orchard.UI.Navigation {
private static IEnumerable<MenuItem> Merge(IEnumerable<IEnumerable<MenuItem>> sources) {
var comparer = new MenuItemComparer();
var orderer = new PositionComparer();
var orderer = new FlatPositionComparer();
return sources.SelectMany(x => x).ToArray()
.GroupBy(key => key, (key, items) => Join(items), comparer)
@@ -116,7 +116,7 @@ namespace Orchard.UI.Navigation {
}
private static string SelectBestPositionValue(IEnumerable<string> positions) {
var comparer = new PositionComparer();
var comparer = new FlatPositionComparer();
return positions.Aggregate(string.Empty,
(agg, pos) =>
string.IsNullOrEmpty(agg)

View File

@@ -1,105 +0,0 @@
using System;
using System.Collections.Generic;
namespace Orchard.UI.Navigation {
public class PositionComparer : IComparer<string> {
public int Compare(string x, string y) {
if (x == null || y == null) {
return x == null && y == null ? 0 : (x == null ? -1 : 1);
}
if (x == "" || y == "") {
return x == "" && y == "" ? 0 : (x == "" ? -1 : 1);
}
var xRange = new Range { Length = x.Length };
var yRange = new Range { Length = y.Length };
while (xRange.Start != xRange.Length || yRange.Start != yRange.Length) {
var xSize = xRange.NextDot(x);
var ySize = yRange.NextDot(y);
if (xSize == 0 || ySize == 0) {
// one or both sides are empty
if (xSize != 0 || ySize != 0) {
// favor the side that's not empty
return xSize - ySize;
}
// otherwise continue to the next segment if both are
}
else if (xRange.NumericValue != -1 && yRange.NumericValue != -1) {
// two strictly numeric values
// return the difference
var diff = xRange.NumericValue - yRange.NumericValue;
if (diff != 0)
return diff;
// or continue to next segment
}
else {
if (xRange.NumericValue != -1) {
// left-side only has numeric value, right-side explicitly greater
return -1;
}
if (yRange.NumericValue != -1) {
// right-side only has numeric value, left-side explicitly greater
return 1;
}
// two strictly non-numeric
var diff = string.Compare(x, xRange.Start, y, yRange.Start, Math.Min(xSize, ySize),
StringComparison.OrdinalIgnoreCase);
if (diff != 0)
return diff;
if (xSize != ySize)
return xSize - ySize;
}
xRange.Advance();
yRange.Advance();
}
return 0;
}
struct Range {
public int Start { get; private set; }
private int End { get; set; }
public int Length { get; set; }
public int NumericValue { get; private set; }
public int NextDot(string value) {
if (Start == -1) {
End = -1;
return 0;
}
End = value.IndexOf('.', Start);
int numeric;
NumericValue = int.TryParse(Segment(value), out numeric) ? numeric : -1;
return End == -1 ? Length - Start : End - Start;
}
private string Segment(string value) {
if (Start == 0 && End == -1) {
return value;
}
if (End == -1) {
return value.Substring(Start);
}
return value.Substring(Start, End - Start);
}
public void Advance() {
if (End == -1)
Start = Length;
else
Start = End + 1;
}
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.UI;
using Orchard.UI.Navigation;
namespace Orchard.Utility {
@@ -9,7 +10,7 @@ namespace Orchard.Utility {
var topMenuItem = menuItems.FirstOrDefault();
if (topMenuItem != null) {
var maxMenuItem = topMenuItem.Items.Where(PositionHasMojorNumber).OrderByDescending(mi => mi.Position, new PositionComparer()).FirstOrDefault();
var maxMenuItem = topMenuItem.Items.Where(PositionHasMojorNumber).OrderByDescending(mi => mi.Position, new FlatPositionComparer()).FirstOrDefault();
var positionParts = maxMenuItem.Position.Split(new[] {'.'}, StringSplitOptions.RemoveEmptyEntries).Where(s => s.Trim() != "");
if (positionParts.Count() > 0) {
int result;