diff options
Diffstat (limited to 'app/assets/javascripts')
7 files changed, 128 insertions, 101 deletions
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue index 0d84798d690..838652f7210 100644 --- a/app/assets/javascripts/logs/components/environment_logs.vue +++ b/app/assets/javascripts/logs/components/environment_logs.vue @@ -89,10 +89,9 @@ export default { methods: { ...mapActions('environmentLogs', [ 'setInitData', - 'setSearch', - 'showPodLogs', 'showEnvironment', 'fetchEnvironments', + 'fetchLogs', 'fetchMoreLogsPrepend', 'dismissRequestEnvironmentsError', 'dismissInvalidTimeRangeWarning', @@ -191,13 +190,13 @@ export default { <log-advanced-filters v-if="showAdvancedFilters" ref="log-advanced-filters" - class="d-md-flex flex-grow-1" + class="d-md-flex flex-grow-1 min-width-0" :disabled="environments.isLoading" /> <log-simple-filters v-else ref="log-simple-filters" - class="d-md-flex flex-grow-1" + class="d-md-flex flex-grow-1 min-width-0" :disabled="environments.isLoading" /> @@ -205,7 +204,7 @@ export default { ref="scrollButtons" class="flex-grow-0 pr-2 mb-2 controllers" :scroll-down-button-disabled="scrollDownButtonDisabled" - @refresh="showPodLogs(pods.current)" + @refresh="fetchLogs()" @scrollDown="scrollDown" /> </div> diff --git a/app/assets/javascripts/logs/components/log_advanced_filters.vue b/app/assets/javascripts/logs/components/log_advanced_filters.vue index dfbd858bf18..49bb80b3bfd 100644 --- a/app/assets/javascripts/logs/components/log_advanced_filters.vue +++ b/app/assets/javascripts/logs/components/log_advanced_filters.vue @@ -1,25 +1,15 @@ <script> -import { s__ } from '~/locale'; -import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; import { mapActions, mapState } from 'vuex'; -import { - GlIcon, - GlDropdown, - GlDropdownHeader, - GlDropdownDivider, - GlDropdownItem, - GlSearchBoxByClick, -} from '@gitlab/ui'; +import { GlFilteredSearch } from '@gitlab/ui'; +import { __, s__ } from '~/locale'; +import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; import { timeRanges } from '~/vue_shared/constants'; +import { TOKEN_TYPE_POD_NAME } from '../constants'; +import TokenWithLoadingState from './tokens/token_with_loading_state.vue'; export default { components: { - GlIcon, - GlDropdown, - GlDropdownHeader, - GlDropdownDivider, - GlDropdownItem, - GlSearchBoxByClick, + GlFilteredSearch, DateTimePicker, }, props: { @@ -32,11 +22,10 @@ export default { data() { return { timeRanges, - searchQuery: '', }; }, computed: { - ...mapState('environmentLogs', ['timeRange', 'pods']), + ...mapState('environmentLogs', ['timeRange', 'pods', 'logs']), timeRangeModel: { get() { @@ -46,75 +35,56 @@ export default { this.setTimeRange(val); }, }, + /** + * Token options. + * + * Returns null when no pods are present, so suggestions are displayed in the token + */ + podOptions() { + if (this.pods.options.length) { + return this.pods.options.map(podName => ({ value: podName, title: podName })); + } + return null; + }, - podDropdownText() { - return this.pods.current || s__('Environments|All pods'); + tokens() { + return [ + { + icon: 'pod', + type: TOKEN_TYPE_POD_NAME, + title: s__('Environments|Pod name'), + token: TokenWithLoadingState, + operators: [{ value: '=', description: __('is'), default: 'true' }], + unique: true, + options: this.podOptions, + loading: this.logs.isLoading, + noOptionsText: s__('Environments|No pods to display'), + }, + ]; }, }, methods: { - ...mapActions('environmentLogs', ['setSearch', 'showPodLogs', 'setTimeRange']), - isCurrentPod(podName) { - return podName === this.pods.current; + ...mapActions('environmentLogs', ['showFilteredLogs', 'setTimeRange']), + + filteredSearchSubmit(filters) { + this.showFilteredLogs(filters); }, }, }; </script> <template> <div> - <gl-dropdown - ref="podsDropdown" - :text="podDropdownText" - :disabled="disabled" - class="mb-2 gl-h-32 pr-2 d-flex d-md-block flex-grow-0 qa-pods-dropdown" - > - <gl-dropdown-header class="text-center"> - {{ s__('Environments|Filter by pod') }} - </gl-dropdown-header> - - <gl-dropdown-item v-if="!pods.options.length" disabled> - <span ref="noPodsMsg" class="text-muted"> - {{ s__('Environments|No pods to display') }} - </span> - </gl-dropdown-item> - - <template v-else> - <gl-dropdown-item ref="allPodsOption" key="all-pods" @click="showPodLogs(null)"> - <div class="d-flex"> - <gl-icon - :class="{ invisible: pods.current !== null }" - name="status_success_borderless" - /> - <div class="flex-grow-1">{{ s__('Environments|All pods') }}</div> - </div> - </gl-dropdown-item> - <gl-dropdown-divider /> - <gl-dropdown-item - v-for="podName in pods.options" - :key="podName" - class="text-nowrap" - @click="showPodLogs(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> - </template> - </gl-dropdown> - - <gl-search-box-by-click - ref="searchBox" - v-model.trim="searchQuery" - :disabled="disabled" - :placeholder="s__('Environments|Search')" - class="mb-2 pr-2 flex-grow-1" - type="search" - autofocus - @submit="setSearch(searchQuery)" - /> + <div class="mb-2 pr-2 flex-grow-1 min-width-0"> + <gl-filtered-search + :placeholder="__('Search')" + :clear-button-title="__('Clear')" + :close-button-title="__('Close')" + class="gl-h-32" + :disabled="disabled || logs.isLoading" + :available-tokens="tokens" + @submit="filteredSearchSubmit" + /> + </div> <date-time-picker ref="dateTimePicker" diff --git a/app/assets/javascripts/logs/components/tokens/token_with_loading_state.vue b/app/assets/javascripts/logs/components/tokens/token_with_loading_state.vue new file mode 100644 index 00000000000..f8ce704942b --- /dev/null +++ b/app/assets/javascripts/logs/components/tokens/token_with_loading_state.vue @@ -0,0 +1,30 @@ +<script> +import { GlFilteredSearchToken, GlLoadingIcon } from '@gitlab/ui'; + +export default { + components: { + GlFilteredSearchToken, + GlLoadingIcon, + }, + inheritAttrs: false, + props: { + config: { + type: Object, + required: true, + }, + }, +}; +</script> + +<template> + <gl-filtered-search-token :config="config" v-bind="{ ...$attrs }" v-on="$listeners"> + <template #suggestions> + <div class="m-1"> + <gl-loading-icon v-if="config.loading" /> + <div v-else class="py-1 px-2 text-muted"> + {{ config.noOptionsText }} + </div> + </div> + </template> + </gl-filtered-search-token> +</template> diff --git a/app/assets/javascripts/logs/constants.js b/app/assets/javascripts/logs/constants.js new file mode 100644 index 00000000000..450b83f4827 --- /dev/null +++ b/app/assets/javascripts/logs/constants.js @@ -0,0 +1,3 @@ +export const dateFormatMask = 'UTC:mmm dd HH:MM:ss.l"Z"'; + +export const TOKEN_TYPE_POD_NAME = 'TOKEN_TYPE_POD_NAME'; diff --git a/app/assets/javascripts/logs/stores/actions.js b/app/assets/javascripts/logs/stores/actions.js index be847108a49..a86d3c775a9 100644 --- a/app/assets/javascripts/logs/stores/actions.js +++ b/app/assets/javascripts/logs/stores/actions.js @@ -2,6 +2,7 @@ import { backOff } from '~/lib/utils/common_utils'; import httpStatusCodes from '~/lib/utils/http_status'; import axios from '~/lib/utils/axios_utils'; import { convertToFixedRange } from '~/lib/utils/datetime_range'; +import { TOKEN_TYPE_POD_NAME } from '../constants'; import * as types from './mutation_types'; @@ -49,19 +50,42 @@ const requestLogsUntilData = ({ commit, state }) => { return requestUntilData(logs_api_path, params); }; +/** + * Converts filters emitted by the component, e.g. a filterered-search + * to parameters to be applied to the filters of the store + * @param {Array} filters - List of strings or objects to filter by. + * @returns {Object} - An object with `search` and `podName` keys. + */ +const filtersToParams = (filters = []) => { + // Strings become part of the `search` + const search = filters + .filter(f => typeof f === 'string') + .join(' ') + .trim(); + + // null podName to show all pods + const podName = filters.find(f => f?.type === TOKEN_TYPE_POD_NAME)?.value?.data ?? null; + + return { search, podName }; +}; + export const setInitData = ({ commit }, { timeRange, environmentName, podName }) => { commit(types.SET_TIME_RANGE, timeRange); commit(types.SET_PROJECT_ENVIRONMENT, environmentName); commit(types.SET_CURRENT_POD_NAME, podName); }; -export const showPodLogs = ({ dispatch, commit }, podName) => { +export const showFilteredLogs = ({ dispatch, commit }, filters = []) => { + const { podName, search } = filtersToParams(filters); + commit(types.SET_CURRENT_POD_NAME, podName); + commit(types.SET_SEARCH, search); + dispatch('fetchLogs'); }; -export const setSearch = ({ dispatch, commit }, searchQuery) => { - commit(types.SET_SEARCH, searchQuery); +export const showPodLogs = ({ dispatch, commit }, podName) => { + commit(types.SET_CURRENT_POD_NAME, podName); dispatch('fetchLogs'); }; diff --git a/app/assets/javascripts/logs/utils.js b/app/assets/javascripts/logs/utils.js index 30213dbc130..8479eeb3b59 100644 --- a/app/assets/javascripts/logs/utils.js +++ b/app/assets/javascripts/logs/utils.js @@ -1,7 +1,6 @@ import { secondsToMilliseconds } from '~/lib/utils/datetime_utility'; import dateFormat from 'dateformat'; - -const dateFormatMask = 'UTC:mmm dd HH:MM:ss.l"Z"'; +import { dateFormatMask } from './constants'; /** * Returns a time range (`start`, `end`) where `start` is the diff --git a/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue b/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue index adcacf8a1b0..d76c6d9d681 100644 --- a/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue +++ b/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue @@ -36,7 +36,7 @@ export default { <template> <div> - <div> + <div class="border-bottom pb-4"> <h3>{{ s__('StaticSiteEditor|Success!') }}</h3> <p> {{ @@ -45,35 +45,37 @@ export default { ) }} </p> - <div> + <div class="d-flex justify-content-end"> <gl-new-button ref="returnToSiteButton" :href="returnUrl">{{ s__('StaticSiteEditor|Return to site') }}</gl-new-button> - <gl-new-button ref="mergeRequestButton" :href="mergeRequest.url" variant="info">{{ - s__('StaticSiteEditor|View merge request') - }}</gl-new-button> + <gl-new-button + ref="mergeRequestButton" + class="ml-2" + :href="mergeRequest.url" + variant="success" + >{{ s__('StaticSiteEditor|View merge request') }}</gl-new-button + > </div> </div> - <hr /> - - <div> + <div class="pt-2"> <h4>{{ s__('StaticSiteEditor|Summary of changes') }}</h4> <ul> <li> - {{ s__('StaticSiteEditor|A new branch was created:') }} + {{ s__('StaticSiteEditor|You created a new branch:') }} <gl-link ref="branchLink" :href="branch.url">{{ branch.label }}</gl-link> </li> <li> - {{ s__('StaticSiteEditor|Your changes were committed to it:') }} - <gl-link ref="commitLink" :href="commit.url">{{ commit.label }}</gl-link> - </li> - <li> - {{ s__('StaticSiteEditor|A merge request was created:') }} + {{ s__('StaticSiteEditor|You created a merge request:') }} <gl-link ref="mergeRequestLink" :href="mergeRequest.url">{{ mergeRequest.label }}</gl-link> </li> + <li> + {{ s__('StaticSiteEditor|You added a commit:') }} + <gl-link ref="commitLink" :href="commit.url">{{ commit.label }}</gl-link> + </li> </ul> </div> </div> |