diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-07 09:08:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-07 09:08:35 +0300 |
commit | bed53d96d214fd96ea688d3e86e53457ce50043e (patch) | |
tree | 8196df5e612e847c3da3e8f50a0d45d7ae9ea6e0 | |
parent | 83cd5db43517cfd977b0d288b179f794677ba1a7 (diff) |
Add latest changes from gitlab-org/gitlab@master
27 files changed, 270 insertions, 295 deletions
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue index 209e4629830..c0d6e32a739 100644 --- a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue +++ b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue @@ -101,6 +101,9 @@ export default { deleteTable: __('Delete table'), editTableActions: __('Edit table'), }, + dropdownPopperOpts: { + positionFixed: true, + }, }; </script> <template> @@ -124,9 +127,7 @@ export default { no-caret text-sr-only :text="$options.i18n.editTableActions" - :popper-opts="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ { - positionFixed: true, - } /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */" + :popper-opts="$options.dropdownPopperOpts" @hide="handleHide($event)" > <gl-dropdown-item @click="runCommand('addColumnBefore')"> diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue index 4e7dc578193..fc5766a23ef 100644 --- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue +++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue @@ -3,7 +3,6 @@ import { GlTooltipDirective, GlSafeHtmlDirective, GlIcon, GlLoadingIcon } from ' import { mapActions } from 'vuex'; import createFlash from '~/flash'; import { s__, sprintf } from '~/locale'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { UNFOLD_COUNT, INLINE_DIFF_LINES_KEY } from '../constants'; import * as utils from '../store/utils'; @@ -24,7 +23,6 @@ export default { GlTooltip: GlTooltipDirective, SafeHtml: GlSafeHtmlDirective, }, - mixins: [glFeatureFlagsMixin()], props: { file: { type: Object, @@ -93,25 +91,16 @@ export default { nextLineNumbers = {}, ) { this.loadMoreLines({ endpoint, params, lineNumbers, fileHash, isExpandDown, nextLineNumbers }) - .then(() => { - this.isRequesting = false; - }) .catch(() => { createFlash({ message: s__('Diffs|Something went wrong while fetching diff lines.'), }); - this.isRequesting = false; }) .finally(() => { this.loading = { up: false, down: false, all: false }; }); }, handleExpandLines(type = EXPAND_ALL) { - if (this.isRequesting) { - return; - } - - this.isRequesting = true; const endpoint = this.file.context_lines_path; const oldLineNumber = this.line.meta_data.old_pos || 0; const newLineNumber = this.line.meta_data.new_pos || 0; @@ -228,10 +217,7 @@ export default { </script> <template> - <div - v-if="glFeatures.updatedDiffExpansionButtons" - class="diff-grid-row diff-grid-row-full diff-tr line_holder match expansion" - > + <div class="diff-grid-row diff-grid-row-full diff-tr line_holder match expansion"> <div :class="{ parallel: !inline }" class="diff-grid-left diff-grid-2-col left-side"> <div class="diff-td diff-line-num gl-text-center! gl-p-0! gl-w-full! gl-display-flex gl-flex-direction-column" @@ -240,6 +226,7 @@ export default { v-if="showExpandDown" v-gl-tooltip.left :title="s__('Diffs|Next 20 lines')" + :disabled="loading.down" type="button" class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button" @click="handleExpandLines($options.EXPAND_DOWN)" @@ -251,6 +238,7 @@ export default { v-if="lineCountBetween !== -1 && lineCountBetween < 20" v-gl-tooltip.left :title="s__('Diffs|Expand all lines')" + :disabled="loading.all" type="button" class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button" @click="handleExpandLines()" @@ -262,6 +250,7 @@ export default { v-if="showExpandUp" v-gl-tooltip.left :title="s__('Diffs|Previous 20 lines')" + :disabled="loading.up" type="button" class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button" @click="handleExpandLines($options.EXPAND_UP)" @@ -276,32 +265,4 @@ export default { ></div> </div> </div> - <div v-else class="content js-line-expansion-content"> - <button - type="button" - :disabled="!canExpandDown" - class="js-unfold-down gl-mx-2 gl-py-4 gl-cursor-pointer" - @click="handleExpandLines($options.EXPAND_DOWN)" - > - <gl-icon :size="12" name="expand-down" /> - <span>{{ $options.i18n.showMore }}</span> - </button> - <button - type="button" - class="js-unfold-all gl-mx-2 gl-py-4 gl-cursor-pointer" - @click="handleExpandLines()" - > - <gl-icon :size="12" name="expand" /> - <span>{{ $options.i18n.showAll }}</span> - </button> - <button - type="button" - :disabled="!canExpandUp" - class="js-unfold gl-mx-2 gl-py-4 gl-cursor-pointer" - @click="handleExpandLines($options.EXPAND_UP)" - > - <gl-icon :size="12" name="expand-up" /> - <span>{{ $options.i18n.showMore }}</span> - </button> - </div> </template> diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue index 529f8e0a2f9..d740d5adcb6 100644 --- a/app/assets/javascripts/diffs/components/diff_view.vue +++ b/app/assets/javascripts/diffs/components/diff_view.vue @@ -6,7 +6,6 @@ import DraftNote from '~/batch_comments/components/draft_note.vue'; import draftCommentsMixin from '~/diffs/mixins/draft_comments'; import { getCommentedLines } from '~/notes/components/multiline_comment_utils'; import { hide } from '~/tooltips'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { pickDirection } from '../utils/diff_line'; import DiffCommentCell from './diff_comment_cell.vue'; import DiffExpansionCell from './diff_expansion_cell.vue'; @@ -23,11 +22,7 @@ export default { directives: { SafeHtml, }, - mixins: [ - draftCommentsMixin, - glFeatureFlagsMixin(), - IdState({ idProp: (vm) => vm.diffFile.file_hash }), - ], + mixins: [draftCommentsMixin, IdState({ idProp: (vm) => vm.diffFile.file_hash })], props: { diffFile: { type: Object, @@ -171,7 +166,6 @@ export default { <template v-for="(line, index) in diffLines"> <template v-if="line.isMatchLineLeft || line.isMatchLineRight"> <diff-expansion-cell - v-if="glFeatures.updatedDiffExpansionButtons" :key="`expand-${index}`" :file="diffFile" :line="line.left" @@ -180,41 +174,6 @@ export default { :inline="inline" :line-count-between="getCountBetweenIndex(index)" /> - <template v-else> - <div :key="`expand-${index}`" class="diff-tr line_expansion old-line_expansion match"> - <div class="diff-td text-center gl-font-regular"> - <diff-expansion-cell - :file="diffFile" - :context-lines-path="diffFile.context_lines_path" - :line="line.left" - :is-top="index === 0" - :is-bottom="index + 1 === diffLinesLength" - :inline="inline" - /> - </div> - </div> - <div - v-if="line.left.rich_text" - :key="`expand-definition-${index}`" - class="diff-grid-row diff-tr line_holder match" - > - <div class="diff-grid-left diff-grid-3-col left-side"> - <div class="diff-td diff-line-num"></div> - <div v-if="inline" class="diff-td diff-line-num"></div> - <div - v-safe-html="line.left.rich_text" - class="diff-td line_content left-side gl-white-space-normal!" - ></div> - </div> - <div v-if="!inline" class="diff-grid-right diff-grid-3-col right-side"> - <div class="diff-td diff-line-num"></div> - <div - v-safe-html="line.left.rich_text" - class="diff-td line_content right-side gl-white-space-normal!" - ></div> - </div> - </div> - </template> </template> <diff-row v-if="!line.isMatchLineLeft && !line.isMatchLineRight" diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue index 008b5780ecd..f83d8e644cb 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue @@ -24,6 +24,9 @@ export default { i18n: { stage: __('Stage:'), }, + dropdownPopperOpts: { + placement: 'bottom', + }, components: { CiIcon, GlLoadingIcon, @@ -114,9 +117,7 @@ export default { variant="link" :aria-label="stageAriaLabel(stage.title)" :lazy="true" - :popper-opts="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ { - placement: 'bottom', - } /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */" + :popper-opts="$options.dropdownPopperOpts" :toggle-class="['gl-rounded-full!']" menu-class="mini-pipeline-graph-dropdown-menu" @hide="onHideDropdown" diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss index 760fd6ccbd3..5e3fc5be317 100644 --- a/app/assets/stylesheets/framework/diffs.scss +++ b/app/assets/stylesheets/framework/diffs.scss @@ -456,19 +456,6 @@ table.code { table-layout: fixed; border-radius: 0 0 $border-radius-default $border-radius-default; - .diff-tr:first-of-type.line_expansion > .diff-td, - tr:first-of-type.line_expansion > td { - border-top: 0; - } - - .diff-tr:nth-last-of-type(2).line_expansion > .diff-td, - tr:nth-last-of-type(2).line_expansion, - tr:last-of-type.line_expansion { - > td { - border-bottom: 0; - } - } - .diff-tr.line_holder .diff-td, tr.line_holder td { line-height: $code-line-height; @@ -611,10 +598,6 @@ table.code { grid-template-columns: 50px 8px 0 1fr; } - .diff-grid-3-col { - grid-template-columns: 50px 1fr !important; - } - .diff-grid-2-col { grid-template-columns: 100px 1fr !important; @@ -623,10 +606,6 @@ table.code { } } - &.inline-diff-view .diff-grid-3-col { - grid-template-columns: 50px 50px 1fr !important; - } - .diff-grid-comments { display: grid; grid-template-columns: 1fr 1fr; diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss index 433141ae690..5c58d220075 100644 --- a/app/assets/stylesheets/highlight/common.scss +++ b/app/assets/stylesheets/highlight/common.scss @@ -29,36 +29,6 @@ } } -@mixin old-diff-expansion($background, $border, $link) { - background-color: $background; - - .diff-td, - td { - border-top: 1px solid $border; - border-bottom: 1px solid $border; - } - - button { - color: $link; - border: 0; - background: transparent; - - &[disabled] { - color: desaturate($link, 100%); - opacity: 0.5; - cursor: default; - } - - &:hover:not([disabled]) { - text-decoration: underline; - } - - &:not(:focus-visible) { - outline: 0; - } - } -} - @mixin dark-diff-expansion-line { &.expansion .diff-td { diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss index 0eeebdb2e7a..f4d9909d81f 100644 --- a/app/assets/stylesheets/highlight/themes/dark.scss +++ b/app/assets/stylesheets/highlight/themes/dark.scss @@ -154,10 +154,6 @@ $dark-il: #de935f; color: $dark-line-color; } - .old-line_expansion { - @include old-diff-expansion($dark-main-bg, $dark-border, $dark-na); - } - .diff-line-expand-button { @include diff-expansion($gray-600, $gray-200, $gray-300, $white); } diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss index b8cd97d6504..4a6d06a6444 100644 --- a/app/assets/stylesheets/highlight/themes/monokai.scss +++ b/app/assets/stylesheets/highlight/themes/monokai.scss @@ -125,10 +125,6 @@ $monokai-gh: #75715e; color: $monokai-text-color; } - .old-line_expansion { - @include old-diff-expansion($monokai-bg, $monokai-border, $monokai-k); - } - .diff-line-expand-button { @include diff-expansion($gray-600, $gray-200, $gray-300, $white); } diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss index 99a3de23c26..2f35126dd3b 100644 --- a/app/assets/stylesheets/highlight/themes/none.scss +++ b/app/assets/stylesheets/highlight/themes/none.scss @@ -44,10 +44,6 @@ color: $gl-text-color; } - .old-line_expansion { - @include old-diff-expansion($gray-light, $white-normal, $gl-text-color); - } - .diff-line-expand-button { @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800); } diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss index 55d17b8f1d2..acfc98c13ab 100644 --- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss +++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss @@ -128,10 +128,6 @@ $solarized-dark-il: #2aa198; color: $solarized-dark-pre-color; } - .old-line_expansion { - @include old-diff-expansion($solarized-dark-line-bg, $solarized-dark-border, $solarized-dark-kd); - } - .diff-line-expand-button { @include diff-expansion(lighten($solarized-dark-pre-bg, 10%), $gray-200, lighten($solarized-dark-pre-bg, 20%), $white); } diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss index 72b961097e4..74448317270 100644 --- a/app/assets/stylesheets/highlight/themes/solarized-light.scss +++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss @@ -134,10 +134,6 @@ $solarized-light-il: #2aa198; background-color: $solarized-light-pre-bg; color: $solarized-light-pre-color; } - - .old-line_expansion { - @include old-diff-expansion($solarized-light-line-bg, $solarized-light-border, $solarized-light-kd); - } .diff-line-expand-button { @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800); diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss index b984c194033..aac8ccde96e 100644 --- a/app/assets/stylesheets/highlight/white_base.scss +++ b/app/assets/stylesheets/highlight/white_base.scss @@ -133,19 +133,6 @@ pre.code, color: $white-code-color; } -.old-line_expansion { - @include old-diff-expansion($gray-light, $border-color, $blue-600); - - &.diff-tr:last-child { - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; - - .diff-td { - border-bottom: 0; - } - } -} - .diff-line-expand-button { @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800); } diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 79289fe1c2e..176adaf094e 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -44,7 +44,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:rebase_without_ci_ui, project) push_frontend_feature_flag(:issue_assignees_widget, @project) push_frontend_feature_flag(:realtime_labels, project) - push_frontend_feature_flag(:updated_diff_expansion_buttons, project) push_frontend_feature_flag(:refactor_security_extension, @project) push_frontend_feature_flag(:mr_attention_requests, current_user) push_frontend_feature_flag(:remove_diff_header_icons, project) diff --git a/config/feature_flags/development/updated_diff_expansion_buttons.yml b/config/feature_flags/development/updated_diff_expansion_buttons.yml deleted file mode 100644 index a566eab6047..00000000000 --- a/config/feature_flags/development/updated_diff_expansion_buttons.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: updated_diff_expansion_buttons -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80890 -rollout_issue_url: -milestone: '14.10' -type: development -group: group::code review -default_enabled: true diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md index 831015b3e59..64c51ead46d 100644 --- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md +++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md @@ -296,18 +296,6 @@ namespace = Namespace.find_by_full_path("<new_namespace>") ::Projects::TransferService.new(p, current_user).execute(namespace) ``` -### For Removing webhooks that is getting timeout due to large webhook logs - -```ruby -# ID is the webhook_id -hook=WebHook.find(ID) - -WebHooks::DestroyService.new(current_user).execute(hook) - -#In case the service gets timeout consider removing webhook_logs -hook.web_hook_logs.limit(BATCH_SIZE).delete_all -``` - ### Bulk update service integration password for _all_ projects For example, change the Jira user's password for all projects that have the Jira diff --git a/doc/api/issue_links.md b/doc/api/issue_links.md index ac26d2a3d17..eb9e8e8adc0 100644 --- a/doc/api/issue_links.md +++ b/doc/api/issue_links.md @@ -63,6 +63,106 @@ Parameters: ] ``` +## Get an issue link + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88228) in GitLab 15.1. + +Gets details about an issue link. + +```plaintext +GET /projects/:id/issues/:issue_iid/links/:issue_link_id +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +|-----------------|----------------|------------------------|-----------------------------------------------------------------------------| +| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). | +| `issue_iid` | integer | **{check-circle}** Yes | Internal ID of a project's issue. | +| `issue_link_id` | integer/string | **{check-circle}** Yes | ID of an issue relationship. | + +Response body attributes: + +| Attribute | Type | Description | +|:---------------|:-------|:------------------------------------------------------------------------------------------| +| `source_issue` | object | Details of the source issue of the relationship. | +| `target_issue` | object | Details of the target issue of the relationship. | +| `link_type` | string | Type of the relationship. Possible values are `relates_to`, `blocks` and `is_blocked_by`. | + +Example request: + +```shell +curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/84/issues/14/links/1" +``` + +Example response: + +```json +{ + "source_issue" : { + "id" : 83, + "iid" : 11, + "project_id" : 4, + "created_at" : "2016-01-07T12:44:33.959Z", + "title" : "Issues with auth", + "state" : "opened", + "assignees" : [], + "assignee" : null, + "labels" : [ + "bug" + ], + "author" : { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "description" : null, + "updated_at" : "2016-01-07T12:44:33.959Z", + "milestone" : null, + "subscribed" : true, + "user_notes_count": 0, + "due_date": null, + "web_url": "http://example.com/example/example/issues/11", + "confidential": false, + "weight": null + }, + "target_issue" : { + "id" : 84, + "iid" : 14, + "project_id" : 4, + "created_at" : "2016-01-07T12:44:33.959Z", + "title" : "Issues with auth", + "state" : "opened", + "assignees" : [], + "assignee" : null, + "labels" : [ + "bug" + ], + "author" : { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "description" : null, + "updated_at" : "2016-01-07T12:44:33.959Z", + "milestone" : null, + "subscribed" : true, + "user_notes_count": 0, + "due_date": null, + "web_url": "http://example.com/example/example/issues/14", + "confidential": false, + "weight": null + }, + "link_type": "relates_to" +} +``` + ## Create an issue link Creates a two-way relation between two issues. The user must be allowed to diff --git a/doc/development/database/background_migrations.md b/doc/development/database/background_migrations.md index ab52dfad018..4d20d85fce2 100644 --- a/doc/development/database/background_migrations.md +++ b/doc/development/database/background_migrations.md @@ -100,7 +100,7 @@ to automatically split the job into batches: ```ruby queue_background_migration_jobs_by_range_at_intervals( ClassName, - BackgroundMigrationClassName, + 'BackgroundMigrationClassName', 2.minutes, batch_size: 10_000 ) diff --git a/doc/user/group/epics/img/epics_search_v14_7.png b/doc/user/group/epics/img/epics_filter_v14_7.png Binary files differindex baed532c736..baed532c736 100644 --- a/doc/user/group/epics/img/epics_search_v14_7.png +++ b/doc/user/group/epics/img/epics_filter_v14_7.png diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md index e8f720238ed..cead676f136 100644 --- a/doc/user/group/epics/manage_epics.md +++ b/doc/user/group/epics/manage_epics.md @@ -187,17 +187,17 @@ To view epics in a group: The total count of open epics displayed in the sidebar is cached if higher than 1000. The cached value is rounded to thousands or millions and updated every 24 hours. -## Search for an epic from epics list page +## Filter the list of epics -> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) from GitLab Ultimate to GitLab Premium in 12.8. -> - Searching by the user's reaction emoji [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325630) in GitLab 13.11. +> - Filtering by epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9. +> - Filtering by child epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in GitLab 13.0. +> - Filtering by the user's reaction emoji [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325630) in GitLab 13.11. > - Sorting by epic titles [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.1. -> - Searching by milestone and confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268372) in GitLab 14.2 [with a flag](../../../administration/feature_flags.md) named `vue_epics_list`. Disabled by default. +> - Filtering by milestone and confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268372) in GitLab 14.2 [with a flag](../../../administration/feature_flags.md) named `vue_epics_list`. Disabled by default. > - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/276189) in GitLab 14.7. > - [Feature flag `vue_epics_list`](https://gitlab.com/gitlab-org/gitlab/-/issues/327320) removed in GitLab 14.8. -You can search for an epic from the list of epics using filtered search bar based on following -parameters: +You can filter the list of epics by: - Title or description - Author name / username @@ -206,9 +206,9 @@ parameters: - Confidentiality - Reaction emoji -![epics search](img/epics_search_v14_7.png) +![epics filter](img/epics_filter_v14_7.png) -To search: +To filter: 1. On the top bar, select **Menu > Groups** and find your group. 1. On the left sidebar, select **Epics**. @@ -216,7 +216,9 @@ To search: 1. From the dropdown menu, select the scope or enter plain text to search by epic title or description. 1. Press <kbd>Enter</kbd> on your keyboard. The list is filtered. -You can also sort epics list by: +## Sort the list of epics + +You can sort the epics list by: - Start date - Due date diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md index bd0cf92e320..a2dbc8581d9 100644 --- a/doc/user/project/issues/index.md +++ b/doc/user/project/issues/index.md @@ -45,7 +45,7 @@ To learn how the GitLab Strategic Marketing department uses GitLab issues with [ - [Health status](managing_issues.md#health-status) - [Cross-link issues](crosslinking_issues.md) - [Sort issue lists](sorting_issue_lists.md) -- [Search for issues](../../search/index.md#filter-issue-and-merge-request-lists) +- [Search for issues](managing_issues.md#filter-the-list-of-issues) - [Epics](../../group/epics/index.md) - [Issue boards](../issue_board.md) - [Issues API](../../../api/issues.md) diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md index ca151e1a28e..fbdce211295 100644 --- a/doc/user/project/issues/managing_issues.md +++ b/doc/user/project/issues/managing_issues.md @@ -576,6 +576,30 @@ Or: - To use a [keyboard shortcut](../../shortcuts.md), press <kbd>Shift</kbd> + <kbd>i</kbd>. - On the top bar, on the top right, select **{issues}** **Issues**. +## Filter the list of issues + +> - Filtering by iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. +> - Filtering by iterations was moved from GitLab Ultimate to GitLab Premium in 13.9. +> - Filtering by type was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 13.10 [with a flag](../../../administration/feature_flags.md) named `vue_issues_list`. Disabled by default. +> - Filtering by type was [enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 14.10. +> - Filtering by type is generally available in GitLab 15.1. [Feature flag `vue_issues_list`](https://gitlab.com/gitlab-org/gitlab/-/issues/359966) removed. + +To filter the list of issues: + +1. Above the list of issues, select **Search or filter results...**. +1. In the dropdown list that appears, select the attribute you want to filter by. +1. Select or type the operator to use for filtering the attribute. The following operators are + available: + - `=`: Is + - `!=`: Is not ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18059) in GitLab 12.7) +1. Enter the text to filter the attribute by. + You can filter some attributes by **None** or **Any**. +1. Repeat this process to filter by multiple attributes. Multiple attributes are joined by a logical + `AND`. + +GitLab displays the results on-screen, but you can also +[retrieve them as an RSS feed](../../search/index.md#retrieve-search-results-as-feed). + ### Filter issues by ID > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) in GitLab 12.1. diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index c2f0eacebd4..30b69c2fff5 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -60,6 +60,24 @@ Or: - [Review requests](reviews/index.md). - Merge requests assigned. +## Filter the list of merge requests + +To filter the list of merge requests: + +1. Above the list of merge requests, select **Search or filter results...**. +1. In the dropdown list that appears, select the attribute you wish to filter by. +1. Select or type the operator to use for filtering the attribute. The following operators are + available: + - `=`: Is + - `!=`: Is not ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18059) in GitLab 12.7) +1. Enter the text to filter the attribute by. + You can filter some attributes by **None** or **Any**. +1. Repeat this process to filter by multiple attributes. Multiple attributes are joined by a logical + `AND`. + +GitLab displays the results on-screen, but you can also +[retrieve them as an RSS feed](../../search/index.md#retrieve-search-results-as-feed). + ### Filter merge requests by ID > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) in GitLab 12.1. diff --git a/doc/user/search/index.md b/doc/user/search/index.md index b70f060091f..28d4bf22689 100644 --- a/doc/user/search/index.md +++ b/doc/user/search/index.md @@ -31,6 +31,7 @@ Use basic search to find: ## Perform a search To start a search, type your search query in the search bar on the top-right of the screen. +You must type at least two characters. ![basic search](img/basic_search_v15_1.png) @@ -75,47 +76,6 @@ and gives you the option to return to the search results page. ![project SHA search redirect](img/project_search_sha_redirect.png) -## Filter issue and merge request lists - -> - Filtering by epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9. -> - Filtering by child epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in GitLab 13.0. -> - Filtering by iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. -> - Filtering by iterations was moved from GitLab Ultimate to GitLab Premium in 13.9. -> - Filtering by type was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 13.10 [with a flag](../../administration/feature_flags.md) named `vue_issues_list`. Disabled by default. -> - Filtering by type was [enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 14.10. -> - Filtering by type is generally available in GitLab 15.1. [Feature flag `vue_issues_list`](https://gitlab.com/gitlab-org/gitlab/-/issues/359966) removed. -> - Filtering by attention request was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343528) in GitLab 14.10 [with a flag](../../administration/feature_flags.md) named `mr_attention_requests`. Disabled by default. - -Follow these steps to filter the **Issues** and **Merge requests** list pages in projects and -groups: - -1. Select **Search or filter results...**. -1. In the dropdown list that appears, select the attribute you wish to filter by: - - Assignee - - [Attention requests](../project/merge_requests/index.md#request-attention-to-a-merge-request) - - Author - - Confidential - - [Epic and child Epic](../group/epics/index.md) (available only for the group the Epic was created, not for [higher group levels](https://gitlab.com/gitlab-org/gitlab/-/issues/233729)). - - [Iteration](../group/iterations/index.md) - - [Label](../project/labels.md) - - [Milestone](../project/milestones/index.md) - - My-reaction - - Release - - Type - - Weight - - Search for this text -1. Select or type the operator to use for filtering the attribute. The following operators are - available: - - `=`: Is - - `!=`: Is not ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18059) in GitLab 12.7) -1. Enter the text to [filter the attribute by](#filters-autocomplete). - You can filter some attributes by **None** or **Any**. -1. Repeat this process to filter by multiple attributes. Multiple attributes are joined by a logical - `AND`. - -GitLab displays the results on-screen, but you can also -[retrieve them as an RSS feed](#retrieve-search-results-as-feed). - ## Searching for specific terms You can filter issues and merge requests by specific terms included in titles or descriptions. @@ -138,23 +98,12 @@ RSS feed of search results: 1. Go to your project's page. 1. On the left sidebar, select **Issues** or **Merge requests**. -1. Build your search query as described in [Filter issue and merge request lists](#filter-issue-and-merge-request-lists). +1. Perform a search. 1. Select the feed symbol **{rss}** to display the results as an RSS feed in Atom format. The URL of the result contains both a feed token, and your search query. You can add this URL to your feed reader. -## Filters autocomplete - -GitLab provides many filters across many pages (issues, merge requests, epics, -and pipelines among others) which you can use to narrow down your search. When -using the filter functionality, you can start typing characters to bring up -relevant users or other attributes. - -For performance optimization, there is a requirement of a minimum of three -characters to begin your search. To search for issues with the assignee `Simone Presley`, -you must type at least `Sim` before autocomplete displays results. - ## Search history Search history is available for issues and merge requests, and is stored locally @@ -175,17 +124,6 @@ Some filters can be added multiple times. These include but are not limited to a ![multiple assignees filtering](img/multiple_assignees.png) -## Groups - -You can search through your groups from -the left menu, by clicking the menu bar, then **Groups**. - -On the field **Filter by name**, type the group name you want to find, and GitLab -filters them for you as you type. - -You can also **Explore** all public and internal groups available in GitLab.com, -and sort them by **Name**, **Last created**, **Oldest created**, or **Updated date**. - ## Issue boards From an [issue board](../../user/project/issue_board.md), you can filter issues by **Author**, **Assignee**, **Milestone**, and **Labels**. diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb index cf075af8373..c07c2c1994e 100644 --- a/lib/api/issue_links.rb +++ b/lib/api/issue_links.rb @@ -61,6 +61,22 @@ module API end # rubocop: enable CodeReuse/ActiveRecord + desc 'Get issues relation' do + detail 'This feature was introduced in GitLab 15.1.' + success Entities::IssueLink + end + params do + requires :issue_link_id, type: Integer, desc: 'The ID of an issue link' + end + get ':id/issues/:issue_iid/links/:issue_link_id' do + issue = find_project_issue(params[:issue_iid]) + issue_link = IssueLink.for_source_or_target(issue).find(declared_params[:issue_link_id]) + + find_project_issue(issue_link.target.iid.to_s, issue_link.target.project_id.to_s) + + present issue_link, with: Entities::IssueLink + end + desc 'Remove issues relation' do success Entities::IssueLink end diff --git a/spec/frontend/diffs/components/diff_expansion_cell_spec.js b/spec/frontend/diffs/components/diff_expansion_cell_spec.js index bd538996349..5ff0728b358 100644 --- a/spec/frontend/diffs/components/diff_expansion_cell_spec.js +++ b/spec/frontend/diffs/components/diff_expansion_cell_spec.js @@ -1,4 +1,3 @@ -import { getByText } from '@testing-library/dom'; import { mount } from '@vue/test-utils'; import { cloneDeep } from 'lodash'; import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue'; @@ -81,7 +80,7 @@ describe('DiffExpansionCell', () => { const findExpandUp = (wrapper) => wrapper.find(EXPAND_UP_CLASS); const findExpandDown = (wrapper) => wrapper.find(EXPAND_DOWN_CLASS); - const findExpandAll = ({ element }) => getByText(element, 'Show all unchanged lines'); + const findExpandAll = (wrapper) => wrapper.find('.js-unfold-all'); describe('top row', () => { it('should have "expand up" and "show all" option', () => { @@ -90,9 +89,7 @@ describe('DiffExpansionCell', () => { }); expect(findExpandUp(wrapper).exists()).toBe(true); - expect(findExpandDown(wrapper).exists()).toBe(true); expect(findExpandUp(wrapper).attributes('disabled')).not.toBeDefined(); - expect(findExpandDown(wrapper).attributes('disabled')).toBeDefined(); expect(findExpandAll(wrapper)).not.toBe(null); }); }); @@ -114,9 +111,7 @@ describe('DiffExpansionCell', () => { }); expect(findExpandDown(wrapper).exists()).toBe(true); - expect(findExpandUp(wrapper).exists()).toBe(true); expect(findExpandDown(wrapper).attributes('disabled')).not.toBeDefined(); - expect(findExpandUp(wrapper).attributes('disabled')).toBeDefined(); expect(findExpandAll(wrapper)).not.toBe(null); }); }); @@ -144,9 +139,9 @@ describe('DiffExpansionCell', () => { newLineNumber, }); - const wrapper = createComponent({ file }); + const wrapper = createComponent({ file, lineCountBetween: 10 }); - findExpandAll(wrapper).click(); + findExpandAll(wrapper).trigger('click'); expect(store.dispatch).toHaveBeenCalledWith( 'diffs/loadMoreLines', diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js index f982749d1de..dfbe30e460b 100644 --- a/spec/frontend/diffs/components/diff_view_spec.js +++ b/spec/frontend/diffs/components/diff_view_spec.js @@ -49,22 +49,6 @@ describe('DiffView', () => { return shallowMount(DiffView, { propsData, store, stubs }); }; - it('renders a match line', () => { - const wrapper = createWrapper({ - diffLines: [ - { - isMatchLineLeft: true, - left: { - rich_text: '@@ -4,12 +4,12 @@ import createFlash from '~/flash';', - lineDraft: {}, - }, - }, - ], - }); - expect(wrapper.find(DiffExpansionCell).exists()).toBe(true); - expect(wrapper.text()).toContain("@@ -4,12 +4,12 @@ import createFlash from '~/flash';"); - }); - it.each` type | side | container | sides | total ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true }, right: { lineDraft: {}, renderDiscussion: true } }} | ${2} diff --git a/spec/requests/api/issue_links_spec.rb b/spec/requests/api/issue_links_spec.rb index 81dd4c3dfa0..90238c8bf76 100644 --- a/spec/requests/api/issue_links_spec.rb +++ b/spec/requests/api/issue_links_spec.rb @@ -156,6 +156,87 @@ RSpec.describe API::IssueLinks do end end + describe 'GET /links/:issue_link_id' do + def perform_request(issue_link_id, user = nil, params = {}) + get api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link_id}", user), params: params + end + + context 'when unauthenticated' do + it 'returns 401' do + issue_link = create(:issue_link) + + perform_request(issue_link.id) + + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + + context 'when authenticated' do + context 'when issue link does not exist' do + it 'returns 404' do + perform_request(non_existing_record_id, user) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + let_it_be(:target_issue) { create(:issue, project: project) } + + context 'when issue link does not belong to the specified issue' do + it 'returns 404' do + other_issue = create(:issue, project: project) + # source is different than the given API route issue + issue_link = create(:issue_link, source: other_issue, target: target_issue) + + perform_request(issue_link.id, user) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when user has ability to read the issue link' do + it 'returns 200' do + issue_link = create(:issue_link, source: issue, target: target_issue) + + perform_request(issue_link.id, user) + + aggregate_failures "testing response" do + expect(response).to have_gitlab_http_status(:ok) + expect(response).to match_response_schema('public_api/v4/issue_link') + end + end + end + + context 'when user cannot read issue link' do + let(:private_project) { create(:project) } + let(:public_project) { create(:project, :public) } + let(:public_issue) { create(:issue, project: public_project) } + + context 'when the issue link targets an issue in a non-accessible project' do + it 'returns 404' do + private_issue = create(:issue, project: private_project) + issue_link = create(:issue_link, source: public_issue, target: private_issue) + + perform_request(issue_link.id, user) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when issue link targets a non-accessible issue' do + it 'returns 404' do + confidential_issue = create(:issue, :confidential, project: public_project) + issue_link = create(:issue_link, source: public_issue, target: confidential_issue) + + perform_request(issue_link.id, user) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + end + end + describe 'DELETE /links/:issue_link_id' do context 'when unauthenticated' do it 'returns 401' do |