Merge branch '1.9.x' into dev

Conflicts:
	README.md
	src/Orchard.Web/Modules/Orchard.Dashboards/Web.config
	src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj
	src/Orchard.Web/Modules/Orchard.DynamicForms/ValidationRules/Compare.cs
	src/Orchard.Web/Modules/Orchard.DynamicForms/ValidationRules/EmailAddress.cs
	src/Orchard.Web/Modules/Orchard.DynamicForms/ValidationRules/Mandatory.cs
	src/Orchard.Web/Modules/Orchard.DynamicForms/ValidationRules/OptionRequired.cs
	src/Orchard.Web/Modules/Orchard.DynamicForms/ValidationRules/RegularExpression.cs
	src/Orchard.Web/Modules/Orchard.DynamicForms/ValidationRules/Required.cs
	src/Orchard.Web/Modules/Orchard.DynamicForms/ValidationRules/StringLength.cs
This commit is contained in:
Sipke Schoorstra
2015-11-03 22:44:13 +01:00
18 changed files with 257 additions and 24 deletions

View File

@@ -0,0 +1,79 @@
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Helpers;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
namespace Orchard.DynamicForms.Drivers {
public class UrlFieldElementDriver : FormsElementDriver<UrlField> {
private readonly ITokenizer _tokenizer;
public UrlFieldElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
_tokenizer = tokenizer;
}
protected override EditorResult OnBuildEditor(UrlField element, ElementEditorContext context) {
var autoLabelEditor = BuildForm(context, "AutoLabel");
var webAddressFieldEditor = BuildForm(context, "UrlField");
var webAddressFieldValidation = BuildForm(context, "UrlFieldValidation", "Validation:10");
return Editor(context, autoLabelEditor, webAddressFieldEditor, webAddressFieldValidation);
}
protected override void DescribeForm(DescribeContext context) {
context.Form("UrlField", factory => {
var shape = (dynamic) factory;
var form = shape.Fieldset(
Id: "UrlField",
_Value: shape.Textbox(
Id: "Value",
Name: "Value",
Title: "Value",
Classes: new[] {"text", "medium", "tokenized"},
Description: T("The value of this URL field.")));
return form;
});
context.Form("UrlFieldValidation", factory => {
var shape = (dynamic) factory;
var form = shape.Fieldset(
Id: "UrlFieldValidation",
_IsRequired: shape.Checkbox(
Id: "IsRequired",
Name: "IsRequired",
Title: "Required",
Value: "true",
Description: T("Tick this checkbox to make this email field a required field.")),
_MaximumLength: shape.Textbox(
Id: "MaximumLength",
Name: "MaximumLength",
Title: "Maximum Length",
Classes: new[] {"text", "medium", "tokenized"},
Description: T("The maximum length allowed.")),
_CustomValidationMessage: shape.Textbox(
Id: "CustomValidationMessage",
Name: "CustomValidationMessage",
Title: "Custom Validation Message",
Classes: new[] {"text", "large", "tokenized"},
Description: T("Optionally provide a custom validation message.")),
_ShowValidationMessage: shape.Checkbox(
Id: "ShowValidationMessage",
Name: "ShowValidationMessage",
Title: "Show Validation Message",
Value: "true",
Description: T("Autogenerate a validation message when a validation error occurs for the current field. Alternatively, to control the placement of the validation message you can use the ValidationMessage element instead.")));
return form;
});
}
protected override void OnDisplaying(UrlField element, ElementDisplayingContext context) {
context.ElementShape.ProcessedName = _tokenizer.Replace(element.Name, context.GetTokenData());
context.ElementShape.ProcessedLabel = _tokenizer.Replace(element.Label, context.GetTokenData());
context.ElementShape.ProcessedValue = _tokenizer.Replace(element.RuntimeValue, context.GetTokenData());
}
}
}

View File

@@ -0,0 +1,9 @@
using Orchard.DynamicForms.Validators.Settings;
namespace Orchard.DynamicForms.Elements {
public class UrlField : LabeledFormElement {
public UrlFieldValidationSettings ValidationSettings {
get { return Data.GetModel<UrlFieldValidationSettings>(""); }
}
}
}

View File

@@ -169,7 +169,9 @@
<Compile Include="Bindings\InputFieldBindings.cs" />
<Compile Include="Bindings\TaxonomyFieldBindings.cs" />
<Compile Include="Drivers\FieldsetElementDriver.cs" />
<Compile Include="Drivers\UrlFieldElementDriver.cs" />
<Compile Include="Elements\Fieldset.cs" />
<Compile Include="Elements\UrlField.cs" />
<Compile Include="Bindings\NumericFieldBindings.cs" />
<Compile Include="Forms\AddModelErrorForm.cs" />
<Compile Include="Forms\SelectDynamicForms.cs" />
@@ -220,7 +222,9 @@
<Compile Include="ValidationRules\EmailAddress.cs" />
<Compile Include="ValidationRules\RegularExpression.cs" />
<Compile Include="ValidationRules\StringLength.cs" />
<Compile Include="ValidationRules\UrlAddress.cs" />
<Compile Include="Validators\QueryValidator.cs" />
<Compile Include="Validators\Settings\UrlFieldValidationSettings.cs" />
<Compile Include="Validators\TaxonomyValidator.cs" />
<Compile Include="Validators\EnumerationValidator.cs" />
<Compile Include="Validators\CheckBoxValidator.cs" />
@@ -273,6 +277,7 @@
<Compile Include="Validators\ReCaptchaValidator.cs" />
<Compile Include="Validators\TextAreaValidator.cs" />
<Compile Include="Validators\TextFieldValidator.cs" />
<Compile Include="Validators\UrlFieldValidator.cs" />
<Compile Include="ViewModels\FieldValidationSettings.cs" />
<Compile Include="ViewModels\FormBindingSettings.cs" />
<Compile Include="Helpers\ContentTypeDefinitionExtensions.cs" />
@@ -509,6 +514,12 @@
<ItemGroup>
<Content Include="Assets.json" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Elements\UrlField.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Elements\UrlField.Design.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -22,7 +22,9 @@ namespace Orchard.DynamicForms.ValidationRules {
}
private LocalizedString GetValidationMessage(ValidationContext context) {
return new LocalizedString(Tokenize(T(ErrorMessage.WithDefault(String.Format("{0} must match the value of {1}.", context.FieldName, TargetName))).ToString(), context));
return String.IsNullOrWhiteSpace(ErrorMessage)
? T("{0} must match the value of {1}.", context.FieldName, TargetName)
: T(ErrorMessage, context);
}
}
}

View File

@@ -28,7 +28,9 @@ namespace Orchard.DynamicForms.ValidationRules {
}
private LocalizedString GetValidationMessage(ValidationContext context) {
return new LocalizedString(Tokenize(T(ErrorMessage.WithDefault(String.Format("{0} is not a valid email address.", context.FieldName))).ToString(), context));
return String.IsNullOrWhiteSpace(ErrorMessage)
? T("{0} is not a valid email address.", context.FieldName)
: T(ErrorMessage);
}
}
}

View File

@@ -18,7 +18,9 @@ namespace Orchard.DynamicForms.ValidationRules {
}
private LocalizedString GetValidationMessage(ValidationContext context) {
return new LocalizedString(Tokenize(T(ErrorMessage.WithDefault(String.Format("{0} is a mandatory field.", context.FieldName))).ToString(), context));
return String.IsNullOrWhiteSpace(ErrorMessage)
? T("{0} is a mandatory field.", context.FieldName)
: T(ErrorMessage);
}
}
}

View File

@@ -18,7 +18,9 @@ namespace Orchard.DynamicForms.ValidationRules {
}
private LocalizedString GetValidationMessage(ValidationContext context) {
return new LocalizedString(Tokenize(T(ErrorMessage.WithDefault(String.Format("An option is required for {0}.", context.FieldName))).ToString(), context));
return String.IsNullOrWhiteSpace(ErrorMessage)
? T("An option is required for {0}.", context.FieldName)
: T(ErrorMessage, context);
}
}
}

View File

@@ -27,7 +27,9 @@ namespace Orchard.DynamicForms.ValidationRules {
}
private LocalizedString GetValidationMessage(ValidationContext context) {
return new LocalizedString(Tokenize(T(ErrorMessage.WithDefault(String.Format("{0} must match the following pattern: {1}.", context.FieldName, Pattern))).ToString(), context));
return String.IsNullOrWhiteSpace(ErrorMessage)
? T("{0} must match the following pattern: {1}.", context.FieldName, Pattern)
: T(ErrorMessage);
}
}
}

View File

@@ -18,7 +18,9 @@ namespace Orchard.DynamicForms.ValidationRules {
}
private LocalizedString GetValidationMessage(ValidationContext context) {
return new LocalizedString(Tokenize(T(ErrorMessage.WithDefault(String.Format("{0} is a required field.", context.FieldName))).ToString(), context));
return String.IsNullOrWhiteSpace(ErrorMessage)
? T("{0} is a required field.", context.FieldName)
: T(ErrorMessage);
}
}
}

View File

@@ -40,12 +40,12 @@ namespace Orchard.DynamicForms.ValidationRules {
}
private LocalizedString GetValidationMessage(ValidationContext context) {
if (!String.IsNullOrWhiteSpace(ErrorMessage))
return new LocalizedString(Tokenize(String.Format(T(ErrorMessage).ToString(), context.FieldName, Minimum, Maximum), context));
if(!String.IsNullOrWhiteSpace(ErrorMessage))
return T(ErrorMessage, context.FieldName, Minimum, Maximum);
if(Minimum != null && Maximum != null)
return T("{0} must be between {1} and {2} characters long.", context.FieldName, Minimum, Maximum);
else if (Minimum != null)
if (Minimum != null)
return T("{0} must be at least {1} characters long.", context.FieldName, Minimum);
return T("{0} must be at most {1} characters long.", context.FieldName, Maximum);

View File

@@ -0,0 +1,36 @@
using System;
using System.Text.RegularExpressions;
using Orchard.DynamicForms.Helpers;
using Orchard.DynamicForms.Services;
using Orchard.DynamicForms.Services.Models;
using Orchard.Localization;
namespace Orchard.DynamicForms.ValidationRules {
public class UrlAddress : ValidationRule {
public UrlAddress() {
RegexOptions = RegexOptions.Singleline | RegexOptions.IgnoreCase;
Pattern = @"^http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$";
}
public string Pattern { get; set; }
public RegexOptions RegexOptions { get; set; }
public override void Validate(ValidateInputContext context) {
if (!Regex.IsMatch(context.AttemptedValue, Pattern, RegexOptions)) {
var message = GetValidationMessage(context);
context.ModelState.AddModelError(context.FieldName, message.Text);
}
}
public override void RegisterClientAttributes(RegisterClientValidationAttributesContext context) {
context.ClientAttributes["data-val-regex"] = GetValidationMessage(context).Text;
context.ClientAttributes["data-val-regex-pattern"] = Pattern;
}
private LocalizedString GetValidationMessage(ValidationContext context) {
return String.IsNullOrWhiteSpace(ErrorMessage)
? T("{0} is not a valid URL.", context.FieldName)
: T(ErrorMessage);
}
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.DynamicForms.Services.Models;
namespace Orchard.DynamicForms.Validators.Settings {
public class UrlFieldValidationSettings : ValidationSettingsBase {
public bool? IsRequired { get; set; }
public int? MaximumLength { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using Orchard.DynamicForms.Elements;
using Orchard.DynamicForms.Services;
using Orchard.DynamicForms.ValidationRules;
namespace Orchard.DynamicForms.Validators {
public class UrlFieldValidator : ElementValidator<UrlField> {
private readonly IValidationRuleFactory _validationRuleFactory;
public UrlFieldValidator(IValidationRuleFactory validationRuleFactory) {
_validationRuleFactory = validationRuleFactory;
}
protected override IEnumerable<IValidationRule> GetValidationRules(UrlField element) {
var settings = element.ValidationSettings;
if (settings.IsRequired == true)
yield return _validationRuleFactory.Create<Required>(settings.CustomValidationMessage);
if (settings.MaximumLength != null) {
yield return _validationRuleFactory.Create<StringLength>(r => {
r.Maximum = settings.MaximumLength;
r.ErrorMessage = settings.CustomValidationMessage;
});
}
}
}
}

View File

@@ -0,0 +1,21 @@
@using Orchard.DynamicForms.Elements
@using Orchard.Layouts.Helpers
@{
var element = (UrlField)Model.Element;
var tagBuilder = TagBuilderExtensions.CreateElementTagBuilder(Model, "input");
tagBuilder.AddCssClass("text design");
tagBuilder.Attributes["type"] = "url";
tagBuilder.Attributes["value"] = element.Value;
tagBuilder.Attributes["name"] = element.Name;
}
@if (element.ShowLabel) {
<div>
<label for="@element.HtmlId">@element.Label</label>
@tagBuilder.ToHtmlString(TagRenderMode.SelfClosing)
</div>
}
else {
@tagBuilder.ToHtmlString(TagRenderMode.SelfClosing)
}

View File

@@ -0,0 +1,25 @@
@using Orchard.DisplayManagement.Shapes
@using Orchard.DynamicForms.Elements
@using Orchard.Layouts.Helpers
@{
var element = (UrlField)Model.Element;
var tagBuilder = (OrchardTagBuilder)TagBuilderExtensions.CreateElementTagBuilder(Model, "input");
tagBuilder.AddCssClass("text");
tagBuilder.Attributes["type"] = "url";
tagBuilder.Attributes["value"] = Model.ProcessedValue;
tagBuilder.Attributes["name"] = Model.ProcessedName;
tagBuilder.AddClientValidationAttributes((IDictionary<string, string>)Model.ClientValidationAttributes);
if (!ViewData.ModelState.IsValidField(Model.ProcessedName)) {
tagBuilder.AddCssClass("input-validation-error");
}
}
@if (element.ShowLabel) {
<label for="@element.HtmlId">@Model.ProcessedLabel</label>
}
@tagBuilder.ToHtmlString(TagRenderMode.SelfClosing)
@if (element.ValidationSettings.ShowValidationMessage == true) {
@Html.ValidationMessage((string)Model.ProcessedName)
}

View File

@@ -176,8 +176,8 @@
break;
case "save":
{
var frameDoc = self.frame.getDocument();
var form = frameDoc.find("form:first");
var frameWindow = self.frame.getWindow();
var form = frameWindow.$("form:first");
form.submit();
}
break;