Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
616cd97932
commit
cba55463a0
23 changed files with 314 additions and 305 deletions
|
@ -19,6 +19,7 @@ import { updateHistory } from '~/lib/utils/url_utility';
|
|||
import { __ } from '~/locale';
|
||||
import MrWidgetHowToMergeModal from '~/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue';
|
||||
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
|
||||
import notesEventHub from '../../notes/event_hub';
|
||||
import {
|
||||
|
@ -79,6 +80,7 @@ export default {
|
|||
MrWidgetHowToMergeModal,
|
||||
GlAlert,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
alerts: {
|
||||
ALERT_OVERFLOW_HIDDEN,
|
||||
ALERT_MERGE_CONFLICT,
|
||||
|
@ -252,6 +254,10 @@ export default {
|
|||
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
|
||||
},
|
||||
isLimitedContainer() {
|
||||
if (this.glFeatures.mrChangesFluidLayout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !this.renderFileTree && !this.isParallelView && !this.isFluidLayout;
|
||||
},
|
||||
isFullChangeset() {
|
||||
|
@ -386,6 +392,8 @@ export default {
|
|||
diffsApp.instrument();
|
||||
},
|
||||
created() {
|
||||
this.mergeRequestContainers = document.querySelectorAll('.merge-request-container');
|
||||
|
||||
this.adjustView();
|
||||
this.subscribeToEvents();
|
||||
|
||||
|
@ -513,6 +521,13 @@ export default {
|
|||
} else {
|
||||
this.removeEventListeners();
|
||||
}
|
||||
|
||||
if (!this.isFluidLayout && this.glFeatures.mrChangesFluidLayout) {
|
||||
this.mergeRequestContainers.forEach((el) => {
|
||||
el.classList.toggle('limit-container-width', !this.shouldShow);
|
||||
el.classList.toggle('container-limited', !this.shouldShow);
|
||||
});
|
||||
}
|
||||
},
|
||||
setEventListeners() {
|
||||
Mousetrap.bind(keysFor(MR_PREVIOUS_FILE_IN_DIFF), () => this.jumpToFile(-1));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
|
||||
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { isScopedLabel } from '~/lib/utils/common_utils';
|
||||
|
@ -15,6 +15,7 @@ export default {
|
|||
GlIcon,
|
||||
GlLabel,
|
||||
GlFormCheckbox,
|
||||
GlSprintf,
|
||||
IssuableAssignees,
|
||||
},
|
||||
directives: {
|
||||
|
@ -82,9 +83,7 @@ export default {
|
|||
return this.issuable.assignees?.nodes || this.issuable.assignees || [];
|
||||
},
|
||||
createdAt() {
|
||||
return sprintf(__('created %{timeAgo}'), {
|
||||
timeAgo: getTimeago().format(this.issuable.createdAt),
|
||||
});
|
||||
return getTimeago().format(this.issuable.createdAt);
|
||||
},
|
||||
updatedAt() {
|
||||
return sprintf(__('updated %{timeAgo}'), {
|
||||
|
@ -164,132 +163,132 @@ export default {
|
|||
<template>
|
||||
<li
|
||||
:id="`issuable_${issuableId}`"
|
||||
class="issue gl-px-5!"
|
||||
class="issue gl-display-flex! gl-px-5!"
|
||||
:class="{ closed: issuable.closedAt, today: createdInPastDay }"
|
||||
:data-labels="labelIdsString"
|
||||
>
|
||||
<div class="issuable-info-container">
|
||||
<div v-if="showCheckbox" class="issue-check">
|
||||
<gl-form-checkbox
|
||||
class="gl-mr-0"
|
||||
:checked="checked"
|
||||
:data-id="issuableId"
|
||||
@input="$emit('checked-input', $event)"
|
||||
<gl-form-checkbox
|
||||
v-if="showCheckbox"
|
||||
class="issue-check gl-mr-0"
|
||||
:checked="checked"
|
||||
:data-id="issuableId"
|
||||
@input="$emit('checked-input', $event)"
|
||||
>
|
||||
<span class="gl-sr-only">{{ issuable.title }}</span>
|
||||
</gl-form-checkbox>
|
||||
<div class="issuable-main-info">
|
||||
<div data-testid="issuable-title" class="issue-title title">
|
||||
<gl-icon
|
||||
v-if="issuable.confidential"
|
||||
v-gl-tooltip
|
||||
name="eye-slash"
|
||||
:title="__('Confidential')"
|
||||
:aria-label="__('Confidential')"
|
||||
/>
|
||||
<gl-link class="issue-title-text" dir="auto" :href="webUrl" v-bind="issuableTitleProps">
|
||||
{{ issuable.title }}
|
||||
<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2" />
|
||||
</gl-link>
|
||||
<span
|
||||
v-if="taskStatus"
|
||||
class="task-status gl-display-none gl-sm-display-inline-block! gl-ml-3"
|
||||
data-testid="task-status"
|
||||
>
|
||||
<span class="gl-sr-only">{{ issuable.title }}</span>
|
||||
</gl-form-checkbox>
|
||||
{{ taskStatus }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="issuable-main-info">
|
||||
<div data-testid="issuable-title" class="issue-title title">
|
||||
<span class="issue-title-text" dir="auto">
|
||||
<gl-icon
|
||||
v-if="issuable.confidential"
|
||||
v-gl-tooltip
|
||||
name="eye-slash"
|
||||
:title="__('Confidential')"
|
||||
:aria-label="__('Confidential')"
|
||||
/>
|
||||
<gl-link :href="webUrl" v-bind="issuableTitleProps">
|
||||
{{ issuable.title
|
||||
}}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2"
|
||||
/></gl-link>
|
||||
</span>
|
||||
<span
|
||||
v-if="taskStatus"
|
||||
class="task-status gl-display-none gl-sm-display-inline-block! gl-ml-3"
|
||||
data-testid="task-status"
|
||||
>
|
||||
{{ taskStatus }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="issuable-info">
|
||||
<slot v-if="hasSlotContents('reference')" name="reference"></slot>
|
||||
<span v-else data-testid="issuable-reference" class="issuable-reference">
|
||||
{{ reference }}
|
||||
</span>
|
||||
<span class="issuable-authored gl-display-none gl-sm-display-inline-block! gl-mr-3">
|
||||
<span aria-hidden="true">·</span>
|
||||
<span
|
||||
v-gl-tooltip:tooltipcontainer.bottom
|
||||
data-testid="issuable-created-at"
|
||||
:title="tooltipTitle(issuable.createdAt)"
|
||||
>{{ createdAt }}</span
|
||||
>
|
||||
{{ __('by') }}
|
||||
<slot v-if="hasSlotContents('author')" name="author"></slot>
|
||||
<gl-link
|
||||
v-else
|
||||
:data-user-id="authorId"
|
||||
:data-username="author.username"
|
||||
:data-name="author.name"
|
||||
:data-avatar-url="author.avatarUrl"
|
||||
:href="author.webUrl"
|
||||
data-testid="issuable-author"
|
||||
class="author-link js-user-link"
|
||||
>
|
||||
<span class="author">{{ author.name }}</span>
|
||||
</gl-link>
|
||||
<div class="issuable-info">
|
||||
<slot v-if="hasSlotContents('reference')" name="reference"></slot>
|
||||
<span v-else data-testid="issuable-reference" class="issuable-reference">
|
||||
{{ reference }}
|
||||
</span>
|
||||
<span class="gl-display-none gl-sm-display-inline-block">
|
||||
<span aria-hidden="true">·</span>
|
||||
<span class="issuable-authored gl-mr-3">
|
||||
<gl-sprintf :message="__('created %{timeAgo} by %{author}')">
|
||||
<template #timeAgo>
|
||||
<span
|
||||
v-gl-tooltip.bottom
|
||||
:title="tooltipTitle(issuable.createdAt)"
|
||||
data-testid="issuable-created-at"
|
||||
>
|
||||
{{ createdAt }}
|
||||
</span>
|
||||
</template>
|
||||
<template #author>
|
||||
<slot v-if="hasSlotContents('author')" name="author"></slot>
|
||||
<gl-link
|
||||
v-else
|
||||
:data-user-id="authorId"
|
||||
:data-username="author.username"
|
||||
:data-name="author.name"
|
||||
:data-avatar-url="author.avatarUrl"
|
||||
:href="author.webUrl"
|
||||
data-testid="issuable-author"
|
||||
class="author-link js-user-link"
|
||||
>
|
||||
<span class="author">{{ author.name }}</span>
|
||||
</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
<slot name="timeframe"></slot>
|
||||
|
||||
<span v-if="labels.length" role="group" :aria-label="__('Labels')">
|
||||
<gl-label
|
||||
v-for="(label, index) in labels"
|
||||
:key="index"
|
||||
:background-color="label.color"
|
||||
:title="labelTitle(label)"
|
||||
:description="label.description"
|
||||
:scoped="scopedLabel(label)"
|
||||
:target="labelTarget(label)"
|
||||
:class="{ 'gl-ml-2': index }"
|
||||
size="sm"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span v-if="labels.length" role="group" :aria-label="__('Labels')">
|
||||
<gl-label
|
||||
v-for="(label, index) in labels"
|
||||
:key="index"
|
||||
:background-color="label.color"
|
||||
:title="labelTitle(label)"
|
||||
:description="label.description"
|
||||
:scoped="scopedLabel(label)"
|
||||
:target="labelTarget(label)"
|
||||
:class="{ 'gl-ml-2': index }"
|
||||
size="sm"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="issuable-meta">
|
||||
<ul v-if="showIssuableMeta" class="controls">
|
||||
<li v-if="hasSlotContents('status')" class="issuable-status">
|
||||
<slot name="status"></slot>
|
||||
</li>
|
||||
<li v-if="assignees.length" class="gl-display-flex">
|
||||
<issuable-assignees
|
||||
:assignees="assignees"
|
||||
:icon-size="16"
|
||||
:max-visible="4"
|
||||
img-css-classes="gl-mr-2!"
|
||||
class="gl-align-items-center gl-display-flex gl-ml-3"
|
||||
/>
|
||||
</li>
|
||||
<slot name="statistics"></slot>
|
||||
<li
|
||||
v-if="showDiscussions"
|
||||
data-testid="issuable-discussions"
|
||||
class="issuable-comments gl-display-none gl-sm-display-block"
|
||||
>
|
||||
<gl-link
|
||||
v-gl-tooltip:tooltipcontainer.top
|
||||
:title="__('Comments')"
|
||||
:href="issuableNotesLink"
|
||||
:class="{ 'no-comments': !notesCount }"
|
||||
class="gl-reset-color!"
|
||||
>
|
||||
<gl-icon name="comments" />
|
||||
{{ notesCount }}
|
||||
</gl-link>
|
||||
</li>
|
||||
</ul>
|
||||
<div
|
||||
data-testid="issuable-updated-at"
|
||||
class="float-right issuable-updated-at gl-display-none gl-sm-display-inline-block"
|
||||
</div>
|
||||
<div class="issuable-meta">
|
||||
<ul v-if="showIssuableMeta" class="controls">
|
||||
<li v-if="hasSlotContents('status')" class="issuable-status">
|
||||
<slot name="status"></slot>
|
||||
</li>
|
||||
<li v-if="assignees.length">
|
||||
<issuable-assignees
|
||||
:assignees="assignees"
|
||||
:icon-size="16"
|
||||
:max-visible="4"
|
||||
img-css-classes="gl-mr-2!"
|
||||
class="gl-align-items-center gl-display-flex gl-ml-3"
|
||||
/>
|
||||
</li>
|
||||
<slot name="statistics"></slot>
|
||||
<li
|
||||
v-if="showDiscussions"
|
||||
data-testid="issuable-discussions"
|
||||
class="issuable-comments gl-display-none gl-sm-display-block"
|
||||
>
|
||||
<span
|
||||
v-gl-tooltip:tooltipcontainer.bottom
|
||||
:title="tooltipTitle(issuable.updatedAt)"
|
||||
class="issuable-updated-at"
|
||||
>{{ updatedAt }}</span
|
||||
<gl-link
|
||||
v-gl-tooltip.top
|
||||
:title="__('Comments')"
|
||||
:href="issuableNotesLink"
|
||||
:class="{ 'no-comments': !notesCount }"
|
||||
class="gl-reset-color!"
|
||||
>
|
||||
</div>
|
||||
<gl-icon name="comments" />
|
||||
{{ notesCount }}
|
||||
</gl-link>
|
||||
</li>
|
||||
</ul>
|
||||
<div
|
||||
v-gl-tooltip.bottom
|
||||
class="gl-text-gray-500 gl-display-none gl-sm-display-inline-block"
|
||||
:title="tooltipTitle(issuable.updatedAt)"
|
||||
data-testid="issuable-updated-at"
|
||||
>
|
||||
{{ updatedAt }}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -284,72 +284,70 @@ export default {
|
|||
<slot name="sidebar-items" :checked-issuables="bulkEditIssuables"></slot>
|
||||
</template>
|
||||
</issuable-bulk-edit-sidebar>
|
||||
<div class="issuables-holder">
|
||||
<ul v-if="issuablesLoading" class="content-list">
|
||||
<li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
|
||||
<gl-skeleton-loading />
|
||||
</li>
|
||||
</ul>
|
||||
<template v-else>
|
||||
<component
|
||||
:is="issuablesWrapper"
|
||||
v-if="issuables.length > 0"
|
||||
class="content-list issuable-list issues-list"
|
||||
:class="{ 'manual-ordering': isManualOrdering }"
|
||||
v-bind="$options.vueDraggableAttributes"
|
||||
@update="handleVueDraggableUpdate"
|
||||
<ul v-if="issuablesLoading" class="content-list">
|
||||
<li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
|
||||
<gl-skeleton-loading />
|
||||
</li>
|
||||
</ul>
|
||||
<template v-else>
|
||||
<component
|
||||
:is="issuablesWrapper"
|
||||
v-if="issuables.length > 0"
|
||||
class="content-list issuable-list issues-list"
|
||||
:class="{ 'manual-ordering': isManualOrdering }"
|
||||
v-bind="$options.vueDraggableAttributes"
|
||||
@update="handleVueDraggableUpdate"
|
||||
>
|
||||
<issuable-item
|
||||
v-for="issuable in issuables"
|
||||
:key="issuableId(issuable)"
|
||||
:class="{ 'gl-cursor-grab': isManualOrdering }"
|
||||
:issuable-symbol="issuableSymbol"
|
||||
:issuable="issuable"
|
||||
:enable-label-permalinks="enableLabelPermalinks"
|
||||
:label-filter-param="labelFilterParam"
|
||||
:show-checkbox="showBulkEditSidebar"
|
||||
:checked="issuableChecked(issuable)"
|
||||
@checked-input="handleIssuableCheckedInput(issuable, $event)"
|
||||
>
|
||||
<issuable-item
|
||||
v-for="issuable in issuables"
|
||||
:key="issuableId(issuable)"
|
||||
:class="{ 'gl-cursor-grab': isManualOrdering }"
|
||||
:issuable-symbol="issuableSymbol"
|
||||
:issuable="issuable"
|
||||
:enable-label-permalinks="enableLabelPermalinks"
|
||||
:label-filter-param="labelFilterParam"
|
||||
:show-checkbox="showBulkEditSidebar"
|
||||
:checked="issuableChecked(issuable)"
|
||||
@checked-input="handleIssuableCheckedInput(issuable, $event)"
|
||||
>
|
||||
<template #reference>
|
||||
<slot name="reference" :issuable="issuable"></slot>
|
||||
</template>
|
||||
<template #author>
|
||||
<slot name="author" :author="issuable.author"></slot>
|
||||
</template>
|
||||
<template #timeframe>
|
||||
<slot name="timeframe" :issuable="issuable"></slot>
|
||||
</template>
|
||||
<template #status>
|
||||
<slot name="status" :issuable="issuable"></slot>
|
||||
</template>
|
||||
<template #statistics>
|
||||
<slot name="statistics" :issuable="issuable"></slot>
|
||||
</template>
|
||||
</issuable-item>
|
||||
</component>
|
||||
<slot v-else name="empty-state"></slot>
|
||||
</template>
|
||||
<template #reference>
|
||||
<slot name="reference" :issuable="issuable"></slot>
|
||||
</template>
|
||||
<template #author>
|
||||
<slot name="author" :author="issuable.author"></slot>
|
||||
</template>
|
||||
<template #timeframe>
|
||||
<slot name="timeframe" :issuable="issuable"></slot>
|
||||
</template>
|
||||
<template #status>
|
||||
<slot name="status" :issuable="issuable"></slot>
|
||||
</template>
|
||||
<template #statistics>
|
||||
<slot name="statistics" :issuable="issuable"></slot>
|
||||
</template>
|
||||
</issuable-item>
|
||||
</component>
|
||||
<slot v-else name="empty-state"></slot>
|
||||
</template>
|
||||
|
||||
<div v-if="showPaginationControls && useKeysetPagination" class="gl-text-center gl-mt-3">
|
||||
<gl-keyset-pagination
|
||||
:has-next-page="hasNextPage"
|
||||
:has-previous-page="hasPreviousPage"
|
||||
@next="$emit('next-page')"
|
||||
@prev="$emit('previous-page')"
|
||||
/>
|
||||
</div>
|
||||
<gl-pagination
|
||||
v-else-if="showPaginationControls"
|
||||
:per-page="defaultPageSize"
|
||||
:total-items="totalItems"
|
||||
:value="currentPage"
|
||||
:prev-page="previousPage"
|
||||
:next-page="nextPage"
|
||||
align="center"
|
||||
class="gl-pagination gl-mt-3"
|
||||
@input="$emit('page-change', $event)"
|
||||
<div v-if="showPaginationControls && useKeysetPagination" class="gl-text-center gl-mt-3">
|
||||
<gl-keyset-pagination
|
||||
:has-next-page="hasNextPage"
|
||||
:has-previous-page="hasPreviousPage"
|
||||
@next="$emit('next-page')"
|
||||
@prev="$emit('previous-page')"
|
||||
/>
|
||||
</div>
|
||||
<gl-pagination
|
||||
v-else-if="showPaginationControls"
|
||||
:per-page="defaultPageSize"
|
||||
:total-items="totalItems"
|
||||
:value="currentPage"
|
||||
:prev-page="previousPage"
|
||||
:next-page="nextPage"
|
||||
align="center"
|
||||
class="gl-pagination gl-mt-3"
|
||||
@input="$emit('page-change', $event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -85,7 +85,7 @@ export default {
|
|||
<span>
|
||||
<span
|
||||
v-if="issue.milestone"
|
||||
class="issuable-milestone gl-display-none gl-sm-display-inline-block! gl-mr-3"
|
||||
class="issuable-milestone gl-mr-3"
|
||||
data-testid="issuable-milestone"
|
||||
>
|
||||
<gl-link v-gl-tooltip :href="milestoneLink" :title="milestoneDate">
|
||||
|
@ -96,7 +96,7 @@ export default {
|
|||
<span
|
||||
v-if="issue.dueDate"
|
||||
v-gl-tooltip
|
||||
class="issuable-due-date gl-display-none gl-sm-display-inline-block! gl-mr-3"
|
||||
class="issuable-due-date gl-mr-3"
|
||||
:class="{ 'gl-text-red-500': showDueDateInRed }"
|
||||
:title="__('Due date')"
|
||||
data-testid="issuable-due-date"
|
||||
|
@ -107,21 +107,14 @@ export default {
|
|||
<span
|
||||
v-if="timeEstimate"
|
||||
v-gl-tooltip
|
||||
class="gl-display-none gl-sm-display-inline-block! gl-mr-3"
|
||||
class="gl-mr-3"
|
||||
:title="__('Estimate')"
|
||||
data-testid="time-estimate"
|
||||
>
|
||||
<gl-icon name="timer" />
|
||||
{{ timeEstimate }}
|
||||
</span>
|
||||
<weight-count
|
||||
class="issuable-weight gl-display-none gl-sm-display-inline-block gl-mr-3"
|
||||
:weight="issue.weight"
|
||||
/>
|
||||
<issue-health-status
|
||||
v-if="showHealthStatus"
|
||||
class="gl-display-none gl-sm-display-inline-block"
|
||||
:health-status="healthStatus"
|
||||
/>
|
||||
<weight-count class="issuable-weight gl-mr-3" :weight="issue.weight" />
|
||||
<issue-health-status v-if="showHealthStatus" :health-status="healthStatus" />
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -77,7 +77,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="issue-assignees">
|
||||
<div>
|
||||
<user-avatar-link
|
||||
v-for="assignee in assigneesToShow"
|
||||
:key="assignee.id"
|
||||
|
@ -97,10 +97,9 @@ export default {
|
|||
</user-avatar-link>
|
||||
<span
|
||||
v-if="numHiddenAssignees > 0"
|
||||
v-gl-tooltip
|
||||
v-gl-tooltip.bottom
|
||||
:title="assigneesCounterTooltip"
|
||||
class="avatar-counter"
|
||||
data-placement="bottom"
|
||||
data-qa-selector="avatar_counter_content"
|
||||
>{{ assigneeCounterLabel }}</span
|
||||
>
|
||||
|
|
|
@ -673,40 +673,40 @@
|
|||
.issuable-info-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.issuable-main-info {
|
||||
flex: 1 auto;
|
||||
margin-right: 10px;
|
||||
min-width: 0;
|
||||
.issuable-main-info {
|
||||
flex: 1 auto;
|
||||
margin-right: 10px;
|
||||
min-width: 0;
|
||||
|
||||
.issue-weight-icon,
|
||||
.issue-estimate-icon {
|
||||
vertical-align: sub;
|
||||
}
|
||||
.issue-weight-icon,
|
||||
.issue-estimate-icon {
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
|
||||
.issuable-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
flex: 1 0 auto;
|
||||
|
||||
.controls {
|
||||
margin-bottom: 2px;
|
||||
line-height: 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.issue-updated-at {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(xs) {
|
||||
.issuable-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
flex: 1 0 auto;
|
||||
|
||||
.controls {
|
||||
margin-bottom: 2px;
|
||||
line-height: 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.issue-updated-at {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(xs) {
|
||||
.issuable-meta {
|
||||
.controls li {
|
||||
margin-right: 0;
|
||||
}
|
||||
.controls li {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:diffs_virtual_scrolling, project, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml)
|
||||
|
||||
# Usage data feature flags
|
||||
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: mr_changes_fluid_layout
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70815
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341809
|
||||
milestone: '14.4'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: false
|
|
@ -4,7 +4,7 @@ Rails.backtrace_cleaner.remove_silencers!
|
|||
|
||||
# This allows us to see the proper caller of SQL calls in {development,test}.log
|
||||
if (Rails.env.development? || Rails.env.test?) && Gitlab.ee?
|
||||
Rails.backtrace_cleaner.add_silencer { |line| %r(^ee/lib/gitlab/database/load_balancing).match?(line) }
|
||||
Rails.backtrace_cleaner.add_silencer { |line| %r(^lib/gitlab/database/load_balancing).match?(line) }
|
||||
end
|
||||
|
||||
Rails.backtrace_cleaner.add_silencer { |line| !Gitlab::APP_DIRS_PATTERN.match?(line) }
|
||||
|
|
|
@ -488,29 +488,31 @@ The exported project is located within a `.tar.gz` file in `/var/opt/gitlab/gitl
|
|||
|
||||
If it seems that a commit has gone "missing", search the sequence of pushes to a repository.
|
||||
[This StackOverflow article](https://stackoverflow.com/questions/13468027/the-mystery-of-the-missing-commit-across-merges)
|
||||
describes how you can end up in this state without a force push.
|
||||
describes how you can end up in this state without a force push. Another cause can be a misconfigured [server hook](../server_hooks.md) that changes a HEAD ref via a `git reset` operation.
|
||||
|
||||
If you look at the output from the sample code below for the target branch, you
|
||||
see a discontinuity in the from/to commits as you step through the output. Each new
|
||||
push should be "from" the "to" SHA of the previous push. When this discontinuity happens,
|
||||
you see two pushes with the same "from" SHA:
|
||||
see a discontinuity in the from/to commits as you step through the output. The `commit_from` of each new push should equal the `commit_to` of the previous push. A break in that sequence indicates one or more commits have been "lost" from the repository history.
|
||||
|
||||
```ruby
|
||||
p = Project.find_with_namespace('u/p')
|
||||
p.events.pushed_action.last(100).each do |e|
|
||||
printf "%-20.20s %8s...%8s (%s)\n", e.data[:ref], e.data[:before], e.data[:after], e.author.try(:username)
|
||||
end
|
||||
```
|
||||
|
||||
GitLab 9.5 and above:
|
||||
The following example checks the last 100 pushes and prints the `commit_from` and `commit_to` entries:
|
||||
|
||||
```ruby
|
||||
p = Project.find_by_full_path('u/p')
|
||||
p.events.pushed_action.last(100).each do |e|
|
||||
printf "%-20.20s %8s...%8s (%s)\n", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
|
||||
printf "%-20.20s %8s...%8s (%s)
|
||||
", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
|
||||
end
|
||||
```
|
||||
|
||||
Example output showing break in sequence at line 4:
|
||||
|
||||
```plaintext
|
||||
master f21b07713251e04575908149bdc8ac1f105aabc3...6bc56c1f46244792222f6c85b11606933af171de (root)
|
||||
master 6bc56c1f46244792222f6c85b11606933af171de...132da6064f5d3453d445fd7cb452b148705bdc1b (root)
|
||||
master 132da6064f5d3453d445fd7cb452b148705bdc1b...a62e1e693150a2e46ace0ce696cd4a52856dfa65 (root)
|
||||
master 58b07b719a4b0039fec810efa52f479ba1b84756...f05321a5b5728bd8a89b7bf530aa44043c951dce (root)
|
||||
master f05321a5b5728bd8a89b7bf530aa44043c951dce...7d02e575fd790e76a3284ee435368279a5eb3773 (root)
|
||||
```
|
||||
|
||||
## Mirrors
|
||||
|
||||
### Find mirrors with "bad decrypt" errors
|
||||
|
|
|
@ -9,6 +9,7 @@ type: index, concepts, howto
|
|||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in GitLab Ultimate 10.6.
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to GitLab Free in 11.9.
|
||||
> - `CHAT_USER_ID` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/341798) in GitLab 14.4.
|
||||
|
||||
GitLab ChatOps provides a method to interact with CI/CD jobs through chat services
|
||||
like Slack. Many organizations' discussion, collaboration, and troubleshooting takes
|
||||
|
@ -30,6 +31,7 @@ to the job:
|
|||
|
||||
- `CHAT_INPUT` contains any additional arguments.
|
||||
- `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
|
||||
- `CHAT_USER_ID` is set to the chat service's user ID of the user who triggered the slash command.
|
||||
|
||||
When executed, ChatOps looks up the specified job name and attempts to match it
|
||||
to a corresponding job in [`.gitlab-ci.yml`](../yaml/index.md). If a matching job
|
||||
|
|
|
@ -20,6 +20,7 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
|
|||
|------------------------------------------|--------|--------|-------------|
|
||||
| `CHAT_CHANNEL` | 10.6 | all | The Source chat channel that triggered the [ChatOps](../chatops/index.md) command. |
|
||||
| `CHAT_INPUT` | 10.6 | all | The additional arguments passed with the [ChatOps](../chatops/index.md) command. |
|
||||
| `CHAT_USER_ID` | 14.4 | all | The chat service's user ID of the user who triggered the [ChatOps](../chatops/index.md) command. |
|
||||
| `CI` | all | 0.4 | Available for all jobs executed in CI/CD. `true` when available. |
|
||||
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. |
|
||||
| `CI_BUILDS_DIR` | all | 11.10 | The top-level directory where builds are executed. |
|
||||
|
|
|
@ -31,9 +31,7 @@ attempts. This is because some tables may have been added during the failed
|
|||
upgrade. If these tables are still present after you restore from the
|
||||
older backup it can lead to migration failures on future upgrades.
|
||||
|
||||
Starting in GitLab 8.6 we drop all tables prior to importing the backup to
|
||||
prevent this problem. If you've restored a backup to a version prior to 8.6 you
|
||||
may have to manually correct the problem next time you upgrade.
|
||||
We drop all tables prior to importing the backup to prevent this problem.
|
||||
|
||||
Example error:
|
||||
|
||||
|
@ -52,38 +50,16 @@ Copy the version from the error. In this case the version number is
|
|||
WARNING:
|
||||
Use the following steps only if you are certain you must do them.
|
||||
|
||||
### GitLab 8.6+
|
||||
1. Pass the version to a database Rake task to manually mark the migration as
|
||||
complete.
|
||||
|
||||
Pass the version to a database Rake task to manually mark the migration as
|
||||
complete.
|
||||
```shell
|
||||
# Source install
|
||||
sudo -u git -H bundle exec rake gitlab:db:mark_migration_complete[20151103134857] RAILS_ENV=production
|
||||
|
||||
```shell
|
||||
# Source install
|
||||
sudo -u git -H bundle exec rake gitlab:db:mark_migration_complete[20151103134857] RAILS_ENV=production
|
||||
# Omnibus install
|
||||
sudo gitlab-rake gitlab:db:mark_migration_complete[20151103134857]
|
||||
```
|
||||
|
||||
# Omnibus install
|
||||
sudo gitlab-rake gitlab:db:mark_migration_complete[20151103134857]
|
||||
```
|
||||
|
||||
After the migration is successfully marked, run the Rake `db:migrate` task again.
|
||||
Repeat this process until all failed migrations are complete.
|
||||
|
||||
### GitLab < 8.6
|
||||
|
||||
```shell
|
||||
# Source install
|
||||
sudo -u git -H bundle exec rails console -e production
|
||||
|
||||
# Omnibus install
|
||||
sudo gitlab-rails console
|
||||
```
|
||||
|
||||
At the Rails console, type the following commands:
|
||||
|
||||
```ruby
|
||||
ActiveRecord::Base.connection.execute("INSERT INTO schema_migrations (version) VALUES('20151103134857')")
|
||||
exit
|
||||
```
|
||||
|
||||
After the migration is successfully marked, run the Rake `db:migrate` task again.
|
||||
Repeat this process until all failed migrations are complete.
|
||||
1. After the migration is successfully marked, run the Rake `db:migrate` task again.
|
||||
1. Repeat this process until all failed migrations are complete.
|
||||
|
|
|
@ -47,7 +47,7 @@ In `.gitlab-ci.yml` define:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
template: Dependency-Scanning.gitlab-ci.yml
|
||||
template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SECURE_ANALYZERS_PREFIX: my-docker-registry/gl-images
|
||||
|
@ -64,7 +64,7 @@ In `.gitlab-ci.yml` define:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
template: Dependency-Scanning.gitlab-ci.yml
|
||||
template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
DS_EXCLUDED_ANALYZERS: "bundler-audit, gemnasium"
|
||||
|
@ -77,7 +77,7 @@ In `.gitlab-ci.yml` define:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
template: Dependency-Scanning.gitlab-ci.yml
|
||||
template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
DS_EXCLUDED_ANALYZERS: "gemnasium, gemnasium-maven, gemnasium-python, bundler-audit, retire.js"
|
||||
|
|
|
@ -347,7 +347,7 @@ Add the following to your `.gitlab-ci.yml` file:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
```
|
||||
|
||||
The included template creates dependency scanning jobs in your CI/CD
|
||||
|
@ -381,7 +381,7 @@ For example:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SECURE_LOG_LEVEL: error
|
||||
|
@ -403,7 +403,7 @@ the `gemnasium` analyzer:
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
gemnasium-dependency_scanning:
|
||||
variables:
|
||||
|
@ -414,7 +414,7 @@ To override the `dependencies: []` attribute, add an override job as above, targ
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
gemnasium-dependency_scanning:
|
||||
dependencies: ["build"]
|
||||
|
@ -713,7 +713,7 @@ value of `GEMNASIUM_DB_REMOTE_URL` to the location of your offline Git copy of t
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
|
||||
|
@ -868,7 +868,7 @@ to the supported `requirements.txt` as follows.
|
|||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
|
|
@ -66,7 +66,8 @@ module Gitlab
|
|||
def build_environment_variables(pipeline)
|
||||
pipeline.variables.build(
|
||||
[{ key: 'CHAT_INPUT', value: arguments },
|
||||
{ key: 'CHAT_CHANNEL', value: channel }]
|
||||
{ key: 'CHAT_CHANNEL', value: channel },
|
||||
{ key: 'CHAT_USER_ID', value: chat_name.chat_id }]
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -39900,6 +39900,9 @@ msgstr ""
|
|||
msgid "created %{timeAgo}"
|
||||
msgstr ""
|
||||
|
||||
msgid "created %{timeAgo} by %{author}"
|
||||
msgstr ""
|
||||
|
||||
msgid "created by"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "1.212.0",
|
||||
"@gitlab/tributejs": "1.0.0",
|
||||
"@gitlab/ui": "32.11.2",
|
||||
"@gitlab/ui": "32.11.4",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "6.1.3-2",
|
||||
"@rails/ujs": "6.1.3-2",
|
||||
|
|
|
@ -702,4 +702,23 @@ describe('diffs/components/app', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fluid layout', () => {
|
||||
beforeEach(() => {
|
||||
setFixtures(
|
||||
'<div><div class="merge-request-container limit-container-width container-limited"></div></div>',
|
||||
);
|
||||
});
|
||||
|
||||
it('removes limited container classes when on diffs tab', () => {
|
||||
createComponent({ isFluidLayout: false, shouldShow: true }, () => {}, {
|
||||
glFeatures: { mrChangesFluidLayout: true },
|
||||
});
|
||||
|
||||
const containerClassList = document.querySelector('.merge-request-container').classList;
|
||||
|
||||
expect(containerClassList).not.toContain('container-limited');
|
||||
expect(containerClassList).not.toContain('limit-container-width');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GlLink, GlLabel, GlIcon, GlFormCheckbox } from '@gitlab/ui';
|
||||
import { GlLink, GlLabel, GlIcon, GlFormCheckbox, GlSprintf } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import IssuableItem from '~/issuable_list/components/issuable_item.vue';
|
||||
|
@ -16,6 +16,9 @@ const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots
|
|||
showCheckbox: false,
|
||||
},
|
||||
slots,
|
||||
stubs: {
|
||||
GlSprintf,
|
||||
},
|
||||
});
|
||||
|
||||
const MOCK_GITLAB_URL = 'http://0.0.0.0:3000';
|
||||
|
@ -135,13 +138,6 @@ describe('IssuableItem', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('createdAt', () => {
|
||||
it('returns string containing timeago string based on `issuable.createdAt`', () => {
|
||||
expect(wrapper.vm.createdAt).toContain('created');
|
||||
expect(wrapper.vm.createdAt).toContain('ago');
|
||||
});
|
||||
});
|
||||
|
||||
describe('updatedAt', () => {
|
||||
it('returns string containing timeago string based on `issuable.updatedAt`', () => {
|
||||
expect(wrapper.vm.updatedAt).toContain('updated');
|
||||
|
@ -449,8 +445,7 @@ describe('IssuableItem', () => {
|
|||
it('renders issuable updatedAt info', () => {
|
||||
const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
|
||||
|
||||
expect(updatedAtEl.exists()).toBe(true);
|
||||
expect(updatedAtEl.find('span').attributes('title')).toBe('Sep 10, 2020 11:41am UTC');
|
||||
expect(updatedAtEl.attributes('title')).toBe('Sep 10, 2020 11:41am UTC');
|
||||
expect(updatedAtEl.text()).toBe(wrapper.vm.updatedAt);
|
||||
});
|
||||
|
||||
|
|
|
@ -94,10 +94,6 @@ describe('IssueAssigneesComponent', () => {
|
|||
expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Assigned to Terrell Graham');
|
||||
});
|
||||
|
||||
it('renders component root element with class `issue-assignees`', () => {
|
||||
expect(wrapper.element.classList.contains('issue-assignees')).toBe(true);
|
||||
});
|
||||
|
||||
it('renders assignee', () => {
|
||||
const data = findAvatars().wrappers.map((x) => ({
|
||||
...x.props(),
|
||||
|
|
|
@ -72,6 +72,7 @@ RSpec.describe Gitlab::Chat::Command do
|
|||
|
||||
expect(vars['CHAT_INPUT']).to eq('foo')
|
||||
expect(vars['CHAT_CHANNEL']).to eq('123')
|
||||
expect(vars['CHAT_USER_ID']).to eq(chat_name.chat_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -974,10 +974,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
|
||||
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
|
||||
|
||||
"@gitlab/ui@32.11.2":
|
||||
version "32.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.11.2.tgz#c18456543700b84ec473eccf9871a75d416984cb"
|
||||
integrity sha512-taJ7aLAt8xG2NB9Rwgve9u+BGn788wgsEe6wjx4crEEWJ3EemXr/zmTe6kzSgo+n/zjZfFBRLl0vjUWCj5ylSQ==
|
||||
"@gitlab/ui@32.11.4":
|
||||
version "32.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.11.4.tgz#ead781c4fd57b4f7bc6818de99e56d023f94c397"
|
||||
integrity sha512-plxOvtAIo+PIng1jBssj/QCx2ATIbZqQvLvCeezgAABgY107XhqZDw50VZL0texTX+0jGwB5PaXthmU/wnCk2w==
|
||||
dependencies:
|
||||
"@babel/standalone" "^7.0.0"
|
||||
bootstrap-vue "2.18.1"
|
||||
|
|
Loading…
Reference in a new issue