mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Merge
--HG-- branch : InputShapes
This commit is contained in:
Binary file not shown.
@@ -101,6 +101,31 @@ namespace Orchard.Core.Shapes {
|
||||
//object ActionLinkValue,
|
||||
//object Description,
|
||||
string EnabledBy) {
|
||||
|
||||
/*
|
||||
* #id #type #name #title #title_display #field_prefix #field_suffix #description #required
|
||||
* #title_display=={before,after,invisible,attribute,none}
|
||||
*
|
||||
* {form_element}
|
||||
* <div attributes id="#id" class="form-type-#type form-item-#name">
|
||||
* {form_element_label}
|
||||
* <label class="option?#title_display==after element-invisible?#title_display==invisible" for="#id">
|
||||
* #title
|
||||
* {form_required_marker}
|
||||
* <span class='form-required'>This field is required.</span>
|
||||
* {/form_required_marker}?#required
|
||||
* </label>
|
||||
* {/form_element_label}?#title
|
||||
* <span class="field-prefix">#field_prefix</span>?#field_prefix
|
||||
* #child_content
|
||||
* <span class="field-suffix">#field_suffix</span>?#field_suffix
|
||||
* {form_element_label/}?#title_display==after
|
||||
* <div class="description">#description</div>?
|
||||
* </div>
|
||||
* {/form_element}
|
||||
*/
|
||||
|
||||
|
||||
// Wraps an input with metadata as follows (most of it is optional and won't render if not present):
|
||||
/*
|
||||
<div data-controllerid="{EnabledByInputId}">
|
||||
@@ -173,6 +198,33 @@ namespace Orchard.Core.Shapes {
|
||||
Output.WriteLine(div.ToString(TagRenderMode.EndTag));
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public void Form(Action<object> Output, dynamic Display, dynamic Shape) {
|
||||
OrchardTagBuilder tag = _tagBuilderFactory.Create(Shape, "form");
|
||||
Output(tag.ToString(TagRenderMode.StartTag));
|
||||
foreach(var item in Shape) {
|
||||
Output(Display(item));
|
||||
}
|
||||
Output(tag.ToString(TagRenderMode.EndTag));
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public void Fieldset(Action<object> Output, dynamic Display, dynamic Shape) {
|
||||
OrchardTagBuilder tag = _tagBuilderFactory.Create(Shape, "fieldset");
|
||||
Output(tag.ToString(TagRenderMode.StartTag));
|
||||
foreach(var item in Shape) {
|
||||
Output(Display(item));
|
||||
}
|
||||
Output(tag.ToString(TagRenderMode.EndTag));
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public IHtmlString Textbox(dynamic Display, dynamic Shape) {
|
||||
Shape.Metadata.Type = "Input";
|
||||
Shape.Type = "textbox";
|
||||
return Display(Shape);
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public IHtmlString Input(HtmlHelper Html, dynamic Shape, dynamic Display, string Type, string Name, dynamic Value) {
|
||||
var tag = (TagBuilder)_tagBuilderFactory.Create(Shape, "input");
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Xml.Linq;
|
||||
using Orchard.Experimental.Models;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.Themes;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.UI.Admin;
|
||||
@@ -39,6 +40,19 @@ namespace Orchard.Experimental.Controllers {
|
||||
public ActionResult Simple() {
|
||||
return View(new Simple { Title = "This is a simple text", Quantity = 5 });
|
||||
}
|
||||
|
||||
public ActionResult Forms() {
|
||||
var form = Shape.Form();
|
||||
form.Captcha = Shape.Fieldset(Title: T("Captcha"), Response: Shape.Textbox());
|
||||
form.Actions = Shape.Fieldset(Ok: Shape.Button(T("OK")), Cancel: Shape.Button(T("Cancel")));
|
||||
|
||||
form.Add(form.Captcha);
|
||||
form.Add(form.Actions);
|
||||
form.Actions.Add(form.Actions.Ok);
|
||||
form.Actions.Add(form.Actions.Cancel);
|
||||
|
||||
return new ShapeResult(this, form);
|
||||
}
|
||||
|
||||
public ActionResult _RenderableAction() {
|
||||
return PartialView("_RenderableAction", "This is render action");
|
||||
|
||||
@@ -81,6 +81,8 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
|
||||
|
||||
if (parameter.Name == "Output" && parameter.ParameterType == typeof(TextWriter))
|
||||
return output;
|
||||
if (parameter.Name == "Output" && parameter.ParameterType == typeof(Action<object>))
|
||||
return new Action<object>(output.Write);
|
||||
|
||||
// meh--
|
||||
if (parameter.Name == "Html") {
|
||||
@@ -95,7 +97,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
|
||||
}
|
||||
|
||||
var getter = _getters.GetOrAdd(parameter.Name, n =>
|
||||
CallSite<Func<CallSite, object, object>>.Create(
|
||||
CallSite<Func<CallSite, object, dynamic>>.Create(
|
||||
Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
|
||||
CSharpBinderFlags.None, n, null, new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })));
|
||||
|
||||
@@ -110,13 +112,13 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
|
||||
}
|
||||
|
||||
|
||||
static readonly ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>> _getters =
|
||||
new ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>>();
|
||||
static readonly ConcurrentDictionary<string, CallSite<Func<CallSite, object, dynamic>>> _getters =
|
||||
new ConcurrentDictionary<string, CallSite<Func<CallSite, object, dynamic>>>();
|
||||
|
||||
static readonly ConcurrentDictionary<Type, Func<object, object>> _converters =
|
||||
new ConcurrentDictionary<Type, Func<object, object>>();
|
||||
static readonly ConcurrentDictionary<Type, Func<dynamic, object>> _converters =
|
||||
new ConcurrentDictionary<Type, Func<dynamic, object>>();
|
||||
|
||||
static Func<object, object> CompileConverter(Type targetType) {
|
||||
static Func<dynamic, object> CompileConverter(Type targetType) {
|
||||
var valueParameter = Expression.Parameter(typeof(object), "value");
|
||||
|
||||
return Expression.Lambda<Func<object, object>>(
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
positional = positional.Skip(1);
|
||||
}
|
||||
|
||||
var shapeBehavior = new Shape.ShapeBehavior();
|
||||
if (creatingContext.BaseType == typeof(Array)) {
|
||||
// array is a hint - not an intended base class
|
||||
creatingContext.BaseType = typeof(Shape);
|
||||
@@ -67,7 +66,7 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
new ClaySharp.Behaviors.InterfaceProxyBehavior(),
|
||||
new ClaySharp.Behaviors.PropBehavior(),
|
||||
new ClaySharp.Behaviors.NilResultBehavior(),
|
||||
shapeBehavior,
|
||||
new Shape.ShapeBehavior(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -92,7 +91,6 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
ShapeType = creatingContext.ShapeType,
|
||||
Shape = ClayActivator.CreateInstance(creatingContext.BaseType, creatingContext.Behaviors)
|
||||
};
|
||||
shapeBehavior._shape = createdContext.Shape;
|
||||
var shapeMetadata = new ShapeMetadata { Type = shapeType };
|
||||
createdContext.Shape.Metadata = shapeMetadata;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Orchard.DisplayManagement.Shapes {
|
||||
public virtual IDictionary<string, string> Attributes { get { return _attributes; } }
|
||||
public virtual IEnumerable<dynamic> Items { get { return _items; } }
|
||||
|
||||
public virtual Shape Add(object item, string position = DefaultPosition) {
|
||||
public virtual Shape Add(object item, string position = null) {
|
||||
// pszmyd: Ignoring null shapes
|
||||
if (item == null) {
|
||||
return this;
|
||||
@@ -35,7 +35,7 @@ namespace Orchard.DisplayManagement.Shapes {
|
||||
item is String ) {
|
||||
// need to implement positioned wrapper for non-shape objects
|
||||
}
|
||||
else {
|
||||
else if (item is IShape) {
|
||||
((dynamic) item).Metadata.Position = position;
|
||||
}
|
||||
}
|
||||
@@ -58,14 +58,12 @@ namespace Orchard.DisplayManagement.Shapes {
|
||||
}
|
||||
|
||||
public class ShapeBehavior : ClayBehavior {
|
||||
public dynamic _shape;
|
||||
// This can't really be done without a hack until indexer methods offer a self parameter
|
||||
public override object SetIndex(Func<object> proceed, IEnumerable<object> keys, object value) {
|
||||
public override object SetIndex(Func<object> proceed, dynamic self, IEnumerable<object> keys, object value) {
|
||||
if (keys.Count() == 1) {
|
||||
var name = keys.Single().ToString();
|
||||
if (name.Equals("Id")) {
|
||||
// need to mutate the actual type
|
||||
var s = _shape as Shape;
|
||||
var s = self as Shape;
|
||||
if (s != null) {
|
||||
s.Id = System.Convert.ToString(value);
|
||||
}
|
||||
@@ -73,21 +71,21 @@ namespace Orchard.DisplayManagement.Shapes {
|
||||
}
|
||||
if (name.Equals("Classes")) {
|
||||
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
|
||||
MergeClasses(args, _shape.Classes);
|
||||
MergeClasses(args, self.Classes);
|
||||
return value;
|
||||
}
|
||||
if (name.Equals("Attributes")) {
|
||||
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
|
||||
MergeAttributes(args, _shape.Attributes);
|
||||
MergeAttributes(args, self.Attributes);
|
||||
return value;
|
||||
}
|
||||
if (name.Equals("Items")) {
|
||||
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
|
||||
MergeItems(args, _shape.Items);
|
||||
MergeItems(args, self);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return base.SetIndex(proceed, keys, value);
|
||||
return proceed();
|
||||
}
|
||||
|
||||
public override object InvokeMember(Func<object> proceed, dynamic self, string name, INamedEnumerable<object> args) {
|
||||
|
||||
@@ -19,7 +19,4 @@ namespace Orchard.Localization.Services {
|
||||
return new CultureSelectorResult { Priority = -5, CultureName = currentCultureName };
|
||||
}
|
||||
}
|
||||
|
||||
public class CultureSettings {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +260,7 @@
|
||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||
<Compile Include="Themes\ThemeManager.cs" />
|
||||
<Compile Include="Time\CurrentTimeZoneWorkContext.cs" />
|
||||
<Compile Include="Time\FallbackTimeZoneSelector.cs" />
|
||||
<Compile Include="Time\SiteTimeZoneSelector.cs" />
|
||||
<Compile Include="Time\IClock.cs" />
|
||||
<Compile Include="Time\ITimeZoneSelector.cs" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.Time {
|
||||
public class CurrentTimeZoneWorkContext : IWorkContextStateProvider {
|
||||
@@ -12,21 +13,23 @@ namespace Orchard.Time {
|
||||
|
||||
public Func<WorkContext, T> Get<T>(string name) {
|
||||
if (name == "CurrentTimeZone") {
|
||||
return ctx => {
|
||||
var timeZone = _timeZoneSelectors
|
||||
.Select(x => x.GetTimeZone(ctx.HttpContext))
|
||||
.Where(x => x != null)
|
||||
.OrderByDescending(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (timeZone == null || timeZone.TimeZone == null) {
|
||||
return (T)(object)TimeZoneInfo.Utc;
|
||||
}
|
||||
|
||||
return (T)(object)timeZone.TimeZone;
|
||||
};
|
||||
return ctx => (T)(object)CurrentTimeZone(ctx.HttpContext);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
TimeZoneInfo CurrentTimeZone(HttpContextBase httpContext) {
|
||||
var timeZone = _timeZoneSelectors
|
||||
.Select(x => x.GetTimeZone(httpContext))
|
||||
.Where(x => x != null)
|
||||
.OrderByDescending(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (timeZone == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return timeZone.TimeZone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
src/Orchard/Time/FallbackTimeZoneSelector.cs
Normal file
16
src/Orchard/Time/FallbackTimeZoneSelector.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.Time {
|
||||
/// <summary>
|
||||
/// Implements <see cref="ITimeZoneSelector"/> by providing the timezone defined in the machine's local settings.
|
||||
/// </summary>
|
||||
public class FallbackTimeZoneSelector : ITimeZoneSelector {
|
||||
public TimeZoneSelectorResult GetTimeZone(HttpContextBase context) {
|
||||
return new TimeZoneSelectorResult {
|
||||
Priority = -100,
|
||||
TimeZone = TimeZoneInfo.Local
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,13 @@ namespace Orchard.Time {
|
||||
|
||||
public TimeZoneSelectorResult GetTimeZone(HttpContextBase context) {
|
||||
var siteTimeZoneId = _workContextAccessor.GetContext(context).CurrentSite.SiteTimeZone;
|
||||
|
||||
if (String.IsNullOrEmpty(siteTimeZoneId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TimeZoneSelectorResult {
|
||||
Priority = 0,
|
||||
Priority = -5,
|
||||
TimeZone = TimeZoneInfo.FindSystemTimeZoneById(siteTimeZoneId)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Orchard.UI.Zones {
|
||||
}
|
||||
return parentMember;
|
||||
}
|
||||
public override object GetIndex(Func<object> proceed, System.Collections.Generic.IEnumerable<object> keys) {
|
||||
public override object GetIndex(Func<object> proceed, object self, System.Collections.Generic.IEnumerable<object> keys) {
|
||||
if (keys.Count() == 1) {
|
||||
return GetMember(proceed, null, System.Convert.ToString(keys.Single()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user