Revert "Switch to using Vue3 date-picker in item card [SCI-9741] (#6697)" (#6700)

This reverts commit eaa0989c77.
This commit is contained in:
Alex Kriuchykhin 2023-11-24 12:55:22 +01:00 committed by GitHub
parent 3b165ba92d
commit 39f4637351
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 375 additions and 504 deletions

View file

@ -11,61 +11,46 @@ export default {
return 'border-sn-light-grey hover:border-sn-sleepy-grey'; return 'border-sn-light-grey hover:border-sn-sleepy-grey';
}, },
isEditable() { isEditable() {
return this.isEditing && this.editingField === this.dateType; return this.isEditing && this.editingField === this.dateType
}, }
}, },
methods: { methods: {
enableEdit() { enableEdit() {
this.isEditing = true; this.isEditing = true
this.$emit('setEditingField', this.dateType); this.$emit('setEditingField', this.dateType)
}, },
saveChange() { saveChange() {
if ( if (!this.isEditing ||
!this.isEditing this.isSaving ||
|| this.isSaving !this.params ||
|| !this.params (this.params && !Object.keys(this.params).includes(this.colId?.toString()))) {
|| (this.params && !Object.keys(this.params).includes(this.colId?.toString())) Object.assign(this.$data, { isEditing: false, isSaving: false, errorMessage: null });
) {
Object.assign(this.$data, {
isEditing: false,
isSaving: false,
errorMessage: null,
});
return; return;
} };
// Don't submit unless values changed // Don't submit unless values changed
switch (true) { switch (true) {
case ['date', 'dateTime', 'time'].includes(this.dateType): case ['date', 'dateTime', 'time'].includes(this.dateType):
if (this.equalDates(this.params[this.colId], this.initDate)) { if(this.equalDates(this.params[this.colId], this.initDate)) {
Object.assign(this.$data, { isEditing: false, isSaving: false }); Object.assign(this.$data, { isEditing: false, isSaving: false });
return; return;
} }
if ( if(this.dateType === 'time' && this.equalTimes(this.params[this.colId], this.initDate)) {
this.dateType === 'time'
&& this.equalTimes(this.params[this.colId], this.initDate)
) {
Object.assign(this.$data, { isEditing: false, isSaving: false }); Object.assign(this.$data, { isEditing: false, isSaving: false });
return; return;
} }
break;
case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType): case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType):
if ( if (this.equalDates(this.timeFrom?.datetime, this.initStartDate) &&
this.equalDates(this.timeFrom?.datetime, this.initStartDate) this.equalDates(this.timeTo?.datetime, this.initEndDate)) {
&& this.equalDates(this.timeTo?.datetime, this.initEndDate)
) {
Object.assign(this.$data, { isEditing: false, isSaving: false }); Object.assign(this.$data, { isEditing: false, isSaving: false });
return; return;
} }
if ( if (this.dateType === 'timeRange' &&
this.dateType === 'timeRange' this.equalTimes(this.timeFrom?.datetime, this.initStartDate) &&
&& this.equalTimes(this.timeFrom?.datetime, this.initStartDate) this.equalTimes(this.timeTo?.datetime, this.initEndDate)) {
&& this.equalTimes(this.timeTo?.datetime, this.initEndDate)
) {
Object.assign(this.$data, { isEditing: false, isSaving: false }); Object.assign(this.$data, { isEditing: false, isSaving: false });
return; return;
} }
break;
default: default:
break; break;
} }
@ -80,34 +65,28 @@ export default {
const cellValue = result?.value; const cellValue = result?.value;
switch (true) { switch (true) {
case ['date', 'dateTime', 'time'].includes(this.dateType): case ['date', 'dateTime', 'time'].includes(this.dateType):
this.values = cellValue; this.values = cellValue
this.initDate = cellValue?.datetime; this.initDate = cellValue?.datetime
break;
case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType): case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType):
this.initStartDate = cellValue?.start_time?.datetime; this.initStartDate = cellValue?.start_time?.datetime;
this.initEndDate = cellValue?.end_time?.datetime; this.initEndDate = cellValue?.end_time?.datetime;
break;
default: default:
break; break;
} }
Object.assign($this.$data, { Object.assign($this.$data, { isEditing: false, isSaving: false, values: result?.value });
isEditing: false,
isSaving: false,
values: result?.value,
});
if ($('.dataTable')[0]) $('.dataTable').DataTable().ajax.reload(null, false); if ($('.dataTable')[0]) $('.dataTable').DataTable().ajax.reload(null, false);
}, }
}); });
}, },
setParams() { setParams() {
const defaultParams = this.params ? this.params : { [this.colId]: {} }; let defaultParams = this.params ? this.params : { [this.colId]: {} };
switch (true) { switch (true) {
case ['date', 'dateTime', 'time'].includes(this.dateType): case ['date', 'dateTime', 'time'].includes(this.dateType):
defaultParams[this.colId] = this.values?.datetime; defaultParams[this.colId] = this.values?.datetime;
break; break;
case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType): case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType):
defaultParams[this.colId].start_time = this.timeFrom?.datetime; defaultParams[this.colId]['start_time'] = this.timeFrom?.datetime;
defaultParams[this.colId].end_time = this.timeTo?.datetime; defaultParams[this.colId]['end_time'] = this.timeTo?.datetime;
break; break;
default: default:
break; break;
@ -115,23 +94,21 @@ export default {
this.params = defaultParams; this.params = defaultParams;
}, },
formatDateTime(date, field = null) { formatDateTime(date, field = null) {
this.values = this.values ? this.values : { [this.colId]: {} }; this.values = this.values ? this.values : { [this.colId]: {} }
const params = this.params && this.params[this.colId] let params = this.params && this.params[this.colId] ? this.params : { [this.colId]: {} };
? this.params let timeFrom = this.timeFrom || {};
: { [this.colId]: {} }; let timeTo = this.timeTo || {};
const timeFrom = this.timeFrom || {};
const timeTo = this.timeTo || {};
switch (true) { switch (true) {
case ['date', 'dateTime', 'time'].includes(this.dateType): case ['date', 'dateTime', 'time'].includes(this.dateType):
params[this.colId] = date; params[this.colId] = date;
this.values.datetime = date; this.values['datetime'] = date;
break; break;
case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType): case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType):
if (field === 'start_time') { if (field === 'start_time') {
timeFrom.datetime = date; timeFrom['datetime'] = date;
} }
if (field === 'end_time') { if (field === 'end_time'){
timeTo.datetime = date; timeTo['datetime'] = date;
} }
params[this.colId][field] = date; params[this.colId][field] = date;
break; break;
@ -144,30 +121,22 @@ export default {
}, },
dateValue(date) { dateValue(date) {
const typesThatCantBeEmpty = ['dateRange', 'dateTimeRange']; const typesThatCantBeEmpty = ['dateRange', 'dateTimeRange'];
if ( if (date && (date.currentTarget === null) && typesThatCantBeEmpty.includes(this.dateType)) {
date
&& date.currentTarget === null
&& typesThatCantBeEmpty.includes(this.dateType)
) {
this.errorMessage = I18n.t('repositories.item_card.date_time.errors.select_valid_value'); this.errorMessage = I18n.t('repositories.item_card.date_time.errors.select_valid_value');
return null; return;
} }
if (date) return new Date(date); if(date) return new Date(date)
return null; return new Date()
}, },
hasMonthText() { hasMonthText(){
$('body') $('body').data('datetime-picker-format')?.match(/MMM/)
.data('datetime-picker-format')
?.match(/MMM/);
}, },
equalDates(date1, date2) { equalDates(date1, date2){
return new Date(date1).getTime() === new Date(date2).getTime(); return new Date(date1).getTime() === new Date(date2).getTime();
}, },
equalTimes(date1, date2) { equalTimes(date1, date2){
return ( return new Date(date1).getHours() === new Date(date2).getHours() &&
new Date(date1).getHours() === new Date(date2).getHours() new Date(date1).getMinutes() == new Date(date2).getMinutes()
&& new Date(date1).getMinutes() === new Date(date2).getMinutes()
);
}, },
validateAndSave() { validateAndSave() {
this.errorMessage = null; this.errorMessage = null;
@ -176,38 +145,28 @@ export default {
// To do // To do
break; break;
case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType): case ['dateRange', 'dateTimeRange', 'timeRange'].includes(this.dateType):
if (!this.params?.[this.colId]) return; if(this.params && this.params[this.colId]) {
if((!this.params[this.colId].start_time && this.params[this.colId].end_time) ||
// start_time and end_time must be both present or both absent (this.params[this.colId].start_time && !this.params[this.colId].end_time)) {
if ( this.errorMessage = I18n.t('repositories.item_card.date_time.errors.not_valid_range');
!!this.params[this.colId]?.start_time?.getTime?.() return;
^ !!this.params[this.colId]?.end_time?.getTime?.() }
) { if (this.params[this.colId].start_time && this.params[this.colId].end_time &&
this.errorMessage = I18n.t('repositories.item_card.date_time.errors.not_valid_range'); this.params[this.colId].start_time.getTime() && this.params[this.colId].end_time.getTime()) {
return; if(this.params[this.colId].start_time.getTime() > this.params[this.colId].end_time.getTime()) {
} this.errorMessage = I18n.t('repositories.item_card.date_time.errors.not_valid_range');
return
// start_time should always be lesser then end_time }
if ( }
this.params[this.colId]?.start_time?.getTime?.() if (!this.params[this.colId].start_time && !this.params[this.colId].end_time) {
&& this.params[this.colId].start_time.getTime() > this.params[this.colId].end_time.getTime() this.params = { [this.colId]: null }
) { }
this.errorMessage = I18n.t('repositories.item_card.date_time.errors.not_valid_range');
return;
}
// start_time and end_time both are absent
if (
!this.params[this.colId]?.start_time
&& !this.params[this.colId]?.end_time
) {
this.params = { [this.colId]: null };
} }
break; break;
default: default:
break; break;
} }
this.saveChange(); this.saveChange();
}, }
}, },
}; };

View file

@ -1,385 +1,297 @@
<template> <template>
<div> <div>
<div <div ref="dateTimeRangeOverlay"
ref="dateTimeRangeOverlay" class="fixed top-0 left-0 right-0 bottom-0 bg-transparent z-[999] hidden">
class="fixed top-0 left-0 right-0 bottom-0 bg-transparent z-[999] hidden" </div>
></div>
<div <div
@click="enableEdit" @click="enableEdit"
v-click-outside="validateAndSave" v-click-outside="validateAndSave"
class="text-sn-dark-grey font-inter text-sm font-normal leading-5 w-full rounded relative !px-2 !py-0 class="text-sn-dark-grey font-inter text-sm font-normal leading-5 w-full rounded relative"
min-h-[32px] flex items-center
[&_.dp\_\_input]:border-0 [&_.dp\_\_input]:p-0"
:class="editableClassName" :class="editableClassName"
> >
<template v-if="dateType === 'date'"> <!-- DATE -->
<div <div v-if="dateType === 'date'">
v-if="isEditing || values?.datetime" <div v-if="isEditing || values?.datetime" ref="edit">
ref="edit"
class="[&_.dp\_\_input]:!w-20"
>
<DateTimePicker <DateTimePicker
:mode="'date'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime($event)" @change="formatDateTime($event)"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePicker${colId}`" :selectorId="`DatePicker${colId}`"
:dateOnly="true"
:defaultValue="dateValue(values?.datetime)" :defaultValue="dateValue(values?.datetime)"
:placeholder=" :standAlone="true"
i18n.t('repositories.item_card.repository_date_value.placeholder')
"
/> />
</div> </div>
<div <div v-else ref="view" :class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }" >
v-else {{ i18n.t(`repositories.item_card.repository_date_value.${canEdit ? 'placeholder' : 'no_date'}`) }}
ref="view"
:class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }"
>
{{
i18n.t(
`repositories.item_card.repository_date_value.${
canEdit ? "placeholder" : "no_date"
}`
)
}}
</div> </div>
</template> </div>
<template v-else-if="dateType === 'dateRange'">
<div <!-- DATE RANGE -->
v-if="isEditing || (timeFrom?.datetime && timeTo?.datetime)" <div v-else-if="dateType === 'dateRange'">
ref="edit" <div v-if="isEditing || (timeFrom?.datetime && timeTo?.datetime)" ref="edit" class="w-full flex align-center">
class="w-full flex align-center [&_.dp\_\_input]:!w-20"
>
<div> <div>
<DateTimePicker <DateTimePicker
:mode="'date'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime($event, 'start_time')" @change="formatDateTime($event, 'start_time')"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePickerStart${colId}`" :selectorId="`DatePickerStart${colId}`"
:dateOnly="true"
:defaultValue="dateValue(timeFrom?.datetime)" :defaultValue="dateValue(timeFrom?.datetime)"
:placeholder=" :standAlone="true"
i18n.t( :dateClassName="hasMonthText() ? 'w-[135px]' : 'w-[90px]'"
'repositories.item_card.repository_date_range_value.placeholder'
)
"
/> />
</div> </div>
<span class="flex items-center mx-1">-</span> <span class="mr-3">-</span>
<div> <div>
<DateTimePicker <DateTimePicker
:mode="'date'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime($event, 'end_time')" @change="formatDateTime($event, 'end_time')"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePickerEnd${colId}`" :selectorId="`DatePickerEnd${colId}`"
:dateOnly="true"
:defaultValue="dateValue(timeTo?.datetime)" :defaultValue="dateValue(timeTo?.datetime)"
:placeholder=" :standAlone="true"
i18n.t( :dateClassName="hasMonthText() ? 'w-[135px]' : 'ml-2 w-[90px]'"
'repositories.item_card.repository_date_range_value.placeholder'
)
"
/> />
</div> </div>
</div> </div>
<div <div v-else ref="view" :class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }" >
v-else {{ i18n.t(`repositories.item_card.repository_date_range_value.${canEdit ? 'placeholder' : 'no_date_range'}`) }}
ref="view"
:class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }"
>
{{
i18n.t(
`repositories.item_card.repository_date_range_value.${
canEdit ? "placeholder" : "no_date_range"
}`
)
}}
</div> </div>
</template> </div>
<template v-if="dateType === 'dateTime'">
<div <!-- DATE-TIME -->
v-if="isEditing || values?.datetime" <div v-if="dateType === 'dateTime'">
ref="edit" <div v-if="isEditing || values?.datetime" ref="edit" class="w-full">
class="w-full [&_.dp\_\_input]:!w-[7.125rem]"
>
<DateTimePicker <DateTimePicker
:mode="'datetime'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime" @change="formatDateTime"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePicker${colId}`" :selectorId="`DatePicker${colId}`"
:defaultValue="dateValue(values?.datetime)" :defaultValue="dateValue(values?.datetime)"
:placeholder=" :standAlone="true"
i18n.t( :dateClassName="hasMonthText() ? 'w-[135px]' : 'w-[90px]'"
'repositories.item_card.repository_date_time_value.placeholder' timeClassName="w-11"
)
"
/> />
</div> </div>
<div <div v-else ref="view" :class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }" >
v-else {{ i18n.t(`repositories.item_card.repository_date_time_value.${canEdit ? 'placeholder' : 'no_date_time'}`) }}
ref="view"
:class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }"
>
{{
i18n.t(
`repositories.item_card.repository_date_time_value.${
canEdit ? "placeholder" : "no_date_time"
}`
)
}}
</div> </div>
</template> </div>
<template v-else-if="dateType === 'dateTimeRange'">
<div <!-- DATE-TIME RANGE -->
v-if="isEditing || (timeFrom?.datetime && timeTo?.datetime)" <div v-else-if="dateType === 'dateTimeRange'">
ref="edit" <div v-if="isEditing || (timeFrom?.datetime && timeTo?.datetime)" ref="edit" class="w-full flex">
class="w-full flex [&_.dp\_\_input]:!w-[7.125rem]"
>
<div> <div>
<DateTimePicker <DateTimePicker
:mode="'datetime'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime($event, 'start_time')" @change="formatDateTime($event, 'start_time')"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePickerStart${colId}`" :selectorId="`DatePickerStart${colId}`"
:defaultValue="dateValue(timeFrom?.datetime)" :defaultValue="dateValue(timeFrom?.datetime)"
:timeOnly="false" :timeOnly="false"
:dateOnly="false" :dateOnly="false"
:placeholder=" :standAlone="true"
i18n.t( :dateClassName="hasMonthText() ? 'w-[135px]' : 'w-[90px]'"
'repositories.item_card.repository_date_time_range_value.placeholder' timeClassName="w-11"
)
"
/> />
</div> </div>
<span class="flex items-center mx-1">-</span> <span class="mx-1">-</span>
<div> <div>
<DateTimePicker <DateTimePicker
:mode="'datetime'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime($event, 'end_time')" @change="formatDateTime($event, 'end_time')"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePickerEnd${colId}`" :selectorId="`DatePickerEnd${colId}`"
:defaultValue="dateValue(timeTo?.datetime)" :defaultValue="dateValue(timeTo?.datetime)"
:timeOnly="false" :timeOnly="false"
:dateOnly="false" :dateOnly="false"
:placeholder=" :standAlone="true"
i18n.t( :dateClassName="hasMonthText() ? 'w-[135px]' : 'ml-2 w-[90px]'"
'repositories.item_card.repository_date_time_range_value.placeholder' timeClassName="w-11"
)
"
/> />
</div> </div>
</div> </div>
<div <div v-else ref="view" :class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }" >
v-else {{ i18n.t(`repositories.item_card.repository_date_time_range_value.${canEdit ? 'placeholder' : 'no_date_time_range'}`) }}
ref="view"
:class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }"
>
{{
i18n.t(
`repositories.item_card.repository_date_time_range_value.${
canEdit ? "placeholder" : "no_date_time_range"
}`
)
}}
</div> </div>
</template> </div>
<template v-else-if="dateType === 'time'">
<div <!-- TIME -->
v-if="isEditing || values?.datetime" <div v-else-if="dateType === 'time'">
ref="edit" <div v-if="isEditing || values?.datetime" ref="edit">
class="[&_.dp\_\_input]:!w-10"
>
<DateTimePicker <DateTimePicker
:mode="'time'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime" @change="formatDateTime"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePicker${colId}`" :selectorId="`DatePicker${colId}`"
:timeOnly="true"
:defaultValue="dateValue(values?.datetime)" :defaultValue="dateValue(values?.datetime)"
:placeholder=" :standAlone="true"
i18n.t('repositories.item_card.repository_time_value.placeholder') timeClassName="w-11"
"
/> />
</div> </div>
<div <div v-else ref="view" :class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }">
v-else {{ i18n.t(`repositories.item_card.repository_time_value.${ canEdit ? 'placeholder' : 'no_time'}`) }}
ref="view"
:class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }"
>
{{
i18n.t(
`repositories.item_card.repository_time_value.${
canEdit ? "placeholder" : "no_time"
}`
)
}}
</div> </div>
</template> </div>
<template v-else-if="dateType === 'timeRange'">
<div <!-- TIME RANGE -->
v-if="isEditing || (timeFrom?.datetime && timeTo?.datetime)" <div v-else-if="dateType === 'timeRange'">
ref="edit" <div v-if="isEditing || (timeFrom?.datetime && timeTo?.datetime)" ref="edit" class="w-full flex">
class="w-full flex [&_.dp\_\_input]:!w-10"
>
<div> <div>
<DateTimePicker <DateTimePicker
:mode="'time'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime($event, 'start_time')" @change="formatDateTime($event, 'start_time')"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePickerStart${colId}`" :selectorId="`DatePickerStart${colId}`"
:timeOnly="true"
:defaultValue="dateValue(timeFrom?.datetime)" :defaultValue="dateValue(timeFrom?.datetime)"
:placeholder=" :standAlone="true"
i18n.t( timeClassName="w-11"
'repositories.item_card.repository_time_range_value.placeholder'
)
"
/> />
</div> </div>
<span class="flex items-center mx-1">-</span> <span class="mx-1">-</span>
<div> <div>
<DateTimePicker <DateTimePicker
:mode="'time'"
:disabled="!canEdit" :disabled="!canEdit"
@change="formatDateTime($event, 'end_time')" @change="formatDateTime($event, 'end_time')"
@open="enableEdit"
@close="validateAndSave"
:inputIconHidden="true"
inputClassName="sci-cursor-edit"
:selectorId="`DatePickerEnd${colId}`" :selectorId="`DatePickerEnd${colId}`"
:timeOnly="true"
:defaultValue="dateValue(timeTo?.datetime)" :defaultValue="dateValue(timeTo?.datetime)"
:placeholder=" :standAlone="true"
i18n.t( timeClassName="ml-2 w-11"
'repositories.item_card.repository_time_range_value.placeholder'
)
"
/> />
</div> </div>
</div> </div>
<div <div v-else ref="view" :class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }">
v-else {{ i18n.t(`repositories.item_card.repository_time_range_value.${canEdit ? 'placeholder' : 'no_time_range'}`) }}
ref="view"
:class="{ 'text-sn-dark-grey': !canEdit, 'text-sn-grey': canEdit }"
>
{{
i18n.t(
`repositories.item_card.repository_time_range_value.${
canEdit ? "placeholder" : "no_time_range"
}`
)
}}
</div> </div>
</template> </div>
<span class="absolute right-2 top-1.5" v-if="values?.reminder"> <span class="absolute right-2 top-1.5" v-if="values?.reminder">
<Reminder :value="values" /> <Reminder :value="values" />
</span> </span>
</div> </div>
<div <div class="text-sn-delete-red text-xs w-full " :class="{ visible: errorMessage, invisible: !errorMessage }">
class="text-sn-delete-red text-xs w-full "
:class="{ visible: errorMessage, invisible: !errorMessage }"
>
{{ errorMessage }} {{ errorMessage }}
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { vOnClickOutside } from '@vueuse/components'; import { vOnClickOutside } from '@vueuse/components'
import dateTimeRange from '../mixins/date_time_range'; import date_time_range from './../mixins/date_time_range';
import DateTimePicker from '../../shared/date_time_picker.vue'; import DateTimePicker from '../../shared/date_time_picker.vue';
import Reminder from '../reminder.vue'; import Reminder from './../reminder.vue';
export default { export default {
name: 'DateTimeRange', name: 'DateTimeRange',
mixins: [dateTimeRange], mixins: [date_time_range],
components: { components: {
DateTimePicker, DateTimePicker,
Reminder, Reminder
},
directives: {
'click-outside': vOnClickOutside,
},
data() {
return {
values: {},
errorMessage: null,
params: null,
cellUpdatePath: null,
timeFrom: null,
timeTo: null,
isEditing: false,
initValue: null,
initStartDate: null,
initEndDate: null,
};
},
props: {
dateType: String,
colVal: null,
colId: null,
updatePath: null,
startTime: null,
endTime: null,
editingField: false,
canEdit: { type: Boolean, default: false },
},
computed: {
editableClassName() {
const className = 'border-solid border-[1px] py-2 px-3 sci-cursor-edit';
if (this.canEdit && this.errorMessage) return `${className} border-sn-delete-red`;
if (this.canEdit && this.isEditing) return `${className} border-sn-science-blue`;
if (this.canEdit) return `${className} border-sn-light-grey hover:border-sn-sleepy-grey`;
return '';
}, },
}, directives: {
mounted() { 'click-outside': vOnClickOutside
this.cellUpdatePath = this.updatePath; },
this.values = this.colVal || {}; data() {
this.timeFrom = this.startTime; return {
this.timeTo = this.endTime; values: {},
this.errorMessage = null; errorMessage: null,
this.setParams(); params: null,
this.initDate = this.colVal?.datetime; cellUpdatePath: null,
this.initStartDate = this.startTime?.datetime; timeFrom: null,
this.initEndDate = this.endTime?.datetime; timeTo: null,
}, isEditing: false,
watch: { initValue: null,
isEditing(newValue) { initStartDate: null,
if (!newValue) return; initEndDate: null
// Focus input field to open date picker }
this.$nextTick(() => { },
$(this.$refs.edit) props: {
?.find('input')[0] dateType: String,
?.focus(); colVal: null,
}); colId: null,
updatePath: null,
startTime: null,
endTime: null,
editingField: false,
canEdit: { type: Boolean, default: false }
},
computed: {
editableClassName() {
const className = 'border-solid border-[1px] py-2 px-3 sci-cursor-edit'
if (this.canEdit && this.errorMessage) return `${className} border-sn-delete-red`;
if (this.canEdit && this.isEditing) return `${className} border-sn-science-blue`;
if (this.canEdit) return `${className} border-sn-light-grey hover:border-sn-sleepy-grey`;
return ''
}
},
methods: {
showOverlay() {
const overlay = this.$refs.dateTimeRangeOverlay;
overlay.classList.remove('hidden');
},
hideOverlay() {
const overlay = this.$refs.dateTimeRangeOverlay;
overlay.classList.add('hidden');
},
bringCalendarToFront() {
const calendarEl = document.querySelector('.dp__instance_calendar');
calendarEl.classList.add('z-[9999]');
},
preventBodyScrolling() {
document.body.classList.add('overflow-hidden');
document.body.classList.remove('overflow-auto');
},
allowBodyScrolling() {
document.body.classList.remove('overflow-hidden');
document.body.classList.add('overflow-auto');
},
focusClearedInput() {
const firstInput = $(this.$refs.edit)?.find('input')[0];
const secondInput = $(this.$refs.edit)?.find('input')[1];
// first is empty
if (!firstInput.value) {
firstInput.focus();
firstInput.click();
}
// second is empty
if (!secondInput.value) {
secondInput.focus();
secondInput.click();
}
this.preventBodyScrolling();
this.showOverlay();
this.bringCalendarToFront();
},
},
mounted() {
this.cellUpdatePath = this.updatePath;
this.values = this.colVal || {};
this.timeFrom = this.startTime
this.timeTo = this.endTime
this.errorMessage = null;
this.setParams();
this.initDate = this.colVal?.datetime;
this.initStartDate = this.startTime?.datetime;
this.initEndDate = this.endTime?.datetime;
},
watch: {
isEditing(newValue) {
if (!newValue) return;
// Focus input field to open date picker
this.$nextTick(() => {
$(this.$refs.edit)?.find('input')[0]?.focus();
})
},
errorMessage(newVal) {
if (newVal !== null) {
this.$nextTick(() => {
this.focusClearedInput();
});
}
if (newVal === null) {
this.hideOverlay();
this.allowBodyScrolling();
}
},
} }
} }
};
</script> </script>

View file

@ -42,6 +42,7 @@ export default {
}, },
mounted() { mounted() {
console.log('mounted');
window.addEventListener('resize', this.handleResize); window.addEventListener('resize', this.handleResize);
this.initializeComponent(); this.initializeComponent();
this.$nextTick(() => { this.$nextTick(() => {

View file

@ -18,10 +18,6 @@
week-start="0" week-start="0"
:enable-time-picker="mode == 'datetime'" :enable-time-picker="mode == 'datetime'"
:time-picker="mode == 'time'" :time-picker="mode == 'time'"
:hide-input-icon="inputIconHidden"
:input-class-name="inputClassName"
@open="this.$emit('open')"
@close="this.$emit('close')"
:placeholder="placeholder" > :placeholder="placeholder" >
<template #arrow-right> <template #arrow-right>
<img class="slot-icon" src="/images/calendar/navigate_next.svg"/> <img class="slot-icon" src="/images/calendar/navigate_next.svg"/>
@ -52,141 +48,144 @@
</template> </template>
<script> <script>
import VueDatePicker from '@vuepic/vue-datepicker'; import VueDatePicker from '@vuepic/vue-datepicker';
export default { export default {
name: 'DateTimePicker', name: 'DateTimePicker',
props: { props: {
mode: { type: String, default: 'datetime' }, mode: { type: String, default: 'datetime' },
clearable: { type: Boolean, default: false }, clearable: { type: Boolean, default: false },
teleport: { type: Boolean, default: true }, teleport: { type: Boolean, default: true },
defaultValue: { type: Date, required: false }, defaultValue: { type: Date, required: false },
placeholder: { type: String }, placeholder: { type: String },
inputIconHidden: { type: Boolean, default: false }, standAlone: { type: Boolean, default: false, required: false },
inputClassName: { type: String, default: null }, dateClassName: { type: String, default: '' },
disabled: { type: Boolean, default: false }, timeClassName: { type: String, default: '' },
}, disabled: { type: Boolean, default: false }
data() { },
return { data() {
manualUpdate: false, return {
datetime: this.defaultValue, manualUpdate: false,
time: null, datetime: this.defaultValue,
markers: [ time: null,
{ markers: [
date: new Date(), {
type: 'dot', date: new Date(),
color: '#3B99FD', type: 'dot',
}, color: '#3B99FD',
], },
}; ]
}, }
created() { },
if (this.defaultValue) { created() {
this.time = {
hours: this.defaultValue.getHours(),
minutes: this.defaultValue.getMinutes(),
};
}
},
components: {
VueDatePicker,
},
watch: {
defaultValue() {
this.datetime = this.defaultValue;
if (this.defaultValue) { if (this.defaultValue) {
this.time = { this.time = {
hours: this.defaultValue.getHours(), hours: this.defaultValue.getHours(),
minutes: this.defaultValue.getMinutes(), minutes:this.defaultValue.getMinutes(),
}; }
} }
}, },
datetime() { components: {
if (this.mode === 'time') { VueDatePicker
this.time = null; },
watch: {
defaultValue: function () {
this.datetime = this.defaultValue;
if (this.defaultValue) {
this.time = {
hours: this.defaultValue.getHours(),
minutes: this.defaultValue.getMinutes()
}
}
},
datetime: function () {
if (this.mode == 'time') {
if (this.datetime) { this.time = null;
if (this.datetime) {
this.time = { this.time = {
hours: this.datetime.getHours(), hours: this.datetime.getHours(),
minutes: this.datetime.getMinutes(), minutes: this.datetime.getMinutes()
}; }
} }
return; return
} }
if (this.manualUpdate) { if (this.manualUpdate) {
this.manualUpdate = false; this.manualUpdate = false;
return; return;
} }
if (this.datetime === null) { if ( this.datetime == null) {
this.$emit('cleared'); this.$emit('cleared');
} }
if (this.defaultValue !== this.datetime) { if (this.defaultValue != this.datetime) {
this.$emit('change', this.datetime); this.$emit('change', this.datetime);
}
},
time() {
if (this.manualUpdate) {
this.manualUpdate = false;
return;
}
if (this.mode !== 'time') return;
let newDate;
if (this.time) {
newDate = new Date();
newDate.setHours(this.time.hours);
newDate.setMinutes(this.time.minutes);
} else {
newDate = {
hours: null,
minutes: null,
};
this.$emit('cleared');
}
if (this.defaultValue !== newDate) {
this.$emit('change', newDate);
}
},
},
computed: {
compDatetime: {
get() {
if (this.mode === 'time') {
return this.time;
} }
return this.datetime;
}, },
set(val) { time: function () {
if (this.mode === 'time') { if (this.manualUpdate) {
this.time = val; this.manualUpdate = false;
return;
}
if (this.mode != 'time') return;
let newDate;
if (this.time) {
newDate = new Date();
newDate.setHours(this.time.hours);
newDate.setMinutes(this.time.minutes);
} else { } else {
this.datetime = val; newDate = {
hours: null,
minutes: null
};
this.$emit('cleared');
}
if (this.defaultValue != newDate) {
this.$emit('change', newDate);
}
}
},
computed: {
compDatetime: {
get () {
if (this.mode == 'time') {
return this.time
} else {
return this.datetime
}
},
set (val) {
if (this.mode == 'time') {
this.time = val
} else {
this.datetime = val
}
} }
}, },
format() {
if (this.mode == 'time') return 'HH:mm'
if (this.mode == 'date') return document.body.dataset.datetimePickerFormatVue
return `${document.body.dataset.datetimePickerFormatVue} HH:mm`
}
}, },
format() { mounted() {
if (this.mode === 'time') return 'HH:mm'; window.addEventListener('resize', this.close);
if (this.mode === 'date') return document.body.dataset.datetimePickerFormatVue;
return `${document.body.dataset.datetimePickerFormatVue} HH:mm`;
}, },
}, unmounted() {
mounted() { window.removeEventListener('resize', this.close);
window.addEventListener('resize', this.close);
},
unmounted() {
window.removeEventListener('resize', this.close);
},
methods: {
close() {
this.$refs.datetimePicker.closeMenu();
}, },
}, methods: {
}; close() {
this.$refs.datetimePicker.closeMenu();
},
}
}
</script> </script>