Files
edx-platform/cms/static/js/views/validation.js
Syed Ali Abbas Zaidi 8480dbc228 chore: apply amnesty on existing not fixable issues (#32215)
* fix: eslint operator-linebreak issue

* fix: eslint quotes issue

* fix: react jsx indent and props issues

* fix: eslint trailing spaces issues

* fix: eslint line around directives issue

* fix: eslint semi rule

* fix: eslint newline per chain rule

* fix: eslint space infix ops rule

* fix: eslint space-in-parens issue

* fix: eslint space before function paren issue

* fix: eslint space before blocks issue

* fix: eslint arrow body style issue

* fix: eslint dot-location issue

* fix: eslint quotes issue

* fix: eslint quote props issue

* fix: eslint operator assignment issue

* fix: eslint new line after import issue

* fix: indent issues

* fix: operator assignment issue

* fix: all autofixable eslint issues

* fix: all react related fixable issues

* fix: autofixable eslint issues

* chore: remove all template literals

* fix: remaining autofixable issues

* chore: apply amnesty on all existing issues

* fix: failing xss-lint issues

* refactor: apply amnesty on remaining issues

* refactor: apply amnesty on new issues

* fix: remove file level suppressions

* refactor: apply amnesty on new issues
2023-08-07 19:13:19 +05:00

178 lines
7.2 KiB
JavaScript

define(['edx-ui-toolkit/js/utils/html-utils',
'js/views/baseview',
'underscore',
'jquery',
'gettext',
'common/js/components/views/feedback_notification',
'common/js/components/views/feedback_alert',
'js/views/baseview',
'jquery.smoothScroll'],
function(HtmlUtils, BaseView, _, $, gettext, NotificationView, AlertView) {
var ValidatingView = BaseView.extend({
// Intended as an abstract class which catches validation errors on the model and
// decorates the fields. Needs wiring per class, but this initialization shows how
// either have your init call this one or copy the contents
initialize: function() {
this.listenTo(this.model, 'invalid', this.handleValidationError);
this.selectorToField = _.invert(this.fieldToSelectorMap);
},
errorTemplate: HtmlUtils.template('<span class="message-error"><%- message %></span>'),
save_title: gettext("You've made some changes"),
save_message: gettext('Your changes will not take effect until you save your progress.'),
error_title: gettext("You've made some changes, but there are some errors"),
error_message: gettext('Please address the errors on this page first, and then save your progress.'),
events: {
'change input': 'clearValidationErrors',
'change textarea': 'clearValidationErrors'
},
fieldToSelectorMap: {
// Your subclass must populate this w/ all of the model keys and dom selectors
// which may be the subjects of validation errors
},
_cacheValidationErrors: [],
handleValidationError: function(model, error) {
this.clearValidationErrors();
// error is object w/ fields and error strings
// eslint-disable-next-line guard-for-in
for (var field in error) {
var ele = this.$el.find('#' + this.fieldToSelectorMap[field]);
this._cacheValidationErrors.push(ele);
this.getInputElements(ele).addClass('error');
HtmlUtils.append($(ele).parent(), this.errorTemplate({message: error[field]}));
}
$('.wrapper-notification-warning').addClass('wrapper-notification-warning-w-errors');
$('.action-save').addClass('is-disabled');
// TODO: (pfogg) should this text fade in/out on change?
$('#notification-warning-title').text(this.error_title);
$('#notification-warning-description').text(this.error_message);
},
clearValidationErrors: function() {
// error is object w/ fields and error strings
while (this._cacheValidationErrors.length > 0) {
var ele = this._cacheValidationErrors.pop();
this.getInputElements(ele).removeClass('error');
$(ele).nextAll('.message-error').remove();
}
$('.wrapper-notification-warning').removeClass('wrapper-notification-warning-w-errors');
$('.action-save').removeClass('is-disabled');
$('#notification-warning-title').text(this.save_title);
$('#notification-warning-description').text(this.save_message);
},
setField: function(event) {
// Set model field and return the new value.
this.clearValidationErrors();
var field = this.selectorToField[event.currentTarget.id];
var newVal = '';
if (event.currentTarget.type == 'checkbox') {
newVal = $(event.currentTarget).is(':checked').toString();
} else {
newVal = $(event.currentTarget).val();
}
this.model.set(field, newVal);
this.model.isValid();
return newVal;
},
// these should perhaps go into a superclass but lack of event hash inheritance demotivates me
inputFocus: function(event) {
$("label[for='" + event.currentTarget.id + "']").addClass('is-focused');
},
inputUnfocus: function(event) {
$("label[for='" + event.currentTarget.id + "']").removeClass('is-focused');
},
getInputElements: function(ele) {
var inputElements = 'input, textarea';
if ($(ele).is(inputElements)) {
return $(ele);
} else {
// put error on the contained inputs
return $(ele).find(inputElements);
}
},
showNotificationBar: function(message, primaryClick, secondaryClick) {
// Show a notification with message. primaryClick is called on
// pressing the save button, and secondaryClick (if it's
// passed, which it may not be) will be called on
// cancel. Takes care of hiding the notification bar at the
// appropriate times.
if (this.notificationBarShowing) {
return;
}
// If we've already saved something, hide the alert.
if (this.saved) {
this.saved.hide();
}
var self = this;
this.confirmation = new NotificationView.Warning({
title: this.save_title,
message: message,
actions: {
primary: {
text: gettext('Save Changes'),
class: 'action-save',
click: function() {
primaryClick();
self.confirmation.hide();
self.notificationBarShowing = false;
}
},
secondary: [{
text: gettext('Cancel'),
class: 'action-cancel',
click: function() {
if (secondaryClick) {
secondaryClick();
}
self.model.clear({silent: true});
self.confirmation.hide();
self.notificationBarShowing = false;
}
}]
}
});
this.notificationBarShowing = true;
this.confirmation.show();
// Make sure the bar is in the right state
this.model.isValid();
},
showSavedBar: function(title, message) {
var defaultTitle = gettext('Your changes have been saved.');
this.saved = new AlertView.Confirmation({
title: title || defaultTitle,
message: message,
closeIcon: false
});
this.saved.show();
$.smoothScroll({
offset: 0,
easing: 'swing',
speed: 1000
});
},
saveView: function() {
var self = this;
this.model.save(
{},
{
success: function() {
self.showSavedBar();
self.render();
},
silent: true
}
);
}
});
return ValidatingView;
}); // end define()