Files
raven-client/ayanova/src/views/customize.vue
2019-12-06 20:05:19 +00:00

377 lines
14 KiB
Vue

<template>
<v-container>
<!-- <div>
READY: {{ formState.ready }}
<br />
LOADING: {{ formState.loading }}
<br />
DIRTY: {{ formState.dirty }}
<br />
VALID: {{ formState.valid }}
<br />
READONLY: {{ formState.readOnly }}
<br />
</div> -->
<div>
{{ obj }}
</div>
<v-row v-if="this.formState.ready">
<v-col>
<v-form ref="form">
<v-row>
<v-col cols="12" mt-1 mb-2>
<v-alert
ref="errorbox"
v-show="formState.errorBoxMessage"
color="error"
icon="fa-exclamation-circle "
transition="scale-transition"
class="multi-line"
outlined
>{{ formState.errorBoxMessage }}</v-alert
>
</v-col>
<template v-for="item in obj">
<v-col :key="item.key" cols="12" sm="6" lg="4" xl="3" px-2>
<v-card>
<v-card-title>
{{ item.title }}
</v-card-title>
<v-card-subtitle>
{{ item.key }}
</v-card-subtitle>
<v-checkbox
v-model="item.visible"
:label="lt('FormFieldVisible')"
:ref="item.key"
:disabled="item.stockRequired"
@change="visibleChanged(item)"
></v-checkbox>
<v-checkbox
v-model="item.required"
:label="lt('FormFieldEntryRequired')"
:disabled="item.stockRequired"
@change="requiredChanged(item)"
></v-checkbox>
<v-select
v-if="item.custom"
v-model="item.type"
:items="pickLists.formFieldDataTypes"
item-text="name"
item-value="id"
:label="lt('FormfieldDataType')"
></v-select>
<v-divider></v-divider>
{{ item }}
</v-card>
</v-col>
</template>
</v-row>
</v-form>
</v-col>
</v-row>
</v-container>
</template>
<script>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Xeslint-disable */
////////////////////////////////////////////////////////////////////////////////////////////////////////////
const FORM_KEY = "customize";
const API_BASE_URL = "FormCustom/";
export default {
beforeRouteEnter(to, from, next) {
var ltKeysRequired = [
"FormFieldEntryRequired",
"FormFieldVisible",
"FormfieldDataType",
"FormFieldDataTypesCurrency",
"FormFieldDataTypesDateOnly",
"FormFieldDataTypesDateTime",
"FormFieldDataTypesNumber",
"FormFieldDataTypesText",
"FormFieldDataTypesTimeOnly",
"FormFieldDataTypesTrueFalse"
];
window.$gz.locale.fetch(ltKeysRequired).then(next());
},
beforeCreate() {
var vm = this;
initForm(this)
.then(() => {
vm.formState.ready = true;
})
.catch(err => {
vm.formState.ready = true;
window.$gz.errorHandler.handleFormError(err);
});
},
created() {
//NOTE: this would normally be in getDataFromAPI but this form doesn't really need that function so doing it here
//modify the menu as necessary
generateMenu(this, false); //default is never read only and passing in this vm
},
data() {
return {
obj: [],
formCustomTemplateKey: this.$route.params.formCustomTemplateKey,
pickLists: {
formFieldDataTypes: [
{ name: this.lt("FormFieldDataTypesCurrency"), id: "currency" },
{ name: this.lt("FormFieldDataTypesDateOnly"), id: "date" },
{ name: this.lt("FormFieldDataTypesTimeOnly"), id: "time" },
{ name: this.lt("FormFieldDataTypesDateTime"), id: "datetime" },
{ name: this.lt("FormFieldDataTypesText"), id: "text" },
{ name: this.lt("FormFieldDataTypesNumber"), id: "number" },
{ name: this.lt("FormFieldDataTypesTrueFalse"), id: "bool" }
]
},
formState: {
ready: false,
dirty: false,
valid: true,
readOnly: false,
loading: true,
errorBoxMessage: null,
appError: null,
serverError: {}
},
rights: window.$gz.role.defaultRightsObject()
};
},
//WATCHERS
watch: {
formState: {
handler: function(val) {
//,oldval is available here too if necessary
if (this.formState.loading) {
return;
}
//enable / disable save button
var canSave = val.dirty && val.valid && !val.readOnly;
if (canSave) {
window.$gz.eventBus.$emit("menu-enable-item", FORM_KEY + ":save");
} else {
window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":save");
}
//enable / disable duplicate button
var canDuplicate = !val.dirty && val.valid && !val.readOnly;
if (canDuplicate) {
window.$gz.eventBus.$emit(
"menu-enable-item",
FORM_KEY + ":duplicate"
);
} else {
window.$gz.eventBus.$emit(
"menu-disable-item",
FORM_KEY + ":duplicate"
);
}
},
deep: true
}
},
computed: {
canSave: function() {
return this.formState.valid && this.formState.dirty;
},
canDuplicate: function() {
return this.formState.valid && !this.formState.dirty;
}
},
components: {},
methods: {
lt: function(ltkey) {
return window.$gz.locale.get(ltkey);
},
visibleChanged: function(item) {
//Note: stock items can't be changed so no need to take that into account
if (item.required && item.visible == false) {
item.required = false;
}
},
requiredChanged: function(item) {
//Note: stock items can't be changed so no need to take that into account
if (item.required && item.visible == false) {
item.visible = true;
}
}
}
};
//////////////////////
//
//
function generateMenu(vm) {
var menuOptions = {
isMain: false,
icon: "fa-sliders-h",
title: window.$gz.locale.get("Customize"),
helpUrl: "intro/#searching",
formData: {
formKey: FORM_KEY,
ayaType: window.$gz.type.FormCustom,
formCustomTemplateKey: undefined
},
menuItems: []
};
if (vm.rights.change) {
menuOptions.menuItems.push({
title: window.$gz.locale.get("Save"),
icon: "save",
surface: true,
key: FORM_KEY + ":save",
vm: vm
});
}
window.$gz.eventBus.$emit("menu-change", menuOptions);
}
function initForm(vm) {
return ensureTemplateIsInStore(vm).then(initDataObject(vm));
//return initDataObject(vm).then(ensureTemplateIsInStore(vm));
}
////////////////////
//
function initDataObject(vm) {
//http://localhost:7575/api/v8/FormCustom/AvailableFields/widget
var url =
API_BASE_URL + "AvailableFields/" + vm.$route.params.formCustomTemplateKey;
return window.$gz.api.get(url).then(res => {
if (res.error) {
throw res.error;
}
//set vm.obj to the combined synthesized snapshot array of template and availble fields for working data for this form
// - {key, ltdisplay, hideable, custom, required, hide, type}
//Iterate formAvailableFields
//create a new object based on the f.a.f. item and any existing template values for that item
for (var i = 0; i < res.data.length; i++) {
//get the formAvailableField record into an object to save typing
var faf = res.data[i];
//get the customTemplate record for this field if it exists
var templateItem = (templateItem = window.$gz.formCustomTemplate.getFieldTemplateValue(
vm.formCustomTemplateKey,
faf.key
));
//handle non-existent template item (expected)
if (templateItem === undefined || templateItem === null) {
templateItem = { required: false, hide: false, type: "text" };
}
// var canHide=faf.hideable && templateItem.required!==true;
var objItem = {
key: faf.key,
title: window.$gz.locale.get(faf.key),
stockRequired: !faf.hideable,
custom: faf.custom,
required: faf.hideable === false || templateItem.required === true,
visible: templateItem.hide !== true,
type: templateItem.type
};
//debugger;
vm.obj.push(objItem);
}
// vm.formAvailableFields = res.data;
});
}
////////////////////
//
function ensureTemplateIsInStore(vm) {
return window.$gz.formCustomTemplate.get(
vm.$route.params.formCustomTemplateKey
);
}
/*
OLD (not used, drop)
"ObjectCustomFieldCustomGrid": "Custom Fields",
"ObjectCustomFieldDisplayName": "Display as",
"ObjectCustomFieldFieldName": "Field Name",
"ObjectCustomFieldFieldType": "Field data type",
"ObjectCustomFieldObjectName": "Object name",
"ObjectCustomFieldVisible": "Visible",
CURRENT (used)
"FormFieldDataTypesCurrency": "Money",
"FormFieldDataTypesDateOnly": "Date",
"FormFieldDataTypesDateTime": "Date & Time",
"FormFieldDataTypesNumber": "Number",
"FormFieldDataTypesText": "Text",
"FormFieldDataTypesTimeOnly": "Time",
"FormFieldDataTypesTrueFalse": "True/False",
NEW (used)
"FormFieldEntryRequired" = "Required"
"FormFieldVisible" = "Visible" (copy from ObjectCustomFieldVisible)
"FormfieldDataType" = "Data type" (copy from ObjectCustomFieldDataType)
UI:
(Note: localization is in another area, no need to worry about display names here even for custom fields)
List of fields in a grid:
LTDisplay [FieldKey] , Visible, Required, DataType (if custom)
(Some items will have their visible or required read only because they are stock and can't be changed see FormAvailableFields.cs in server)
(A required field by default can't be hidden, setting to required automatically toggles hidden=false here but reverse doesn't do the opposite)
TODO:
Fetch - form field custom data
Possibly turn it into a easily iterated collection in the Data key
Iterate and display in series of boxes (small factor UI)
OnSave sends to server and roundtrips back to refresh local cached copy
Example form available fields
{"data":[
{"key":"WidgetName","propertyName":"Name","hideable":false,"sharedLTKey":false,"custom":false},
{"key":"WidgetSerial","propertyName":"Serial","hideable":true,"sharedLTKey":false,"custom":false},
{"key":"WidgetDollarAmount","propertyName":"DollarAmount","hideable":true,"sharedLTKey":false,"custom":false},
{"key":"WidgetCount","propertyName":"Count","hideable":true,"sharedLTKey":false,"custom":false},
{"key":"WidgetRoles","propertyName":"Roles","hideable":true,"sharedLTKey":false,"custom":false},
{"key":"WidgetStartDate","propertyName":"StartDate","hideable":false,"sharedLTKey":false,"custom":false},
{"key":"WidgetEndDate","propertyName":"EndDate","hideable":false,"sharedLTKey":false,"custom":false},
{"key":"WidgetNotes","propertyName":"Notes","hideable":true,"sharedLTKey":false,"custom":false},
{"key":"Active","propertyName":"Active","hideable":true,"sharedLTKey":true,"custom":false},
{"key":"Tags","propertyName":"Tags","hideable":true,"sharedLTKey":true,"custom":false},
{"key":"WidgetCustom1","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom2","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom3","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom4","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom5","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom6","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom7","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom8","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom9","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom10","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom11","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom12","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom13","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom14","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom15","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true},
{"key":"WidgetCustom16","propertyName":null,"hideable":true,"sharedLTKey":false,"custom":true}],"readOnly":true}
Example form custom template
"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
*/
</script>