mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Merge branch 'dev' into feature/recipesteps
Conflicts: src/Orchard.Web/Modules/Orchard.Recipes/Services/RecipeParser.cs src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml
This commit is contained in:
@@ -1,16 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Localization.Models;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Services;
|
||||
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
@@ -217,6 +209,17 @@ namespace Orchard.Tests.Localization {
|
||||
Assert.AreEqual(dateTimeLocal, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("DateTime which is DateTimeKind.Local is converted to DateTimeKind.Utc.")]
|
||||
public void ConvertFromLocalizedDateStringTest01() {
|
||||
var container = TestHelpers.InitializeContainer("en-US", "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15);
|
||||
var dateTimeLocalString = dateTimeLocal.ToShortDateString();
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromLocalizedDateString(dateTimeLocalString);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Value.Kind);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Converting to Gregorian calendar yields a DateTimeParts instance equivalent to the original DateTime.")]
|
||||
public void ConvertToSiteCalendarTest01() {
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<ul class="menu-items-zone">
|
||||
@foreach (var descriptor in Model.MenuItemDescriptors.OrderBy(x => x.DisplayName)) {
|
||||
<li>
|
||||
<div class="menu-item-description"><h2>@T(descriptor.DisplayName.CamelFriendly())</h2>
|
||||
<div class="menu-item-description"><h2>@T(descriptor.DisplayName)</h2>
|
||||
@if (!string.IsNullOrWhiteSpace(descriptor.Description)) {
|
||||
<span class="hint">@T(descriptor.Description)</span>
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Orchard.Layouts.Helpers {
|
||||
public static class MetaDataExtensions {
|
||||
public static ContentPartDefinitionBuilder Placable(this ContentPartDefinitionBuilder builder, bool placable = true) {
|
||||
return builder.WithSetting("ContentPartLayoutSettings.Placable", placable.ToString());
|
||||
public static ContentPartDefinitionBuilder Placeable(this ContentPartDefinitionBuilder builder, bool placeable = true) {
|
||||
return builder.WithSetting("ContentPartLayoutSettings.Placeable", placeable.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +45,10 @@ namespace Orchard.Layouts {
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
.DisplayedAs("Layout Widget"));
|
||||
|
||||
ContentDefinitionManager.AlterPartDefinition("BodyPart", part => part.Placable());
|
||||
ContentDefinitionManager.AlterPartDefinition("TitlePart", part => part.Placable());
|
||||
ContentDefinitionManager.AlterPartDefinition("CommonPart", part => part.Placable());
|
||||
ContentDefinitionManager.AlterPartDefinition("TagsPart", part => part.Placable());
|
||||
ContentDefinitionManager.AlterPartDefinition("BodyPart", part => part.Placeable());
|
||||
ContentDefinitionManager.AlterPartDefinition("TitlePart", part => part.Placeable());
|
||||
ContentDefinitionManager.AlterPartDefinition("CommonPart", part => part.Placeable());
|
||||
ContentDefinitionManager.AlterPartDefinition("TagsPart", part => part.Placeable());
|
||||
|
||||
ContentDefinitionManager.AlterPartDefinition("ElementWrapperPart", part => part
|
||||
.Attachable()
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Orchard.Layouts.Providers {
|
||||
? contentTypeDefinition.Parts.Select(x => x.PartDefinition)
|
||||
: _contentDefinitionManager.Value.ListPartDefinitions();
|
||||
|
||||
return parts.Where(p => p.Settings.GetModel<ContentPartLayoutSettings>().Placable);
|
||||
return parts.Where(p => p.Settings.GetModel<ContentPartLayoutSettings>().Placeable);
|
||||
}
|
||||
|
||||
private void Displaying(ElementDisplayingContext context) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function ($) {
|
||||
var placable = $("input[name=\"ContentPartLayoutSettings.Placable\"]");
|
||||
var placeable = $("input[name=\"ContentPartLayoutSettings.Placeable\"]");
|
||||
|
||||
$(placable).on("change", function (e) {
|
||||
$(placeable).on("change", function (e) {
|
||||
syncEnableEditorInput();
|
||||
});
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
var syncEnableEditorInput = function () {
|
||||
var enableEditorDialog = $("input[name=\"ContentPartLayoutSettings.EnableEditorDialog\"]");
|
||||
var isPlacable = placable.is(":checked");
|
||||
var isPlaceable = placeable.is(":checked");
|
||||
|
||||
enableEditorDialog.prop("disabled", !isPlacable);
|
||||
enableEditorDialog.prop("disabled", !isPlaceable);
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
@@ -68,7 +68,21 @@ namespace Orchard.Layouts.Services {
|
||||
}
|
||||
|
||||
private IEnumerable<IContentPartDriver> GetPartDrivers(string partName) {
|
||||
return _contentPartDrivers.Where(x => x.GetType().BaseType.GenericTypeArguments[0].Name == partName);
|
||||
return _contentPartDrivers.Where(x => GetPartOfDriver(x.GetType().BaseType).Name == partName);
|
||||
}
|
||||
|
||||
private Type GetPartOfDriver(Type type) {
|
||||
var baseType = type;
|
||||
|
||||
while (baseType != null && typeof(IContentPartDriver).IsAssignableFrom(baseType)) {
|
||||
if (baseType.GenericTypeArguments.Any()) {
|
||||
return baseType.GenericTypeArguments[0];
|
||||
}
|
||||
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace Orchard.Layouts.Settings {
|
||||
public class ContentPartLayoutSettings {
|
||||
/// <summary>
|
||||
/// This setting is used to configure a part to be placable on a layout.
|
||||
/// This setting is used to configure a part to be placeable on a layout.
|
||||
/// </summary>
|
||||
public bool Placable { get; set; }
|
||||
public bool Placeable { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Orchard.Layouts.Settings {
|
||||
public override IEnumerable<TemplateViewModel> PartEditorUpdate(ContentPartDefinitionBuilder builder, IUpdateModel updateModel) {
|
||||
var model = new ContentPartLayoutSettings();
|
||||
updateModel.TryUpdateModel(model, "ContentPartLayoutSettings", null, null);
|
||||
builder.Placable(model.Placable);
|
||||
builder.Placeable(model.Placeable);
|
||||
yield return DefinitionTemplate(model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Script.Include("contentpart-layouts-settings.js");
|
||||
}
|
||||
<fieldset>
|
||||
@Html.CheckBoxFor(m => m.Placable)
|
||||
<label for="@Html.FieldIdFor(m => m.Placable)" class="forcheckbox">@T("Placable")</label>
|
||||
<span class="hint">@T("Check to allow this part to be placable on a layout.")</span>
|
||||
@Html.CheckBoxFor(m => m.Placeable)
|
||||
<label for="@Html.FieldIdFor(m => m.Placeable)" class="forcheckbox">@T("Placeable")</label>
|
||||
<span class="hint">@T("Check to allow this part to be placeable on a layout.")</span>
|
||||
</fieldset>
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
@{
|
||||
Style.Include("admin-projections.css");
|
||||
|
||||
Layout.Title = T("Manage Queries").ToString();
|
||||
var index = 0;
|
||||
|
||||
var pageSizes = new List<int?>() { 10, 50, 100 };
|
||||
@@ -74,4 +74,4 @@
|
||||
</table>
|
||||
@Display(Model.Pager)
|
||||
</fieldset>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,11 @@ using Orchard.Recipes.Models;
|
||||
|
||||
namespace Orchard.Recipes.Services {
|
||||
public class RecipeParser : Component, IRecipeParser {
|
||||
public Recipe ParseRecipe(XDocument recipeDocument) {
|
||||
return ParseRecipe(recipeDocument.ToString(SaveOptions.DisableFormatting));
|
||||
}
|
||||
|
||||
|
||||
public Recipe ParseRecipe(string recipeText) {
|
||||
var recipe = new Recipe();
|
||||
|
||||
if (String.IsNullOrEmpty(recipeText)) {
|
||||
if (string.IsNullOrEmpty(recipeText)) {
|
||||
throw new Exception("Recipe is empty");
|
||||
}
|
||||
|
||||
@@ -22,7 +19,7 @@ namespace Orchard.Recipes.Services {
|
||||
var recipeSteps = new List<RecipeStep>();
|
||||
|
||||
foreach (var element in recipeTree.Elements()) {
|
||||
// Recipe metadata
|
||||
// Recipe metadata.
|
||||
if (element.Name.LocalName == "Recipe") {
|
||||
foreach (var metadataElement in element.Elements()) {
|
||||
switch (metadataElement.Name.LocalName) {
|
||||
@@ -47,6 +44,9 @@ namespace Orchard.Recipes.Services {
|
||||
case "ExportUtc":
|
||||
recipe.ExportUtc = !string.IsNullOrEmpty(metadataElement.Value) ? (DateTime?)XmlConvert.ToDateTime(metadataElement.Value, XmlDateTimeSerializationMode.Utc) : null;
|
||||
break;
|
||||
case "Category":
|
||||
recipe.Category = metadataElement.Value;
|
||||
break;
|
||||
case "Tags":
|
||||
recipe.Tags = metadataElement.Value;
|
||||
break;
|
||||
@@ -56,7 +56,7 @@ namespace Orchard.Recipes.Services {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recipe step
|
||||
// Recipe step.
|
||||
else {
|
||||
var recipeStep = new RecipeStep { Name = element.Name.LocalName, Step = element };
|
||||
recipeSteps.Add(recipeStep);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Recipes.Models;
|
||||
using Orchard.Setup.Services;
|
||||
using Orchard.Setup.ViewModels;
|
||||
using Orchard.Localization;
|
||||
@@ -44,7 +42,7 @@ namespace Orchard.Setup.Controllers {
|
||||
|
||||
public ActionResult Index() {
|
||||
var initialSettings = _setupService.Prime();
|
||||
var recipes = OrderRecipes(_setupService.Recipes());
|
||||
var recipes = _setupService.Recipes().ToList();
|
||||
string recipeDescription = null;
|
||||
if (recipes.Count > 0) {
|
||||
recipeDescription = recipes[0].Description;
|
||||
@@ -54,13 +52,11 @@ namespace Orchard.Setup.Controllers {
|
||||
// will take a while to finish (user inputting data and the setup process itself).
|
||||
// We use this opportunity to start a background task to "pre-compile" all the known
|
||||
// views in the app folder, so that the application is more reponsive when the user
|
||||
// hits the homepage and admin screens for the first time.))
|
||||
// hits the homepage and admin screens for the first time).
|
||||
if (StringComparer.OrdinalIgnoreCase.Equals(initialSettings.Name, ShellSettings.DefaultName)) {
|
||||
_viewsBackgroundCompilation.Start();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
|
||||
return IndexViewResult(new SetupViewModel {
|
||||
AdminUsername = "admin",
|
||||
DatabaseIsPreconfigured = !string.IsNullOrEmpty(initialSettings.DataProvider),
|
||||
@@ -71,32 +67,32 @@ namespace Orchard.Setup.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Index")]
|
||||
public ActionResult IndexPOST(SetupViewModel model) {
|
||||
// sets the setup request timeout to 10 minutes to give enough time to execute custom recipes.
|
||||
// Sets the setup request timeout to 10 minutes to give enough time to execute custom recipes.
|
||||
HttpContext.Server.ScriptTimeout = 600;
|
||||
|
||||
var recipes = OrderRecipes(_setupService.Recipes());
|
||||
var recipes = _setupService.Recipes().ToList();
|
||||
|
||||
// if no builtin provider, a connection string is mandatory
|
||||
// If no builtin provider, a connection string is mandatory.
|
||||
if (model.DatabaseProvider != SetupDatabaseType.Builtin && string.IsNullOrEmpty(model.DatabaseConnectionString))
|
||||
ModelState.AddModelError("DatabaseConnectionString", T("A connection string is required").Text);
|
||||
ModelState.AddModelError("DatabaseConnectionString", T("A connection string is required.").Text);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword ) {
|
||||
ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match").Text);
|
||||
if (!string.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword ) {
|
||||
ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match.").Text);
|
||||
}
|
||||
|
||||
if (model.DatabaseProvider != SetupDatabaseType.Builtin && !String.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) {
|
||||
if (model.DatabaseProvider != SetupDatabaseType.Builtin && !string.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) {
|
||||
model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim();
|
||||
if(!Char.IsLetter(model.DatabaseTablePrefix[0])) {
|
||||
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter").Text);
|
||||
if(!char.IsLetter(model.DatabaseTablePrefix[0])) {
|
||||
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter.").Text);
|
||||
}
|
||||
|
||||
if(model.DatabaseTablePrefix.Any(x => !Char.IsLetterOrDigit(x))) {
|
||||
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must contain letters or digits").Text);
|
||||
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must contain letters or digits.").Text);
|
||||
}
|
||||
}
|
||||
if (model.Recipe == null) {
|
||||
if (!(recipes.Select(r => r.Name).Contains(DefaultRecipe))) {
|
||||
ModelState.AddModelError("Recipe", T("No recipes were found in the Setup module").Text);
|
||||
ModelState.AddModelError("Recipe", T("No recipes were found.").Text);
|
||||
}
|
||||
else {
|
||||
model.Recipe = DefaultRecipe;
|
||||
@@ -155,7 +151,7 @@ namespace Orchard.Setup.Controllers {
|
||||
// uses a "single lock" mechanism for compiling views).
|
||||
_viewsBackgroundCompilation.Stop();
|
||||
|
||||
// redirect to the welcome page.
|
||||
// Redirect to the welcome page.
|
||||
return Redirect("~/" + _shellSettings.RequestUrlPrefix);
|
||||
} catch (Exception ex) {
|
||||
Logger.Error(ex, "Setup failed");
|
||||
@@ -170,19 +166,5 @@ namespace Orchard.Setup.Controllers {
|
||||
return IndexViewResult(model);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Recipe> OrderRecipes(IEnumerable<Recipe> recipes) {
|
||||
var recipeList = new List<Recipe>();
|
||||
var tempList = new List<Recipe>();
|
||||
foreach (var recipe in recipes) {
|
||||
if (recipe.Name == DefaultRecipe) {
|
||||
recipeList.Add(recipe);
|
||||
}
|
||||
else {
|
||||
tempList.Add(recipe);
|
||||
}
|
||||
}
|
||||
return recipeList.Concat(tempList).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<Description>A recipe providing the features you need for a personal blog site.</Description>
|
||||
<Author>The Orchard Team</Author>
|
||||
<WebSite>http://orchardproject.net</WebSite>
|
||||
<Category>Default</Category>
|
||||
<Tags>blog</Tags>
|
||||
<Version>1.0</Version>
|
||||
<IsSetupRecipe>true</IsSetupRecipe>
|
||||
@@ -19,7 +20,7 @@
|
||||
Orchard.Taxonomies,Orchard.Workflows,
|
||||
TheThemeMachine" />
|
||||
|
||||
<ContentSchema>
|
||||
<ContentDefinition>
|
||||
<Types>
|
||||
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
|
||||
<TitlePart/>
|
||||
@@ -39,7 +40,7 @@
|
||||
<Parts>
|
||||
<BodyPart BodyPartSettings.FlavorDefault="html" />
|
||||
</Parts>
|
||||
</ContentSchema>
|
||||
</ContentDefinition>
|
||||
|
||||
<Settings>
|
||||
<SiteSettingsPart PageSize="20" PageTitleSeparator = " - " />
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<Description>A recipe providing only the core Orchard framework, with limited end-user functionality. This is useful for development scenarios.</Description>
|
||||
<Author>The Orchard Team</Author>
|
||||
<WebSite>http://orchardproject.net</WebSite>
|
||||
<Category>Default</Category>
|
||||
<Tags>developer</Tags>
|
||||
<Version>1.0</Version>
|
||||
<IsSetupRecipe>true</IsSetupRecipe>
|
||||
@@ -13,7 +14,7 @@
|
||||
<Feature disable="Feeds, Containers"
|
||||
enable="Orchard.jQuery,Orchard.Alias,Orchard.Autoroute" />
|
||||
|
||||
<ContentSchema>
|
||||
<ContentDefinition>
|
||||
<Types>
|
||||
<Page ContentTypeSettings.Draftable="True">
|
||||
<BodyPart />
|
||||
@@ -22,7 +23,7 @@
|
||||
<Parts>
|
||||
<BodyPart BodyPartSettings.FlavorDefault="html" />
|
||||
</Parts>
|
||||
</ContentSchema>
|
||||
</ContentDefinition>
|
||||
|
||||
<Settings />
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<Description>The default recipe for an Orchard site that includes pages, blogs, custom content types, comments, tags, widgets and basic navigation.</Description>
|
||||
<Author>The Orchard Team</Author>
|
||||
<WebSite>http://orchardproject.net</WebSite>
|
||||
<Category>Default</Category>
|
||||
<Tags></Tags>
|
||||
<Version>1.0</Version>
|
||||
<IsSetupRecipe>true</IsSetupRecipe>
|
||||
@@ -18,7 +19,7 @@
|
||||
Orchard.Layouts,Orchard.Layouts.Tokens,
|
||||
TheThemeMachine" />
|
||||
|
||||
<ContentSchema>
|
||||
<ContentDefinition>
|
||||
<Types>
|
||||
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
|
||||
<TagsPart />
|
||||
@@ -38,7 +39,7 @@
|
||||
<Parts>
|
||||
<BodyPart BodyPartSettings.FlavorDefault="html" />
|
||||
</Parts>
|
||||
</ContentSchema>
|
||||
</ContentDefinition>
|
||||
|
||||
<Settings />
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
@model Orchard.Setup.ViewModels.SetupViewModel
|
||||
@{
|
||||
Script.Require("jQuery");
|
||||
Script.Require("jQuery");
|
||||
Script.Require("ShapesBase");
|
||||
Script.Include("setup.js");
|
||||
}
|
||||
@{
|
||||
var groupedRecipes = Model.Recipes.Where(x => !String.IsNullOrWhiteSpace(x.Category)).GroupBy(x => x.Category);
|
||||
var unspecifiedCategoryRecipes = Model.Recipes.Where(x => String.IsNullOrWhiteSpace(x.Category)).ToList();
|
||||
}
|
||||
<h1>@Html.TitleForPage(T("Get Started").ToString())</h1>
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@@ -30,7 +34,7 @@
|
||||
if (!Model.DatabaseIsPreconfigured) {
|
||||
<fieldset class="data">
|
||||
<legend>@T("How would you like to store your data?")</legend>
|
||||
@Html.ValidationMessage("DatabaseOptions", "Unable to setup data storage")
|
||||
@Html.ValidationMessage("DatabaseOptions", "Unable to setup data storage.")
|
||||
<div>
|
||||
@Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.Builtin.ToString(), new { id = "builtin" })
|
||||
<label for="builtin" class="forcheckbox">@T("Use built-in data storage (SQL Server Compact)")</label>
|
||||
@@ -71,16 +75,29 @@ if (!Model.DatabaseIsPreconfigured) {
|
||||
</fieldset>
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Choose an Orchard Recipe")</legend>
|
||||
<div>@T("Orchard Recipes allow you to setup your site with additional pre-configured options, features and settings out of the box")</div>
|
||||
<div>
|
||||
<legend>@T("Choose an Orchard Recipe")</legend>
|
||||
<div>@T("Orchard Recipes allow you to setup your site with additional pre-configured options, features and settings out of the box.")</div>
|
||||
<div>
|
||||
<select id="@Html.FieldIdFor(m => m.Recipe)" name="@Html.FieldNameFor(m => m.Recipe)" class="recipe">
|
||||
@foreach(var recipe in Model.Recipes) {
|
||||
@Html.SelectOption(Model.Recipe, recipe.Name, recipe.Name, new { recipedescription = recipe.Description })
|
||||
@foreach(var recipeGroup in groupedRecipes.OrderBy(x => x.Key)) {
|
||||
if (groupedRecipes.Count() > 1) {
|
||||
<optgroup label="@recipeGroup.Key"></optgroup>
|
||||
}
|
||||
foreach (var recipe in recipeGroup.OrderBy(x => x.Name)) {
|
||||
@Html.SelectOption(Model.Recipe, recipe.Name, recipe.Name, new { recipedescription = recipe.Description })
|
||||
}
|
||||
}
|
||||
@if (unspecifiedCategoryRecipes.Any()) {
|
||||
if (groupedRecipes.Any()) {
|
||||
<optgroup label="@T("Unspecified")"></optgroup>
|
||||
}
|
||||
foreach (var recipe in unspecifiedCategoryRecipes.OrderBy(x => x.Name)) {
|
||||
@Html.SelectOption(Model.Recipe, recipe.Name, recipe.Name, new { recipedescription = recipe.Description })
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div id="recipedescription">@Model.RecipeDescription</div>
|
||||
<div id="recipedescription">@Model.RecipeDescription</div>
|
||||
</fieldset>
|
||||
<div id="throbber">
|
||||
<div class="curtain"></div>
|
||||
|
||||
@@ -30,48 +30,48 @@
|
||||
var selectedTerms = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Terms.Where(x => x.IsChecked).Select(x => new { label = x.Name, value = x.Id, levels = 0, disabled = true }));
|
||||
}
|
||||
<fieldset class="taxonomy-wrapper" data-name-prefix="@Html.FieldNameFor(m => m)" data-id-prefix="@Html.FieldIdFor(m => m)">
|
||||
<legend @if (Model.Settings.Required) { <text> class="required" </text> }>@Model.DisplayName.CamelFriendly()</legend>
|
||||
<legend @if(Model.Settings.Required) { <text>class="required"</text> }>@Model.DisplayName</legend>
|
||||
@if (Model.Settings.Autocomplete) {
|
||||
<div class="terms-editor" data-all-terms="@allTerms" data-selected-terms="@selectedTerms" data-allow-new-terms="@Model.Settings.AllowCustomTerms.ToString().ToLower()" data-singlechoice="@Model.Settings.SingleChoice.ToString().ToLower()">
|
||||
<ul></ul>
|
||||
@if (Model.Settings.SingleChoice) {
|
||||
<div class="hint">@T("Enter a single term. Hit <i>tab</i> or <i>enter</i> to apply the term.") @if (!Model.Settings.AllowCustomTerms) { <text>@T("This taxonomy does not allow you to create new terms.") </text> }</div>
|
||||
}
|
||||
else {
|
||||
<div class="hint">@T("Enter multiple terms. Hit <i>tab</i>, <i>enter</i> or <i>,</i> to add multiple terms.") @if (!Model.Settings.AllowCustomTerms) { <text>@T("This taxonomy does not allow you to create new terms.") </text> }</div>
|
||||
}
|
||||
</div>
|
||||
<div class="terms-editor" data-all-terms="@allTerms" data-selected-terms="@selectedTerms" data-allow-new-terms="@Model.Settings.AllowCustomTerms.ToString().ToLower()" data-singlechoice="@Model.Settings.SingleChoice.ToString().ToLower()">
|
||||
<ul></ul>
|
||||
@if (Model.Settings.SingleChoice) {
|
||||
<div class="hint">@T("Enter a single term. Hit <i>tab</i> or <i>enter</i> to apply the term.") @if (!Model.Settings.AllowCustomTerms) { <text>@T("This taxonomy does not allow you to create new terms.") </text> }</div>
|
||||
}
|
||||
else {
|
||||
<div class="hint">@T("Enter multiple terms. Hit <i>tab</i>, <i>enter</i> or <i>,</i> to add multiple terms.") @if (!Model.Settings.AllowCustomTerms) { <text>@T("This taxonomy does not allow you to create new terms.") </text> }</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (!String.IsNullOrWhiteSpace(Model.Settings.Hint)) {
|
||||
<span class="hint">@Model.Settings.Hint</span>
|
||||
<span class="hint">@Model.Settings.Hint</span>
|
||||
}
|
||||
<div class="hidden-taxonomy-state">
|
||||
<ul class="terms">
|
||||
@foreach (var entry in Model.Terms) {
|
||||
var ti = termIndex;
|
||||
<li>
|
||||
@{
|
||||
var disabled = IsTermDisabled(entry);
|
||||
if (Model.Settings.SingleChoice) {
|
||||
@foreach (var entry in Model.Terms) {
|
||||
var ti = termIndex;
|
||||
<li>
|
||||
@{
|
||||
var disabled = IsTermDisabled(entry);
|
||||
if (Model.Settings.SingleChoice) {
|
||||
<input @if (disabled) { <text> disabled="disabled" </text> } type="radio" value="@Model.Terms[ti].Id" @if (entry.Id == Model.SingleTermId) { <text> checked="checked" </text> } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" />
|
||||
}
|
||||
else {
|
||||
<input @if (disabled) { <text> disabled="disabled" </text> } type="checkbox" value="true" @if (entry.IsChecked) { <text> checked="checked" </text> } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" />
|
||||
}
|
||||
}
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)">@entry.Name</label>
|
||||
@Html.HiddenFor(m => m.Terms[ti].Id)
|
||||
</li>
|
||||
termIndex++;
|
||||
}
|
||||
else {
|
||||
<input @if (disabled) { <text> disabled="disabled" </text> } type="checkbox" value="true" @if (entry.IsChecked) { <text> checked="checked" </text> } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" />
|
||||
}
|
||||
}
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)">@entry.Name</label>
|
||||
@Html.HiddenFor(m => m.Terms[ti].Id)
|
||||
</li>
|
||||
termIndex++;
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
@if (!Model.Terms.Any()) {
|
||||
<div class="no-terms">
|
||||
@T("There are no terms defined for {0} yet.", Model.DisplayName.CamelFriendly())
|
||||
<a href="@Url.Action("Index", "TermAdmin", new { taxonomyId = Model.TaxonomyId, area = "Orchard.Taxonomies" })">@T("Create some terms")</a>
|
||||
</div>
|
||||
<div class="no-terms">
|
||||
@T("There are no terms defined for {0} yet.", Model.DisplayName)
|
||||
<a href="@Url.Action("Index", "TermAdmin", new { taxonomyId = Model.TaxonomyId, area = "Orchard.Taxonomies" })">@T("Create some terms")</a>
|
||||
</div>
|
||||
}
|
||||
@Html.HiddenFor(m => m.TaxonomyId)
|
||||
</fieldset>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
@{
|
||||
Style.Include("admin-taxonomy.css");
|
||||
Script.Require("jQuery");
|
||||
Script.Require("jQuery");
|
||||
Script.Include("~/Themes/TheAdmin/scripts/admin.js").AtFoot();
|
||||
Script.Include("admin-taxonomy-expando.js").AtFoot();
|
||||
|
||||
@@ -14,39 +14,39 @@
|
||||
}
|
||||
|
||||
<fieldset class="taxonomy-wrapper" data-name-prefix="@Html.FieldNameFor(m => m)" data-id-prefix="@Html.FieldIdFor(m => m)">
|
||||
<legend @if (settings.Required) { <text> class="required" </text> }>@Model.DisplayName.CamelFriendly()</legend>
|
||||
|
||||
<legend @if(settings.Required) { <text>class="required"</text> }>@Model.DisplayName</legend>
|
||||
|
||||
<div class="expando">
|
||||
@if (!String.IsNullOrWhiteSpace(Model.Settings.Hint)) {
|
||||
<span class="hint">@Model.Settings.Hint</span>
|
||||
}
|
||||
|
||||
|
||||
<ul class="terms">
|
||||
@foreach (var entry in Model.Terms) {
|
||||
var ti = termIndex;
|
||||
<li>
|
||||
@* Tabs for levels *@ @for (var i = 1; i <= entry.GetLevels(); i++) { <span class="gap"> </span> }
|
||||
@{
|
||||
var disabled = !entry.Selectable || (Model.Settings.LeavesOnly && Model.Terms.Any(t => t.Path.Contains(entry.Path + entry.Id)));
|
||||
if (Model.Settings.SingleChoice) {
|
||||
var disabled = !entry.Selectable || (Model.Settings.LeavesOnly && Model.Terms.Any(t => t.Path.Contains(entry.Path + entry.Id)));
|
||||
if (Model.Settings.SingleChoice) {
|
||||
<input @if (disabled) { <text> disabled="disabled" </text> } type="radio" value="@Model.Terms[ti].Id" @if (entry.Id == Model.SingleTermId) { <text> checked="checked" </text> } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name.ToLower()" />
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
<input @if (disabled) { <text> disabled="disabled" </text> } type="checkbox" value="true" @if (entry.IsChecked) { <text> checked="checked" </text> } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name.ToLower()" />
|
||||
}
|
||||
}
|
||||
}
|
||||
@Html.HiddenFor(m => m.Terms[ti].Id)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)">@entry.Name</label>
|
||||
</li>
|
||||
termIndex++;
|
||||
termIndex++;
|
||||
}
|
||||
</ul>
|
||||
|
||||
|
||||
@if (!Model.Terms.Any()) {
|
||||
<div class="no-terms">
|
||||
@T("There are no terms defined for {0} yet.", Model.DisplayName.CamelFriendly())
|
||||
@T("There are no terms defined for {0} yet.", Model.DisplayName)
|
||||
<a href="@Url.Action("Index", "TermAdmin", new { taxonomyId = Model.TaxonomyId, area = "Orchard.Taxonomies" })">@T("Create some terms")</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@Html.HiddenFor(m => m.TaxonomyId)
|
||||
|
||||
@@ -656,7 +656,7 @@ input.textMedium, input.text-medium, input.text.medium {
|
||||
width:26em;
|
||||
}
|
||||
select {
|
||||
padding:1px;
|
||||
padding:1px;
|
||||
}
|
||||
select:focus, textarea:focus, input.text:focus, input.text-box:focus, input.text-small:focus, input.textMedium:focus, input.text-medium:focus {
|
||||
border-color:#666d51;
|
||||
|
||||
@@ -110,10 +110,18 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy {
|
||||
private void GetShapeType(PlacementShapeLocation shapeLocation, out string shapeType, out string differentiator) {
|
||||
differentiator = "";
|
||||
shapeType = shapeLocation.ShapeType;
|
||||
var separatorLengh = 2;
|
||||
var separatorIndex = shapeType.LastIndexOf("__");
|
||||
|
||||
var dashIndex = shapeType.LastIndexOf('-');
|
||||
if (dashIndex > 0 && dashIndex < shapeType.Length - 1) {
|
||||
differentiator = shapeType.Substring(dashIndex + 1);
|
||||
shapeType = shapeType.Substring(0, dashIndex);
|
||||
if (dashIndex > separatorIndex) {
|
||||
separatorIndex = dashIndex;
|
||||
separatorLengh = 1;
|
||||
}
|
||||
|
||||
if (separatorIndex > 0 && separatorIndex < shapeType.Length - separatorLengh) {
|
||||
differentiator = shapeType.Substring(separatorIndex + separatorLengh);
|
||||
shapeType = shapeType.Substring(0, separatorIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Orchard.Localization.Models {
|
||||
public class DateLocalizationOptions {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Localization.Models;
|
||||
using Orchard.Services;
|
||||
using Orchard.Settings;
|
||||
|
||||
namespace Orchard.Localization.Services {
|
||||
|
||||
@@ -218,6 +216,9 @@ namespace Orchard.Localization.Services {
|
||||
}
|
||||
}
|
||||
|
||||
if (options.EnableTimeZoneConversion)
|
||||
dateValue = DateTime.SpecifyKind(dateValue, DateTimeKind.Utc);
|
||||
|
||||
return dateValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Orchard.Recipes.Models {
|
||||
public string Version { get; set; }
|
||||
public bool IsSetupRecipe { get; set; }
|
||||
public DateTime? ExportUtc { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string Tags { get; set; }
|
||||
public IEnumerable<RecipeStep> RecipeSteps { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user