added path validation to add series/ recent folders.
This commit is contained in:
parent
bf9946b653
commit
4465d50a31
|
@ -164,6 +164,7 @@
|
||||||
<Compile Include="System\SystemModule.cs" />
|
<Compile Include="System\SystemModule.cs" />
|
||||||
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
||||||
<Compile Include="Update\UpdateModule.cs" />
|
<Compile Include="Update\UpdateModule.cs" />
|
||||||
|
<Compile Include="Validation\PathValidator.cs" />
|
||||||
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.RootFolders;
|
using NzbDrone.Core.RootFolders;
|
||||||
using NzbDrone.Api.Mapping;
|
using NzbDrone.Api.Mapping;
|
||||||
|
using NzbDrone.Api.Validation;
|
||||||
|
|
||||||
namespace NzbDrone.Api.RootFolders
|
namespace NzbDrone.Api.RootFolders
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,8 @@ namespace NzbDrone.Api.RootFolders
|
||||||
GetResourceById = GetRootFolder;
|
GetResourceById = GetRootFolder;
|
||||||
CreateResource = CreateRootFolder;
|
CreateResource = CreateRootFolder;
|
||||||
DeleteResource = DeleteFolder;
|
DeleteResource = DeleteFolder;
|
||||||
|
|
||||||
|
SharedValidator.RuleFor(c=>c.Path).IsValidPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RootFolderResource GetRootFolder(int id)
|
private RootFolderResource GetRootFolder(int id)
|
||||||
|
|
|
@ -31,10 +31,10 @@ namespace NzbDrone.Api.Series
|
||||||
|
|
||||||
SharedValidator.RuleFor(s => s.QualityProfileId).ValidId();
|
SharedValidator.RuleFor(s => s.QualityProfileId).ValidId();
|
||||||
|
|
||||||
PutValidator.RuleFor(s => s.Path).NotEmpty();
|
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||||
|
|
||||||
PostValidator.RuleFor(s => s.Path).NotEmpty().When(s => String.IsNullOrEmpty(s.RootFolderPath));
|
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => String.IsNullOrEmpty(s.RootFolderPath));
|
||||||
PostValidator.RuleFor(s => s.RootFolderPath).NotEmpty().When(s => String.IsNullOrEmpty(s.Path));
|
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => String.IsNullOrEmpty(s.Path));
|
||||||
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
using FluentValidation.Validators;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Validation
|
||||||
|
{
|
||||||
|
public class PathValidator : PropertyValidator
|
||||||
|
{
|
||||||
|
public PathValidator()
|
||||||
|
: base("Invalid Path")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsValid(PropertyValidatorContext context)
|
||||||
|
{
|
||||||
|
return context.PropertyValue.ToString().IsPathValid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
using System.Text.RegularExpressions;
|
using System;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using FluentValidation.Validators;
|
using FluentValidation.Validators;
|
||||||
|
|
||||||
|
@ -20,5 +22,10 @@ namespace NzbDrone.Api.Validation
|
||||||
{
|
{
|
||||||
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(s)?://", RegexOptions.IgnoreCase)).WithMessage("must start with http:// or https://");
|
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(s)?://", RegexOptions.IgnoreCase)).WithMessage("must start with http:// or https://");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IRuleBuilderOptions<T, string> IsValidPath<T>(this IRuleBuilder<T, string> ruleBuilder)
|
||||||
|
{
|
||||||
|
return ruleBuilder.SetValidator(new PathValidator());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -95,8 +95,7 @@ namespace NzbDrone.Common.EnsureThat
|
||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Regex windowsInvalidPathRegex = new Regex(@"[/*<>""|]", RegexOptions.Compiled);
|
|
||||||
private static readonly Regex windowsPathRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled);
|
|
||||||
|
|
||||||
[DebuggerStepThrough]
|
[DebuggerStepThrough]
|
||||||
public static Param<string> IsValidPath(this Param<string> param)
|
public static Param<string> IsValidPath(this Param<string> param)
|
||||||
|
@ -104,31 +103,14 @@ namespace NzbDrone.Common.EnsureThat
|
||||||
if (string.IsNullOrWhiteSpace(param.Value))
|
if (string.IsNullOrWhiteSpace(param.Value))
|
||||||
throw ExceptionFactory.CreateForParamValidation(param.Name, ExceptionMessages.EnsureExtensions_IsNotNullOrWhiteSpace);
|
throw ExceptionFactory.CreateForParamValidation(param.Name, ExceptionMessages.EnsureExtensions_IsNotNullOrWhiteSpace);
|
||||||
|
|
||||||
|
if (param.Value.IsPathValid()) return param;
|
||||||
|
|
||||||
if (OsInfo.IsLinux)
|
if (OsInfo.IsLinux)
|
||||||
{
|
|
||||||
if (!param.Value.StartsWith(Path.DirectorySeparatorChar.ToString()))
|
|
||||||
{
|
{
|
||||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid *nix path. paths must start with /", param.Value));
|
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid *nix path. paths must start with /", param.Value));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (windowsInvalidPathRegex.IsMatch(param.Value))
|
|
||||||
{
|
|
||||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. It contains invalid characters", param.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Network path
|
|
||||||
if (param.Value.StartsWith(Path.DirectorySeparatorChar.ToString())) return param;
|
|
||||||
|
|
||||||
if (!windowsPathRegex.IsMatch(param.Value))
|
|
||||||
{
|
|
||||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. paths must be a full path eg. C:\\Windows", param.Value));
|
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. paths must be a full path eg. C:\\Windows", param.Value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using NzbDrone.Common.EnsureThat;
|
using NzbDrone.Common.EnsureThat;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
|
||||||
|
@ -45,6 +46,32 @@ namespace NzbDrone.Common
|
||||||
return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath(), StringComparison.InvariantCultureIgnoreCase);
|
return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath(), StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly Regex WindowsInvalidPathRegex = new Regex(@"[/*<>""|]", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex WindowsPathRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
public static bool IsPathValid(this string path)
|
||||||
|
{
|
||||||
|
if (OsInfo.IsLinux && !path.StartsWith(Path.DirectorySeparatorChar.ToString()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (WindowsInvalidPathRegex.IsMatch(path))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Network path
|
||||||
|
if (path.StartsWith(Path.DirectorySeparatorChar.ToString())) return true;
|
||||||
|
|
||||||
|
if (!WindowsPathRegex.IsMatch(path))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static bool ContainsInvalidPathChars(this string text)
|
public static bool ContainsInvalidPathChars(this string text)
|
||||||
{
|
{
|
||||||
return text.IndexOfAny(Path.GetInvalidPathChars()) >= 0;
|
return text.IndexOfAny(Path.GetInvalidPathChars()) >= 0;
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace NzbDrone.Core.Validation
|
||||||
|
|
||||||
public static IRuleBuilderOptions<T, string> ValidRootUrl<T>(this IRuleBuilder<T, string> ruleBuilder)
|
public static IRuleBuilderOptions<T, string> ValidRootUrl<T>(this IRuleBuilder<T, string> ruleBuilder)
|
||||||
{
|
{
|
||||||
|
ruleBuilder.SetValidator(new NotEmptyValidator(null));
|
||||||
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(?:s)?://[a-z0-9-.]+", RegexOptions.IgnoreCase)).WithMessage("must be valid URL that");
|
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(?:s)?://[a-z0-9-.]+", RegexOptions.IgnoreCase)).WithMessage("must be valid URL that");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using NLog;
|
using System.Runtime.CompilerServices;
|
||||||
|
using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
@ -39,7 +40,7 @@ namespace NzbDrone.Integration.Test
|
||||||
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget));
|
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget));
|
||||||
}
|
}
|
||||||
|
|
||||||
[SetUp]
|
[TestFixtureSetUp]
|
||||||
public void SmokeTestSetup()
|
public void SmokeTestSetup()
|
||||||
{
|
{
|
||||||
_runner = new NzbDroneRunner();
|
_runner = new NzbDroneRunner();
|
||||||
|
@ -63,7 +64,7 @@ namespace NzbDrone.Integration.Test
|
||||||
NamingConfig = new ClientBase<NamingConfigResource>(RestClient, "config/naming");
|
NamingConfig = new ClientBase<NamingConfigResource>(RestClient, "config/naming");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TearDown]
|
[TestFixtureTearDown]
|
||||||
public void SmokeTestTearDown()
|
public void SmokeTestTearDown()
|
||||||
{
|
{
|
||||||
_runner.KillAll();
|
_runner.KillAll();
|
||||||
|
|
|
@ -58,5 +58,17 @@ namespace NzbDrone.Integration.Test
|
||||||
|
|
||||||
RootFolders.All().Should().BeEmpty();
|
RootFolders.All().Should().BeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void invalid_path_should_return_bad_request()
|
||||||
|
{
|
||||||
|
var rootFolder = new RootFolderResource
|
||||||
|
{
|
||||||
|
Path = "invalid_path"
|
||||||
|
};
|
||||||
|
|
||||||
|
var postResponse = RootFolders.InvalidPost(rootFolder);
|
||||||
|
postResponse.Should().NotBeEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,12 +9,6 @@ namespace NzbDrone.Integration.Test
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class SeriesIntegrationTest : IntegrationTest
|
public class SeriesIntegrationTest : IntegrationTest
|
||||||
{
|
{
|
||||||
[Test]
|
|
||||||
public void should_have_no_series_on_start_application()
|
|
||||||
{
|
|
||||||
Series.All().Should().BeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void series_lookup_on_trakt()
|
public void series_lookup_on_trakt()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
'backbone',
|
'backbone',
|
||||||
|
|
|
@ -7,10 +7,11 @@ define(
|
||||||
'AddSeries/RootFolders/Collection',
|
'AddSeries/RootFolders/Collection',
|
||||||
'AddSeries/RootFolders/Model',
|
'AddSeries/RootFolders/Model',
|
||||||
'Shared/LoadingView',
|
'Shared/LoadingView',
|
||||||
|
'Mixins/AsValidatedView',
|
||||||
'Mixins/AutoComplete'
|
'Mixins/AutoComplete'
|
||||||
], function (Marionette, RootFolderCollectionView, RootFolderCollection, RootFolderModel, LoadingView) {
|
], function (Marionette, RootFolderCollectionView, RootFolderCollection, RootFolderModel, LoadingView, AsValidatedView) {
|
||||||
|
|
||||||
return Marionette.Layout.extend({
|
var layout = Marionette.Layout.extend({
|
||||||
template: 'AddSeries/RootFolders/LayoutTemplate',
|
template: 'AddSeries/RootFolders/LayoutTemplate',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
|
@ -55,12 +56,16 @@ define(
|
||||||
Path: this.ui.pathInput.val()
|
Path: this.ui.pathInput.val()
|
||||||
});
|
});
|
||||||
|
|
||||||
RootFolderCollection.add(newDir);
|
this.bindToModelValidation(newDir);
|
||||||
|
|
||||||
newDir.save().done(function () {
|
newDir.save().done(function () {
|
||||||
|
RootFolderCollection.add(newDir);
|
||||||
self.trigger('folderSelected', {model: newDir});
|
self.trigger('folderSelected', {model: newDir});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return AsValidatedView.apply(layout);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
<h3>Select Folder</h3>
|
<h3>Select Folder</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body root-folders-modal">
|
<div class="modal-body root-folders-modal">
|
||||||
<div class="input-prepend input-append x-path">
|
<div class="validation-errors"></div>
|
||||||
|
<div class="input-prepend input-append x-path control-group">
|
||||||
<span class="add-on"> <i class="icon-folder-open"></i></span>
|
<span class="add-on"> <i class="icon-folder-open"></i></span>
|
||||||
<input class="span9" type="text" placeholder="Start Typing Folder Path...">
|
<input class="span9" type="text" validation-name="path" placeholder="Start Typing Folder Path...">
|
||||||
<button class="btn btn-success x-add"><i class="icon-ok"/></button>
|
<button class="btn btn-success x-add">
|
||||||
|
<i class="icon-ok"/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{{#if items}}
|
{{#if items}}
|
||||||
<h4>Recent Folders</h4>
|
<h4>Recent Folders</h4>
|
||||||
|
|
|
@ -4,6 +4,7 @@ define(
|
||||||
'backbone'
|
'backbone'
|
||||||
], function (Backbone) {
|
], function (Backbone) {
|
||||||
return Backbone.Model.extend({
|
return Backbone.Model.extend({
|
||||||
|
urlRoot : window.ApiRoot + '/rootfolder',
|
||||||
defaults: {
|
defaults: {
|
||||||
freeSpace: 0
|
freeSpace: 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ define(
|
||||||
|
|
||||||
this.listenTo(App.vent, Config.Events.ConfigUpdatedEvent, this._onConfigUpdated);
|
this.listenTo(App.vent, Config.Events.ConfigUpdatedEvent, this._onConfigUpdated);
|
||||||
this.listenTo(this.model, 'change', this.render);
|
this.listenTo(this.model, 'change', this.render);
|
||||||
this.listenTo(RootFolders, 'change', this.render);
|
this.listenTo(RootFolders, 'all', this.render);
|
||||||
|
|
||||||
this.rootFolderLayout = new RootFolderLayout();
|
this.rootFolderLayout = new RootFolderLayout();
|
||||||
this.listenTo(this.rootFolderLayout, 'folderSelected', this._setRootFolder);
|
this.listenTo(this.rootFolderLayout, 'folderSelected', this._setRootFolder);
|
||||||
|
@ -108,6 +108,7 @@ define(
|
||||||
_setRootFolder: function (options) {
|
_setRootFolder: function (options) {
|
||||||
App.vent.trigger(App.Commands.CloseModalCommand);
|
App.vent.trigger(App.Commands.CloseModalCommand);
|
||||||
this.ui.rootFolder.val(options.model.id);
|
this.ui.rootFolder.val(options.model.id);
|
||||||
|
this._rootFolderChanged();
|
||||||
},
|
},
|
||||||
|
|
||||||
_addSeries: function () {
|
_addSeries: function () {
|
||||||
|
|
|
@ -39,8 +39,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.page-toolbar {
|
.page-toolbar {
|
||||||
margin-top : 10px;
|
margin-top : 10px;
|
||||||
margin-bottom : 30px;
|
margin-bottom : 30px;
|
||||||
|
@ -78,8 +76,6 @@ th {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
a, .btn {
|
a, .btn {
|
||||||
i {
|
i {
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
|
@ -91,7 +87,6 @@ a, .btn {
|
||||||
background-color : white;
|
background-color : white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color : #1c1c1c;
|
background-color : #1c1c1c;
|
||||||
background-image : url('../Content/Images/pattern.png');
|
background-image : url('../Content/Images/pattern.png');
|
||||||
|
@ -146,3 +141,9 @@ footer {
|
||||||
background-color : transparent;
|
background-color : transparent;
|
||||||
box-shadow : none;
|
box-shadow : none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.validation-errors {
|
||||||
|
i {
|
||||||
|
padding-right : 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,36 +12,48 @@ define(
|
||||||
var originalOnClose = this.prototype.onClose;
|
var originalOnClose = this.prototype.onClose;
|
||||||
var originalBeforeClose = this.prototype.onBeforeClose;
|
var originalBeforeClose = this.prototype.onBeforeClose;
|
||||||
|
|
||||||
|
var errorHandler = function (response) {
|
||||||
|
|
||||||
|
if (response.status === 400) {
|
||||||
|
|
||||||
|
var view = this;
|
||||||
|
var validationErrors = JSON.parse(response.responseText);
|
||||||
|
_.each(validationErrors, function (error) {
|
||||||
|
view.$el.processServerError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var validatedSync = function (method, model,options) {
|
||||||
|
this.$el.removeAllErrors();
|
||||||
|
arguments[2].isValidatedCall = true;
|
||||||
|
return model._originalSync.apply(this, arguments).fail(errorHandler.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
var bindToModel = function (model) {
|
||||||
|
|
||||||
|
if (!model._originalSync) {
|
||||||
|
model._originalSync = model.sync;
|
||||||
|
model.sync = validatedSync.bind(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.prototype.onRender = function () {
|
this.prototype.onRender = function () {
|
||||||
|
|
||||||
Validation.bind(this);
|
Validation.bind(this);
|
||||||
|
this.bindToModelValidation = bindToModel.bind(this);
|
||||||
|
|
||||||
if (!this.originalSync && this.model) {
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.originalSync = this.model.sync;
|
|
||||||
|
|
||||||
|
|
||||||
var boundHandler = errorHandler.bind(this);
|
|
||||||
|
|
||||||
this.model.sync = function () {
|
|
||||||
self.$el.removeAllErrors();
|
|
||||||
|
|
||||||
arguments[2].isValidatedCall = true;
|
|
||||||
|
|
||||||
return self.originalSync.apply(this, arguments).fail(boundHandler);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.model) {
|
if (this.model) {
|
||||||
|
this.bindToModelValidation(this.model);
|
||||||
|
}
|
||||||
|
|
||||||
if (originalOnRender) {
|
if (originalOnRender) {
|
||||||
originalOnRender.call(this);
|
originalOnRender.call(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.prototype.onBeforeClose = function () {
|
this.prototype.onBeforeClose = function () {
|
||||||
|
|
||||||
if (this.model) {
|
if (this.model) {
|
||||||
|
@ -65,22 +77,6 @@ define(
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var errorHandler = function (response) {
|
|
||||||
|
|
||||||
if (response.status === 400) {
|
|
||||||
|
|
||||||
var view = this;
|
|
||||||
|
|
||||||
var validationErrors = JSON.parse(response.responseText);
|
|
||||||
|
|
||||||
_.each(validationErrors, function (error) {
|
|
||||||
view.$el.processServerError(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,6 +8,10 @@ define(
|
||||||
|
|
||||||
var validationName = error.propertyName.toLowerCase();
|
var validationName = error.propertyName.toLowerCase();
|
||||||
|
|
||||||
|
this.find('.validation-errors')
|
||||||
|
.addClass('alert alert-error')
|
||||||
|
.append('<div><i class="icon-exclamation-sign"></i>' + error.errorMessage + '</div>');
|
||||||
|
|
||||||
var input = this.find('[name]').filter(function () {
|
var input = this.find('[name]').filter(function () {
|
||||||
return this.name.toLowerCase() === validationName;
|
return this.name.toLowerCase() === validationName;
|
||||||
});
|
});
|
||||||
|
@ -45,6 +49,7 @@ define(
|
||||||
|
|
||||||
$.fn.removeAllErrors = function () {
|
$.fn.removeAllErrors = function () {
|
||||||
this.find('.error').removeClass('error');
|
this.find('.error').removeClass('error');
|
||||||
|
this.find('.validation-errors').removeClass('alert').removeClass('alert-error').html('');
|
||||||
this.find('.validation-error').remove();
|
this.find('.validation-error').remove();
|
||||||
return this.find('.help-inline.error-message').remove();
|
return this.find('.help-inline.error-message').remove();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue