This commit is contained in:
2020-11-28 00:24:27 +00:00
parent becb883eec
commit 8d1d881662
6 changed files with 341 additions and 322 deletions

View File

@@ -35,9 +35,27 @@ To REMOVE: apt-get remove dotnet-runtime-3.0 (replace 3.0 with whatever version
MISC ITEMS THAT CAME UP
todo: bugbug datetime control clear buttons don't trigger emit of empty date times
todo: DATE / TIME / DATE_TIME controls switch back to vuetify ones
Ensure can clear completely to null value
Test it out thoroughly there was a reason I quit using it the first time
i18n
smoke test (maybe some way to bypass the control for test purposes)
Is it possible to still keep the native ones in there somehow with a v-if template and a setting?
maybe get the nonnative one working then look into supporting this for edge cases or future proofing
Lots of warnings about using native ones on the MDN site, looks like I should use a component of some kind
so if I do I might as well use the vuetify ones since there are no substantially greater options out there
It would be very nice though if I could opt to have the user be able to choose alternatives like a native input for when
browser makers actually get around to implementing them properly, some have and some are good but some like apple just don't work
bugbug datetime control clear buttons don't trigger emit of empty date times
contractexpires on customer form clearing it and saving sends date to server as if it wasn't cleared at all
Better solution: one clear button that clears all and emits properly and disable the built in if possible
todo: gz-data-table make sure unbounded notes column is bounded by some length restriction
mobile format is ok, it cuts off at one line, but for desktop we should have a sane limit as right now it's completely unbounded
this should apply to any column that displays text but particularly just the plain text ones

View File

@@ -1,91 +1,129 @@
<template>
<v-row>
<template v-if="!readonly">
<v-col cols="6">
<v-text-field
ref="dateField"
:value="splitValue.date"
@change="updateValue()"
:readonly="readonly"
:disabled="disabled"
:label="label"
:rules="rules"
type="date"
:error-messages="allErrors()"
:data-cy="'dateinput:' + testId"
></v-text-field>
<div>
<v-row v-if="!readonly">
<v-col xs6>
<v-dialog
ref="theDateDialog"
v-model="dlgdate"
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-on="on"
prepend-icon="$ayiCalendarAlt"
@click:prepend="dlgdate = true"
v-model="formatDate"
v-bind:label="label"
v-bind:rules="rules"
readonly
:error="!!error"
:data-cy="'dtfpick:' + testId"
></v-text-field>
</template>
<v-date-picker
v-model="dateOnly"
@input="dlgdate = false"
:locale="defaultLocale"
:data-cy="'dpick:' + testId"
>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="dlgdate = false">{{
$ay.t("OK")
}}</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
<v-col cols="6">
<v-text-field
ref="timeField"
:value="splitValue.time"
@change="updateValue()"
:readonly="readonly"
:disabled="disabled"
type="time"
:data-cy="'timeinput:' + testId"
></v-text-field>
<v-col xs6>
<v-dialog
ref="theTimeDialog"
v-model="dlgtime"
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-on="on"
v-model="formatTime"
label
prepend-icon="$ayiClock"
@click:prepend="dlgtime = true"
readonly
:error="!!error"
:data-cy="'ttfpick:' + testId"
></v-text-field>
</template>
<v-time-picker
scrollable
ampm-in-title
:format="hour12 ? 'ampm' : '24hr'"
v-model="timeOnly"
:data-cy="'tpick:' + testId"
>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="dlgtime = false">{{
$ay.t("OK")
}}</v-btn>
</v-time-picker>
</v-dialog>
</v-col>
</template>
<template v-else>
<v-text-field
:value="readonlyFormat()"
:label="label"
readonly
disabled
></v-text-field>
</template>
</v-row>
</v-row>
<v-text-field
v-if="readonly"
v-model="formatDateTime"
v-bind:label="label"
prepend-icon="$ayiCalendarAlt"
disabled
></v-text-field>
<p v-show="error" class="form__error v-messages theme--light error--text">
{{ error }}
</p>
</div>
</template>
<script>
//==========================================
//==========================================
/* Xeslint-disable */
export default {
data() {
return {
timeZoneName: window.$gz.locale.getBrowserTimeZoneName()
};
},
data: () => ({
date: null,
oldDate: null,
dlgdate: false,
dlgtime: false,
//cache display format stuff
timeZoneName: window.$gz.locale.getBrowserTimeZoneName(),
languageName: window.$gz.locale.getBrowserLanguages(),
hour12: window.$gz.locale.getHour12(),
defaultLocale: window.$gz.locale.getBrowserFirstLanguage().split("-", 1)[0]
}),
props: {
label: String,
rules: Array,
"error-messages": { type: Array, default: null },
value: { type: String, default: null },
value: String,
readonly: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
error: {
type: String,
required: false
},
testId: String
},
computed: {
splitValue() {
return {
date: window.$gz.locale.utcDateStringToLocal8601DateOnlyString(
this.value,
this.timeZoneName
),
time: window.$gz.locale.utcDateStringToLocal8601TimeOnlyString(
this.value,
this.timeZoneName
)
};
watch: {
date() {
//this tortuous fuckery is required so that the input and change events only fire on a real change, not initial page load
//also it shouldn't signal a change if the values are the same and nothing was effectively changed
let hasChanged = false;
if (this.date != this.oldDate) {
hasChanged = true;
}
this.oldDate = this.date;
if (hasChanged) {
this.$emit("input", this.date); //always in UTC
}
},
value() {
this.date = this.value; //always in UTC
}
},
methods: {
allErrors() {
let ret = "";
if (this.error != null) {
ret = this.error;
}
if (this.errorMessages != null && this.errorMessages.length > 0) {
ret += this.errorMessages.toString();
}
return ret;
},
readonlyFormat() {
computed: {
formatDateTime() {
return window.$gz.locale.utcDateToShortDateAndTimeLocalized(
this.value,
this.timeZoneName,
@@ -93,33 +131,72 @@ export default {
this.hour12
);
},
updateValue() {
let vm = this;
let dateValue = vm.$refs.dateField.$refs.input.value;
if (!dateValue) {
let v = new Date();
let fullYear = v.getFullYear();
let fullMonth = v.getMonth() + 1;
if (fullMonth < 10) {
fullMonth = "0" + fullMonth.toString();
}
let fullDay = v.getDate();
if (fullDay < 10) {
fullDay = "0" + fullDay.toString();
}
dateValue = fullYear + "-" + fullMonth + "-" + fullDay;
}
let timeValue = vm.$refs.timeField.$refs.input.value;
if (!timeValue) {
timeValue = "00:00:00";
}
let ret = window.$gz.locale.localTimeDateStringToUTC8601String(
dateValue + "T" + timeValue,
vm.timeZoneName
formatDate() {
return window.$gz.locale.utcDateToShortDateLocalized(
this.value,
this.timeZoneName,
this.languageName
);
vm.$emit("input", ret);
},
formatTime() {
return window.$gz.locale.utcDateToShortTimeLocalized(
this.value,
this.timeZoneName,
this.languageName,
this.hour12
);
},
dateOnly: {
get() {
//return date only portion converted to local working time zone: YYYY-MM-DD
return window.$gz.locale.utcDateStringToLocal8601DateOnlyString(
this.value,
this.timeZoneName
);
},
set(value) {
//2017-08-15T12:10:34.4443084+03:00
let TimePortion = this.timeOnly;
if (!TimePortion) {
TimePortion = "00:00:00";
}
this.date = window.$gz.locale.localTimeDateStringToUTC8601String(
value + "T" + TimePortion,
this.timeZoneName
);
}
},
timeOnly: {
//expects just the hours minutes seconds portion: 18:18:49
//Needs to convert into and out of the desired time zone or the control will show the UTC time instead
get() {
return window.$gz.locale.utcDateStringToLocal8601TimeOnlyString(
this.value,
this.timeZoneName
);
},
set(value) {
let DatePortion = this.dateOnly;
if (!DatePortion) {
let v = new Date();
let fullYear = v.getFullYear();
let fullMonth = v.getMonth() + 1;
if (fullMonth < 10) {
fullMonth = "0" + fullMonth.toString();
}
let fullDay = v.getDate();
if (fullDay < 10) {
fullDay = "0" + fullDay.toString();
}
DatePortion = fullYear + "-" + fullMonth + "-" + fullDay;
}
this.date = window.$gz.locale.localTimeDateStringToUTC8601String(
DatePortion + "T" + value,
this.timeZoneName
);
}
}
}
};

View File

@@ -0,0 +1,126 @@
<template>
<v-row>
<template v-if="!readonly">
<v-col cols="6">
<v-text-field
ref="dateField"
:value="splitValue.date"
@change="updateValue()"
:readonly="readonly"
:disabled="disabled"
:label="label"
:rules="rules"
type="date"
:error-messages="allErrors()"
:data-cy="'dateinput:' + testId"
></v-text-field>
</v-col>
<v-col cols="6">
<v-text-field
ref="timeField"
:value="splitValue.time"
@change="updateValue()"
:readonly="readonly"
:disabled="disabled"
type="time"
:data-cy="'timeinput:' + testId"
></v-text-field>
</v-col>
</template>
<template v-else>
<v-text-field
:value="readonlyFormat()"
:label="label"
readonly
disabled
></v-text-field>
</template>
</v-row>
</template>
<script>
//==========================================
//==========================================
export default {
data() {
return {
timeZoneName: window.$gz.locale.getBrowserTimeZoneName()
};
},
props: {
label: String,
rules: Array,
"error-messages": { type: Array, default: null },
value: { type: String, default: null },
readonly: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
error: {
type: String,
required: false
},
testId: String
},
computed: {
splitValue() {
return {
date: window.$gz.locale.utcDateStringToLocal8601DateOnlyString(
this.value,
this.timeZoneName
),
time: window.$gz.locale.utcDateStringToLocal8601TimeOnlyString(
this.value,
this.timeZoneName
)
};
}
},
methods: {
allErrors() {
let ret = "";
if (this.error != null) {
ret = this.error;
}
if (this.errorMessages != null && this.errorMessages.length > 0) {
ret += this.errorMessages.toString();
}
return ret;
},
readonlyFormat() {
return window.$gz.locale.utcDateToShortDateAndTimeLocalized(
this.value,
this.timeZoneName,
this.languageName,
this.hour12
);
},
updateValue() {
let vm = this;
let dateValue = vm.$refs.dateField.$refs.input.value;
if (!dateValue) {
let v = new Date();
let fullYear = v.getFullYear();
let fullMonth = v.getMonth() + 1;
if (fullMonth < 10) {
fullMonth = "0" + fullMonth.toString();
}
let fullDay = v.getDate();
if (fullDay < 10) {
fullDay = "0" + fullDay.toString();
}
dateValue = fullYear + "-" + fullMonth + "-" + fullDay;
}
let timeValue = vm.$refs.timeField.$refs.input.value;
if (!timeValue) {
timeValue = "00:00:00";
}
let ret = window.$gz.locale.localTimeDateStringToUTC8601String(
dateValue + "T" + timeValue,
vm.timeZoneName
);
vm.$emit("input", ret);
}
}
};
</script>

View File

@@ -1,203 +0,0 @@
<template>
<div>
<v-row v-if="!readonly">
<v-col xs6>
<v-dialog
ref="theDateDialog"
v-model="dlgdate"
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-on="on"
prepend-icon="$ayiCalendarAlt"
@click:prepend="dlgdate = true"
v-model="formatDate"
v-bind:label="label"
v-bind:rules="rules"
readonly
:error="!!error"
:data-cy="'dtfpick:' + testId"
></v-text-field>
</template>
<v-date-picker
v-model="dateOnly"
@input="dlgdate = false"
:locale="defaultLocale"
:data-cy="'dpick:' + testId"
>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="dlgdate = false">{{
$ay.t("OK")
}}</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
<v-col xs6>
<v-dialog
ref="theTimeDialog"
v-model="dlgtime"
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-on="on"
v-model="formatTime"
label
prepend-icon="$ayiClock"
@click:prepend="dlgtime = true"
readonly
:error="!!error"
:data-cy="'ttfpick:' + testId"
></v-text-field>
</template>
<v-time-picker
scrollable
ampm-in-title
:format="hour12 ? 'ampm' : '24hr'"
v-model="timeOnly"
:data-cy="'tpick:' + testId"
>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="dlgtime = false">{{
$ay.t("OK")
}}</v-btn>
</v-time-picker>
</v-dialog>
</v-col>
</v-row>
<v-text-field
v-if="readonly"
v-model="formatDateTime"
v-bind:label="label"
prepend-icon="$ayiCalendarAlt"
disabled
></v-text-field>
<p v-show="error" class="form__error v-messages theme--light error--text">
{{ error }}
</p>
</div>
</template>
<script>
/* Xeslint-disable */
export default {
data: () => ({
date: null,
oldDate: null,
dlgdate: false,
dlgtime: false,
//cache display format stuff
timeZoneName: window.$gz.locale.getBrowserTimeZoneName(),
languageName: window.$gz.locale.getBrowserLanguages(),
hour12: window.$gz.locale.getHour12(),
defaultLocale: window.$gz.locale.getBrowserFirstLanguage().split("-", 1)[0]
}),
props: {
label: String,
rules: Array,
value: String,
readonly: { type: Boolean, default: false },
error: {
type: String,
required: false
},
testId: String
},
watch: {
date() {
//this tortuous fuckery is required so that the input and change events only fire on a real change, not initial page load
//also it shouldn't signal a change if the values are the same and nothing was effectively changed
let hasChanged = false;
if (this.date != this.oldDate) {
hasChanged = true;
}
this.oldDate = this.date;
if (hasChanged) {
this.$emit("input", this.date); //always in UTC
}
},
value() {
this.date = this.value; //always in UTC
}
},
computed: {
formatDateTime() {
return window.$gz.locale.utcDateToShortDateAndTimeLocalized(
this.value,
this.timeZoneName,
this.languageName,
this.hour12
);
},
formatDate() {
return window.$gz.locale.utcDateToShortDateLocalized(
this.value,
this.timeZoneName,
this.languageName
);
},
formatTime() {
return window.$gz.locale.utcDateToShortTimeLocalized(
this.value,
this.timeZoneName,
this.languageName,
this.hour12
);
},
dateOnly: {
get() {
//return date only portion converted to local working time zone: YYYY-MM-DD
return window.$gz.locale.utcDateStringToLocal8601DateOnlyString(
this.value,
this.timeZoneName
);
},
set(value) {
//2017-08-15T12:10:34.4443084+03:00
let TimePortion = this.timeOnly;
if (!TimePortion) {
TimePortion = "00:00:00";
}
this.date = window.$gz.locale.localTimeDateStringToUTC8601String(
value + "T" + TimePortion,
this.timeZoneName
);
}
},
timeOnly: {
//expects just the hours minutes seconds portion: 18:18:49
//Needs to convert into and out of the desired time zone or the control will show the UTC time instead
get() {
return window.$gz.locale.utcDateStringToLocal8601TimeOnlyString(
this.value,
this.timeZoneName
);
},
set(value) {
let DatePortion = this.dateOnly;
if (!DatePortion) {
let v = new Date();
let fullYear = v.getFullYear();
let fullMonth = v.getMonth() + 1;
if (fullMonth < 10) {
fullMonth = "0" + fullMonth.toString();
}
let fullDay = v.getDate();
if (fullDay < 10) {
fullDay = "0" + fullDay.toString();
}
DatePortion = fullYear + "-" + fullMonth + "-" + fullDay;
}
this.date = window.$gz.locale.localTimeDateStringToUTC8601String(
DatePortion + "T" + value,
this.timeZoneName
);
}
}
}
};
</script>

View File

@@ -33,8 +33,8 @@ import gzenums from "./api/enums";
import "@/assets/css/main.css";
//controls
import dateTimeControl from "./components/date-time-control.vue";
//import dateTimeControl2 from "./components/date-time-non-native-control.vue";//keeping around in case need it for some reason
//import dateTimeControl from "./components/date-time-control.vue";
import dateTimeControl from "./components/date-time-control.vue";
import dateControl from "./components/date-control.vue";
import timeControl from "./components/time-control.vue";
import tagPicker from "./components/tag-picker.vue";
@@ -177,8 +177,8 @@ document.addEventListener("fetchEnd", function() {
/////////////////////////////////////////////////////////////
//GZ COMPONENTS
//
Vue.component("gz-date-time-picker", dateTimeControl);
//Vue.component("gz-date-time-non-native-picker", dateTimeNonNativeControl);//keeping in case decide to support alternative (at this time mostly for mac ios it seems)
Vue.component("gz-date-time-picker", dateTimeControl); //keeping in case decide to support alternative (at this time mostly for mac ios it seems)
Vue.component("gz-date-picker", dateControl);
Vue.component("gz-time-picker", timeControl);
Vue.component("gz-tag-picker", tagPicker);

View File

@@ -2,6 +2,7 @@
<v-container fluid>
<gz-report-selector ref="reportSelector"></gz-report-selector>
<!-- {{ formState }} -->
{{ obj.contractExpires }}
<div v-if="formState.ready">
<gz-error :errorBoxMessage="formState.errorBoxMessage"></gz-error>
@@ -187,7 +188,7 @@
</v-col>
<v-col
v-if="form().showMe(this, 'DefaultServiceTemplateID')"
v-if="form().showMe(this, 'DefaultServiceTemplateId')"
cols="12"
sm="6"
lg="4"
@@ -196,16 +197,16 @@
<gz-pick-list
:ayaType="ayaTypes().WorkOrderTemplate"
:showEditIcon="true"
v-model="obj.defaultServiceTemplateID"
v-model="obj.defaultServiceTemplatedId"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('WorkOrderTemplate')"
ref="defaultServiceTemplateID"
data-cy="defaultServiceTemplateID"
ref="defaultServiceTemplateId"
data-cy="defaultServiceTemplateId"
:error-messages="
form().serverErrors(this, 'defaultServiceTemplateID')
form().serverErrors(this, 'defaultServiceTemplateId')
"
@input="fieldValueChanged('defaultServiceTemplateID')"
@input="fieldValueChanged('defaultServiceTemplateId')"
></gz-pick-list>
</v-col>
@@ -232,7 +233,7 @@
<v-col
v-if="
form().showMe(this, 'HeadOfficeID') && obj.billHeadOffice
form().showMe(this, 'HeadOfficeId') && obj.billHeadOffice
"
cols="12"
sm="6"
@@ -242,19 +243,19 @@
<gz-pick-list
:ayaType="ayaTypes().HeadOffice"
:showEditIcon="true"
v-model="obj.headOfficeID"
v-model="obj.headOfficeId"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('HeadOffice')"
ref="headOfficeID"
data-cy="headOfficeID"
:error-messages="form().serverErrors(this, 'headOfficeID')"
@input="fieldValueChanged('headOfficeID')"
ref="headOfficeId"
data-cy="headOfficeId"
:error-messages="form().serverErrors(this, 'headOfficeId')"
@input="fieldValueChanged('headOfficeId')"
></gz-pick-list>
</v-col>
<v-col
v-if="form().showMe(this, 'ContractID')"
v-if="form().showMe(this, 'ContractId')"
cols="12"
sm="6"
lg="4"
@@ -263,14 +264,14 @@
<gz-pick-list
:ayaType="ayaTypes().Contract"
:showEditIcon="true"
v-model="obj.contractID"
v-model="obj.contractId"
:readonly="formState.readOnly"
:disabled="formState.readOnly"
:label="$ay.t('Contract')"
ref="contractID"
data-cy="contractID"
:error-messages="form().serverErrors(this, 'contractID')"
@input="fieldValueChanged('contractID')"
ref="contractId"
data-cy="contractId"
:error-messages="form().serverErrors(this, 'contractId')"
@input="fieldValueChanged('contractId')"
></gz-pick-list>
</v-col>