diff options
Diffstat (limited to 'app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue')
-rw-r--r-- | app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue | 215 |
1 files changed, 78 insertions, 137 deletions
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue index 4efabcb7df3..5ef1f959b2c 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue @@ -1,12 +1,19 @@ <script> -import { GlSprintf, GlLink } from '@gitlab/ui'; +import { GlFormRadio, GlFormRadioGroup, GlLink, GlSprintf } from '@gitlab/ui'; import { s__, sprintf } from '~/locale'; import { getWeekdayNames } from '~/lib/utils/datetime_utility'; +const KEY_EVERY_DAY = 'everyDay'; +const KEY_EVERY_WEEK = 'everyWeek'; +const KEY_EVERY_MONTH = 'everyMonth'; +const KEY_CUSTOM = 'custom'; + export default { components: { - GlSprintf, + GlFormRadio, + GlFormRadioGroup, GlLink, + GlSprintf, }, props: { initialCronInterval: { @@ -22,6 +29,7 @@ export default { randomWeekDayIndex: this.generateRandomWeekDayIndex(), randomDay: this.generateRandomDay(), inputNameAttribute: 'schedule[cron]', + radioValue: this.initialCronInterval ? KEY_CUSTOM : KEY_EVERY_DAY, cronInterval: this.initialCronInterval, cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron', }; @@ -29,14 +37,11 @@ export default { computed: { cronIntervalPresets() { return { - everyDay: `0 ${this.randomHour} * * *`, - everyWeek: `0 ${this.randomHour} * * ${this.randomWeekDayIndex}`, - everyMonth: `0 ${this.randomHour} ${this.randomDay} * *`, + [KEY_EVERY_DAY]: `0 ${this.randomHour} * * *`, + [KEY_EVERY_WEEK]: `0 ${this.randomHour} * * ${this.randomWeekDayIndex}`, + [KEY_EVERY_MONTH]: `0 ${this.randomHour} ${this.randomDay} * *`, }; }, - intervalIsPreset() { - return Object.values(this.cronIntervalPresets).includes(this.cronInterval); - }, formattedTime() { if (this.randomHour > 12) { return `${this.randomHour - 12}:00pm`; @@ -45,24 +50,36 @@ export default { } return `${this.randomHour}:00am`; }, + radioOptions() { + return [ + { + value: KEY_EVERY_DAY, + text: sprintf(s__(`Every day (at %{time})`), { time: this.formattedTime }), + }, + { + value: KEY_EVERY_WEEK, + text: sprintf(s__('Every week (%{weekday} at %{time})'), { + weekday: this.weekday, + time: this.formattedTime, + }), + }, + { + value: KEY_EVERY_MONTH, + text: sprintf(s__('Every month (Day %{day} at %{time})'), { + day: this.randomDay, + time: this.formattedTime, + }), + }, + { + value: KEY_CUSTOM, + text: s__('PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})'), + link: this.cronSyntaxUrl, + }, + ]; + }, weekday() { return getWeekdayNames()[this.randomWeekDayIndex]; }, - everyDayText() { - return sprintf(s__(`Every day (at %{time})`), { time: this.formattedTime }); - }, - everyWeekText() { - return sprintf(s__('Every week (%{weekday} at %{time})'), { - weekday: this.weekday, - time: this.formattedTime, - }); - }, - everyMonthText() { - return sprintf(s__('Every month (Day %{day} at %{time})'), { - day: this.randomDay, - time: this.formattedTime, - }); - }, }, watch: { cronInterval() { @@ -72,38 +89,18 @@ export default { gl.pipelineScheduleFieldErrors.updateFormValidityState(); }); }, - }, - // If at the mounting stage the default is still an empty string, we - // know we are not editing an existing field so we update it so - // that the default is the first radio option - mounted() { - if (this.cronInterval === '') { - this.cronInterval = this.cronIntervalPresets.everyDay; - } + radioValue: { + immediate: true, + handler(val) { + if (val !== KEY_CUSTOM) { + this.cronInterval = this.cronIntervalPresets[val]; + } + }, + }, }, methods: { - setCustomInput(e) { - if (!this.isEditingCustom) { - this.isEditingCustom = true; - this.$refs.customInput.click(); - // Because we need to manually trigger the click on the radio btn, - // it will add a space to update the v-model. If the user is typing - // and the space is added, it will feel very unituitive so we reset - // the value to the original - this.cronInterval = e.target.value; - } - if (this.intervalIsPreset) { - this.isEditingCustom = false; - } - }, - toggleCustomInput(shouldEnable) { - this.isEditingCustom = shouldEnable; - - if (shouldEnable) { - // We need to change the value so other radios don't remain selected - // because the model (cronInterval) hasn't changed. The server trims it. - this.cronInterval = `${this.cronInterval} `; - } + onCustomInput() { + this.radioValue = KEY_CUSTOM; }, generateRandomHour() { return Math.floor(Math.random() * 23); @@ -119,89 +116,33 @@ export default { </script> <template> - <div class="interval-pattern-form-group"> - <div class="cron-preset-radio-input"> - <input - id="every-day" - v-model="cronInterval" - :name="inputNameAttribute" - :value="cronIntervalPresets.everyDay" - class="label-bold" - type="radio" - @click="toggleCustomInput(false)" - /> - - <label class="label-bold" for="every-day"> - {{ everyDayText }} - </label> - </div> - - <div class="cron-preset-radio-input"> - <input - id="every-week" - v-model="cronInterval" - :name="inputNameAttribute" - :value="cronIntervalPresets.everyWeek" - class="label-bold" - type="radio" - @click="toggleCustomInput(false)" - /> - - <label class="label-bold" for="every-week"> - {{ everyWeekText }} - </label> - </div> - - <div class="cron-preset-radio-input"> - <input - id="every-month" - v-model="cronInterval" - :name="inputNameAttribute" - :value="cronIntervalPresets.everyMonth" - class="label-bold" - type="radio" - @click="toggleCustomInput(false)" - /> - - <label class="label-bold" for="every-month"> - {{ everyMonthText }} - </label> - </div> - - <div class="cron-preset-radio-input"> - <input - id="custom" - ref="customInput" - v-model="cronInterval" - :name="inputNameAttribute" - :value="cronInterval" - class="label-bold" - type="radio" - @click="toggleCustomInput(true)" - /> - - <label for="custom"> {{ s__('PipelineSheduleIntervalPattern|Custom') }} </label> - - <gl-sprintf :message="__('(%{linkStart}Cron syntax%{linkEnd})')"> - <template #link="{content}"> - <gl-link :href="cronSyntaxUrl" target="_blank" class="gl-font-sm"> - {{ content }} - </gl-link> - </template> - </gl-sprintf> - </div> - - <div class="cron-interval-input-wrapper"> - <input - id="schedule_cron" - v-model="cronInterval" - :placeholder="__('Define a custom pattern with cron syntax')" - :name="inputNameAttribute" - class="form-control inline cron-interval-input" - type="text" - required="true" - @input="setCustomInput" - /> - </div> + <div> + <gl-form-radio-group v-model="radioValue" :name="inputNameAttribute"> + <gl-form-radio + v-for="option in radioOptions" + :key="option.value" + :value="option.value" + :data-testid="option.value" + > + <gl-sprintf v-if="option.link" :message="option.text"> + <template #link="{content}"> + <gl-link :href="option.link" target="_blank" class="gl-font-sm"> + {{ content }} + </gl-link> + </template> + </gl-sprintf> + <template v-else>{{ option.text }}</template> + </gl-form-radio> + </gl-form-radio-group> + <input + id="schedule_cron" + v-model="cronInterval" + :placeholder="__('Define a custom pattern with cron syntax')" + :name="inputNameAttribute" + class="form-control inline cron-interval-input" + type="text" + required="true" + @input="onCustomInput" + /> </div> </template> |