mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Compare commits
62 Commits
issue/5848
...
lucene48
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63be17f440 | ||
|
|
06ee7849c1 | ||
|
|
61c91ff858 | ||
|
|
92cbf8925b | ||
|
|
c8b7c64d93 | ||
|
|
9572ef9ad3 | ||
|
|
388932b41f | ||
|
|
829f69198c | ||
|
|
4648a252b9 | ||
|
|
219f29cd20 | ||
|
|
51003bf582 | ||
|
|
0d5cff66a9 | ||
|
|
7e66c98dd5 | ||
|
|
14c2ee7944 | ||
|
|
9ae372a920 | ||
|
|
eecb61a132 | ||
|
|
4574a9fb0b | ||
|
|
bec9a6d792 | ||
|
|
dbe89d0a82 | ||
|
|
255547288b | ||
|
|
a9abc294e3 | ||
|
|
101d61b808 | ||
|
|
054925c297 | ||
|
|
ff97d1e975 | ||
|
|
e26fee3d6c | ||
|
|
ec0ea5e321 | ||
|
|
dd9d67fe48 | ||
|
|
9105187f78 | ||
|
|
1da6066e83 | ||
|
|
52c6debc97 | ||
|
|
f3be4fa2c7 | ||
|
|
d64541d47a | ||
|
|
9714c2c5f0 | ||
|
|
855d183be3 | ||
|
|
a37e548b25 | ||
|
|
99695f07cc | ||
|
|
63ca6ee2d8 | ||
|
|
042c47cc3f | ||
|
|
49ab41d4dc | ||
|
|
7fb63fd9eb | ||
|
|
e853550bda | ||
|
|
24c68bebe4 | ||
|
|
0a82363187 | ||
|
|
1e87eee2e4 | ||
|
|
53244d702c | ||
|
|
07cc3a6bad | ||
|
|
6f4762a30c | ||
|
|
ce3179307d | ||
|
|
2620dc820d | ||
|
|
9c88c7fcd1 | ||
|
|
a01b7dde23 | ||
|
|
65ae99abd4 | ||
|
|
59d95f11ee | ||
|
|
c7fde5bc72 | ||
|
|
d080037af9 | ||
|
|
5a6ba5ddd6 | ||
|
|
658a5601a5 | ||
|
|
d958df3041 | ||
|
|
8690278bed | ||
|
|
a28b966685 | ||
|
|
3656e5e466 | ||
|
|
2b61e3368d |
28
README.md
28
README.md
@@ -1,6 +1,13 @@
|
||||
# Orchard
|
||||
|
||||
Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
|
||||
|
||||
[](https://gitter.im/OrchardCMS/Orchard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
You can try it for free on [DotNest.com](https://dotnest.com) or on Microsoft Azure by clicking on this button
|
||||
|
||||
[](https://ms.portal.azure.com/#create/OutercurveFoundation.OrchardCMS.0.5.9)
|
||||
|
||||
## About The Orchard Project
|
||||
|
||||
#### Please visit our website at http://orchardproject.net for the most current information about this project.
|
||||
@@ -13,26 +20,29 @@ Orchard is delivered under the [.NET Foundation](http://www.dotnetfoundation.org
|
||||
|
||||
Our mission is to empower our users and foster a dedicated and diverse community that builds the CMS that we all want to use.
|
||||
|
||||
There are many ways you can [contribute to Orchard](http://orchardproject.net/contribution): you can [fix bugs](https://github.com/OrchardCMS/Orchard/issues), contribute modules and themes to [our gallery](http://gallery.orchardproject.net/), [write documentation](https://github.com/OrchardCMS/OrchardDoc), [translate Orchard](http://orchardproject.net/localize), or answer questions [on our forums](http://orchard.codeplex.com/discussions) and [on Stack Overflow](http://stackoverflow.com/questions/tagged/orchardcms).
|
||||
|
||||
## Project Status
|
||||
Orchard is currently in version 1.9.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach.
|
||||
Our 1.9.1 release is available from our Downloads page, and is easy to [Install Orchard using the Web Platform Installer](http://www.orchardproject.net/docs/Installing-Orchard.ashx). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project.
|
||||
Orchard is currently in version 1.9.2. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach.
|
||||
Our 1.9.2 release is available from our Downloads page, and is easy to [Install Orchard using the Web Platform Installer](http://docs.orchardproject.net/Documentation/Installing-Orchard). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project.
|
||||
|
||||
* [Download the latest release](https://github.com/OrchardCMS/Orchard/releases)
|
||||
* [Feature roadmap](http://www.orchardproject.net/docs/feature-roadmap.ashx)
|
||||
* [Feature roadmap](http://docs.orchardproject.net/Documentation/feature-roadmap)
|
||||
* [Docs and designs/specs](http://www.orchardproject.net/docs)
|
||||
* [About us](http://www.orchardproject.net/about)
|
||||
* [Contact us](mailto:ofeedbk@microsoft.com)
|
||||
|
||||
## How To Get Involved
|
||||
We hope that by engaging with the community in the very early stages of the project that we will be able to shape Orchard into a valuable set of tools and applications for the community. The Orchard team is committed to open community participation and accepts code contributions today. We encourage community participation at all levels from general project feedback to bug fixes and patches.
|
||||
We hope that by engaging with the community we will continue to shape Orchard into a valuable set of tools and applications. The Orchard team is committed to open community participation and accepts code contributions. We encourage community participation at all levels from general project feedback to bug fixes and patches.
|
||||
|
||||
There are many ways you can [contribute to Orchard](http://orchardproject.net/contribution):
|
||||
|
||||
* [Check out the code](https://github.com/OrchardCMS/Orchard)
|
||||
* [Check out the docs](http://orchardproject.net/docs)
|
||||
* [Write documentation](https://github.com/OrchardCMS/OrchardDoc)
|
||||
* [Find and file a bug](https://github.com/OrchardCMS/Orchard/issues)
|
||||
* [Propose a feature idea](http://orchard.uservoice.com)
|
||||
* [Ask and answer questions](http://www.orchardproject.net/discussions)
|
||||
* [Ask and answer questions in our forums](http://www.orchardproject.net/discussions) and [on Stack Overflow](http://stackoverflow.com/questions/tagged/orchardcms)
|
||||
* [Participate in our gitter.im chatroom](https://gitter.im/OrchardCMS/Orchard)
|
||||
* [Participate in forum discussions](http://orchard.codeplex.com/discussions)
|
||||
* [Submit a patch](http://www.orchardproject.net/docs/Contributing-patches.ashx)
|
||||
* [Submit a pull request](http://docs.orchardproject.net/Documentation/Contributing-patches)
|
||||
* [Translate Orchard](http://orchardproject.net/localize)
|
||||
* [Contribute modules and themes to our gallery](http://gallery.orchardproject.net/)
|
||||
* [Send us feedback](mailto:ofeedbk@microsoft.com)
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
This is a modified version including a [assembly: SecutiryTransparent] attribute in AssemblyInfo.cs
|
||||
@@ -23,19 +23,20 @@
|
||||
|
||||
<!-- Prompts for the database name and fills it into the database scripts -->
|
||||
<parameter name="Database Name" description="Name of the database for Orchard." defaultValue="orchard" tags="SQL, dbName">
|
||||
<parameterEntry type="TextFile" scope="install.sql" match="PlaceHolderForDb" />
|
||||
|
||||
</parameter>
|
||||
|
||||
<!-- Prompts for the database username and fills it into the database scripts.
|
||||
The SQL tag indicates it is a parameter required for SQL, the DbUsername tag indicates this is a Db username -->
|
||||
<parameter name="Database Username" description="User name to access you application database." defaultValue="orcharduser" tags="SQL, DbUsername">
|
||||
<parameterEntry type="TextFile" scope="install.sql" match="PlaceHolderForUser" />
|
||||
<parameterEntry type="TextFile" scope="createuser.sql" match="PlaceHolderForUser" />
|
||||
<parameterEntry type="TextFile" scope="createlogin.sql" match="PlaceHolderForUser" />
|
||||
</parameter>
|
||||
|
||||
<!-- Prompts for the database password and fills it into the database scripts.
|
||||
The SQL tag indicates it is a parameter required for SQL, the DbUserPassword tag indicates this is a Db password -->
|
||||
<parameter name="Database Password" description="Password for the Database Username." tags="New, Password, SQL, DbUserPassword">
|
||||
<parameterEntry type="TextFile" scope="install.sql" match="PlaceHolderForPassword" />
|
||||
<parameterEntry type="TextFile" scope="createlogin.sql" match="PlaceHolderForPassword" />
|
||||
</parameter>
|
||||
|
||||
<!-- Prompts for the admin creds and uses it for the administrator connection string. This is used to create a login and assign permissions.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -561,6 +561,23 @@
|
||||
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
|
||||
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
|
||||
</Target>
|
||||
<Target Name="DeleteDebugFiles" AfterTargets="AfterBuild">
|
||||
<RemoveDir Directories="Themes;Core;Modules" />
|
||||
</Target>
|
||||
<Target Name="CopyDebugFiles" AfterTargets="DeleteDebugFiles" Condition="'$(Configuration)' == 'Debug'">
|
||||
<PropertyGroup>
|
||||
<SrcFolder>..\..</SrcFolder>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Excluded Include="$(SrcFolder)\**\bin\**\*;$(SrcFolder)\**\obj\**\*;$(SrcFolder)\**\*.user;$(SrcFolder)\**\*.cs;$(SrcFolder)\**\*.csproj;$(SrcFolder)\**\.hg\**\*" />
|
||||
<Src-Themes Include="$(SrcFolder)\Orchard.Web\Themes\**\*" Exclude="@(Excluded)" />
|
||||
<Src-Core Include="$(SrcFolder)\Orchard.Web\Core\**\*" Exclude="@(Excluded)" />
|
||||
<Src-Modules Include="$(SrcFolder)\Orchard.Web\Modules\**\*" Exclude="@(Excluded)" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(Src-Themes)" DestinationFolder="Themes\%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(Src-Core)" DestinationFolder="Core\%(RecursiveDir)" />
|
||||
<Copy SourceFiles="@(Src-Modules)" DestinationFolder="Modules\%(RecursiveDir)" />
|
||||
</Target>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
@@ -580,6 +597,11 @@
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>del "$(TargetDir)\Modules"
|
||||
del "$(TargetDir)\Themes"
|
||||
del "$(TargetDir)\Media"</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
_menuService = menuService;
|
||||
_menuManager = menuManager;
|
||||
_navigationManager = navigationManager;
|
||||
|
||||
Services = orchardServices;
|
||||
T = NullLocalizer.Instance;
|
||||
Logger = NullLogger.Instance;
|
||||
@@ -155,7 +154,7 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
ModelState.AddModelError(key, errorMessage.ToString());
|
||||
}
|
||||
|
||||
public ActionResult CreateMenuItem(string id, int menuId, string returnUrl) {
|
||||
public ActionResult CreateMenuItem(string id, int menuId, string returnUrl, string parentMenuItemPosition = null) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -164,25 +163,31 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
|
||||
if (menuPart == null)
|
||||
return HttpNotFound();
|
||||
|
||||
|
||||
// load the menu
|
||||
var menu = Services.ContentManager.Get(menuId);
|
||||
|
||||
if (menu == null)
|
||||
return HttpNotFound();
|
||||
|
||||
try {
|
||||
// filter the content items for this specific menu
|
||||
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
|
||||
|
||||
|
||||
try {
|
||||
if (!String.IsNullOrEmpty(parentMenuItemPosition)) {
|
||||
var menuEntries = _menuService.GetMenuParts(menuId).Select(CreateMenuItemEntries);
|
||||
menuPart.MenuPosition = GetNextChildPosition(menuEntries, parentMenuItemPosition);
|
||||
}
|
||||
else {
|
||||
// filter the content items for this specific menu
|
||||
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
|
||||
}
|
||||
|
||||
var model = Services.ContentManager.BuildEditor(menuPart);
|
||||
|
||||
|
||||
return View(model);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
if (exception.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Error(T("Creating menu item failed: {0}", exception.Message).Text);
|
||||
Services.Notifier.Error(T("Creating menu item failed: {0}", exception.Message));
|
||||
@@ -191,7 +196,7 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("CreateMenuItem")]
|
||||
public ActionResult CreateMenuItemPost(string id, int menuId, string returnUrl) {
|
||||
public ActionResult CreateMenuItemPost(string id, int menuId, string returnUrl, string parentMenuItemPosition = null) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -205,12 +210,18 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
|
||||
if (menu == null)
|
||||
return HttpNotFound();
|
||||
|
||||
|
||||
var model = Services.ContentManager.UpdateEditor(menuPart, this);
|
||||
|
||||
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
|
||||
if (!String.IsNullOrEmpty(parentMenuItemPosition)) {
|
||||
var menuEntries = _menuService.GetMenuParts(menuId).Select(CreateMenuItemEntries);
|
||||
menuPart.MenuPosition = GetNextChildPosition(menuEntries, parentMenuItemPosition);
|
||||
}
|
||||
else {
|
||||
menuPart.MenuPosition = Position.GetNext( _navigationManager.BuildMenu(menu));
|
||||
}
|
||||
|
||||
menuPart.Menu = menu;
|
||||
|
||||
Services.ContentManager.Create(menuPart);
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
@@ -222,5 +233,23 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
|
||||
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
|
||||
}
|
||||
|
||||
private static string GetNextChildPosition(IEnumerable<MenuItemEntry> menuItems, string parentMenuItemPosition) {
|
||||
var parentMenuItemPositionPlusDot = parentMenuItemPosition + ".";
|
||||
var childElements = menuItems.Where(childElement => childElement.Position.StartsWith(parentMenuItemPositionPlusDot));
|
||||
if (childElements.Any()) {
|
||||
var result = childElements
|
||||
.Select(childElement => {
|
||||
var positionParts = childElement.Position.Substring(parentMenuItemPositionPlusDot.Length).Split(new[] { '.' }, 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
return positionParts.Any() ? int.Parse(positionParts[0]) : 0;
|
||||
})
|
||||
.Max();
|
||||
|
||||
return parentMenuItemPositionPlusDot + (result + 1);
|
||||
}
|
||||
|
||||
return parentMenuItemPositionPlusDot + "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,27 @@
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(function () {
|
||||
$(".navigation-menu-item > div").on("click", function () {
|
||||
if ($(".navigation-menu-item > div.menu-item-selected").length) {
|
||||
if ($(this).hasClass("menu-item-selected")) {
|
||||
$(this).removeClass("menu-item-selected");
|
||||
}
|
||||
else {
|
||||
$(".navigation-menu-item > div").removeClass("menu-item-selected");
|
||||
$(this).addClass("menu-item-selected")
|
||||
}
|
||||
}
|
||||
else {
|
||||
$(this).addClass("menu-item-selected");
|
||||
}
|
||||
});
|
||||
|
||||
$(".menu-item-actions > .button").on("click", function (e) {
|
||||
if ($(".navigation-menu-item > div.menu-item-selected").length) {
|
||||
e.originalEvent.currentTarget.href = $(this).attr("href") + "&parentMenuItemPosition=" + $(".navigation-menu-item > div.menu-item-selected > .navigation-position > input").val();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
||||
@@ -172,4 +172,13 @@
|
||||
.dir-rtl div.menu-item-actions {
|
||||
left:10px;
|
||||
right: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-menu li div.menu-item-selected {
|
||||
background-color: #6a7b42;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.navigation-menu li div.menu-item-selected a {
|
||||
color: #edf9f5;
|
||||
}
|
||||
@@ -46,6 +46,8 @@
|
||||
<div class="container">
|
||||
<div class="navigation-menu">
|
||||
@if (Model.MenuItemEntries.Any()) {
|
||||
@Html.Hint(T("If you'd like to add a new menu item under another one directly then select the parent by clicking on it."))
|
||||
|
||||
@RenderMenuItems(Model.MenuItemEntries, 0)
|
||||
}
|
||||
else {
|
||||
@@ -77,8 +79,8 @@
|
||||
}
|
||||
|
||||
|
||||
@helper RenderMenuItems(IList<MenuItemEntry> menuItems, int index) {
|
||||
|
||||
@helper RenderMenuItems(IList<MenuItemEntry> menuItems, int index) {
|
||||
|
||||
@:<ol>
|
||||
|
||||
// store current level to detect lowerb or upper level
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Lucene.Models {
|
||||
|
||||
public class LuceneDocumentIndex : IDocumentIndex {
|
||||
|
||||
public List<AbstractField> Fields { get; private set; }
|
||||
public List<Field> Fields { get; private set; }
|
||||
|
||||
private string _name;
|
||||
private string _stringValue;
|
||||
@@ -24,7 +24,7 @@ namespace Lucene.Models {
|
||||
public int ContentItemId { get; private set; }
|
||||
|
||||
public LuceneDocumentIndex(int documentId, Localizer t) {
|
||||
Fields = new List<AbstractField>();
|
||||
Fields = new List<Field>();
|
||||
SetContentItemId(documentId);
|
||||
IsDirty = false;
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Lucene.Models {
|
||||
|
||||
public IDocumentIndex SetContentItemId(int contentItemId) {
|
||||
ContentItemId = contentItemId;
|
||||
Fields.Add(new Field("id", contentItemId.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
|
||||
Fields.Add(new StringField("id", contentItemId.ToString(), Field.Store.YES));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -102,19 +102,26 @@ namespace Lucene.Models {
|
||||
if(_removeTags) {
|
||||
_stringValue = _stringValue.RemoveTags(true);
|
||||
}
|
||||
Fields.Add(new Field(_name, _stringValue ?? String.Empty,
|
||||
_store ? Field.Store.YES : Field.Store.NO,
|
||||
_analyze ? Field.Index.ANALYZED : Field.Index.NOT_ANALYZED));
|
||||
Fields.Add(new TextField(
|
||||
_name,
|
||||
_stringValue ?? String.Empty,
|
||||
_store ? Field.Store.YES : Field.Store.NO
|
||||
//,_analyze ? Field.Index.ANALYZED : Field.Index.NOT_ANALYZED
|
||||
));
|
||||
break;
|
||||
case TypeCode.Int32:
|
||||
Fields.Add(new NumericField(_name,
|
||||
_store ? Field.Store.YES : Field.Store.NO,
|
||||
true).SetIntValue(_intValue));
|
||||
Fields.Add(new DoubleField(
|
||||
_name,
|
||||
_intValue,
|
||||
_store ? Field.Store.YES : Field.Store.NO
|
||||
));
|
||||
break;
|
||||
case TypeCode.Single:
|
||||
Fields.Add(new NumericField(_name,
|
||||
_store ? Field.Store.YES : Field.Store.NO,
|
||||
true).SetDoubleValue(_doubleValue));
|
||||
Fields.Add(new DoubleField(
|
||||
_name,
|
||||
_doubleValue,
|
||||
_store ? Field.Store.YES : Field.Store.NO
|
||||
));
|
||||
break;
|
||||
case TypeCode.Empty:
|
||||
break;
|
||||
|
||||
@@ -11,7 +11,7 @@ using Lucene.Net.Util;
|
||||
using Orchard.Indexing;
|
||||
using Orchard.Logging;
|
||||
using Lucene.Net.Documents;
|
||||
using Lucene.Net.QueryParsers;
|
||||
using Lucene.Net.Search.QueryParsers;
|
||||
using Lucene.Net.Analysis.Tokenattributes;
|
||||
|
||||
namespace Lucene.Services {
|
||||
@@ -33,7 +33,7 @@ namespace Lucene.Services {
|
||||
private bool _asFilter;
|
||||
|
||||
// pending clause attributes
|
||||
private Occur _occur;
|
||||
private BooleanClause.Occur _occur;
|
||||
private bool _exactMatch;
|
||||
private bool _notAnalyzed;
|
||||
private float _boost;
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
+ <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Orchard.Azure.Services.FileSystems {
|
||||
_publicHostName = publicHostName;
|
||||
}
|
||||
|
||||
private void EnsureInitialized() {
|
||||
protected void EnsureInitialized() {
|
||||
if (_storageAccount != null) {
|
||||
return;
|
||||
}
|
||||
@@ -355,7 +355,7 @@ namespace Orchard.Azure.Services.FileSystems {
|
||||
// as opposed to the File System implementation, if nothing is done on the stream
|
||||
// the file will be emptied, because Azure doesn't implement FileMode.Truncate
|
||||
_blob.DeleteIfExists();
|
||||
_blob = _blob.Container.GetBlockBlobReference(_blob.Uri.ToString());
|
||||
_blob = _blob.Container.GetBlockBlobReference(_blob.Name);
|
||||
_blob.UploadFromStream(new MemoryStream(new byte[0]));
|
||||
return OpenWrite();
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace Orchard.Azure.Services.FileSystems.Media {
|
||||
/// <param name="url">The public URL of the media.</param>
|
||||
/// <returns>The corresponding local path.</returns>
|
||||
public string GetStoragePath(string url) {
|
||||
EnsureInitialized();
|
||||
if (url.StartsWith(_absoluteRoot)) {
|
||||
return HttpUtility.UrlDecode(url.Substring(Combine(_absoluteRoot, "/").Length));
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>$$ProjectName$$</RootNamespace>
|
||||
<AssemblyName>$$ProjectName$$</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<OldToolsVersion>4.0</OldToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="ViewModels\NavigationPartViewModel.cs" />
|
||||
<Content Include="Scripts\ContentPicker.js" />
|
||||
<Content Include="Scripts\SelectableContentTab.js" />
|
||||
<Content Include="Styles\content-picker-admin.css" />
|
||||
<Content Include="Styles\ContentPicker.css" />
|
||||
<Content Include="Styles\Images\move.gif" />
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Orchard.ContentPicker {
|
||||
public void BuildManifests(ResourceManifestBuilder builder) {
|
||||
var manifest = builder.Add();
|
||||
manifest.DefineScript("ContentPicker").SetUrl("ContentPicker.js", "ContentPicker.js").SetDependencies("jQuery");
|
||||
manifest.DefineScript("SelectableContentTab").SetUrl("SelectableContentTab.js", "SelectableContentTab.js").SetDependencies("jQuery");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,14 +80,26 @@
|
||||
addButton.click(function() {
|
||||
addButton.trigger("orchard-admin-contentpicker-open", {
|
||||
callback: function(data) {
|
||||
var tmpl = template.replace( /\{contentItemId\}/g , data.id)
|
||||
.replace( /\{edit-link\}/g , data.editLink)
|
||||
.replace( /\{status-text}/g , data.published? "" : " - " + notPublishedText);
|
||||
var content = $(tmpl);
|
||||
$(self).find('table.content-picker tbody').append(content);
|
||||
if (Array.isArray && Array.isArray(data)) {
|
||||
data.forEach(function (d) {
|
||||
var tmpl = template.replace(/\{contentItemId\}/g, d.id)
|
||||
.replace(/\{edit-link\}/g, d.editLink)
|
||||
.replace(/\{status-text}/g, d.published ? "" : " - " + notPublishedText);
|
||||
var content = $(tmpl);
|
||||
$(self).find('table.content-picker tbody').append(content);
|
||||
});
|
||||
refreshIds();
|
||||
$(self).find('.content-picker-message').show();
|
||||
} else {
|
||||
var tmpl = template.replace(/\{contentItemId\}/g, data.id)
|
||||
.replace(/\{edit-link\}/g, data.editLink)
|
||||
.replace(/\{status-text}/g, data.published ? "" : " - " + notPublishedText);
|
||||
var content = $(tmpl);
|
||||
$(self).find('table.content-picker tbody').append(content);
|
||||
|
||||
refreshIds();
|
||||
$(self).find('.content-picker-message').show();
|
||||
refreshIds();
|
||||
$(self).find('.content-picker-message').show();
|
||||
}
|
||||
},
|
||||
baseUrl: baseUrl,
|
||||
part: partName,
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
jQuery(function ($) {
|
||||
|
||||
Initialize = function () {
|
||||
|
||||
$('.button.addSelected').on('click', function () {
|
||||
var selectedItems = $('.content-picker-itemCheck:checked');
|
||||
var itemsToAdd = new Array();
|
||||
$.each(selectedItems, function (index, item) {
|
||||
var related = $(item).siblings('.content-picker-item').children('.related');
|
||||
var data = {
|
||||
id: related.data("id"),
|
||||
displayText: related.data("display-text"),
|
||||
editLink: related.data("edit-link"),
|
||||
editUrl: related.data("edit-url"),
|
||||
adminUrl: related.data("admin-url"),
|
||||
displayLink: related.data("display-link"),
|
||||
published: related.data("published")
|
||||
};
|
||||
return itemsToAdd.push(data);
|
||||
});
|
||||
window.opener.jQuery[query("callback")](itemsToAdd);
|
||||
window.close();
|
||||
});
|
||||
$('.content-picker-SelectAll').on('click', function () {
|
||||
$('.content-picker-itemCheck').prop('checked', $(this).prop("checked"));
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
return Initialize();
|
||||
});
|
||||
});
|
||||
@@ -19,4 +19,37 @@ body {
|
||||
padding: 18px;
|
||||
background: white;
|
||||
border: 1px solid #E4E5E6;
|
||||
}
|
||||
|
||||
.content-picker-item
|
||||
{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.content-picker-itemCheck
|
||||
{
|
||||
position:absolute;
|
||||
|
||||
}
|
||||
|
||||
label[for="selectAll"]:before
|
||||
{
|
||||
content:'';
|
||||
display:block;
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
label[for="selectAll"]
|
||||
{
|
||||
display:inline;
|
||||
}
|
||||
|
||||
.addSelected
|
||||
{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.page-size-options > div:first-child
|
||||
{
|
||||
display:inline-block;
|
||||
}
|
||||
@@ -3,27 +3,30 @@
|
||||
ContentItem contentItem = Model.ContentItem;
|
||||
}
|
||||
<div class="summary" itemscope="itemscope" itemid="@contentItem.Id" itemtype="http://orchardproject.net/data/ContentItem">
|
||||
<div class="properties">
|
||||
@*<input type="checkbox" value="@contentItem.Id" name="itemIds"/>*@
|
||||
<h3>@Html.ItemDisplayText(contentItem)</h3> - <div class="contentType">@contentItem.TypeDefinition.DisplayName</div>
|
||||
@if (Model.Header != null) {
|
||||
<div class="header">@Display(Model.Header)</div>
|
||||
}
|
||||
@if (Model.Meta != null) {
|
||||
<div class="metadata">@Display(Model.Meta)</div>
|
||||
<input type="checkbox" class="content-picker-itemCheck" />
|
||||
<div class="content-picker-item">
|
||||
<div class="properties">
|
||||
@*<input type="checkbox" value="@contentItem.Id" name="itemIds"/>*@
|
||||
<h3>@Html.ItemDisplayText(contentItem)</h3> - <div class="contentType">@contentItem.TypeDefinition.DisplayName</div>
|
||||
@if (Model.Header != null) {
|
||||
<div class="header">@Display(Model.Header)</div>
|
||||
}
|
||||
@if (Model.Meta != null) {
|
||||
<div class="metadata">@Display(Model.Meta)</div>
|
||||
}
|
||||
</div>
|
||||
<div class="related"
|
||||
data-display-text="@Html.ItemDisplayText(contentItem)"
|
||||
data-id="@contentItem.Id"
|
||||
data-edit-link="@Html.Encode(Html.ItemEditLink(contentItem))"
|
||||
data-edit-url="@Html.Encode(Url.ItemEditUrl(contentItem))"
|
||||
data-admin-url="@Html.Encode(Url.ItemAdminUrl(contentItem))"
|
||||
data-display-link="@Html.Encode(Html.ItemDisplayLink(contentItem))"
|
||||
data-published="@contentItem.VersionRecord.Published.ToString().ToLower()" >
|
||||
@Html.Link(T("Select").Text, "#", new { @class = "button select"})
|
||||
</div>
|
||||
@if (Model.Content != null) {
|
||||
<div class="primary">@Display(Model.Content)</div>
|
||||
}
|
||||
</div>
|
||||
<div class="related"
|
||||
data-display-text="@Html.ItemDisplayText(contentItem)"
|
||||
data-id="@contentItem.Id"
|
||||
data-edit-link="@Html.Encode(Html.ItemEditLink(contentItem))"
|
||||
data-edit-url="@Html.Encode(Url.ItemEditUrl(contentItem))"
|
||||
data-admin-url="@Html.Encode(Url.ItemAdminUrl(contentItem))"
|
||||
data-display-link="@Html.Encode(Html.ItemDisplayLink(contentItem))"
|
||||
data-published="@contentItem.VersionRecord.Published.ToString().ToLower()" >
|
||||
@Html.Link(T("Select").Text, "#", new { @class = "button select"})
|
||||
</div>
|
||||
@if (Model.Content != null) {
|
||||
<div class="primary">@Display(Model.Content)</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@using Orchard.Core.Contents.ViewModels;
|
||||
@{
|
||||
Script.Require("SelectableContentTab");
|
||||
|
||||
var typeDisplayName = Model.TypeDisplayName;
|
||||
var pageTitle = T("Recent Content");
|
||||
|
||||
@@ -8,6 +10,7 @@
|
||||
}
|
||||
|
||||
Layout.Title = pageTitle;
|
||||
|
||||
}
|
||||
|
||||
<div class="manage">
|
||||
@@ -33,6 +36,7 @@
|
||||
<fieldset class="contentItems bulk-items">
|
||||
@Display(Model.ContentItems)
|
||||
</fieldset>
|
||||
@Html.Link(T("Add Selected").Text, "#", new { @class = "button addSelected"})
|
||||
@Display(Model.Pager)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,19 +8,28 @@ using Orchard.CustomForms.Models;
|
||||
using Orchard.CustomForms.ViewModels;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using System;
|
||||
using Orchard.Core.Contents.Settings;
|
||||
using Orchard.Security;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.CustomForms.Drivers {
|
||||
public class CustomFormPartDriver : ContentPartDriver<CustomFormPart> {
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
private readonly IAuthorizationService _authService;
|
||||
|
||||
public CustomFormPartDriver(
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
IOrchardServices orchardServices) {
|
||||
IOrchardServices orchardServices,
|
||||
IAuthorizationService authService) {
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
_orchardServices = orchardServices;
|
||||
_authService = authService;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
protected override DriverResult Display(CustomFormPart part, string displayType, dynamic shapeHelper) {
|
||||
// this method is used by the widget to render the form when it is displayed
|
||||
|
||||
@@ -55,6 +64,19 @@ namespace Orchard.CustomForms.Drivers {
|
||||
};
|
||||
|
||||
updater.TryUpdateModel(viewModel, Prefix, null, null);
|
||||
|
||||
// Warn if the custom form is set to save a content item that is viewable by anonymous users (publicly accessible)
|
||||
if (viewModel.CustomFormPart.SaveContentItem) {
|
||||
// If it's draftable then don't display the warning because the generated content items won't be publicly accessible
|
||||
var typeDefinition = _contentDefinitionManager.ListTypeDefinitions().Where(x => String.Equals(x.Name, viewModel.CustomFormPart.ContentType, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
||||
if (typeDefinition != null && !typeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable) {
|
||||
// Create a dummy content item of the specified type to check permissions against
|
||||
if (_authService.TryCheckAccess(Orchard.Core.Contents.Permissions.ViewContent, null, _orchardServices.ContentManager.New(viewModel.CustomFormPart.ContentType))) {
|
||||
_orchardServices.Notifier.Add(UI.Notify.NotifyType.Warning, T("Your custom form will save data to content items that are publicly accessible."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
|
||||
@Display(editor)
|
||||
|
||||
@Html.Hidden("returnUrl", Request.RawUrl);
|
||||
@Html.Hidden("returnUrl", Request.RawUrl, new { id = string.Empty });
|
||||
|
||||
<fieldset class="submit-button">
|
||||
<button type="submit" name="submit.Save" value="submit.Save">@Model.ContentPart.SubmitButtonText</button>
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
|
||||
<configSections>
|
||||
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
|
||||
<remove name="host"/>
|
||||
<remove name="pages"/>
|
||||
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false"/>
|
||||
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
<pages pageBaseType="Orchard.Mvc.ViewEngines.Razor.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="System.Web.Mvc"/>
|
||||
<add namespace="System.Web.Mvc.Ajax"/>
|
||||
<add namespace="System.Web.Mvc.Html"/>
|
||||
<add namespace="System.Web.Routing"/>
|
||||
<add namespace="System.Web.WebPages"/>
|
||||
<add namespace="System.Linq"/>
|
||||
<add namespace="System.Collections.Generic"/>
|
||||
<add namespace="Orchard.Mvc.Html"/>
|
||||
</namespaces>
|
||||
</pages>
|
||||
</system.web.webPages.razor>
|
||||
|
||||
<system.web>
|
||||
<compilation targetFramework="4.5.1">
|
||||
<assemblies>
|
||||
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
<add assembly="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
<add assembly="Orchard.Framework"/>
|
||||
<add assembly="Orchard.Core"/>
|
||||
<add assembly="Orchard.Layouts"/>
|
||||
</assemblies>
|
||||
</compilation>
|
||||
</system.web>
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NHibernate" publicKeyToken="AA95F207798DFDB4" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.4000" newVersion="4.0.0.4000"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Iesi.Collections" publicKeyToken="AA95F207798DFDB4" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Autofac" publicKeyToken="17863AF14B0044DA" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -0,0 +1,79 @@
|
||||
using Orchard.DynamicForms.Elements;
|
||||
using Orchard.Forms.Services;
|
||||
using Orchard.Layouts.Framework.Drivers;
|
||||
using Orchard.Layouts.Framework.Display;
|
||||
using Orchard.Layouts.Helpers;
|
||||
using Orchard.Tokens;
|
||||
using DescribeContext = Orchard.Forms.Services.DescribeContext;
|
||||
|
||||
namespace Orchard.DynamicForms.Drivers {
|
||||
public class UrlFieldElementDriver : FormsElementDriver<UrlField> {
|
||||
private readonly ITokenizer _tokenizer;
|
||||
|
||||
public UrlFieldElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
|
||||
_tokenizer = tokenizer;
|
||||
}
|
||||
|
||||
protected override EditorResult OnBuildEditor(UrlField element, ElementEditorContext context) {
|
||||
var autoLabelEditor = BuildForm(context, "AutoLabel");
|
||||
var webAddressFieldEditor = BuildForm(context, "UrlField");
|
||||
var webAddressFieldValidation = BuildForm(context, "UrlFieldValidation", "Validation:10");
|
||||
|
||||
return Editor(context, autoLabelEditor, webAddressFieldEditor, webAddressFieldValidation);
|
||||
}
|
||||
|
||||
protected override void DescribeForm(DescribeContext context) {
|
||||
context.Form("UrlField", factory => {
|
||||
var shape = (dynamic) factory;
|
||||
var form = shape.Fieldset(
|
||||
Id: "UrlField",
|
||||
_Value: shape.Textbox(
|
||||
Id: "Value",
|
||||
Name: "Value",
|
||||
Title: "Value",
|
||||
Classes: new[] {"text", "medium", "tokenized"},
|
||||
Description: T("The value of this URL field.")));
|
||||
|
||||
return form;
|
||||
});
|
||||
|
||||
context.Form("UrlFieldValidation", factory => {
|
||||
var shape = (dynamic) factory;
|
||||
var form = shape.Fieldset(
|
||||
Id: "UrlFieldValidation",
|
||||
_IsRequired: shape.Checkbox(
|
||||
Id: "IsRequired",
|
||||
Name: "IsRequired",
|
||||
Title: "Required",
|
||||
Value: "true",
|
||||
Description: T("Tick this checkbox to make this email field a required field.")),
|
||||
_MaximumLength: shape.Textbox(
|
||||
Id: "MaximumLength",
|
||||
Name: "MaximumLength",
|
||||
Title: "Maximum Length",
|
||||
Classes: new[] {"text", "medium", "tokenized"},
|
||||
Description: T("The maximum length allowed.")),
|
||||
_CustomValidationMessage: shape.Textbox(
|
||||
Id: "CustomValidationMessage",
|
||||
Name: "CustomValidationMessage",
|
||||
Title: "Custom Validation Message",
|
||||
Classes: new[] {"text", "large", "tokenized"},
|
||||
Description: T("Optionally provide a custom validation message.")),
|
||||
_ShowValidationMessage: shape.Checkbox(
|
||||
Id: "ShowValidationMessage",
|
||||
Name: "ShowValidationMessage",
|
||||
Title: "Show Validation Message",
|
||||
Value: "true",
|
||||
Description: T("Autogenerate a validation message when a validation error occurs for the current field. Alternatively, to control the placement of the validation message you can use the ValidationMessage element instead.")));
|
||||
|
||||
return form;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnDisplaying(UrlField element, ElementDisplayContext context) {
|
||||
context.ElementShape.ProcessedName = _tokenizer.Replace(element.Name, context.GetTokenData());
|
||||
context.ElementShape.ProcessedLabel = _tokenizer.Replace(element.Label, context.GetTokenData());
|
||||
context.ElementShape.ProcessedValue = _tokenizer.Replace(element.RuntimeValue, context.GetTokenData());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Orchard.DynamicForms.Validators.Settings;
|
||||
|
||||
namespace Orchard.DynamicForms.Elements {
|
||||
public class UrlField : LabeledFormElement {
|
||||
public UrlFieldValidationSettings ValidationSettings {
|
||||
get { return Data.GetModel<UrlFieldValidationSettings>(""); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,9 @@
|
||||
<Compile Include="Bindings\InputFieldBindings.cs" />
|
||||
<Compile Include="Bindings\TaxonomyFieldBindings.cs" />
|
||||
<Compile Include="Drivers\FieldsetElementDriver.cs" />
|
||||
<Compile Include="Drivers\UrlFieldElementDriver.cs" />
|
||||
<Compile Include="Elements\Fieldset.cs" />
|
||||
<Compile Include="Elements\UrlField.cs" />
|
||||
<Compile Include="Forms\AddModelErrorForm.cs" />
|
||||
<Compile Include="Forms\SelectDynamicForms.cs" />
|
||||
<Compile Include="Bindings\TextFieldBindings.cs" />
|
||||
@@ -217,7 +219,9 @@
|
||||
<Compile Include="ValidationRules\EmailAddress.cs" />
|
||||
<Compile Include="ValidationRules\RegularExpression.cs" />
|
||||
<Compile Include="ValidationRules\StringLength.cs" />
|
||||
<Compile Include="ValidationRules\UrlAddress.cs" />
|
||||
<Compile Include="Validators\QueryValidator.cs" />
|
||||
<Compile Include="Validators\Settings\UrlFieldValidationSettings.cs" />
|
||||
<Compile Include="Validators\TaxonomyValidator.cs" />
|
||||
<Compile Include="Validators\EnumerationValidator.cs" />
|
||||
<Compile Include="Validators\CheckBoxValidator.cs" />
|
||||
@@ -271,6 +275,7 @@
|
||||
<Compile Include="Validators\ReCaptchaValidator.cs" />
|
||||
<Compile Include="Validators\TextAreaValidator.cs" />
|
||||
<Compile Include="Validators\TextFieldValidator.cs" />
|
||||
<Compile Include="Validators\UrlFieldValidator.cs" />
|
||||
<Compile Include="ViewModels\FieldValidationSettings.cs" />
|
||||
<Compile Include="ViewModels\FormBindingSettings.cs" />
|
||||
<Compile Include="Helpers\ContentTypeDefinitionExtensions.cs" />
|
||||
@@ -506,6 +511,12 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Assets.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Elements\UrlField.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Elements\UrlField.Design.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Tokens;
|
||||
|
||||
namespace Orchard.DynamicForms.Services {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Orchard.DynamicForms.Helpers;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
using Orchard.Localization;
|
||||
@@ -22,7 +21,9 @@ namespace Orchard.DynamicForms.ValidationRules {
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
return T(Tokenize(ErrorMessage.WithDefault(String.Format("{0} must match the value of {1}.", context.FieldName, TargetName)), context));
|
||||
return String.IsNullOrWhiteSpace(ErrorMessage)
|
||||
? T("{0} must match the value of {1}.", context.FieldName, TargetName)
|
||||
: T(ErrorMessage, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,9 @@ namespace Orchard.DynamicForms.ValidationRules {
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
return T(Tokenize(ErrorMessage.WithDefault(String.Format("{0} is not a valid email address.", context.FieldName)), context));
|
||||
return String.IsNullOrWhiteSpace(ErrorMessage)
|
||||
? T("{0} is not a valid email address.", context.FieldName)
|
||||
: T(ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Orchard.DynamicForms.Helpers;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
using Orchard.Localization;
|
||||
@@ -18,7 +17,9 @@ namespace Orchard.DynamicForms.ValidationRules {
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
return T(Tokenize(ErrorMessage.WithDefault(String.Format("{0} is a mandatory field.", context.FieldName)), context));
|
||||
return String.IsNullOrWhiteSpace(ErrorMessage)
|
||||
? T("{0} is a mandatory field.", context.FieldName)
|
||||
: T(ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Orchard.DynamicForms.Helpers;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
using Orchard.Localization;
|
||||
@@ -18,7 +17,9 @@ namespace Orchard.DynamicForms.ValidationRules {
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
return T(Tokenize(ErrorMessage.WithDefault(String.Format("An option is required for {0}.", context.FieldName)), context));
|
||||
return String.IsNullOrWhiteSpace(ErrorMessage)
|
||||
? T("An option is required for {0}.", context.FieldName)
|
||||
: T(ErrorMessage, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Orchard.DynamicForms.Helpers;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
using Orchard.Localization;
|
||||
@@ -27,7 +26,9 @@ namespace Orchard.DynamicForms.ValidationRules {
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
return T(Tokenize(ErrorMessage.WithDefault(String.Format("{0} must match the following pattern: {1}.", context.FieldName, Pattern)), context));
|
||||
return String.IsNullOrWhiteSpace(ErrorMessage)
|
||||
? T("{0} must match the following pattern: {1}.", context.FieldName, Pattern)
|
||||
: T(ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Orchard.DynamicForms.Helpers;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
using Orchard.Localization;
|
||||
@@ -18,7 +17,9 @@ namespace Orchard.DynamicForms.ValidationRules {
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
return T(Tokenize(ErrorMessage.WithDefault(String.Format("{0} is a required field.", context.FieldName)), context));
|
||||
return String.IsNullOrWhiteSpace(ErrorMessage)
|
||||
? T("{0} is a required field.", context.FieldName)
|
||||
: T(ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,12 +40,13 @@ namespace Orchard.DynamicForms.ValidationRules {
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
if (!String.IsNullOrWhiteSpace(ErrorMessage))
|
||||
return T(Tokenize(String.Format(ErrorMessage, context.FieldName, Minimum, Maximum), context));
|
||||
if(!String.IsNullOrWhiteSpace(ErrorMessage))
|
||||
return T(ErrorMessage, context.FieldName, Minimum, Maximum);
|
||||
|
||||
if(Minimum != null && Maximum != null)
|
||||
if (Minimum != null && Maximum != null)
|
||||
return T("{0} must be between {1} and {2} characters long.", context.FieldName, Minimum, Maximum);
|
||||
else if (Minimum != null)
|
||||
|
||||
if (Minimum != null)
|
||||
return T("{0} must be at least {1} characters long.", context.FieldName, Minimum);
|
||||
|
||||
return T("{0} must be at most {1} characters long.", context.FieldName, Maximum);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Orchard.DynamicForms.Helpers;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.DynamicForms.ValidationRules {
|
||||
public class UrlAddress : ValidationRule {
|
||||
public UrlAddress() {
|
||||
RegexOptions = RegexOptions.Singleline | RegexOptions.IgnoreCase;
|
||||
Pattern = @"^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$";
|
||||
}
|
||||
|
||||
public string Pattern { get; set; }
|
||||
public RegexOptions RegexOptions { get; set; }
|
||||
|
||||
public override void Validate(ValidateInputContext context) {
|
||||
if (!Regex.IsMatch(context.AttemptedValue, Pattern, RegexOptions)) {
|
||||
var message = GetValidationMessage(context);
|
||||
context.ModelState.AddModelError(context.FieldName, message.Text);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RegisterClientAttributes(RegisterClientValidationAttributesContext context) {
|
||||
context.ClientAttributes["data-val-regex"] = GetValidationMessage(context).Text;
|
||||
context.ClientAttributes["data-val-regex-pattern"] = Pattern;
|
||||
}
|
||||
|
||||
private LocalizedString GetValidationMessage(ValidationContext context) {
|
||||
return String.IsNullOrWhiteSpace(ErrorMessage)
|
||||
? T("{0} is not a valid URL.", context.FieldName)
|
||||
: T(ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Orchard.DynamicForms.Services.Models;
|
||||
|
||||
namespace Orchard.DynamicForms.Validators.Settings {
|
||||
public class UrlFieldValidationSettings : ValidationSettingsBase {
|
||||
public bool? IsRequired { get; set; }
|
||||
public int? MaximumLength { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.DynamicForms.Elements;
|
||||
using Orchard.DynamicForms.Services;
|
||||
using Orchard.DynamicForms.ValidationRules;
|
||||
|
||||
namespace Orchard.DynamicForms.Validators {
|
||||
public class UrlFieldValidator : ElementValidator<UrlField> {
|
||||
private readonly IValidationRuleFactory _validationRuleFactory;
|
||||
|
||||
public UrlFieldValidator(IValidationRuleFactory validationRuleFactory) {
|
||||
_validationRuleFactory = validationRuleFactory;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IValidationRule> GetValidationRules(UrlField element) {
|
||||
var settings = element.ValidationSettings;
|
||||
|
||||
if (settings.IsRequired == true)
|
||||
yield return _validationRuleFactory.Create<Required>(settings.CustomValidationMessage);
|
||||
|
||||
if (settings.MaximumLength != null) {
|
||||
yield return _validationRuleFactory.Create<StringLength>(r => {
|
||||
r.Maximum = settings.MaximumLength;
|
||||
r.ErrorMessage = settings.CustomValidationMessage;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
@using Orchard.DynamicForms.Elements
|
||||
@using Orchard.Layouts.Helpers
|
||||
@{
|
||||
var element = (UrlField)Model.Element;
|
||||
var tagBuilder = TagBuilderExtensions.CreateElementTagBuilder(Model, "input");
|
||||
|
||||
tagBuilder.AddCssClass("text design");
|
||||
tagBuilder.Attributes["type"] = "url";
|
||||
tagBuilder.Attributes["value"] = element.Value;
|
||||
tagBuilder.Attributes["name"] = element.Name;
|
||||
}
|
||||
|
||||
@if (element.ShowLabel) {
|
||||
<div>
|
||||
<label for="@element.HtmlId">@element.Label</label>
|
||||
@tagBuilder.ToHtmlString(TagRenderMode.SelfClosing)
|
||||
</div>
|
||||
}
|
||||
else {
|
||||
@tagBuilder.ToHtmlString(TagRenderMode.SelfClosing)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
@using Orchard.DisplayManagement.Shapes
|
||||
@using Orchard.DynamicForms.Elements
|
||||
@using Orchard.Layouts.Helpers
|
||||
@{
|
||||
var element = (UrlField)Model.Element;
|
||||
var tagBuilder = (OrchardTagBuilder)TagBuilderExtensions.CreateElementTagBuilder(Model, "input");
|
||||
|
||||
tagBuilder.AddCssClass("text");
|
||||
tagBuilder.Attributes["type"] = "url";
|
||||
tagBuilder.Attributes["value"] = Model.ProcessedValue;
|
||||
tagBuilder.Attributes["name"] = Model.ProcessedName;
|
||||
tagBuilder.AddClientValidationAttributes((IDictionary<string, string>)Model.ClientValidationAttributes);
|
||||
|
||||
if (!ViewData.ModelState.IsValidField(Model.ProcessedName)) {
|
||||
tagBuilder.AddCssClass("input-validation-error");
|
||||
}
|
||||
}
|
||||
|
||||
@if (element.ShowLabel) {
|
||||
<label for="@element.HtmlId">@Model.ProcessedLabel</label>
|
||||
}
|
||||
@tagBuilder.ToHtmlString(TagRenderMode.SelfClosing)
|
||||
@if (element.ValidationSettings.ShowValidationMessage == true) {
|
||||
@Html.ValidationMessage((string)Model.ProcessedName)
|
||||
}
|
||||
@@ -237,7 +237,10 @@ namespace Orchard.Indexing.Services {
|
||||
// skip items from types which are not indexed
|
||||
var settings = GetTypeIndexingSettings(item.ContentItem);
|
||||
if (settings.List.Contains(indexName)) {
|
||||
documentIndex = ExtractDocumentIndex(item.ContentItem);
|
||||
if (item.ContentItem.HasPublished()) {
|
||||
var published = _contentManager.Get(item.Id, VersionOptions.Published);
|
||||
documentIndex = ExtractDocumentIndex(published);
|
||||
}
|
||||
}
|
||||
else if (settings.List.Contains(indexName + ":latest")) {
|
||||
var latest = _contentManager.Get(item.Id, VersionOptions.Latest);
|
||||
|
||||
@@ -169,8 +169,8 @@
|
||||
break;
|
||||
case "save":
|
||||
{
|
||||
var frameDoc = self.frame.getDocument();
|
||||
var form = frameDoc.find("form:first");
|
||||
var frameWindow = self.frame.getWindow();
|
||||
var form = frameWindow.$("form:first");
|
||||
form.submit();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -380,7 +380,11 @@ namespace Orchard.Lists.Controllers {
|
||||
[HttpPost, ActionName("List")]
|
||||
[FormValueRequired("listViewName")]
|
||||
public ActionResult ChangeListView(int containerId, string listViewName, PagerParameters pagerParameters) {
|
||||
var container = _containerService.Get(containerId);
|
||||
var container = _containerService.Get(containerId, VersionOptions.Latest);
|
||||
if (container == null || !container.Has<ContainerPart>()) {
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
container.Record.AdminListViewName = listViewName;
|
||||
return RedirectToAction("List", new { containerId, page = pagerParameters.Page, pageSize = pagerParameters.PageSize });
|
||||
}
|
||||
|
||||
@@ -156,10 +156,10 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder().MediaPath;
|
||||
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(rootMediaFolder, skip, count, order, mediaType);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(rootMediaFolder, mediaType);
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
var rootMediaFolderPath = rootMediaFolder == null ? null : rootMediaFolder.MediaPath;
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(rootMediaFolderPath, skip, count, order, mediaType);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(rootMediaFolderPath, mediaType);
|
||||
|
||||
|
||||
var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel {
|
||||
@@ -256,4 +256,4 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
return new FolderHierarchy(root) {Children = _mediaLibraryService.GetMediaFolders(root.MediaPath).Select(GetFolderHierarchy)};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Orchard.MediaLibrary {
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Author",
|
||||
Permissions = new[] {ManageMediaContent}
|
||||
Permissions = new[] {ManageOwnMedia}
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Contributor",
|
||||
|
||||
@@ -71,8 +71,11 @@ $(function () {
|
||||
|
||||
var listWidth = $('#media-library-main-list').width();
|
||||
var listHeight = $('#media-library-main-list').height();
|
||||
var itemWidth = $('.thumbnail').first().width();
|
||||
var itemHeight = $('.thumbnail').first().height();
|
||||
var itemWidth = $('#media-library-main-list li').first().width();
|
||||
var itemHeight = $('#media-library-main-list li').first().height();
|
||||
var defaultDimension = $(window).width() < 1420 ? 120 : 200;
|
||||
if (itemHeight == 0 || itemHeight == null) itemHeight = defaultDimension;
|
||||
if (itemWidth == 0 || itemWidth == null) itemWidth = defaultDimension;
|
||||
var draftText = $("#media-library").data("draft-text");
|
||||
|
||||
var itemsPerRow = Math.floor(listWidth / itemWidth);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.zone-content, #content, #main, #layout-content, #layout-main {
|
||||
.zone-content, #content, #main, #layout-content, #layout-main {
|
||||
height: 100%;
|
||||
display: block;
|
||||
min-height: 400px;
|
||||
@@ -155,6 +155,10 @@
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
#media-library-main-list.pending li {
|
||||
opacity:.3;
|
||||
}
|
||||
|
||||
/* Remove the space for the editor, and the scrollbar in the import page */
|
||||
#media-library-import #media-library-main-list {
|
||||
overflow-y: hidden;
|
||||
@@ -499,4 +503,4 @@ padding-right: 16px;
|
||||
.dir-rtl .media-library-main-list-overlay p {
|
||||
padding-right:inherit;
|
||||
padding-left:5px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ html.dyn #main ul.features button { display:none; }
|
||||
height:6em;
|
||||
margin:0 .5% 1% .5%;
|
||||
position:relative;
|
||||
width:32.2%;
|
||||
width:32%;
|
||||
}
|
||||
|
||||
.features.summary-view .missingDependencies{
|
||||
@@ -223,4 +223,4 @@ h2.recentlyInstalledModule {padding:0 0 0 40px;}
|
||||
|
||||
.dir-rtl .manage {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,7 @@
|
||||
$allCheckboxes.prop("checked", false);
|
||||
}
|
||||
});
|
||||
|
||||
$('input[name=DataProvider]:checked').click();
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -4,18 +4,19 @@
|
||||
Layout.Title = T("Add New Tenant").ToString();
|
||||
|
||||
Script.Require("jQuery").AtFoot();
|
||||
Script.Include(Url.Content("~/Themes/TheAdmin/Scripts/admin.js")).AtFoot();
|
||||
Script.Require("ShapesBase").AtFoot();
|
||||
Script.Include(Url.Content("~/Themes/TheAdmin/Scripts/admin.js")).AtFoot();
|
||||
Script.Include("multi-tenancy.admin.js").AtFoot();
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<fieldset>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.Name)">@T("Name")</label>
|
||||
@Html.TextBoxFor(m => m.Name, new { @class = "text" })
|
||||
<span class="hint">@T("The name of the tenant as it will be displayed in the admin.")</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.RequestUrlHost)">@T("Host")</label>
|
||||
@Html.TextBoxFor(m => m.RequestUrlHost, new { @class = "text medium" })
|
||||
@@ -30,7 +31,7 @@
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>@T("Database Setup")</legend>
|
||||
<div>
|
||||
<div>
|
||||
@Html.RadioButtonFor(svm => svm.DataProvider, "", new { id = "tenantDatabaseOption" })
|
||||
<label for="tenantDatabaseOption" class="forcheckbox">@T("Allow the tenant to set up the database")</label>
|
||||
</div>
|
||||
@@ -48,18 +49,18 @@
|
||||
<span class="hint">@T("Example:") @T("Data Source=sqlServerName;Initial Catalog=dbName;Persist Security Info=True;User ID=userName;Password=password")</span>
|
||||
</span>
|
||||
<span data-controllerid="sqlDatabaseOption">
|
||||
<label for="DatabaseTablePrefix">@T("Database Table Prefix")</label>
|
||||
<label for="DatabaseTablePrefix">@T("Database table prefix")</label>
|
||||
@Html.EditorFor(svm => svm.DatabaseTablePrefix)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Themes)">@T("Available Themes")</label>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Themes)">@T("Available Themes")</label>
|
||||
<div>
|
||||
<span class="hint">@T("Select the Themes which should be available for this tenant. If none is selected, they will all be available.")</span>
|
||||
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<input type="checkbox" class="select-all" id="select-all-themes" />
|
||||
@@ -79,11 +80,11 @@
|
||||
}
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Modules)">@T("Available Modules")</label>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Modules)">@T("Available Modules")</label>
|
||||
<div>
|
||||
<span class="hint">@T("Select the Modules which should be available for this tenant. If none is selected, they will all be available.")</span>
|
||||
|
||||
@@ -94,21 +95,21 @@
|
||||
</li>
|
||||
|
||||
@for (var i = 0; i < Model.Modules.Count; i++) {
|
||||
<li>
|
||||
@{
|
||||
var theme = Model.Modules[i];
|
||||
@Html.CheckBox(Html.FieldNameFor(m => m.Modules[i].Checked), Model.Modules[i].Checked, new { id = Html.FieldIdFor(x => x.Modules[i]) })
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Modules[i])">@Model.Modules[i].ModuleName</label>
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleId)
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleName)
|
||||
}
|
||||
</li>
|
||||
<li>
|
||||
@{
|
||||
var theme = Model.Modules[i];
|
||||
@Html.CheckBox(Html.FieldNameFor(m => m.Modules[i].Checked), Model.Modules[i].Checked, new { id = Html.FieldIdFor(x => x.Modules[i]) })
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Modules[i])">@Model.Modules[i].ModuleName</label>
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleId)
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleName)
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ol>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<button class="primaryAction" type="submit">@T("Save")</button>
|
||||
</fieldset>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
Layout.Title = T("Edit Tenant").ToString();
|
||||
|
||||
Script.Require("jQuery").AtFoot();
|
||||
Script.Include(Url.Content("~/Themes/TheAdmin/Scripts/admin.js")).AtFoot();
|
||||
Script.Require("ShapesBase").AtFoot();
|
||||
Script.Include(Url.Content("~/Themes/TheAdmin/Scripts/admin.js")).AtFoot();
|
||||
Script.Include("multi-tenancy.admin.js").AtFoot();
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<fieldset>
|
||||
<div>
|
||||
@@ -24,19 +25,19 @@
|
||||
<label for="@Html.FieldIdFor(m => m.RequestUrlPrefix)">@T("URL prefix")</label>
|
||||
@Html.TextBoxFor(m => m.RequestUrlPrefix, new { @class = "text medium" })
|
||||
<span class="hint">@T("(Optional) Example: If prefix is \"site1\", the tenant URL prefix is \"http://orchardproject.net/site1\"")</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>@T("Database Setup")</legend>
|
||||
@if (Model.State != TenantState.Uninitialized) {
|
||||
<div class="warning message">@T("Warning: If you don't know what you're doing you *will* (likely) send this tenant into a downward spiral of irrecoverable disrepair. Have a nice day.")</div>
|
||||
@if (Model.State != TenantState.Uninitialized) {
|
||||
<div class="message message-Warning">@T("Warning: If you don't know what you're doing you *will* (likely) send this tenant into a downward spiral of irrecoverable disrepair. Have a nice day.")</div>
|
||||
}
|
||||
else {
|
||||
<div>
|
||||
else {
|
||||
<div>
|
||||
@Html.RadioButtonFor(svm => svm.DataProvider, "", new { id = "tenantDatabaseOption" })
|
||||
<label for="tenantDatabaseOption" class="forcheckbox">@T("Allow the tenant to set up the database")</label>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div>
|
||||
@Html.RadioButtonFor(svm => svm.DataProvider, "SqlCe", new { id = "builtinDatabaseOption" })
|
||||
<label for="builtinDatabaseOption" class="forcheckbox">@T("Use built-in data storage (SQL Server Compact)")</label>
|
||||
@@ -44,23 +45,25 @@
|
||||
<div>
|
||||
@Html.RadioButtonFor(svm => svm.DataProvider, "SqlServer", new { id = "sqlDatabaseOption" })
|
||||
<label for="sqlDatabaseOption" class="forcheckbox">@T("Use an existing SQL Server (or SQL Express) database")</label>
|
||||
<span data-controllerid="sqlDatabaseOption">
|
||||
<label for="DatabaseConnectionString">@T("Connection string")</label>
|
||||
@Html.TextBoxFor(svm => svm.DatabaseConnectionString, new { @class = "text large" })
|
||||
<span class="hint">@T("Example:")<br />@T("Data Source=sqlServerName;Initial Catalog=dbName;Persist Security Info=True;User ID=userName;Password=password")</span>
|
||||
</span>
|
||||
<span data-controllerid="sqlDatabaseOption">
|
||||
<label for="DatabaseTablePrefix">@T("Database Table Prefix")</label>
|
||||
@Html.EditorFor(svm => svm.DatabaseTablePrefix)
|
||||
</span>
|
||||
<div class="options">
|
||||
<span data-controllerid="sqlDatabaseOption">
|
||||
<label for="DatabaseConnectionString">@T("Connection string")</label>
|
||||
@Html.TextBoxFor(svm => svm.DatabaseConnectionString)
|
||||
<span class="hint">@T("Example:") @T("Data Source=sqlServerName;Initial Catalog=dbName;Persist Security Info=True;User ID=userName;Password=password")</span>
|
||||
</span>
|
||||
<span data-controllerid="sqlDatabaseOption">
|
||||
<label for="DatabaseTablePrefix">@T("Database table prefix")</label>
|
||||
@Html.EditorFor(svm => svm.DatabaseTablePrefix)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Themes)">@T("Available Themes")</label>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Themes)">@T("Available Themes")</label>
|
||||
<div>
|
||||
<span class="hint">@T("Select the Themes which should be available for this tenant. If none is selected, they will all be available.")</span>
|
||||
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<input type="checkbox" class="select-all" id="select-all-themes" />
|
||||
@@ -80,11 +83,11 @@
|
||||
}
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Modules)">@T("Available Modules")</label>
|
||||
|
||||
<fieldset class="available-extensions">
|
||||
<label for="@Html.FieldIdFor(m => m.Modules)">@T("Available Modules")</label>
|
||||
<div>
|
||||
<span class="hint">@T("Select the Modules which should be available for this tenant. If none is selected, they will all be available.")</span>
|
||||
|
||||
@@ -95,21 +98,21 @@
|
||||
</li>
|
||||
|
||||
@for (var i = 0; i < Model.Modules.Count; i++) {
|
||||
<li>
|
||||
@{
|
||||
var theme = Model.Modules[i];
|
||||
@Html.CheckBox(Html.FieldNameFor(m => m.Modules[i].Checked), Model.Modules[i].Checked, new { id = Html.FieldIdFor(x => x.Modules[i]) })
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Modules[i])">@Model.Modules[i].ModuleName</label>
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleId)
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleName)
|
||||
}
|
||||
</li>
|
||||
<li>
|
||||
@{
|
||||
var theme = Model.Modules[i];
|
||||
@Html.CheckBox(Html.FieldNameFor(m => m.Modules[i].Checked), Model.Modules[i].Checked, new { id = Html.FieldIdFor(x => x.Modules[i]) })
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Modules[i])">@Model.Modules[i].ModuleName</label>
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleId)
|
||||
@Html.HiddenFor(m => m.Modules[i].ModuleName)
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ol>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<button class="primaryAction" type="submit">@T("Save")</button>
|
||||
</fieldset>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Orchard.Redis.Caching {
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
Database.KeyDeleteWithPrefix(GetLocalizedKey("*"));
|
||||
_connectionMultiplexer.KeyDeleteWithPrefix(GetLocalizedKey("*"));
|
||||
}
|
||||
|
||||
private string GetLocalizedKey(string key) {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace Orchard.Redis.Extensions {
|
||||
public static class RedisConnectionExtensions {
|
||||
public static void KeyDeleteWithPrefix(this IConnectionMultiplexer connection, string prefix) {
|
||||
var keys = GetKeys(connection, prefix);
|
||||
var database = connection.GetDatabase();
|
||||
database.KeyDelete(keys.Select(key => (RedisKey)key).ToArray());
|
||||
}
|
||||
|
||||
public static int KeyCount(this IConnectionMultiplexer connection, string prefix) {
|
||||
return GetKeys(connection, prefix).Count();
|
||||
}
|
||||
|
||||
// CYCLES EACH ENDPOINT FOR A CONNECTION SO KEYS ARE FETECHED IN A REDIS CLUSTER CONFIGURATION
|
||||
// STACKEXCHANGECLIENT .KEYS WILL PERFORM SCAN ON REDIS SERVERS THAT SUPPORT IT
|
||||
public static IEnumerable<string> GetKeys(this IConnectionMultiplexer connection, string prefix) {
|
||||
if (connection == null) {
|
||||
throw new ArgumentException("Connection cannot be null", "connection");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(prefix)) {
|
||||
throw new ArgumentException("Prefix cannot be empty", "database");
|
||||
}
|
||||
|
||||
var keys = new List<string>();
|
||||
var databaseId = connection.GetDatabase().Database;
|
||||
|
||||
foreach (var endPoint in connection.GetEndPoints()) {
|
||||
var server = connection.GetServer(endPoint);
|
||||
keys.AddRange(server.Keys(pattern: prefix, database: databaseId).Select(x => x.ToString()));
|
||||
}
|
||||
|
||||
return keys.Distinct();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace Orchard.Redis.Extensions {
|
||||
public static class RedisDatabaseExtensions {
|
||||
|
||||
public static void KeyDeleteWithPrefix(this IDatabase database, string prefix) {
|
||||
if (database == null) {
|
||||
throw new ArgumentException("Database cannot be null", "database");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(prefix)) {
|
||||
throw new ArgumentException("Prefix cannot be empty", "database");
|
||||
}
|
||||
|
||||
database.ScriptEvaluate(@"
|
||||
local keys = redis.call('keys', ARGV[1])
|
||||
for i=1,#keys,5000 do
|
||||
redis.call('del', unpack(keys, i, math.min(i+4999, #keys)))
|
||||
end", values: new RedisValue[] { prefix });
|
||||
}
|
||||
|
||||
public static int KeyCount(this IDatabase database, string prefix) {
|
||||
if (database == null) {
|
||||
throw new ArgumentException("Database cannot be null", "database");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(prefix)) {
|
||||
throw new ArgumentException("Prefix cannot be empty", "database");
|
||||
}
|
||||
|
||||
var retVal = database.ScriptEvaluate("return table.getn(redis.call('keys', ARGV[1]))", values: new RedisValue[] { prefix });
|
||||
|
||||
if (retVal.IsNull) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Caching\RedisCacheStorageProvider.cs" />
|
||||
<Compile Include="Extensions\RedisDatabaseExtensions.cs" />
|
||||
<Compile Include="Extensions\RedisConnectionExtensions.cs" />
|
||||
<Compile Include="Configuration\IRedisConnectionProvider.cs" />
|
||||
<Compile Include="Configuration\RedisConnectionProvider.cs" />
|
||||
<Compile Include="MessageBus\RedisMessageBusBroker.cs" />
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Orchard.Redis.OutputCache {
|
||||
}
|
||||
|
||||
public void Set(string key, CacheItem cacheItem) {
|
||||
if(cacheItem == null) {
|
||||
if (cacheItem == null) {
|
||||
throw new ArgumentNullException("cacheItem");
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Orchard.Redis.OutputCache {
|
||||
}
|
||||
|
||||
public void RemoveAll() {
|
||||
Database.KeyDeleteWithPrefix(GetLocalizedKey("*"));
|
||||
Database.KeyDelete(GetPrefixedKeys().Select(key => (RedisKey)key).ToArray());
|
||||
}
|
||||
|
||||
public CacheItem GetCacheItem(string key) {
|
||||
@@ -85,11 +85,11 @@ namespace Orchard.Redis.OutputCache {
|
||||
}
|
||||
|
||||
using (var compressedStream = new MemoryStream(value)) {
|
||||
if(compressedStream.Length == 0) {
|
||||
if (compressedStream.Length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
using(var decompressedStream = Decompress(compressedStream)) {
|
||||
using (var decompressedStream = Decompress(compressedStream)) {
|
||||
return Deserialize(decompressedStream);
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ namespace Orchard.Redis.OutputCache {
|
||||
}
|
||||
|
||||
public int GetCacheItemsCount() {
|
||||
return Database.KeyCount(GetLocalizedKey("*"));
|
||||
return GetPrefixedKeys().Count();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -123,19 +123,19 @@ namespace Orchard.Redis.OutputCache {
|
||||
/// </summary>
|
||||
/// <returns>The keys for the current tenant.</returns>
|
||||
private IEnumerable<string> GetAllKeys() {
|
||||
var prefix = GetLocalizedKey("");
|
||||
return GetPrefixedKeys().Select(x => x.Substring(prefix.Length));
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetPrefixedKeys() {
|
||||
// prevent the same request from computing the list twice (count + list)
|
||||
if (_keysCache == null) {
|
||||
_keysCache = new HashSet<string>();
|
||||
var prefix = GetLocalizedKey("");
|
||||
|
||||
foreach (var endPoint in _connectionMultiplexer.GetEndPoints()) {
|
||||
var server = _connectionMultiplexer.GetServer(endPoint);
|
||||
foreach (var key in server.Keys(pattern: GetLocalizedKey("*"))) {
|
||||
_keysCache.Add(key.ToString().Substring(prefix.Length));
|
||||
}
|
||||
var keys = _connectionMultiplexer.GetKeys(GetLocalizedKey("*"));
|
||||
foreach (var key in keys) {
|
||||
_keysCache.Add(key);
|
||||
}
|
||||
}
|
||||
|
||||
return _keysCache;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,11 +68,7 @@ namespace Orchard.Search {
|
||||
}
|
||||
|
||||
public int Create() {
|
||||
|
||||
_indexManager.GetSearchIndexProvider().CreateIndex("Admin");
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Page", cfg => cfg.WithSetting("TypeIndexing.Indexes", "Page:latest"));
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
@{
|
||||
Script.Require("SelectableContentTab");
|
||||
|
||||
var pageTitle = T("Search Content");
|
||||
Layout.Title = pageTitle;
|
||||
}
|
||||
@@ -11,10 +13,18 @@
|
||||
<button type="submit">@T("Search")</button>
|
||||
</fieldset>
|
||||
|
||||
if (Model.ContentItems.Items.Count > 0)
|
||||
{
|
||||
<label for="selectAll">@T("Select All")</label>
|
||||
<input name="selectAll" type="checkbox" class="content-picker-SelectAll" />
|
||||
}
|
||||
<fieldset class="contentItems bulk-items">
|
||||
@Display(Model.ContentItems)
|
||||
@Display(Model.ContentItems)
|
||||
</fieldset>
|
||||
|
||||
if (Model.ContentItems.Items.Count > 0)
|
||||
{
|
||||
@Html.Link(T("Add Selected").Text, "#", new { @class = "button addSelected"})
|
||||
}
|
||||
@Display(Model.Pager)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,28 +58,7 @@ namespace Orchard.Taxonomies.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ContentPart part, TaxonomyField field, dynamic shapeHelper) {
|
||||
return ContentShape("Fields_TaxonomyField_Edit", GetDifferentiator(field, part), () => {
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<TaxonomyFieldSettings>();
|
||||
var appliedTerms = GetAppliedTerms(part, field, VersionOptions.Latest).ToDictionary(t => t.Id, t => t);
|
||||
var taxonomy = _taxonomyService.GetTaxonomyByName(settings.Taxonomy);
|
||||
var terms = taxonomy != null
|
||||
? _taxonomyService.GetTerms(taxonomy.Id).Where(t => !string.IsNullOrWhiteSpace(t.Name)).Select(t => t.CreateTermEntry()).ToList()
|
||||
: new List<TermEntry>(0);
|
||||
|
||||
terms.ForEach(t => t.IsChecked = appliedTerms.ContainsKey(t.Id));
|
||||
|
||||
var viewModel = new TaxonomyFieldViewModel {
|
||||
DisplayName = field.DisplayName,
|
||||
Name = field.Name,
|
||||
Terms = terms,
|
||||
Settings = settings,
|
||||
SingleTermId = terms.Where(t => t.IsChecked).Select(t => t.Id).FirstOrDefault(),
|
||||
TaxonomyId = taxonomy != null ? taxonomy.Id : 0
|
||||
};
|
||||
|
||||
var templateName = settings.Autocomplete ? "Fields/TaxonomyField.Autocomplete" : "Fields/TaxonomyField";
|
||||
return shapeHelper.EditorTemplate(TemplateName: templateName, Model: viewModel, Prefix: GetPrefix(field, part));
|
||||
});
|
||||
return BuildEditorShape(part, field, shapeHelper);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ContentPart part, TaxonomyField field, IUpdateModel updater, dynamic shapeHelper) {
|
||||
@@ -103,7 +82,38 @@ namespace Orchard.Taxonomies.Drivers {
|
||||
_taxonomyService.UpdateTerms(part.ContentItem, checkedTerms, field.Name);
|
||||
}
|
||||
|
||||
return Editor(part, field, shapeHelper);
|
||||
return BuildEditorShape(part, field, shapeHelper, viewModel);
|
||||
}
|
||||
|
||||
private ContentShapeResult BuildEditorShape(ContentPart part, TaxonomyField field, dynamic shapeHelper, TaxonomyFieldViewModel appliedViewModel = null) {
|
||||
return ContentShape("Fields_TaxonomyField_Edit", GetDifferentiator(field, part), () => {
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<TaxonomyFieldSettings>();
|
||||
var taxonomy = _taxonomyService.GetTaxonomyByName(settings.Taxonomy);
|
||||
var terms = taxonomy != null
|
||||
? _taxonomyService.GetTerms(taxonomy.Id).Where(t => !string.IsNullOrWhiteSpace(t.Name)).Select(t => t.CreateTermEntry()).ToList()
|
||||
: new List<TermEntry>(0);
|
||||
|
||||
// Ensure the modified taxonomy items are not lost if a model validation error occurs
|
||||
if (appliedViewModel != null) {
|
||||
terms.ForEach(t => t.IsChecked = appliedViewModel.Terms.Any(at => at.Id == t.Id && at.IsChecked) || t.Id == appliedViewModel.SingleTermId);
|
||||
}
|
||||
else {
|
||||
var appliedTerms = GetAppliedTerms(part, field, VersionOptions.Latest).ToDictionary(t => t.Id, t => t);
|
||||
terms.ForEach(t => t.IsChecked = appliedTerms.ContainsKey(t.Id));
|
||||
}
|
||||
|
||||
var viewModel = new TaxonomyFieldViewModel {
|
||||
DisplayName = field.DisplayName,
|
||||
Name = field.Name,
|
||||
Terms = terms,
|
||||
Settings = settings,
|
||||
SingleTermId = terms.Where(t => t.IsChecked).Select(t => t.Id).FirstOrDefault(),
|
||||
TaxonomyId = taxonomy != null ? taxonomy.Id : 0
|
||||
};
|
||||
|
||||
var templateName = settings.Autocomplete ? "Fields/TaxonomyField.Autocomplete" : "Fields/TaxonomyField";
|
||||
return shapeHelper.EditorTemplate(TemplateName: templateName, Model: viewModel, Prefix: GetPrefix(field, part));
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Exporting(ContentPart part, TaxonomyField field, ExportContentContext context) {
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace Orchard.Taxonomies.Handlers {
|
||||
public class TermsPartHandler : ContentHandler {
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
private readonly HashSet<int> _processedTermParts = new HashSet<int>();
|
||||
|
||||
public TermsPartHandler(
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
@@ -88,12 +90,17 @@ namespace Orchard.Taxonomies.Handlers {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Fires off a processing engine task to run the count processing after the request so it's non-blocking.
|
||||
// Fires off a processing engine task to run the count processing after the request so it's non-blocking.
|
||||
private void RecalculateCount(IProcessingEngine processingEngine, ShellSettings shellSettings, IShellDescriptorManager shellDescriptorManager, TermsPart part) {
|
||||
var termPartRecordIds = part.Terms.Select(t => t.TermRecord.Id).ToArray();
|
||||
processingEngine.AddTask(shellSettings, shellDescriptorManager.GetShellDescriptor(), "ITermCountProcessor.Process", new Dictionary<string, object> { { "termPartRecordIds", termPartRecordIds } });
|
||||
|
||||
if (termPartRecordIds.Any()) {
|
||||
if (!_processedTermParts.Any()) {
|
||||
processingEngine.AddTask(shellSettings, shellDescriptorManager.GetShellDescriptor(), "ITermCountProcessor.Process", new Dictionary<string, object> { { "termPartRecordIds", _processedTermParts } });
|
||||
}
|
||||
foreach (var termPartRecordId in termPartRecordIds) {
|
||||
_processedTermParts.Add(termPartRecordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Activating(ActivatingContentContext context) {
|
||||
@@ -113,4 +120,4 @@ namespace Orchard.Taxonomies.Handlers {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@ using Orchard.Events;
|
||||
|
||||
namespace Orchard.Taxonomies.Services {
|
||||
public interface ITermCountProcessor : IEventHandler {
|
||||
void Process(params int[] termPartRecordIds);
|
||||
void Process(IEnumerable<int> termPartRecordIds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Orchard.Taxonomies.Services {
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private readonly IShellDescriptorManager _shellDescriptorManager;
|
||||
|
||||
private readonly HashSet<int> _processedTermParts = new HashSet<int>();
|
||||
|
||||
public TaxonomyService(
|
||||
IRepository<TermContentItem> termContentItemRepository,
|
||||
@@ -266,9 +267,14 @@ namespace Orchard.Taxonomies.Services {
|
||||
}
|
||||
|
||||
var termPartRecordIds = termList.Select(t => t.Term.TermRecord.Id).ToArray();
|
||||
_processingEngine.AddTask(_shellSettings, _shellDescriptorManager.GetShellDescriptor(), "ITermCountProcessor.Process", new Dictionary<string, object> { { "termPartRecordIds", termPartRecordIds } });
|
||||
|
||||
|
||||
if (termPartRecordIds.Any()) {
|
||||
if (!_processedTermParts.Any()) {
|
||||
_processingEngine.AddTask(_shellSettings, _shellDescriptorManager.GetShellDescriptor(), "ITermCountProcessor.Process", new Dictionary<string, object> { { "termPartRecordIds", _processedTermParts } });
|
||||
}
|
||||
foreach (var termPartRecordId in termPartRecordIds) {
|
||||
_processedTermParts.Add(termPartRecordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IContentQuery<TermsPart, TermsPartRecord> GetContentItemsQuery(TermPart term, string fieldName = null) {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Taxonomies.Models;
|
||||
|
||||
@@ -9,20 +13,31 @@ namespace Orchard.Taxonomies.Services {
|
||||
_taxonomyService = taxonomyService;
|
||||
}
|
||||
|
||||
public void Process(params int[] termPartRecordIds) {
|
||||
|
||||
public void Process(IEnumerable<int> termPartRecordIds)
|
||||
{
|
||||
var processedTermPartRecordIds = new List<int>();
|
||||
foreach (var id in termPartRecordIds) {
|
||||
var termPart = _taxonomyService.GetTerm(id);
|
||||
while (termPart != null) {
|
||||
termPart.Count = (int)_taxonomyService.GetContentItemsCount(termPart);
|
||||
|
||||
// compute count for the hierarchy too
|
||||
if (termPart.Container != null) {
|
||||
var parentTerm = termPart.Container.As<TermPart>();
|
||||
termPart = parentTerm;
|
||||
if (!processedTermPartRecordIds.Contains(id)) {
|
||||
var termPart = _taxonomyService.GetTerm(id);
|
||||
if (termPart != null) {
|
||||
ProcessTerm(termPart, processedTermPartRecordIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessTerm(TermPart termPart, ICollection<int> processedTermPartRecordIds)
|
||||
{
|
||||
termPart.Count = (int)_taxonomyService.GetContentItemsCount(termPart);
|
||||
processedTermPartRecordIds.Add(termPart.Id);
|
||||
|
||||
// Look for a parent term that has not yet been processed
|
||||
if (termPart.Container != null) {
|
||||
var parentTerm = termPart.Container.As<TermPart>();
|
||||
if (parentTerm != null && !processedTermPartRecordIds.Contains(parentTerm.Id)) {
|
||||
ProcessTerm(parentTerm, processedTermPartRecordIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31BF3856AD364E35" culture="neutral"/>
|
||||
|
||||
Reference in New Issue
Block a user