diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-31 18:08:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-31 18:08:42 +0300 |
commit | c27acb1d376f7127cd33eadcc8f5683ed55262bc (patch) | |
tree | 685c31391dca71a73782b5c8626f4ef5b582dc21 /app/assets/javascripts/vue_shared/components/date_time_picker | |
parent | 1808454313ed75c92e1384466e8c83bfbc8ae25e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/date_time_picker')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue | 108 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js | 76 |
2 files changed, 82 insertions, 102 deletions
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue index 7d4c162473f..eedcafe2b42 100644 --- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue +++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue @@ -1,13 +1,15 @@ <script> import { GlButton, GlDropdown, GlDropdownItem, GlFormGroup } from '@gitlab/ui'; import { __, sprintf } from '~/locale'; + +import { convertToFixedRange, isEqualTimeRanges, findTimeRange } from '~/lib/utils/datetime_range'; + import Icon from '~/vue_shared/components/icon.vue'; import DateTimePickerInput from './date_time_picker_input.vue'; import { - defaultTimeWindows, + defaultTimeRanges, + defaultTimeRange, isValidDate, - getTimeRange, - getTimeWindowKey, stringToISODate, ISODateToString, truncateZerosInDateTime, @@ -15,7 +17,7 @@ import { } from './date_time_picker_lib'; const events = { - apply: 'apply', + input: 'input', invalid: 'invalid', }; @@ -29,24 +31,22 @@ export default { GlDropdownItem, }, props: { - start: { - type: String, - required: true, - }, - end: { - type: String, - required: true, - }, - timeWindows: { + value: { type: Object, required: false, - default: () => defaultTimeWindows, + default: () => defaultTimeRange, + }, + options: { + type: Array, + required: false, + default: () => defaultTimeRanges, }, }, data() { return { - startDate: this.start, - endDate: this.end, + timeRange: this.value, + startDate: '', + endDate: '', }; }, computed: { @@ -67,6 +67,7 @@ export default { set(val) { // Attempt to set a formatted date if possible this.startDate = isDateTimePickerInputValid(val) ? stringToISODate(val) : val; + this.timeRange = null; }, }, endInput: { @@ -76,23 +77,48 @@ export default { set(val) { // Attempt to set a formatted date if possible this.endDate = isDateTimePickerInputValid(val) ? stringToISODate(val) : val; + this.timeRange = null; }, }, timeWindowText() { - const timeWindow = getTimeWindowKey({ start: this.start, end: this.end }, this.timeWindows); - if (timeWindow) { - return this.timeWindows[timeWindow].label; - } else if (isValidDate(this.start) && isValidDate(this.end)) { - return sprintf(__('%{start} to %{end}'), { - start: this.formatDate(this.start), - end: this.formatDate(this.end), - }); + try { + const timeRange = findTimeRange(this.value, this.options); + if (timeRange) { + return timeRange.label; + } + + const { start, end } = convertToFixedRange(this.value); + if (isValidDate(start) && isValidDate(end)) { + return sprintf(__('%{start} to %{end}'), { + start: this.formatDate(start), + end: this.formatDate(end), + }); + } + } catch { + return __('Invalid date range'); } return ''; }, }, + watch: { + value(newValue) { + const { start, end } = convertToFixedRange(newValue); + this.timeRange = this.value; + this.startDate = start; + this.endDate = end; + }, + }, mounted() { + try { + const { start, end } = convertToFixedRange(this.timeRange); + this.startDate = start; + this.endDate = end; + } catch { + // when dates cannot be parsed, emit error. + this.$emit(events.invalid); + } + // Validate on mounted, and trigger an update if needed if (!this.isValid) { this.$emit(events.invalid); @@ -102,21 +128,22 @@ export default { formatDate(date) { return truncateZerosInDateTime(ISODateToString(date)); }, - setTimeWindow(key) { - const { start, end } = getTimeRange(key, this.timeWindows); - this.startDate = start; - this.endDate = end; - - this.apply(); - }, closeDropdown() { this.$refs.dropdown.hide(); }, - apply() { - this.$emit(events.apply, { + isOptionActive(option) { + return isEqualTimeRanges(option, this.timeRange); + }, + setQuickRange(option) { + this.timeRange = option; + this.$emit(events.input, this.timeRange); + }, + setFixedRange() { + this.timeRange = convertToFixedRange({ start: this.startDate, end: this.endDate, }); + this.$emit(events.input, this.timeRange); }, }, }; @@ -146,7 +173,7 @@ export default { </div> <gl-form-group> <gl-button @click="closeDropdown">{{ __('Cancel') }}</gl-button> - <gl-button variant="success" :disabled="!isValid" @click="apply()"> + <gl-button variant="success" :disabled="!isValid" @click="setFixedRange()"> {{ __('Apply') }} </gl-button> </gl-form-group> @@ -155,19 +182,20 @@ export default { <template #label> <span class="gl-pl-5">{{ __('Quick range') }}</span> </template> + <gl-dropdown-item - v-for="(timeWindow, key) in timeWindows" - :key="key" - :active="timeWindow.label === timeWindowText" + v-for="(option, index) in options" + :key="index" + :active="isOptionActive(option)" active-class="active" - @click="setTimeWindow(key)" + @click="setQuickRange(option)" > <icon name="mobile-issue-close" class="align-bottom" - :class="{ invisible: timeWindow.label !== timeWindowText }" + :class="{ invisible: !isOptionActive(option) }" /> - {{ timeWindow.label }} + {{ option.label }} </gl-dropdown-item> </gl-form-group> </div> diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js index 685115b92dd..673d981cf07 100644 --- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js +++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_lib.js @@ -1,6 +1,5 @@ import dateformat from 'dateformat'; import { __ } from '~/locale'; -import { secondsToMilliseconds } from '~/lib/utils/datetime_utility'; /** * Valid strings for this regex are @@ -9,37 +8,30 @@ import { secondsToMilliseconds } from '~/lib/utils/datetime_utility'; const dateTimePickerRegex = /^(\d{4})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])(?: (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?$/; /** - * A key-value pair of "time windows". - * - * A time window is a representation of period of time that starts - * some time in past until now. Keys are only used for easy reference. - * - * It is represented as user friendly `label` and number of `seconds` - * to be substracted from now. + * Default time ranges for the date picker. + * @see app/assets/javascripts/lib/utils/datetime_range.js */ -export const defaultTimeWindows = { - thirtyMinutes: { +export const defaultTimeRanges = [ + { + duration: { seconds: 60 * 30 }, label: __('30 minutes'), - seconds: 60 * 30, }, - threeHours: { + { + duration: { seconds: 60 * 60 * 3 }, label: __('3 hours'), - seconds: 60 * 60 * 3, }, - eightHours: { + { + duration: { seconds: 60 * 60 * 8 }, label: __('8 hours'), - seconds: 60 * 60 * 8, default: true, }, - oneDay: { + { + duration: { seconds: 60 * 60 * 24 * 1 }, label: __('1 day'), - seconds: 60 * 60 * 24 * 1, }, - threeDays: { - label: __('3 days'), - seconds: 60 * 60 * 24 * 3, - }, -}; +]; + +export const defaultTimeRange = defaultTimeRanges.find(tr => tr.default); export const dateFormats = { ISODate: "yyyy-mm-dd'T'HH:MM:ss'Z'", @@ -68,46 +60,6 @@ export const isValidDate = dateString => { }; /** - * For a given time window key (e.g. `threeHours`) and key-value pair - * object of time windows. - * - * Returns a date time range with start and end. - * - * @param {String} timeWindowKey - A key in the object of time windows. - * @param {Object} timeWindows - A key-value pair of time windows, - * with a second duration and a label. - * @returns An object with time range, start and end dates, in ISO format. - */ -export const getTimeRange = (timeWindowKey, timeWindows = defaultTimeWindows) => { - let difference; - if (timeWindows[timeWindowKey]) { - difference = timeWindows[timeWindowKey].seconds; - } else { - const [defaultEntry] = Object.entries(timeWindows).filter( - ([, timeWindow]) => timeWindow.default, - ); - // find default time window - difference = defaultEntry[1].seconds; - } - - const end = Math.floor(Date.now() / 1000); // convert milliseconds to seconds - const start = end - difference; - - return { - start: new Date(secondsToMilliseconds(start)).toISOString(), - end: new Date(secondsToMilliseconds(end)).toISOString(), - }; -}; - -export const getTimeWindowKey = ({ start, end }, timeWindows = defaultTimeWindows) => - Object.entries(timeWindows).reduce((acc, [timeWindowKey, timeWindow]) => { - if (new Date(end) - new Date(start) === secondsToMilliseconds(timeWindow.seconds)) { - return timeWindowKey; - } - return acc; - }, null); - -/** * Convert the input in Time picker component to ISO date. * * @param {string} val |