1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-11-04 10:02:40 +01:00

more validation

This commit is contained in:
Keivan Beigi 2013-08-21 17:36:35 -07:00
parent e4c8255d69
commit 488da59143
14 changed files with 105 additions and 69 deletions

View File

@ -165,7 +165,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\IdValidationRule.cs" /> <Compile Include="Validation\RuleBuilderExtensions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

View File

@ -14,7 +14,7 @@ public class ResourceValidator<TResource> : AbstractValidator<TResource>
public IRuleBuilderInitial<TResource, TProperty> RuleForField<TProperty>(Expression<Func<TResource, IEnumerable<Field>>> fieldListAccessor, string fieldName) public IRuleBuilderInitial<TResource, TProperty> RuleForField<TProperty>(Expression<Func<TResource, IEnumerable<Field>>> fieldListAccessor, string fieldName)
{ {
var rule = new PropertyRule(fieldListAccessor.GetMember(), c => GetValue(c, fieldListAccessor.Compile(), fieldName), null, () => CascadeMode.Continue, typeof(TProperty), typeof(TResource)); var rule = new PropertyRule(fieldListAccessor.GetMember(), c => GetValue(c, fieldListAccessor.Compile(), fieldName), null, () => CascadeMode.Continue, typeof(TProperty), typeof(TResource));
rule.PropertyName += "." + fieldName; rule.PropertyName = fieldName;
rule.DisplayName = new StaticStringSource(fieldName); rule.DisplayName = new StaticStringSource(fieldName);
AddRule(rule); AddRule(rule);
@ -34,7 +34,4 @@ private static object GetValue(object container, Func<TResource, IEnumerable<Fie
return resource.Value; return resource.Value;
} }
} }
} }

View File

@ -30,9 +30,11 @@ public SeriesModule(ISeriesService seriesService, ISeriesStatisticsService serie
DeleteResource = DeleteSeries; DeleteResource = DeleteSeries;
SharedValidator.RuleFor(s => s.QualityProfileId).ValidId(); SharedValidator.RuleFor(s => s.QualityProfileId).ValidId();
SharedValidator.RuleFor(s => s.Path).NotEmpty().When(s => String.IsNullOrEmpty(s.RootFolderPath));
SharedValidator.RuleFor(s => s.RootFolderPath).NotEmpty().When(s => String.IsNullOrEmpty(s.Path));
PutValidator.RuleFor(s => s.Path).NotEmpty();
PostValidator.RuleFor(s => s.Path).NotEmpty().When(s => String.IsNullOrEmpty(s.RootFolderPath));
PostValidator.RuleFor(s => s.RootFolderPath).NotEmpty().When(s => String.IsNullOrEmpty(s.Path));
PostValidator.RuleFor(s => s.Title).NotEmpty(); PostValidator.RuleFor(s => s.Title).NotEmpty();
} }

View File

@ -15,5 +15,4 @@ public static IRuleBuilderOptions<T, int> IsZero<T>(this IRuleBuilder<T, int> ru
return ruleBuilder.SetValidator(new EqualValidator(0)); return ruleBuilder.SetValidator(new EqualValidator(0));
} }
} }
} }

View File

@ -38,8 +38,9 @@
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues"> <option name="myValues">
<value> <value>
<list size="1"> <list size="2">
<item index="0" class="java.lang.String" itemvalue="name" /> <item index="0" class="java.lang.String" itemvalue="name" />
<item index="1" class="java.lang.String" itemvalue="validation-name" />
</list> </list>
</value> </value>
</option> </option>

View File

@ -2,7 +2,7 @@
<label class="control-label">{{label}}</label> <label class="control-label">{{label}}</label>
<div class="controls"> <div class="controls">
<input type="password" name="fields.{{order}}.value"/> <input type="password" name="fields.{{order}}.value" validation-name="{{name}}"/>
{{#if helpText}} {{#if helpText}}
<span class="help-inline"> <span class="help-inline">
<i class="icon-question-sign" title="{{helpText}}"/> <i class="icon-question-sign" title="{{helpText}}"/>

View File

@ -2,7 +2,7 @@
<label class="control-label">{{label}}</label> <label class="control-label">{{label}}</label>
<div class="controls"> <div class="controls">
<input type="text" name="fields.{{order}}.value" spellcheck="false"/> <input type="text" name="fields.{{order}}.value" validation-name="{{name}}" spellcheck="false"/>
{{> FormHelpPartial}} {{> FormHelpPartial}}
</div> </div>
</div> </div>

View File

@ -69,10 +69,13 @@
return false; return false;
//message.message = 'NzbDrone Server Not Reachable. make sure NzbDrone is running.'; //message.message = 'NzbDrone Server Not Reachable. make sure NzbDrone is running.';
} }
else { else if (xmlHttpRequest.status === 400 && ajaxOptions.isValidatedCall) {
message.message = '[{0}] {1} : {2}'.format(ajaxOptions.type, xmlHttpRequest.statusText, ajaxOptions.url); return false;
} }
message.message = '[{0}] {1} : {2}'.format(ajaxOptions.type, xmlHttpRequest.statusText, ajaxOptions.url);
window.Messenger().post(message); window.Messenger().post(message);
return false; return false;
}); });

View File

@ -2,7 +2,7 @@ define(
[ [
'backbone.validation', 'backbone.validation',
'underscore', 'underscore',
'jQuery/Validation' 'jQuery/jquery.validation'
], function (Validation, _) { ], function (Validation, _) {
'use strict'; 'use strict';
@ -27,7 +27,10 @@ define(
var boundHandler = errorHandler.bind(this); var boundHandler = errorHandler.bind(this);
this.model.sync = function () { this.model.sync = function () {
self.$el.removeBootstrapError(); self.$el.removeAllErrors();
arguments[2].isValidatedCall = true;
return self.originalSync.apply(this, arguments).fail(boundHandler); return self.originalSync.apply(this, arguments).fail(boundHandler);
}; };
} }
@ -71,9 +74,13 @@ define(
var validationErrors = JSON.parse(response.responseText); var validationErrors = JSON.parse(response.responseText);
_.each(validationErrors, function (error) { _.each(validationErrors, function (error) {
view.$el.addBootstrapError(error); view.$el.processServerError(error);
}); });
} }
}; };
return this;
}; };
}); });

View File

@ -5,8 +5,9 @@ define(
'marionette', 'marionette',
'Quality/QualityProfileCollection', 'Quality/QualityProfileCollection',
'Mixins/AsModelBoundView', 'Mixins/AsModelBoundView',
'Mixins/AsValidatedView',
'Mixins/AutoComplete' 'Mixins/AutoComplete'
], function (App, Marionette, QualityProfiles, AsModelBoundView) { ], function (App, Marionette, QualityProfiles, AsModelBoundView, AsValidatedView) {
var view = Marionette.ItemView.extend({ var view = Marionette.ItemView.extend({
template: 'Series/Edit/EditSeriesTemplate', template: 'Series/Edit/EditSeriesTemplate',
@ -49,5 +50,6 @@ define(
}); });
return AsModelBoundView.apply(view); AsModelBoundView.apply(view);
return AsValidatedView.apply(view);
}); });

View File

@ -1,26 +1,29 @@
'use strict'; 'use strict';
define([ define(
'app', [
'marionette', 'app',
'Settings/Notifications/DeleteView', 'marionette',
'Mixins/AsModelBoundView'], 'Settings/Notifications/DeleteView',
function (App, Marionette, DeleteView, AsModelBoundView) { 'Mixins/AsModelBoundView',
'Mixins/AsValidatedView'
], function (App, Marionette, DeleteView, AsModelBoundView, AsValidatedView) {
var view = Marionette.ItemView.extend({ var view = Marionette.ItemView.extend({
template: 'Settings/Indexers/ItemTemplate', template: 'Settings/Indexers/ItemTemplate',
tagName : 'li', tagName : 'li',
events: { events: {
'click .x-delete': '_deleteIndexer' 'click .x-delete': '_deleteIndexer'
}, },
_deleteIndexer: function () {
var view = new DeleteView({ model: this.model});
App.modalRegion.show(view);
}
});
AsModelBoundView.call(view);
return AsValidatedView.call(view);
_deleteIndexer: function () {
var view = new DeleteView({ model: this.model});
App.modalRegion.show(view);
}
}); });
return AsModelBoundView.call(view);
});

View File

@ -1,5 +1,5 @@
<fieldset> <fieldset>
<legend>Sorting</legend> <legend>Season Folder</legend>
<!--TODO: Remove this and move it to Add Series--> <!--TODO: Remove this and move it to Add Series-->
<div class="control-group"> <div class="control-group">

View File

@ -1,30 +0,0 @@
define(
[
'jquery'
], function ($) {
'use strict';
$.fn.addBootstrapError = function (error) {
var input = this.find('[name]').filter(function () {
return this.name.toLowerCase() === error.propertyName.toLowerCase();
});
var controlGroup = input.parents('.control-group');
if (controlGroup.find('.help-inline').length === 0) {
controlGroup.find('.controls').append('<span class="help-inline error-message">' + error.errorMessage + '</span>');
}
controlGroup.addClass('error');
return controlGroup.find('.help-inline').text();
};
$.fn.removeBootstrapError = function () {
this.removeClass('error');
return this.parents('.control-group').find('.help-inline.error-message').remove();
};
});

View File

@ -0,0 +1,52 @@
define(
[
'jquery'
], function ($) {
'use strict';
$.fn.processServerError = function (error) {
var validationName = error.propertyName.toLowerCase();
var input = this.find('[name]').filter(function () {
return this.name.toLowerCase() === validationName;
});
if (input.length === 0) {
input = this.find('[validation-name]').filter(function () {
return $(this).attr('validation-name').toLowerCase() === validationName;
});
//still not found?
if (input.length === 0) {
this.addFormError(error);
console.error('couldn\'t find input for ' + error.propertyName);
return this;
}
}
var controlGroup = input.parents('.control-group');
controlGroup.find('.controls').append('<span class="help-inline error-message">' + error.errorMessage + '</span>');
controlGroup.addClass('error');
return controlGroup.find('.help-inline').text();
};
$.fn.processClientError = function (error) {
};
$.fn.addFormError = function (error) {
this.find('.control-group').parent().prepend('<div class="alert alert-error validation-error">'+ error.errorMessage +'</div>')
};
$.fn.removeAllErrors = function () {
this.find('.error').removeClass('error');
this.find('.validation-error').remove();
return this.find('.help-inline.error-message').remove();
};
});