diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-24 18:07:55 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-24 18:07:55 +0000 |
commit | 603c7d4cac5e28bc1c75e50c23ed2cbe56f1aafc (patch) | |
tree | 907f5b8ee1b6f5aad396e95e3327a08400b9e8ea /app/assets/javascripts | |
parent | 120f4aaedc8fe830a3f572491d240d8ee6addefb (diff) | |
download | gitlab-ce-603c7d4cac5e28bc1c75e50c23ed2cbe56f1aafc.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
22 files changed, 301 insertions, 207 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 022d79ecf49..14381f63e4b 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -44,7 +44,6 @@ const Api = { mergeRequestsPipeline: '/api/:version/projects/:id/merge_requests/:merge_request_iid/pipelines', adminStatisticsPath: '/api/:version/application/statistics', pipelineSinglePath: '/api/:version/projects/:id/pipelines/:pipeline_id', - lsifPath: '/api/:version/projects/:id/commits/:commit_id/lsif/info', environmentsPath: '/api/:version/projects/:id/environments', group(groupId, callback) { @@ -474,14 +473,6 @@ const Api = { return axios.get(url); }, - lsifData(projectPath, commitId, paths) { - const url = Api.buildUrl(this.lsifPath) - .replace(':id', encodeURIComponent(projectPath)) - .replace(':commit_id', commitId); - - return axios.get(url, { params: { paths } }); - }, - environments(id) { const url = Api.buildUrl(this.environmentsPath).replace(':id', encodeURIComponent(id)); return axios.get(url); diff --git a/app/assets/javascripts/code_navigation/components/app.vue b/app/assets/javascripts/code_navigation/components/app.vue index 0e5f1f0485d..0e0160b9832 100644 --- a/app/assets/javascripts/code_navigation/components/app.vue +++ b/app/assets/javascripts/code_navigation/components/app.vue @@ -7,7 +7,7 @@ export default { Popover, }, computed: { - ...mapState(['currentDefinition', 'currentDefinitionPosition']), + ...mapState(['currentDefinition', 'currentDefinitionPosition', 'definitionPathPrefix']), }, mounted() { this.blobViewer = document.querySelector('.blob-viewer'); @@ -39,5 +39,6 @@ export default { v-if="currentDefinition" :position="currentDefinitionPosition" :data="currentDefinition" + :definition-path-prefix="definitionPathPrefix" /> </template> diff --git a/app/assets/javascripts/code_navigation/components/popover.vue b/app/assets/javascripts/code_navigation/components/popover.vue index d5bbe430fcd..f216a4c6e6f 100644 --- a/app/assets/javascripts/code_navigation/components/popover.vue +++ b/app/assets/javascripts/code_navigation/components/popover.vue @@ -14,6 +14,10 @@ export default { type: Object, required: true, }, + definitionPathPrefix: { + type: String, + required: true, + }, }, data() { return { @@ -27,6 +31,11 @@ export default { top: `${this.position.y + this.position.height}px`, }; }, + definitionPath() { + return ( + this.data.definition_path && `${this.definitionPathPrefix}/${this.data.definition_path}` + ); + }, }, watch: { position: { @@ -67,8 +76,8 @@ export default { {{ hover.value }} </p> </div> - <div v-if="data.definition_url" class="popover-body"> - <gl-button :href="data.definition_url" target="_blank" class="w-100" variant="default"> + <div v-if="definitionPath" class="popover-body"> + <gl-button :href="definitionPath" target="_blank" class="w-100" variant="default"> {{ __('Go to definition') }} </gl-button> </div> diff --git a/app/assets/javascripts/code_navigation/store/actions.js b/app/assets/javascripts/code_navigation/store/actions.js index 5220b1215b8..9b607023f39 100644 --- a/app/assets/javascripts/code_navigation/store/actions.js +++ b/app/assets/javascripts/code_navigation/store/actions.js @@ -1,4 +1,4 @@ -import api from '~/api'; +import axios from '~/lib/utils/axios_utils'; import * as types from './mutation_types'; import { getCurrentHoverElement, setCurrentHoverElement, addInteractionClass } from '../utils'; @@ -12,11 +12,10 @@ export default { fetchData({ commit, dispatch, state }) { commit(types.REQUEST_DATA); - api - .lsifData(state.projectPath, state.commitId, [state.blobPath]) + axios + .get(state.codeNavUrl) .then(({ data }) => { - const dataForPath = data[state.blobPath]; - const normalizedData = dataForPath.reduce((acc, d) => { + const normalizedData = data.reduce((acc, d) => { if (d.hover) { acc[`${d.start_line}:${d.start_char}`] = d; addInteractionClass(d); diff --git a/app/assets/javascripts/code_navigation/store/mutations.js b/app/assets/javascripts/code_navigation/store/mutations.js index bb833a5adbc..febb7afe2f8 100644 --- a/app/assets/javascripts/code_navigation/store/mutations.js +++ b/app/assets/javascripts/code_navigation/store/mutations.js @@ -1,10 +1,9 @@ import * as types from './mutation_types'; export default { - [types.SET_INITIAL_DATA](state, { projectPath, commitId, blobPath }) { - state.projectPath = projectPath; - state.commitId = commitId; - state.blobPath = blobPath; + [types.SET_INITIAL_DATA](state, { codeNavUrl, definitionPathPrefix }) { + state.codeNavUrl = codeNavUrl; + state.definitionPathPrefix = definitionPathPrefix; }, [types.REQUEST_DATA](state) { state.loading = true; diff --git a/app/assets/javascripts/ide/components/branches/search_list.vue b/app/assets/javascripts/ide/components/branches/search_list.vue index 31f1dec43ad..76821bcd986 100644 --- a/app/assets/javascripts/ide/components/branches/search_list.vue +++ b/app/assets/javascripts/ide/components/branches/search_list.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapState } from 'vuex'; -import _ from 'underscore'; +import { debounce } from 'lodash'; import { GlLoadingIcon } from '@gitlab/ui'; import Icon from '~/vue_shared/components/icon.vue'; import Item from './item.vue'; @@ -39,7 +39,7 @@ export default { loadBranches() { this.fetchBranches({ search: this.search }); }, - searchBranches: _.debounce(function debounceSearch() { + searchBranches: debounce(function debounceSearch() { this.loadBranches(); }, 250), focusSearch() { diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue index 2581c3e9928..beff95eb47b 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue @@ -1,5 +1,5 @@ <script> -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import { mapState, mapGetters, createNamespacedHelpers } from 'vuex'; import { sprintf, s__ } from '~/locale'; import consts from '../../stores/modules/commit/constants'; @@ -22,7 +22,7 @@ export default { commitToCurrentBranchText() { return sprintf( s__('IDE|Commit to %{branchName} branch'), - { branchName: `<strong class="monospace">${_.escape(this.currentBranchId)}</strong>` }, + { branchName: `<strong class="monospace">${esc(this.currentBranchId)}</strong>` }, false, ); }, diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue index 7710bfb49ec..504391ffdc7 100644 --- a/app/assets/javascripts/ide/components/jobs/detail.vue +++ b/app/assets/javascripts/ide/components/jobs/detail.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapState } from 'vuex'; -import _ from 'underscore'; +import { throttle } from 'lodash'; import { __ } from '../../../locale'; import tooltip from '../../../vue_shared/directives/tooltip'; import Icon from '../../../vue_shared/components/icon.vue'; @@ -53,7 +53,7 @@ export default { this.$refs.buildTrace.scrollTo(0, 0); } }, - scrollBuildLog: _.throttle(function buildLogScrollDebounce() { + scrollBuildLog: throttle(function buildLogScrollDebounce() { const { scrollTop } = this.$refs.buildTrace; const { offsetHeight, scrollHeight } = this.$refs.buildTrace; diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue index 5a8face062b..15c08988977 100644 --- a/app/assets/javascripts/ide/components/merge_requests/list.vue +++ b/app/assets/javascripts/ide/components/merge_requests/list.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapState } from 'vuex'; -import _ from 'underscore'; +import { debounce } from 'lodash'; import { GlLoadingIcon } from '@gitlab/ui'; import { __ } from '~/locale'; import Icon from '~/vue_shared/components/icon.vue'; @@ -59,7 +59,7 @@ export default { loadMergeRequests() { this.fetchMergeRequests({ type: this.type, search: this.search }); }, - searchMergeRequests: _.debounce(function debounceSearch() { + searchMergeRequests: debounce(function debounceSearch() { this.loadMergeRequests(); }, 250), onSearchFocus() { diff --git a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue index 7f65d089148..8adf0122fb4 100644 --- a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue +++ b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue @@ -1,6 +1,5 @@ <script> import { mapActions, mapState } from 'vuex'; -import _ from 'underscore'; import tooltip from '~/vue_shared/directives/tooltip'; import Icon from '~/vue_shared/components/icon.vue'; import ResizablePanel from '../resizable_panel.vue'; @@ -55,7 +54,7 @@ export default { return this.extensionTabs.filter(tab => tab.show); }, tabViews() { - return _.flatten(this.tabs.map(tab => tab.views)); + return this.tabs.map(tab => tab.views).flat(); }, aliveTabViews() { return this.tabViews.filter(view => this.isAliveView(view.name)); diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue index 3a63fc32639..343b0b6e90c 100644 --- a/app/assets/javascripts/ide/components/pipelines/list.vue +++ b/app/assets/javascripts/ide/components/pipelines/list.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import { GlLoadingIcon } from '@gitlab/ui'; import { sprintf, __ } from '../../../locale'; import Icon from '../../../vue_shared/components/icon.vue'; @@ -35,7 +35,7 @@ export default { return sprintf( __('You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}.'), { - linkStart: `<a href="${_.escape(this.currentProject.web_url)}/-/ci/lint">`, + linkStart: `<a href="${esc(this.currentProject.web_url)}/-/ci/lint">`, linkEnd: '</a>', }, false, diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue index aa8d932da6e..86a773499bc 100644 --- a/app/assets/javascripts/ide/components/preview/clientside.vue +++ b/app/assets/javascripts/ide/components/preview/clientside.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; -import _ from 'underscore'; +import { isEmpty } from 'lodash'; import { Manager } from 'smooshpack'; import { listen } from 'codesandbox-api'; import { GlLoadingIcon } from '@gitlab/ui'; @@ -78,7 +78,7 @@ export default { .then(() => this.initPreview()); }, beforeDestroy() { - if (!_.isEmpty(this.manager)) { + if (!isEmpty(this.manager)) { this.manager.listener(); } this.manager = {}; @@ -125,7 +125,7 @@ export default { clearTimeout(this.timeout); this.timeout = setTimeout(() => { - if (_.isEmpty(this.manager)) { + if (isEmpty(this.manager)) { this.initPreview(); return; diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js index 9e9d9df8f82..55a0dd848c8 100644 --- a/app/assets/javascripts/ide/index.js +++ b/app/assets/javascripts/ide/index.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import { mapActions } from 'vuex'; -import _ from 'underscore'; import Translate from '~/vue_shared/translate'; +import { identity } from 'lodash'; import ide from './components/ide.vue'; import store from './stores'; import router from './ide_router'; @@ -31,7 +31,7 @@ Vue.use(Translate); export function initIde(el, options = {}) { if (!el) return null; - const { rootComponent = ide, extendStore = _.identity } = options; + const { rootComponent = ide, extendStore = identity } = options; return new Vue({ el, diff --git a/app/assets/javascripts/ide/lib/diff/controller.js b/app/assets/javascripts/ide/lib/diff/controller.js index 046e562ba2b..234a7f903a1 100644 --- a/app/assets/javascripts/ide/lib/diff/controller.js +++ b/app/assets/javascripts/ide/lib/diff/controller.js @@ -1,5 +1,5 @@ import { Range } from 'monaco-editor'; -import { throttle } from 'underscore'; +import { throttle } from 'lodash'; import DirtyDiffWorker from './diff_worker'; import Disposable from '../common/disposable'; diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js index 3d729463cb4..3aff4d30d81 100644 --- a/app/assets/javascripts/ide/lib/editor.js +++ b/app/assets/javascripts/ide/lib/editor.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { debounce } from 'lodash'; import { editor as monacoEditor, KeyCode, KeyMod } from 'monaco-editor'; import store from '../stores'; import DecorationsController from './decorations/controller'; @@ -38,7 +38,7 @@ export default class Editor { setupThemes(); - this.debouncedUpdate = _.debounce(() => { + this.debouncedUpdate = debounce(() => { this.updateDimensions(); }, 200); } diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js index ddc0925efb9..04cf0ad53d5 100644 --- a/app/assets/javascripts/ide/stores/actions.js +++ b/app/assets/javascripts/ide/stores/actions.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import Vue from 'vue'; -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import { __, sprintf } from '~/locale'; import { visitUrl } from '~/lib/utils/url_utility'; import flash from '~/flash'; @@ -296,7 +296,7 @@ export const getBranchData = ({ commit, state }, { projectId, branchId, force = sprintf( __('Branch not loaded - %{branchId}'), { - branchId: `<strong>${_.escape(projectId)}/${_.escape(branchId)}</strong>`, + branchId: `<strong>${esc(projectId)}/${esc(branchId)}</strong>`, }, false, ), diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js index 62084892d13..0b168009847 100644 --- a/app/assets/javascripts/ide/stores/actions/project.js +++ b/app/assets/javascripts/ide/stores/actions/project.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import flash from '~/flash'; import { __, sprintf } from '~/locale'; import service from '../../services'; @@ -73,7 +73,7 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => { text: sprintf( __("Branch %{branchName} was not found in this project's repository."), { - branchName: `<strong>${_.escape(branchId)}</strong>`, + branchName: `<strong>${esc(branchId)}</strong>`, }, false, ), @@ -154,7 +154,7 @@ export const openBranch = ({ dispatch, state, getters }, { projectId, branchId, sprintf( __('An error occurred while getting files for - %{branchId}'), { - branchId: `<strong>${_.escape(projectId)}/${_.escape(branchId)}</strong>`, + branchId: `<strong>${esc(projectId)}/${esc(branchId)}</strong>`, }, false, ), diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js index 828e4ed5eb9..7d48f0adc4c 100644 --- a/app/assets/javascripts/ide/stores/actions/tree.js +++ b/app/assets/javascripts/ide/stores/actions/tree.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { defer } from 'lodash'; import { __ } from '../../../locale'; import service from '../../services'; import * as types from '../mutation_types'; @@ -71,7 +71,7 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) => // Defer setting the directory data because this triggers some intense rendering. // The entries is all we need to load the file editor. - _.defer(() => dispatch('setDirectoryData', { projectId, branchId, treeList })); + defer(() => dispatch('setDirectoryData', { projectId, branchId, treeList })); resolve(); }) diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue index 92d4be81c75..70b3af8dc75 100644 --- a/app/assets/javascripts/logs/components/environment_logs.vue +++ b/app/assets/javascripts/logs/components/environment_logs.vue @@ -7,17 +7,15 @@ import { GlAlert, GlDropdown, GlDropdownHeader, - GlDropdownDivider, GlDropdownItem, - GlFormGroup, - GlSearchBoxByClick, GlInfiniteScroll, } from '@gitlab/ui'; -import { s__ } from '~/locale'; -import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; + +import LogSimpleFilters from './log_simple_filters.vue'; +import LogAdvancedFilters from './log_advanced_filters.vue'; import LogControlButtons from './log_control_buttons.vue'; -import { timeRanges, defaultTimeRange } from '~/vue_shared/constants'; +import { defaultTimeRange } from '~/vue_shared/constants'; import { timeRangeFromUrl } from '~/monitoring/utils'; import { formatDate } from '../utils'; @@ -28,12 +26,10 @@ export default { GlAlert, GlDropdown, GlDropdownHeader, - GlDropdownDivider, GlDropdownItem, - GlFormGroup, - GlSearchBoxByClick, GlInfiniteScroll, - DateTimePicker, + LogSimpleFilters, + LogAdvancedFilters, LogControlButtons, }, filters: { @@ -63,49 +59,22 @@ export default { traceHeight: 600, data() { return { - searchQuery: '', - timeRanges, isElasticStackCalloutDismissed: false, scrollDownButtonDisabled: true, }; }, computed: { ...mapState('environmentLogs', ['environments', 'timeRange', 'logs', 'pods']), - ...mapGetters('environmentLogs', ['trace']), - - timeRangeModel: { - get() { - return this.timeRange.selected; - }, - set(val) { - this.setTimeRange(val); - }, - }, + ...mapGetters('environmentLogs', ['trace', 'showAdvancedFilters']), showLoader() { return this.logs.isLoading; }, - advancedFeaturesEnabled() { - const environment = this.environments.options.find( - ({ name }) => name === this.environments.current, - ); - return environment && environment.enable_advanced_logs_querying; - }, - disableAdvancedControls() { - return this.environments.isLoading || !this.advancedFeaturesEnabled; - }, shouldShowElasticStackCallout() { - return !this.isElasticStackCalloutDismissed && this.disableAdvancedControls; - }, - - podDropdownText() { - if (this.pods.current) { - return this.pods.current; - } else if (this.advancedFeaturesEnabled) { - // "All pods" is a valid option when advanced querying is available - return s__('Environments|All pods'); - } - return s__('Environments|No pod selected'); + return ( + !this.isElasticStackCalloutDismissed && + (this.environments.isLoading || !this.showAdvancedFilters) + ); }, }, mounted() { @@ -121,7 +90,6 @@ export default { ...mapActions('environmentLogs', [ 'setInitData', 'setSearch', - 'setTimeRange', 'showPodLogs', 'showEnvironment', 'fetchEnvironments', @@ -131,9 +99,6 @@ export default { isCurrentEnvironment(envName) { return envName === this.environments.current; }, - isCurrentPod(podName) { - return podName === this.pods.current; - }, topReached() { if (!this.logs.isLoading) { this.fetchMoreLogsPrepend(); @@ -167,123 +132,49 @@ export default { </strong> </a> </gl-alert> - <div class="top-bar js-top-bar d-flex"> - <div class="row mx-n1"> - <gl-form-group - id="environments-dropdown-fg" - label-size="sm" - label-for="environments-dropdown" - class="col-3 px-1" + <div class="top-bar d-md-flex border bg-secondary-50 pt-2 pr-1 pb-0 pl-2"> + <div class="flex-grow-0"> + <gl-dropdown + id="environments-dropdown" + :text="environments.current" + :disabled="environments.isLoading" + class="mb-2 gl-h-32 pr-2 d-flex d-md-block js-environments-dropdown" > - <gl-dropdown - id="environments-dropdown" - :text="environments.current" - :disabled="environments.isLoading" - class="d-flex gl-h-32 js-environments-dropdown" - toggle-class="dropdown-menu-toggle" + <gl-dropdown-header class="text-center"> + {{ s__('Environments|Select environment') }} + </gl-dropdown-header> + <gl-dropdown-item + v-for="env in environments.options" + :key="env.id" + @click="showEnvironment(env.name)" > - <gl-dropdown-header class="text-center"> - {{ s__('Environments|Select environment') }} - </gl-dropdown-header> - <gl-dropdown-item - v-for="env in environments.options" - :key="env.id" - @click="showEnvironment(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> - </gl-form-group> - - <gl-form-group - id="pods-dropdown-fg" - label-size="sm" - label-for="pods-dropdown" - class="col-3 px-1" - > - <gl-dropdown - id="pods-dropdown" - :text="podDropdownText" - :disabled="environments.isLoading" - class="d-flex gl-h-32 js-pods-dropdown" - toggle-class="dropdown-menu-toggle" - > - <gl-dropdown-header class="text-center"> - {{ s__('Environments|Filter by pod') }} - </gl-dropdown-header> - - <template v-if="advancedFeaturesEnabled"> - <gl-dropdown-item key="all-pods" @click="showPodLogs(null)"> - <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-divider /> - </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 - 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> - </gl-dropdown> - </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 - id="dates-fg" - label-size="sm" - label-for="time-window-dropdown" - class="col-3 px-1" - > - <date-time-picker - ref="dateTimePicker" - v-model="timeRangeModel" - class="w-100 gl-h-32" - right - :disabled="disableAdvancedControls" - :options="timeRanges" - /> - </gl-form-group> + <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> </div> + <log-advanced-filters + v-if="showAdvancedFilters" + ref="log-advanced-filters" + class="d-md-flex flex-grow-1" + :disabled="environments.isLoading" + /> + <log-simple-filters + v-else + ref="log-simple-filters" + class="d-md-flex flex-grow-1" + :disabled="environments.isLoading" + /> + <log-control-buttons ref="scrollButtons" - class="controllers" + class="flex-grow-0 pr-2 mb-2 controllers" :scroll-down-button-disabled="scrollDownButtonDisabled" @refresh="showPodLogs(pods.current)" @scrollDown="scrollDown" diff --git a/app/assets/javascripts/logs/components/log_advanced_filters.vue b/app/assets/javascripts/logs/components/log_advanced_filters.vue new file mode 100644 index 00000000000..dfbd858bf18 --- /dev/null +++ b/app/assets/javascripts/logs/components/log_advanced_filters.vue @@ -0,0 +1,128 @@ +<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 { timeRanges } from '~/vue_shared/constants'; + +export default { + components: { + GlIcon, + GlDropdown, + GlDropdownHeader, + GlDropdownDivider, + GlDropdownItem, + GlSearchBoxByClick, + DateTimePicker, + }, + props: { + disabled: { + type: Boolean, + required: false, + default: false, + }, + }, + data() { + return { + timeRanges, + searchQuery: '', + }; + }, + computed: { + ...mapState('environmentLogs', ['timeRange', 'pods']), + + timeRangeModel: { + get() { + return this.timeRange.selected; + }, + set(val) { + this.setTimeRange(val); + }, + }, + + podDropdownText() { + return this.pods.current || s__('Environments|All pods'); + }, + }, + methods: { + ...mapActions('environmentLogs', ['setSearch', 'showPodLogs', 'setTimeRange']), + isCurrentPod(podName) { + return podName === this.pods.current; + }, + }, +}; +</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)" + /> + + <date-time-picker + ref="dateTimePicker" + v-model="timeRangeModel" + :disabled="disabled" + :options="timeRanges" + class="mb-2 gl-h-32 pr-2 d-block date-time-picker-wrapper" + right + /> + </div> +</template> diff --git a/app/assets/javascripts/logs/components/log_simple_filters.vue b/app/assets/javascripts/logs/components/log_simple_filters.vue new file mode 100644 index 00000000000..21fe1695624 --- /dev/null +++ b/app/assets/javascripts/logs/components/log_simple_filters.vue @@ -0,0 +1,73 @@ +<script> +import { s__ } from '~/locale'; +import { mapActions, mapState } from 'vuex'; +import { GlIcon, GlDropdown, GlDropdownHeader, GlDropdownItem } from '@gitlab/ui'; + +export default { + components: { + GlIcon, + GlDropdown, + GlDropdownHeader, + GlDropdownItem, + }, + props: { + disabled: { + type: Boolean, + required: false, + default: false, + }, + }, + data() { + return { + searchQuery: '', + }; + }, + computed: { + ...mapState('environmentLogs', ['pods']), + + podDropdownText() { + return this.pods.current || s__('Environments|No pod selected'); + }, + }, + methods: { + ...mapActions('environmentLogs', ['showPodLogs']), + isCurrentPod(podName) { + return podName === this.pods.current; + }, + }, +}; +</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|Select 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> + <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> + </gl-dropdown> + </div> +</template> diff --git a/app/assets/javascripts/logs/stores/getters.js b/app/assets/javascripts/logs/stores/getters.js index 8770306fdd6..d92969c5389 100644 --- a/app/assets/javascripts/logs/stores/getters.js +++ b/app/assets/javascripts/logs/stores/getters.js @@ -5,5 +5,9 @@ const mapTrace = ({ timestamp = null, pod = '', message = '' }) => export const trace = state => state.logs.lines.map(mapTrace).join('\n'); -// prevent babel-plugin-rewire from generating an invalid default during karma tests -export default () => {}; +export const showAdvancedFilters = state => { + const environment = state.environments.options.find( + ({ name }) => name === state.environments.current, + ); + return Boolean(environment?.enable_advanced_logs_querying); +}; |