Коммит 4bd001d1 создал по автору Deepika Guliani's avatar Deepika Guliani Зафиксировано автором Natalia Tepluhina
Просмотр файлов

Move actions from sidebar to main in Issues/Incidents/Epics

владелец 866be8a0
......@@ -26,3 +26,8 @@ export const IssuableStatusText = {
[STATUS_MERGED]: __('Merged'),
[STATUS_LOCKED]: __('Open'),
};
export const IssuableTypeText = {
[TYPE_ISSUE]: __('issue'),
[TYPE_MERGE_REQUEST]: __('merge request'),
};
......@@ -2,23 +2,36 @@
import {
GlButton,
GlDropdown,
GlDropdownDivider,
GlDropdownItem,
GlLink,
GlModal,
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import { mapActions, mapGetters, mapState } from 'vuex';
import { createAlert, VARIANT_SUCCESS } from '~/alert';
import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
import { STATUS_CLOSED, TYPE_INCIDENT, TYPE_ISSUE } from '~/issues/constants';
import { ISSUE_STATE_EVENT_CLOSE, ISSUE_STATE_EVENT_REOPEN } from '~/issues/show/constants';
import { STATUS_CLOSED, TYPE_INCIDENT, TYPE_ISSUE, IssuableTypeText } from '~/issues/constants';
import {
ISSUE_STATE_EVENT_CLOSE,
ISSUE_STATE_EVENT_REOPEN,
NEW_ACTIONS_POPOVER_KEY,
} from '~/issues/show/constants';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { getCookie, parseBoolean, setCookie } from '~/lib/utils/common_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__, __, sprintf } from '~/locale';
import eventHub from '~/notes/event_hub';
import Tracking from '~/tracking';
import toast from '~/vue_shared/plugins/global_toast';
import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue';
import NewHeaderActionsPopover from '~/issues/show/components/new_header_actions_popover.vue';
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import IssuableLockForm from '~/sidebar/components/lock/issuable_lock_form.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import issueReferenceQuery from '~/sidebar/queries/issue_reference.query.graphql';
import issuesEventHub from '../event_hub';
import promoteToEpicMutation from '../queries/promote_to_epic.mutation.graphql';
import updateIssueMutation from '../queries/update_issue.mutation.graphql';
......@@ -44,21 +57,27 @@ export default {
'The issue was successfully promoted to an epic. Redirecting to epic...',
),
reportAbuse: __('Report abuse to administrator'),
referenceFetchError: __('An error occurred while fetching reference'),
copyReferenceText: __('Copy reference'),
},
components: {
DeleteIssueModal,
GlButton,
GlDropdown,
GlDropdownDivider,
GlDropdownItem,
GlLink,
GlModal,
AbuseCategorySelector,
NewHeaderActionsPopover,
SidebarSubscriptionsWidget,
IssuableLockForm,
},
directives: {
GlModal: GlModalDirective,
GlTooltip: GlTooltipDirective,
},
mixins: [trackingMixin],
mixins: [trackingMixin, glFeatureFlagMixin()],
inject: {
canCreateIssue: {
default: false,
......@@ -105,15 +124,46 @@ export default {
reportedFromUrl: {
default: '',
},
issuableEmailAddress: {
default: '',
},
fullPath: {
default: '',
},
},
data() {
return {
isReportAbuseDrawerOpen: false,
};
},
apollo: {
issuableReference: {
query: issueReferenceQuery,
variables() {
return {
fullPath: this.fullPath,
iid: this.iid,
};
},
update(data) {
return data.workspace?.issuable?.reference || '';
},
skip() {
return !this.isMrSidebarMoved;
},
error(error) {
createAlert({ message: this.$options.i18n.referenceFetchError });
Sentry.captureException(error);
},
},
},
computed: {
...mapState(['isToggleStateButtonLoading']),
...mapGetters(['openState', 'getBlockedByIssues']),
...mapGetters(['getNoteableData']),
isLocked() {
return this.getNoteableData.discussion_locked;
},
isClosed() {
return this.openState === STATUS_CLOSED;
},
......@@ -157,6 +207,17 @@ export default {
hasMobileDropdown() {
return this.hasDesktopDropdown || this.showToggleIssueStateButton;
},
copyMailAddressText() {
return sprintf(__('Copy %{issueType} email address'), {
issueType: IssuableTypeText[this.issueType],
});
},
isMrSidebarMoved() {
return this.glFeatures.movedMrSidebar;
},
showLockIssueOption() {
return this.isMrSidebarMoved && this.issueType === TYPE_ISSUE;
},
},
created() {
eventHub.$on('toggle.issuable.state', this.toggleIssueState);
......@@ -166,6 +227,7 @@ export default {
},
methods: {
...mapActions(['toggleStateButtonLoading']),
...mapActions(['updateLockedAttribute']),
toggleIssueState() {
if (!this.isClosed && this.getBlockedByIssues?.length) {
this.$refs.blockedByIssuesModal.show();
......@@ -244,7 +306,19 @@ export default {
edit() {
issuesEventHub.$emit('open.form');
},
dismissPopover() {
if (this.isMrSidebarMoved && !parseBoolean(getCookie(`${NEW_ACTIONS_POPOVER_KEY}`))) {
setCookie(NEW_ACTIONS_POPOVER_KEY, true);
}
},
copyReference() {
toast(__('Reference copied'));
},
copyEmailAddress() {
toast(__('Email address copied'));
},
},
TYPE_ISSUE,
};
</script>
......@@ -259,6 +333,21 @@ export default {
data-testid="mobile-dropdown"
:loading="isToggleStateButtonLoading"
>
<template v-if="isMrSidebarMoved">
<sidebar-subscriptions-widget
:iid="String(iid)"
:full-path="fullPath"
:issuable-type="$options.TYPE_ISSUE"
data-testid="notification-toggle"
/>
<gl-dropdown-divider />
</template>
<template v-if="showLockIssueOption">
<issuable-lock-form :is-editable="false" data-testid="lock-issue-toggle" />
</template>
<gl-dropdown-item v-if="canUpdateIssue" @click="edit">
{{ $options.i18n.edit }}
</gl-dropdown-item>
......@@ -275,9 +364,21 @@ export default {
<gl-dropdown-item v-if="canPromoteToEpic" @click="promoteToEpic">
{{ __('Promote to epic') }}
</gl-dropdown-item>
<gl-dropdown-item v-if="!isIssueAuthor" @click="toggleReportAbuseDrawer(true)">
{{ $options.i18n.reportAbuse }}
</gl-dropdown-item>
<template v-if="isMrSidebarMoved">
<gl-dropdown-item
:data-clipboard-text="issuableReference"
data-testid="copy-reference"
@click="copyReference"
>{{ $options.i18n.copyReferenceText }}</gl-dropdown-item
>
<gl-dropdown-item
v-if="issuableEmailAddress"
:data-clipboard-text="issuableEmailAddress"
data-testid="copy-email"
@click="copyEmailAddress"
>{{ copyMailAddressText }}</gl-dropdown-item
>
</template>
<gl-dropdown-item
v-if="canReportSpam"
:href="submitAsSpamPath"
......@@ -287,6 +388,7 @@ export default {
{{ __('Submit as spam') }}
</gl-dropdown-item>
<template v-if="canDestroyIssue">
<gl-dropdown-divider />
<gl-dropdown-item
v-gl-modal="$options.deleteModalId"
variant="danger"
......@@ -295,6 +397,13 @@ export default {
{{ deleteButtonText }}
</gl-dropdown-item>
</template>
<gl-dropdown-item
v-if="!isIssueAuthor"
data-testid="report-abuse-item"
@click="toggleReportAbuseDrawer(true)"
>
{{ $options.i18n.reportAbuse }}
</gl-dropdown-item>
</gl-dropdown>
<gl-button
......@@ -322,6 +431,7 @@ export default {
<gl-dropdown
v-if="hasDesktopDropdown"
id="new-actions-header-dropdown"
v-gl-tooltip.hover
class="gl-display-none gl-sm-display-inline-flex! gl-sm-ml-3"
icon="ellipsis_v"
......@@ -334,7 +444,19 @@ export default {
data-testid="desktop-dropdown"
no-caret
right
@shown="dismissPopover"
>
<template v-if="isMrSidebarMoved">
<sidebar-subscriptions-widget
:iid="String(iid)"
:full-path="fullPath"
:issuable-type="$options.TYPE_ISSUE"
data-testid="notification-toggle"
/>
<gl-dropdown-divider />
</template>
<gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
{{ newIssueTypeText }}
</gl-dropdown-item>
......@@ -346,9 +468,24 @@ export default {
>
{{ __('Promote to epic') }}
</gl-dropdown-item>
<gl-dropdown-item v-if="!isIssueAuthor" @click="toggleReportAbuseDrawer(true)">
{{ $options.i18n.reportAbuse }}
</gl-dropdown-item>
<template v-if="showLockIssueOption">
<issuable-lock-form :is-editable="false" data-testid="lock-issue-toggle" />
</template>
<template v-if="isMrSidebarMoved">
<gl-dropdown-item
:data-clipboard-text="issuableReference"
data-testid="copy-reference"
@click="copyReference"
>{{ $options.i18n.copyReferenceText }}</gl-dropdown-item
>
<gl-dropdown-item
v-if="issuableEmailAddress"
:data-clipboard-text="issuableEmailAddress"
data-testid="copy-email"
@click="copyEmailAddress"
>{{ copyMailAddressText }}</gl-dropdown-item
>
</template>
<gl-dropdown-item
v-if="canReportSpam"
:href="submitAsSpamPath"
......@@ -357,8 +494,8 @@ export default {
>
{{ __('Submit as spam') }}
</gl-dropdown-item>
<template v-if="canDestroyIssue">
<gl-dropdown-divider />
<gl-dropdown-item
v-gl-modal="$options.deleteModalId"
variant="danger"
......@@ -368,8 +505,16 @@ export default {
{{ deleteButtonText }}
</gl-dropdown-item>
</template>
<gl-dropdown-item
v-if="!isIssueAuthor"
data-testid="report-abuse-item"
@click="toggleReportAbuseDrawer(true)"
>
{{ $options.i18n.reportAbuse }}
</gl-dropdown-item>
</gl-dropdown>
<new-header-actions-popover v-if="isMrSidebarMoved" :issue-type="issueType" />
<gl-modal
ref="blockedByIssuesModal"
modal-id="blocked-by-issues-modal"
......
<script>
import { GlPopover, GlButton } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import { getCookie, parseBoolean, setCookie } from '~/lib/utils/common_utils';
import { NEW_ACTIONS_POPOVER_KEY } from '~/issues/show/constants';
import { IssuableTypeText } from '~/issues/constants';
export default {
name: 'NewHeaderActionsPopover',
i18n: {
popoverText: s__(
'HeaderAction|Notifications and other %{issueType} actions have moved to this menu.',
),
confirmButtonText: s__('HeaderAction|Okay!'),
},
components: {
GlPopover,
GlButton,
},
props: {
issueType: {
type: String,
required: true,
},
},
data() {
return {
dismissKey: NEW_ACTIONS_POPOVER_KEY,
popoverDismissed: parseBoolean(getCookie(`${NEW_ACTIONS_POPOVER_KEY}`)),
};
},
computed: {
popoverText() {
return sprintf(this.$options.i18n.popoverText, {
issueType: IssuableTypeText[this.issueType],
});
},
showPopover() {
return !this.popoverDismissed;
},
},
methods: {
dismissPopover() {
this.popoverDismissed = true;
setCookie(this.dismissKey, this.popoverDismissed);
},
},
};
</script>
<template>
<div>
<gl-popover
v-if="showPopover"
target="new-actions-header-dropdown"
container="viewport"
placement="left"
:show="showPopover"
triggers="manual"
content="text"
:css-classes="['gl-p-2 new-header-popover']"
>
<template #title>
<div class="gl-font-base gl-font-weight-normal">
{{ popoverText }}
</div>
</template>
<gl-button
data-testid="confirm-button"
variant="confirm"
type="submit"
@click="dismissPopover"
>{{ $options.i18n.confirmButtonText }}</gl-button
>
</gl-popover>
</div>
</template>
......@@ -17,3 +17,5 @@ export const issueState = {
issueType: undefined,
isDirty: false,
};
export const NEW_ACTIONS_POPOVER_KEY = 'new-actions-popover-viewed';
......@@ -174,6 +174,8 @@ export function initHeaderActions(store, type = '') {
reportedUserId: parseInt(el.dataset.reportedUserId, 10),
reportedFromUrl: el.dataset.reportedFromUrl,
submitAsSpamPath: el.dataset.submitAsSpamPath,
issuableEmailAddress: el.dataset.issuableEmailAddress,
fullPath: el.dataset.projectPath,
},
render: (createElement) => createElement(HeaderActions),
});
......
......@@ -56,8 +56,10 @@ Sidebar.prototype.addEventListeners = function () {
const layoutPage = document.querySelector('.layout-page');
const rightSidebar = document.querySelector('.js-right-sidebar');
updateSidebarClasses(layoutPage, rightSidebar);
window.addEventListener('resize', () => updateSidebarClasses(layoutPage, rightSidebar));
if (rightSidebar.classList.contains('right-sidebar-merge-requests')) {
updateSidebarClasses(layoutPage, rightSidebar);
window.addEventListener('resize', () => updateSidebarClasses(layoutPage, rightSidebar));
}
}
};
......
<script>
import { GlIcon, GlTooltipDirective, GlOutsideDirective as Outside } from '@gitlab/ui';
import { mapGetters, mapActions } from 'vuex';
import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/issues/constants';
import { TYPE_ISSUE } from '~/issues/constants';
import { __, sprintf } from '~/locale';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { createAlert } from '~/alert';
import toast from '~/vue_shared/plugins/global_toast';
......@@ -45,10 +46,8 @@ export default {
},
computed: {
...mapGetters(['getNoteableData']),
isMergeRequest() {
return (
this.getNoteableData.targetType === TYPE_MERGE_REQUEST && this.glFeatures.movedMrSidebar
);
isMovedMrSidebar() {
return this.glFeatures.movedMrSidebar;
},
issuableDisplayName() {
const isInIssuePage = this.getNoteableData.targetType === TYPE_ISSUE;
......@@ -60,7 +59,6 @@ export default {
lockStatus() {
return this.isLocked ? this.$options.locked : this.$options.unlocked;
},
tooltipLabel() {
return this.isLocked ? __('Locked') : __('Unlocked');
},
......@@ -89,8 +87,13 @@ export default {
fullPath: this.fullPath,
})
.then(() => {
if (this.isMergeRequest) {
toast(this.isLocked ? __('Merge request locked.') : __('Merge request unlocked.'));
if (this.isMovedMrSidebar) {
toast(
sprintf(__('%{issuableDisplayName} %{lockStatus}.'), {
issuableDisplayName: capitalizeFirstCharacter(this.issuableDisplayName),
lockStatus: this.isLocked ? __('locked') : __('unlocked'),
}),
);
}
})
.catch(() => {
......@@ -113,14 +116,14 @@ export default {
</script>
<template>
<li v-if="isMergeRequest" class="gl-dropdown-item">
<button type="button" class="dropdown-item" @click="toggleLocked">
<li v-if="isMovedMrSidebar" class="gl-dropdown-item">
<button type="button" class="dropdown-item" data-testid="issuable-lock" @click="toggleLocked">
<span class="gl-dropdown-item-text-wrapper">
<template v-if="isLocked">
{{ __('Unlock merge request') }}
{{ sprintf(__('Unlock %{issuableType}'), { issuableType: issuableDisplayName }) }}
</template>
<template v-else>
{{ __('Lock merge request') }}
{{ sprintf(__('Lock %{issuableType}'), { issuableType: issuableDisplayName }) }}
</template>
</span>
</button>
......
<script>
import { GlDropdownForm, GlIcon, GlLoadingIcon, GlToggle, GlTooltipDirective } from '@gitlab/ui';
import { createAlert } from '~/alert';
import {
TYPE_EPIC,
TYPE_MERGE_REQUEST,
WORKSPACE_GROUP,
WORKSPACE_PROJECT,
} from '~/issues/constants';
import { TYPE_EPIC, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { __, sprintf } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
......@@ -91,8 +86,8 @@ export default {
},
},
computed: {
isMergeRequest() {
return this.issuableType === TYPE_MERGE_REQUEST && this.glFeatures.movedMrSidebar;
isMovedMrSidebar() {
return this.glFeatures.movedMrSidebar;
},
isLoading() {
return this.$apollo.queries?.subscribed?.loading || this.loading;
......@@ -148,7 +143,7 @@ export default {
});
}
if (this.isMergeRequest) {
if (this.isMovedMrSidebar) {
toast(subscribed ? __('Notifications turned on.') : __('Notifications turned off.'));
}
},
......@@ -187,7 +182,7 @@ export default {
</script>
<template>
<gl-dropdown-form v-if="isMergeRequest" class="gl-dropdown-item">
<gl-dropdown-form v-if="isMovedMrSidebar" class="gl-dropdown-item">
<div class="gl-px-5 gl-pb-2 gl-pt-1">
<gl-toggle
:value="subscribed"
......
......@@ -17,6 +17,7 @@ import { __ } from '~/locale';
import { apolloProvider } from '~/graphql_shared/issuable_client';
import Translate from '~/vue_shared/translate';
import UserSelect from '~/vue_shared/components/user_select/user_select.vue';
import NewHeaderActionsPopover from '~/issues/show/components/new_header_actions_popover.vue';
import CollapsedAssigneeList from './components/assignees/collapsed_assignee_list.vue';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import SidebarAssigneesWidget from './components/assignees/sidebar_assignees_widget.vue';
......@@ -787,6 +788,21 @@ export function mountAssigneesDropdown() {
});
}
function mountNewIssuePopover() {
const el = document.querySelector('.js-sidebar-header-popover');
if (!el) {
return null;
}
return new Vue({
el,
name: 'NewHeaderActionsPopover',
render: (createElement) =>
createElement(NewHeaderActionsPopover, { props: { issueType: TYPE_MERGE_REQUEST } }),
});
}
const isAssigneesWidgetShown =
(isInIssuePage() || isInDesignPage() || isInMRPage()) && gon.features.issueAssigneesWidget;
......@@ -814,6 +830,7 @@ export function mountSidebar(mediator, store) {
mountSidebarSeverityWidget();
mountSidebarEscalationStatus();
mountMoveIssueButton();
mountNewIssuePopover();
}
export { getSidebarOptions };
......@@ -165,3 +165,13 @@
border: 0;
}
}
.merge-request-notification-toggle {
.gl-toggle {
@include gl-ml-auto;
}
.gl-toggle-label {
@include gl-font-weight-normal;
}
}
......@@ -74,3 +74,7 @@
color: $gl-text-color;
}
}
.new-header-popover {
z-index: 999;
}
......@@ -10,6 +10,7 @@ class Projects::IncidentsController < Projects::ApplicationController
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_mvc, @project&.work_items_mvc_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?)
push_frontend_feature_flag(:moved_mr_sidebar, project)
end
feature_category :incident_management
......
......@@ -67,6 +67,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_force_frontend_feature_flag(:work_items_mvc, project&.work_items_mvc_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_mvc_2, project&.work_items_mvc_2_feature_flag_enabled?)
push_frontend_feature_flag(:epic_widget_edit_confirmation, project)
push_frontend_feature_flag(:moved_mr_sidebar, project)
end
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
......
......@@ -12,8 +12,8 @@ def sidebar_gutter_toggle_icon
end
end
def sidebar_gutter_collapsed_class
return "right-sidebar-expanded" if moved_mr_sidebar_enabled?
def sidebar_gutter_collapsed_class(is_merge_request_with_flag)
return "right-sidebar-expanded" if is_merge_request_with_flag
"right-sidebar-#{sidebar_gutter_collapsed? ? 'collapsed' : 'expanded'}"
end
......
......@@ -153,7 +153,7 @@ def show_moved_service_desk_issue_warning?(issue)
issue.moved_from.project.service_desk_enabled? && !issue.project.service_desk_enabled?
end
def issue_header_actions_data(project, issuable, current_user)
def issue_header_actions_data(project, issuable, current_user, issuable_sidebar)
new_issuable_params = { issue: {}, add_related_issue: issuable.iid }
if issuable.incident?
new_issuable_params[:issuable_template] = 'incident'
......@@ -176,7 +176,8 @@ def issue_header_actions_data(project, issuable, current_user)
report_abuse_path: add_category_abuse_reports_path,
reported_user_id: issuable.author.id,
reported_from_url: issue_url(issuable),
submit_as_spam_path: mark_as_spam_project_issue_path(project, issuable)
submit_as_spam_path: mark_as_spam_project_issue_path(project, issuable),
issuable_email_address: issuable_sidebar.nil? ? '' : issuable_sidebar[:create_note_email]
}
end
......
......@@ -179,6 +179,10 @@ def reviewers_label(merge_request, include_value: true)
end
end
def moved_mr_sidebar_enabled?
Feature.enabled?(:moved_mr_sidebar, @project)
end
def diffs_tab_pane_data(project, merge_request, params)
{
"is-locked": merge_request.discussion_locked?,
......@@ -256,10 +260,6 @@ def merge_request_header(project, merge_request)
_('%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}').html_safe % { author: link_to_author.html_safe, source_branch: merge_request_source_branch(merge_request).html_safe, copy_button: copy_button.html_safe, target_branch: target_branch.html_safe, created_at: time_ago_with_tooltip(merge_request.created_at, html_class: 'gl-display-inline-block').html_safe }
end
def moved_mr_sidebar_enabled?
Feature.enabled?(:moved_mr_sidebar, @project) && defined?(@merge_request)
end
def sticky_header_data
data = {
iid: @merge_request.iid,
......
......@@ -38,7 +38,7 @@ def page_with_sidebar_class
end
def page_gutter_class
moved_sidebar_enabled = current_controller?('merge_requests') && moved_mr_sidebar_enabled?
moved_sidebar_enabled = @is_merge_request_with_flag
if (page_has_markdown? || current_path?('projects/merge_requests#diffs')) && !current_controller?('conflicts')
if cookies[:collapsed_gutter] == 'true'
......
- display_issuable_type = issuable_display_type(@merge_request)
.btn-group.gl-md-ml-3.gl-display-flex.dropdown.gl-dropdown.gl-md-w-auto.gl-w-full
= button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex!", data: { toggle: 'dropdown', title: _('Merge request actions'), testid: 'merge-request-actions', 'aria-label': _('Merge request actions') } do
%span.js-sidebar-header-popover
= button_tag type: 'button', id: "new-actions-header-dropdown", class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex! gl-rounded-base!", data: { toggle: 'dropdown', title: _('Merge request actions'), testid: 'merge-request-actions', 'aria-label': _('Merge request actions') } do
= sprite_icon "ellipsis_v", size: 16, css_class: "dropdown-icon gl-icon"
= button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md btn-block gl-button gl-dropdown-toggle gl-md-display-none!", data: { 'toggle' => 'dropdown' } do
%span.gl-dropdown-button-text= _('Merge request actions')
......
......@@ -9,14 +9,15 @@
- reviewers = local_assigns.fetch(:reviewers, nil)
- in_group_context_with_iterations = @project.group.present? && issuable_sidebar[:supports_iterations]
- is_merge_request = issuable_type === 'merge_request'
- moved_sidebar_enabled = moved_mr_sidebar_enabled? && is_merge_request
- moved_sidebar_enabled = moved_mr_sidebar_enabled?
- is_merge_request_with_flag = is_merge_request && moved_sidebar_enabled
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class} #{'right-sidebar-merge-requests' if moved_sidebar_enabled}", 'aria-live' => 'polite', 'aria-label': issuable_type }
.issuable-sidebar{ class: "#{'is-merge-request' if moved_sidebar_enabled}" }
.issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end gl-lg-display-none!' if moved_sidebar_enabled}" }
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class(is_merge_request_with_flag)} #{'right-sidebar-merge-requests' if is_merge_request_with_flag}", 'aria-live' => 'polite', 'aria-label': issuable_type }
.issuable-sidebar{ class: "#{'is-merge-request' if is_merge_request_with_flag}" }
.issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end gl-lg-display-none!' if is_merge_request_with_flag}" }
%button.btn.gl-button.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ type: "reset", class: "gl-shadow-none! #{'gl-display-block' if moved_sidebar_enabled}", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }
= sidebar_gutter_toggle_icon
- if signed_in && !moved_sidebar_enabled
- if signed_in && !is_merge_request_with_flag
.js-sidebar-todo-widget-root{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } }
= form_for issuable_type, url: issuable_sidebar[:issuable_json_path], remote: true, html: { class: 'issuable-context-form inline-update js-issuable-update' } do |f|
......@@ -81,17 +82,17 @@
.js-sidebar-participants-widget-root
.block.with-sub-blocks
- if !moved_sidebar_enabled
- if !moved_sidebar_enabled
.block.with-sub-blocks
.js-sidebar-reference-widget-root
- if issuable_type == 'merge_request' && !moved_sidebar_enabled
.sub-block.js-sidebar-source-branch
.sidebar-collapsed-icon.js-dont-change-state
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
.gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mb-2.hide-collapsed
%span.gl-overflow-hidden.gl-text-overflow-ellipsis.gl-white-space-nowrap
= _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<span class='gl-font-monospace' data-testid='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</span>".html_safe, source_branch: html_escape(source_branch) }
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
- if is_merge_request && !moved_sidebar_enabled
.sub-block.js-sidebar-source-branch
.sidebar-collapsed-icon.js-dont-change-state
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
.gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mb-2.hide-collapsed
%span.gl-overflow-hidden.gl-text-overflow-ellipsis.gl-white-space-nowrap
= _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<span class='gl-font-monospace' data-testid='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</span>".html_safe, source_branch: html_escape(source_branch) }
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
- if show_forwarding_email
.block
......
......@@ -19,4 +19,4 @@
%a.btn.gl-button.btn-default.btn-icon.float-right.gl-display-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
= sprite_icon('chevron-double-lg-left')
.js-issue-header-actions{ data: issue_header_actions_data(@project, issuable, current_user) }
.js-issue-header-actions{ data: issue_header_actions_data(@project, issuable, current_user, @issuable_sidebar) }
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать