Added proper form validation to printer profile editor to the UI

Closes #809
This commit is contained in:
Gina Häußge 2015-03-13 15:49:35 +01:00
parent 5cadfb5a09
commit 91b9fb3e3f
2 changed files with 88 additions and 11 deletions

View file

@ -31,6 +31,8 @@ $(function() {
}
};
self.requestInProgress = ko.observable(false);
self.profiles = new ItemListHelper(
"printerProfiles",
{
@ -57,6 +59,7 @@ $(function() {
self.editorName = ko.observable();
self.editorColor = ko.observable();
self.editorIdentifier = ko.observable();
self.editorIdentifierPlaceholder = ko.observable();
self.editorModel = ko.observable();
self.editorVolumeWidth = ko.observable();
@ -110,6 +113,46 @@ $(function() {
return extruderOffsets.slice(0, numExtruders);
});
self.editorNameInvalid = ko.computed(function() {
return !self.editorName();
});
self.editorIdentifierInvalid = ko.computed(function() {
var identifier = self.editorIdentifier();
var placeholder = self.editorIdentifierPlaceholder();
var data = identifier;
if (!identifier) {
data = placeholder;
}
var validCharacters = (data && (data == self._sanitize(data)));
var existingProfile = self.profiles.getItem(function(item) {return item.id == data});
return !data || !validCharacters || (self.editorNew() && existingProfile != undefined);
});
self.editorIdentifierInvalidText = ko.computed(function() {
if (!self.editorIdentifierInvalid()) {
return "";
}
if (!self.editorIdentifier() && !self.editorIdentifierPlaceholder()) {
return gettext("Identifier must be set");
} else if (self.editorIdentifier() != self._sanitize(self.editorIdentifier())) {
return gettext("Invalid characters, only a-z, A-Z, 0-9, -, ., _, ( and ) are allowed")
} else {
return gettext("A profile with such an identifier already exists");
}
});
self.enableEditorSubmitButton = ko.computed(function() {
return !self.editorNameInvalid() && !self.editorIdentifierInvalid() && !self.requestInProgress();
});
self.editorName.subscribe(function() {
self.editorIdentifierPlaceholder(self._sanitize(self.editorName()).toLowerCase());
});
self.makeDefault = function(data) {
var profile = {
id: data.id,
@ -153,6 +196,7 @@ $(function() {
self.addProfile = function(callback) {
var profile = self._editorData();
self.requestInProgress(true);
$.ajax({
url: API_BASEURL + "printerprofiles",
type: "POST",
@ -160,23 +204,35 @@ $(function() {
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({profile: profile}),
success: function() {
self.requestInProgress(false);
if (callback !== undefined) {
callback();
}
self.requestData();
},
error: function(jqXHR) {
alert(jqXHR.responseText);
error: function() {
self.requestInProgress(false);
var text = gettext("There was unexpected error while saving the printer profile, please consult the logs.");
new PNotify({title: gettext("Saving failed"), text: text, type: "error", hide: false});
}
});
};
self.removeProfile = function(data) {
self.requestInProgress(true);
$.ajax({
url: data.resource,
type: "DELETE",
dataType: "json",
success: self.requestData
success: function() {
self.requestInProgress(false);
self.requestData();
},
error: function() {
self.requestInProgress(false);
var text = gettext("There was unexpected error while removing the printer profile, please consult the logs.");
new PNotify({title: gettext("Saving failed"), text: text, type: "error", hide: false});
}
})
};
@ -185,6 +241,8 @@ $(function() {
profile = self._editorData();
}
self.requestInProgress(true);
$.ajax({
url: API_BASEURL + "printerprofiles/" + profile.id,
type: "PATCH",
@ -192,10 +250,16 @@ $(function() {
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({profile: profile}),
success: function() {
self.requestInProgress(false);
if (callback !== undefined) {
callback();
}
self.requestData();
},
error: function() {
self.requestInProgress(false);
var text = gettext("There was unexpected error while updating the printer profile, please consult the logs.");
new PNotify({title: gettext("Saving failed"), text: text, type: "error", hide: false});
}
});
};
@ -248,7 +312,9 @@ $(function() {
dialogTitle.text(add ? gettext("Add Printer Profile") : _.sprintf(gettext("Edit Printer Profile \"%(name)s\""), {name: data.name}));
confirmButton.unbind("click");
confirmButton.bind("click", function() {
self.confirmEditProfile(add);
if (self.enableEditorSubmitButton()) {
self.confirmEditProfile(add);
}
});
editDialog.modal("show");
};
@ -266,8 +332,13 @@ $(function() {
};
self._editorData = function() {
var identifier = self.editorIdentifier();
if (!identifier) {
identifier = self.editorIdentifierPlaceholder();
}
var profile = {
id: self.editorIdentifier(),
id: identifier,
name: self.editorName(),
color: self.editorColor(),
model: self.editorModel(),
@ -314,6 +385,10 @@ $(function() {
return profile;
};
self._sanitize = function(name) {
return name.replace(/[^a-zA-Z0-9\-_\.\(\) ]/g, "").replace(/ /g, "_");
};
self.onSettingsShown = self.requestData;
self.onStartup = self.requestData;
}

View file

@ -12,7 +12,7 @@
<td class="settings_printerProfiles_profiles_name"><span class="icon-star" data-bind="invisible: !isdefault()"></span> <span data-bind="text: name"></span></td>
<td class="settings_printerProfiles_profiles_model" data-bind="text: model"></td>
<td class="settings_printerProfiles_profiles_action">
<a href="#" class="icon-star" title="{{ _('Set as default profile') }}" data-bind="click: function() { $root.printerProfiles.makeDefault($data); }"></a>&nbsp;|&nbsp;<a href="#" class="icon-pencil" title="{{ _('Edit Profile') }}" data-bind="click: function() { $root.printerProfiles.showEditProfileDialog($data); }"></a>&nbsp;|&nbsp;<a href="#" class="icon-trash" title="{{ _('Delete Profile') }}" data-bind="click: function() { $root.printerProfiles.removeProfile($data); }"></a>
<a href="#" class="icon-star" title="{{ _('Set as default profile') }}" data-bind="click: function() { $root.printerProfiles.makeDefault($data); }, css: {disabled: $root.printerProfiles.requestInProgress()}, enabled: !$root.printerProfiles.requestInProgress()"></a>&nbsp;|&nbsp;<a href="#" class="icon-pencil" title="{{ _('Edit Profile') }}" data-bind="click: function() { $root.printerProfiles.showEditProfileDialog($data); }, css: {disabled: $root.printerProfiles.requestInProgress()}, enabled: !$root.printerProfiles.requestInProgress()"></a>&nbsp;|&nbsp;<a href="#" class="icon-trash" title="{{ _('Delete Profile') }}" data-bind="click: function() { $root.printerProfiles.removeProfile($data); }, css: {disabled: $root.printerProfiles.requestInProgress()}, enabled: !$root.printerProfiles.requestInProgress()"></a>
</td>
</tr>
</tbody>
@ -40,16 +40,18 @@
</div>
<div class="modal-body">
<form class="form-horizontal">
<div class="control-group">
<div class="control-group" data-bind="css: {error: printerProfiles.editorNameInvalid()}">
<label class="control-label">{{ _('Name') }}</label>
<div class="controls">
<input type="text" data-bind="value: printerProfiles.editorName">
<input type="text" data-bind="value: printerProfiles.editorName, valueUpdate: 'afterkeydown'">
<span data-bind="visible: printerProfiles.editorNameInvalid()"><br><span class="help-inline">{{ _('Name must be set') }}</span></span>
</div>
</div>
<div class="control-group">
<div class="control-group" data-bind="css: {error: printerProfiles.editorIdentifierInvalid()}">
<label class="control-label">{{ _('Identifier') }}</label>
<div class="controls">
<input type="text" data-bind="value: printerProfiles.editorIdentifier, enable: $root.printerProfiles.editorNew, css: {disabled: !$root.printerProfiles.editorNew()}">
<input type="text" data-bind="value: printerProfiles.editorIdentifier, valueUpdate: 'afterkeydown', enable: printerProfiles.editorNew, css: {disabled: !printerProfiles.editorNew()}, attr: {placeholder: printerProfiles.editorIdentifierPlaceholder}">
<span data-bind="visible: printerProfiles.editorIdentifierInvalid()"><br><span class="help-inline" data-bind="text: printerProfiles.editorIdentifierInvalidText()"></span></span>
</div>
</div>
<div class="control-group">
@ -180,6 +182,6 @@
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Abort') }}</button>
<button class="btn btn-primary btn-confirm">{{ _('Confirm') }}</button>
<button class="btn btn-primary btn-confirm" data-bind="enabled: printerProfiles.enableEditorSubmitButton, css: {disabled: !printerProfiles.enableEditorSubmitButton()}"><i class="icon-spinner icon-spin" data-bind="visible: printerProfiles.requestInProgress()"></i> {{ _('Confirm') }}</button>
</div>
</div>