Commit 50c50a8f authored by Miguel Rincon's avatar Miguel Rincon

Add time picker to logs page

Add the datepicker component to the logs page and
connect it to the Vuex store.

Fixes a few style issues in the component, so it can adapt to
more layouts.
parent 3c21e5e2
......@@ -149,7 +149,13 @@ export default {
};
</script>
<template>
<gl-dropdown :text="timeWindowText" class="date-time-picker" menu-class="date-time-picker-menu">
<gl-dropdown
:text="timeWindowText"
class="date-time-picker"
menu-class="date-time-picker-menu"
v-bind="$attrs"
toggle-class="w-100 text-truncate"
>
<div class="d-flex justify-content-between gl-p-2">
<gl-form-group
:label="__('Custom range')"
......
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
import { GlDropdown, GlDropdownItem, GlFormGroup, GlSearchBoxByClick, GlAlert } from '@gitlab/ui';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import { scrollDown } from '~/lib/utils/scroll_utils';
import LogControlButtons from './log_control_buttons.vue';
import { timeRanges, defaultTimeRange } from '~/monitoring/constants';
export default {
components: {
GlAlert,
......@@ -11,6 +14,7 @@ export default {
GlDropdownItem,
GlFormGroup,
GlSearchBoxByClick,
DateTimePicker,
LogControlButtons,
},
props: {
......@@ -37,12 +41,24 @@ export default {
data() {
return {
searchQuery: '',
selectedTimeRange: defaultTimeRange,
timeRanges,
isElasticStackCalloutDismissed: false,
};
},
computed: {
...mapState('environmentLogs', ['environments', 'timeWindow', 'logs', 'pods']),
...mapState('environmentLogs', ['environments', 'timeRange', 'logs', 'pods']),
...mapGetters('environmentLogs', ['trace']),
timeRangeModel: {
get() {
return this.timeRange.current;
},
set(val) {
this.setTimeRange(val);
},
},
showLoader() {
return this.logs.isLoading || !this.logs.isComplete;
},
......@@ -85,7 +101,7 @@ export default {
...mapActions('environmentLogs', [
'setInitData',
'setSearch',
'setTimeWindow',
'setTimeRange',
'showPodLogs',
'showEnvironment',
'fetchEnvironments',
......@@ -166,22 +182,13 @@ export default {
label-for="time-window-dropdown"
class="col-3 px-1"
>
<gl-dropdown
id="time-window-dropdown"
ref="time-window-dropdown"
<date-time-picker
ref="dateTimePicker"
v-model="timeRangeModel"
class="w-100 gl-h-32"
:disabled="disableAdvancedControls"
:text="timeWindow.options[timeWindow.current].label"
class="d-flex gl-h-32"
toggle-class="dropdown-menu-toggle"
>
<gl-dropdown-item
v-for="(option, key) in timeWindow.options"
:key="key"
@click="setTimeWindow(key)"
>
{{ option.label }}
</gl-dropdown-item>
</gl-dropdown>
:options="timeRanges"
/>
</gl-form-group>
<gl-form-group
id="search-fg"
......
import { __ } from '~/locale';
export const defaultTimeWindow = 'oneHour';
export const timeWindows = {
oneHour: {
label: __('1 hour'),
seconds: 60 * 60,
},
fourHours: {
label: __('4 hours'),
seconds: 60 * 60 * 4,
},
oneDay: {
label: __('1 day'),
seconds: 60 * 60 * 24,
},
twoDays: {
label: __('2 days'),
seconds: 60 * 60 * 24 * 3,
},
pastWeek: {
label: __('Past week'),
seconds: 60 * 60 * 24 * 7,
},
twoWeeks: {
label: __('2 weeks'),
seconds: 60 * 60 * 24 * 15,
},
};
......@@ -4,10 +4,17 @@ import httpStatusCodes from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
import flash from '~/flash';
import { s__ } from '~/locale';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
import * as types from './mutation_types';
import { getTimeRange } from '../utils';
import { timeWindows } from '../constants';
const flashTimeRangeWarning = () => {
flash(s__('Metrics|Invalid time range, please verify.'), 'warning');
};
const flashLogsError = () => {
flash(s__('Metrics|There was an error fetching the logs, please try again'));
};
const requestLogsUntilData = params =>
backOff((next, stop) => {
......@@ -39,8 +46,8 @@ export const setSearch = ({ dispatch, commit }, searchQuery) => {
dispatch('fetchLogs');
};
export const setTimeWindow = ({ dispatch, commit }, timeWindowKey) => {
commit(types.SET_TIME_WINDOW, timeWindowKey);
export const setTimeRange = ({ dispatch, commit }, timeRange) => {
commit(types.SET_TIME_RANGE, timeRange);
dispatch('fetchLogs');
};
......@@ -72,12 +79,14 @@ export const fetchLogs = ({ commit, state }) => {
search: state.search,
};
if (state.timeWindow.current) {
const { current } = state.timeWindow;
const { start, end } = getTimeRange(timeWindows[current].seconds);
params.start = start;
params.end = end;
if (state.timeRange.current) {
try {
const { start, end } = convertToFixedRange(state.timeRange.current);
params.start = start;
params.end = end;
} catch {
flashTimeRangeWarning();
}
}
commit(types.REQUEST_PODS_DATA);
......@@ -94,7 +103,7 @@ export const fetchLogs = ({ commit, state }) => {
.catch(() => {
commit(types.RECEIVE_PODS_DATA_ERROR);
commit(types.RECEIVE_LOGS_DATA_ERROR);
flash(s__('Metrics|There was an error fetching the logs, please try again'));
flashLogsError();
});
};
......
export const SET_PROJECT_ENVIRONMENT = 'SET_PROJECT_ENVIRONMENT';
export const SET_SEARCH = 'SET_SEARCH';
export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
export const SET_TIME_RANGE = 'SET_TIME_RANGE';
export const SET_CURRENT_POD_NAME = 'SET_CURRENT_POD_NAME';
export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA';
export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCCESS';
......@@ -10,7 +11,6 @@ export const REQUEST_LOGS_DATA = 'REQUEST_LOGS_DATA';
export const RECEIVE_LOGS_DATA_SUCCESS = 'RECEIVE_LOGS_DATA_SUCCESS';
export const RECEIVE_LOGS_DATA_ERROR = 'RECEIVE_LOGS_DATA_ERROR';
export const SET_CURRENT_POD_NAME = 'SET_CURRENT_POD_NAME';
export const REQUEST_PODS_DATA = 'REQUEST_PODS_DATA';
export const RECEIVE_PODS_DATA_SUCCESS = 'RECEIVE_PODS_DATA_SUCCESS';
export const RECEIVE_PODS_DATA_ERROR = 'RECEIVE_PODS_DATA_ERROR';
......@@ -7,8 +7,8 @@ export default {
},
/** Time Range data */
[types.SET_TIME_WINDOW](state, timeWindowKey) {
state.timeWindow.current = timeWindowKey;
[types.SET_TIME_RANGE](state, timeRange) {
state.timeRange.current = timeRange;
},
/** Environments data */
......
import { defaultTimeWindow, timeWindows } from '../constants';
import { timeRanges, defaultTimeRange } from '~/monitoring/constants';
export default () => ({
/**
......@@ -9,9 +9,9 @@ export default () => ({
/**
* Time range (Show last)
*/
timeWindow: {
options: { ...timeWindows },
current: defaultTimeWindow,
timeRange: {
options: timeRanges,
current: defaultTimeRange,
},
/**
......
......@@ -18,10 +18,6 @@
}
}
.dropdown-menu {
width: 300px;
}
.controllers {
@include build-controllers(16px, flex-end, true, 2);
}
......
---
title: Add time picker to logs page
merge_request: 23837
author:
type: added
import Vue from 'vue';
import { GlDropdown, GlDropdownItem, GlSearchBoxByClick } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import EnvironmentLogs from 'ee/logs/components/environment_logs.vue';
import { createStore } from 'ee/logs/stores';
......@@ -42,7 +43,7 @@ describe('EnvironmentLogs', () => {
const findEnvironmentsDropdown = () => wrapper.find('.js-environments-dropdown');
const findPodsDropdown = () => wrapper.find('.js-pods-dropdown');
const findSearchBar = () => wrapper.find('.js-logs-search');
const findTimeWindowDropdown = () => wrapper.find({ ref: 'time-window-dropdown' });
const findTimeRangePicker = () => wrapper.find({ ref: 'dateTimePicker' });
const findLogControlButtons = () => wrapper.find({ name: 'log-control-buttons-stub' });
const findLogTrace = () => wrapper.find('.js-log-trace');
......@@ -116,8 +117,8 @@ describe('EnvironmentLogs', () => {
expect(findSearchBar().exists()).toBe(true);
expect(findSearchBar().is(GlSearchBoxByClick)).toBe(true);
expect(findTimeWindowDropdown().exists()).toBe(true);
expect(findTimeWindowDropdown().is(GlDropdown)).toBe(true);
expect(findTimeRangePicker().exists()).toBe(true);
expect(findTimeRangePicker().is(DateTimePicker)).toBe(true);
// log trace
expect(findLogTrace().isEmpty()).toBe(false);
......@@ -169,7 +170,7 @@ describe('EnvironmentLogs', () => {
});
it('displays a disabled time window dropdown', () => {
expect(findTimeWindowDropdown().attributes('disabled')).toBe('true');
expect(findTimeRangePicker().attributes('disabled')).toBe('true');
});
it('does not update buttons state', () => {
......@@ -207,7 +208,7 @@ describe('EnvironmentLogs', () => {
it('displays a disabled search bar and time window dropdown', () => {
expect(findSearchBar().exists()).toBe(true);
expect(findSearchBar().attributes('disabled')).toBe('true');
expect(findTimeWindowDropdown().attributes('disabled')).toBe('true');
expect(findTimeRangePicker().attributes('disabled')).toBe('true');
});
});
......@@ -234,7 +235,7 @@ describe('EnvironmentLogs', () => {
});
it('displays an enabled time window dropdown', () => {
expect(findTimeWindowDropdown().attributes('disabled')).toBeFalsy();
expect(findTimeRangePicker().attributes('disabled')).toBeFalsy();
});
it('populates environments dropdown', () => {
......
......@@ -119,12 +119,19 @@ describe('Logs Store Mutations', () => {
});
});
describe('SET_TIME_WINDOW', () => {
it('sets a time window Key', () => {
const mockKey = 'fourHours';
mutations[types.SET_TIME_WINDOW](state, mockKey);
describe('SET_TIME_RANGE', () => {
it('sets a default range', () => {
expect(state.timeRange.current).toEqual(expect.any(Object));
});
it('sets a time range', () => {
const mockRange = {
start: '2020-01-10T18:00:00.000Z',
end: '2020-01-10T10:00:00.000Z',
};
mutations[types.SET_TIME_RANGE](state, mockRange);
expect(state.timeWindow.current).toEqual(mockKey);
expect(state.timeRange.current).toEqual(mockRange);
});
});
......
......@@ -649,9 +649,6 @@ msgstr ""
msgid "1st contribution!"
msgstr ""
msgid "2 days"
msgstr ""
msgid "2 weeks"
msgstr ""
......@@ -682,9 +679,6 @@ msgstr ""
msgid "30+ contributions"
msgstr ""
msgid "4 hours"
msgstr ""
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
......@@ -11991,6 +11985,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
msgid "Metrics|Invalid time range, please verify."
msgstr ""
msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
......@@ -13362,9 +13359,6 @@ msgstr ""
msgid "Past due"
msgstr ""
msgid "Past week"
msgstr ""
msgid "Paste a machine public key here. Read more about how to generate it %{link_start}here%{link_end}"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment