diff --git a/app/assets/javascripts/issues/show/index.js b/app/assets/javascripts/issues/show/index.js index a27f86bd9c3732d7db49ccc967c63ec16f862ec0..d35b9237ad4193fe5b0fa8ee98f6dd5deae605f9 100644 --- a/app/assets/javascripts/issues/show/index.js +++ b/app/assets/javascripts/issues/show/index.js @@ -7,7 +7,6 @@ import { TYPE_INCIDENT, TYPE_ISSUE } from '~/issues/constants'; import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils'; import { scrollToTargetOnResize } from '~/lib/utils/resize_observer'; import IssueApp from './components/app.vue'; -import HeaderActions from './components/header_actions.vue'; import IncidentTabs from './components/incidents/incident_tabs.vue'; import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue'; import { issueState } from './constants'; @@ -199,49 +198,6 @@ export function initIssueApp(issueData, store) { }); } -export function initHeaderActions(store, type = '') { - const el = document.querySelector('.js-issue-header-actions'); - - if (!el) { - return undefined; - } - - bootstrapApollo({ ...issueState, issueType: el.dataset.issueType }); - - const canCreate = - type === TYPE_INCIDENT ? el.dataset.canCreateIncident : el.dataset.canCreateIssue; - - return new Vue({ - el, - name: 'HeaderActionsRoot', - apolloProvider, - store, - provide: { - canCreateIssue: parseBoolean(canCreate), - canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue), - canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic), - canReopenIssue: parseBoolean(el.dataset.canReopenIssue), - canReportSpam: parseBoolean(el.dataset.canReportSpam), - canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue), - iid: el.dataset.iid, - issuableId: el.dataset.issuableId, - isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor), - issuePath: el.dataset.issuePath, - issueType: el.dataset.issueType, - newIssuePath: el.dataset.newIssuePath, - projectPath: el.dataset.projectPath, - projectId: el.dataset.projectId, - reportAbusePath: el.dataset.reportAbusePath, - 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), - }); -} - export function initSentryErrorStackTrace() { const el = document.querySelector('#js-sentry-error-stack-trace'); diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index c83545fa7a7481cefd3be6932e7ba687d987af5f..22328b3f96478343b819f464bc5ced8e9464c079 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -33,22 +33,6 @@ def assignees_label(issuable, include_value: true) end end - def sidebar_milestone_tooltip_label(milestone) - return _('Milestone') unless milestone.present? - - [escape_once(milestone[:title]), sidebar_milestone_remaining_days(milestone) || _('Milestone')].join('<br/>') - end - - def sidebar_milestone_remaining_days(milestone) - due_date_with_remaining_days(milestone[:due_date], milestone[:start_date]) - end - - def due_date_with_remaining_days(due_date, start_date = nil) - return unless due_date - - "#{due_date.to_fs(:medium)} (#{remaining_days_in_words(due_date, start_date)})" - end - def multi_label_name(current_labels, default_label) return default_label if current_labels.blank? @@ -131,46 +115,6 @@ def group_dropdown_label(group_id, default_label) end # rubocop: enable CodeReuse/ActiveRecord - def issuable_meta_author_status(author) - return "" unless author&.status&.customized? && status = user_status(author) - - status.to_s.html_safe - end - - def issuable_meta(issuable, project) - output = [] - - if issuable.respond_to?(:work_item_type) && WorkItems::Type::WI_TYPES_WITH_CREATED_HEADER.include?(issuable.issue_type) - output << content_tag(:span, sprite_icon(issuable.work_item_type.icon_name.to_s, css_class: 'gl-icon gl-vertical-align-middle gl-text-gray-500'), class: 'gl-mr-2', aria: { hidden: 'true' }) - output << content_tag(:span, s_('IssuableStatus|%{wi_type} created %{created_at} by ').html_safe % { wi_type: IntegrationsHelper.integration_issue_type(issuable.issue_type), created_at: time_ago_with_tooltip(issuable.created_at) }, class: 'gl-mr-2') - else - output << content_tag(:span, s_('IssuableStatus|Created %{created_at} by').html_safe % { created_at: time_ago_with_tooltip(issuable.created_at) }, class: 'gl-mr-2') - end - - if issuable.is_a?(Issue) && issuable.service_desk_reply_to - output << "#{html_escape(issuable.present(current_user: current_user).service_desk_reply_to)} via " - end - - output << content_tag(:strong) do - author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "d-none d-sm-inline-block") - author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "d-inline d-sm-none") - - author_output << issuable_meta_author_status(issuable.author) - - author_output - end - - if access = project.team.human_max_access(issuable.author_id) - output << content_tag(:span, access, class: "user-access-role has-tooltip d-none d-xl-inline-block gl-ml-3 ", title: _("This user has the %{access} role in the %{name} project.") % { access: access.downcase, name: project.name }) - elsif project.team.contributor?(issuable.author_id) - output << content_tag(:span, _("Contributor"), class: "user-access-role has-tooltip d-none d-xl-inline-block gl-ml-3", title: _("This user has previously committed to the %{name} project.") % { name: project.name }) - end - - output << content_tag(:span, (sprite_icon('first-contribution', css_class: 'gl-icon gl-vertical-align-middle') if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!')) - - output.join.html_safe - end - def issuables_state_counter_text(issuable_type, state, display_count) titles = { opened: _("Open"), @@ -353,12 +297,6 @@ def assignee_sidebar_data(assignee, merge_request: nil) end end - def reviewer_sidebar_data(reviewer, merge_request: nil) - { avatar_url: reviewer.avatar_url, name: reviewer.name, username: reviewer.username }.tap do |data| - data[:can_merge] = merge_request.can_be_merged_by?(reviewer) if merge_request - end - end - def issuable_squash_option?(issuable, project) if issuable.persisted? issuable.squash @@ -428,27 +366,6 @@ def sidebar_gutter_collapsed? cookies[:collapsed_gutter] == 'true' end - def issuable_todo_button_data(issuable, is_collapsed) - { - todo_text: _('Add a to do'), - mark_text: _('Mark as done'), - todo_icon: sprite_icon('todo-add'), - mark_icon: sprite_icon('todo-done', css_class: 'todo-undone'), - issuable_id: issuable[:id], - issuable_type: issuable[:type], - create_path: issuable[:create_todo_path], - delete_path: issuable.dig(:current_user, :todo, :delete_path), - placement: is_collapsed ? 'left' : nil, - container: is_collapsed ? 'body' : nil, - boundary: 'viewport', - is_collapsed: is_collapsed, - track_label: "right_sidebar", - track_property: "update_todo", - track_action: "click_button", - track_value: "" - } - end - def close_reopen_params(issuable, action) { issuable.model_name.to_s.underscore => { state_event: action } diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index ed655b562c273d87ffbb737f4e9dc5f77b35ac4a..df5992e5c1352ca4e3b5a3cbd21daa13a61f65eb 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -35,15 +35,6 @@ def issue_repositioning_disabled? end end - def issue_status_visibility(issue, status_box:) - case status_box - when :open - 'hidden' if issue.closed? - when :closed - 'hidden' unless issue.closed? - end - end - def confidential_icon(issue) sprite_icon('eye-slash', css_class: 'gl-vertical-align-text-bottom') if issue.confidential? end @@ -128,24 +119,6 @@ def can_create_confidential_merge_request? can?(current_user, :create_merge_request_in, @project) end - def issue_closed_link(issue, current_user, css_class: '') - if issue.moved? && can?(current_user, :read_issue, issue.moved_to) - link_to(s_('IssuableStatus|moved'), issue.moved_to, class: css_class) - elsif issue.duplicated? && can?(current_user, :read_issue, issue.duplicated_to) - link_to(s_('IssuableStatus|duplicated'), issue.duplicated_to, class: css_class) - end - end - - def issue_closed_text(issue, current_user) - link = issue_closed_link(issue, current_user, css_class: 'text-underline gl-reset-color!') - - if link - s_('IssuableStatus|Closed (%{link})').html_safe % { link: link } - else - s_('IssuableStatus|Closed') - end - end - def show_moved_service_desk_issue_warning?(issue) return false unless issue.moved_from return false unless issue.from_service_desk? diff --git a/app/models/work_items/type.rb b/app/models/work_items/type.rb index 369ffc660aadc8fddae9175744583739d6345d16..b7ceeecbc7fafc8517a69649c91096ac219ca679 100644 --- a/app/models/work_items/type.rb +++ b/app/models/work_items/type.rb @@ -44,8 +44,6 @@ class Type < ApplicationRecord # where it's possible to switch between issue and incident. CHANGEABLE_BASE_TYPES = %w[issue incident test_case].freeze - WI_TYPES_WITH_CREATED_HEADER = %w[issue incident ticket].freeze - cache_markdown_field :description, pipeline: :single_line enum base_type: BASE_TYPES.transform_values { |value| value[:enum_value] } diff --git a/app/views/shared/issue_type/_details_header.html.haml b/app/views/shared/issue_type/_details_header.html.haml deleted file mode 100644 index 558287480e1a82a1eb9f079f80b2d76977e54ba1..0000000000000000000000000000000000000000 --- a/app/views/shared/issue_type/_details_header.html.haml +++ /dev/null @@ -1,21 +0,0 @@ -- link = issue_closed_link(@issue, current_user, css_class: 'text-underline gl-reset-color!') -- badge_classes = 'issuable-status-badge gl-mr-3' - -.detail-page-header - .detail-page-header-body.gl-flex-wrap - = gl_badge_tag({ variant: :info, icon: 'issue-closed', icon_classes: 'gl-mr-0!' }, { class: "#{issue_status_visibility(issuable, status_box: :closed)} #{badge_classes} issuable-status-badge-closed" }) do - .gl-display-none.gl-sm-display-block.gl-ml-2 - = issue_closed_text(issuable, current_user) - - if link - %span.gl-pl-2.gl-sm-display-none - = "(#{link})" - = gl_badge_tag({ variant: :success, icon: 'issues', icon_classes: 'gl-mr-0!' }, { class: "#{issue_status_visibility(issuable, status_box: :open)} #{badge_classes} issuable-status-badge-open" }) do - %span.gl-display-none.gl-sm-display-block.gl-ml-2 - = _('Open') - - #js-issuable-header-warnings{ data: { hidden: issue_hidden?(issuable).to_s } } - = issuable_meta(issuable, @project) - - = render Pajamas::ButtonComponent.new(href: '#', icon: 'chevron-double-lg-left', button_options: { class: 'gl-ml-auto gl-display-block gl-sm-display-none! js-sidebar-toggle' }) - - .js-issue-header-actions{ data: issue_header_actions_data(@project, issuable, current_user, @issuable_sidebar) } diff --git a/ee/app/helpers/ee/issues_helper.rb b/ee/app/helpers/ee/issues_helper.rb index 6d2bfd21766383d7d68a8c1bf2a00ea574c5e9ed..7afa7bd2c9022fc38c0776d5446ee7772a2f8973 100644 --- a/ee/app/helpers/ee/issues_helper.rb +++ b/ee/app/helpers/ee/issues_helper.rb @@ -25,15 +25,6 @@ def scoped_labels_available?(parent) parent.feature_available?(:scoped_labels) end - override :issue_closed_link - def issue_closed_link(issue, current_user, css_class: '') - if issue.promoted? && can?(current_user, :read_epic, issue.promoted_to_epic) - link_to(s_('IssuableStatus|promoted'), issue.promoted_to_epic, class: css_class) - else - super - end - end - override :issue_header_actions_data def issue_header_actions_data(project, issuable, current_user, issuable_sidebar) actions = super diff --git a/ee/spec/helpers/ee/issues_helper_spec.rb b/ee/spec/helpers/ee/issues_helper_spec.rb index 1cdd0de3bad9c852f29a3d3cf6fedd688967d221..a3f4b8f188868e257a6d9ab5e8ec645c5a035b60 100644 --- a/ee/spec/helpers/ee/issues_helper_spec.rb +++ b/ee/spec/helpers/ee/issues_helper_spec.rb @@ -7,43 +7,6 @@ let(:project) { create :project, group: group } let(:issue) { create :issue, project: project } - describe '#issue_closed_link' do - let(:new_epic) { create(:epic) } - let(:user) { create(:user) } - - context 'with linked issue' do - context 'with promoted issue' do - before do - issue.update!(promoted_to_epic: new_epic) - end - - context 'when user has permission to see new epic' do - before do - expect(helper).to receive(:can?).with(user, :read_epic, new_epic) { true } - end - - let(:css_class) { 'text-white text-underline' } - - it 'returns link' do - link = "<a class=\"#{css_class}\" href=\"/groups/#{new_epic.group.full_path}/-/epics/#{new_epic.iid}\">(promoted)</a>" - - expect(helper.issue_closed_link(issue, user, css_class: css_class)).to match(link) - end - end - - context 'when user has no permission to see new epic' do - before do - expect(helper).to receive(:can?).with(user, :read_epic, new_epic) { false } - end - - it 'returns nil' do - expect(helper.issue_closed_link(issue, user)).to be_nil - end - end - end - end - end - describe '#issue_in_subepic?' do let_it_be(:epic) { create(:epic) } let_it_be(:epic_issue) { create(:epic_issue, epic: epic) } diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 983101d810fce12342e02efc8ef88f6bd8dc9122..6390a5e1896f2af722a446b70e9d11d5afbf52b0 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -25965,18 +25965,12 @@ msgstr "" msgid "IssuableEvents|unassigned" msgstr "" -msgid "IssuableStatus|%{wi_type} created %{created_at} by " -msgstr "" - msgid "IssuableStatus|Closed" msgstr "" msgid "IssuableStatus|Closed (%{link})" msgstr "" -msgid "IssuableStatus|Created %{created_at} by" -msgstr "" - msgid "IssuableStatus|duplicated" msgstr "" diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb index 7b5537c54ccf1366f4ea84e3d6e7533febb487df..092cc787573207475a26c022fd07ec168149da3c 100644 --- a/spec/helpers/issuables_helper_spec.rb +++ b/spec/helpers/issuables_helper_spec.rb @@ -134,109 +134,6 @@ end end - describe '#issuable_meta', time_travel_to: '2022-08-05 00:00:00 +0000' do - let(:user) { create(:user) } - - let_it_be(:project) { create(:project) } - - describe 'Issuable created status text' do - subject { helper.issuable_meta(issuable, project) } - - context 'when issuable is a work item and flag is off' do - using RSpec::Parameterized::TableSyntax - - before do - stub_feature_flags(work_items: false) - end - - where(:issuable_type, :text) do - :issue | 'Issue created Aug 05, 2022 by' - :incident | 'Incident created Aug 05, 2022 by' - end - - let(:issuable) { build_stubbed(:work_item, issuable_type, created_at: Date.current) } - - with_them do - it { is_expected.to have_content(text) } - end - end - - context 'when issuable is a work item and flag is on' do - using RSpec::Parameterized::TableSyntax - - where(:issuable_type, :text) do - :issue | 'Issue created Aug 05, 2022 by' - :incident | 'Incident created Aug 05, 2022 by' - end - - let(:issuable) { build_stubbed(:work_item, issuable_type, created_at: Date.current) } - - with_them do - it { is_expected.to have_content(text) } - end - end - - context 'when issuable is not a work item' do - let(:issuable) { build_stubbed(:merge_request, created_at: Date.current) } - - it { is_expected.to have_content('Created Aug 05, 2022') } - end - end - - describe 'author status' do - let(:issuable) { build(:merge_request, source_project: project, author: user, created_at: '2020-01-30') } - - it 'displays an emoji if the user status is set' do - user.status = UserStatus.new(message: 'lol') - content = helper.issuable_meta(issuable, project) - expect(content).to match('<span class="user-status-emoji has-tooltip" title="lol" data-html="true" data-placement="top">') - expect(content).to match('<gl-emoji title="speech balloon" data-name="speech_balloon" data-unicode-version="6.0">') - end - - it 'does not displays an emoji if the user status is not set' do - user.status = UserStatus.new - content = helper.issuable_meta(issuable, project) - expect(content).not_to match('class="user-status-emoji has-tooltip"') - expect(content).not_to match('gl-emoji') - end - end - - describe 'service desk reply to email address' do - let(:email) { 'user@example.com' } - let(:obfuscated_email) { 'us*****@e*****.c**' } - let(:service_desk_issue) { build_stubbed(:issue, project: project, author: User.support_bot, service_desk_reply_to: email) } - - subject { helper.issuable_meta(service_desk_issue, project) } - - context 'with anonymous user' do - before do - allow(helper).to receive(:current_user).and_return(nil) - end - - it { is_expected.to have_content(obfuscated_email) } - end - - context 'with signed in user' do - context 'when user has no role in project' do - before do - allow(helper).to receive(:current_user).and_return(user) - end - - it { is_expected.to have_content(obfuscated_email) } - end - - context 'when user has reporter role in project' do - before do - project.add_reporter(user) - allow(helper).to receive(:current_user).and_return(user) - end - - it { is_expected.to have_content(email) } - end - end - end - end - describe '#issuables_state_counter_text' do let_it_be(:user) { create(:user) } @@ -613,38 +510,6 @@ end end - describe '#reviewer_sidebar_data' do - let(:user) { create(:user) } - - subject { helper.reviewer_sidebar_data(user, merge_request: merge_request) } - - context 'without merge_request' do - let(:merge_request) { nil } - - it 'returns hash of reviewer data' do - is_expected.to eql({ - avatar_url: user.avatar_url, - name: user.name, - username: user.username - }) - end - end - - context 'with merge_request' do - let(:merge_request) { build(:merge_request) } - - where(can_merge: [true, false]) - - with_them do - before do - allow(merge_request).to receive(:can_be_merged_by?).and_return(can_merge) - end - - it { is_expected.to include({ can_merge: can_merge }) } - end - end - end - describe '#issuable_squash_option?' do using RSpec::Parameterized::TableSyntax @@ -722,16 +587,6 @@ end end - describe '#sidebar_milestone_tooltip_label' do - it 'escapes HTML in the milestone title' do - milestone = build(:milestone, title: '<img onerror=alert(1)>', due_date: Date.new(2022, 6, 26)) - - expect(helper.sidebar_milestone_tooltip_label(milestone)).to eq( - '<img onerror=alert(1)><br/>Jun 26, 2022 (<strong>Past due</strong>)' - ) - end - end - describe '#issuable_type_selector_data' do using RSpec::Parameterized::TableSyntax diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 0cde9aeac8df4377a57c3ab576fef73e7181ed06..caa9fb504dd4f66bde72af6d1880cc9473e49777 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -136,81 +136,6 @@ end end - describe '#issue_closed_link' do - let(:new_issue) { create(:issue, project: project) } - let(:guest) { create(:user) } - - before do - allow(helper).to receive(:can?) do |*args| - Ability.allowed?(*args) - end - end - - shared_examples 'successfully displays link to issue and with css class' do |action| - it 'returns link' do - link = "<a class=\"#{css_class}\" href=\"/#{new_issue.project.full_path}/-/issues/#{new_issue.iid}\">(#{action})</a>" - - expect(helper.issue_closed_link(issue, user, css_class: css_class)).to match(link) - end - end - - shared_examples 'does not display link' do - it 'returns nil' do - expect(helper.issue_closed_link(issue, user)).to be_nil - end - end - - context 'with linked issue' do - context 'with moved issue' do - before do - issue.update!(moved_to: new_issue) - end - - context 'when user has permission to see new issue' do - let(:user) { project.owner } - let(:css_class) { 'text-white text-underline' } - - it_behaves_like 'successfully displays link to issue and with css class', 'moved' - end - - context 'when user has no permission to see new issue' do - let(:user) { guest } - - it_behaves_like 'does not display link' - end - end - - context 'with duplicated issue' do - before do - issue.update!(duplicated_to: new_issue) - end - - context 'when user has permission to see new issue' do - let(:user) { project.owner } - let(:css_class) { 'text-white text-underline' } - - it_behaves_like 'successfully displays link to issue and with css class', 'duplicated' - end - - context 'when user has no permission to see new issue' do - let(:user) { guest } - - it_behaves_like 'does not display link' - end - end - end - - context 'without linked issue' do - let(:user) { project.owner } - - before do - issue.update!(moved_to: nil, duplicated_to: nil) - end - - it_behaves_like 'does not display link' - end - end - describe '#show_moved_service_desk_issue_warning?' do let(:project1) { create(:project, service_desk_enabled: true) } let(:project2) { create(:project, service_desk_enabled: true) }