492 lines
17 KiB
Vue
492 lines
17 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>
|
|
FAF
|
|
{{ obj }}
|
|
</div>
|
|
<v-divider></v-divider>
|
|
<div>
|
|
CUSTOM TEMPLATE
|
|
{{ tempTemplate }}
|
|
</div>
|
|
<v-divider></v-divider> -->
|
|
<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-card-text>
|
|
<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.uiFieldDataTypes"
|
|
item-text="name"
|
|
item-value="id"
|
|
:label="lt('UiFieldDataType')"
|
|
@change="dataTypeChanged(item)"
|
|
></v-select>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</template>
|
|
</v-row>
|
|
</v-form>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</template>
|
|
<script>
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/* Xeslint-disable */
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//NOTE: This is a simple form with no need for business rules or validation so stripped out any extraneous code related to all that
|
|
//
|
|
const FORM_KEY = "customize";
|
|
const API_BASE_URL = "FormCustom/";
|
|
export default {
|
|
beforeRouteEnter(to, from, next) {
|
|
var ltKeysRequired = [
|
|
"FormFieldEntryRequired",
|
|
"FormFieldVisible",
|
|
"UiFieldDataType",
|
|
"UiFieldDataTypesCurrency",
|
|
"UiFieldDataTypesDateOnly",
|
|
"UiFieldDataTypesDateTime",
|
|
"UiFieldDataTypesNumber",
|
|
"UiFieldDataTypesText",
|
|
"UiFieldDataTypesTimeOnly",
|
|
"UiFieldDataTypesTrueFalse"
|
|
];
|
|
|
|
window.$gz.locale.fetch(ltKeysRequired).then(next);
|
|
},
|
|
beforeCreate() {
|
|
var vm = this;
|
|
|
|
var vv = initForm(this);
|
|
|
|
vv.then(() => {
|
|
vm.formState.ready = true;
|
|
}).catch(err => {
|
|
vm.formState.ready = true;
|
|
window.$gz.errorHandler.handleFormError(err);
|
|
});
|
|
},
|
|
beforeRouteLeave(to, from, next) {
|
|
//var vm = this;
|
|
if (this.formState.dirty) {
|
|
window.$gz.dialog.confirmLeaveUnsaved().then(dialogResult => {
|
|
if (dialogResult == true) {
|
|
next();
|
|
} else {
|
|
next(false);
|
|
}
|
|
});
|
|
} else {
|
|
next();
|
|
}
|
|
},
|
|
beforeDestroy() {
|
|
window.$gz.eventBus.$off("menu-click", clickHandler);
|
|
},
|
|
created() {
|
|
window.$gz.eventBus.$on("menu-click", clickHandler);
|
|
//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
|
|
//init disable save button so it can be enabled only on edit to show dirty form
|
|
window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":save");
|
|
},
|
|
data() {
|
|
return {
|
|
obj: [],
|
|
concurrencyToken: undefined,
|
|
formCustomTemplateKey: this.$route.params.formCustomTemplateKey,
|
|
pickLists: {
|
|
uiFieldDataTypes: [
|
|
{ name: this.lt("UiFieldDataTypesDateTime"), id: "1" },
|
|
{ name: this.lt("UiFieldDataTypesDateOnly"), id: "2" },
|
|
{ name: this.lt("UiFieldDataTypesTimeOnly"), id: "3" },
|
|
{ name: this.lt("UiFieldDataTypesText"), id: "4" },
|
|
{ name: this.lt("UiFieldDataTypesTrueFalse"), id: "6" },
|
|
{ name: this.lt("UiFieldDataTypesInteger"), id: "5" },
|
|
{ name: this.lt("UiFieldDataTypesDecimal"), id: "7" },
|
|
{ name: this.lt("UiFieldDataTypesCurrency"), id: "8" }
|
|
]
|
|
},
|
|
formState: {
|
|
ready: false,
|
|
dirty: false,
|
|
valid: true,
|
|
readOnly: false,
|
|
loading: true,
|
|
errorBoxMessage: null,
|
|
appError: null,
|
|
serverError: {}
|
|
},
|
|
rights: window.$gz.role.getRights(window.$gz.type.FormCustom)
|
|
//,tempTemplate: window.$gz.store.state.formCustomTemplate["widget"]
|
|
};
|
|
},
|
|
|
|
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;
|
|
}
|
|
this.formState.dirty = true;
|
|
enableSaveButton();
|
|
},
|
|
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;
|
|
}
|
|
this.formState.dirty = true;
|
|
enableSaveButton();
|
|
},
|
|
dataTypeChanged: function(item) {
|
|
//nothing to scan here just set form dirty
|
|
this.formState.dirty = true;
|
|
enableSaveButton();
|
|
},
|
|
submit() {
|
|
var vm = this;
|
|
var url = API_BASE_URL + this.formCustomTemplateKey;
|
|
|
|
//clear any errors vm might be around from previous submit
|
|
window.$gz.form.deleteAllErrorBoxErrors(this);
|
|
|
|
//Create template data object here....
|
|
//Note that server expects to see a string array of json template, not actual json
|
|
var newObj = {
|
|
formKey: this.formCustomTemplateKey,
|
|
concurrencyToken: this.concurrencyToken,
|
|
template: "[]"
|
|
};
|
|
//temporary array to hold template for later stringification
|
|
var temp = [];
|
|
//Rules:
|
|
for (var i = 0; i < this.obj.length; i++) {
|
|
var fldItem = this.obj[i];
|
|
if (fldItem.custom == false) {
|
|
//Process regular stock field
|
|
//If it's *not* set to stockRequired (i.e. built in field with biz rules that can't be hidden or changed)
|
|
// and it's also set to hidden or required then it's template-worthy
|
|
if (
|
|
!fldItem.stockRequired &&
|
|
(fldItem.visible == false || fldItem.required == true)
|
|
) {
|
|
temp.push({
|
|
fld: fldItem.key,
|
|
required: fldItem.required,
|
|
hide: !fldItem.visible
|
|
});
|
|
}
|
|
} else {
|
|
//Process custom field
|
|
//If it's not visible then don't add it at all
|
|
if (fldItem.visible == true) {
|
|
temp.push({
|
|
fld: fldItem.key,
|
|
required: fldItem.required,
|
|
type: fldItem.type
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
//now set the template as a json string
|
|
newObj.template = JSON.stringify(temp);
|
|
|
|
window.$gz.api
|
|
.upsert(url, newObj)
|
|
.then(res => {
|
|
vm.formState.loading = false;
|
|
if (res.error != undefined) {
|
|
vm.formState.serverError = res.error;
|
|
window.$gz.form.setErrorBoxErrors(vm);
|
|
} else {
|
|
//Handle "put" of an existing record (UPDATE) (there is no POST of a new record for this particular object)
|
|
|
|
//Set store values for template and token
|
|
window.$gz.formCustomTemplate.set(
|
|
vm.formCustomTemplateKey,
|
|
res.data.concurrencyToken,
|
|
newObj.template
|
|
);
|
|
//set our local concurrency token value
|
|
vm.concurrencyToken = res.data.concurrencyToken;
|
|
|
|
//form is now clean
|
|
window.$gz.form.setFormState({
|
|
vm: vm,
|
|
dirty: false
|
|
});
|
|
}
|
|
})
|
|
.catch(function handleSubmitError(error) {
|
|
vm.formState.loading = false;
|
|
window.$gz.errorHandler.handleFormError(error, vm);
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
function enableSaveButton() {
|
|
window.$gz.eventBus.$emit("menu-enable-item", FORM_KEY + ":save");
|
|
}
|
|
|
|
/////////////////////////////
|
|
//
|
|
//
|
|
function clickHandler(menuItem) {
|
|
if (!menuItem) {
|
|
return;
|
|
}
|
|
var m = window.$gz.menu.parseMenuItem(menuItem);
|
|
if (m.owner == FORM_KEY && !m.disabled) {
|
|
switch (m.key) {
|
|
case "save":
|
|
m.vm.submit();
|
|
break;
|
|
|
|
default:
|
|
window.$gz.eventBus.$emit(
|
|
"notify-warning",
|
|
FORM_KEY + "::context click: [" + m.key + "]"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////
|
|
//
|
|
//
|
|
function generateMenu(vm) {
|
|
var menuOptions = {
|
|
isMain: false,
|
|
icon: "fa-sliders-h",
|
|
title: window.$gz.locale.get("Customize"),
|
|
helpUrl: "form-ay-customize",
|
|
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(() => {
|
|
//Must use return here
|
|
return initDataObject(vm);
|
|
});
|
|
}
|
|
|
|
////////////////////
|
|
//
|
|
function ensureTemplateIsInStore(vm) {
|
|
return window.$gz.formCustomTemplate.get(
|
|
vm.$route.params.formCustomTemplateKey
|
|
);
|
|
}
|
|
|
|
////////////////////
|
|
//
|
|
function initDataObject(vm) {
|
|
//http://localhost:7575/api/v8/ObjectFields/ObjectFields/widget
|
|
|
|
var url = "FormFieldsDefinitions/" + 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 ObjectFields
|
|
//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 = window.$gz.formCustomTemplate.getFieldTemplateValue(
|
|
vm.formCustomTemplateKey,
|
|
faf.fieldKey
|
|
);
|
|
|
|
//handle non-existent template item (expected)
|
|
if (templateItem === undefined || templateItem === null) {
|
|
templateItem = {
|
|
required: false,
|
|
hide: faf.isCustomField ? true : false, //hide if custom because it's not set to display if it's not present, all others are stock fields
|
|
type: "text"
|
|
};
|
|
}
|
|
|
|
// var canHide=faf.hideable && templateItem.required!==true;
|
|
|
|
var objItem = {
|
|
key: faf.fieldKey,
|
|
title: window.$gz.locale.get(faf.ltKey),
|
|
stockRequired: !faf.hideable,
|
|
custom: faf.isCustomField,
|
|
required: faf.hideable === false || templateItem.required === true,
|
|
visible: templateItem.hide !== true,
|
|
type: templateItem.type
|
|
};
|
|
|
|
vm.obj.push(objItem);
|
|
vm.concurrencyToken = window.$gz.formCustomTemplate.getTemplateConcurrencyToken(
|
|
vm.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)
|
|
"UiFieldDataTypesCurrency": "Money",
|
|
"UiFieldDataTypesDateOnly": "Date",
|
|
"UiFieldDataTypesDateTime": "Date & Time",
|
|
"UiFieldDataTypesNumber": "Number",
|
|
"UiFieldDataTypesText": "Text",
|
|
"UiFieldDataTypesTimeOnly": "Time",
|
|
"UiFieldDataTypesTrueFalse": "True/False",
|
|
|
|
NEW (used)
|
|
"FormFieldEntryRequired" = "Required"
|
|
"FormFieldVisible" = "Visible" (copy from ObjectCustomFieldVisible)
|
|
"UiFieldDataType" = "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 ObjectFields.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":"WidgetUserType","propertyName":"UserType","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>
|