diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index ef872853b..ab096c256 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using System.Web.Routing; @@ -102,44 +103,12 @@ namespace Orchard.Core.Contents.Controllers { var viewModel = new EditTypeViewModel(); TryUpdateModel(viewModel); - if (!ModelState.IsValid) { + if (!ModelState.IsValid) return EditType(id); - } - var contentTypeDefinitionParts = viewModel.Parts.Select( - p => new ContentTypeDefinition.Part( - new ContentPartDefinition( - p.PartDefinition.Name, - p.PartDefinition.Fields.Select( - f => new ContentPartDefinition.Field( - new ContentFieldDefinition(f.FieldDefinition.Name), - f.Name, - f.Settings - ) - ), - p.PartDefinition.Settings - ), - p.Settings - ) - ).ToList(); - - if (viewModel.Fields.Any()) { - var implicitContentTypeDefinitionPart = new ContentTypeDefinition.Part( - new ContentPartDefinition( - viewModel.Name, - viewModel.Fields.Select( - f => new ContentPartDefinition.Field( - new ContentFieldDefinition(f.FieldDefinition.Name), - f.Name, - f.Settings - ) - ), - null - ), - null - ); - contentTypeDefinitionParts.Add(implicitContentTypeDefinitionPart); - } + var contentTypeDefinitionParts = viewModel.Parts.Select(GenerateTypePart).ToList(); + if (viewModel.Fields.Any()) + contentTypeDefinitionParts.Add(GenerateTypePart(viewModel)); //todo: apply the changes along the lines of but definately not resembling // for now this _might_ just get a little messy -> @@ -151,11 +120,48 @@ namespace Orchard.Core.Contents.Controllers { viewModel.Settings ) ); - // little == lot return RedirectToAction("Index"); } + private static ContentTypeDefinition.Part GenerateTypePart(EditTypePartViewModel viewModel) { + return new ContentTypeDefinition.Part( + new ContentPartDefinition( + viewModel.PartDefinition.Name, + viewModel.PartDefinition.Fields.Select( + f => new ContentPartDefinition.Field( + new ContentFieldDefinition(f.FieldDefinition.Name), + f.Name, + f.Settings + ) + ), + viewModel.PartDefinition.Settings + ), + viewModel.Settings + ); + } + + private static ContentTypeDefinition.Part GenerateTypePart(EditTypeViewModel viewModel) { + return new ContentTypeDefinition.Part( + new ContentPartDefinition( + viewModel.Name, + viewModel.Fields.Select( + f => new ContentPartDefinition.Field( + new ContentFieldDefinition(f.FieldDefinition.Name), + f.Name, + f.Settings + ) + ), + null + ), + null + ); + } + + #endregion + + #region Parts + public ActionResult EditPart(string id) { if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a part."))) return new HttpUnauthorizedResult(); @@ -181,36 +187,101 @@ namespace Orchard.Core.Contents.Controllers { var viewModel = new EditPartViewModel(); TryUpdateModel(viewModel); - if (!ModelState.IsValid) { + if (!ModelState.IsValid) return EditPart(id); - } //todo: apply the changes along the lines of but definately not resembling // for now this _might_ just get a little messy -> - _contentDefinitionService.AlterPartDefinition( - new ContentPartDefinition( - viewModel.Name, - viewModel.Fields.Select( - f => new ContentPartDefinition.Field( - new ContentFieldDefinition(f.FieldDefinition.Name), - f.Name, - f.Settings - ) - ), - viewModel.Settings - ) - ); - // little == lot + _contentDefinitionService.AlterPartDefinition(GeneratePart(viewModel)); return RedirectToAction("Index"); } + public ActionResult AddFieldTo(string id) { + if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a part."))) + return new HttpUnauthorizedResult(); + + var contentPartDefinition = _contentDefinitionService.GetPartDefinition(id); + + if (contentPartDefinition == null) { + //id passed in might be that of a type w/ no implicit field + var contentTypeDefinition = _contentDefinitionService.GetTypeDefinition(id); + if (contentTypeDefinition != null) + contentPartDefinition = new ContentPartDefinition(id); + else + return new NotFoundResult(); + } + + var viewModel = new AddFieldViewModel { + Part = new EditPartViewModel(contentPartDefinition), + Fields = _contentDefinitionService.GetFieldDefinitions() + }; + + return View(viewModel); + } + + [HttpPost, ActionName("AddFieldTo")] + public ActionResult AddFieldToPOST(string id) { + if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a part."))) + return new HttpUnauthorizedResult(); + + var viewModel = new AddFieldViewModel(); + TryUpdateModel(viewModel); + + var contentPartDefinition = _contentDefinitionService.GetPartDefinition(id); + var contentTypeDefinition = _contentDefinitionService.GetTypeDefinition(id); + + if (!ModelState.IsValid) + return AddFieldTo(id); + + if (contentPartDefinition == null) { + //id passed in might be that of a type w/ no implicit field + if (contentTypeDefinition != null) { + contentPartDefinition = new ContentPartDefinition(id); + var contentTypeDefinitionParts = contentTypeDefinition.Parts.ToList(); + contentTypeDefinitionParts.Add(new ContentTypeDefinition.Part(contentPartDefinition, null)); + _contentDefinitionService.AlterTypeDefinition( + new ContentTypeDefinition( + contentTypeDefinition.Name, + contentTypeDefinition.DisplayName, + contentTypeDefinitionParts, + contentTypeDefinition.Settings + ) + ); + } + else { + return new NotFoundResult(); + } + } + + var contentPartFields = contentPartDefinition.Fields.ToList(); + contentPartFields.Add(new ContentPartDefinition.Field(new ContentFieldDefinition(viewModel.FieldTypeName), viewModel.DisplayName, null)); + _contentDefinitionService.AlterPartDefinition(new ContentPartDefinition(contentPartDefinition.Name, contentPartFields, contentPartDefinition.Settings)); + + if (contentTypeDefinition != null) + return RedirectToAction("EditType", new { id }); + + return RedirectToAction("EditPart", new {id}); + } + + private static ContentPartDefinition GeneratePart(EditPartViewModel viewModel) { + return new ContentPartDefinition( + viewModel.Name, + viewModel.Fields.Select( + f => new ContentPartDefinition.Field( + new ContentFieldDefinition(f.FieldDefinition.Name), + f.Name, + f.Settings + ) + ), + viewModel.Settings + ); + } + #endregion #region Content - #endregion - public ActionResult List(ListContentsViewModel model) { const int pageSize = 20; var skip = (Math.Max(model.Page ?? 0, 1) - 1) * pageSize; @@ -328,5 +399,7 @@ namespace Orchard.Core.Contents.Controllers { void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) { ModelState.AddModelError(key, errorMessage.ToString()); } + + #endregion } } diff --git a/src/Orchard.Web/Core/Contents/Services/ContentDefinitionService.cs b/src/Orchard.Web/Core/Contents/Services/ContentDefinitionService.cs index b0a78fe48..a3f833085 100644 --- a/src/Orchard.Web/Core/Contents/Services/ContentDefinitionService.cs +++ b/src/Orchard.Web/Core/Contents/Services/ContentDefinitionService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Models; using Orchard.Localization; @@ -10,10 +11,12 @@ using Orchard.UI.Notify; namespace Orchard.Core.Contents.Services { public class ContentDefinitionService : IContentDefinitionService { private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly IEnumerable _contentFieldDrivers; - public ContentDefinitionService(IOrchardServices services, IContentDefinitionManager contentDefinitionManager) { + public ContentDefinitionService(IOrchardServices services, IContentDefinitionManager contentDefinitionManager, IEnumerable contentFieldDrivers) { Services = services; _contentDefinitionManager = contentDefinitionManager; + _contentFieldDrivers = contentFieldDrivers; T = NullLocalizer.Instance; } @@ -76,6 +79,10 @@ namespace Orchard.Core.Contents.Services { throw new NotImplementedException(); } + public IEnumerable GetFieldDefinitions() { + return _contentFieldDrivers.SelectMany(d => d.GetFieldInfo()); + } + //gratuitously stolen from the RoutableService private static string GenerateTypeName(string displayName) { if (string.IsNullOrWhiteSpace(displayName)) diff --git a/src/Orchard.Web/Core/Contents/Services/IContentDefinitionService.cs b/src/Orchard.Web/Core/Contents/Services/IContentDefinitionService.cs index 8840ee23c..53793e78c 100644 --- a/src/Orchard.Web/Core/Contents/Services/IContentDefinitionService.cs +++ b/src/Orchard.Web/Core/Contents/Services/IContentDefinitionService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Models; namespace Orchard.Core.Contents.Services { @@ -13,5 +14,7 @@ namespace Orchard.Core.Contents.Services { void AddPartDefinition(ContentPartDefinition contentPartDefinition); void AlterPartDefinition(ContentPartDefinition contentPartDefinition); void RemovePartDefinition(string name); + + IEnumerable GetFieldDefinitions(); } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Styles/admin.css b/src/Orchard.Web/Core/Contents/Styles/admin.css index 5a898fa4e..ba113a16e 100644 --- a/src/Orchard.Web/Core/Contents/Styles/admin.css +++ b/src/Orchard.Web/Core/Contents/Styles/admin.css @@ -5,13 +5,42 @@ margin-top:-4em; } -.manage-part h3 { +.manage-part h3, +.manage-field h3 { border-bottom:1px solid #EAEAEA; } -.manage-part .manage { +.manage-part .manage, +.manage-field .manage { font-size:1.4em; margin-top:-2.4em; } .manage-part .manage.minor { margin-top:-1.7em; +} +.manage-part label, +.manage-field label { + font-weight:normal; +} + +/* should pull this back into the base admin theme css, w/out the .manage-part of course */ +.manage-part dl { + margin:0 0 1em; + overflow:auto; + padding:6px 0 0; +} +.manage-part dt { + font-weight:bold; +} +.manage-part dl dl { + font-size:1em; + margin:0; + padding:0; +} +.manage-part dd dt { + clear:left; + float:left; +} +.manage-part dd dd { + float:left; + padding-left:.5em; } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/ViewModels/AddFieldViewModel.cs b/src/Orchard.Web/Core/Contents/ViewModels/AddFieldViewModel.cs new file mode 100644 index 000000000..f26912f63 --- /dev/null +++ b/src/Orchard.Web/Core/Contents/ViewModels/AddFieldViewModel.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Orchard.ContentManagement.MetaData; +using Orchard.Mvc.ViewModels; + +namespace Orchard.Core.Contents.ViewModels { + public class AddFieldViewModel : BaseViewModel { + public AddFieldViewModel() { + Fields = new List(); + } + + public string DisplayName { get; set; } + public string FieldTypeName { get; set; } + public EditPartViewModel Part { get; set; } + public IEnumerable Fields { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/AddFieldTo.ascx b/src/Orchard.Web/Core/Contents/Views/Admin/AddFieldTo.ascx new file mode 100644 index 000000000..79a562468 --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Views/Admin/AddFieldTo.ascx @@ -0,0 +1,18 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><% +Html.RegisterStyle("admin.css"); %> +

<%:Html.TitleForPage(T("Add a new field to {0}", Model.Part.Name).ToString())%>

<% +using (Html.BeginFormAntiForgeryPost()) { %> + <%:Html.ValidationSummary() %> +
+ + <%:Html.TextBoxFor(m => m.DisplayName, new {@class = "textMedium", autofocus = "autofocus"}) %> +
+
+ + <%:Html.DropDownListFor(m => m.FieldTypeName, new SelectList(Model.Fields, "FieldTypeName", "FieldTypeName"))%> +
+
+ +
<% +} %> diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/EditPart.ascx b/src/Orchard.Web/Core/Contents/Views/Admin/EditPart.ascx index 78589bdc0..c3f6642c5 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/EditPart.ascx +++ b/src/Orchard.Web/Core/Contents/Views/Admin/EditPart.ascx @@ -1,7 +1,7 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> <%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><% Html.RegisterStyle("admin.css"); %> -

<%:Html.TitleForPage(T("Edit Part").ToString())%>

<% +

<%:Html.TitleForPage(T("Edit Part").ToString()) %>

<% using (Html.BeginFormAntiForgeryPost()) { %> <%:Html.ValidationSummary() %>
@@ -9,9 +9,9 @@ using (Html.BeginFormAntiForgeryPost()) { %> <%--// has unintended consequences (renamging the part) - changing the name creates a new part of that name--%> <%:Html.TextBoxFor(m => m.Name, new {@class = "textMedium"}) %>
- <%:Html.EditorFor(m => m.Settings, "Settings", "")%> + <%:Html.EditorFor(m => m.Settings, "Settings", "") %>

<%:T("Fields") %>

-
<%: Html.ActionLink(T("Add").Text, "AddField", new { }, new { @class = "button" })%>
+
<%: Html.ActionLink(T("Add").Text, "AddFieldTo", new { area = "Contents", id = Model.Name }, new { @class = "button" }) %>
<%:Html.EditorFor(m => m.Fields, "Fields", "") %>
diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/EditType.ascx b/src/Orchard.Web/Core/Contents/Views/Admin/EditType.ascx index 86c390021..79fc9d4e4 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/EditType.ascx +++ b/src/Orchard.Web/Core/Contents/Views/Admin/EditType.ascx @@ -1,7 +1,8 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> <%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><% Html.RegisterStyle("admin.css"); %> -

<%:Html.TitleForPage(T("Edit Content Type").ToString())%>

<% +

<%:Html.TitleForPage(T("Edit Content Type").ToString())%>

+<% using (Html.BeginFormAntiForgeryPost()) { %> <%:Html.ValidationSummary() %>
@@ -14,11 +15,11 @@ using (Html.BeginFormAntiForgeryPost()) { %>
<%:Html.EditorFor(m => m.Settings) %>

<%:T("Parts") %>

-
<%: Html.ActionLink(T("Add").Text, "AddPart", new { }, new { @class = "button" })%>
+
<%: Html.ActionLink(T("Add").Text, "AddPart", new { }, new { @class = "button" }) %>
<%:Html.EditorFor(m => m.Parts, "Parts", "") %>

<%:T("Fields") %>

-
<%: Html.ActionLink(T("Add").Text, "AddField", new { }, new { @class = "button" })%>
- <%:Html.EditorFor(m => m.Fields, "Fields", "")%> +
<%: Html.ActionLink(T("Add").Text, "AddFieldTo", new { area = "Contents", id = Model.Name }, new { @class = "button" }) %>
+ <%:Html.EditorFor(m => m.Fields, "Fields", "") %>
<% diff --git a/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Field.ascx b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Field.ascx new file mode 100644 index 000000000..08660099b --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Field.ascx @@ -0,0 +1,6 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %> +
<%:Model.Name %> (<%:Model.FieldDefinition.Name %>)
+
+ <%:Html.DisplayFor(m => m.Settings, "Settings", "") %> +
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.Fields.ascx b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Fields.ascx similarity index 73% rename from src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.Fields.ascx rename to src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Fields.ascx index 131951c4f..164e32511 100644 --- a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.Fields.ascx +++ b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Fields.ascx @@ -1,10 +1,10 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl>" %> <%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><% if (Model.Any()) { %> -
<% +
<% foreach (var field in Model) { var f = field; %> - <%:Html.EditorFor(m => f, "Part.Fields") %><% + <%:Html.DisplayFor(m => f, "Field") %><% } %> -
<% + <% } %> \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Field.ascx b/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Field.ascx index 522d9ee91..4ca058cba 100644 --- a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Field.ascx +++ b/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Field.ascx @@ -1,9 +1,8 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> <%@ Import Namespace="Orchard.Core.Contents.ViewModels" %> -
-

<%:Model.Name %>

-

<%:Model.FieldDefinition.Name %>

-
+
+

<%:Model.Name %> (<%:Model.FieldDefinition.Name %>)

+
<%--// these inline forms can't be here. should probably have some JavaScript in here to build up the forms and add the "remove" link. // get the antiforgery token from the edit type form and mark up the part in a semantic way so I can get some info from the DOM --%> <%:Html.Link("[remove]", "#forshowonlyandnotintendedtowork!") %> diff --git a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.Field.ascx b/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.Field.ascx deleted file mode 100644 index 24ad5a714..000000000 --- a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.Field.ascx +++ /dev/null @@ -1,14 +0,0 @@ -<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> -<%@ Import Namespace="Orchard.ContentManagement.MetaData.Models" %> -
-

<%:Model.FieldDefinition.Name %>

-
- <%--// these inline forms can't be here. should probably have some JavaScript in here to build up the forms and add the "remove" link. - // get the antiforgery token from the edit type form and mark up the part in a semantic way so I can get some info from the DOM --%> - <%:Html.Link("[remove]", "#forshowonlyandnotintendedtowork!") %> -<%-- <% using (Html.BeginFormAntiForgeryPost(Url.Action("RemovePart", new { area = "Contents" }), FormMethod.Post, new {@class = "inline link"})) { %> - <%=Html.Hidden("name", Model.PartDefinition.Name, new { id = "" }) %> - - <% } %> --%> -
-
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.ascx b/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.ascx index 214c22b7c..8ae5b99ad 100644 --- a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.ascx +++ b/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Part.ascx @@ -11,12 +11,10 @@ <% } %> --%>
- <%:Html.EditorFor(m => m.Settings, "Settings", "") %><% - if (Model.PartDefinition.Settings.Any() || Model.PartDefinition.Fields.Any()) { %> + <%:Html.EditorFor(m => m.Settings, "Settings", "") %>

<%:T("Global configuration") %>

<%:Html.ActionLink(T("Edit").Text, "EditPart", new { area = "Contents", id = Model.PartDefinition.Name }) %>
<%:Html.DisplayFor(m => m.PartDefinition.Settings, "Settings", "PartDefinition") %> - <%:Html.EditorFor(m => m.PartDefinition.Fields, "Part.Fields") %><% - } %> + <%:Html.DisplayFor(m => m.PartDefinition.Fields, "Fields") %> <%:Html.Hidden("PartDefinition.Name", Model.PartDefinition.Name) %>
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Settings.ascx b/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Settings.ascx index 240add0b6..5a0f59533 100644 --- a/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Settings.ascx +++ b/src/Orchard.Web/Core/Contents/Views/EditorTemplates/Settings.ascx @@ -1,8 +1,7 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> <%@ import Namespace="Orchard.ContentManagement.MetaData.Models" %><% if (Model.Any()) { %> -
- <%:T("[Settings]") %><% +
<% var si = 0; foreach (var setting in Model) { var s = setting; diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index 9c5b2fbe2..8997fb84e 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -76,6 +76,7 @@ + @@ -207,6 +208,7 @@ + @@ -221,8 +223,8 @@ - - + + diff --git a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs index ee5bed54c..e907a9d62 100644 --- a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs +++ b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs @@ -46,6 +46,10 @@ namespace Orchard.Core.Settings.Metadata { return _partDefinitionRepository.Fetch(x => !x.Hidden).Select(Build).ToReadOnlyCollection(); } + public IEnumerable ListFieldDefinitions() { + return _fieldDefinitionRepository.Fetch(x => true, cfdr => cfdr.Asc(fdr => fdr.Name)).Select(Build).ToReadOnlyCollection(); + } + public void StoreTypeDefinition(ContentTypeDefinition contentTypeDefinition) { Apply(contentTypeDefinition, Acquire(contentTypeDefinition)); } diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ProfilingCommands.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ProfilingCommands.cs index 6635ab22b..aae71f2d8 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ProfilingCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ProfilingCommands.cs @@ -3,9 +3,11 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Aspects; using Orchard.Core.Common.Models; using Orchard.Core.Navigation.Models; +using Orchard.Environment.Extensions; using Orchard.Security; namespace Orchard.DevTools.Commands { + [OrchardFeature("Profiling")] public class ProfilingCommands : DefaultOrchardCommandHandler { private readonly IContentManager _contentManager; private readonly IMembershipService _membershipService; diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs new file mode 100644 index 000000000..8ef6923cb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs @@ -0,0 +1,136 @@ +using System; +using System.IO; +using System.Linq; +using System.Web.Hosting; +using Orchard.Commands; +using Orchard.Environment.Extensions; + +namespace Orchard.DevTools.Commands { + [OrchardFeature("Scaffolding")] + public class ScaffoldingCommands : DefaultOrchardCommandHandler { + private readonly IExtensionManager _extensionManager; + + public ScaffoldingCommands(IExtensionManager extensionManager) { + _extensionManager = extensionManager; + } + + [OrchardSwitch] + public bool IncludeInSolution { get; set; } + + [CommandHelp("scaffolding create module [/IncludeInSolution:true|false]\r\n\t" + "Create a new Orchard module")] + [CommandName("scaffolding create module")] + [OrchardSwitches("IncludeInSolution")] + public void CreateModule(string moduleName) { + Context.Output.WriteLine(T("Creating Module {0}", moduleName)); + + if (_extensionManager.AvailableExtensions().Any(extension => extension.ExtensionType == "Module" && String.Equals(moduleName, extension.DisplayName, StringComparison.OrdinalIgnoreCase))) { + Context.Output.WriteLine(T("Creating Module {0} failed: a module of the same name already exists", moduleName)); + return; + } + + IntegrateModule(moduleName); + + Context.Output.WriteLine(T("Module {0} created successfully", moduleName)); + } + + + [CommandHelp("scaffolding create controller \r\n\t" + "Create a new Orchard controller in a module")] + [CommandName("scaffolding create controller")] + public void CreateController(string moduleName, string controllerName) { + Context.Output.WriteLine(T("Creating Controller {0} in Module {1}", controllerName, moduleName)); + + foreach (var extension in _extensionManager.AvailableExtensions()) { + if (extension.ExtensionType == "Module" && String.Equals(moduleName, extension.DisplayName, StringComparison.OrdinalIgnoreCase)) { + string moduleControllersPath = HostingEnvironment.MapPath("~/Modules/" + extension.Name + "/Controllers/"); + string controllerPath = moduleControllersPath + controllerName + ".cs"; + string moduleCsProjPath = HostingEnvironment.MapPath(string.Format("~/Modules/{0}/{0}.csproj", extension.Name)); + string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard.DevTools/ScaffoldingTemplates/"); + if (!Directory.Exists(moduleControllersPath)) { + Directory.CreateDirectory(moduleControllersPath); + } + if (File.Exists(controllerPath)) { + Context.Output.WriteLine(T("Controller {0} already exists in target Module {1}.", controllerName, moduleName)); + return; + } + string controllerText = File.ReadAllText(templatesPath + "Controller.txt"); + controllerText = controllerText.Replace("$$ModuleName$$", moduleName); + controllerText = controllerText.Replace("$$ControllerName$$", controllerName); + File.WriteAllText(controllerPath, controllerText); + string projectFileText = File.ReadAllText(moduleCsProjPath); + // The string searches in solution/project files can be made aware of comment lines. + if (projectFileText.Contains("\r\n ", "Controllers\\" + controllerName + ".cs"); + projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("\r\n \r\n \r\n ", "Controllers\\" + controllerName + ".cs"); + projectFileText = projectFileText.Insert(projectFileText.LastIndexOf(""), itemGroupReference); + } + File.WriteAllText(moduleCsProjPath, projectFileText); + Context.Output.WriteLine(T("Controller {0} created successfully in Module {1}", controllerName, moduleName)); + return; + } + } + Context.Output.WriteLine(T("Creating Controller {0} failed: target Module {1} could not be found.", controllerName, moduleName)); + } + + private void IntegrateModule(string moduleName) { + string rootWebProjectPath = HostingEnvironment.MapPath("~/Orchard.Web.csproj"); + string projectGuid = Guid.NewGuid().ToString().ToUpper(); + + CreateFilesFromTemplates(moduleName, projectGuid); + // The string searches in solution/project files can be made aware of comment lines. + if (IncludeInSolution) { + // Add project reference to Orchard.Web.csproj + string webProjectReference = string.Format( + "\r\n \r\n {{{1}}}\r\n Orchard.{0}\r\n ", + moduleName, projectGuid); + string webProjectText = File.ReadAllText(rootWebProjectPath); + webProjectText = webProjectText.Insert(webProjectText.LastIndexOf("\r\n"), webProjectReference); + File.WriteAllText(rootWebProjectPath, webProjectText); + + // Add project to Orchard.sln + string solutionPath = Directory.GetParent(rootWebProjectPath).Parent.FullName + "\\Orchard.sln"; + if (File.Exists(solutionPath)) { + string projectReference = string.Format( + "EndProject\r\nProject(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"Orchard.{0}\", \"Orchard.Web\\Modules\\Orchard.{0}\\Orchard.{0}.csproj\", \"{{{1}}}\"\r\n", + moduleName, projectGuid); + string projectConfiguationPlatforms = string.Format( + "GlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU\r\n", + projectGuid); + string solutionText = File.ReadAllText(solutionPath); + solutionText = solutionText.Insert(solutionText.LastIndexOf("EndProject\r\n"), projectReference); + solutionText = solutionText.Replace("GlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n", projectConfiguationPlatforms); + solutionText = solutionText.Insert(solutionText.LastIndexOf("EndGlobalSection"), "\t{" + projectGuid + "} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}\r\n\t"); + + File.WriteAllText(solutionPath, solutionText); + } + else { + Context.Output.WriteLine(T("Warning: Solution file could not be found at {0}", solutionPath)); + } + } + } + + private static void CreateFilesFromTemplates(string moduleName, string projectGuid) { + string modulePath = HostingEnvironment.MapPath("~/Modules/Orchard." + moduleName + "/"); + string propertiesPath = modulePath + "Properties"; + string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard.DevTools/ScaffoldingTemplates/"); + + Directory.CreateDirectory(modulePath); + Directory.CreateDirectory(propertiesPath); + string templateText = File.ReadAllText(templatesPath + "ModuleAssemblyInfo.txt"); + templateText = templateText.Replace("$$ModuleName$$", moduleName); + templateText = templateText.Replace("$$ModuleTypeLibGuid$$", Guid.NewGuid().ToString()); + File.WriteAllText(propertiesPath + "\\AssemblyInfo.cs", templateText); + File.WriteAllText(modulePath + "\\Web.config", File.ReadAllText(templatesPath + "ModuleWebConfig.txt")); + templateText = File.ReadAllText(templatesPath + "ModuleManifest.txt"); + templateText = templateText.Replace("$$ModuleName$$", moduleName); + File.WriteAllText(modulePath + "\\Module.txt", templateText); + templateText = File.ReadAllText(templatesPath + "\\ModuleCsProj.txt"); + templateText = templateText.Replace("$$ModuleName$$", moduleName); + templateText = templateText.Replace("$$ModuleProjectGuid$$", projectGuid); + File.WriteAllText(modulePath + "\\Orchard." + moduleName + ".csproj", templateText); + } + } +} + diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt b/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt index 40cb75a5e..1aeb0b2b3 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt @@ -7,5 +7,13 @@ orchardversion: 0.1.2010.0312 description: This module is not activated by default and should only be used in a development environment. It contains various debugging and tracing tools that can display information about your content types. features: Orchard.DevTools: - Description: An assortment of debuging tools. - Category: Developer \ No newline at end of file + Description: An assortment of debugging tools. + Category: Developer + Scaffolding: + Description: Tools to create Orchard components. + Category: Developer + Dependencies: Orchard.DevTools + Profiling: + Description: Tools to help profile Orchard. + Category: Developer + Dependencies: Orchard.DevTools \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj index fd88a2bd9..8ed2402e5 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj @@ -71,6 +71,7 @@ + @@ -85,6 +86,11 @@ + + + + + @@ -106,6 +112,7 @@ Orchard.Core + + + + + $(ProjectDir)\..\Manifests + + + + + + + + + + + + False + True + 45979 + / + + + False + True + http://orchard.codeplex.com + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/ModuleManifest.txt b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/ModuleManifest.txt new file mode 100644 index 000000000..7f7d0b295 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/ModuleManifest.txt @@ -0,0 +1,5 @@ +name: $$ModuleName$$ +antiforgery: enabled +features: + Orchard.$$ModuleName$$: + Description: Description for feature $$ModuleName$$. \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/ModuleWebConfig.txt b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/ModuleWebConfig.txt new file mode 100644 index 000000000..9445e4ba4 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/ModuleWebConfig.txt @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index 6cf84f249..a106bbd64 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css @@ -147,10 +147,11 @@ h1 { font-size:2.6em; } /* 26px */ h2 { font-size:2.1em; } /* 21px */ h2 span { font-size:.57em; } /* 12px */ h3 { font-size:1.8em; } /* 18px */ +h3 span { font-size:.667em; } /* 12px */ h4 { font-size:1.6em; } /* 16px */ h5 { font-size:1.4em; } /* 14px */ -h6, p, label, /*input, select,*/ .button, +h6, p, dl, label, /*input, select,*/ .button, .message, .validation-summary-errors, table.items th, table.items td, table.items caption { font-size:1.4em; line-height:1.4em; } /* 14px */ table.items p, table.items label, table.items input, table.items .button { font-size:1em; line-height:1em; } diff --git a/src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs b/src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs index 8b635f2a5..a17decb2b 100644 --- a/src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs +++ b/src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs @@ -7,6 +7,7 @@ namespace Orchard.ContentManagement.MetaData { public interface IContentDefinitionManager : IDependency { IEnumerable ListTypeDefinitions(); IEnumerable ListPartDefinitions(); + IEnumerable ListFieldDefinitions(); ContentTypeDefinition GetTypeDefinition(string name); ContentPartDefinition GetPartDefinition(string name);