Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
83cd5db435
commit
bed53d96d2
|
@ -101,6 +101,9 @@ export default {
|
||||||
deleteTable: __('Delete table'),
|
deleteTable: __('Delete table'),
|
||||||
editTableActions: __('Edit table'),
|
editTableActions: __('Edit table'),
|
||||||
},
|
},
|
||||||
|
dropdownPopperOpts: {
|
||||||
|
positionFixed: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
@ -124,9 +127,7 @@ export default {
|
||||||
no-caret
|
no-caret
|
||||||
text-sr-only
|
text-sr-only
|
||||||
:text="$options.i18n.editTableActions"
|
:text="$options.i18n.editTableActions"
|
||||||
:popper-opts="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ {
|
:popper-opts="$options.dropdownPopperOpts"
|
||||||
positionFixed: true,
|
|
||||||
} /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
|
|
||||||
@hide="handleHide($event)"
|
@hide="handleHide($event)"
|
||||||
>
|
>
|
||||||
<gl-dropdown-item @click="runCommand('addColumnBefore')">
|
<gl-dropdown-item @click="runCommand('addColumnBefore')">
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { GlTooltipDirective, GlSafeHtmlDirective, GlIcon, GlLoadingIcon } from '
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import { s__, sprintf } from '~/locale';
|
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 { UNFOLD_COUNT, INLINE_DIFF_LINES_KEY } from '../constants';
|
||||||
import * as utils from '../store/utils';
|
import * as utils from '../store/utils';
|
||||||
|
|
||||||
|
@ -24,7 +23,6 @@ export default {
|
||||||
GlTooltip: GlTooltipDirective,
|
GlTooltip: GlTooltipDirective,
|
||||||
SafeHtml: GlSafeHtmlDirective,
|
SafeHtml: GlSafeHtmlDirective,
|
||||||
},
|
},
|
||||||
mixins: [glFeatureFlagsMixin()],
|
|
||||||
props: {
|
props: {
|
||||||
file: {
|
file: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -93,25 +91,16 @@ export default {
|
||||||
nextLineNumbers = {},
|
nextLineNumbers = {},
|
||||||
) {
|
) {
|
||||||
this.loadMoreLines({ endpoint, params, lineNumbers, fileHash, isExpandDown, nextLineNumbers })
|
this.loadMoreLines({ endpoint, params, lineNumbers, fileHash, isExpandDown, nextLineNumbers })
|
||||||
.then(() => {
|
|
||||||
this.isRequesting = false;
|
|
||||||
})
|
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
createFlash({
|
createFlash({
|
||||||
message: s__('Diffs|Something went wrong while fetching diff lines.'),
|
message: s__('Diffs|Something went wrong while fetching diff lines.'),
|
||||||
});
|
});
|
||||||
this.isRequesting = false;
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = { up: false, down: false, all: false };
|
this.loading = { up: false, down: false, all: false };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleExpandLines(type = EXPAND_ALL) {
|
handleExpandLines(type = EXPAND_ALL) {
|
||||||
if (this.isRequesting) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isRequesting = true;
|
|
||||||
const endpoint = this.file.context_lines_path;
|
const endpoint = this.file.context_lines_path;
|
||||||
const oldLineNumber = this.line.meta_data.old_pos || 0;
|
const oldLineNumber = this.line.meta_data.old_pos || 0;
|
||||||
const newLineNumber = this.line.meta_data.new_pos || 0;
|
const newLineNumber = this.line.meta_data.new_pos || 0;
|
||||||
|
@ -228,10 +217,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="diff-grid-row diff-grid-row-full diff-tr line_holder match expansion">
|
||||||
v-if="glFeatures.updatedDiffExpansionButtons"
|
|
||||||
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="{ parallel: !inline }" class="diff-grid-left diff-grid-2-col left-side">
|
||||||
<div
|
<div
|
||||||
class="diff-td diff-line-num gl-text-center! gl-p-0! gl-w-full! gl-display-flex gl-flex-direction-column"
|
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-if="showExpandDown"
|
||||||
v-gl-tooltip.left
|
v-gl-tooltip.left
|
||||||
:title="s__('Diffs|Next 20 lines')"
|
:title="s__('Diffs|Next 20 lines')"
|
||||||
|
:disabled="loading.down"
|
||||||
type="button"
|
type="button"
|
||||||
class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button"
|
class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button"
|
||||||
@click="handleExpandLines($options.EXPAND_DOWN)"
|
@click="handleExpandLines($options.EXPAND_DOWN)"
|
||||||
|
@ -251,6 +238,7 @@ export default {
|
||||||
v-if="lineCountBetween !== -1 && lineCountBetween < 20"
|
v-if="lineCountBetween !== -1 && lineCountBetween < 20"
|
||||||
v-gl-tooltip.left
|
v-gl-tooltip.left
|
||||||
:title="s__('Diffs|Expand all lines')"
|
:title="s__('Diffs|Expand all lines')"
|
||||||
|
:disabled="loading.all"
|
||||||
type="button"
|
type="button"
|
||||||
class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button"
|
class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button"
|
||||||
@click="handleExpandLines()"
|
@click="handleExpandLines()"
|
||||||
|
@ -262,6 +250,7 @@ export default {
|
||||||
v-if="showExpandUp"
|
v-if="showExpandUp"
|
||||||
v-gl-tooltip.left
|
v-gl-tooltip.left
|
||||||
:title="s__('Diffs|Previous 20 lines')"
|
:title="s__('Diffs|Previous 20 lines')"
|
||||||
|
:disabled="loading.up"
|
||||||
type="button"
|
type="button"
|
||||||
class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button"
|
class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button"
|
||||||
@click="handleExpandLines($options.EXPAND_UP)"
|
@click="handleExpandLines($options.EXPAND_UP)"
|
||||||
|
@ -276,32 +265,4 @@ export default {
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</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>
|
</template>
|
||||||
|
|
|
@ -6,7 +6,6 @@ import DraftNote from '~/batch_comments/components/draft_note.vue';
|
||||||
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
|
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
|
||||||
import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
|
import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
|
||||||
import { hide } from '~/tooltips';
|
import { hide } from '~/tooltips';
|
||||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
|
||||||
import { pickDirection } from '../utils/diff_line';
|
import { pickDirection } from '../utils/diff_line';
|
||||||
import DiffCommentCell from './diff_comment_cell.vue';
|
import DiffCommentCell from './diff_comment_cell.vue';
|
||||||
import DiffExpansionCell from './diff_expansion_cell.vue';
|
import DiffExpansionCell from './diff_expansion_cell.vue';
|
||||||
|
@ -23,11 +22,7 @@ export default {
|
||||||
directives: {
|
directives: {
|
||||||
SafeHtml,
|
SafeHtml,
|
||||||
},
|
},
|
||||||
mixins: [
|
mixins: [draftCommentsMixin, IdState({ idProp: (vm) => vm.diffFile.file_hash })],
|
||||||
draftCommentsMixin,
|
|
||||||
glFeatureFlagsMixin(),
|
|
||||||
IdState({ idProp: (vm) => vm.diffFile.file_hash }),
|
|
||||||
],
|
|
||||||
props: {
|
props: {
|
||||||
diffFile: {
|
diffFile: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -171,7 +166,6 @@ export default {
|
||||||
<template v-for="(line, index) in diffLines">
|
<template v-for="(line, index) in diffLines">
|
||||||
<template v-if="line.isMatchLineLeft || line.isMatchLineRight">
|
<template v-if="line.isMatchLineLeft || line.isMatchLineRight">
|
||||||
<diff-expansion-cell
|
<diff-expansion-cell
|
||||||
v-if="glFeatures.updatedDiffExpansionButtons"
|
|
||||||
:key="`expand-${index}`"
|
:key="`expand-${index}`"
|
||||||
:file="diffFile"
|
:file="diffFile"
|
||||||
:line="line.left"
|
:line="line.left"
|
||||||
|
@ -180,41 +174,6 @@ export default {
|
||||||
:inline="inline"
|
:inline="inline"
|
||||||
:line-count-between="getCountBetweenIndex(index)"
|
: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>
|
</template>
|
||||||
<diff-row
|
<diff-row
|
||||||
v-if="!line.isMatchLineLeft && !line.isMatchLineRight"
|
v-if="!line.isMatchLineLeft && !line.isMatchLineRight"
|
||||||
|
|
|
@ -24,6 +24,9 @@ export default {
|
||||||
i18n: {
|
i18n: {
|
||||||
stage: __('Stage:'),
|
stage: __('Stage:'),
|
||||||
},
|
},
|
||||||
|
dropdownPopperOpts: {
|
||||||
|
placement: 'bottom',
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
CiIcon,
|
CiIcon,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
|
@ -114,9 +117,7 @@ export default {
|
||||||
variant="link"
|
variant="link"
|
||||||
:aria-label="stageAriaLabel(stage.title)"
|
:aria-label="stageAriaLabel(stage.title)"
|
||||||
:lazy="true"
|
:lazy="true"
|
||||||
:popper-opts="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ {
|
:popper-opts="$options.dropdownPopperOpts"
|
||||||
placement: 'bottom',
|
|
||||||
} /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
|
|
||||||
:toggle-class="['gl-rounded-full!']"
|
:toggle-class="['gl-rounded-full!']"
|
||||||
menu-class="mini-pipeline-graph-dropdown-menu"
|
menu-class="mini-pipeline-graph-dropdown-menu"
|
||||||
@hide="onHideDropdown"
|
@hide="onHideDropdown"
|
||||||
|
|
|
@ -456,19 +456,6 @@ table.code {
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
border-radius: 0 0 $border-radius-default $border-radius-default;
|
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,
|
.diff-tr.line_holder .diff-td,
|
||||||
tr.line_holder td {
|
tr.line_holder td {
|
||||||
line-height: $code-line-height;
|
line-height: $code-line-height;
|
||||||
|
@ -611,10 +598,6 @@ table.code {
|
||||||
grid-template-columns: 50px 8px 0 1fr;
|
grid-template-columns: 50px 8px 0 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.diff-grid-3-col {
|
|
||||||
grid-template-columns: 50px 1fr !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.diff-grid-2-col {
|
.diff-grid-2-col {
|
||||||
grid-template-columns: 100px 1fr !important;
|
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 {
|
.diff-grid-comments {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|
|
@ -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 {
|
@mixin dark-diff-expansion-line {
|
||||||
&.expansion .diff-td {
|
&.expansion .diff-td {
|
||||||
|
|
|
@ -154,10 +154,6 @@ $dark-il: #de935f;
|
||||||
color: $dark-line-color;
|
color: $dark-line-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.old-line_expansion {
|
|
||||||
@include old-diff-expansion($dark-main-bg, $dark-border, $dark-na);
|
|
||||||
}
|
|
||||||
|
|
||||||
.diff-line-expand-button {
|
.diff-line-expand-button {
|
||||||
@include diff-expansion($gray-600, $gray-200, $gray-300, $white);
|
@include diff-expansion($gray-600, $gray-200, $gray-300, $white);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,10 +125,6 @@ $monokai-gh: #75715e;
|
||||||
color: $monokai-text-color;
|
color: $monokai-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.old-line_expansion {
|
|
||||||
@include old-diff-expansion($monokai-bg, $monokai-border, $monokai-k);
|
|
||||||
}
|
|
||||||
|
|
||||||
.diff-line-expand-button {
|
.diff-line-expand-button {
|
||||||
@include diff-expansion($gray-600, $gray-200, $gray-300, $white);
|
@include diff-expansion($gray-600, $gray-200, $gray-300, $white);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,6 @@
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.old-line_expansion {
|
|
||||||
@include old-diff-expansion($gray-light, $white-normal, $gl-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.diff-line-expand-button {
|
.diff-line-expand-button {
|
||||||
@include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
|
@include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,10 +128,6 @@ $solarized-dark-il: #2aa198;
|
||||||
color: $solarized-dark-pre-color;
|
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 {
|
.diff-line-expand-button {
|
||||||
@include diff-expansion(lighten($solarized-dark-pre-bg, 10%), $gray-200, lighten($solarized-dark-pre-bg, 20%), $white);
|
@include diff-expansion(lighten($solarized-dark-pre-bg, 10%), $gray-200, lighten($solarized-dark-pre-bg, 20%), $white);
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,10 +134,6 @@ $solarized-light-il: #2aa198;
|
||||||
background-color: $solarized-light-pre-bg;
|
background-color: $solarized-light-pre-bg;
|
||||||
color: $solarized-light-pre-color;
|
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 {
|
.diff-line-expand-button {
|
||||||
@include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
|
@include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
|
||||||
|
|
|
@ -133,19 +133,6 @@ pre.code,
|
||||||
color: $white-code-color;
|
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 {
|
.diff-line-expand-button {
|
||||||
@include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
|
@include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
||||||
push_frontend_feature_flag(:rebase_without_ci_ui, project)
|
push_frontend_feature_flag(:rebase_without_ci_ui, project)
|
||||||
push_frontend_feature_flag(:issue_assignees_widget, @project)
|
push_frontend_feature_flag(:issue_assignees_widget, @project)
|
||||||
push_frontend_feature_flag(:realtime_labels, 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(:refactor_security_extension, @project)
|
||||||
push_frontend_feature_flag(:mr_attention_requests, current_user)
|
push_frontend_feature_flag(:mr_attention_requests, current_user)
|
||||||
push_frontend_feature_flag(:remove_diff_header_icons, project)
|
push_frontend_feature_flag(:remove_diff_header_icons, project)
|
||||||
|
|
|
@ -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
|
|
|
@ -296,18 +296,6 @@ namespace = Namespace.find_by_full_path("<new_namespace>")
|
||||||
::Projects::TransferService.new(p, current_user).execute(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
|
### Bulk update service integration password for _all_ projects
|
||||||
|
|
||||||
For example, change the Jira user's password for all projects that have the Jira
|
For example, change the Jira user's password for all projects that have the Jira
|
||||||
|
|
|
@ -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
|
## Create an issue link
|
||||||
|
|
||||||
Creates a two-way relation between two issues. The user must be allowed to
|
Creates a two-way relation between two issues. The user must be allowed to
|
||||||
|
|
|
@ -100,7 +100,7 @@ to automatically split the job into batches:
|
||||||
```ruby
|
```ruby
|
||||||
queue_background_migration_jobs_by_range_at_intervals(
|
queue_background_migration_jobs_by_range_at_intervals(
|
||||||
ClassName,
|
ClassName,
|
||||||
BackgroundMigrationClassName,
|
'BackgroundMigrationClassName',
|
||||||
2.minutes,
|
2.minutes,
|
||||||
batch_size: 10_000
|
batch_size: 10_000
|
||||||
)
|
)
|
||||||
|
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
@ -187,17 +187,17 @@ To view epics in a group:
|
||||||
The total count of open epics displayed in the sidebar is cached if higher
|
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.
|
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.
|
> - Filtering by epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9.
|
||||||
> - Searching by the user's reaction emoji [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325630) in GitLab 13.11.
|
> - 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.
|
> - 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.
|
> - [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.
|
> - [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
|
You can filter the list of epics by:
|
||||||
parameters:
|
|
||||||
|
|
||||||
- Title or description
|
- Title or description
|
||||||
- Author name / username
|
- Author name / username
|
||||||
|
@ -206,9 +206,9 @@ parameters:
|
||||||
- Confidentiality
|
- Confidentiality
|
||||||
- Reaction emoji
|
- 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 top bar, select **Menu > Groups** and find your group.
|
||||||
1. On the left sidebar, select **Epics**.
|
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. 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.
|
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
|
- Start date
|
||||||
- Due date
|
- Due date
|
||||||
|
|
|
@ -45,7 +45,7 @@ To learn how the GitLab Strategic Marketing department uses GitLab issues with [
|
||||||
- [Health status](managing_issues.md#health-status)
|
- [Health status](managing_issues.md#health-status)
|
||||||
- [Cross-link issues](crosslinking_issues.md)
|
- [Cross-link issues](crosslinking_issues.md)
|
||||||
- [Sort issue lists](sorting_issue_lists.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)
|
- [Epics](../../group/epics/index.md)
|
||||||
- [Issue boards](../issue_board.md)
|
- [Issue boards](../issue_board.md)
|
||||||
- [Issues API](../../../api/issues.md)
|
- [Issues API](../../../api/issues.md)
|
||||||
|
|
|
@ -576,6 +576,30 @@ Or:
|
||||||
- To use a [keyboard shortcut](../../shortcuts.md), press <kbd>Shift</kbd> + <kbd>i</kbd>.
|
- 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**.
|
- 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
|
### Filter issues by ID
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) in GitLab 12.1.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) in GitLab 12.1.
|
||||||
|
|
|
@ -60,6 +60,24 @@ Or:
|
||||||
- [Review requests](reviews/index.md).
|
- [Review requests](reviews/index.md).
|
||||||
- Merge requests assigned.
|
- 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
|
### Filter merge requests by ID
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) in GitLab 12.1.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39908) in GitLab 12.1.
|
||||||
|
|
|
@ -31,6 +31,7 @@ Use basic search to find:
|
||||||
## Perform a search
|
## Perform a search
|
||||||
|
|
||||||
To start a search, type your search query in the search bar on the top-right of the screen.
|
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)
|
![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)
|
![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
|
## Searching for specific terms
|
||||||
|
|
||||||
You can filter issues and merge requests by specific terms included in titles or descriptions.
|
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. Go to your project's page.
|
||||||
1. On the left sidebar, select **Issues** or **Merge requests**.
|
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.
|
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.
|
The URL of the result contains both a feed token, and your search query.
|
||||||
You can add this URL to your feed reader.
|
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
|
||||||
|
|
||||||
Search history is available for issues and merge requests, and is stored locally
|
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)
|
![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
|
## Issue boards
|
||||||
|
|
||||||
From an [issue board](../../user/project/issue_board.md), you can filter issues by **Author**, **Assignee**, **Milestone**, and **Labels**.
|
From an [issue board](../../user/project/issue_board.md), you can filter issues by **Author**, **Assignee**, **Milestone**, and **Labels**.
|
||||||
|
|
|
@ -61,6 +61,22 @@ module API
|
||||||
end
|
end
|
||||||
# rubocop: enable CodeReuse/ActiveRecord
|
# 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
|
desc 'Remove issues relation' do
|
||||||
success Entities::IssueLink
|
success Entities::IssueLink
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { getByText } from '@testing-library/dom';
|
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
|
import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
|
||||||
|
@ -81,7 +80,7 @@ describe('DiffExpansionCell', () => {
|
||||||
|
|
||||||
const findExpandUp = (wrapper) => wrapper.find(EXPAND_UP_CLASS);
|
const findExpandUp = (wrapper) => wrapper.find(EXPAND_UP_CLASS);
|
||||||
const findExpandDown = (wrapper) => wrapper.find(EXPAND_DOWN_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', () => {
|
describe('top row', () => {
|
||||||
it('should have "expand up" and "show all" option', () => {
|
it('should have "expand up" and "show all" option', () => {
|
||||||
|
@ -90,9 +89,7 @@ describe('DiffExpansionCell', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(findExpandUp(wrapper).exists()).toBe(true);
|
expect(findExpandUp(wrapper).exists()).toBe(true);
|
||||||
expect(findExpandDown(wrapper).exists()).toBe(true);
|
|
||||||
expect(findExpandUp(wrapper).attributes('disabled')).not.toBeDefined();
|
expect(findExpandUp(wrapper).attributes('disabled')).not.toBeDefined();
|
||||||
expect(findExpandDown(wrapper).attributes('disabled')).toBeDefined();
|
|
||||||
expect(findExpandAll(wrapper)).not.toBe(null);
|
expect(findExpandAll(wrapper)).not.toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -114,9 +111,7 @@ describe('DiffExpansionCell', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(findExpandDown(wrapper).exists()).toBe(true);
|
expect(findExpandDown(wrapper).exists()).toBe(true);
|
||||||
expect(findExpandUp(wrapper).exists()).toBe(true);
|
|
||||||
expect(findExpandDown(wrapper).attributes('disabled')).not.toBeDefined();
|
expect(findExpandDown(wrapper).attributes('disabled')).not.toBeDefined();
|
||||||
expect(findExpandUp(wrapper).attributes('disabled')).toBeDefined();
|
|
||||||
expect(findExpandAll(wrapper)).not.toBe(null);
|
expect(findExpandAll(wrapper)).not.toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -144,9 +139,9 @@ describe('DiffExpansionCell', () => {
|
||||||
newLineNumber,
|
newLineNumber,
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrapper = createComponent({ file });
|
const wrapper = createComponent({ file, lineCountBetween: 10 });
|
||||||
|
|
||||||
findExpandAll(wrapper).click();
|
findExpandAll(wrapper).trigger('click');
|
||||||
|
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(
|
expect(store.dispatch).toHaveBeenCalledWith(
|
||||||
'diffs/loadMoreLines',
|
'diffs/loadMoreLines',
|
||||||
|
|
|
@ -49,22 +49,6 @@ describe('DiffView', () => {
|
||||||
return shallowMount(DiffView, { propsData, store, stubs });
|
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`
|
it.each`
|
||||||
type | side | container | sides | total
|
type | side | container | sides | total
|
||||||
${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true }, right: { lineDraft: {}, renderDiscussion: true } }} | ${2}
|
${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true }, right: { lineDraft: {}, renderDiscussion: true } }} | ${2}
|
||||||
|
|
|
@ -156,6 +156,87 @@ RSpec.describe API::IssueLinks do
|
||||||
end
|
end
|
||||||
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
|
describe 'DELETE /links/:issue_link_id' do
|
||||||
context 'when unauthenticated' do
|
context 'when unauthenticated' do
|
||||||
it 'returns 401' do
|
it 'returns 401' do
|
||||||
|
|
Loading…
Reference in New Issue