This commit is contained in:
2020-02-10 19:58:06 +00:00
parent f4f1338c1c
commit 080a1ae794
3 changed files with 485 additions and 0 deletions

445
ayanova/src/api/enums.js Normal file
View File

@@ -0,0 +1,445 @@
/* ZZeslint-disable */
//TODO: Need enum translator
//AuthorizationRoles.128
//window.$gz.local.enumLocalized(enumType, enumValue)
//(in locale) check if have that type already featched, if not fetches the whole list and caches it locally
//also a method to return the list of enumerated types in ID order with localized names
//window.$gz.local.enumList(enumType) - returns a list usable on edit forms
/* enums: {
AuthorizationRoles0:"No role",
AuthorizationRoles1:"Business admin limited"
etc
to get all authorization roles iterate list looking for start of key that is AuthorizationRoles
To get individual one same but only need to fetch actual value i.e. AuthorizationRoles1
if not one item starts with AuthorizationRoles then list needs to be fetched, maybe can use the enumpicklist route for that
This way entirely bypasses locale stuff
//big object so maybe it's own thing, not part of locale at all or locale fronts for it??
*/
export default {
getEnumDisplay(enumKey, enumValue) {
// debugger;
if (!window.$gz._.has(window.$gz.store.state.localeText, key)) {
return "??" + key;
}
return window.$gz.store.state.localeText[key];
},
///////////////////////////////////
//
// Returns an array of enum value and display objects
// for enum key specified
// e.g. [{0:"no role"},{1:"Limited role"}]
//
getEnumList(enumKey) {
// debugger;
if (!window.$gz._.has(window.$gz.store.state.enums, enumKey)) {
return "??" + key;
}
return window.$gz.store.state.localeText[key];
},
fetch(keys) {
return new Promise(function fetchLocaleKeysFromServer(resolve) {
//
//step 1: build an array of keys that we don't have already
//Note: this will ensure only unique keys go into the store so it's safe to call this with dupes as can happen
//for example datatables have dynamic column names so they need to fetch on demand
var needIt = [];
for (var i = 0; i < keys.length; i++) {
if (!window.$gz._.has(window.$gz.store.state.localeText, keys[i])) {
needIt.push(keys[i]);
}
}
if (needIt.length == 0) {
resolve();
return;
}
//step 2: get it
fetch(
window.$gz.api.APIUrl("locale/subset"),
window.$gz.api.fetchPostOptions(needIt)
)
.then(window.$gz.api.status)
.then(window.$gz.api.json)
.then(response => {
window.$gz._.forEach(
response.data,
function commitFetchedLTItemToStore(item) {
window.$gz.store.commit("addLocaleText", item);
}
);
resolve();
});
});
},
//Keys that will always be required for any AyaNova work for any user
coreKeys: [
//main nav options
"Home",
"Dashboard",
"Schedule",
"MemoList",
"UserSettings",
"Locale",
"SetLoginPassword",
"NotifySubscriptionList",
"UserPreferences",
"Service",
"ClientList",
"HeadOfficeList",
"WorkorderServiceList",
"WorkorderServiceTemplate",
"WorkorderQuoteList",
"WorkorderQuoteTemplate",
"WorkorderPreventiveMaintenanceList",
"WorkorderPreventiveMaintenanceTemplate",
"UnitList",
"UnitModels",
"ContractList",
"ClientServiceRequestList",
"LoanItemList",
"PartList",
"PartByWarehouseInventoryList",
"WorkorderItemPartRequestList",
"InventoryPurchaseOrders",
"InventoryPurchaseOrderReceipts",
"InventoryPartInventoryAdjustments",
"WidgetList",
"VendorList",
"AdministrationGlobalSettings",
"HelpLicense",
"UserList",
"LocalizedTextDesign",
"ReportList",
"ReminderList",
"Inventory",
"Accounting",
"Administration",
"Operations",
"Attachments",
"Review",
"History",
"Statistics",
"Backup",
"ServerJobs",
"ServerLog",
"ServerMetrics",
"NotificationSettings",
"HelpAboutAyaNova",
"MenuHelp",
"More",
"Logout",
//form required options
"Active",
"Add",
"Cancel",
"Close",
"Save",
"Delete",
"OK",
"Print",
"Report",
"WikiPage",
"Duplicate",
"RecordHistory",
"Search",
"TypeToSearchOrAdd",
"NoData",
"ErrorFieldLengthExceeded",
"ErrorStartDateAfterEndDate",
"ErrorRequiredFieldEmpty",
"ErrorFieldValueNotInteger",
"ErrorFieldValueNotDecimal",
"ErrorAPI2000",
"ErrorAPI2001",
"ErrorAPI2002",
"ErrorAPI2003",
"ErrorAPI2004",
"ErrorAPI2005",
"ErrorAPI2010",
"ErrorAPI2020",
"ErrorAPI2030",
"ErrorAPI2200",
"ErrorAPI2201",
"ErrorAPI2202",
"ErrorAPI2203",
"ErrorAPI2204",
"ErrorAPI2205",
"ErrorAPI2206",
"ErrorAPI2207",
"ErrorAPI2208",
"ErrorAPI2209",
"ErrorServerUnresponsive",
"ErrorUserNotAuthenticated",
"ErrorUserNotAuthorized",
"DeletePrompt",
"AreYouSureUnsavedChanges",
"Leave",
"Copy",
"Tags",
"Customize",
"ObjectCustomFieldCustomGrid",
"RowsPerPage",
"PageOfPageText",
"Loading",
"AM",
"PM"
],
////////////////////////////////////////////////////////
// Take in a string that contains one or more
//locale keys between square brackets
//translate each and return the string translated
//
translateString(s) {
var ret = s;
var pattern = /\[(.*?)\]/g;
var match;
while ((match = pattern.exec(s)) != null) {
var foundMatch = match[0];
var ltKey = match[1];
var newValue = this.get(ltKey);
ret = ret.replace(foundMatch, newValue);
}
return ret;
},
////////////////////////////////////////////////////////
// attempt to determine user's preferred language settings
// As of Jan 2020 all major browsers support
// navigator.languages
// but some use navigator.language (singular) to denote UI language preference
// not browsing language preference
// so the ideal way to do this is to use navigator.languages[0] for the preferred language
// and ignore the singular property since we don't care about the actual browser UI language
// only how the user expects to see the page itself
//
// also for sake of future proofing and edge cases need to have it be manually settable as well
// ############### TODO: modify all of these to put the user's manual override first in line (if there is one)
//https://appmakers.dev/bcp-47-language-codes-list/
getBrowserLanguages() {
return window.navigator.languages;
},
getBrowserFirstLanguage() {
return window.navigator.languages[0];
},
///////////////////////////////////////////
// Get users default time zone
//https://www.iana.org/time-zones
//https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
getTimeZoneName() {
return Intl.DateTimeFormat().resolvedOptions().timeZone;
},
//////////////////////////////////////////////////
// Get the user's chosen currency name
//https://en.wikipedia.org/wiki/ISO_4217
getCurrencyName() {
return window.$gz.store.state.locale.currencyName;
},
//////////////////////////////////////////////////
// Get the user's chosen 12hr clock
//
getHour12() {
return window.$gz.store.state.locale.hour12;
},
///////////////////////////////////////////
// Turn a utc date into a displayable
// short date and time
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
//
utcDateToShortDateAndTimeLocalized(
value,
timeZoneName,
languageName,
hour12
) {
if (!value) {
return "";
}
if (!timeZoneName) {
timeZoneName = this.getTimeZoneName();
}
if (!languageName) {
languageName = this.getBrowserLanguages();
}
if (!hour12) {
hour12 = this.getHour12();
}
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
var parsedDate = new Date(value);
//is it a valid date?
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
return "not valid";
}
return parsedDate.toLocaleString(languageName, {
timeZone: timeZoneName,
dateStyle: "short",
timeStyle: "short",
hour12: hour12
});
}, ///////////////////////////////////////////
// Turn a utc date into a displayable
// short date
//
utcDateToShortDateLocalized(value, timeZoneName, languageName) {
if (!value) {
return "";
}
if (!timeZoneName) {
timeZoneName = this.getTimeZoneName();
}
if (!languageName) {
languageName = this.getBrowserLanguages();
}
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
var parsedDate = new Date(value);
//is it a valid date?
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
return "not valid";
}
return parsedDate.toLocaleDateString(languageName, {
timeZone: timeZoneName,
dateStyle: "short"
});
}, ///////////////////////////////////////////
// Turn a utc date into a displayable
// short time
//
utcDateToShortTimeLocalized(value, timeZoneName, languageName, hour12) {
if (!value) {
return "";
}
if (!timeZoneName) {
timeZoneName = this.getTimeZoneName();
}
if (!languageName) {
languageName = this.getBrowserLanguages();
}
if (!hour12) {
hour12 = this.getHour12();
}
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
var parsedDate = new Date(value);
//is it a valid date?
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
return "not valid";
}
return parsedDate.toLocaleTimeString(languageName, {
timeZone: timeZoneName,
timeStyle: "short",
hour12: hour12
});
},
///////////////////////////////////////////////
// Convert a utc date to local time zone
// and return time portion only in iso 8601
// format (used by time and date picker components)
//
utcDateStringToLocal8601TimeOnlyString(value, timeZoneName) {
if (!value) {
//if no value, return the current time as expected by the time picker
} else {
//ok, the reason for sv-SE is that it's a locale that returns the time already in ISO format and 24hr by default
//that can change over time so if this breaks that's why
//also fr-CA does as well as possibly en-CA
//https://stackoverflow.com/a/58633686/8939
if (!timeZoneName) {
timeZoneName = this.getTimeZoneName();
}
return new Date(value).toLocaleTimeString("sv-SE", {
timeZone: timeZoneName
});
}
},
///////////////////////////////////////////////
// Convert a local time only string with date string
// to UTC and output as ISO 8601
// (used by time and date picker components)
//
localTimeDateStringToUTC8601String(value, timeZoneName) {
//https://moment.github.io/luxon/docs/manual/zones.html#creating-datetimes-in-a-zone
if (!timeZoneName) {
timeZoneName = this.getTimeZoneName();
}
//parse in the time in the currently used timezone
return window.$gz.DateTime.fromISO(value, {
zone: this.timeZoneName
})
.setZone("utc") //convert to UTC
.toISO(); //output as ISO 8601
},
///////////////////////////////////////////////
// Convert a utc date to local time zone
// and return date only portion only in iso 8601
// format (used by time and date picker components)
//
utcDateStringToLocal8601DateOnlyString(value, timeZoneName) {
if (!value) {
//if no value, return the current time as expected by the time picker
} else {
//ok, the reason for sv-SE is that it's a locale that returns the time already in ISO format and 24hr by default
//that can change over time so if this breaks that's why
//also fr-CA does as well as possibly en-CA
//https://stackoverflow.com/a/58633686/8939
if (!timeZoneName) {
timeZoneName = this.getTimeZoneName();
}
return new Date(value).toLocaleDateString("sv-SE", {
timeZone: timeZoneName
});
}
},
///////////////////////////////////////////
// Turn a decimal number into a local
// currency display
//
currencyLocalized(value, languageName, currencyName) {
if (!value) return "";
if (!languageName) {
languageName = this.getBrowserLanguages();
}
if (!currencyName) {
currencyName = this.getCurrencyName();
}
return new Intl.NumberFormat(languageName, {
style: "currency",
currency: currencyName
}).format(value);
},
///////////////////////////////////////////
// Turn a decimal number into a local
// decimal format display
//
decimalLocalized(value, languageName) {
if (!value) return "";
if (!languageName) {
languageName = this.getBrowserLanguages();
}
return new Intl.NumberFormat(languageName, {
minimumFractionDigits: 2
}).format(value);
},
////////////////////////////////////////////////////////
// dynamically set the vuetify language elements from
// users localized text (am/pm etc)
// Keeping vuetify using en locale and just adjusting on top of that
//
setVuetifyDefaultLanguageElements(vm) {
vm.$vuetify.lang.locales.en.close = this.get("OK");
vm.$vuetify.lang.locales.en.timePicker.am = this.get("AM");
vm.$vuetify.lang.locales.en.timePicker.pm = this.get("PM");
}
};

View File

@@ -520,6 +520,22 @@ function buildRecords(listData, columndefinitions, filters) {
break;
case 10: //enum
//TODO: Need enum translator
//AuthorizationRoles.128
//window.$gz.local.enumLocalized(enumType, enumValue)
//(in locale) check if have that type already featched, if not fetches the whole list and caches it locally
//also a method to return the list of enumerated types in ID order with localized names
//window.$gz.local.enumList(enumType) - returns a list usable on edit forms
/* enums: {
AuthorizationRoles0:"No role",
AuthorizationRoles1:"Business admin limited"
etc
to get all authorization roles iterate list looking for start of key that is AuthorizationRoles
To get individual one same but only need to fetch actual value i.e. AuthorizationRoles1
if not one item starts with AuthorizationRoles then list needs to be fetched, maybe can use the enumpicklist route for that
This way entirely bypasses locale stuff
//big object so maybe it's own thing, not part of locale at all or locale fronts for it??
*/
display = columndefinitions[iColumn].et + "." + display;
break;
default:
@@ -575,4 +591,23 @@ async function fetchLocalizedHeaderNames(columnData) {
window.$gz.errorHandler.handleFormError(err);
});
}
//CURRENTLY THINKING NOT TO CACHE THIS AS
//users might only ever view the list and
//often it might not contain the whole range of options
//so would be unnecessary fetching
// `//////////////////////
// //
// //
// function preFetchEnumListNames(vm, enumListTypes) {
// //enumlisttypes is an array of enum lists to fetch names for
// return window.$gz.api
// .get("EnumPickList/list/authorizationroles")
// .then(res => {
// if (res.error) {
// throw res.error;
// }
// vm.pickLists.roles = res.data;
// });
// }`
</script>

View File

@@ -20,6 +20,7 @@ export default new Vuex.Store({
userType: 0,
homePage: undefined,
localeText: {},
enums: {}, //all enum values with localized text to match stored as key e.g. enums:{AuthorizationRoles:[{0:"no role"},{1:"Limited role"}],UserTypes:[{0:"Technician"},{1:"Client user"}]}
locale: {
languageOverride: "en-US",
timeZoneOverride: "America/New_York",
@@ -52,6 +53,7 @@ export default new Vuex.Store({
state.homePage = undefined;
state.navItems = [];
state.localeText = {};
state.enums = {};
state.formCustomTemplate = {};
state.apiUrl = "";
state.locale.languageOverride = "en-US";
@@ -77,6 +79,9 @@ export default new Vuex.Store({
state.locale.hour12 = data.hour12;
state.locale.timeZoneOverride = data.timeZoneOverride;
},
setEnum(state, data) {
state.enums[data.enumKey] = data.items; //{enumKey:"AuthorizationRoles",items:[{0:"no role"},{1:"Limited role"}]}
},
setAPIURL(state, data) {
state.apiUrl = data;
},