--HG--
branch : dev
This commit is contained in:
Suha Can
2010-06-09 11:49:16 -07:00
239 changed files with 5857 additions and 1099 deletions

View File

@@ -1,5 +1,6 @@
using System.Linq;
using Orchard.Blogs.Services;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Blogs {
@@ -10,10 +11,12 @@ namespace Orchard.Blogs {
_blogService = blogService;
}
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Blogs", "2", BuildMenu);
builder.Add(T("Blogs"), "2", BuildMenu);
}
private void BuildMenu(NavigationItemBuilder menu) {
@@ -22,20 +25,20 @@ namespace Orchard.Blogs {
var singleBlog = blogCount == 1 ? blogs.ElementAt(0) : null;
if (blogCount > 0 && singleBlog == null)
menu.Add("Manage Blogs", "1.0",
menu.Add(T("Manage Blogs"), "1.0",
item =>
item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs));
else if (singleBlog != null)
menu.Add("Manage Blog", "1.0",
menu.Add(T("Manage Blog"), "1.0",
item =>
item.Action("Item", "BlogAdmin", new {area = "Orchard.Blogs", blogSlug = singleBlog.Slug}).Permission(Permissions.MetaListBlogs));
menu.Add("Add New Blog", "1.1",
menu.Add(T("Add New Blog"), "1.1",
item =>
item.Action("Create", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.ManageBlogs));
if (singleBlog != null)
menu.Add("Add New Post", "1.2",
menu.Add(T("Add New Post"), "1.2",
item =>
item.Action("Create", "BlogPostAdmin", new {area = "Orchard.Blogs", blogSlug = singleBlog.Slug}).Permission(Permissions.PublishBlogPost));
}

View File

@@ -0,0 +1,128 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using Orchard.Blogs.Models;
using Orchard.Commands;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Common.Models;
using Orchard.Core.Navigation.Models;
using Orchard.Security;
using System.IO;
using Orchard.Blogs.Services;
using Orchard.Core.Navigation.Services;
namespace Orchard.Blogs.Commands {
public class BlogCommands : DefaultOrchardCommandHandler {
private readonly IContentManager _contentManager;
private readonly IMembershipService _membershipService;
private readonly IBlogService _blogService;
private readonly IMenuService _menuService;
public BlogCommands(
IContentManager contentManager,
IMembershipService membershipService,
IBlogService blogService,
IMenuService menuService) {
_contentManager = contentManager;
_membershipService = membershipService;
_blogService = blogService;
_menuService = menuService;
}
[OrchardSwitch]
public string FeedUrl { get; set; }
[OrchardSwitch]
public string Slug { get; set; }
[OrchardSwitch]
public string Title { get; set; }
[OrchardSwitch]
public string MenuText { get; set; }
[CommandName("blog create")]
[CommandHelp("blog create /Slug:<slug> /Title:<title> [/MenuText:<menu text>]\r\n\t" + "Creates a new Blog")]
[OrchardSwitches("Slug,Title,MenuText")]
public string Create() {
var admin = _membershipService.GetUser("admin");
if(!IsSlugValid(Slug)) {
return "Invalid Slug provided. Blog creation failed.";
}
var blog = _contentManager.New("blog");
blog.As<ICommonAspect>().Owner = admin;
blog.As<RoutableAspect>().Slug = Slug;
blog.As<RoutableAspect>().Title = Title;
if ( !String.IsNullOrWhiteSpace(MenuText) ) {
blog.As<MenuPart>().OnMainMenu = true;
blog.As<MenuPart>().MenuPosition = _menuService.Get().Select(menuPart => menuPart.MenuPosition).Max() + 1 + ".0";
blog.As<MenuPart>().MenuText = MenuText;
}
_contentManager.Create(blog);
return "Blog created successfully";
}
[CommandName("blog import")]
[CommandHelp("blog import /Slug:<slug> /FeedUrl:<feed url>\r\n\t" + "Import all items from <feed url> into the blog at the specified <slug>")]
[OrchardSwitches("FeedUrl,Slug")]
public string Import() {
var admin = _membershipService.GetUser("admin");
XDocument doc;
try {
Context.Output.WriteLine("Loading feed...");
doc = XDocument.Load(FeedUrl);
Context.Output.WriteLine("Found {0} items", doc.Descendants("item").Count());
}
catch ( Exception ex ) {
Context.Output.WriteLine(T("An error occured while loading the file: " + ex.Message));
return "Import terminated.";
}
var blog = _blogService.Get(Slug);
if ( blog == null ) {
return "Blog not found at specified slug: " + Slug;
}
foreach ( var item in doc.Descendants("item") ) {
string postName = item.Element("title").Value;
Context.Output.WriteLine("Adding post: {0}...", postName.Substring(0, Math.Min(postName.Length, 40)));
var post = _contentManager.New("blogpost");
post.As<ICommonAspect>().Owner = admin;
post.As<ICommonAspect>().Container = blog;
post.As<RoutableAspect>().Slug = Slugify(postName);
post.As<RoutableAspect>().Title = postName;
post.As<BodyAspect>().Text = item.Element("description").Value;
_contentManager.Create(post);
}
return "Import feed completed.";
}
private static string Slugify(string slug) {
var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s]+");
slug = dissallowed.Replace(slug, "-");
slug = slug.Trim('-');
if ( slug.Length > 1000 )
slug = slug.Substring(0, 1000);
return slug.ToLowerInvariant();
}
private static bool IsSlugValid(string slug) {
// see http://tools.ietf.org/html/rfc3987 for prohibited chars
return slug == null || String.IsNullOrEmpty(slug.Trim()) || Regex.IsMatch(slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$");
}
}
}

View File

@@ -9,6 +9,7 @@ namespace Orchard.Blogs.Models {
public string Name {
get { return this.As<RoutableAspect>().Title; }
set { this.As<RoutableAspect>().Title = value; }
}
//TODO: (erikpo) Need a data type for slug

View File

@@ -66,6 +66,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Commands\BlogCommands.cs" />
<Compile Include="Controllers\BlogAdminController.cs" />
<Compile Include="Drivers\BlogDriver.cs" />
<Compile Include="Controllers\BlogPostAdminController.cs" />
@@ -122,6 +123,7 @@
<Content Include="Scripts\jquery.ui.widget.js" />
<Content Include="Scripts\jquery.utils.js" />
<Content Include="Scripts\ui.timepickr.js" />
<Content Include="Styles\admin.css" />
<Content Include="Styles\archives.css" />
<Content Include="Styles\datetime.css" />
<Content Include="Styles\images\ui-bg_flat_0_aaaaaa_40x100.png" />

View File

@@ -0,0 +1,3 @@
.blogdescription {
margin-top:1em;
}

View File

@@ -2,8 +2,8 @@
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
<%@ Import Namespace="Orchard.Blogs.Models"%>
<h1 class="withActions">
<a href="<%=Url.BlogForAdmin(Model.Item.Slug) %>"><%: Html.TitleForPage(Model.Item.Name) %></a>
<h1><a href="<%=Url.BlogForAdmin(Model.Item.Slug) %>"><%: Html.TitleForPage(Model.Item.Name) %></a>
</h1>
<% Html.Zone("manage"); %><%--
<form>

View File

@@ -9,7 +9,7 @@
<a href="<%=Url.BlogPostCreate(Model.Item) %>" title="<%: T("New Post") %>"><%: T("New Post") %></a><%: T(" | ")%>
<a href="<%=Url.BlogEdit(Model.Item.Slug) %>" title="<%: T("Settings") %>"><%: T("Settings") %></a><%: T(" | ")%>
<%-- todo: (heskew) this is waaaaa too verbose. need template helpers for all ibuttons --%>
<% using (Html.BeginFormAntiForgeryPost(Url.BlogDelete(Model.Item.Slug), FormMethod.Post, new { @class = "inline" })) { %>
<% using (Html.BeginFormAntiForgeryPost(Url.BlogDelete(Model.Item.Slug), FormMethod.Post, new { @class = "inline link" })) { %>
<button type="submit" class="linkButton" title="<%: T("Remove") %>"><%: T("Remove") %></button><%
} %>
</div>

View File

@@ -2,6 +2,7 @@
<%@ Import Namespace="Orchard.Blogs"%>
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
<%@ Import Namespace="Orchard.Blogs.Models"%><%
Html.RegisterStyle("admin.css");
if (AuthorizedFor(Permissions.ManageBlogs)) { %>
<div class="folderProperties">
<p><a href="<%=Url.BlogEdit(Model.Slug) %>" class="edit"><%: T("Edit") %></a></p>

View File

@@ -1,13 +1,16 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Comments {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Comments", "3",
builder.Add(T("Comments"), "3",
menu => menu
.Add("Manage Comments", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" }).Permission(Permissions.ManageComments))
.Add(T("Manage Comments"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" }).Permission(Permissions.ManageComments))
);
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using System.Xml.Linq;
using Orchard.ContentManagement.MetaData;
using Orchard.DevTools.ViewModels;
namespace Orchard.DevTools.Controllers {
[ValidateInput(false)]
public class MetadataController : Controller {
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IContentDefinitionWriter _contentDefinitionWriter;
private readonly IContentDefinitionReader _contentDefinitionReader;
public MetadataController(
IContentDefinitionManager contentDefinitionManager,
IContentDefinitionWriter contentDefinitionWriter,
IContentDefinitionReader contentDefinitionReader) {
_contentDefinitionManager = contentDefinitionManager;
_contentDefinitionWriter = contentDefinitionWriter;
_contentDefinitionReader = contentDefinitionReader;
}
public ActionResult Index() {
var model = new MetadataIndexViewModel {
TypeDefinitions = _contentDefinitionManager.ListTypeDefinitions(),
PartDefinitions = _contentDefinitionManager.ListPartDefinitions()
};
var types = new XElement("Types");
foreach (var type in model.TypeDefinitions) {
types.Add(_contentDefinitionWriter.Export(type));
}
var parts = new XElement("Parts");
foreach (var part in model.PartDefinitions) {
parts.Add(_contentDefinitionWriter.Export(part));
}
var stringWriter = new StringWriter();
using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true, IndentChars = " " })) {
if (xmlWriter != null) {
new XElement("Orchard", types, parts).WriteTo(xmlWriter);
}
}
model.ExportText = stringWriter.ToString();
return View(model);
}
[HttpPost]
public ActionResult Index(MetadataIndexViewModel model) {
var root = XElement.Parse(model.ExportText);
foreach (var element in root.Elements("Types").Elements()) {
var typeElement = element;
var typeName = XmlConvert.DecodeName(element.Name.LocalName);
_contentDefinitionManager.AlterTypeDefinition(typeName, alteration => _contentDefinitionReader.Merge(typeElement, alteration));
}
return RedirectToAction("Index");
}
}
}

View File

@@ -73,6 +73,7 @@
<Compile Include="Commands\ProfilingCommands.cs" />
<Compile Include="Controllers\ContentController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\MetadataController.cs" />
<Compile Include="Handlers\DebugLinkHandler.cs" />
<Compile Include="Models\ShowDebugLink.cs" />
<Compile Include="Models\Simple.cs" />
@@ -80,6 +81,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\ContentIndexViewModel.cs" />
<Compile Include="ViewModels\ContentDetailsViewModel.cs" />
<Compile Include="ViewModels\MetadataIndexViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
@@ -90,6 +92,7 @@
<Content Include="Views\Home\Index.aspx" />
<Content Include="Views\DisplayTemplates\Parts\DevTools.ShowDebugLink.ascx" />
<Content Include="Views\EditorTemplates\Parts\DevTools.ShowDebugLink.ascx" />
<Content Include="Views\Metadata\Index.aspx" />
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
</ItemGroup>

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Mvc.ViewModels;
namespace Orchard.DevTools.ViewModels {
public class MetadataIndexViewModel : BaseViewModel {
public IEnumerable<ContentTypeDefinition> TypeDefinitions { get; set; }
public IEnumerable<ContentPartDefinition> PartDefinitions { get; set; }
public string ExportText { get; set; }
}
}

View File

@@ -2,4 +2,7 @@
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
<h1><%: Html.TitleForPage(T("Dev Tools").ToString()) %></h1>
<p><%: Html.ActionLink(T("Contents").ToString(), "Index", "Content") %></p>
<p><%: Html.ActionLink(T("Metadata").ToString(), "Index", "Metadata") %></p>
<p><%: Html.ActionLink(T("Test Unauthorized Request").ToString(), "NotAuthorized", "Home")%></p>

View File

@@ -0,0 +1,44 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<MetadataIndexViewModel>" %>
<%@ Import Namespace="Orchard.DevTools.ViewModels" %>
<style title="text/css">
ul
{
margin-left: 12px;
}
</style>
<h1>
Metadata</h1>
<h2>
Content Type Definitions</h2>
<ul>
<%foreach (var type in Model.TypeDefinitions) {%>
<li>
<%:type.Name %>
<ul>
<%foreach (var part in type.Parts) {%>
<li>
<%:part.PartDefinition.Name %></li>
<%
}%>
</ul>
</li>
<%
}%>
</ul>
<h2>
Content Part Definitions</h2>
<ul>
<%foreach (var part in Model.PartDefinitions) {%>
<li>
<%:part.Name %></li>
<%
}%>
</ul>
<h2>
Exported as xml</h2>
<% using (Html.BeginFormAntiForgeryPost()) { %>
<%:Html.TextAreaFor(m=>m.ExportText, new{style="width:100%;height:640px;"}) %>
<br />
<input class="button primaryAction" type="submit" value="<%=_Encoded("Merge Changes") %>" />
<%} %>

View File

@@ -1,13 +1,16 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Media {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Media", "4",
builder.Add(T("Media"), "4",
menu => menu
.Add("Manage Media", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" }).Permission(Permissions.ManageMediaFiles))
.Add(T("Manage Media"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" }).Permission(Permissions.ManageMediaFiles))
);
}
}

View File

@@ -93,6 +93,7 @@
<ItemGroup>
<Content Include="Content\Admin\images\folder.gif" />
<Content Include="Module.txt" />
<Content Include="Styles\admin.css" />
<Content Include="Views\Admin\Add.aspx" />
<Content Include="Views\Admin\Create.aspx" />
<Content Include="Views\Admin\Edit.aspx" />

View File

@@ -0,0 +1,7 @@
.breadCrumbs, .folderProperties {
float:left;
margin:-2em 0 0;
}
.folderProperties {
float:right;
}

View File

@@ -2,6 +2,8 @@
<%@ Import Namespace="Orchard.Media.Helpers"%>
<%@ Import Namespace="Orchard.Media.Models"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%>
<%Html.RegisterStyle("admin.css"); %>
<h1><%: Html.TitleForPage(T("Add Media").ToString()) %></h1>
<div class="breadCrumbs">
<p><%: Html.ActionLink(T("Media Folders").ToString(), "Index") %> &#62;

View File

@@ -1,7 +1,8 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<MediaFolderCreateViewModel>" %>
<%@ Import Namespace="Orchard.Media.Helpers"%>
<%@ Import Namespace="Orchard.Media.Models"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%><%
Html.RegisterStyle("admin.css"); %>
<h1><%: Html.TitleForPage(T("Add a Folder").ToString()) %></h1>
<div class="breadCrumbs">
<p><%: Html.ActionLink(T("Media Folders").ToString(), "Index") %> &#62;

View File

@@ -1,7 +1,8 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<MediaFolderEditViewModel>" %>
<%@ Import Namespace="Orchard.Media.Models"%>
<%@ Import Namespace="Orchard.Media.Helpers"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%><%
Html.RegisterStyle("admin.css"); %>
<h1><%: Html.TitleForPage(T("Manage Folder").ToString())%></h1>

View File

@@ -1,7 +1,8 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<MediaItemEditViewModel>" %>
<%@ Import Namespace="Orchard.Media.Models"%>
<%@ Import Namespace="Orchard.Media.Helpers"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%><%
Html.RegisterStyle("admin.css"); %>
<h1><%: Html.TitleForPage(T("Edit Media - {0}", Model.Name).ToString())%></h1>
<div class="breadCrumbs">

View File

@@ -1,7 +1,8 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<MediaFolderEditPropertiesViewModel>" %>
<%@ Import Namespace="Orchard.Media.Helpers"%>
<%@ Import Namespace="Orchard.Media.Models"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%>
<%@ Import Namespace="Orchard.Media.ViewModels"%><%
Html.RegisterStyle("admin.css"); %>
<h1><%: Html.TitleForPage(T("Folder Properties").ToString())%></h1>
<div class="breadCrumbs">
<p><%: Html.ActionLink(T("Media Folders").ToString(), "Index")%> &#62;

View File

@@ -1,16 +1,18 @@

using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.MetaData {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder)
{
builder.Add("Content Types", "5",
builder.Add(T("Content Types"), "5",
menu => menu
.Add("Content Types", "1.0", item => item.Action("ContentTypeList", "MetaData", new { area = "Orchard.MetaData" }).Permission(Permissions.ManageMetaData))
.Add(T("Content Types"), "1.0", item => item.Action("ContentTypeList", "Admin", new { area = "Orchard.MetaData" }).Permission(Permissions.ManageMetaData))
);
}

View File

@@ -0,0 +1,82 @@
using System.Web.Mvc;
using Orchard.ContentManagement.MetaData;
using Orchard.Localization;
using Orchard.MetaData.ViewModels;
namespace Orchard.MetaData.Controllers {
public class AdminController : Controller {
private readonly IContentDefinitionManager _contentDefinitionManager;
public IOrchardServices Services { get; set; }
public AdminController(IOrchardServices services, IContentDefinitionManager contentDefinitionManager) {
_contentDefinitionManager = contentDefinitionManager;
Services = services;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
//
// GET: /ContentTypeList/
public ActionResult ContentTypeList(string id) {
if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData")))
return new HttpUnauthorizedResult();
var contentTypes = _contentDefinitionManager.ListTypeDefinitions();
var contentParts = _contentDefinitionManager.ListPartDefinitions();
var model = new ContentTypesIndexViewModel();
foreach (var contentType in contentTypes) {
var contentTypeEntry = new ContentTypeEntry { Name = contentType.Name, DisplayName = contentType.Name };
if (contentType.Name == id) {
foreach (var contentTypePartNameRecord in contentParts) {
var contentTypePartEntry = new ContentTypePartEntry { Name = contentTypePartNameRecord.Name };
foreach (var contentTypePartEntryTest in contentType.Parts) {
if (contentTypePartEntryTest.PartDefinition.Name == contentTypePartEntry.Name) {
contentTypePartEntry.Selected = true;
}
}
model.ContentTypeParts.Add(contentTypePartEntry);
}
model.SelectedContentType = contentTypeEntry;
}
model.ContentTypes.Add(contentTypeEntry);
}
return View(model);
}
//
// POST: /ContentTypeList/Save
[HttpPost]
public ActionResult Save(string id, FormCollection collection) {
if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData")))
return new HttpUnauthorizedResult();
var existingDefinition = _contentDefinitionManager.GetTypeDefinition(id);
_contentDefinitionManager.AlterTypeDefinition(id, alter => {
foreach(var part in existingDefinition.Parts) {
alter.RemovePart(part.PartDefinition.Name);
}
foreach (var formKey in collection.AllKeys) {
if (formKey.Contains("part_")) {
var partName = formKey.Replace("part_", "");
alter.WithPart(partName);
}
}
});
return RedirectToAction("ContentTypeList", new { id });
}
}
}

View File

@@ -1,84 +0,0 @@
using System.Web.Mvc;
using Orchard.ContentManagement.MetaData.Services;
using Orchard.Localization;
using Orchard.MetaData.ViewModels;
using Orchard.UI.Admin;
namespace Orchard.MetaData.Controllers
{
[Admin]
public class MetaDataController : Controller
{
private readonly IContentTypeService _contentTypeService;
public IOrchardServices Services { get; set; }
public MetaDataController(IOrchardServices services, IContentTypeService contentTypeService)
{
_contentTypeService = contentTypeService;
Services = services;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
//
// GET: /ContentTypeList/
public ActionResult ContentTypeList(string id) {
if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData")))
return new HttpUnauthorizedResult();
var contentTypes = _contentTypeService.GetContentTypes();
var contentTypePartNames = _contentTypeService.GetContentTypePartNames();
var model = new ContentTypesIndexViewModel();
foreach(var contentType in contentTypes) {
var contentTypeEntry = new ContentTypeEntry {Name = contentType.Name,DisplayName = contentType.Name};
if (contentType.Name==id) {
foreach(var contentTypePartNameRecord in contentTypePartNames) {
var contentTypePartEntry = new ContentTypePartEntry { Name = contentTypePartNameRecord.PartName };
foreach(var contentTypePartEntryTest in contentType.ContentParts) {
if (contentTypePartEntryTest.PartName.PartName==contentTypePartEntry.Name) {
contentTypePartEntry.Selected = true;
}
}
model.ContentTypeParts.Add(contentTypePartEntry);
}
model.SelectedContentType = contentTypeEntry;
}
model.ContentTypes.Add(contentTypeEntry);
}
return View(model);
}
//
// POST: /ContentTypeList/Save
[HttpPost]
public ActionResult Save(string id, FormCollection collection)
{
if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData")))
return new HttpUnauthorizedResult();
var contentTypeRecord = _contentTypeService.GetContentTypeRecord(id);
//using a while loop because we are removing items from the collection
while (contentTypeRecord.ContentParts.Count>0) {
_contentTypeService.UnMapContentTypeToContentPart(contentTypeRecord.Name, contentTypeRecord.ContentParts[0].PartName.PartName);
}
foreach(var formKey in collection.AllKeys) {
if (formKey.Contains("part_")) {
var partName = formKey.Replace("part_", "");
_contentTypeService.MapContentTypeToContentPart(contentTypeRecord.Name,partName);
}
}
return RedirectToAction("ContentTypeList", new { id });
}
}
}

View File

@@ -66,7 +66,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\MetaDataController.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\ContentTypesViewModel.cs" />
@@ -74,7 +74,7 @@
<ItemGroup>
<Content Include="Module.txt" />
<Content Include="Web.config" />
<Content Include="Views\MetaData\ContentTypeList.ascx" />
<Content Include="Views\Admin\ContentTypeList.ascx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">

View File

@@ -25,7 +25,7 @@
%>
<tr class="<%=contentTypeClass %>">
<td>
<%: Html.ActionLink(item.Name, "ContentTypeList", new {id=item.Name})%>
<%= Html.ActionLink(item.Name, "ContentTypeList", new {id=item.Name})%>
</td>
</tr>
@@ -60,7 +60,7 @@ using (Html.BeginFormAntiForgeryPost(Url.Action("Save",new {id=Model.SelectedCon
<input name="<%="part_" + item.Name%>" type="checkbox" /><%}%>
</td>
<td class="ContentTypePartListRowItem">
<%: item.Name %>
<%= Html.Encode(item.Name)%>
</td>
</tr>
@@ -68,7 +68,7 @@ using (Html.BeginFormAntiForgeryPost(Url.Action("Save",new {id=Model.SelectedCon
</table>
<p>
<input type="submit" value="<%: T("Save") %>" />
<input type="submit" value="<%=_Encoded("Save") %>" />
</p>
<% } %>
</div>

View File

@@ -1,15 +1,18 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Modules {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Features", "10",
builder.Add(T("Features"), "10",
menu => menu
.Add("Manage Features", "1.0", item => item.Action("Features", "Admin", new { area = "Orchard.Modules" })
.Add(T("Manage Features"), "1.0", item => item.Action("Features", "Admin", new { area = "Orchard.Modules" })
.Permission(Permissions.ManageFeatures))
.Add("Installed Modules", "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Modules" })
.Add(T("Installed Modules"), "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Modules" })
.Permission(Permissions.ManageModules)));
}
}

View File

@@ -1,6 +1,9 @@
#main .features h2 {
margin-top:0;
}
#main .features h3 {
padding:0;
}
.features.detail-view .category > ul {
border:1px solid #EAEAEA;
margin-bottom:2em;
@@ -11,6 +14,9 @@
}
.features.summary-view .feature {
border:1px solid #EAEAEA;
box-shadow: 0px 1px 2px #d6d6d6;
-moz-box-shadow: 0px 1px 2px #d6d6d6;
-webkit-box-shadow: 0px 1px 2px #d6d6d6;
display:block;
float:left;
height:5em;

View File

@@ -1,14 +1,17 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.MultiTenancy {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Tenants", "22",
builder.Add(T("Tenants"), "22",
menu => menu
.Add("Manage Tenants", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.MultiTenancy" }).Permission(Permissions.ManageTenants))
.Add("Add New Tenant", "1.1", item => item.Action("Add", "Admin", new { area = "Orchard.MultiTenancy" }).Permission(Permissions.ManageTenants)));
.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)));
}
}
}

View File

@@ -96,6 +96,7 @@
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

View File

@@ -1,4 +1,5 @@
using Orchard.Pages.Services;
using Orchard.Localization;
using Orchard.Pages.Services;
using Orchard.UI.Navigation;
namespace Orchard.Pages {
@@ -9,19 +10,21 @@ namespace Orchard.Pages {
_pageService = pageService;
}
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Pages", "1", BuildMenu);
builder.Add(T("Pages"), "1", BuildMenu);
}
private void BuildMenu(NavigationItemBuilder menu) {
if (_pageService.GetCount() > 0)
menu.Add("Manage Pages", "1.0",
menu.Add(T("Manage Pages"), "1.0",
item =>
item.Action("List", "Admin", new {area = "Orchard.Pages"}).Permission(Permissions.MetaListPages));
menu.Add("Add New Page", "1.1",
menu.Add(T("Add New Page"), "1.1",
item =>
item.Action("Create", "Admin", new {area = "Orchard.Pages"}).Permission(Permissions.EditPages));
}

View File

@@ -93,6 +93,7 @@
<Compile Include="ViewModels\PageViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Styles\admin.css" />
<Content Include="Content\Admin\images\draft.gif" />
<Content Include="Content\Admin\images\offline.gif" />
<Content Include="Content\Admin\images\online.gif" />

View File

@@ -0,0 +1,19 @@
.pageList {
margin:0;
padding:0;
/*background:#FFFFFF url(images/backgroundGradient.gif) repeat-x scroll left top;*/
}
.orchard-pages .contentItems {
margin:.5em 0 0;
padding:0;
}
.contentItems .properties ul {
margin:0.8em 0 0 2em;
}
.contentItems .properties ul li {
margin:0;
padding:0 0 .1em 0;
}
.properties h3 {
display:inline;
}

View File

@@ -3,8 +3,10 @@
<%@ Import Namespace="Orchard.ContentManagement"%>
<%@ Import Namespace="Orchard.Core.Common.Models"%>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<%@ Import Namespace="Orchard.Pages.ViewModels"%>
<h1><%: Html.TitleForPage(T("Manage Pages").ToString())%></h1>
<%@ Import Namespace="Orchard.Pages.ViewModels"%><%
Html.RegisterStyle("admin.css"); %>
<h1><%=Html.TitleForPage(T("Manage Pages").ToString())%></h1>
<%-- todo: Add helper text here when ready. <p><%: T("Possible text about setting up a page goes here.")%></p>--%>
<div class="manage"><%: Html.ActionLink(T("Add a page").ToString(), "Create", new { }, new { @class = "button primaryAction" })%></div><%
using (Html.BeginFormAntiForgeryPost()) { %>

View File

@@ -1,14 +1,16 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Roles {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Users", "5",
builder.Add(T("Users"), "5",
menu => menu
.Add("Manage Roles", "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Roles" }).Permission(Permissions.ManageRoles))
.Add("Add New Role", "2.1", item => item.Action("Create", "Admin", new { area = "Orchard.Roles" }).Permission(Permissions.ManageRoles)));
.Add(T("Manage Roles"), "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Roles" }).Permission(Permissions.ManageRoles))
.Add(T("Add New Role"), "2.1", item => item.Action("Create", "Admin", new { area = "Orchard.Roles" }).Permission(Permissions.ManageRoles)));
}
}
}

View File

@@ -1,12 +1,14 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Security;
namespace Orchard.Roles.Models {
public static class UserSimulation {
public static IUser Create(string role) {
var simulation = new ContentItemBuilder("user")
var simulationType = new ContentTypeDefinitionBuilder().Named("user").Build();
var simulation = new ContentItemBuilder(simulationType)
.Weld<SimulatedUser>()
.Weld<SimulatedUserRoles>()
.Build();

View File

@@ -0,0 +1,16 @@
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Search {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site"), "11",
menu => menu
.Add(T("Search Index"), "10.0", item => item.Action("Index", "Admin", new {area = "Orchard.Search"})
.Permission(Permissions.ManageSearchIndex)));
}
}
}

View File

@@ -0,0 +1,50 @@
using System.Web.Mvc;
using Orchard.Localization;
using Orchard.Search.Services;
using Orchard.Search.ViewModels;
using Orchard.UI.Notify;
namespace Orchard.Search.Controllers {
public class AdminController : Controller {
private readonly ISearchService _searchService;
public AdminController(ISearchService searchService, IOrchardServices services) {
_searchService = searchService;
Services = services;
T = NullLocalizer.Instance;
}
public IOrchardServices Services { get; private set; }
public Localizer T { get; set; }
public ActionResult Index() {
var viewModel = new SearchIndexViewModel {HasIndexToManage = _searchService.HasIndexToManage, IndexUpdatedUtc = _searchService.GetIndexUpdatedUtc()};
if (!viewModel.HasIndexToManage)
Services.Notifier.Information(T("There is not search index to manage for this site."));
return View(viewModel);
}
[HttpPost]
public ActionResult Update() {
if (!Services.Authorizer.Authorize(Permissions.ManageSearchIndex, T("Not allowed to manage the search index.")))
return new HttpUnauthorizedResult();
_searchService.UpdateIndex();
return RedirectToAction("Index");
}
[HttpPost]
public ActionResult Rebuild() {
if (!Services.Authorizer.Authorize(Permissions.ManageSearchIndex, T("Not allowed to manage the search index.")))
return new HttpUnauthorizedResult();
_searchService.RebuildIndex();
_searchService.UpdateIndex();
return RedirectToAction("Index");
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.Search.Services;
using Orchard.Search.ViewModels;
namespace Orchard.Search.Controllers {
[ValidateInput(false)]
public class SearchController : Controller {
private readonly ISearchService _searchService;
private readonly IContentManager _contentManager;
public SearchController(ISearchService searchService, IContentManager contentManager) {
_searchService = searchService;
_contentManager = contentManager;
}
public ActionResult Index(string q, int page = 1, int pageSize = 10) {
var searchViewModel = new SearchViewModel {
Query = q,
DefaultPageSize = 10, // <- yeah, I know :|
PageOfResults = _searchService.Query(q, page, pageSize, searchHit => new SearchResultViewModel {
Content = _contentManager.BuildDisplayModel(_contentManager.Get(searchHit.Id), "SummaryForSearch"),
SearchHit = searchHit
})
};
//todo: deal with page requests beyond result count
return View(searchViewModel);
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Web.Mvc;
using Orchard.Mvc.Filters;
using Orchard.Mvc.ViewModels;
using Orchard.Search.ViewModels;
namespace Orchard.Search.Filters {
public class SearchFilter : FilterProvider, IResultFilter {
public void OnResultExecuting(ResultExecutingContext filterContext) {
var viewModel = filterContext.Controller.ViewData.Model as BaseViewModel;
if (viewModel != null)
viewModel.Zones.AddRenderPartial("search", "SearchForm", viewModel is SearchViewModel ? viewModel : new SearchViewModel());
}
public void OnResultExecuted(ResultExecutedContext filterContext) {
}
}
}

View File

@@ -0,0 +1,11 @@
name: Search
antiforgery: enabled
author: The Orchard Team
website: http://orchardproject.net
version: 0.1
orchardversion: 0.1.2010.0312
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ut arcu turpis, et placerat nunc. Nunc sollicitudin iaculis est, in ultricies mi facilisis et. Aenean et tortor non metus adipiscing laoreet in a justo. Pellentesque faucibus nisl ac lectus mollis quis pellentesque tortor egestas. Curabitur vel velit semper nunc gravida scelerisque. Vivamus at tellus dolor, in ultrices quam posuere.
features:
Orchard.Search:
Description: Standard interface to Orchard's built-in search.
Category: Search

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{4BE4EB01-AC56-4048-924E-2CA77F509ABA}</ProjectGuid>
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Orchard.Search</RootNamespace>
<AssemblyName>Orchard.Search</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
</ItemGroup>
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\SearchController.cs" />
<Compile Include="Filters\SearchFilter.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Routes.cs" />
<Compile Include="Services\ISearchService.cs" />
<Compile Include="Services\SearchService.cs" />
<Compile Include="ViewModels\SearchIndexViewModel.cs" />
<Compile Include="ViewModels\SearchResultViewModel.cs" />
<Compile Include="ViewModels\SearchViewModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
<Content Include="Styles\admin.css" />
<Content Include="Styles\search.css" />
<Content Include="Views\Admin\Index.ascx" />
<Content Include="Views\SearchForm.ascx" />
<Content Include="Views\Search\Index.ascx" />
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Web.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- 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">
</Target> -->
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)" />
</Target>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>47866</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://orchard.codeplex.com</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using Orchard.Security.Permissions;
namespace Orchard.Search {
public class Permissions : IPermissionProvider {
public static readonly Permission ManageSearchIndex = new Permission { Description = "Manage Search Index", Name = "ManageSearchIndex" };
public string ModuleName {
get {
return "Search";
}
}
public IEnumerable<Permission> GetPermissions() {
return new Permission[] {
ManageSearchIndex,
};
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] {ManageSearchIndex}
},
};
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Orchard.Search")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Orchard.Search")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("fa37585c-b84e-4b5b-a7da-13692ff45a94")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Mvc.Routes;
namespace Orchard.Search {
public class Routes : IRouteProvider {
public void GetRoutes(ICollection<RouteDescriptor> routes) {
foreach (var routeDescriptor in GetRoutes())
routes.Add(routeDescriptor);
}
public IEnumerable<RouteDescriptor> GetRoutes() {
return new[] {
new RouteDescriptor {
Priority = 5,
Route = new Route(
"Search",
new RouteValueDictionary {
{"area", "Orchard.Search"},
{"controller", "search"},
{"action", "index"}
},
null,
new RouteValueDictionary {
{"area", "Orchard.Search"}
},
new MvcRouteHandler())
}
};
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using Orchard.Collections;
using Orchard.Indexing;
namespace Orchard.Search.Services {
public interface ISearchService : IDependency {
bool HasIndexToManage { get; }
IPageOfItems<T> Query<T>(string query, int skip, int? take, Func<ISearchHit, T> shapeResult);
void RebuildIndex();
void UpdateIndex();
DateTime GetIndexUpdatedUtc();
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Collections;
using Orchard.Indexing;
using Orchard.Localization;
using Orchard.Localization.Services;
using Orchard.UI.Notify;
using System.Web;
namespace Orchard.Search.Services
{
public class SearchService : ISearchService
{
private const string SearchIndexName = "Search";
private readonly IIndexManager _indexManager;
private readonly IEnumerable<IIndexNotifierHandler> _indexNotifierHandlers;
private readonly ICultureManager _cultureManager;
public SearchService(IOrchardServices services, IIndexManager indexManager, IEnumerable<IIndexNotifierHandler> indexNotifierHandlers, ICultureManager cultureManager) {
Services = services;
_indexManager = indexManager;
_indexNotifierHandlers = indexNotifierHandlers;
_cultureManager = cultureManager;
T = NullLocalizer.Instance;
}
public IOrchardServices Services { get; set; }
public Localizer T { get; set; }
public bool HasIndexToManage {
get { return _indexManager.HasIndexProvider(); }
}
IPageOfItems<T> ISearchService.Query<T>(string query, int page, int? pageSize, Func<ISearchHit, T> shapeResult) {
if (string.IsNullOrWhiteSpace(query) || !_indexManager.HasIndexProvider())
return null;
var searchBuilder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(SearchIndexName)
.WithField("title", query)
.WithField("body", query);
if(HttpContext.Current != null) {
searchBuilder.WithField("culture", _cultureManager.GetCurrentCulture(HttpContext.Current));
}
var totalCount = searchBuilder.Count();
if (pageSize != null)
searchBuilder = searchBuilder
.Slice((page > 0 ? page - 1 : 0) * (int)pageSize, (int)pageSize);
var pageOfItems = new PageOfItems<T>(searchBuilder.Search().Select(shapeResult)) {
PageNumber = page,
PageSize = pageSize != null ? (int) pageSize : totalCount,
TotalItemCount = totalCount
};
return pageOfItems;
}
void ISearchService.RebuildIndex() {
if (!_indexManager.HasIndexProvider()) {
Services.Notifier.Warning(T("There is no search index to rebuild."));
return;
}
var searchProvider = _indexManager.GetSearchIndexProvider();
if (searchProvider.Exists(SearchIndexName))
searchProvider.DeleteIndex(SearchIndexName);
searchProvider.CreateIndex(SearchIndexName); // or just reset the updated date and let the background process recreate the index
Services.Notifier.Information(T("The search index has been rebuilt."));
}
void ISearchService.UpdateIndex() {
foreach(var handler in _indexNotifierHandlers) {
handler.UpdateIndex(SearchIndexName);
}
Services.Notifier.Information(T("The search index has been updated."));
}
DateTime ISearchService.GetIndexUpdatedUtc() {
return !HasIndexToManage
? DateTime.MinValue
: _indexManager.GetSearchIndexProvider().GetLastIndexUtc(SearchIndexName);
}
}
}

View File

@@ -0,0 +1,3 @@
#main button {
display:block;
}

View File

@@ -0,0 +1,18 @@
form.search {
float:left;
}
form.search input {
display:inline;
width:20em;
}
.search-summary {
float:right;
font-style:italic;
margin-top:0;
}
.search-summary em {
font-weight:bold;
}
.search-results {
clear:both;
}

View File

@@ -0,0 +1,10 @@
using System;
using Orchard.Mvc.ViewModels;
namespace Orchard.Search.ViewModels {
public class SearchIndexViewModel : BaseViewModel {
public bool HasIndexToManage { get; set; }
//todo: hang the index updated date off here to show in the admin UI (e.g. -> index updated: June 4, 2010 [update index])
public DateTime IndexUpdatedUtc { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
using Orchard.Indexing;
using Orchard.Mvc.ViewModels;
namespace Orchard.Search.ViewModels {
public class SearchResultViewModel {
public ISearchHit SearchHit { get; set; }
public ContentItemViewModel Content { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using Orchard.Collections;
using Orchard.Mvc.ViewModels;
namespace Orchard.Search.ViewModels {
public class SearchViewModel : BaseViewModel {
public string Query { get; set; }
public int DefaultPageSize { get; set; }
public IPageOfItems<SearchResultViewModel> PageOfResults { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Search.ViewModels.SearchIndexViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.Html" %><%
Html.RegisterStyle("admin.css"); %>
<h1><%=Html.TitleForPage(T("Search Index Management").ToString()) %></h1><%
using (Html.BeginForm("update", "admin", FormMethod.Post, new {area = "Orchard.Search"})) { %>
<fieldset>
<p><%=T("The search index was last updated {0}. <button type=\"submit\" title=\"Update the search index.\" class=\"primaryAction\">Update</button>", Html.DateTimeRelative(Model.IndexUpdatedUtc))%></p>
<%=Html.AntiForgeryTokenOrchard() %>
</fieldset><%
}
using (Html.BeginForm("rebuild", "admin", FormMethod.Post, new {area = "Orchard.Search"})) { %>
<fieldset>
<p><%=T("Rebuild the search index for a fresh start. <button type=\"submit\" title=\"Rebuild the search index.\">Rebuild</button>") %></p>
<%=Html.AntiForgeryTokenOrchard() %>
</fieldset><%
} %>

View File

@@ -0,0 +1,17 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Search.ViewModels.SearchViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.Html" %><%
Html.RegisterStyle("search.css"); %>
<h1><%=Html.TitleForPage(T("Search").Text)%></h1><%
Html.Zone("search");
if (!string.IsNullOrWhiteSpace(Model.Query)) {
if (Model.PageOfResults.Count() == 0) { %>
<p class="search-summary"><%=T("<em>zero</em> results") %></p><%
}
else { %>
<p class="search-summary"><%=T("<em>{0} - {1}</em> of <em>{2}</em> results", Model.PageOfResults.StartPosition, Model.PageOfResults.EndPosition, Model.PageOfResults.TotalItemCount)%></p><%
}
}
if (Model.PageOfResults != null && Model.PageOfResults.Count() > 0) { %>
<%=Html.UnorderedList(Model.PageOfResults, (r, i) => Html.DisplayForItem(r.Content).ToHtmlString() , "search-results contentItems") %>
<%=Html.Pager(Model.PageOfResults, Model.PageOfResults.PageNumber, Model.DefaultPageSize, new {q = Model.Query}) %><%
} %>

View File

@@ -0,0 +1,8 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<SearchViewModel>" %>
<%@ Import Namespace="Orchard.Search.ViewModels" %><%
using(Html.BeginForm("index", "search", new { area = "Orchard.Search" }, FormMethod.Get, new { @class = "search" })) { %>
<fieldset>
<%=Html.TextBox("q", Model.Query) %>
<button type="submit"><%=T("Search") %></button>
</fieldset><%
} %>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
Enabling request validation in view pages would cause validation to occur
after the input has already been processed by the controller. By default
MVC performs request validation before a controller processes the input.
To change this behavior apply the ValidateInputAttribute to a
controller or action.
-->
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0"?>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>
<appSettings/>
<connectionStrings>
<add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="false" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<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"/></assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<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.Linq"/>
<add namespace="System.Collections.Generic"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet
Information Services 7.0. It is not necessary for previous version of IIS.
-->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
</modules>
<handlers>
<remove name="UrlRoutingHandler"/>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -3,6 +3,8 @@ using System.Linq;
using System.Web;
using Orchard.Comments.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Core.Common.Models;
using Orchard.Core.Navigation.Models;
using Orchard.Core.Settings.Models;
@@ -55,12 +57,14 @@ namespace Orchard.Setup.Services {
string[] hardcoded = {
"Orchard.Framework",
"Common",
"Contents",
"Dashboard",
"Feeds",
"HomePage",
"Navigation",
"Scheduling",
"Indexing",
"Localization",
"Settings",
"XmlRpc",
"Orchard.Users",
@@ -79,7 +83,7 @@ namespace Orchard.Setup.Services {
}
var shellSettings = new ShellSettings(_shellSettings);
if (string.IsNullOrEmpty(shellSettings.DataProvider)) {
shellSettings.DataProvider = context.DatabaseProvider;
shellSettings.DataConnectionString = context.DatabaseConnectionString;
@@ -144,6 +148,11 @@ namespace Orchard.Setup.Services {
//var hackInstallationGenerator = environment.Resolve<IHackInstallationGenerator>();
//hackInstallationGenerator.GenerateInstallEvents();
var contentDefinitionManager = environment.Resolve<IContentDefinitionManager>();
contentDefinitionManager.AlterTypeDefinition("blogpost", cfg => cfg.WithPart("HasComments").WithPart("HasTags").WithPart("Localized"));
contentDefinitionManager.AlterTypeDefinition("page", cfg => cfg.WithPart("HasComments").WithPart("HasTags").WithPart("Localized"));
contentDefinitionManager.AlterTypeDefinition("sandboxpage", cfg => cfg.WithPart("HasComments").WithPart("HasTags").WithPart("Localized"));
// create home page as a CMS page
var page = contentManager.Create("page", VersionOptions.Draft);
page.As<BodyAspect>().Text = "<p>Welcome to Orchard!</p><p>Congratulations, you've successfully set-up your Orchard site.</p><p>This is the home page of your new site. We've taken the liberty to write here about a few things you could look at next in order to get familiar with the application. Once you feel confident you don't need this anymore, just click <a href=\"Admin/Pages/Edit/3\">Edit</a> to go into edit mode and replace this with whatever you want on your home page to make it your own.</p><p>One thing you could do (but you don't have to) is go into <a href=\"Admin/Settings\">Manage Settings</a> (follow the <a href=\"Admin\">Admin</a> link and then look for it under \"Settings\" in the menu on the left) and check that everything is configured the way you want.</p><p>You probably want to make the site your own. One of the ways you can do that is by clicking <a href=\"Admin/Themes\">Manage Themes</a> in the admin menu. A theme is a packaged look and feel that affects the whole site.</p><p>Next, you can start playing with the content types that we installed. For example, go ahead and click <a href=\"Admin/Pages/Create\">Add New Page</a> in the admin menu and create an \"about\" page. Then, add it to the navigation menu by going to <a href=\"Admin/Navigation\">Manage Menu</a>. You can also click <a href=\"Admin/Blogs/Create\">Add New Blog</a> and start posting by clicking \"Add New Post\".</p><p>Finally, Orchard has been designed to be extended. It comes with a few built-in modules such as pages and blogs or themes. You can install new themes by going to <a href=\"Admin/Themes\">Manage Themes</a> and clicking <a href=\"Admin/Themes/Install\">Install a new Theme</a>. Like for themes, modules are created by other users of Orchard just like you so if you feel up to it, please <a href=\"http://www.orchardproject.net/\">consider participating</a>.</p><p>--The Orchard Crew</p>";
@@ -168,24 +177,6 @@ namespace Orchard.Setup.Services {
var authenticationService = environment.Resolve<IAuthenticationService>();
authenticationService.SignIn(user, true);
}
//Add ContentType mappings
var contentTypeService = environment.Resolve<IContentTypeService>();
//Add ContentTypePartNames to MetaData
contentTypeService.AddContentTypePartNameToMetaData("HasComments");
contentTypeService.AddContentTypePartNameToMetaData("HasTags");
//Add mappings from ContentTypes to ContentParts to MetaData
contentTypeService.MapContentTypeToContentPart("blogpost","HasComments");
contentTypeService.MapContentTypeToContentPart("page", "HasComments");
contentTypeService.MapContentTypeToContentPart("sandboxpage", "HasComments");
contentTypeService.MapContentTypeToContentPart("blogpost", "HasTags");
contentTypeService.MapContentTypeToContentPart("page", "HasTags");
contentTypeService.MapContentTypeToContentPart("sandboxpage", "HasTags");
}
catch {
environment.Resolve<ITransactionManager>().Cancel();

View File

@@ -7,6 +7,7 @@ using Orchard.Commands;
using Orchard.Commands.Builtin;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Data.Builders;
using Orchard.Environment.Extensions;
using Orchard.Localization;
@@ -90,7 +91,8 @@ namespace Orchard.Setup {
class SafeModeSiteService : ISiteService {
public ISite GetSiteSettings() {
var site = new ContentItemBuilder("site")
var siteType = new ContentTypeDefinitionBuilder().Named("site").Build();
var site = new ContentItemBuilder(siteType)
.Weld<SafeModeSite>()
.Build();

View File

@@ -1,13 +1,15 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Tags {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Tags", "3",
builder.Add(T("Tags"), "3",
menu => menu
.Add("Manage Tags", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Tags" }).Permission(Permissions.ManageTags))
.Add(T("Manage Tags"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Tags" }).Permission(Permissions.ManageTags))
);
}
}

View File

@@ -1,13 +1,15 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Themes {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Site", "11",
builder.Add(T("Site"), "11",
menu => menu
.Add("Manage Themes", "4.0", item => item.Action("Index", "Admin", new { area = "Orchard.Themes" })
.Add(T("Manage Themes"), "4.0", item => item.Action("Index", "Admin", new { area = "Orchard.Themes" })
.Permission(Permissions.ManageThemes).Permission(Permissions.ApplyTheme)));
}
}

View File

@@ -88,6 +88,7 @@
<ItemGroup>
<Content Include="Content\orchard.ico" />
<Content Include="Scripts\base.js" />
<Content Include="Styles\admin.css" />
<Content Include="Styles\Images\toolBarActiveButtonBackground.gif" />
<Content Include="Styles\Images\toolBarBackground.gif" />
<Content Include="Styles\Images\toolBarHoverButtonBackground.gif" />

View File

@@ -0,0 +1,38 @@
#main .templates p {
margin:0 0 .3em 0;
}
.templates li {
margin:.8em;
width:30%;
display: -moz-inline-stack;
display:inline-block;
vertical-align:top;
zoom:1;
*display: inline;
}
.templates .inline button {
font-size:1.2em;
}
.templates .wasFormInlineLink {
font-size:1.4em;
}
.templates p {
overflow:hidden;
}
.templates img, .themePreviewImage {
border:1px solid #e8e8e8;
height:200px;
margin:.27em 0 .93em 0;
display:block;
}
.previewImage {
border:1px solid #525e50;
height:50%;
width:50%;
}
.themes #main h2 {
margin:1em 0 0 0;
}
.themePreviewImage {
height:300px;
}

View File

@@ -1,6 +1,7 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ThemesIndexViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<%@ Import Namespace="Orchard.Themes.ViewModels"%>
<%@ Import Namespace="Orchard.Themes.ViewModels"%><%
Html.RegisterStyle("admin.css"); %>
<h1><%: Html.TitleForPage(T("Manage Themes").ToString()) %></h1>
<% if (Model.CurrentTheme == null) {
%><p><%: T("There is no current theme in the application. The built-in theme will be used.")

View File

@@ -1,14 +1,16 @@
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Users {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add("Users", "5",
builder.Add(T("Users"), "5",
menu => menu
.Add("Manage Users", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Users" }).Permission(Permissions.ManageUsers))
.Add("Add New User", "1.1", item => item.Action("Create", "Admin", new { area = "Orchard.Users" }).Permission(Permissions.ManageUsers)));
.Add(T("Manage Users"), "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Users" }).Permission(Permissions.ManageUsers))
.Add(T("Add New User"), "1.1", item => item.Action("Create", "Admin", new { area = "Orchard.Users" }).Permission(Permissions.ManageUsers)));
}
}
}

View File

@@ -10,6 +10,7 @@ using Orchard.Users.Services;
using Orchard.Users.ViewModels;
namespace Orchard.Users.Controllers {
[ValidateInput(false)]
public class AdminController : Controller, IUpdateModel {
private readonly IMembershipService _membershipService;
private readonly IUserService _userService;