diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-01 18:08:16 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-01 18:08:16 +0300 |
commit | 711f8595324430e216ba62f874e7db9fdf482f73 (patch) | |
tree | da5b8063c16a20e2ab414ca20526ef64817b4393 | |
parent | 65f197cdb6f7732e6c56433483a17f50d98b48f0 (diff) |
Add latest changes from gitlab-org/gitlab@master
59 files changed, 371 insertions, 114 deletions
diff --git a/app/assets/javascripts/alert_management/components/alert_management_list.vue b/app/assets/javascripts/alert_management/components/alert_management_list.vue index 0b4e2d8ca02..ecb92ccef6f 100644 --- a/app/assets/javascripts/alert_management/components/alert_management_list.vue +++ b/app/assets/javascripts/alert_management/components/alert_management_list.vue @@ -11,6 +11,7 @@ import { GlTabs, GlTab, GlBadge, + GlPagination, } from '@gitlab/ui'; import createFlash from '~/flash'; import { s__ } from '~/locale'; @@ -22,6 +23,7 @@ import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query import { ALERTS_STATUS_TABS, ALERTS_SEVERITY_LABELS, + DEFAULT_PAGE_SIZE, trackAlertListViewsOptions, trackAlertStatusUpdateOptions, } from '../constants'; @@ -34,6 +36,14 @@ const bodyTrClass = 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200'; const findDefaultSortColumn = () => document.querySelector('.js-started-at'); +const initialPaginationState = { + currentPage: 1, + prevPageCursor: '', + nextPageCursor: '', + firstPageSize: DEFAULT_PAGE_SIZE, + lastPageSize: null, +}; + export default { i18n: { noAlertsMsg: s__( @@ -110,6 +120,7 @@ export default { GlTabs, GlTab, GlBadge, + GlPagination, }, props: { projectPath: { @@ -142,10 +153,20 @@ export default { projectPath: this.projectPath, statuses: this.statusFilter, sort: this.sort, + firstPageSize: this.pagination.firstPageSize, + lastPageSize: this.pagination.lastPageSize, + prevPageCursor: this.pagination.prevPageCursor, + nextPageCursor: this.pagination.nextPageCursor, }; }, update(data) { - return data.project?.alertManagementAlerts?.nodes; + const { alertManagementAlerts: { nodes: list = [], pageInfo = {} } = {} } = + data.project || {}; + + return { + list, + pageInfo, + }; }, error() { this.errored = true; @@ -169,7 +190,9 @@ export default { isAlertDismissed: false, isErrorAlertDismissed: false, sort: 'STARTED_AT_ASC', - statusFilter: this.$options.statusTabs[4].filters, + statusFilter: [], + filteredByStatus: '', + pagination: initialPaginationState, }; }, computed: { @@ -185,19 +208,34 @@ export default { return this.$apollo.queries.alerts.loading; }, hasAlerts() { - return this.alerts?.length; + return this.alerts?.list?.length; }, tbodyTrClass() { return !this.loading && this.hasAlerts ? bodyTrClass : ''; }, + showPaginationControls() { + return Boolean(this.prevPage || this.nextPage); + }, + alertsForCurrentTab() { + return this.alertsCount ? this.alertsCount[this.filteredByStatus.toLowerCase()] : 0; + }, + prevPage() { + return Math.max(this.pagination.currentPage - 1, 0); + }, + nextPage() { + const nextPage = this.pagination.currentPage + 1; + return nextPage > Math.ceil(this.alertsForCurrentTab / DEFAULT_PAGE_SIZE) ? null : nextPage; + }, }, mounted() { - findDefaultSortColumn().ariaSort = 'ascending'; this.trackPageViews(); }, methods: { filterAlertsByStatus(tabIndex) { - this.statusFilter = this.$options.statusTabs[tabIndex].filters; + this.resetPagination(); + const { filters, status } = this.$options.statusTabs[tabIndex]; + this.statusFilter = filters; + this.filteredByStatus = status; }, fetchSortedData({ sortBy, sortDesc }) { const sortDirection = sortDesc ? 'DESC' : 'ASC'; @@ -206,6 +244,7 @@ export default { if (sortBy !== 'startedAt') { findDefaultSortColumn().ariaSort = 'none'; } + this.resetPagination(); this.sort = `${sortColumn}_${sortDirection}`; }, updateAlertStatus(status, iid) { @@ -222,6 +261,7 @@ export default { this.trackStatusUpdate(status); this.$apollo.queries.alerts.refetch(); this.$apollo.queries.alertsCount.refetch(); + this.resetPagination(); }) .catch(() => { createFlash( @@ -246,6 +286,28 @@ export default { // TODO: Update to show list of assignee(s) after https://gitlab.com/gitlab-org/gitlab/-/issues/218405 return assignees?.length > 0 ? assignees[0]?.username : s__('AlertManagement|Unassigned'); }, + handlePageChange(page) { + const { startCursor, endCursor } = this.alerts.pageInfo; + + if (page > this.pagination.currentPage) { + this.pagination = { + ...initialPaginationState, + nextPageCursor: endCursor, + currentPage: page, + }; + } else { + this.pagination = { + lastPageSize: DEFAULT_PAGE_SIZE, + firstPageSize: null, + prevPageCursor: startCursor, + nextPageCursor: '', + currentPage: page, + }; + } + }, + resetPagination() { + this.pagination = initialPaginationState; + }, }, }; </script> @@ -275,7 +337,7 @@ export default { </h4> <gl-table class="alert-management-table mt-3" - :items="alerts" + :items="alerts ? alerts.list : []" :fields="$options.fields" :show-empty="true" :busy="loading" @@ -283,6 +345,7 @@ export default { :tbody-tr-class="tbodyTrClass" :no-local-sorting="true" sort-icon-left + sort-by="startedAt" @row-clicked="navigateToAlertDetails" @sort-changed="fetchSortedData" > @@ -350,6 +413,16 @@ export default { <gl-loading-icon size="lg" color="dark" class="mt-3" /> </template> </gl-table> + + <gl-pagination + v-if="showPaginationControls" + :value="pagination.currentPage" + :prev-page="prevPage" + :next-page="nextPage" + align="center" + class="gl-pagination prepend-top-default" + @input="handlePageChange" + /> </div> <gl-empty-state v-else diff --git a/app/assets/javascripts/alert_management/constants.js b/app/assets/javascripts/alert_management/constants.js index b79a64646eb..b9670466c0f 100644 --- a/app/assets/javascripts/alert_management/constants.js +++ b/app/assets/javascripts/alert_management/constants.js @@ -63,3 +63,5 @@ export const trackAlertStatusUpdateOptions = { action: 'update_alert_status', label: 'Status', }; + +export const DEFAULT_PAGE_SIZE = 10; diff --git a/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql index 42e5282e174..1d3c3c83cc1 100644 --- a/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql +++ b/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql @@ -1,11 +1,32 @@ #import "../fragments/list_item.fragment.graphql" -query getAlerts($projectPath: ID!, $statuses: [AlertManagementStatus!], $sort: AlertManagementAlertSort ) { - project(fullPath: $projectPath) { - alertManagementAlerts(statuses: $statuses, sort: $sort) { - nodes { - ...AlertListItem - } +query getAlerts( + $projectPath: ID!, + $statuses: [AlertManagementStatus!], + $sort: AlertManagementAlertSort, + $firstPageSize: Int, + $lastPageSize: Int, + $prevPageCursor: String = "" + $nextPageCursor: String = "" +) { + project(fullPath: $projectPath, ) { + alertManagementAlerts( + statuses: $statuses, + sort: $sort, + first: $firstPageSize + last: $lastPageSize, + after: $nextPageCursor, + before: $prevPageCursor + ) { + nodes { + ...AlertListItem + }, + pageInfo { + hasNextPage + endCursor + hasPreviousPage + startCursor + } + } } - } } diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue index 6edbdc7090c..3242993b06a 100644 --- a/app/assets/javascripts/badges/components/badge.vue +++ b/app/assets/javascripts/badges/components/badge.vue @@ -84,10 +84,10 @@ export default { <div v-show="hasError" class="btn-group"> <div class="btn btn-default btn-sm disabled"> - <icon :size="16" class="gl-ml-3 append-right-8" name="doc-image" aria-hidden="true" /> + <icon :size="16" class="gl-ml-3 gl-mr-3" name="doc-image" aria-hidden="true" /> </div> <div class="btn btn-default btn-sm disabled"> - <span class="gl-ml-3 append-right-8">{{ s__('Badges|No badge image') }}</span> + <span class="gl-ml-3 gl-mr-3">{{ s__('Badges|No badge image') }}</span> </div> </div> diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue index bb363b8d85e..bad14666bb2 100644 --- a/app/assets/javascripts/badges/components/badge_list_row.vue +++ b/app/assets/javascripts/badges/components/badge_list_row.vue @@ -54,7 +54,7 @@ export default { <div v-if="canEditBadge" class="table-action-buttons"> <button :disabled="badge.isDeleting" - class="btn btn-default append-right-8" + class="btn btn-default gl-mr-3" type="button" @click="editBadge(badge)" > diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue index 6e0859571db..3e0ae6f65c6 100644 --- a/app/assets/javascripts/batch_comments/components/draft_note.vue +++ b/app/assets/javascripts/batch_comments/components/draft_note.vue @@ -86,7 +86,7 @@ export default { <publish-button :show-count="true" :should-publish="false" - class="btn btn-success btn-inverted append-right-8" + class="btn btn-success btn-inverted gl-mr-3" /> <loading-button ref="publishNowButton" diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue index 13b2291d44b..195e1b7ec5c 100644 --- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue +++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue @@ -103,7 +103,7 @@ export default { :show-count="false" :should-publish="true" :label="__('Submit review')" - class="float-right append-right-8" + class="float-right gl-mr-3" /> </div> </div> diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue index 9cd74b19c48..df9c419ff96 100644 --- a/app/assets/javascripts/batch_comments/components/preview_item.vue +++ b/app/assets/javascripts/batch_comments/components/preview_item.vue @@ -83,7 +83,7 @@ export default { @click="scrollToDraft(draft)" > <span class="review-preview-item-header"> - <icon class="append-right-8 flex-shrink-0" :name="iconName" /> + <icon class="gl-mr-3 flex-shrink-0" :name="iconName" /> <span class="bold text-nowrap"> <span class="review-preview-item-header-text block-truncated"> {{ titleText }} </span> <template v-if="showLinePosition"> @@ -98,7 +98,7 @@ export default { v-if="draft.discussion_id && resolvedStatusMessage" class="review-preview-item-footer draft-note-resolution p-0" > - <icon class="append-right-8" name="status_success" /> {{ resolvedStatusMessage }} + <icon class="gl-mr-3" name="status_success" /> {{ resolvedStatusMessage }} </span> </button> </template> diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue index 76e7cb03799..e852032e9e0 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.vue +++ b/app/assets/javascripts/boards/components/issue_card_inner.vue @@ -188,7 +188,7 @@ export default { > <span v-if="issue.referencePath" - class="board-card-number overflow-hidden d-flex append-right-8 gl-mt-3" + class="board-card-number overflow-hidden d-flex gl-mr-3 gl-mt-3" > <tooltip-on-truncate v-if="issueReferencePath" diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue index 7eb791f97e4..7b703c5ede1 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue @@ -170,7 +170,7 @@ export default { v-if="tableIsNotEmpty" ref="secret-value-reveal-button" data-qa-selector="reveal_ci_variable_value_button" - class="append-right-8" + class="gl-mr-3" @click="toggleValues(!valuesHidden)" >{{ valuesButtonText }}</gl-deprecated-button > diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue index a4ca2a6c857..c4db122ba6f 100644 --- a/app/assets/javascripts/clusters/components/application_row.vue +++ b/app/assets/javascripts/clusters/components/application_row.vue @@ -313,7 +313,7 @@ export default { :data-qa-selector="id" > <div class="gl-responsive-table-row-layout" role="row"> - <div class="table-section append-right-8 section-align-top" role="gridcell"> + <div class="table-section gl-mr-3 section-align-top" role="gridcell"> <img v-if="hasLogo" :src="logoUrl" diff --git a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue index c2f963f0b34..24c70b99efe 100644 --- a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue +++ b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue @@ -168,7 +168,7 @@ export default { }} </gl-alert> <div class="gl-responsive-table-row-layout" role="row"> - <div class="table-section append-right-8 section-align-top" role="gridcell"> + <div class="table-section gl-mr-3 section-align-top" role="gridcell"> <img :src="modSecurityLogo" :alt="`${$options.title} logo`" diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue index e9f581a95eb..6f6fa312865 100644 --- a/app/assets/javascripts/diffs/components/compare_versions.vue +++ b/app/assets/javascripts/diffs/components/compare_versions.vue @@ -86,7 +86,7 @@ export default { <button v-gl-tooltip.hover type="button" - class="btn btn-default append-right-8 js-toggle-tree-list" + class="btn btn-default gl-mr-3 js-toggle-tree-list" :class="{ active: showTreeList, }" @@ -126,15 +126,11 @@ export default { <gl-deprecated-button v-if="commit || startVersion" :href="latestVersionPath" - class="append-right-8 js-latest-version" + class="gl-mr-3 js-latest-version" > {{ __('Show latest version') }} </gl-deprecated-button> - <gl-deprecated-button - v-show="hasCollapsedFile" - class="append-right-8" - @click="expandAllFiles" - > + <gl-deprecated-button v-show="hasCollapsedFile" class="gl-mr-3" @click="expandAllFiles"> {{ __('Expand all') }} </gl-deprecated-button> <settings-dropdown /> diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue index 410909190b3..5fe58c5e512 100644 --- a/app/assets/javascripts/groups/components/group_item.vue +++ b/app/assets/javascripts/groups/components/group_item.vue @@ -104,7 +104,7 @@ export default { <gl-loading-icon v-if="group.isChildrenLoading" size="lg" - class="d-none d-sm-inline-flex flex-shrink-0 append-right-8" + class="d-none d-sm-inline-flex flex-shrink-0 gl-mr-3" /> <div :class="{ 'd-sm-flex': !group.isChildrenLoading }" @@ -117,12 +117,12 @@ export default { </div> <div class="group-text-container d-flex flex-fill align-items-center"> <div class="group-text flex-grow-1 flex-shrink-1"> - <div class="d-flex align-items-center flex-wrap title namespace-title append-right-8"> + <div class="d-flex align-items-center flex-wrap title namespace-title gl-mr-3"> <a v-tooltip :href="group.relativePath" :title="group.fullName" - class="no-expand gl-mt-3 append-right-8" + class="no-expand gl-mt-3 gl-mr-3" data-placement="bottom" >{{ // ending bracket must be by closing tag to prevent diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue index 24499fb9f6d..d171852b6a1 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue @@ -56,7 +56,7 @@ export default { v-if="canDiscard" ref="discardButton" type="button" - class="btn btn-remove btn-inverted append-right-8" + class="btn btn-remove btn-inverted gl-mr-3" @click="showDiscardModal" > {{ __('Discard changes') }} diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue index 49885917c53..ed4097f5459 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue @@ -74,7 +74,7 @@ export default { <div class="ide-commit-list-container"> <header class="multi-file-commit-panel-header d-flex mb-0"> <div class="d-flex align-items-center flex-fill"> - <icon v-once :name="iconName" :size="18" class="append-right-8" /> + <icon v-once :name="iconName" :size="18" class="gl-mr-3" /> <strong> {{ titleText }} </strong> <div class="d-flex ml-auto"> <button diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue index 5ae44c0d9a8..c65169f5d31 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue @@ -87,7 +87,7 @@ export default { @click="openFileInEditor" > <span class="multi-file-commit-list-file-path d-flex align-items-center"> - <file-icon :file-name="file.name" class="append-right-8" /> + <file-icon :file-name="file.name" class="gl-mr-3" /> <template v-if="file.prevName && file.prevName !== file.name"> {{ file.prevName }} → </template> diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue index 40dc0a6e80d..169a948c2da 100644 --- a/app/assets/javascripts/ide/components/jobs/stage.vue +++ b/app/assets/javascripts/ide/components/jobs/stage.vue @@ -75,7 +75,7 @@ export default { > {{ stage.name }} </strong> - <div v-if="!stage.isLoading || stage.jobs.length" class="append-right-8 gl-ml-2"> + <div v-if="!stage.isLoading || stage.jobs.length" class="gl-mr-3 gl-ml-2"> <span class="badge badge-pill"> {{ jobsCount }} </span> </div> <icon :name="collapseIcon" class="ide-stage-collapse-icon" /> diff --git a/app/assets/javascripts/ide/components/mr_file_icon.vue b/app/assets/javascripts/ide/components/mr_file_icon.vue index cf8a1abbde4..4fab57b6f3e 100644 --- a/app/assets/javascripts/ide/components/mr_file_icon.vue +++ b/app/assets/javascripts/ide/components/mr_file_icon.vue @@ -18,6 +18,6 @@ export default { :title="__('Part of merge request changes')" :size="12" name="git-merge" - class="append-right-8" + class="gl-mr-3" /> </template> diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue index 629a71451e9..7bd9a90e8b8 100644 --- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue +++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue @@ -285,7 +285,7 @@ export default { <slot name="topLeft"></slot> <h5 ref="graphTitle" - class="prometheus-graph-title gl-font-lg font-weight-bold text-truncate append-right-8" + class="prometheus-graph-title gl-font-lg font-weight-bold text-truncate gl-mr-3" tabindex="0" > {{ title }} diff --git a/app/assets/javascripts/releases/components/evidence_block.vue b/app/assets/javascripts/releases/components/evidence_block.vue index acae6fda533..2cc15777343 100644 --- a/app/assets/javascripts/releases/components/evidence_block.vue +++ b/app/assets/javascripts/releases/components/evidence_block.vue @@ -71,7 +71,7 @@ export default { :download="evidenceTitle(index)" :href="evidenceUrl(index)" > - <gl-icon name="review-list" class="align-middle append-right-8" /> + <gl-icon name="review-list" class="align-middle gl-mr-3" /> <span>{{ evidenceTitle(index) }}</span> </gl-link> @@ -96,7 +96,7 @@ export default { <gl-icon v-gl-tooltip name="clock" - class="align-middle append-right-8" + class="align-middle gl-mr-3" :title="collectedAt(index)" /> <span>{{ timeSummary(index) }}</span> diff --git a/app/assets/javascripts/releases/components/release_block_metadata.vue b/app/assets/javascripts/releases/components/release_block_metadata.vue index 40133941011..a3377ce044a 100644 --- a/app/assets/javascripts/releases/components/release_block_metadata.vue +++ b/app/assets/javascripts/releases/components/release_block_metadata.vue @@ -57,7 +57,7 @@ export default { <template> <div class="card-subtitle d-flex flex-wrap text-secondary"> - <div class="append-right-8"> + <div class="gl-mr-3"> <icon name="commit" class="align-middle" /> <gl-link v-if="commitUrl" v-gl-tooltip.bottom :title="commit.title" :href="commitUrl"> {{ commit.shortId }} @@ -65,7 +65,7 @@ export default { <span v-else v-gl-tooltip.bottom :title="commit.title">{{ commit.shortId }}</span> </div> - <div class="append-right-8"> + <div class="gl-mr-3"> <icon name="tag" class="align-middle" /> <gl-link v-if="tagUrl" v-gl-tooltip.bottom :title="__('Tag')" :href="tagUrl"> {{ release.tagName }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue index 2433ba879aa..0464c4b9c15 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue @@ -117,7 +117,7 @@ export default { :href="webIdePath" :title="ideButtonTitle" :class="{ disabled: !mr.canPushToSourceBranch }" - class="btn btn-default js-web-ide d-none d-md-inline-block append-right-8" + class="btn btn-default js-web-ide d-none d-md-inline-block gl-mr-3" data-placement="bottom" tabindex="0" role="button" @@ -129,7 +129,7 @@ export default { :disabled="mr.sourceBranchRemoved" data-target="#modal_merge_info" data-toggle="modal" - class="btn btn-default js-check-out-branch append-right-8" + class="btn btn-default js-check-out-branch gl-mr-3" type="button" > {{ s__('mrWidget|Check out branch') }} diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue index e80cb06edfb..47231c4ad39 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue @@ -52,7 +52,7 @@ export default { :download="fileName" target="_blank" > - <icon :size="16" name="download" class="float-left append-right-8" /> + <icon :size="16" name="download" class="float-left gl-mr-3" /> {{ __('Download') }} </gl-link> </div> diff --git a/app/assets/javascripts/vue_shared/components/file_finder/item.vue b/app/assets/javascripts/vue_shared/components/file_finder/item.vue index 018e3a84c39..590501a975a 100644 --- a/app/assets/javascripts/vue_shared/components/file_finder/item.vue +++ b/app/assets/javascripts/vue_shared/components/file_finder/item.vue @@ -75,12 +75,8 @@ export default { @mouseover="mouseOverRow" @mousemove="mouseMove" > - <file-icon - :file-name="file.name" - :size="16" - css-classes="diff-file-changed-icon append-right-8" - /> - <span class="diff-changed-file-content append-right-8"> + <file-icon :file-name="file.name" :size="16" css-classes="diff-file-changed-icon gl-mr-3" /> + <span class="diff-changed-file-content gl-mr-3"> <strong class="diff-changed-file-name"> <span v-for="(char, charIndex) in file.name.split('')" diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index bf474251572..b0144cde360 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -414,7 +414,6 @@ img.emoji { .append-right-2 { margin-right: 2px; } .append-right-4 { margin-right: 4px; } .append-right-5 { margin-right: 5px; } -.append-right-8 { margin-right: 8px; } .append-right-10 { margin-right: 10px; } .append-right-15 { margin-right: 15px; } .append-right-default { margin-right: $gl-padding; } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 154717f9776..47c6a9a44ca 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -920,7 +920,7 @@ button.mini-pipeline-graph-dropdown-toggle { .ci-status-icon { - @extend .append-right-8; + @include gl-mr-3; position: relative; diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb index 65be2a22958..dc7e78a85a9 100644 --- a/app/models/releases/link.rb +++ b/app/models/releases/link.rb @@ -14,6 +14,13 @@ module Releases scope :sorted, -> { order(created_at: :desc) } + enum link_type: { + other: 0, + runbook: 1, + package: 2, + image: 3 + } + def internal? url.start_with?(release.project.web_url) end diff --git a/app/views/admin/hooks/edit.html.haml b/app/views/admin/hooks/edit.html.haml index 9ce0fa8d401..636dd6bdfc1 100644 --- a/app/views/admin/hooks/edit.html.haml +++ b/app/views/admin/hooks/edit.html.haml @@ -9,7 +9,7 @@ = form_for @hook, as: :hook, url: admin_hook_path do |f| = render partial: 'form', locals: { form: f, hook: @hook } .form-actions - %span>= f.submit _('Save changes'), class: 'btn btn-success append-right-8' + %span>= f.submit _('Save changes'), class: 'btn btn-success gl-mr-3' = render 'shared/web_hooks/test_button', hook: @hook = link_to _('Delete'), admin_hook_path(@hook), method: :delete, class: 'btn btn-remove float-right', data: { confirm: _('Are you sure?') } diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml index 617e5d1d5d3..486625c790b 100644 --- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml +++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml @@ -2,7 +2,7 @@ .bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } } %button.close.js-close{ type: "button" } × .gcp-signup-offer--content - .gcp-signup-offer--icon.append-right-8 + .gcp-signup-offer--icon.gl-mr-3 = sprite_icon("information", size: 16) .gcp-signup-offer--copy %h4= s_('ClusterIntegration|Did you know?') diff --git a/app/views/import/bitbucket_server/new.html.haml b/app/views/import/bitbucket_server/new.html.haml index ac86be8fa7a..2eac8d0c5a1 100644 --- a/app/views/import/bitbucket_server/new.html.haml +++ b/app/views/import/bitbucket_server/new.html.haml @@ -13,14 +13,14 @@ .form-group.row = label_tag :bitbucket_server_url, 'Bitbucket Server URL', class: 'col-form-label col-md-2' .col-md-4 - = text_field_tag :bitbucket_server_url, '', class: 'form-control append-right-8', placeholder: _('https://your-bitbucket-server'), size: 40 + = text_field_tag :bitbucket_server_url, '', class: 'form-control gl-mr-3', placeholder: _('https://your-bitbucket-server'), size: 40 .form-group.row = label_tag :bitbucket_server_url, 'Username', class: 'col-form-label col-md-2' .col-md-4 - = text_field_tag :bitbucket_username, '', class: 'form-control append-right-8', placeholder: _('username'), size: 40 + = text_field_tag :bitbucket_username, '', class: 'form-control gl-mr-3', placeholder: _('username'), size: 40 .form-group.row = label_tag :personal_access_token, 'Password/Personal Access Token', class: 'col-form-label col-md-2' .col-md-4 - = password_field_tag :personal_access_token, '', class: 'form-control append-right-8', placeholder: _('Personal Access Token'), size: 40 + = password_field_tag :personal_access_token, '', class: 'form-control gl-mr-3', placeholder: _('Personal Access Token'), size: 40 .form-actions = submit_tag _('List your Bitbucket Server repositories'), class: 'btn btn-success' diff --git a/app/views/import/phabricator/new.html.haml b/app/views/import/phabricator/new.html.haml index eaa36b9012e..3dfc7c37d98 100644 --- a/app/views/import/phabricator/new.html.haml +++ b/app/views/import/phabricator/new.html.haml @@ -16,10 +16,10 @@ .form-group.row = label_tag :phabricator_server_url, _('Phabricator Server URL'), class: 'col-form-label col-md-2' .col-md-4 - = text_field_tag :phabricator_server_url, params[:phabricator_server_url], class: 'form-control append-right-8', placeholder: 'https://your-phabricator-server', size: 40 + = text_field_tag :phabricator_server_url, params[:phabricator_server_url], class: 'form-control gl-mr-3', placeholder: 'https://your-phabricator-server', size: 40 .form-group.row = label_tag :api_token, _('API Token'), class: 'col-form-label col-md-2' .col-md-4 - = password_field_tag :api_token, params[:api_token], class: 'form-control append-right-8', placeholder: _('Personal Access Token'), size: 40 + = password_field_tag :api_token, params[:api_token], class: 'form-control gl-mr-3', placeholder: _('Personal Access Token'), size: 40 .form-actions = submit_tag _('Import tasks'), class: 'btn btn-success' diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index b4e218451a0..38470fea6da 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -80,7 +80,7 @@ - if @project.badges.present? .project-badges.mb-2 - @project.badges.each do |badge| - %a.append-right-8{ href: badge.rendered_link_url(@project), + %a.gl-mr-3{ href: badge.rendered_link_url(@project), target: '_blank', rel: 'noopener noreferrer' }> %img.project-badge{ src: badge.rendered_image_url(@project), diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index 4b82eb2c5ef..2d9c7f9848f 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -1,6 +1,6 @@ - unless @project.empty_repo? - if current_user && can?(current_user, :fork_project, @project) - .count-badge.d-inline-flex.align-item-stretch.append-right-8 + .count-badge.d-inline-flex.align-item-stretch.gl-mr-3 - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: s_('ProjectOverview|Go to your fork'), class: 'btn btn-default has-tooltip count-badge-button d-flex align-items-center fork-btn' do = sprite_icon('fork', { css_class: 'icon' }) diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 02e5297528b..3dac38d1356 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,5 +1,5 @@ - if current_user - .count-badge.d-inline-flex.align-item-stretch.append-right-8 + .count-badge.d-inline-flex.align-item-stretch.gl-mr-3 %button.count-badge-button.btn.btn-default.btn-xs.d-flex.align-items-center.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(@project, :json) } } - if current_user.starred?(@project) = sprite_icon('star', { css_class: 'icon' }) @@ -12,7 +12,7 @@ = @project.star_count - else - .count-badge.d-inline-flex.align-item-stretch.append-right-8 + .count-badge.d-inline-flex.align-item-stretch.gl-mr-3 = link_to new_user_session_path, class: 'btn btn-default btn-xs has-tooltip count-badge-button d-flex align-items-center star-btn', title: s_('ProjectOverview|You must sign in to star a project') do = sprite_icon('star-o', { css_class: 'icon' }) %span= s_('ProjectOverview|Star') diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 86e6e732610..17c1764e8a4 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -22,8 +22,8 @@ - diff_files.each do |diff_file| %li %a.diff-changed-file{ href: "##{hexdigest(diff_file.file_path)}", title: diff_file.new_path } - = sprite_icon(diff_file_changed_icon(diff_file), size: 16, css_class: "#{diff_file_changed_icon_color(diff_file)} diff-file-changed-icon append-right-8") - %span.diff-changed-file-content.append-right-8 + = sprite_icon(diff_file_changed_icon(diff_file), size: 16, css_class: "#{diff_file_changed_icon_color(diff_file)} diff-file-changed-icon gl-mr-3") + %span.diff-changed-file-content.gl-mr-3 - if diff_file.file_path %strong.diff-changed-file-name = diff_file.file_path diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml index f7eae802dac..15100840c0a 100644 --- a/app/views/projects/hooks/edit.html.haml +++ b/app/views/projects/hooks/edit.html.haml @@ -10,7 +10,7 @@ = form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f| = render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook } - %span>= f.submit 'Save changes', class: 'btn btn-success append-right-8' + %span>= f.submit 'Save changes', class: 'btn btn-success gl-mr-3' = render 'shared/web_hooks/test_button', hook: @hook = link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn btn-remove float-right', data: { confirm: _('Are you sure?') } diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml index a77eea8beaa..73904354a12 100644 --- a/app/views/projects/issues/_new_branch.html.haml +++ b/app/views/projects/issues/_new_branch.html.haml @@ -41,7 +41,7 @@ = _('Create branch') %li.divider.droplab-item-ignore - %li.droplab-item-ignore.gl-ml-3.append-right-8.prepend-top-16 + %li.droplab-item-ignore.gl-ml-3.gl-mr-3.prepend-top-16 - if can_create_confidential_merge_request? #js-forked-project{ data: { namespace_path: @project.namespace.full_path, project_path: @project.full_path, new_fork_path: new_project_fork_path(@project), help_page_path: help_page_path('user/project/merge_requests') } } .form-group diff --git a/app/views/shared/notifications/_new_button.html.haml b/app/views/shared/notifications/_new_button.html.haml index 566f08b94ce..796ff095eea 100644 --- a/app/views/shared/notifications/_new_button.html.haml +++ b/app/views/shared/notifications/_new_button.html.haml @@ -8,7 +8,7 @@ - else - button_title = _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) } - .js-notification-dropdown.notification-dropdown.home-panel-action-button.prepend-top-default.append-right-8.dropdown.inline + .js-notification-dropdown.notification-dropdown.home-panel-action-button.prepend-top-default.gl-mr-3.dropdown.inline = form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f| = hidden_setting_source_input(notification_setting) = hidden_field_tag "hide_label", true diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 5a0003e546f..fc3f1a8d1c1 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -32,7 +32,7 @@ .d-flex.align-items-center.flex-wrap.project-title %h2.d-flex.gl-mt-3 = link_to project_path(project), class: 'text-plain' do - %span.project-full-name.append-right-8>< + %span.project-full-name.gl-mr-3>< %span.namespace-name - if project.namespace && !skip_namespace = project.namespace.human_name diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml index 34a62340966..470e2f6b904 100644 --- a/app/views/shared/web_hooks/_hook.html.haml +++ b/app/views/shared/web_hooks/_hook.html.haml @@ -11,6 +11,6 @@ = hook.enable_ssl_verification ? _('enabled') : _('disabled') .col-md-4.col-lg-5.text-right-md.prepend-top-5 - %span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm append-right-8' - %span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn btn-sm append-right-8' + %span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm gl-mr-3' + %span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn btn-sm gl-mr-3' = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn btn-sm' diff --git a/changelogs/unreleased/207257-specify-asset-types-in-releases.yml b/changelogs/unreleased/207257-specify-asset-types-in-releases.yml new file mode 100644 index 00000000000..ee11eb72389 --- /dev/null +++ b/changelogs/unreleased/207257-specify-asset-types-in-releases.yml @@ -0,0 +1,5 @@ +--- +title: Add link_type column to release_links table +merge_request: 33156 +author: +type: changed diff --git a/changelogs/unreleased/213881-alerts-list-pagination.yml b/changelogs/unreleased/213881-alerts-list-pagination.yml new file mode 100644 index 00000000000..310152722ed --- /dev/null +++ b/changelogs/unreleased/213881-alerts-list-pagination.yml @@ -0,0 +1,5 @@ +--- +title: Alerts list pagination +merge_request: 33073 +author: +type: added diff --git a/db/migrate/20200527092027_add_link_type_to_release_links.rb b/db/migrate/20200527092027_add_link_type_to_release_links.rb new file mode 100644 index 00000000000..5088775f665 --- /dev/null +++ b/db/migrate/20200527092027_add_link_type_to_release_links.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AddLinkTypeToReleaseLinks < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + with_lock_retries do + add_column :release_links, :link_type, :integer, limit: 2, default: 0 + end + end + + def down + with_lock_retries do + remove_column :release_links, :link_type + end + end +end diff --git a/db/structure.sql b/db/structure.sql index e4b5d5d35c5..5242cde1f9b 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -5730,7 +5730,8 @@ CREATE TABLE public.release_links ( name character varying NOT NULL, created_at timestamp with time zone NOT NULL, updated_at timestamp with time zone NOT NULL, - filepath character varying(128) + filepath character varying(128), + link_type smallint DEFAULT 0 ); CREATE SEQUENCE public.release_links_id_seq @@ -14031,6 +14032,7 @@ COPY "schema_migrations" (version) FROM STDIN; 20200526153844 20200526164946 20200526164947 +20200527092027 20200527094322 20200527095401 20200527151413 diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index 11ea6b0f150..fdd64c20c70 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -126,10 +126,12 @@ configuration option in `gitlab.yml`. These metrics are served from the | `sidekiq_jobs_db_seconds` | Histogram | 12.9 | Seconds of DB time to run Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` | | `sidekiq_jobs_gitaly_seconds` | Histogram | 12.9 | Seconds of Gitaly time to run Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` | | `sidekiq_redis_requests_duration_seconds` | Histogram | 13.1 | Duration in seconds that a Sidekiq job spent querying a Redis server | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` | +| `sidekiq_elasticsearch_requests_duration_seconds` | Histogram | 13.1 | Duration in seconds that a Sidekiq job spent in requests to an Elasticsearch server | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` | | `sidekiq_jobs_queue_duration_seconds` | Histogram | 12.5 | Duration in seconds that a Sidekiq job was queued before being executed | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` | | `sidekiq_jobs_failed_total` | Counter | 12.2 | Sidekiq jobs failed | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` | | `sidekiq_jobs_retried_total` | Counter | 12.2 | Sidekiq jobs retried | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` | | `sidekiq_redis_requests_total` | Counter | 13.1 | Redis requests during a Sidekiq job execution | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` | +| `sidekiq_elasticsearch_requests_total` | Counter | 13.1 | Elasticsearch requests during a Sidekiq job execution | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` | | `sidekiq_running_jobs` | Gauge | 12.2 | Number of Sidekiq jobs running | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` | | `sidekiq_concurrency` | Gauge | 12.5 | Maximum number of Sidekiq jobs | | | `geo_db_replication_lag_seconds` | Gauge | 10.2 | Database replication lag (seconds) | `url` | diff --git a/doc/user/project/bulk_editing.md b/doc/user/project/bulk_editing.md index 8a7446155f4..14a570fa17d 100644 --- a/doc/user/project/bulk_editing.md +++ b/doc/user/project/bulk_editing.md @@ -4,29 +4,31 @@ group: Project Management info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- -# Bulk editing issues and merge requests +# Bulk editing issues, epics, and merge requests > **Notes:** > > - A permission level of `Reporter` or higher is required in order to manage > issues. +> - A permission level of `Reporter` or higher is required in order to manage +> epics. > - A permission level of `Developer` or higher is required in order to manage > merge requests. -Attributes can be updated simultaneously across multiple issues or merge requests +Attributes can be updated simultaneously across multiple issues, epics, or merge requests by using the bulk editing feature. ![Bulk editing](img/bulk-editing.png) NOTE: **Note:** -Bulk editing issues and merge requests is also available at the group level. +Bulk editing issues, epics, and merge requests is also available at the group level. For more details, see [bulk editing group issues and merge requests](../group/bulk_editing/index.md). -To update multiple project issues or merge requests at the same time: +To update multiple project issues, epics, or merge requests at the same time: 1. Navigate to their respective list. -1. Click **Edit issues** or **Edit merge requests**. +1. Click either **Edit issues**, **Edit epics**, or **Edit merge requests**. - This will open a sidebar on the right-hand side of your screen where editable fields will be displayed. diff --git a/lib/gitlab/diff/formatters/base_formatter.rb b/lib/gitlab/diff/formatters/base_formatter.rb index 9704aed82c1..31eeadc45f7 100644 --- a/lib/gitlab/diff/formatters/base_formatter.rb +++ b/lib/gitlab/diff/formatters/base_formatter.rb @@ -6,6 +6,7 @@ module Gitlab class BaseFormatter attr_reader :old_path attr_reader :new_path + attr_reader :file_identifier_hash attr_reader :base_sha attr_reader :start_sha attr_reader :head_sha @@ -16,6 +17,7 @@ module Gitlab attrs[:diff_refs] = diff_file.diff_refs attrs[:old_path] = diff_file.old_path attrs[:new_path] = diff_file.new_path + attrs[:file_identifier_hash] = diff_file.file_identifier_hash end if diff_refs = attrs[:diff_refs] @@ -26,6 +28,7 @@ module Gitlab @old_path = attrs[:old_path] @new_path = attrs[:new_path] + @file_identifier_hash = attrs[:file_identifier_hash] @base_sha = attrs[:base_sha] @start_sha = attrs[:start_sha] @head_sha = attrs[:head_sha] @@ -36,7 +39,7 @@ module Gitlab end def to_h - { + out = { base_sha: base_sha, start_sha: start_sha, head_sha: head_sha, @@ -44,6 +47,12 @@ module Gitlab new_path: new_path, position_type: position_type } + + if Feature.enabled?(:file_identifier_hash) + out[:file_identifier_hash] = file_identifier_hash + end + + out end def position_type diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb index 10ad23b7774..a5120a1b8fe 100644 --- a/lib/gitlab/diff/position.rb +++ b/lib/gitlab/diff/position.rb @@ -9,6 +9,7 @@ module Gitlab delegate :old_path, :new_path, + :file_identifier_hash, :base_sha, :start_sha, :head_sha, diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb index 00dd3b5937a..6a942a6ce06 100644 --- a/lib/gitlab/sidekiq_middleware/server_metrics.rb +++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb @@ -49,6 +49,8 @@ module Gitlab @metrics[:sidekiq_jobs_gitaly_seconds].observe(labels, get_gitaly_time(job)) @metrics[:sidekiq_redis_requests_total].increment(labels, get_redis_calls(job)) @metrics[:sidekiq_redis_requests_duration_seconds].observe(labels, get_redis_time(job)) + @metrics[:sidekiq_elasticsearch_requests_total].increment(labels, get_elasticsearch_calls(job)) + @metrics[:sidekiq_elasticsearch_requests_duration_seconds].observe(labels, get_elasticsearch_time(job)) end end @@ -62,9 +64,11 @@ module Gitlab sidekiq_jobs_gitaly_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_gitaly_seconds, 'Seconds of Gitaly time to run Sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS), sidekiq_jobs_queue_duration_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_queue_duration_seconds, 'Duration in seconds that a Sidekiq job was queued before being executed', {}, SIDEKIQ_LATENCY_BUCKETS), sidekiq_redis_requests_duration_seconds: ::Gitlab::Metrics.histogram(:sidekiq_redis_requests_duration_seconds, 'Duration in seconds that a Sidekiq job spent requests a Redis server', {}, Gitlab::Instrumentation::Redis::QUERY_TIME_BUCKETS), + sidekiq_elasticsearch_requests_duration_seconds: ::Gitlab::Metrics.histogram(:sidekiq_elasticsearch_requests_duration_seconds, 'Duration in seconds that a Sidekiq job spent in requests to an Elasticsearch server', {}, SIDEKIQ_LATENCY_BUCKETS), sidekiq_jobs_failed_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_failed_total, 'Sidekiq jobs failed'), sidekiq_jobs_retried_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_retried_total, 'Sidekiq jobs retried'), sidekiq_redis_requests_total: ::Gitlab::Metrics.counter(:sidekiq_redis_requests_total, 'Redis requests during a Sidekiq job execution'), + sidekiq_elasticsearch_requests_total: ::Gitlab::Metrics.counter(:sidekiq_elasticsearch_requests_total, 'Elasticsearch requests during a Sidekiq job execution'), sidekiq_running_jobs: ::Gitlab::Metrics.gauge(:sidekiq_running_jobs, 'Number of Sidekiq jobs running', {}, :all), sidekiq_concurrency: ::Gitlab::Metrics.gauge(:sidekiq_concurrency, 'Maximum number of Sidekiq jobs', {}, :all) } @@ -82,6 +86,14 @@ module Gitlab job.fetch(:redis_calls, 0) end + def get_elasticsearch_time(job) + job.fetch(:elasticsearch_duration_s, 0) + end + + def get_elasticsearch_calls(job) + job.fetch(:elasticsearch_calls, 0) + end + def get_gitaly_time(job) job.fetch(:gitaly_duration_s, 0) end diff --git a/spec/frontend/alert_management/components/alert_management_list_spec.js b/spec/frontend/alert_management/components/alert_management_list_spec.js index 8d7fbbb763f..614c7a59953 100644 --- a/spec/frontend/alert_management/components/alert_management_list_spec.js +++ b/spec/frontend/alert_management/components/alert_management_list_spec.js @@ -7,8 +7,10 @@ import { GlDropdown, GlDropdownItem, GlIcon, + GlTabs, GlTab, GlBadge, + GlPagination, } from '@gitlab/ui'; import { visitUrl } from '~/lib/utils/url_utility'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; @@ -39,19 +41,21 @@ describe('AlertManagementList', () => { const findLoader = () => wrapper.find(GlLoadingIcon); const findStatusDropdown = () => wrapper.find(GlDropdown); const findStatusFilterTabs = () => wrapper.findAll(GlTab); + const findStatusTabs = () => wrapper.find(GlTabs); const findStatusFilterBadge = () => wrapper.findAll(GlBadge); const findDateFields = () => wrapper.findAll(TimeAgo); const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem); const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]'); const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]'); const findSeverityColumnHeader = () => wrapper.findAll('th').at(0); - + const findStartTimeColumnHeader = () => wrapper.findAll('th').at(1); + const findPagination = () => wrapper.find(GlPagination); const alertsCount = { - acknowledged: 6, - all: 16, open: 14, - resolved: 2, triggered: 10, + acknowledged: 6, + resolved: 1, + all: 16, }; function mountComponent({ @@ -76,6 +80,7 @@ describe('AlertManagementList', () => { mocks: { $apollo: { mutate: jest.fn(), + query: jest.fn(), queries: { alerts: { loading, @@ -134,7 +139,7 @@ describe('AlertManagementList', () => { it('loading state', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: null, alertsCount: null }, + data: { alerts: {}, alertsCount: null }, loading: true, }); expect(findAlertsTable().exists()).toBe(true); @@ -149,7 +154,7 @@ describe('AlertManagementList', () => { it('error state', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: null, alertsCount: null, errored: true }, + data: { alerts: { errors: ['error'] }, alertsCount: null, errored: true }, loading: false, }); expect(findAlertsTable().exists()).toBe(true); @@ -166,7 +171,7 @@ describe('AlertManagementList', () => { it('empty state', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: [], alertsCount: { all: 0 }, errored: false }, + data: { alerts: { list: [], pageInfo: {} }, alertsCount: { all: 0 }, errored: false }, loading: false, }); expect(findAlertsTable().exists()).toBe(true); @@ -183,7 +188,7 @@ describe('AlertManagementList', () => { it('has data state', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); expect(findLoader().exists()).toBe(false); @@ -199,7 +204,7 @@ describe('AlertManagementList', () => { it('displays status dropdown', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); expect(findStatusDropdown().exists()).toBe(true); @@ -208,7 +213,7 @@ describe('AlertManagementList', () => { it('shows correct severity icons', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); @@ -225,7 +230,7 @@ describe('AlertManagementList', () => { it('renders severity text', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); @@ -239,7 +244,7 @@ describe('AlertManagementList', () => { it('renders Unassigned when no assignee(s) present', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); @@ -253,7 +258,7 @@ describe('AlertManagementList', () => { it('renders username(s) when assignee(s) present', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); @@ -267,7 +272,7 @@ describe('AlertManagementList', () => { it('navigates to the detail page when alert row is clicked', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); @@ -282,15 +287,17 @@ describe('AlertManagementList', () => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, data: { - alerts: [ - { - iid: 1, - status: 'acknowledged', - startedAt: '2020-03-17T23:18:14.996Z', - endedAt: '2020-04-17T23:18:14.996Z', - severity: 'high', - }, - ], + alerts: { + list: [ + { + iid: 1, + status: 'acknowledged', + startedAt: '2020-03-17T23:18:14.996Z', + endedAt: '2020-04-17T23:18:14.996Z', + severity: 'high', + }, + ], + }, alertsCount, errored: false, }, @@ -326,27 +333,31 @@ describe('AlertManagementList', () => { beforeEach(() => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, errored: false, sort: 'STARTED_AT_ASC', alertsCount }, + data: { alerts: { list: mockAlerts }, errored: false, sort: 'STARTED_AT_ASC', alertsCount }, loading: false, + stubs: { GlTable }, }); }); it('updates sort with new direction and column key', () => { findSeverityColumnHeader().trigger('click'); - expect(wrapper.vm.$data.sort).toEqual('SEVERITY_ASC'); + expect(wrapper.vm.$data.sort).toBe('SEVERITY_ASC'); findSeverityColumnHeader().trigger('click'); - expect(wrapper.vm.$data.sort).toEqual('SEVERITY_DESC'); + expect(wrapper.vm.$data.sort).toBe('SEVERITY_DESC'); }); it('updates the `ariaSort` attribute so the sort icon appears in the proper column', () => { - expect(mockStartedAtCol.ariaSort).toEqual('ascending'); + expect(findStartTimeColumnHeader().attributes('aria-sort')).toBe('ascending'); findSeverityColumnHeader().trigger('click'); - expect(mockStartedAtCol.ariaSort).toEqual('none'); + wrapper.vm.$nextTick(() => { + expect(findStartTimeColumnHeader().attributes('aria-sort')).toBe('none'); + expect(findSeverityColumnHeader().attributes('aria-sort')).toBe('ascending'); + }); }); }); @@ -367,7 +378,7 @@ describe('AlertManagementList', () => { beforeEach(() => { mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount, errored: false }, + data: { alerts: { list: mockAlerts }, alertsCount, errored: false }, loading: false, }); }); @@ -403,7 +414,7 @@ describe('AlertManagementList', () => { jest.spyOn(Tracking, 'event'); mountComponent({ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, - data: { alerts: mockAlerts, alertsCount }, + data: { alerts: { list: mockAlerts }, alertsCount }, loading: false, }); }); @@ -424,4 +435,64 @@ describe('AlertManagementList', () => { }); }); }); + + describe('Pagination', () => { + beforeEach(() => { + mountComponent({ + props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, + data: { alerts: { list: mockAlerts, pageInfo: {} }, alertsCount, errored: false }, + loading: false, + }); + }); + + it('does NOT show pagination control when list is smaller than default page size', () => { + findStatusTabs().vm.$emit('input', 3); + wrapper.vm.$nextTick(() => { + expect(findPagination().exists()).toBe(false); + }); + }); + + it('shows pagination control when list is larger than default page size', () => { + findStatusTabs().vm.$emit('input', 0); + wrapper.vm.$nextTick(() => { + expect(findPagination().exists()).toBe(true); + }); + }); + + describe('prevPage', () => { + it('returns prevPage number', () => { + findPagination().vm.$emit('input', 3); + + return wrapper.vm.$nextTick(() => { + expect(wrapper.vm.prevPage).toBe(2); + }); + }); + + it('returns 0 when it is the first page', () => { + findPagination().vm.$emit('input', 1); + + return wrapper.vm.$nextTick(() => { + expect(wrapper.vm.prevPage).toBe(0); + }); + }); + }); + + describe('nextPage', () => { + it('returns nextPage number', () => { + findPagination().vm.$emit('input', 1); + + return wrapper.vm.$nextTick(() => { + expect(wrapper.vm.nextPage).toBe(2); + }); + }); + + it('returns `null` when currentPage is already last page', () => { + findStatusTabs().vm.$emit('input', 3); + findPagination().vm.$emit('input', 1); + return wrapper.vm.$nextTick(() => { + expect(wrapper.vm.nextPage).toBeNull(); + }); + }); + }); + }); }); diff --git a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap index 6bce68af642..bdd3d439fd4 100644 --- a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap +++ b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap @@ -25,7 +25,7 @@ exports[`IDE pipeline stage renders stage details & icon 1`] = ` </strong> <div - class="append-right-8 gl-ml-2" + class="gl-mr-3 gl-ml-2" > <span class="badge badge-pill" diff --git a/spec/frontend/jobs/components/job_log_spec.js b/spec/frontend/jobs/components/job_log_spec.js index 2bb1e0af3a2..a167fe8a134 100644 --- a/spec/frontend/jobs/components/job_log_spec.js +++ b/spec/frontend/jobs/components/job_log_spec.js @@ -10,7 +10,7 @@ describe('Job Log', () => { let vm; const trace = - '<span>Running with gitlab-runner 12.1.0 (de7731dd)<br/></span><span> on docker-auto-scale-com d5ae8d25<br/></span><div class="append-right-8" data-timestamp="1565502765" data-section="prepare-executor" role="button"></div><span class="section section-header js-s-prepare-executor">Using Docker executor with image ruby:2.6 ...<br/></span>'; + '<span>Running with gitlab-runner 12.1.0 (de7731dd)<br/></span><span> on docker-auto-scale-com d5ae8d25<br/></span><div class="gl-mr-3" data-timestamp="1565502765" data-section="prepare-executor" role="button"></div><span class="section section-header js-s-prepare-executor">Using Docker executor with image ruby:2.6 ...<br/></span>'; beforeEach(() => { store = createStore(); diff --git a/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb b/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb index edf30ffc56f..3f88f39ba92 100644 --- a/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb +++ b/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb @@ -10,6 +10,7 @@ describe Gitlab::Diff::Formatters::ImageFormatter do head_sha: 789, old_path: 'old_image.png', new_path: 'new_image.png', + file_identifier_hash: '777', position_type: 'image' } end diff --git a/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb b/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb index fa129a20e58..50dd597c5a7 100644 --- a/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb +++ b/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb @@ -10,6 +10,7 @@ describe Gitlab::Diff::Formatters::TextFormatter do head_sha: 789, old_path: 'old_path.txt', new_path: 'new_path.txt', + file_identifier_hash: '777', line_range: nil } end diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index c29a85ce624..aae4ba6e025 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -144,6 +144,7 @@ Releases::Link: - url - name - filepath +- link_type - created_at - updated_at ProjectMember: diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb index 7000a52bb5d..4b7baea25e8 100644 --- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb @@ -34,6 +34,8 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do let(:redis_requests_total) { double('redis calls total metric') } let(:running_jobs_metric) { double('running jobs metric') } let(:redis_seconds_metric) { double('redis seconds metric') } + let(:elasticsearch_seconds_metric) { double('elasticsearch seconds metric') } + let(:elasticsearch_requests_total) { double('elasticsearch calls total metric') } before do allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_queue_duration_seconds, anything, anything, anything).and_return(queue_duration_seconds) @@ -42,9 +44,11 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_db_seconds, anything, anything, anything).and_return(db_seconds_metric) allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything).and_return(gitaly_seconds_metric) allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_redis_requests_duration_seconds, anything, anything, anything).and_return(redis_seconds_metric) + allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_elasticsearch_requests_duration_seconds, anything, anything, anything).and_return(elasticsearch_seconds_metric) allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_failed_total, anything).and_return(failed_total_metric) allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_retried_total, anything).and_return(retried_total_metric) allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_redis_requests_total, anything).and_return(redis_requests_total) + allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_elasticsearch_requests_total, anything).and_return(elasticsearch_requests_total) allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_running_jobs, anything, {}, :all).and_return(running_jobs_metric) allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_concurrency, anything, {}, :all).and_return(concurrency_metric) @@ -76,6 +80,9 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do let(:redis_calls) { 2 } let(:redis_duration) { 0.01 } + let(:elasticsearch_calls) { 8 } + let(:elasticsearch_duration) { 0.54 } + before do allow(subject).to receive(:get_thread_cputime).and_return(thread_cputime_before, thread_cputime_after) allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after) @@ -86,14 +93,19 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do job[:redis_calls] = redis_calls job[:redis_duration_s] = redis_duration + job[:elasticsearch_calls] = elasticsearch_calls + job[:elasticsearch_duration_s] = elasticsearch_duration + allow(running_jobs_metric).to receive(:increment) allow(redis_requests_total).to receive(:increment) + allow(elasticsearch_requests_total).to receive(:increment) allow(queue_duration_seconds).to receive(:observe) allow(user_execution_seconds_metric).to receive(:observe) allow(db_seconds_metric).to receive(:observe) allow(gitaly_seconds_metric).to receive(:observe) allow(completion_seconds_metric).to receive(:observe) allow(redis_seconds_metric).to receive(:observe) + allow(elasticsearch_seconds_metric).to receive(:observe) end it 'yields block' do @@ -109,7 +121,9 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do expect(gitaly_seconds_metric).to receive(:observe).with(labels_with_job_status, gitaly_duration) expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, monotonic_time_duration) expect(redis_seconds_metric).to receive(:observe).with(labels_with_job_status, redis_duration) + expect(elasticsearch_seconds_metric).to receive(:observe).with(labels_with_job_status, elasticsearch_duration) expect(redis_requests_total).to receive(:increment).with(labels_with_job_status, redis_calls) + expect(elasticsearch_requests_total).to receive(:increment).with(labels_with_job_status, elasticsearch_calls) subject.call(worker, job, :test) { nil } end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2c5d624e75f..46237c6c9c9 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -195,6 +195,10 @@ RSpec.configure do |config| stub_feature_flags(flag => enable_rugged) end + # Disable the usage of file_identifier_hash by default until it is ready + # See https://gitlab.com/gitlab-org/gitlab/-/issues/33867 + stub_feature_flags(file_identifier_hash: false) + allow(Gitlab::GitalyClient).to receive(:can_use_disk?).and_return(enable_rugged) end diff --git a/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb index c9300aff3e6..326800e6dc2 100644 --- a/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb @@ -32,7 +32,21 @@ RSpec.shared_examples "position formatter" do subject { formatter.to_h } - it { is_expected.to eq(formatter_hash) } + context 'when file_identifier_hash is disabled' do + before do + stub_feature_flags(file_identifier_hash: false) + end + + it { is_expected.to eq(formatter_hash.except(:file_identifier_hash)) } + end + + context 'when file_identifier_hash is enabled' do + before do + stub_feature_flags(file_identifier_hash: true) + end + + it { is_expected.to eq(formatter_hash) } + end end describe '#==' do |