Commit f996f939 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '207912-implementing-filtered-search-dropdown-improvement' into 'master'

Log filters: Replace "form group header" with "dropdown header"

See merge request gitlab-org/gitlab!26635
parents 99b3ee82 04889cb8
...@@ -3,8 +3,10 @@ import { throttle } from 'lodash'; ...@@ -3,8 +3,10 @@ import { throttle } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { import {
GlSprintf, GlSprintf,
GlIcon,
GlAlert, GlAlert,
GlDropdown, GlDropdown,
GlDropdownHeader,
GlDropdownDivider, GlDropdownDivider,
GlDropdownItem, GlDropdownItem,
GlFormGroup, GlFormGroup,
...@@ -22,8 +24,10 @@ import { formatDate } from '../utils'; ...@@ -22,8 +24,10 @@ import { formatDate } from '../utils';
export default { export default {
components: { components: {
GlSprintf, GlSprintf,
GlIcon,
GlAlert, GlAlert,
GlDropdown, GlDropdown,
GlDropdownHeader,
GlDropdownDivider, GlDropdownDivider,
GlDropdownItem, GlDropdownItem,
GlFormGroup, GlFormGroup,
...@@ -124,6 +128,12 @@ export default { ...@@ -124,6 +128,12 @@ export default {
'fetchMoreLogsPrepend', 'fetchMoreLogsPrepend',
]), ]),
isCurrentEnvironment(envName) {
return envName === this.environments.current;
},
isCurrentPod(podName) {
return podName === this.pods.current;
},
topReached() { topReached() {
if (!this.logs.isLoading) { if (!this.logs.isLoading) {
this.fetchMoreLogsPrepend(); this.fetchMoreLogsPrepend();
...@@ -161,7 +171,6 @@ export default { ...@@ -161,7 +171,6 @@ export default {
<div class="row mx-n1"> <div class="row mx-n1">
<gl-form-group <gl-form-group
id="environments-dropdown-fg" id="environments-dropdown-fg"
:label="s__('Environments|Environment')"
label-size="sm" label-size="sm"
label-for="environments-dropdown" label-for="environments-dropdown"
class="col-3 px-1" class="col-3 px-1"
...@@ -173,18 +182,27 @@ export default { ...@@ -173,18 +182,27 @@ export default {
class="d-flex gl-h-32 js-environments-dropdown" class="d-flex gl-h-32 js-environments-dropdown"
toggle-class="dropdown-menu-toggle" toggle-class="dropdown-menu-toggle"
> >
<gl-dropdown-header class="text-center">
{{ s__('Environments|Select environment') }}
</gl-dropdown-header>
<gl-dropdown-item <gl-dropdown-item
v-for="env in environments.options" v-for="env in environments.options"
:key="env.id" :key="env.id"
@click="showEnvironment(env.name)" @click="showEnvironment(env.name)"
> >
{{ env.name }} <div class="d-flex">
<gl-icon
:class="{ invisible: !isCurrentEnvironment(env.name) }"
name="status_success_borderless"
/>
<div class="flex-grow-1">{{ env.name }}</div>
</div>
</gl-dropdown-item> </gl-dropdown-item>
</gl-dropdown> </gl-dropdown>
</gl-form-group> </gl-form-group>
<gl-form-group <gl-form-group
id="pods-dropdown-fg" id="pods-dropdown-fg"
:label="s__('Environments|Logs from')"
label-size="sm" label-size="sm"
label-for="pods-dropdown" label-for="pods-dropdown"
class="col-3 px-1" class="col-3 px-1"
...@@ -196,24 +214,58 @@ export default { ...@@ -196,24 +214,58 @@ export default {
class="d-flex gl-h-32 js-pods-dropdown" class="d-flex gl-h-32 js-pods-dropdown"
toggle-class="dropdown-menu-toggle" toggle-class="dropdown-menu-toggle"
> >
<gl-dropdown-header class="text-center">
{{ s__('Environments|Filter by pod') }}
</gl-dropdown-header>
<template v-if="advancedFeaturesEnabled"> <template v-if="advancedFeaturesEnabled">
<gl-dropdown-item key="all-pods" @click="showPodLogs(null)"> <gl-dropdown-item key="all-pods" @click="showPodLogs(null)">
{{ s__('Environments|All pods') }} <div class="d-flex">
<gl-icon
:class="{ invisible: !isCurrentPod(null) }"
name="status_success_borderless"
/>
<div class="flex-grow-1">{{ s__('Environments|All pods') }}</div>
</div>
</gl-dropdown-item> </gl-dropdown-item>
<gl-dropdown-divider /> <gl-dropdown-divider />
</template> </template>
<gl-dropdown-item v-if="!pods.options.length" :disabled="true">
<span class="text-muted">
{{ s__('Environments|No pods to display') }}
</span>
</gl-dropdown-item>
<gl-dropdown-item <gl-dropdown-item
v-for="podName in pods.options" v-for="podName in pods.options"
:key="podName" :key="podName"
class="text-nowrap"
@click="showPodLogs(podName)" @click="showPodLogs(podName)"
> >
{{ podName }} <div class="d-flex">
<gl-icon
:class="{ invisible: !isCurrentPod(podName) }"
name="status_success_borderless"
/>
<div class="flex-grow-1">{{ podName }}</div>
</div>
</gl-dropdown-item> </gl-dropdown-item>
</gl-dropdown> </gl-dropdown>
</gl-form-group> </gl-form-group>
<gl-form-group id="search-fg" label-size="sm" label-for="search" class="col-3 px-1">
<gl-search-box-by-click
v-model.trim="searchQuery"
:disabled="disableAdvancedControls"
:placeholder="s__('Environments|Search')"
class="js-logs-search"
type="search"
autofocus
@submit="setSearch(searchQuery)"
/>
</gl-form-group>
<gl-form-group <gl-form-group
id="dates-fg" id="dates-fg"
:label="s__('Environments|Show last')"
label-size="sm" label-size="sm"
label-for="time-window-dropdown" label-for="time-window-dropdown"
class="col-3 px-1" class="col-3 px-1"
...@@ -222,32 +274,16 @@ export default { ...@@ -222,32 +274,16 @@ export default {
ref="dateTimePicker" ref="dateTimePicker"
v-model="timeRangeModel" v-model="timeRangeModel"
class="w-100 gl-h-32" class="w-100 gl-h-32"
right
:disabled="disableAdvancedControls" :disabled="disableAdvancedControls"
:options="timeRanges" :options="timeRanges"
/> />
</gl-form-group> </gl-form-group>
<gl-form-group
id="search-fg"
:label="s__('Environments|Search')"
label-size="sm"
label-for="search"
class="col-3 px-1"
>
<gl-search-box-by-click
v-model.trim="searchQuery"
:disabled="disableAdvancedControls"
:placeholder="s__('Environments|Search')"
class="js-logs-search"
type="search"
autofocus
@submit="setSearch(searchQuery)"
/>
</gl-form-group>
</div> </div>
<log-control-buttons <log-control-buttons
ref="scrollButtons" ref="scrollButtons"
class="controllers align-self-end mb-1" class="controllers"
:scroll-down-button-disabled="scrollDownButtonDisabled" :scroll-down-button-disabled="scrollDownButtonDisabled"
@refresh="showPodLogs(pods.current)" @refresh="showPodLogs(pods.current)"
@scrollDown="scrollDown" @scrollDown="scrollDown"
......
...@@ -379,7 +379,7 @@ ...@@ -379,7 +379,7 @@
} }
.top-bar { .top-bar {
@include build-trace-top-bar($gl-line-height * 5); @include build-trace-top-bar($gl-line-height * 3);
position: relative; position: relative;
top: 0; top: 0;
......
---
title: Improve logs dropdown with more clear labels
merge_request: 26635
author:
type: added
...@@ -50,7 +50,7 @@ describe 'Environment > Pod Logs', :js do ...@@ -50,7 +50,7 @@ describe 'Environment > Pod Logs', :js do
page.within('.js-pods-dropdown') do page.within('.js-pods-dropdown') do
find(".dropdown-menu-toggle:not([disabled])").click find(".dropdown-menu-toggle:not([disabled])").click
dropdown_items = find(".dropdown-menu").all(".dropdown-item") dropdown_items = find(".dropdown-menu").all(".dropdown-item:not([disabled])")
expect(dropdown_items.size).to eq(1) expect(dropdown_items.size).to eq(1)
dropdown_items.each_with_index do |item, i| dropdown_items.each_with_index do |item, i|
......
...@@ -7723,6 +7723,9 @@ msgstr "" ...@@ -7723,6 +7723,9 @@ msgstr ""
msgid "Environments|Environments are places where code gets deployed, such as staging or production." msgid "Environments|Environments are places where code gets deployed, such as staging or production."
msgstr "" msgstr ""
msgid "Environments|Filter by pod"
msgstr ""
msgid "Environments|Install Elastic Stack on your cluster to enable advanced querying capabilities such as full text search." msgid "Environments|Install Elastic Stack on your cluster to enable advanced querying capabilities such as full text search."
msgstr "" msgstr ""
...@@ -7735,9 +7738,6 @@ msgstr "" ...@@ -7735,9 +7738,6 @@ msgstr ""
msgid "Environments|Learn more about stopping environments" msgid "Environments|Learn more about stopping environments"
msgstr "" msgstr ""
msgid "Environments|Logs from"
msgstr ""
msgid "Environments|Logs from %{start} to %{end}." msgid "Environments|Logs from %{start} to %{end}."
msgstr "" msgstr ""
...@@ -7753,6 +7753,9 @@ msgstr "" ...@@ -7753,6 +7753,9 @@ msgstr ""
msgid "Environments|No pod selected" msgid "Environments|No pod selected"
msgstr "" msgstr ""
msgid "Environments|No pods to display"
msgstr ""
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file." msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "" msgstr ""
...@@ -7792,10 +7795,10 @@ msgstr "" ...@@ -7792,10 +7795,10 @@ msgstr ""
msgid "Environments|Search" msgid "Environments|Search"
msgstr "" msgstr ""
msgid "Environments|Show all" msgid "Environments|Select environment"
msgstr "" msgstr ""
msgid "Environments|Show last" msgid "Environments|Show all"
msgstr "" msgstr ""
msgid "Environments|Stop" msgid "Environments|Stop"
......
import Vue from 'vue'; import Vue from 'vue';
import { GlSprintf, GlDropdown, GlDropdownItem, GlSearchBoxByClick } from '@gitlab/ui'; import { GlSprintf, GlIcon, GlDropdown, GlDropdownItem, GlSearchBoxByClick } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import EnvironmentLogs from '~/logs/components/environment_logs.vue'; import EnvironmentLogs from '~/logs/components/environment_logs.vue';
...@@ -45,6 +45,10 @@ describe('EnvironmentLogs', () => { ...@@ -45,6 +45,10 @@ describe('EnvironmentLogs', () => {
const findEnvironmentsDropdown = () => wrapper.find('.js-environments-dropdown'); const findEnvironmentsDropdown = () => wrapper.find('.js-environments-dropdown');
const findPodsDropdown = () => wrapper.find('.js-pods-dropdown'); const findPodsDropdown = () => wrapper.find('.js-pods-dropdown');
const findPodsDropdownItems = () =>
findPodsDropdown()
.findAll(GlDropdownItem)
.filter(itm => !itm.attributes('disabled'));
const findSearchBar = () => wrapper.find('.js-logs-search'); const findSearchBar = () => wrapper.find('.js-logs-search');
const findTimeRangePicker = () => wrapper.find({ ref: 'dateTimePicker' }); const findTimeRangePicker = () => wrapper.find({ ref: 'dateTimePicker' });
const findInfoAlert = () => wrapper.find('.js-elasticsearch-alert'); const findInfoAlert = () => wrapper.find('.js-elasticsearch-alert');
...@@ -179,7 +183,7 @@ describe('EnvironmentLogs', () => { ...@@ -179,7 +183,7 @@ describe('EnvironmentLogs', () => {
it('displays a disabled pods dropdown', () => { it('displays a disabled pods dropdown', () => {
expect(findPodsDropdown().attributes('disabled')).toBe('true'); expect(findPodsDropdown().attributes('disabled')).toBe('true');
expect(findPodsDropdown().findAll(GlDropdownItem).length).toBe(0); expect(findPodsDropdownItems()).toHaveLength(0);
}); });
it('displays a disabled search bar', () => { it('displays a disabled search bar', () => {
...@@ -296,8 +300,22 @@ describe('EnvironmentLogs', () => { ...@@ -296,8 +300,22 @@ describe('EnvironmentLogs', () => {
}); });
}); });
it('dropdown has one environment selected', () => {
const items = findEnvironmentsDropdown().findAll(GlDropdownItem);
mockEnvironments.forEach((env, i) => {
const item = items.at(i);
if (item.text() !== mockEnvName) {
expect(item.find(GlIcon).classes()).toContain('invisible');
} else {
// selected
expect(item.find(GlIcon).classes()).not.toContain('invisible');
}
});
});
it('populates pods dropdown', () => { it('populates pods dropdown', () => {
const items = findPodsDropdown().findAll(GlDropdownItem); const items = findPodsDropdownItems();
expect(findPodsDropdown().props('text')).toBe(mockPodName); expect(findPodsDropdown().props('text')).toBe(mockPodName);
expect(items.length).toBe(mockPods.length + 1); expect(items.length).toBe(mockPods.length + 1);
...@@ -313,6 +331,19 @@ describe('EnvironmentLogs', () => { ...@@ -313,6 +331,19 @@ describe('EnvironmentLogs', () => {
expect(getInfiniteScrollAttr('fetched-items')).toBe(mockTrace.length); expect(getInfiniteScrollAttr('fetched-items')).toBe(mockTrace.length);
}); });
it('dropdown has one pod selected', () => {
const items = findPodsDropdownItems();
mockPods.forEach((pod, i) => {
const item = items.at(i);
if (item.text() !== mockPodName) {
expect(item.find(GlIcon).classes()).toContain('invisible');
} else {
// selected
expect(item.find(GlIcon).classes()).not.toContain('invisible');
}
});
});
it('populates logs trace', () => { it('populates logs trace', () => {
const trace = findLogTrace(); const trace = findLogTrace();
expect(trace.text().split('\n').length).toBe(mockTrace.length); expect(trace.text().split('\n').length).toBe(mockTrace.length);
...@@ -341,7 +372,7 @@ describe('EnvironmentLogs', () => { ...@@ -341,7 +372,7 @@ describe('EnvironmentLogs', () => {
}); });
it('pod name, trace is refreshed', () => { it('pod name, trace is refreshed', () => {
const items = findPodsDropdown().findAll(GlDropdownItem); const items = findPodsDropdownItems();
const index = 2; // any pod const index = 2; // any pod
expect(dispatch).not.toHaveBeenCalledWith(`${module}/showPodLogs`, expect.anything()); expect(dispatch).not.toHaveBeenCalledWith(`${module}/showPodLogs`, expect.anything());
......
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