This commit is contained in:
@@ -45,6 +45,13 @@ CURRENT ROADMAP
|
||||
CURRENT TODOs
|
||||
=-=-=-=-=-=-=
|
||||
|
||||
|
||||
TODO: Make sure can easily make new record in Widget form before getting into deeper stuff or making any other object forms.
|
||||
|
||||
TODO: UI would be greatly enhanced if server defined form customization rules for required fields both Custom and regular were incorporated into client end before roundtripping to the server
|
||||
- Right now it has to save the record to get the return errors about required fields, that is shit. The client is easily able to tell what is required in the form customization so it should be able to surface that up front
|
||||
- This will save bandwidth and annoyance factor 1000 for people
|
||||
|
||||
TODO: Widget edit form, new record sb time and dates pre-filled in? Server involved? How to handle new record initial date set?
|
||||
- Seeing a few issues that are probably related to having an empty record on start of new object
|
||||
- Don't start blank basically
|
||||
@@ -54,16 +61,37 @@ TODO: Widget edit form, new record sb time and dates pre-filled in? Server invol
|
||||
TODO: Widget edit form, new record cdata error as it's empty on new
|
||||
- To see, create new and edit the custom2
|
||||
|
||||
TODO: Custom fields
|
||||
- Needs to cache the customization data of the form and concurrency token used to fetch it and then it checks the concurrency token periodically
|
||||
- {"data":{"id":1,"concurrencyToken":3761005,"formKey":"widget","template":"[{\"fld\":\"WidgetNotes\",\"required\":\"true\"},{\"fld\":\"WidgetCustom1\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"datetime\"},{\"fld\":\"WidgetCustom2\",\"hide\":\"false\",\"required\":\"true\",\"type\":\"text\"},{\"fld\":\"WidgetCustom3\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"number\"},{\"fld\":\"WidgetCustom4\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"bool\"},{\"fld\":\"WidgetCustom5\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"currency\"},{\"fld\":\"WidgetCustom6\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"date\"},{\"fld\":\"WidgetCustom7\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"time\"}]"}}
|
||||
|
||||
- Needs to be aware of and handle the fact that the end user may change the data type
|
||||
- if it expects a type of value and finds one it can't co-erce into the new type then it should zap it or set it null by default.
|
||||
- This could get ugly so just stick to a simple system like wiping uncoercable data and fuck it, they made their choice :)
|
||||
- Implement then Componentize
|
||||
- Maybe start with a component first now that I have my feet wet in it, saves time
|
||||
- Have to think about the design, but probably most useful when on the same page as the main record just like in v7 windows
|
||||
- Should be a single component I can reference on the form that handles it all directly
|
||||
- Custom field "slot" maybe just like the VUE Way so that it can be easily optionally shown or not in it's slot
|
||||
- Though, these need to be part of the record as well, hmmm...maybe better if they appear to be just normal fields and are added dynamically??
|
||||
- It would be nice though to just insert a slot and let a component handle it rather than buncvh of code on every form...
|
||||
- It's kind of like one control that is bound to the JSON custom fields-field and it would update it as edited and required so I guess this is how to think about it and implement it, as a control
|
||||
|
||||
TODO: Form customize UI
|
||||
- Where you create custom fields and edit
|
||||
- If a user changes a field data type there needs to be a big warning before accepting it.
|
||||
|
||||
TODO: Support form customization beyond Custom:
|
||||
- hide fields not used
|
||||
- force user to enter a value in a field optionally that isn't already required
|
||||
|
||||
TODO: Save button isn't enabling on changes in new record when it should. Enter in a value in the Name field of an empty record and move to a new field and it should immediately show the save button due to dirtiness?
|
||||
- Or is it becuase of broken rules that are not being displayed immediately? (new record should really show a bunch of broken rules right away as it has some empty and required fields)
|
||||
- Yes this seems to be it, also until all rules are unbroken save sb not enabled, but it appears that one more edit needs to be done after the last broken rule to unstick it or maybe it's the case mismatch issue above that will fix it
|
||||
|
||||
TODO: Make sure can easily make new record in Widget form before getting into deeper stuff or making any other object forms.
|
||||
|
||||
TODO: UI would be greatly enhanced if server defined form customization rules for required fields both Custom and regular were incorporated into client end before roundtripping to the server
|
||||
- Right now it has to save the record to get the return errors about required fields, that is shit. The client is easily able to tell what is required in the form customization so it should be able to surface that up front
|
||||
- This will save bandwidth and annoyance factor 1000 for people
|
||||
|
||||
|
||||
|
||||
TODO: Bug? Set widget edit form times to 4:20pm and observe that in the main grid list it shows as 320 pm!?
|
||||
|
||||
@@ -100,27 +128,7 @@ TODO: (may be done already) modify the inventory-widget-edit form initialization
|
||||
TODO: DataDump plugin needs an explanation of what it is in the flow, right now it's completely cryptic and people may be using it for stuff thinking it's for something it's not
|
||||
- Also, verify it's manager account only that can run it or maybe someone with total rights to everything?
|
||||
|
||||
TODO: Custom fields
|
||||
- Needs to cache the customization data of the form and concurrency token used to fetch it and then it checks the concurrency token periodically
|
||||
- Needs to be aware of and handle the fact that the end user may change the data type
|
||||
- if it expects a type of value and finds one it can't co-erce into the new type then it should zap it or set it null by default.
|
||||
- This could get ugly so just stick to a simple system like wiping uncoercable data and fuck it, they made their choice :)
|
||||
- Implement then Componentize
|
||||
- Maybe start with a component first now that I have my feet wet in it, saves time
|
||||
- Have to think about the design, but probably most useful when on the same page as the main record just like in v7 windows
|
||||
- Should be a single component I can reference on the form that handles it all directly
|
||||
- Custom field "slot" maybe just like the VUE Way so that it can be easily optionally shown or not in it's slot
|
||||
- Though, these need to be part of the record as well, hmmm...maybe better if they appear to be just normal fields and are added dynamically??
|
||||
- It would be nice though to just insert a slot and let a component handle it rather than buncvh of code on every form...
|
||||
- It's kind of like one control that is bound to the JSON custom fields-field and it would update it as edited and required so I guess this is how to think about it and implement it, as a control
|
||||
|
||||
TODO: Form customize UI
|
||||
- Where you create custom fields and edit
|
||||
- If a user changes a field data type there needs to be a big warning before accepting it.
|
||||
|
||||
TODO: Support form customization beyond Custom:
|
||||
- hide fields not used
|
||||
- force user to enter a value in a field optionally that isn't already required
|
||||
|
||||
|
||||
TODO: Record history display / check other AyaNova 7 options / buttons that need to carry forward
|
||||
|
||||
@@ -16,6 +16,9 @@ function addDataKeyNames(obj) {
|
||||
}
|
||||
|
||||
export default {
|
||||
// cache the form customization data if it's not already present
|
||||
//cache invalidation is hard, this needs it...hmmm....
|
||||
//for now will rely on logout and back in to clear up any customization issues
|
||||
get(formKey) {
|
||||
return new Promise(function getFormTemplate(resolve) {
|
||||
if (
|
||||
|
||||
@@ -47,6 +47,21 @@ function isNumber(n) {
|
||||
//
|
||||
function getControl(vm, ref) {
|
||||
var ctrl = vm.$refs[ref];
|
||||
if (ctrl === undefined) {
|
||||
//it's either a sub field in custom fields component or it's a coding error
|
||||
var customFields = vm.$refs["customFields"];
|
||||
if (customFields !== undefined) {
|
||||
ctrl = customFields.$refs[ref];
|
||||
}
|
||||
}
|
||||
|
||||
//can't do it like this because during init undefined is normal apparently
|
||||
// if (ctrl === undefined && window.$gz.errorHandler.devMode()) {
|
||||
// debugger;
|
||||
// throw "DEV ERROR gzform::formState.getControl -> control ref of [" +
|
||||
// ref +
|
||||
// "] was not found in the form or in the custom fields";
|
||||
// }
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
@@ -63,11 +78,12 @@ function getControlValue(ctrl) {
|
||||
// Get field name from control
|
||||
//
|
||||
function getControlLabel(ctrl) {
|
||||
if (window.$gz.errorHandler.developmentModeShowErrorsImmediately) {
|
||||
if (!ctrl.label) {
|
||||
throw "gzform:getControlLabel - the control has no label " + ctrl;
|
||||
}
|
||||
}
|
||||
// if (window.$gz.errorHandler.developmentModeShowErrorsImmediately) {
|
||||
// if (!ctrl.label) {
|
||||
// debugger;
|
||||
// throw "gzform:getControlLabel - the control has no label " + ctrl;
|
||||
// }
|
||||
// }
|
||||
return ctrl.label;
|
||||
}
|
||||
|
||||
@@ -82,16 +98,15 @@ function getErrorsForField(vm, ref) {
|
||||
return !o.target;
|
||||
});
|
||||
} else {
|
||||
|
||||
ret = window.$gz._.filter(vm.formState.serverError.details, function(o) {
|
||||
if (!o.target) {
|
||||
return false;
|
||||
}
|
||||
//server error fields are capitalized
|
||||
//server error fields are capitalized
|
||||
//client field names are generally lower case except for custom fields
|
||||
//so we need to normalize them all to lower case to match
|
||||
//they will always differ by more than case so this is fine
|
||||
console.log("getErrorsForField finding matches, comparing serverErrorField:["+o.target.toLowerCase() + "] to form field ref:["+ref.toLowerCase()+"]");
|
||||
// console.log("getErrorsForField finding matches, comparing serverErrorField:["+o.target.toLowerCase() + "] to form field ref:["+ref.toLowerCase()+"]");
|
||||
return o.target.toLowerCase() == ref.toLowerCase();
|
||||
});
|
||||
}
|
||||
@@ -134,6 +149,7 @@ export default {
|
||||
if (vm.formState.loading) {
|
||||
return false;
|
||||
}
|
||||
//debugger;
|
||||
var ctrl = getControl(vm, ref);
|
||||
if (typeof ctrl == "undefined") {
|
||||
return false;
|
||||
@@ -324,10 +340,8 @@ export default {
|
||||
// Process and return server errors if any for form and field specified
|
||||
//
|
||||
serverErrors(vm, ref) {
|
||||
|
||||
//CHECK PREREQUISITES IN DEV MODE TO ENSURE FORM ISN"T MISSING NEEDED DATA ATTRIBUTES ETC
|
||||
if (window.$gz.errorHandler.devMode()) {
|
||||
|
||||
//make sure formState.serverErrors is defined on data
|
||||
if (!window.$gz._.has(vm, "formState.serverError")) {
|
||||
throw "DEV ERROR gzform::formState.serverErrors -> formState.serverError seems to be missing from form's vue data object";
|
||||
@@ -355,7 +369,6 @@ export default {
|
||||
|
||||
//check for errors if we have any errors
|
||||
if (!window.$gz._.isEmpty(vm.formState.serverError)) {
|
||||
|
||||
//First let's get the top level error code
|
||||
|
||||
var apiErrorCode = parseInt(vm.formState.serverError.code);
|
||||
@@ -443,7 +456,8 @@ export default {
|
||||
//
|
||||
onChange(vm, ref) {
|
||||
//xeslint-disable-next-line
|
||||
//console.log("GZFORM::onChange triggered!");
|
||||
//WidgetCustom2
|
||||
//console.log("GZFORM::onChange triggered for field " + ref);
|
||||
if (triggeringChange || vm.formState.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,14 @@
|
||||
|
||||
<div>
|
||||
<v-row align-center justify-left row wrap>
|
||||
<!-- Here is what a template object looks like
|
||||
"template":"[
|
||||
{\"fld\":\"WidgetNotes\",\"required\":\"true\"},{\"fld\":\"WidgetCustom1\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"datetime\"},
|
||||
{\"fld\":\"WidgetCustom2\",\"hide\":\"false\",\"required\":\"true\",\"type\":\"text\"},{\"fld\":\"WidgetCustom3\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"number\"},
|
||||
{\"fld\":\"WidgetCustom4\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"bool\"},{\"fld\":\"WidgetCustom5\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"currency\"},
|
||||
{\"fld\":\"WidgetCustom6\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"date\"},{\"fld\":\"WidgetCustom7\",\"hide\":\"false\",\"required\":\"false\",\"type\":\"time\"}]"
|
||||
Note that it mixes in regular stock form fields that the end user has set to required as well as the custom ones, we identify custom by the presence of the "type" property
|
||||
-->
|
||||
<template v-for="item in this.$store.state.formCustomTemplate[formKey]">
|
||||
<v-col
|
||||
v-if="item.type"
|
||||
@@ -38,13 +46,16 @@
|
||||
DATE and TIME CONTROL HERE
|
||||
</div>
|
||||
<div v-else-if="item.type === 'text'">
|
||||
{{ lt(item.fld) }}
|
||||
<v-textarea
|
||||
v-model="_self[item.dataKey]"
|
||||
:readonly="readOnly"
|
||||
:label="lt(item.fld)"
|
||||
:ref="item.fld"
|
||||
:error-messages="form().serverErrors(parentVM, item.fld)"
|
||||
:rules="[form().required(parentVM, item.fld)]"
|
||||
auto-grow
|
||||
clearable
|
||||
></v-textarea>
|
||||
|
||||
<!-- <v-textarea
|
||||
@@ -55,6 +66,10 @@
|
||||
ref="notes"
|
||||
@change="onChange('notes')"
|
||||
auto-grow
|
||||
|
||||
@change="onChange(item.fld)"
|
||||
|
||||
>
|
||||
></v-textarea> -->
|
||||
</div>
|
||||
<div v-else-if="item.type === 'number'">
|
||||
@@ -76,7 +91,7 @@
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* xeslint-disable */
|
||||
/* eslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* v-if="item.hide == false"
|
||||
@@ -115,7 +130,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
c1: null,
|
||||
//c2: "Here is my WidgetCustom2 Data!",
|
||||
// c2: null, this was replaced with a computed property as will all others
|
||||
c3: null,
|
||||
c4: null,
|
||||
c5: null,
|
||||
@@ -155,11 +170,16 @@ export default {
|
||||
//nothing
|
||||
return window.$gz.form;
|
||||
},
|
||||
onChange(ref) {
|
||||
if (!this.parentVM.formState.loading && !this.parentVM.formState.readOnly) {
|
||||
window.$gz.form.onChange(this.parentVM, ref);
|
||||
}
|
||||
},
|
||||
GetValueForField: function(dataKey) {
|
||||
if (!this.value) {
|
||||
return null;
|
||||
}
|
||||
// debugger;
|
||||
//debugger;
|
||||
//get the data out of the JSON string value
|
||||
var cData = JSON.parse(this.value);
|
||||
|
||||
@@ -169,20 +189,29 @@ export default {
|
||||
//coerce it to that type and return it
|
||||
//TODO: Method here
|
||||
|
||||
// debugger;
|
||||
|
||||
return cData[dataKey];
|
||||
},
|
||||
SetValueForField: function(dataKey, newValue) {
|
||||
//https://stackoverflow.com/questions/39868963/vue-2-mutating-props-vue-warn
|
||||
|
||||
//debugger;
|
||||
|
||||
//Get the data out of the json string value
|
||||
//
|
||||
var cData = JSON.parse(this.value);
|
||||
|
||||
//then set item in the cData
|
||||
//TODO: This will likely need also to be converted because dates and stuff
|
||||
//initial naive attempt: (tostring is suspect)
|
||||
cData[dataKey] = newValue.toString();
|
||||
//handle null or undefined
|
||||
if (newValue === null || newValue === undefined) {
|
||||
cData[dataKey] = null;
|
||||
} else {
|
||||
|
||||
//then set item in the cData
|
||||
|
||||
//TODO: This will likely need also to be converted because dates and stuff
|
||||
//initial naive attempt: (tostring is suspect)
|
||||
cData[dataKey] = newValue.toString();
|
||||
}
|
||||
|
||||
//emit the new data so it syncs with the parent source
|
||||
var ret = JSON.stringify(cData);
|
||||
@@ -203,10 +232,6 @@ export default {
|
||||
throw "custom-fields-control: $gz.locale is required and missing";
|
||||
}
|
||||
}
|
||||
|
||||
//trigger the template fetch
|
||||
|
||||
//var v=this.$store.state.formCustomTemplate[this.formKey];
|
||||
},
|
||||
created() {
|
||||
// console.log("custom-fields-control::BEFORECREATE: TOP");
|
||||
|
||||
@@ -147,6 +147,7 @@
|
||||
ref="notes"
|
||||
@change="onChange('notes')"
|
||||
auto-grow
|
||||
clearable
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
|
||||
@@ -235,11 +236,10 @@ export default {
|
||||
"WidgetCustom16"
|
||||
];
|
||||
|
||||
window.$gz.locale
|
||||
.fetch(ltKeysRequired)
|
||||
.then(
|
||||
window.$gz.formCustomTemplate.get(FORM_CUSTOM_TEMPLATE_KEY).then(next())
|
||||
);
|
||||
window.$gz.locale.fetch(ltKeysRequired).then(
|
||||
//ensure cached any form customizations for this particular form
|
||||
window.$gz.formCustomTemplate.get(FORM_CUSTOM_TEMPLATE_KEY).then(next())
|
||||
);
|
||||
|
||||
// //very important as this in conjunction with the menu options means
|
||||
// //navigation guards work properly by just sending people here
|
||||
@@ -276,7 +276,7 @@ export default {
|
||||
valid: true,
|
||||
loading: false,
|
||||
readOnly: readOnly
|
||||
});
|
||||
});
|
||||
|
||||
//it's a new record so it can't be deleted so...
|
||||
this.rights.delete = false;
|
||||
|
||||
Reference in New Issue
Block a user