This commit is contained in:
@@ -14,8 +14,13 @@ TODO CLIENT STUFF
|
||||
|
||||
TODO NEXT
|
||||
|
||||
IMMEDIATE ISSUES:
|
||||
Not clearing server errorbox on submit.
|
||||
I'm thinking I need to rethink how it works perhaps and bind it to a watched function or some shit, right now it's part of the validation system but it should be decoupled from that in reality
|
||||
Vue really expects fields to update based on watched or local properties in data so it should both get it's value for if should show and for what to show from a local property that is set maybe by the gzvalidate
|
||||
|
||||
See server project widget validation code which will now give server errors on certain values so can proceed with work.
|
||||
Current issue is where to put notifications, code is to help test also as I'm not sure if server errors will be preventing submit when their are no field errors etc
|
||||
Current issue is where to put notifications, code is to help test, also not clearing server errorbox on submit
|
||||
|
||||
Issues:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable */
|
||||
/* Xeslint-disable */
|
||||
///////////////////////////////
|
||||
// GZVALIDATE
|
||||
//
|
||||
@@ -6,11 +6,7 @@
|
||||
// All locale keys for validation *MUST* be fetched prior to this being used as it assumes all keys are fetched first
|
||||
// Add any new keys used to the block in locale.js=>commonKeysEditForm
|
||||
|
||||
//import v.$dayjs from "v.$dayjs";
|
||||
//import v.$gzlocale from "./v.$gzlocale";
|
||||
//import _ from "../libs/lodash.min.js";
|
||||
import errorHandler from "./errorhandler";
|
||||
|
||||
var triggeringChange = false;
|
||||
|
||||
function isEmpty(o) {
|
||||
@@ -55,11 +51,6 @@ function getControl(v, ref) {
|
||||
// Get value from control
|
||||
//
|
||||
function getControlValue(ctrl) {
|
||||
/*
|
||||
ctrl.$refs[ref].value 0
|
||||
ctrl.$refs[ref].label "Count"
|
||||
ctrl.$refs[ref].initialValue
|
||||
*/
|
||||
var value = ctrl.value;
|
||||
return value;
|
||||
}
|
||||
@@ -76,48 +67,43 @@ function getControlLabel(ctrl) {
|
||||
return ctrl.label;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////
|
||||
// // DEBUG / DEVELOPMENT LOGGING
|
||||
// //
|
||||
// function logControl(caller, ctrl, ref) {
|
||||
// if (ref != "xcount") {
|
||||
// return;
|
||||
// }
|
||||
/////////////////////////////////////////
|
||||
// Get errors for a particular field
|
||||
// from server error collection
|
||||
//
|
||||
function getErrorsForField(v, ref) {
|
||||
var ret = [];
|
||||
if (ref == "errorbox") {
|
||||
ret = v.$_.filter(v.serverError.details, function(o) {
|
||||
return !o.target;
|
||||
});
|
||||
} else {
|
||||
ret = v.$_.filter(v.serverError.details, function(o) {
|
||||
if (!o.target) {
|
||||
return false;
|
||||
}
|
||||
//server error fields are capitalized
|
||||
return o.target.toLowerCase() == ref;
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// var hasChanged = false;
|
||||
// if (ctrl.internalChange) {
|
||||
// hasChanged = true;
|
||||
// } else {
|
||||
// if (ctrl.initialValue && ctrl.lazyValue) {
|
||||
// if (ctrl.initialValue != ctrl.lazyValue) {
|
||||
// hasChange = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
///////////////////////////////
|
||||
// ERROR BOX ERRORS
|
||||
// gathers any messages for error box on form which is the generic catch all for non field specific errors from server
|
||||
function GetErrorBoxErrors(v, errs) {
|
||||
if (errs.length < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// var v =
|
||||
// "CTRL=" +
|
||||
// ref +
|
||||
// ", CALLER [" +
|
||||
// caller +
|
||||
// "], " +
|
||||
// ", internalChange=" +
|
||||
// ctrl.internalChange +
|
||||
// ", lazyValue=" +
|
||||
// ctrl.lazyValue +
|
||||
// ", initialValue=" +
|
||||
// ctrl.initialValue +
|
||||
// ", loading=" +
|
||||
// ctrl.loading +
|
||||
// ", isDirty=" +
|
||||
// ctrl.isDirty +
|
||||
// ", isResetting=" +
|
||||
// ctrl.isResetting +
|
||||
// ", HAS CHANGED =" +
|
||||
// hasChanged;
|
||||
|
||||
// console.log(v);
|
||||
// }
|
||||
var ret = "";
|
||||
//loop array and append each error to a return string
|
||||
for (var i = 0; i < errs.length; i++) {
|
||||
ret += errs[i] + "\r\n";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
export default {
|
||||
///////////////////////////////
|
||||
@@ -129,9 +115,6 @@ export default {
|
||||
return false;
|
||||
}
|
||||
|
||||
//DEBUG
|
||||
//logControl("Required", ctrl, ref);
|
||||
|
||||
var value = getControlValue(ctrl);
|
||||
if (!isEmpty(value)) {
|
||||
return false;
|
||||
@@ -154,9 +137,6 @@ export default {
|
||||
return false;
|
||||
}
|
||||
|
||||
//DEBUG
|
||||
// logControl("MaxLength", ctrl, ref);
|
||||
|
||||
var value = getControlValue(ctrl);
|
||||
if (isEmpty(value)) {
|
||||
return false;
|
||||
@@ -193,10 +173,6 @@ export default {
|
||||
return false;
|
||||
}
|
||||
|
||||
//DEBUG
|
||||
// logControl("After", ctrlStart, refStart);
|
||||
// logControl("After", ctrlEnd, refEnd);
|
||||
|
||||
var valueStart = getControlValue(ctrlStart);
|
||||
if (isEmpty(valueStart)) {
|
||||
return false;
|
||||
@@ -297,11 +273,8 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var ret = [];
|
||||
|
||||
//return ret;
|
||||
|
||||
//check for errors if we have any errors
|
||||
if (!v.$_.isEmpty(v.serverError)) {
|
||||
//debugger;
|
||||
@@ -309,9 +282,6 @@ export default {
|
||||
|
||||
var apiErrorCode = parseInt(v.serverError.code);
|
||||
|
||||
//TODO: This logic is faulty, there could be overall errors that are not field specific, however there are also field ones that trigger overall errors.
|
||||
//Keep top part if statement for gathering all overall errors, but then also run the field errors block and check for field errors where "target" is empty and add them in to the return as well
|
||||
|
||||
//GENERAL ERROR
|
||||
if (ref == "errorbox") {
|
||||
//Add any general errors to ret
|
||||
@@ -326,26 +296,9 @@ export default {
|
||||
//Specific field validation errors are in an array in "details" key
|
||||
if (!v.$_.isEmpty(v.serverError.details)) {
|
||||
//See if this key is in the details array
|
||||
var errorsForField = [];
|
||||
|
||||
if (ref == "errorbox") {
|
||||
errorsForField = v.$_.filter(v.serverError.details, function(o) {
|
||||
return !o.target;
|
||||
});
|
||||
} else {
|
||||
errorsForField = v.$_.filter(v.serverError.details, function(o) {
|
||||
if (!o.target) {
|
||||
return false;
|
||||
}
|
||||
//server error fields are capitalized
|
||||
return o.target.toLowerCase() == ref;
|
||||
});
|
||||
}
|
||||
var errorsForField = getErrorsForField(v, ref);
|
||||
|
||||
if (errorsForField.length > 0) {
|
||||
//DEBUG
|
||||
//logControl("ServerErrors", getControl(v, ref), ref);
|
||||
|
||||
//iterate the errorsForField object and add each to return array of errors
|
||||
v.$_.each(errorsForField, function(ve) {
|
||||
var fldErr = "";
|
||||
@@ -368,111 +321,23 @@ export default {
|
||||
|
||||
//default if no error message to display
|
||||
return ret;
|
||||
},
|
||||
|
||||
//OK, this is sketchy a bit but seems to work
|
||||
//If it returns a value that is displayed as an error in the field (hides any rule errors but whatever)
|
||||
//Tested and confirmed that If I make a change to the underlying data property that is housing the data used here to determine if a field has an error, and remove that error then it instantly resolves in the UI and removes the message so that's good!
|
||||
// - so if we store the server errors in the data() property and edit it the changes to (for example remove a rule), the changes will be reflected instantly
|
||||
|
||||
//Vuetify seems to prioritize messages over validation rule messages or perhaps it's set to display only one at a time no matter what value is set for error-count
|
||||
//What I need is each field needs to bind here
|
||||
//This code needs to determine if there are any errors for the field in question,
|
||||
//and return the appropriate string of text
|
||||
//Then eventually this needs to go into gzvalidate as part of *it's* code so I can just easily call that shit from anywhere
|
||||
|
||||
//To determine: how to detect the field has been edited and is dirty and so remove the server error message for that field?
|
||||
|
||||
//Have a think about this: is it better to just show all server errors in their own place instead?
|
||||
// - how many are field related and how many are general?
|
||||
//- what is best for the end user and least confusing? (probably error with field unless it's general then at top and cleared instantly when they modify the field in question)
|
||||
|
||||
//IN ADDITION: on submit needs to clear serverErrors
|
||||
|
||||
/*
|
||||
Steps to completion:
|
||||
|
||||
On submit show server errors for fields in their fields, show general errors at the top of form in an error box
|
||||
When a field is edited any *server* errors must clear for that field right away
|
||||
When the form is submitted all server errors cleared if any from previous submit
|
||||
|
||||
|
||||
//example error when submit when there are no roles set at all (blank)
|
||||
//{"error":{"code":"2200","details":[{"target":"WidgetCustom1","error":"2204"}],"message":"Object did not pass validation"}}
|
||||
|
||||
Here are all the API level error codes that can be returned by the API server:
|
||||
|
||||
| CODE | MEANING |
|
||||
| ----- | ------------------------------ |
|
||||
//THESE ARE ALL GENERAL FORM LEVEL ERRORS
|
||||
| 2000 | API closed - Server is running but access to the API has been closed to all users |
|
||||
| 2001 | API closed all non OPS routes - Server is running but access to the API has been restricted to only server maintenance operations related functionality |
|
||||
| 2002 | Internal error from the API server, details in [server log](common-log.md) file |
|
||||
| 2003 | Authentication failed, bad login or password, user not found |
|
||||
| 2004 | Not authorized - current user is not authorized for operation attempted on the resource (insufficient rights) |
|
||||
| 2005 | Object was changed by another user since retrieval (concurrency token mismatch) |
|
||||
| 2010 | Object not found - API could not find the object requested |
|
||||
| 2020 | PUT Id mismatch - object Id does not match route Id |
|
||||
| 2030 | Invalid operation - operation could not be completed, not valid, details in message property |
|
||||
| 2200 | Validation error - general top level indicating object was not valid, specifics in "details" property |
|
||||
|
||||
//THESE HAVE FIELD NAMES IN AN ARRAY under details
|
||||
| 2201 | Validation error - Field is required but is empty or null |
|
||||
| 2202 | Validation error - Field length exceeded |
|
||||
| 2203 | Validation error - invalid value |
|
||||
|
||||
//general errors
|
||||
"ErrorAPI2000":"The server is closed",
|
||||
"ErrorAPI2001":"The server is closed for maintenance",
|
||||
"ErrorAPI2002":"Internal server error",
|
||||
"ErrorAPI2003":"Authentication failed",
|
||||
"ErrorAPI2004":"Not authorized",
|
||||
"ErrorAPI2005":"Object was recently changed by another user and can't be saved",
|
||||
"ErrorAPI2010":"Object not found",
|
||||
"ErrorAPI2020":"Route id doesn't match object id",
|
||||
"ErrorAPI2030":"Invalid operation",
|
||||
"ErrorAPI2200":"Validation error",
|
||||
|
||||
//field errors
|
||||
"ErrorAPI2201":"Required field",
|
||||
"ErrorAPI2202":"Length exceeded",
|
||||
"ErrorAPI2203":"Invalid value"
|
||||
|
||||
Validation errors for fields will have a code of one of the following:
|
||||
| RequiredPropertyEmpty | An AyaNova fixed rule required property value is empty |
|
||||
| CustomRequiredPropertyEmpty | A user customized form property set to required has an empty value |
|
||||
| RequiredPropertyMissing | Required property is missing entirely |
|
||||
| LengthExceeded | A text property has more characters than are allowed. The limit will be returned in the `message` property of the validation error |
|
||||
| NotUnique | A text property is required to be unique but an existing identical value was found in the database |
|
||||
| StartDateMustComeBeforeEndDate | When an object requires a start and end date the start date must be earlier than the end date |
|
||||
| InvalidValue | Generic error indicating an input object's property is not set correctly |
|
||||
| ReferentialIntegrity | Indicates modifying the object (usually a delete) will break the link to other records in the database. The other records need to be modified before continuing |
|
||||
| InvalidOperation | Indicates the operation is invalid, details provided in the `message` |
|
||||
| NotChangeable | Indicates the attempted property change is invalid because the value is fixed and cannot be changed |
|
||||
|
||||
*/
|
||||
///////////////////////////////
|
||||
// ClearServerErrors
|
||||
// Clear all server errors and ensure error box doesn't show and validation is triggered
|
||||
ClearServerErrors(v) {
|
||||
//clear all keys from server error
|
||||
v.$gzutil.RemoveAllPropertiesFromObject(v.serverError);
|
||||
v.errorBoxMessage = null;
|
||||
},
|
||||
///////////////////////////////
|
||||
// ERROR BOX ERRORS
|
||||
// displays any messages for error box on form which is the generic catch all for non field specific errors from server
|
||||
ErrorBoxErrors(v) {
|
||||
//console.log("gzvalidate::ErrorBoxErrors called...");
|
||||
|
||||
// SetErrorBoxErrors
|
||||
// Gather server errors and set the appropriate keys
|
||||
SetErrorBoxErrors(v) {
|
||||
var errs = this.ServerErrors(v, "errorbox");
|
||||
if (errs.length < 1) {
|
||||
// console.log(
|
||||
// "gzvalidate::ErrorBoxErrors - RETURN NO ERRORS, short circuit return"
|
||||
// );
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = "";
|
||||
//loop array and append each error to a return string
|
||||
for (var i = 0; i < errs.length; i++) {
|
||||
ret += errs[i] + "\r\n";
|
||||
}
|
||||
|
||||
// console.log("gzvalidate::ErrorBoxErrors - RETURN WITH ERRORS");
|
||||
return ret;
|
||||
var ret = GetErrorBoxErrors(v, errs);
|
||||
v.errorBoxMessage = ret;
|
||||
},
|
||||
///////////////////////////////
|
||||
// On Change handler
|
||||
@@ -483,13 +348,16 @@ Here are all the API level error codes that can be returned by the API server:
|
||||
}
|
||||
//If ref appears in the servererrors details collection, remove each one
|
||||
var m = v.$_.remove(v.serverError.details, function(o) {
|
||||
return o.target == ref;
|
||||
if (!o.target) {
|
||||
return false;
|
||||
}
|
||||
return o.target.toLowerCase() == ref;
|
||||
});
|
||||
|
||||
//If there are no more errors in details then remove the whole thing as it's no longer required
|
||||
if (v.serverError.details && v.serverError.details.length < 1) {
|
||||
if (v.serverError.code == "2200") {
|
||||
v.$gzutil.RemoveAllPropertiesFromObject(v.serverError);
|
||||
this.ClearServerErrors(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,18 +372,5 @@ Here are all the API level error codes that can be returned by the API server:
|
||||
v.obj[ref] = val;
|
||||
triggeringChange = false;
|
||||
}
|
||||
},
|
||||
///////////////////////////////
|
||||
// Clean out server errors
|
||||
// This is called both from the form immediately before submit and here in Change handler
|
||||
// It's purpose is to more efficiently clear out the object even though I could set it to an empty object, this way it just keeps the same object
|
||||
// avoiding some potential issues
|
||||
RemoveAllProperties(o) {
|
||||
//clear any errors that might be around from previous submit
|
||||
for (var variableKey in o) {
|
||||
if (o.hasOwnProperty(variableKey)) {
|
||||
delete o[variableKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<v-flex xs12 mt-1 mb-2>
|
||||
<v-alert
|
||||
ref="errorbox"
|
||||
v-show="this.$gzv.ErrorBoxErrors(this)"
|
||||
v-show="errorBoxMessage"
|
||||
color="error"
|
||||
icon="fa-exclamation-circle "
|
||||
value="true"
|
||||
transition="scale-transition"
|
||||
class="multi-line"
|
||||
outline
|
||||
>{{this.$gzv.ErrorBoxErrors(this)}}</v-alert>
|
||||
>{{errorBoxMessage}}</v-alert>
|
||||
</v-flex>
|
||||
<v-flex xs12 sm6 lg4 xl3 px-2>
|
||||
<v-text-field
|
||||
@@ -174,6 +174,7 @@ export default {
|
||||
return {
|
||||
obj: {},
|
||||
serverError: {},
|
||||
errorBoxMessage:null,
|
||||
formReady: false
|
||||
};
|
||||
},
|
||||
@@ -194,11 +195,13 @@ export default {
|
||||
var url = "Widget/" + this.$route.params.id;
|
||||
|
||||
//clear any errors that might be around from previous submit
|
||||
this.$gzutil.RemoveAllPropertiesFromObject(this.serverError);
|
||||
this.$gzv.ClearServerErrors(this);
|
||||
//this.$gzutil.RemoveAllPropertiesFromObject(this.serverError);
|
||||
|
||||
this.$gzapi.upsert(url, this.obj).then(res => {
|
||||
if (res.error) {
|
||||
that.serverError = res.error;
|
||||
that.$gzv.SetErrorBoxErrors(that);
|
||||
} else {
|
||||
//Logic for detecting if a post or put: if id then it was a post, if no id then it was a put
|
||||
if (res.id) {
|
||||
|
||||
Reference in New Issue
Block a user