diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
commit | aee0a117a889461ce8ced6fcf73207fe017f1d99 (patch) | |
tree | 891d9ef189227a8445d83f35c1b0fc99573f4380 /app/assets/javascripts/vue_shared/components/chronic_duration_input.vue | |
parent | 8d46af3258650d305f53b819eabf7ab18d22f59e (diff) |
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/chronic_duration_input.vue')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/chronic_duration_input.vue | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/chronic_duration_input.vue b/app/assets/javascripts/vue_shared/components/chronic_duration_input.vue new file mode 100644 index 00000000000..ffbcdefc924 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/chronic_duration_input.vue @@ -0,0 +1,133 @@ +<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> |