📜 ⬆️ ⬇️

We try Orchard CMS for a corporate site

Hello!

We have a corporate website on Liferay, and it requires a rather painstaking work at the stage of creating the layout. We decided to see how the creation of a custom section in Liferay differs from the same process in Orchard CMS in such a small task as creating corporate news.


')
What we got out of this:

Orchard setup:



The implementation of the “News” section consists of the following parts:
  1. Content type.
  2. Content type settings.
  3. The content itself.
  4. Request.
  5. Projection - how everything will look on the site. Customization of external elements.


Creating a type of "News" and request (for display on the main page):


1. Create ContentType:










2. Add a picture to the news:



3. Create a request
3.1.



3.2. Now you need to configure filters for the query:



3.3. Determine the sort order:



3.4. Since the result of the request must be shown somewhere, we create Projection:



Now on the main page will be a projection. You can create several news items in the dashboard.

Customization of appearance


Create a topic

You must download and enable the Code generation module: http://docs.orchardproject.net/Documentation/Command-line-scaffolding

Next, open the folder with the installed Orchard -> bin -> orchard.exe, wait until it is initialized, we write: codegen theme <theme-name> / BasedOn: TheTheMachine / CreateProject: true

We open the project with the topic:



And we cannot create the Razor template ... In order for us to create .cshtml files from the studio interface, you need to unload the project, open the project file with any text editor and modify the ProjectTypeGuids, adding {E53F8FEA-EAE0-44A6-8774-FFD645390401 to it }. Our result is: {E53F8FEA-EAE0-44A6-8774-FFD645390401}; {349c5851-65df-11da-9384-00065b846f21}; {fae04ec0-301f-11d3-bf4b-00c04f79efbc}. Now you can save the project file and upload it to the studio.



All theme files not found in the current one are taken from the base one, if defined, or from the SafeMode theme. We need to change the favicon and connect the scripts, the favicon is connected only in the template “Document.cshtml”, the scripts associated with the theme are usually connected here.

Now we can create Document.cshtml in the Views folder.
Inside this file, we add links to scripts, register favicon, and the rest of the code is taken from a similar file in the SafeMode topic.
Views \ Document.cshtml:

@using Orchard.Mvc.Html; @using Orchard.UI.Resources; @{ RegisterLink(new LinkEntry { Type = "image/x-icon", Rel = "shortcut icon", Href = Url.Content("~/Themes/ETRTheme/Content/images/favicon-201209261628.ico") }); Script.Include("html5.js").UseCondition("lt IE 9").AtHead(); Script.Include("jquery.min.js").AtHead(); Script.Include("jquery-ui.min.js").AtHead(); Script.Include("knockout-2.2.1.js").AtHead(); Script.Include("jquery.lightbox.js").AtHead(); Script.Include("jquery.cycle.all.js").AtHead(); Script.Include("date.format.js").AtHead(); Script.Include("script.js").AtHead(); string title = Convert.ToString(Model.Title); string siteName = Convert.ToString(WorkContext.CurrentSite.SiteName); } <!DOCTYPE html> <html lang="@WorkContext.CurrentCulture" class="static @Html.ClassForPage()"> <head> <meta charset="utf-8" /> <title>@Html.Title(title, siteName)</title> @Display(Model.Head) <script> (function (d) { d.className = "dyn" + d.className.substring(6, d.className.length); })(document.documentElement);</script> </head> <body> @Display(Model.Body) @Display(Model.Tail) </body> </html> 


This file is responsible for rendering the page, in the line "@Display (Model.Body)" it calls Layout.cshtml.

Layout contains page layout, connects css and "shows" different zones.

Changing shapes for customizing UI

In order to customize the appearance of elements, it is necessary to create several templates with specific names (one for each customization, Orchard will select by what template it will render what element).

http://docs.orchardproject.net/Documentation/Accessing-and-rendering-shapes#NamingShapesandTemplates

In our case there will be, for example, such templates:

Template to display abbreviated news:
Views \ Content-News.Summary.cshtml:

 @using Orchard.Utility.Extensions; @using Orchard.Fields.Fields; @using Orchard.Core.Common.Models; @using Orchard.ContentManagement; @using System.Text.RegularExpressions; @using Orchard.Tags.Models; @using System.Text; @using Orchard.MediaLibrary.Fields; @using Orchard.ContentManagement @{ ContentItem contentItem = Model.ContentItem; var contentTypeClassName = ((string)contentItem.ContentType).HtmlClassify(); var news = ((dynamic)contentItem).News; IEnumerable<ContentField> fields = news.Fields; var common = contentItem.As<CommonPart>(); var publishedDate = ""; if (common.PublishedUtc.HasValue) { var date = common.PublishedUtc.Value; publishedDate = date.ToString("d MMMM yyyy"); } MediaLibraryPickerField newsMainImage = null; bool newsHasImage = false; string imageUrl = null; string imageAlternateText = null; try { newsMainImage = (MediaLibraryPickerField)fields.First(f => f.Name == "NewsMainImage"); imageUrl = newsMainImage.MediaParts.First().MediaUrl; imageAlternateText = newsMainImage.MediaParts.First().AlternateText; newsHasImage = true; } catch (InvalidOperationException e) { newsHasImage = false; } var body = contentItem.As<BodyPart>(); var summaryBodyText = body.Text.RemoveTags().Trim().Replace(Environment.NewLine, " "); summaryBodyText = Regex.Replace(summaryBodyText, @"\s+", " "); var textLength = newsHasImage ? 400 : 500; textLength = textLength > summaryBodyText.Length ? summaryBodyText.Length : textLength; summaryBodyText = summaryBodyText.Substring(0, textLength); var tags = contentItem.As<TagsPart>().CurrentTags; var tagsHtml = new List<IHtmlString>(); foreach (var t in tags) { if (tagsHtml.Any()) { tagsHtml.Add(new HtmlString(", ")); } tagsHtml.Add(Html.ActionLink((string)t.TagName, "Search", "Home", new { area = "Orchard.Tags", tagName = (string)t.TagName }, new { })); } <div @if (newsHasImage) { <text>class="b-newsroll-item-inner"</text> } else { <text>class="b-newsroll-item-inner-no-image"</text> }> @if (common.PublishedUtc.HasValue) { <div class="b-newsroll-date"> @publishedDate </div> } @if (newsHasImage) { <div class="b-newsroll-image-wrapper"> <img class="b-newsroll-image" src="@Url.Content(@imageUrl)" @if (!String.IsNullOrWhiteSpace(imageAlternateText)) { <text>alt="@imageAlternateText"</text> }/> </div> } <div class="b-newsroll-content"> <div class="b-newsroll-text"> <p>@Html.Raw(summaryBodyText)</p> </div> <span class="b-newsroll-content-crop"></span> </div> <div class="b-newsroll-more"> @Html.ItemDisplayLink(T("Read more").ToString(), contentItem) </div> @if (tagsHtml.Any()) { <div class="b-newsroll-tags"> <span> @T("Tags:") </span> @foreach (var htmlString in tagsHtml) { @htmlString } </div> } </div> } 


Creating a grid for positioning news.

Now we need to make a normal grid for news, for this we create the SliderGrid module: the codegen module SliderGrid and describe the shapes in it:

Layouts \ SliderGridLayoutForms.cs:
 using System; using Orchard.DisplayManagement; using Orchard.Forms.Services; using Orchard.Localization; namespace SliderGrid.Layouts { public class SliderGridLayoutForms : IFormProvider { protected dynamic Shape { get; set; } public Localizer T { get; set; } public SliderGridLayoutForms( IShapeFactory shapeFactory) { Shape = shapeFactory; T = NullLocalizer.Instance; } public void Describe(DescribeContext context) { Func<IShapeFactory, object> form = shape => { var f = Shape.Form( Id: "SliderGridLayout", _HtmlProperties: Shape.Fieldset() ); return f; }; context.Form("SliderGridLayout", form); } } } Layouts\SliderGridLayout.cs: using System.Collections.Generic; using System.Linq; using Orchard.ContentManagement; using Orchard.DisplayManagement; using Orchard.Localization; using Orchard.Projections.Descriptors.Layout; using Orchard.Projections.Models; using Orchard.Projections.Services; namespace SliderGrid.Layouts { public class SliderGridLayout : ILayoutProvider { public Localizer T { get; set; } private readonly IContentManager _contentManager; protected dynamic Shape { get; set; } public SliderGridLayout(IShapeFactory shapeFactory, IContentManager contentManager) { _contentManager = contentManager; Shape = shapeFactory; T = NullLocalizer.Instance; } public void Describe(DescribeLayoutContext describe) { describe.For("Html", T("Html"), T("Html Layouts")) .Element("SliderGrid", T("SliderGrid"), T("Renders multiPageGrid of elements + slider."), DisplayLayout, RenderLayout, "SliderGridLayout" ); } public LocalizedString DisplayLayout(LayoutContext context) { return T("Renders multiPageGrid + slider."); } public dynamic RenderLayout(LayoutContext context, IEnumerable<LayoutComponentResult> layoutComponentResults) { IEnumerable<dynamic> shapes = context.LayoutRecord.Display == (int)LayoutRecord.Displays.Content ? layoutComponentResults.Select(x => _contentManager.BuildDisplay(x.ContentItem, context.LayoutRecord.DisplayType)) : layoutComponentResults.Select(x => x.Properties); return Shape.SliderGrid(Items: shapes); } } } 


Turn on grid

We connect the SliderGrid feature in the "modules", change the layout of the LastNews query to SliderGrid:



We change in the projection the request for the just corrected.



findings


In order to be able to write news through the admin area, we need to implement ContentType, in our case - News. To show the news list on the main page, we need Projection, and for it - Query. In order for us to customize the appearance of the elements, we need in the current theme in the Views folder to put templates with specific names, according to which Orchard can figure out which shape this template should be applied to. How to get ContentPart and ContentTypeField from ContentType is clear from the example with short news.

Based on the experiment, we concluded that Orchard and Liferay at the stage of preparing a tool for publishing news ... are about the same. Both there and there is customization of topics, the production of necessary entities, the possibility of customization of these entities, but there is a nuance: at the stage when it is necessary to make a block conclusion (for example, a list of news or articles) problems begin with Liferay - the problem falls on the programmer who needs pull entities on their own to display them. It requires a fairly high qualification in java and in the development of Liferay.

Orchard has a convenient query mechanism - Query, - to cope with which everything is possible.

Source: https://habr.com/ru/post/189314/


All Articles