diff --git a/ayanova/devdocs/todo.txt b/ayanova/devdocs/todo.txt index bbcd0738..d7ea1ea8 100644 --- a/ayanova/devdocs/todo.txt +++ b/ayanova/devdocs/todo.txt @@ -46,23 +46,33 @@ CURRENT TODOs =-=-=-=-=-=-= -TODO: HELP LINKS - - OBJECTIVE: start filling in help now so don't need to do it all later in one big push - - Make sure each form has a unique help link and also make a stub page in the documentation for that help link to be filled in later or now if applicable - - Make up the widget help doc and it should in turn have many links to individual features of the forms in general so can use those for other forms later - - i.e. anything that would be useful to know about the form and the features on it TODO: FORM CUSTOMIZATION FORM - - If a user changes a field data type there needs to be a big warning before accepting it. - - ACTIONABLE - How to handle custom field TYPE changes when they have data? + - ACTIONABLE - How to handle custom field TYPE changes when they have data? - test scenario where a custom field type is changed, how does it react, what code changes are required - I was leaning towards *not* mass changing the underlying records at the server when a type changes only because users may accidentally make a change and then want to reverse it before any records are affected. - However this means the client needs to deal with incompatible data - POTENTIAL FIX: Maybe the server should "vet" custom field data when it's about to send it out to the client and if it detects an invalid value it scrubs it for that record at that moment in time before it sends it off - This way the client is always working with the correct data and also no mass changes are made at the server and if the user chooses not to save the record at the client then nothing is affected - Maybe a function that all customfield able objects call? + - POTENTIAL FIX: Or maybe the Client is responsible for checking if any data incoming is compatible with the type and if not then co-erce it or clear if can't be co-erced + - CURRENT TEXT fields could handle any data so they don't need to be changed + - CURRENT BOOL fields can only handle empty or true false so they would need to be set null + - CURRENT TIME, DATE, DATETIME are pretty specific but all use a datetime string so any value not datetime like should be nulled + - CURRENT NUMBER, CURRENCY are also pretty specific but easy to identify if not fully numeric and then sb nulled or attempt to convert then null if not + - i.e. maybe someone has a text field where they entered $45.00 and wants to make it a currency instead, it should be able to extract the 45.0 + + + +TODO: AUTO-LOGOUT EXPIRED SESSION? + - first off, is this really an issue? + - Right now a user can simply close the browser in the middle of a session, re-open it any amount of time later and it will just keep working, however it might have outdatd cached data from the server + - What about a time limit after which a session needs to login again just to protect the users from themselves? + - Perhaps it can detect a full page refresh (which is what a restart essentially is) and see how long ago it was last active, maybe the time of the last API call to the server and use that info to force re-login. + + TODO: MAIN GRID LIST ANALYSIS, DESIGN AND COMPLETION - Main grid time is off from edit form time by -1 hour diff --git a/ayanova/src/api/gzutil.js b/ayanova/src/api/gzutil.js index ae92da47..00961f1a 100644 --- a/ayanova/src/api/gzutil.js +++ b/ayanova/src/api/gzutil.js @@ -99,6 +99,25 @@ export default { hash |= 0; // Convert to 32bit integer } return hash; + }, + /////////////////////////////// + // CONVERT STRING TO BOOLEAN + // https://stackoverflow.com/a/1414175/8939 + // + stringToBoolean: function(string) { + switch (string.toLowerCase().trim()) { + case "true": + case "yes": + case "1": + return true; + case "false": + case "no": + case "0": + case null: + return false; + default: + return Boolean(string); + } } //new functions above here diff --git a/ayanova/src/components/custom-fields-control.vue b/ayanova/src/components/custom-fields-control.vue index 76b93e41..8cb52c74 100644 --- a/ayanova/src/components/custom-fields-control.vue +++ b/ayanova/src/components/custom-fields-control.vue @@ -173,11 +173,61 @@ export default { //get the data out of the JSON string value var cData = JSON.parse(this.value); - //POtentially, down the road might need to co-erce the value to the right type, this is where that would happen - //get the type it *should* be - //coerce it to that type and return it + //Custom field types can be changed by the user and cause old entered data to be invalid for that field type + //Here we need to take action if the data is of an incompatible type for the control field type and attempt to coerce or simply nullify if not co-ercable the data + // - CURRENT TEXT fields could handle any data so they don't need to be changed + // - CURRENT BOOL fields can only handle empty or true false so they would need to be set null + // - CURRENT TIME, DATE, DATETIME are pretty specific but all use a datetime string so any value not datetime like should be nulled + // - CURRENT NUMBER, CURRENCY are also pretty specific but easy to identify if not fully numeric and then sb nulled or attempt to convert then null if not - return cData[dataKey]; + //Get the field data type + //https://lodash.com/docs#find + var ctrlType = window.$gz._.find( + this.$store.state.formCustomTemplate[this.formKey], + ["dataKey", dataKey] + ).type; + //console.log("Field with datakey " + dataKey + " is of type " + ctrlType); + + //First get current value for the data that came from the server + var ret = cData[dataKey]; + //Only process if value is non-null since all control types can handle null + if (ret != null) { + //check types that matter + switch (ctrlType) { + //DateLike? + case "date": + case "time": + case "datetime": + //can it be parsed into a date using the same library as the components use? + if (!window.$gz.dayjs(ret).isValid()) { + ret = null; + } + break; + case "bool": + //if it's not already a boolean + if (!window.$gz._.isBoolean(ret)) { + //it's not a bool and it's not null, it came from some other data type, + //perhaps though, it's a truty string so check for that before giving up and nulling + if (window.$gz._.isString(ret)) { + ret = window.$gz.util.stringToBoolean(ret); + break; + } + //The number 1? + if (ret === 1) { + ret = true; + break; + } + //The number 0? + if (ret === 0) { + ret = false; + break; + } + } + break; + } + } + //{"c1":"2019-01-27T09:26:06.1673391Z","c2":"Esse sunt re in.","c3":48824971,"c4":false,"c5":0.120971084628706} + return ret; }, SetValueForField: function(dataKey, newValue) { //Get the current data out of the json string value @@ -192,9 +242,6 @@ export default { cData[dataKey] = null; } else { //then set item in the cData - - //POtentially, down the road might need to co-erce the value to the right type, this is where that would happen - cData[dataKey] = newValue.toString(); } diff --git a/ayanova/src/views/About.vue b/ayanova/src/views/About.vue index 8e605170..3e7a2dce 100644 --- a/ayanova/src/views/About.vue +++ b/ayanova/src/views/About.vue @@ -205,6 +205,7 @@ export default { isMain: false, icon: "fa-info-circle", title: window.$gz.locale.get("HelpAboutAyaNova"), + helpUrl: "user-form-about", menuItems: [ { title: window.$gz.locale.get("Copy"), diff --git a/ayanova/src/views/Home.vue b/ayanova/src/views/Home.vue index f08413a8..eb706cb1 100644 --- a/ayanova/src/views/Home.vue +++ b/ayanova/src/views/Home.vue @@ -13,7 +13,8 @@ export default { window.$gz.eventBus.$emit("menu-change", { isMain: true, icon: "fa-home", - title: window.$gz.locale.get("Home") + title: window.$gz.locale.get("Home"), + helpUrl: "user-form-home" }); } }; diff --git a/ayanova/src/views/accounting.vue b/ayanova/src/views/accounting.vue index c41cb162..d42882d6 100644 --- a/ayanova/src/views/accounting.vue +++ b/ayanova/src/views/accounting.vue @@ -13,7 +13,8 @@ export default { window.$gz.eventBus.$emit("menu-change", { isMain: true, icon: "fa-file-invoice-dollar", - title: window.$gz.locale.get("Accounting") + title: window.$gz.locale.get("Accounting"), + helpUrl: "user-form-accounting" }); } }; diff --git a/ayanova/src/views/administration.vue b/ayanova/src/views/administration.vue index e48d8025..b844a5be 100644 --- a/ayanova/src/views/administration.vue +++ b/ayanova/src/views/administration.vue @@ -13,7 +13,8 @@ export default { window.$gz.eventBus.$emit("menu-change", { isMain: true, icon: "fa-user-tie", - title: window.$gz.locale.get("Administration") + title: window.$gz.locale.get("Administration"), + helpUrl: "user-form-administration" }); } }; diff --git a/ayanova/src/views/dispatch.vue b/ayanova/src/views/dispatch.vue index d091915f..e266432d 100644 --- a/ayanova/src/views/dispatch.vue +++ b/ayanova/src/views/dispatch.vue @@ -13,7 +13,8 @@ export default { window.$gz.eventBus.$emit("menu-change", { isMain: true, icon: "fa-shipping-fast", - title: window.$gz.locale.get("Dispatch") + title: window.$gz.locale.get("Dispatch"), + helpUrl: "user-form-dispatch" }); } }; diff --git a/ayanova/src/views/inventory.vue b/ayanova/src/views/inventory.vue index 9ea39c8a..63ec8109 100644 --- a/ayanova/src/views/inventory.vue +++ b/ayanova/src/views/inventory.vue @@ -61,7 +61,8 @@ export default { window.$gz.eventBus.$emit("menu-change", { isMain: true, icon: "fa-dolly", - title: window.$gz.locale.get("Inventory") + title: window.$gz.locale.get("Inventory"), + helpUrl: "user-form-inventory" }); }, components: { diff --git a/ayanova/src/views/log.vue b/ayanova/src/views/log.vue index c2797f13..ff8cd61f 100644 --- a/ayanova/src/views/log.vue +++ b/ayanova/src/views/log.vue @@ -26,6 +26,8 @@ export default { isMain: false, icon: "fa-info-circle", title: window.$gz.locale.get("Log"), + helpUrl: "user-form-log", + menuItems: [ // { // title: window.$gz.locale.get("Log"), diff --git a/ayanova/src/views/operations.vue b/ayanova/src/views/operations.vue index c0a31440..70db052e 100644 --- a/ayanova/src/views/operations.vue +++ b/ayanova/src/views/operations.vue @@ -13,7 +13,8 @@ export default { window.$gz.eventBus.$emit("menu-change", { isMain: true, icon: "fa-cogs", - title: window.$gz.locale.get("Operations") + title: window.$gz.locale.get("Operations"), + helpUrl: "user-form-operations" }); } }; diff --git a/ayanova/src/views/service.vue b/ayanova/src/views/service.vue index 6d3f25b3..c3ef9b4a 100644 --- a/ayanova/src/views/service.vue +++ b/ayanova/src/views/service.vue @@ -13,7 +13,8 @@ export default { window.$gz.eventBus.$emit("menu-change", { isMain: true, icon: "fa-toolbox", - title: window.$gz.locale.get("Service") + title: window.$gz.locale.get("Service"), + helpUrl: "user-form-service" }); } };