debian-mirror-gitlab/app/assets/javascripts/vue_shared/components/chronic_duration_input.vue
2022-01-26 12:08:38 +05:30

133 lines
3.2 KiB
Vue

<script>
import * as Sentry from '@sentry/browser';
import { GlFormInput } from '@gitlab/ui';
import {
DurationParseError,
outputChronicDuration,
parseChronicDuration,
} from '~/chronic_duration';
import { __ } from '~/locale';
export default {
components: {
GlFormInput,
},
model: {
prop: 'value',
event: 'change',
},
props: {
value: {
type: Number,
required: false,
default: null,
},
name: {
type: String,
required: false,
default: null,
},
integerRequired: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
numberData: this.value,
humanReadableData: this.convertDuration(this.value),
isValueValid: this.value === null ? null : true,
};
},
computed: {
numberValue: {
get() {
return this.numberData;
},
set(value) {
if (this.numberData !== value) {
this.numberData = value;
this.humanReadableData = this.convertDuration(value);
this.isValueValid = value === null ? null : true;
}
this.emitEvents();
},
},
humanReadableValue: {
get() {
return this.humanReadableData;
},
set(value) {
this.humanReadableData = value;
try {
if (value === '') {
this.numberData = null;
this.isValueValid = null;
} else {
this.numberData = parseChronicDuration(value, {
keepZero: true,
raiseExceptions: true,
});
this.isValueValid = true;
}
} catch (e) {
if (e instanceof DurationParseError) {
this.isValueValid = false;
} else {
Sentry.captureException(e);
}
}
this.emitEvents(true);
},
},
isValidDecimal() {
return !this.integerRequired || this.numberData === null || Number.isInteger(this.numberData);
},
feedback() {
if (this.isValueValid === false) {
return this.$options.i18n.INVALID_INPUT_FEEDBACK;
}
if (!this.isValidDecimal) {
return this.$options.i18n.INVALID_DECIMAL_FEEDBACK;
}
return '';
},
},
i18n: {
INVALID_INPUT_FEEDBACK: __('Please enter a valid time interval'),
INVALID_DECIMAL_FEEDBACK: __('An integer value is required for seconds'),
},
watch: {
value() {
this.numberValue = this.value;
},
},
mounted() {
this.emitEvents();
},
methods: {
convertDuration(value) {
return value === null ? '' : outputChronicDuration(value);
},
emitEvents(emitChange = false) {
if (emitChange && this.isValueValid !== false && this.isValidDecimal) {
this.$emit('change', this.numberData);
}
const { feedback } = this;
this.$refs.text.$el.setCustomValidity(feedback);
this.$refs.hidden.setCustomValidity(feedback);
this.$emit('valid', {
valid: this.isValueValid && this.isValidDecimal,
feedback,
});
},
},
};
</script>
<template>
<div>
<gl-form-input ref="text" v-bind="$attrs" v-model="humanReadableValue" />
<input ref="hidden" type="hidden" :name="name" :value="numberValue" />
</div>
</template>