This commit is contained in:
2020-11-18 14:51:50 +00:00
parent 67c57291a4
commit 9d3c1c0b0d
6 changed files with 1158 additions and 449 deletions

View File

@@ -68,11 +68,22 @@ todo: TESTING After customer form is made
Test setting coords from phone
OUTSTANDING WITH CUSTOMER
contacts
USER object needs the full contact fields added first
Phone1, Phone2, Phone3 (formerly pager address)
shows all contact info directly in grid
Contact user should default to customer limited role by default
PW / Login generator automatically and sends creds
need code that generates easily enterable urls
if pw starts with "TEMP" or some key token then maybe they need to go to the change password automatically upon login
this way can issue a pw and email it and when user first logs in they must set it to something?
New user useroptions should default to the server default translation automatically
New User should always have useroptions automatically created with sensible defaults
useroptions should not need a POST route at all, only a PUT to update
What happens if new user created, nothing set for langauge etc and then just login??
Centralize MAP URLS
contacts
Maybe convert generic customer contacts list to proper data grid source from server
shows all contact info directly in grid
Change cust-user edit form (and other user edit form) and add tabs and user options section so that it can all be set there as well
Add button to email the user their creds and login and invite them to change the password once they login
Customer User (contacts) UI for this client (generate, view)

View File

@@ -2,231 +2,405 @@
<v-container fluid>
<gz-report-selector ref="reportSelector"></gz-report-selector>
<h2 class="red--text" v-if="$ay.dev">
todo: revisit after add vendor to support usertype contractor TEST SAVE
when have vendor and make sure wont' allow without vendor chosen and make
sure if not error is clear
todo: revisit after add vendor to support usertype contractor
</h2>
<v-row v-if="formState.ready">
<v-col>
<v-form ref="form">
<v-row>
<gz-error :errorBoxMessage="formState.errorBoxMessage"></gz-error>
{{ formState }}
<div v-if="formState.ready">
<gz-error :errorBoxMessage="formState.errorBoxMessage"></gz-error>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="obj.name"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Name')"
:rules="[form().required(this, 'name')]"
:error-messages="form().serverErrors(this, 'name')"
ref="name"
data-cy="name"
@input="fieldValueChanged('name')"
></v-text-field>
</v-col>
<v-form ref="form">
<v-tabs mobile-breakpoint="100" v-model="tab">
<v-tab>{{ $ay.t("User") }}</v-tab>
<v-tab v-if="obj.id != 0">{{ $ay.t("UserSettings") }}</v-tab>
<v-col
v-if="form().showMe(this, 'subVendorId') && obj.userType == 5"
cols="12"
sm="6"
lg="4"
xl="3"
>
<gz-pick-list
:ayaType="ayaTypes().Vendor"
:showEditIcon="true"
v-model="obj.subVendorId"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Vendor')"
ref="subVendorId"
data-cy="subVendorId"
:error-messages="form().serverErrors(this, 'subVendorId')"
@input="fieldValueChanged('subVendorId')"
></gz-pick-list>
</v-col>
<v-tabs-items v-model="tab">
<v-tab-item class="mt-4">
<v-row>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="obj.name"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Name')"
:rules="[form().required(this, 'name')]"
:error-messages="form().serverErrors(this, 'name')"
ref="name"
data-cy="name"
@input="fieldValueChanged('name')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="obj.employeeNumber"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserEmployeeNumber')"
:error-messages="form().serverErrors(this, 'employeeNumber')"
ref="employeeNumber"
data-cy="employeeNumber"
@input="fieldValueChanged('employeeNumber')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'subVendorId') && obj.userType == 5"
cols="12"
sm="6"
lg="4"
xl="3"
>
<gz-pick-list
:ayaType="ayaTypes().Vendor"
:showEditIcon="true"
v-model="obj.subVendorId"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Vendor')"
ref="subVendorId"
data-cy="subVendorId"
:error-messages="form().serverErrors(this, 'subVendorId')"
@input="fieldValueChanged('subVendorId')"
></gz-pick-list>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-role-picker
:label="$ay.t('AuthorizationRoles')"
v-model="obj.roles"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="roles"
testId="roles"
:error-messages="form().serverErrors(this, 'roles')"
@input="fieldValueChanged('roles')"
limitSelectionTo="inside"
></gz-role-picker>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="obj.employeeNumber"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserEmployeeNumber')"
:error-messages="
form().serverErrors(this, 'employeeNumber')
"
ref="employeeNumber"
data-cy="employeeNumber"
@input="fieldValueChanged('employeeNumber')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Active')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-checkbox
v-model="obj.active"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Active')"
ref="active"
data-cy="active"
:error-messages="form().serverErrors(this, 'active')"
@change="fieldValueChanged('active')"
></v-checkbox>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-role-picker
:label="$ay.t('AuthorizationRoles')"
v-model="obj.roles"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="roles"
testId="roles"
:error-messages="form().serverErrors(this, 'roles')"
@input="fieldValueChanged('roles')"
limitSelectionTo="inside"
></gz-role-picker>
</v-col>
<v-col
v-if="form().showMe(this, 'UserType')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-select
v-model="obj.userType"
:items="selectLists.usertypes"
item-text="name"
item-value="id"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserType')"
ref="usertype"
data-cy="usertype"
:rules="[form().integerValid(this, 'usertype')]"
:error-messages="form().serverErrors(this, 'usertype')"
@input="fieldValueChanged('usertype')"
></v-select>
</v-col>
<v-col
v-if="form().showMe(this, 'Active')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-checkbox
v-model="obj.active"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Active')"
ref="active"
data-cy="active"
:error-messages="form().serverErrors(this, 'active')"
@change="fieldValueChanged('active')"
></v-checkbox>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="username"
id="username"
v-model="login"
:readonly="formState.readOnly"
prepend-icon="$ayiUser"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
:label="$ay.t('NewLogin')"
:error-messages="form().serverErrors(this, 'login')"
ref="login"
@input="fieldValueChanged('login')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'UserType')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-select
v-model="obj.userType"
:items="selectLists.usertypes"
item-text="name"
item-value="id"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserType')"
ref="usertype"
data-cy="usertype"
:rules="[form().integerValid(this, 'usertype')]"
:error-messages="form().serverErrors(this, 'usertype')"
@input="fieldValueChanged('usertype')"
></v-select>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="password"
id="password"
v-model="password"
:readonly="formState.readOnly"
:append-outer-icon="reveal ? '$ayiEye' : '$ayiEyeSlash'"
prepend-icon="$ayiKey"
:label="$ay.t('NewPassword')"
:type="reveal ? 'text' : 'password'"
:error-messages="form().serverErrors(this, 'password')"
ref="password"
@input="fieldValueChanged('password')"
@click:append-outer="reveal = !reveal"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-date-time-picker
:label="$ay.t('LastLogin')"
v-model="obj.lastLogin"
readonly
disabled
ref="lastLogin"
testId="lastLogin"
></gz-date-time-picker>
</v-col>
<v-col v-if="form().showMe(this, 'Notes')" cols="12">
<v-textarea
v-model="obj.notes"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserNotes')"
:error-messages="form().serverErrors(this, 'notes')"
ref="notes"
data-cy="notes"
@input="fieldValueChanged('notes')"
auto-grow
></v-textarea>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="username"
id="username"
v-model="login"
:readonly="formState.readOnly"
prepend-icon="$ayiUser"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
:label="$ay.t('NewLogin')"
:error-messages="form().serverErrors(this, 'login')"
ref="login"
@input="fieldValueChanged('login')"
></v-text-field>
</v-col>
<v-col v-if="form().showMe(this, 'Tags')" cols="12">
<gz-tag-picker
v-model="obj.tags"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="tags"
data-cy="tags"
:error-messages="form().serverErrors(this, 'tags')"
@input="fieldValueChanged('tags')"
></gz-tag-picker>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="password"
id="password"
v-model="password"
:readonly="formState.readOnly"
:append-outer-icon="reveal ? '$ayiEye' : '$ayiEyeSlash'"
prepend-icon="$ayiKey"
:label="$ay.t('NewPassword')"
:type="reveal ? 'text' : 'password'"
:error-messages="form().serverErrors(this, 'password')"
ref="password"
@input="fieldValueChanged('password')"
@click:append-outer="reveal = !reveal"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-date-time-picker
:label="$ay.t('LastLogin')"
v-model="obj.lastLogin"
readonly
disabled
ref="lastLogin"
testId="lastLogin"
></gz-date-time-picker>
</v-col>
<v-col v-if="form().showMe(this, 'Notes')" cols="12">
<v-textarea
v-model="obj.notes"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserNotes')"
:error-messages="form().serverErrors(this, 'notes')"
ref="notes"
data-cy="notes"
@input="fieldValueChanged('notes')"
auto-grow
></v-textarea>
</v-col>
<v-col cols="12">
<gz-custom-fields
v-model="obj.customFields"
:formKey="formCustomTemplateKey"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:parentVM="this"
ref="customFields"
data-cy="customFields"
:error-messages="form().serverErrors(this, 'customFields')"
@input="fieldValueChanged('customFields')"
></gz-custom-fields>
</v-col>
<v-col v-if="form().showMe(this, 'Tags')" cols="12">
<gz-tag-picker
v-model="obj.tags"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="tags"
data-cy="tags"
:error-messages="form().serverErrors(this, 'tags')"
@input="fieldValueChanged('tags')"
></gz-tag-picker>
</v-col>
<v-col v-if="form().showMe(this, 'Wiki')" cols="12">
<gz-wiki
:ayaType="ayaType"
:ayaId="obj.id"
ref="wiki"
v-model="obj.wiki"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
@input="fieldValueChanged('wiki')"
></gz-wiki
></v-col>
<v-col cols="12">
<gz-custom-fields
v-model="obj.customFields"
:formKey="formCustomTemplateKey"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:parentVM="this"
ref="customFields"
data-cy="customFields"
:error-messages="form().serverErrors(this, 'customFields')"
@input="fieldValueChanged('customFields')"
></gz-custom-fields>
</v-col>
<v-col
v-if="form().showMe(this, 'Attachments') && obj.id"
cols="12"
>
<gz-attachments
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:ayaType="ayaType"
:ayaId="obj.id"
></gz-attachments
></v-col>
</v-row>
</v-form>
</v-col>
</v-row>
<v-col v-if="form().showMe(this, 'Wiki')" cols="12">
<gz-wiki
:ayaType="ayaType"
:ayaId="obj.id"
ref="wiki"
v-model="obj.wiki"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
@input="fieldValueChanged('wiki')"
></gz-wiki
></v-col>
<v-col
v-if="form().showMe(this, 'Attachments') && obj.id"
cols="12"
>
<gz-attachments
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:ayaType="ayaType"
:ayaId="obj.id"
></gz-attachments
></v-col>
</v-row>
</v-tab-item>
<v-tab-item v-if="obj.id != 0" class="mt-4">
<v-row>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-select
v-model="optionsObj.translationId"
:items="selectLists.translations"
item-text="name"
item-value="id"
:readonly="formState.readOnly"
:label="$ay.t('Translation')"
ref="translationId"
:error-messages="form().serverErrors(this, 'translationId')"
@input="fieldValueChanged('translationId')"
></v-select>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.emailAddress"
:readonly="formState.readOnly"
:label="$ay.t('UserEmailAddress')"
:error-messages="form().serverErrors(this, 'emailAddress')"
ref="emailAddress"
@input="fieldValueChanged('emailAddress')"
data-cy="emailAddress"
type="email"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Phone1')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-text-field
v-model="optionsObj.phone1"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserPhone1')"
ref="phone1"
data-cy="phone1"
type="tel"
:error-messages="form().serverErrors(this, 'phone1')"
@input="fieldValueChanged('phone1')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Phone2')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-text-field
v-model="optionsObj.phone2"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserPhone2')"
ref="phone2"
data-cy="phone2"
type="tel"
:error-messages="form().serverErrors(this, 'phone2')"
@input="fieldValueChanged('phone2')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Phone3')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-text-field
v-model="optionsObj.phone3"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserPageAddress')"
ref="phone3"
data-cy="phone3"
type="tel"
:error-messages="form().serverErrors(this, 'phone3')"
@input="fieldValueChanged('phone3')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.mapUrlTemplate"
:readonly="formState.readOnly"
:label="$ay.t('MapUrlTemplate')"
:error-messages="
form().serverErrors(this, 'mapUrlTemplate')
"
ref="mapUrlTemplate"
@input="fieldValueChanged('mapUrlTemplate')"
data-cy="mapUrlTemplate"
></v-text-field>
<v-select
:items="selectLists.mapUrls"
item-text="name"
item-value="value"
@input="mapUrlSelectionChanged"
></v-select>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.currencyName"
hint="e.g. USD, EUR, GBP, AUD, CAD etc"
:readonly="formState.readOnly"
:label="$ay.t('CurrencyCode')"
:rules="[form().required(this, 'currencyName')]"
:error-messages="form().serverErrors(this, 'currencyName')"
ref="currencyName"
@input="fieldValueChanged('currencyName')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.languageOverride"
:placeholder="locale().getBrowserFirstLanguage()"
:readonly="formState.readOnly"
:label="$ay.t('LanguageCode')"
:error-messages="
form().serverErrors(this, 'languageOverride')
"
ref="languageOverride"
@input="fieldValueChanged('languageOverride')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.timeZoneOverride"
:placeholder="locale().getBrowserTimeZoneName()"
:readonly="formState.readOnly"
:label="$ay.t('TimeZone')"
:error-messages="
form().serverErrors(this, 'timeZoneOverride')
"
ref="timeZoneOverride"
@input="fieldValueChanged('timeZoneOverride')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<!-- https://vuetifyjs.com/en/components/color-pickers -->
<span class="v-label v-label--active theme--light">
{{ $ay.t("UserColor") }}
</span>
<v-color-picker
v-model="optionsObj.uiColor"
:readonly="formState.readOnly"
hide-mode-switch
mode="hexa"
:error-messages="form().serverErrors(this, 'uiColor')"
ref="uiColor"
@input="fieldValueChanged('uiColor')"
></v-color-picker>
</v-col>
</v-row>
</v-tab-item>
</v-tabs-items>
</v-tabs>
</v-form>
</div>
<template v-if="!formState.ready">
<v-progress-circular
indeterminate
@@ -303,7 +477,49 @@ export default {
return {
formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY,
selectLists: {
usertypes: []
usertypes: [],
translations: [],
mapUrls: [
{
name: "Apple",
value:
"http://maps.apple.com/?q={ayaddress}<|>http://maps.apple.com/?ll={aylatitude},{aylongitude}"
},
{
name: "Bing",
value:
"https://bing.com/maps/default.aspx?where1={ayaddress}<|>https://bing.com/maps/default.aspx?cp={aylatitude}~{aylongitude}&lvl=17&style=r&sp=point.{aylatitude}_{aylongitude}"
},
{
name: "Google",
value:
"https://www.google.com/maps/search/?api=1&query={ayaddress}<|>https://www.google.com/maps/search/?api=1&query={aylatitude},{aylongitude}"
},
{
name: "MapQuest",
value:
"https://mapquest.com/?center={ayaddress}&zoom=17<|>https://mapquest.com/?center={aylatitude},{aylongitude}&zoom=17"
},
{
name: "Open Street Map",
value:
"https://www.openstreetmap.org/search?query={ayaddress}<|>https://www.openstreetmap.org/?mlat={aylatitude}&mlon={aylongitude}#map=17/{aylatitude}/{aylongitude}"
},
{
name: "geo URI",
value: "geo:{aylatitude},{aylongitude}"
},
{
name: "Waze",
value:
"https://waze.com/ul?q={ayaddress}<|>https://www.waze.com/ul?ll={aylatitude},{aylongitude}&navigate=yes&zoom=17"
},
{
name: "Yandex",
value:
"https://yandex.ru/maps/?mode=search&text={ayaddress}&z=17<|>https://yandex.ru/maps/?ll={aylatitude},{aylongitude}&z=12&l=map"
}
]
},
obj: {
id: 0,
@@ -322,9 +538,36 @@ export default {
tags: [],
lastLogin: null
},
optionsObj: {
/*concurrency": 7490431,
"translationId": 1,
"emailAddress": null,
"uiColor": "#000000",
"languageOverride": null,
"timeZoneOverride": null,
"currencyName": "USD",
"hour12": true,
"userId": 1 */
id: 0,
concurrency: 0,
emailAddress: null,
phone1: null,
phone2: null,
phone3: null,
mapUrlTemplate: null,
uiColor: null,
languageOverride: null,
timeZoneOverride: null,
currencyName: null,
hour12: null,
translationId: null
},
login: null,
password: null,
reveal: true,
tab: 0,
formState: {
ready: false,
dirty: false,
@@ -383,6 +626,16 @@ export default {
ayaTypes: function() {
return window.$gz.type;
},
translation() {
return window.$gz.translation;
},
locale() {
return window.$gz.locale;
},
mapUrlSelectionChanged(val) {
this.optionsObj.mapUrlTemplate = val;
this.fieldValueChanged("mapUrlTemplate");
},
form() {
return window.$gz.form;
},
@@ -392,6 +645,7 @@ export default {
!this.formState.loading &&
!this.formState.readOnly
) {
console.log("FieldValueChanged for ", ref);
window.$gz.form.fieldValueChanged(this, ref);
}
},
@@ -427,6 +681,8 @@ export default {
valid: true,
loading: false
});
await vm.getUserOptionsDataFromApi();
}
} catch (error) {
window.$gz.errorHandler.handleFormError(error, vm);
@@ -479,6 +735,7 @@ export default {
//PUT - only concurrency token is returned (**warning, if server changes object other fields then this needs to act more like POST above but is more efficient this way**)
//Handle "put" of an existing record (UPDATE)
vm.obj.concurrency = res.data.concurrency;
await vm.submitOptions();
}
//Update the form status
@@ -561,6 +818,77 @@ export default {
} finally {
vm.formState.loading = false;
}
},
async getUserOptionsDataFromApi() {
let vm = this;
vm.formState.loading = true;
let url = `user-option/${vm.obj.id}`;
window.$gz.form.deleteAllErrorBoxErrors(vm);
try {
let res = await window.$gz.api.get(url);
if (res.error) {
//Not found?
if (res.error.code == "2010") {
window.$gz.form.handleObjectNotFound(vm);
}
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
vm.optionsObj = res.data;
// vm.activeTranslationId = res.data.translationId;
//Update the form status
window.$gz.form.setFormState({
vm: vm,
dirty: false,
valid: true,
loading: false
});
//modify the menu as necessary
generateMenu(vm);
}
} catch (error) {
//Update the form status
window.$gz.form.setFormState({
vm: vm,
loading: false
});
window.$gz.errorHandler.handleFormError(error, vm);
}
},
async submitOptions() {
let vm = this;
if (vm.canSave) {
vm.formState.loading = true;
let url = `user-option/${vm.obj.id}`;
//clear any errors vm might be around from previous submit
window.$gz.form.deleteAllErrorBoxErrors(vm);
try {
let res = await window.$gz.api.upsert(url, vm.optionsObj);
vm.formState.loading = false;
if (res.error) {
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
//UserOptions is never a POST as it always exists and can't be deleted so always a PUT
//Handle "put" of an existing record (UPDATE)
vm.optionsObj.concurrency = res.data.concurrency;
window.$gz.form.setFormState({
vm: vm,
dirty: false
});
}
} catch (error) {
vm.formState.loading = false;
window.$gz.errorHandler.handleFormError(error, vm);
}
}
}
}
};
@@ -778,5 +1106,16 @@ async function populateSelectionLists(vm) {
vm.selectLists.usertypes = window.$gz.enums.getSelectionList(
"insideusertype"
);
//------------
//http://localhost:7575/api/v8/translation/list
let res = await window.$gz.api.get("translation/list");
if (res.error) {
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
//window.$gz.errorHandler.handleFormError(res.error, vm);
} else {
vm.selectLists.translations = res.data;
}
}
</script>

View File

@@ -641,7 +641,7 @@
hide-default-footer
@click:row="contactsRowClick"
:sort-by="['name']"
show-select
:show-select="false"
:header-props="{ sortByText: $ay.t('Sort') }"
data-cy="custUsersTable"
>
@@ -653,7 +653,7 @@
</template>
<template v-slot:top>
<div>
<div class="text-right mb-6">
<v-btn
@click="contactsGetDataFromApi"
:disabled="obj.id == 0"
@@ -1129,15 +1129,17 @@ export default {
ret.push({
id: o.id,
name: o.name,
emailAddress: o.emailAddress,
phone1: o.phone1,
phone2: o.phone2,
phone3: o.phone3,
active: o.active,
userType: window.$gz.enums.get("outsideusertype", o.userType),
lastLogin: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
o.lastLogin,
this.timeZoneName,
this.languageName,
this.hour12
),
roles: this.rolesDisplayFromRoles(o.roles)
)
});
}
@@ -1432,6 +1434,10 @@ async function fetchTranslatedText(vm) {
async function createTableHeaders(vm) {
vm.headers = [
{ text: vm.$ay.t("User"), value: "name" },
{ text: vm.$ay.t("UserEmailAddress"), value: "emailAddress" },
{ text: vm.$ay.t("UserPhone1"), value: "phone1" },
{ text: vm.$ay.t("UserPhone2"), value: "phone2" },
{ text: vm.$ay.t("UserPageAddress"), value: "phone3" },
{ text: vm.$ay.t("Active"), value: "active" },
{ text: vm.$ay.t("LastLogin"), value: "lastLogin" }
];

View File

@@ -2,214 +2,389 @@
<v-container fluid>
<gz-report-selector ref="reportSelector"></gz-report-selector>
<v-row v-if="formState.ready">
<v-col>
<v-form ref="form">
<v-row>
<gz-error :errorBoxMessage="formState.errorBoxMessage"></gz-error>
<div v-if="formState.ready">
<gz-error :errorBoxMessage="formState.errorBoxMessage"></gz-error>
<v-col
v-if="form().showMe(this, 'customerId') && obj.userType == 3"
cols="12"
sm="6"
lg="4"
xl="3"
>
<gz-pick-list
:ayaType="ayaTypes().Customer"
:showEditIcon="true"
:includeInactive="true"
v-model="obj.customerId"
:readonly="true"
:disabled="true"
:label="$ay.t('Customer')"
ref="customerId"
data-cy="customerId"
:error-messages="form().serverErrors(this, 'customerId')"
@input="fieldValueChanged('customerId')"
></gz-pick-list>
</v-col>
<v-form ref="form">
<v-tabs mobile-breakpoint="100" v-model="tab">
<v-tab>{{ $ay.t("User") }}</v-tab>
<v-tab v-if="obj.id != 0">{{ $ay.t("UserSettings") }}</v-tab>
<v-col
v-if="form().showMe(this, 'headOfficeId') && obj.userType == 4"
cols="12"
sm="6"
lg="4"
xl="3"
>
<gz-pick-list
:ayaType="ayaTypes().HeadOffice"
:showEditIcon="true"
:includeInactive="true"
v-model="obj.headOfficeId"
:readonly="true"
:disabled="true"
:label="$ay.t('HeadOffice')"
ref="headOfficeId"
data-cy="headOfficeId"
:error-messages="form().serverErrors(this, 'headOfficeId')"
@input="fieldValueChanged('headOfficeId')"
></gz-pick-list>
</v-col>
<v-tabs-items v-model="tab">
<v-tab-item class="mt-4">
<v-row>
<v-col
v-if="form().showMe(this, 'customerId') && obj.userType == 3"
cols="12"
sm="6"
lg="4"
xl="3"
>
<gz-pick-list
:ayaType="ayaTypes().Customer"
:showEditIcon="true"
:includeInactive="true"
v-model="obj.customerId"
:readonly="true"
:disabled="true"
:label="$ay.t('Customer')"
ref="customerId"
data-cy="customerId"
:error-messages="form().serverErrors(this, 'customerId')"
@input="fieldValueChanged('customerId')"
></gz-pick-list>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="obj.name"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Name')"
:rules="[form().required(this, 'name')]"
:error-messages="form().serverErrors(this, 'name')"
ref="name"
data-cy="name"
@input="fieldValueChanged('name')"
></v-text-field>
</v-col>
<v-col
v-if="
form().showMe(this, 'headOfficeId') && obj.userType == 4
"
cols="12"
sm="6"
lg="4"
xl="3"
>
<gz-pick-list
:ayaType="ayaTypes().HeadOffice"
:showEditIcon="true"
:includeInactive="true"
v-model="obj.headOfficeId"
:readonly="true"
:disabled="true"
:label="$ay.t('HeadOffice')"
ref="headOfficeId"
data-cy="headOfficeId"
:error-messages="form().serverErrors(this, 'headOfficeId')"
@input="fieldValueChanged('headOfficeId')"
></gz-pick-list>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-role-picker
:label="$ay.t('AuthorizationRoles')"
v-model="obj.roles"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="roles"
testId="roles"
:error-messages="form().serverErrors(this, 'roles')"
@input="fieldValueChanged('roles')"
limitSelectionTo="outside"
></gz-role-picker>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="obj.name"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Name')"
:rules="[form().required(this, 'name')]"
:error-messages="form().serverErrors(this, 'name')"
ref="name"
data-cy="name"
@input="fieldValueChanged('name')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Active')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-checkbox
v-model="obj.active"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Active')"
ref="active"
data-cy="active"
:error-messages="form().serverErrors(this, 'active')"
@change="fieldValueChanged('active')"
></v-checkbox>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-role-picker
:label="$ay.t('AuthorizationRoles')"
v-model="obj.roles"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="roles"
testId="roles"
:error-messages="form().serverErrors(this, 'roles')"
@input="fieldValueChanged('roles')"
limitSelectionTo="outside"
></gz-role-picker>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="username"
id="username"
v-model="login"
:readonly="formState.readOnly"
prepend-icon="$ayiUser"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
:label="$ay.t('NewLogin')"
:error-messages="form().serverErrors(this, 'login')"
ref="login"
@input="fieldValueChanged('login')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Active')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-checkbox
v-model="obj.active"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Active')"
ref="active"
data-cy="active"
:error-messages="form().serverErrors(this, 'active')"
@change="fieldValueChanged('active')"
></v-checkbox>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="password"
id="password"
v-model="password"
:readonly="formState.readOnly"
:append-outer-icon="reveal ? '$ayiEye' : '$ayiEyeSlash'"
prepend-icon="$ayiKey"
:label="$ay.t('NewPassword')"
:type="reveal ? 'text' : 'password'"
:error-messages="form().serverErrors(this, 'password')"
ref="password"
@input="fieldValueChanged('password')"
@click:append-outer="reveal = !reveal"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-date-time-picker
:label="$ay.t('LastLogin')"
v-model="obj.lastLogin"
readonly
disabled
ref="lastLogin"
testId="lastLogin"
></gz-date-time-picker>
</v-col>
<v-col v-if="form().showMe(this, 'Notes')" cols="12">
<v-textarea
v-model="obj.notes"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserNotes')"
:error-messages="form().serverErrors(this, 'notes')"
ref="notes"
data-cy="notes"
@input="fieldValueChanged('notes')"
auto-grow
></v-textarea>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="username"
id="username"
v-model="login"
:readonly="formState.readOnly"
prepend-icon="$ayiUser"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
:label="$ay.t('NewLogin')"
:error-messages="form().serverErrors(this, 'login')"
ref="login"
@input="fieldValueChanged('login')"
></v-text-field>
</v-col>
<v-col v-if="form().showMe(this, 'Tags')" cols="12">
<gz-tag-picker
v-model="obj.tags"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="tags"
data-cy="tags"
:error-messages="form().serverErrors(this, 'tags')"
@input="fieldValueChanged('tags')"
></gz-tag-picker>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
name="password"
id="password"
v-model="password"
:readonly="formState.readOnly"
:append-outer-icon="reveal ? '$ayiEye' : '$ayiEyeSlash'"
prepend-icon="$ayiKey"
:label="$ay.t('NewPassword')"
:type="reveal ? 'text' : 'password'"
:error-messages="form().serverErrors(this, 'password')"
ref="password"
@input="fieldValueChanged('password')"
@click:append-outer="reveal = !reveal"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-date-time-picker
:label="$ay.t('LastLogin')"
v-model="obj.lastLogin"
readonly
disabled
ref="lastLogin"
testId="lastLogin"
></gz-date-time-picker>
</v-col>
<v-col v-if="form().showMe(this, 'Notes')" cols="12">
<v-textarea
v-model="obj.notes"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserNotes')"
:error-messages="form().serverErrors(this, 'notes')"
ref="notes"
data-cy="notes"
@input="fieldValueChanged('notes')"
auto-grow
></v-textarea>
</v-col>
<v-col cols="12">
<gz-custom-fields
v-model="obj.customFields"
:formKey="formCustomTemplateKey"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:parentVM="this"
ref="customFields"
data-cy="customFields"
:error-messages="form().serverErrors(this, 'customFields')"
@input="fieldValueChanged('customFields')"
></gz-custom-fields>
</v-col>
<v-col v-if="form().showMe(this, 'Tags')" cols="12">
<gz-tag-picker
v-model="obj.tags"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
ref="tags"
data-cy="tags"
:error-messages="form().serverErrors(this, 'tags')"
@input="fieldValueChanged('tags')"
></gz-tag-picker>
</v-col>
<v-col v-if="form().showMe(this, 'Wiki')" cols="12">
<gz-wiki
:ayaType="ayaType"
:ayaId="obj.id"
ref="wiki"
v-model="obj.wiki"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
@input="fieldValueChanged('wiki')"
></gz-wiki
></v-col>
<v-col cols="12">
<gz-custom-fields
v-model="obj.customFields"
:formKey="formCustomTemplateKey"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:parentVM="this"
ref="customFields"
data-cy="customFields"
:error-messages="form().serverErrors(this, 'customFields')"
@input="fieldValueChanged('customFields')"
></gz-custom-fields>
</v-col>
<v-col
v-if="form().showMe(this, 'Attachments') && obj.id"
cols="12"
>
<gz-attachments
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:ayaType="ayaType"
:ayaId="obj.id"
></gz-attachments
></v-col>
</v-row>
</v-form>
</v-col>
</v-row>
<v-col v-if="form().showMe(this, 'Wiki')" cols="12">
<gz-wiki
:ayaType="ayaType"
:ayaId="obj.id"
ref="wiki"
v-model="obj.wiki"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
@input="fieldValueChanged('wiki')"
></gz-wiki
></v-col>
<v-col
v-if="form().showMe(this, 'Attachments') && obj.id"
cols="12"
>
<gz-attachments
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:ayaType="ayaType"
:ayaId="obj.id"
></gz-attachments
></v-col>
</v-row>
</v-tab-item>
<v-tab-item v-if="obj.id != 0" class="mt-4">
<v-row>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-select
v-model="optionsObj.translationId"
:items="selectLists.translations"
item-text="name"
item-value="id"
:readonly="formState.readOnly"
:label="$ay.t('Translation')"
ref="translationId"
:error-messages="form().serverErrors(this, 'translationId')"
@input="fieldValueChanged('translationId')"
></v-select>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.emailAddress"
:readonly="formState.readOnly"
:label="$ay.t('UserEmailAddress')"
:error-messages="form().serverErrors(this, 'emailAddress')"
ref="emailAddress"
@input="fieldValueChanged('emailAddress')"
data-cy="emailAddress"
type="email"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Phone1')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-text-field
v-model="optionsObj.phone1"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserPhone1')"
ref="phone1"
data-cy="phone1"
type="tel"
:error-messages="form().serverErrors(this, 'phone1')"
@input="fieldValueChanged('phone1')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Phone2')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-text-field
v-model="optionsObj.phone2"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserPhone2')"
ref="phone2"
data-cy="phone2"
type="tel"
:error-messages="form().serverErrors(this, 'phone2')"
@input="fieldValueChanged('phone2')"
></v-text-field>
</v-col>
<v-col
v-if="form().showMe(this, 'Phone3')"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-text-field
v-model="optionsObj.phone3"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('UserPageAddress')"
ref="phone3"
data-cy="phone3"
type="tel"
:error-messages="form().serverErrors(this, 'phone3')"
@input="fieldValueChanged('phone3')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.mapUrlTemplate"
:readonly="formState.readOnly"
:label="$ay.t('MapUrlTemplate')"
:error-messages="
form().serverErrors(this, 'mapUrlTemplate')
"
ref="mapUrlTemplate"
@input="fieldValueChanged('mapUrlTemplate')"
data-cy="mapUrlTemplate"
></v-text-field>
<v-select
:items="selectLists.mapUrls"
item-text="name"
item-value="value"
@input="mapUrlSelectionChanged"
></v-select>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.currencyName"
hint="e.g. USD, EUR, GBP, AUD, CAD etc"
:readonly="formState.readOnly"
:label="$ay.t('CurrencyCode')"
:rules="[form().required(this, 'currencyName')]"
:error-messages="form().serverErrors(this, 'currencyName')"
ref="currencyName"
@input="fieldValueChanged('currencyName')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.languageOverride"
:placeholder="locale().getBrowserFirstLanguage()"
:readonly="formState.readOnly"
:label="$ay.t('LanguageCode')"
:error-messages="
form().serverErrors(this, 'languageOverride')
"
ref="languageOverride"
@input="fieldValueChanged('languageOverride')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
v-model="optionsObj.timeZoneOverride"
:placeholder="locale().getBrowserTimeZoneName()"
:readonly="formState.readOnly"
:label="$ay.t('TimeZone')"
:error-messages="
form().serverErrors(this, 'timeZoneOverride')
"
ref="timeZoneOverride"
@input="fieldValueChanged('timeZoneOverride')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<!-- https://vuetifyjs.com/en/components/color-pickers -->
<span class="v-label v-label--active theme--light">
{{ $ay.t("UserColor") }}
</span>
<v-color-picker
v-model="optionsObj.uiColor"
:readonly="formState.readOnly"
hide-mode-switch
mode="hexa"
:error-messages="form().serverErrors(this, 'uiColor')"
ref="uiColor"
@input="fieldValueChanged('uiColor')"
></v-color-picker>
</v-col>
</v-row>
</v-tab-item>
</v-tabs-items>
</v-tabs>
</v-form>
</div>
<template v-if="!formState.ready">
<v-progress-circular
indeterminate
@@ -254,12 +429,23 @@ export default {
} else {
/* Customer = 3,
HeadOffice = 4, */
if (vm.$route.params.customerid != 0) {
if (vm.$route.params.customerid && vm.$route.params.customerid != 0) {
vm.obj.customerId = vm.$route.params.customerid;
vm.obj.userType = 3;
} else if (vm.$route.params.headofficeid != 0) {
} else if (
vm.$route.params.headofficeid &&
vm.$route.params.headofficeid != 0
) {
vm.obj.headOfficeId = vm.$route.params.headofficeid;
vm.obj.userType = 4;
} else {
//no customer or headoffice id, can't proceed
// navigate backwards
vm.$router.go(-1);
//if above turns out to be problematic just go to customers list instead
// vm.$router.push({
// name: "cust-customers"
// });
}
vm.formState.loading = false; //here we handle it immediately
}
@@ -295,7 +481,49 @@ export default {
return {
formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY,
selectLists: {
usertypes: []
usertypes: [],
translations: [],
mapUrls: [
{
name: "Apple",
value:
"http://maps.apple.com/?q={ayaddress}<|>http://maps.apple.com/?ll={aylatitude},{aylongitude}"
},
{
name: "Bing",
value:
"https://bing.com/maps/default.aspx?where1={ayaddress}<|>https://bing.com/maps/default.aspx?cp={aylatitude}~{aylongitude}&lvl=17&style=r&sp=point.{aylatitude}_{aylongitude}"
},
{
name: "Google",
value:
"https://www.google.com/maps/search/?api=1&query={ayaddress}<|>https://www.google.com/maps/search/?api=1&query={aylatitude},{aylongitude}"
},
{
name: "MapQuest",
value:
"https://mapquest.com/?center={ayaddress}&zoom=17<|>https://mapquest.com/?center={aylatitude},{aylongitude}&zoom=17"
},
{
name: "Open Street Map",
value:
"https://www.openstreetmap.org/search?query={ayaddress}<|>https://www.openstreetmap.org/?mlat={aylatitude}&mlon={aylongitude}#map=17/{aylatitude}/{aylongitude}"
},
{
name: "geo URI",
value: "geo:{aylatitude},{aylongitude}"
},
{
name: "Waze",
value:
"https://waze.com/ul?q={ayaddress}<|>https://www.waze.com/ul?ll={aylatitude},{aylongitude}&navigate=yes&zoom=17"
},
{
name: "Yandex",
value:
"https://yandex.ru/maps/?mode=search&text={ayaddress}&z=17<|>https://yandex.ru/maps/?ll={aylatitude},{aylongitude}&z=12&l=map"
}
]
},
obj: {
id: 0,
@@ -314,9 +542,34 @@ export default {
tags: [],
lastLogin: null
},
optionsObj: {
/*concurrency": 7490431,
"translationId": 1,
"emailAddress": null,
"uiColor": "#000000",
"languageOverride": null,
"timeZoneOverride": null,
"currencyName": "USD",
"hour12": true,
"userId": 1 */
id: 0,
concurrency: 0,
emailAddress: null,
phone1: null,
phone2: null,
phone3: null,
mapUrlTemplate: null,
uiColor: null,
languageOverride: null,
timeZoneOverride: null,
currencyName: null,
hour12: null,
translationId: null
},
login: null,
password: null,
reveal: true,
tab: 0,
formState: {
ready: false,
dirty: false,
@@ -375,6 +628,16 @@ export default {
ayaTypes: function() {
return window.$gz.type;
},
translation() {
return window.$gz.translation;
},
locale() {
return window.$gz.locale;
},
mapUrlSelectionChanged(val) {
this.optionsObj.mapUrlTemplate = val;
this.fieldValueChanged("mapUrlTemplate");
},
form() {
return window.$gz.form;
},
@@ -419,6 +682,8 @@ export default {
valid: true,
loading: false
});
await vm.getUserOptionsDataFromApi();
}
} catch (error) {
window.$gz.errorHandler.handleFormError(error, vm);
@@ -457,11 +722,12 @@ export default {
if (res.data.id) {
//POST - whole new object returned
vm.obj = res.data;
//Change URL to new record
//NOTE: will not cause a page re-render, almost nothing does unless forced with a KEY property or using router.GO()
this.$router.push({
name: "adm-user",
name: "cust-user",
params: {
recordid: res.data.id,
obj: res.data //Pass data object to new form
@@ -471,6 +737,7 @@ export default {
//PUT - only concurrency token is returned (**warning, if server changes object other fields then this needs to act more like POST above but is more efficient this way**)
//Handle "put" of an existing record (UPDATE)
vm.obj.concurrency = res.data.concurrency;
await vm.submitOptions();
}
//Update the form status
@@ -553,6 +820,77 @@ export default {
} finally {
vm.formState.loading = false;
}
},
async getUserOptionsDataFromApi() {
let vm = this;
vm.formState.loading = true;
let url = `user-option/${vm.obj.id}`;
window.$gz.form.deleteAllErrorBoxErrors(vm);
try {
let res = await window.$gz.api.get(url);
if (res.error) {
//Not found?
if (res.error.code == "2010") {
window.$gz.form.handleObjectNotFound(vm);
}
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
vm.optionsObj = res.data;
// vm.activeTranslationId = res.data.translationId;
//Update the form status
window.$gz.form.setFormState({
vm: vm,
dirty: false,
valid: true,
loading: false
});
//modify the menu as necessary
generateMenu(vm);
}
} catch (error) {
//Update the form status
window.$gz.form.setFormState({
vm: vm,
loading: false
});
window.$gz.errorHandler.handleFormError(error, vm);
}
},
async submitOptions() {
let vm = this;
if (vm.canSave) {
vm.formState.loading = true;
let url = `user-option/${vm.obj.id}`;
//clear any errors vm might be around from previous submit
window.$gz.form.deleteAllErrorBoxErrors(vm);
try {
let res = await window.$gz.api.upsert(url, vm.optionsObj);
vm.formState.loading = false;
if (res.error) {
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
//UserOptions is never a POST as it always exists and can't be deleted so always a PUT
//Handle "put" of an existing record (UPDATE)
vm.optionsObj.concurrency = res.data.concurrency;
window.$gz.form.setFormState({
vm: vm,
dirty: false
});
}
} catch (error) {
vm.formState.loading = false;
window.$gz.errorHandler.handleFormError(error, vm);
}
}
}
}
};
@@ -723,7 +1061,7 @@ let JUST_DELETED = false;
async function initForm(vm) {
await fetchTranslatedText(vm);
await window.$gz.formCustomTemplate.get(FORM_CUSTOM_TEMPLATE_KEY);
//await populateSelectionLists(vm);
await populateSelectionLists(vm);
}
//////////////////////////////////////////////////////////
@@ -757,18 +1095,33 @@ async function fetchTranslatedText(vm) {
"UserCustom13",
"UserCustom14",
"UserCustom15",
"UserCustom16"
"UserCustom16",
"CurrencyCode",
"LanguageCode",
"TimeZone",
"UserEmailAddress",
"UserColor",
"Translation",
"DarkMode",
"MapUrlTemplate",
"UserPhone1",
"UserPhone2",
"UserPageAddress"
]);
}
// //////////////////////
// //
// //
// async function populateSelectionLists(vm) {
// //ensure the pick lists required are pre-fetched
// await window.$gz.enums.fetchEnumList("outsideusertype");
// vm.selectLists.usertypes = window.$gz.enums.getSelectionList(
// "outsideusertype"
// );
// }
//////////////////////
//
//
async function populateSelectionLists(vm) {
//http://localhost:7575/api/v8/translation/list
let res = await window.$gz.api.get("translation/list");
if (res.error) {
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
//window.$gz.errorHandler.handleFormError(res.error, vm);
} else {
vm.selectLists.translations = res.data;
}
}
</script>

View File

@@ -111,6 +111,10 @@ export default {
ret.push({
id: o.id,
name: o.name,
emailAddress: o.emailAddress,
phone1: o.phone1,
phone2: o.phone2,
phone3: o.phone3,
active: o.active,
userType: window.$gz.enums.get("outsideusertype", o.userType),
lastLogin: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
@@ -262,7 +266,11 @@ async function fetchTranslatedText(vm) {
"User",
"Active",
"UserType",
"LastLogin"
"LastLogin",
"UserEmailAddress",
"UserPhone1",
"UserPhone2",
"UserPageAddress"
]);
}
@@ -282,6 +290,10 @@ async function cacheEnums(vm) {
async function createTableHeaders(vm) {
vm.headers = [
{ text: vm.$ay.t("User"), value: "name" },
{ text: vm.$ay.t("UserEmailAddress"), value: "emailAddress" },
{ text: vm.$ay.t("UserPhone1"), value: "phone1" },
{ text: vm.$ay.t("UserPhone2"), value: "phone2" },
{ text: vm.$ay.t("UserPageAddress"), value: "phone3" },
{ text: vm.$ay.t("Active"), value: "active" },
{ text: vm.$ay.t("UserType"), value: "userType" },
{ text: vm.$ay.t("LastLogin"), value: "lastLogin" }

View File

@@ -120,17 +120,6 @@
@input="fieldValueChanged('currencyName')"
></v-text-field>
</v-col>
<!-- Keeping in case decide to implement non-native time pickers again, but this won't work with native ones
<v-col cols="12" sm="6" lg="4" xl="3">
<v-checkbox
v-model="obj.hour12"
:readonly="formState.readOnly"
:label="$ay.t('Hour12')"
ref="hour12"
:error-messages="form().serverErrors(this, 'hour12')"
@change="fieldValueChanged('hour12')"
></v-checkbox>
</v-col> -->
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
@@ -192,7 +181,7 @@ export default {
try {
await initForm(vm);
vm.rights = window.$gz.role.getRights(window.$gz.type.UserOptions);
vm.rights = window.$gz.role.fullRightsObject(); //getRights(window.$gz.type.UserOptions);
vm.formState.ready = true;
window.$gz.eventBus.$on("menu-click", clickHandler);
//UserOptions never creates a new one so this code is a little different than other forms
@@ -565,7 +554,6 @@ async function fetchTranslatedText(vm) {
"LanguageCode",
"TimeZone",
"UserEmailAddress",
//"Hour12",
"UserColor",
"Translation",
"DarkMode",