diff --git a/app/assets/stylesheets/framework/images.scss b/app/assets/stylesheets/framework/images.scss index 1e93bf2b7515b632f26f2c5a5077b685b93d4575..a20920e25033bd9d89c0e49afb6635859e43b44c 100644 --- a/app/assets/stylesheets/framework/images.scss +++ b/app/assets/stylesheets/framework/images.scss @@ -39,7 +39,7 @@ svg { fill: currentColor; - $svg-sizes: 8 10 12 16 18 24 32 48 72; + $svg-sizes: 8 10 12 14 16 18 24 32 48 72; @each $svg-size in $svg-sizes { &.s#{$svg-size} { @include svg-size(#{$svg-size}px); diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 19eee4e4abaa2880ae099d23a5f41e139d1549c1..bfcac3f1c3f5adb6e1516ceec68eba277da9ee6f 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -269,6 +269,7 @@ $flash-height: 52px; $context-header-height: 60px; $breadcrumb-min-height: 48px; $project-title-row-height: 24px; +$gl-line-height: 16px; /* * Common component specific colors diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index a91d44805ee104ffe892c5d935eb0934c11fe6ba..618f23d81b12b68a0eb99f59a22c9851fc806f57 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -4,41 +4,29 @@ */ .event-item { font-size: $gl-font-size; - padding: $gl-padding-top 0 $gl-padding-top 40px; + padding: $gl-padding 0 $gl-padding 56px; border-bottom: 1px solid $white-normal; - color: $gl-text-color; + color: $gl-text-color-secondary; position: relative; - - &.event-inline { - .system-note-image { - top: 20px; - } - - .user-avatar { - top: 14px; - } - - .event-title, - .event-item-timestamp { - line-height: 40px; - } - } - - a { - color: $gl-text-color; - } + line-height: $gl-line-height; .system-note-image { position: absolute; left: 0; - top: 14px; svg { - width: 20px; - height: 20px; fill: $gl-text-color-secondary; } + } + + .system-note-image-inline { + svg { + fill: $gl-text-color-secondary; + } + } + .system-note-image, + .system-note-image-inline { &.opened-icon, &.created-icon { svg { @@ -53,16 +41,35 @@ &.accepted-icon svg { fill: $blue-300; } + + &.commented-on-icon svg { + fill: $blue-600; + } + } + + .event-user-info { + margin-bottom: $gl-padding-8; + + .author_name { + a { + color: $gl-text-color; + font-weight: $gl-font-weight-bold; + } + } } .event-title { - @include str-truncated(calc(100% - 174px)); - font-weight: $gl-font-weight-bold; - color: $gl-text-color; + .event-type { + &::first-letter { + text-transform: capitalize; + } + } } .event-body { + margin-top: $gl-padding-8; margin-right: 174px; + color: $gl-text-color; .event-note { word-wrap: break-word; @@ -92,7 +99,7 @@ } .note-image-attach { - margin-top: 4px; + margin-top: $gl-padding-4; margin-left: 0; max-width: 200px; float: none; @@ -107,7 +114,6 @@ color: $gl-gray-500; float: left; font-size: $gl-font-size; - line-height: 16px; margin-right: 5px; } } @@ -127,7 +133,9 @@ } } - &:last-child { border: 0; } + &:last-child { + border: 0; + } .event_commits { li { @@ -154,7 +162,6 @@ .event-item-timestamp { float: right; - line-height: 22px; } } @@ -177,10 +184,8 @@ .event-item { padding-left: 0; - &.event-inline { - .event-title { - line-height: 20px; - } + .event-user-info { + margin-bottom: $gl-padding-4; } .event-title { @@ -194,7 +199,8 @@ } .event-body { - margin: 0; + margin-top: $gl-padding-4; + margin-right: 0; padding-left: 0; } diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index f084adaf5d3114a9a30c8c8bbf301f7f8e6e8bfa..1d691d1d8b80ba4d21fb00be4e86c1154aa944d8 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -240,6 +240,12 @@ left: 0; } + .activities-block { + .event-item { + padding-left: 40px; + } + } + @include media-breakpoint-down(xs) { .cover-block { padding-top: 20px; @@ -267,6 +273,12 @@ margin-right: 0; } } + + .activities-block { + .event-item { + padding-left: 0; + } + } } } diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index c94946a04e720bfd197190a3670fbce0712bb819..2adfc04deb83d0b083b1810c3b6a9ad0b1051ffb 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -163,14 +163,10 @@ module EventsHelper def event_note_title_html(event) if event.note_target - text = raw("#{event.note_target_type} ") + - if event.commit_note? - content_tag(:span, event.note_target_reference, class: 'commit-sha') - else - event.note_target_reference - end - - link_to(text, event_note_target_url(event), title: event.target_title, class: 'has-tooltip') + capture do + concat content_tag(:span, event.note_target_type, class: "event-target-type append-right-4") + concat link_to(event.note_target_reference, event_note_target_url(event), title: event.target_title, class: 'has-tooltip event-target-link append-right-4') + end else content_tag(:strong, '(deleted)') end @@ -183,17 +179,9 @@ module EventsHelper "--broken encoding" end - def event_row_class(event) - if event.body? - "event-block" - else - "event-inline" - end - end - - def icon_for_event(note) + def icon_for_event(note, size: 24) icon_name = ICON_NAMES_BY_EVENT_TYPE[note] - sprite_icon(icon_name) if icon_name + sprite_icon(icon_name, size: size) if icon_name end def icon_for_profile_event(event) @@ -203,8 +191,24 @@ module EventsHelper end else content_tag :div, class: 'system-note-image user-avatar' do - author_avatar(event, size: 32) + author_avatar(event, size: 40) + end + end + end + + def inline_event_icon(event) + unless current_path?('users#show') + content_tag :span, class: "system-note-image-inline d-none d-sm-flex append-right-4 #{event.action_name.parameterize}-icon align-self-center" do + icon_for_event(event.action_name, size: 14) end end end + + def event_user_info(event) + content_tag(:div, class: "event-user-info") do + concat content_tag(:span, link_to_author(event), class: "author_name") + concat " ".html_safe + concat content_tag(:span, event.author.to_reference, class: "username") + end + end end diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 78a1d1a0553c2c47b299eb419d6396062c9deeb8..2fcb1d1fd2b33e0acc244a2439d7c9b2286893b1 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -1,5 +1,5 @@ - if event.visible_to_user?(current_user) - .event-item{ class: event_row_class(event) } + .event-item .event-item-timestamp #{time_ago_with_tooltip(event.created_at)} diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml index 829a3da15580c2132eb7280d157f396fc79d7826..96d6553a2acc97140006c32059894ce53751a51c 100644 --- a/app/views/events/event/_common.html.haml +++ b/app/views/events/event/_common.html.haml @@ -1,20 +1,19 @@ = icon_for_profile_event(event) -.event-title - %span.author_name= link_to_author(event) - %span{ class: event.action_name } += event_user_info(event) + +.event-title.d-flex.flex-wrap + = inline_event_icon(event) - if event.target - = event.action_name - %strong - = link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title do - = event.target_type.titleize.downcase - = event.target.reference_link_text + %span.event-type.d-inline-block.append-right-4{ class: event.action_name } + = event.action_name + %span.event-target-type.append-right-4= event.target_type.titleize.downcase + = link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip event-target-link append-right-4', title: event.target_title do + = event.target.reference_link_text + - unless event.milestone? + %span.event-target-title.append-right-4= """.html_safe + event.target.title + """.html_safe - else - = event_action_name(event) + %span.event-type.d-inline-block.append-right-4{ class: event.action_name } + = event_action_name(event) = render "events/event_scope", event: event - -- if event.target.respond_to?(:title) - .event-body - .event-note - = event.target.title diff --git a/app/views/events/event/_created_project.html.haml b/app/views/events/event/_created_project.html.haml index 6ad7e15713181ea79db69879bb052791889b9ada..2f1566034148dbf86b8a654f3ef6cc31e1e67cae 100644 --- a/app/views/events/event/_created_project.html.haml +++ b/app/views/events/event/_created_project.html.haml @@ -1,8 +1,10 @@ = icon_for_profile_event(event) -.event-title - %span.author_name= link_to_author(event) - %span{ class: event.action_name } += event_user_info(event) + +.event-title.d-flex.flex-wrap + = inline_event_icon(event) + %span.event-type.d-inline-block.append-right-4{ class: event.action_name } = event_action_name(event) - if event.project diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml index cdacd998a6987434c11780bbf5b92c5321406a95..fb0d2c3b8b0b64f506ecbc39c1b536580700616d 100644 --- a/app/views/events/event/_note.html.haml +++ b/app/views/events/event/_note.html.haml @@ -1,9 +1,13 @@ = icon_for_profile_event(event) -.event-title - %span.author_name= link_to_author(event) - = event.action_name += event_user_info(event) + +.event-title.d-flex.flex-wrap + = inline_event_icon(event) + %span.event-type.d-inline-block.append-right-4{ class: event.action_name } + = event.action_name = event_note_title_html(event) + %span.event-target-title.append-right-4= """.html_safe + event.target.title + """.html_safe = render "events/event_scope", event: event diff --git a/app/views/events/event/_private.html.haml b/app/views/events/event/_private.html.haml index ccd2aacb4eafa929930cc19d7d3cf93213b3a354..d91f30c07cb6b60fc3b8460ac98a77b0927bb45f 100644 --- a/app/views/events/event/_private.html.haml +++ b/app/views/events/event/_private.html.haml @@ -1,10 +1,11 @@ -.event-inline.event-item +.event-item .event-item-timestamp = time_ago_with_tooltip(event.created_at) - .system-note-image= sprite_icon('eye-slash', size: 16, css_class: 'icon') + .system-note-image= sprite_icon('eye-slash', size: 24, css_class: 'icon') - .event-title - - author_name = capture do - %span.author_name= link_to_author(event) - = s_('Profiles|%{author_name} made a private contribution').html_safe % { author_name: author_name } + = event_user_info(event) + + .event-title.d-flex.flex-wrap + = inline_event_icon(event) + = s_('Profiles|Made a private contribution') diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml index 5f0ee79cd9b1f0b77e08dce0d64e74cff8a0d170..82693ec832e3ce89e5795ef19ce5ed1888872627 100644 --- a/app/views/events/event/_push.html.haml +++ b/app/views/events/event/_push.html.haml @@ -2,13 +2,15 @@ = icon_for_profile_event(event) -.event-title - %span.author_name= link_to_author(event) - %span.pushed #{event.action_name} #{event.ref_type} - %strong += event_user_info(event) + +.event-title.d-flex.flex-wrap + = inline_event_icon(event) + %span.event-type.d-inline-block.append-right-4.pushed #{event.action_name} #{event.ref_type} + %span - commits_link = project_commits_path(project, event.ref_name) - should_link = event.tag? ? project.repository.tag_exists?(event.ref_name) : project.repository.branch_exists?(event.ref_name) - = link_to_if should_link, event.ref_name, commits_link, class: 'ref-name' + = link_to_if should_link, event.ref_name, commits_link, class: 'ref-name append-right-4' = render "events/event_scope", event: event diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml index f8b3754840dabeaa817fa9d030a4d8c4479fb4a5..cf525f2bb2d8b10406a86a3890b898a76e321a64 100644 --- a/app/views/users/_overview.html.haml +++ b/app/views/users/_overview.html.haml @@ -11,8 +11,8 @@ - if can?(current_user, :read_cross_project) .activities-block - .content-block - %h5.prepend-top-10 + .border-bottom.prepend-top-16 + %h5 = s_('UserProfile|Recent contributions') .overview-content-list{ data: { href: user_path } } .center.light.loading @@ -22,7 +22,7 @@ .col-md-12.col-lg-6 .projects-block - .content-block + .border-bottom.prepend-top-16 %h4 = s_('UserProfile|Personal projects') .overview-content-list{ data: { href: user_projects_path } } diff --git a/changelogs/unreleased/49403-redesign-activity-feed.yml b/changelogs/unreleased/49403-redesign-activity-feed.yml new file mode 100644 index 0000000000000000000000000000000000000000..cec53a3ef5a66f7842c1e2b28f84f3e285e22ebb --- /dev/null +++ b/changelogs/unreleased/49403-redesign-activity-feed.yml @@ -0,0 +1,4 @@ +title: Redesign activity feed +merge_request: 22217 +author: +type: other diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 1c4c9180c426f753575659f7ce9b4911ab29d969..98417c08dfd0cbd2beb9b7615e482fba3c5e9c34 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -4641,9 +4641,6 @@ msgstr "" msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible." msgstr "" -msgid "Profiles|%{author_name} made a private contribution" -msgstr "" - msgid "Profiles|Account scheduled for removal." msgstr "" @@ -4704,6 +4701,9 @@ msgstr "" msgid "Profiles|Invalid username" msgstr "" +msgid "Profiles|Made a private contribution" +msgstr "" + msgid "Profiles|Main settings" msgstr "" diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index aa3ca8923ffda57235a8cbf72f7596a5fc2ae131..a1f93bd3fbddd137a2f321f2813f58673ce542aa 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -153,7 +153,7 @@ describe 'Contributions Calendar', :js do include_context 'visit user page' it 'displays calendar activity log' do - expect(find('.tab-pane#activity .content_list .event-note')).to have_content issue_title + expect(find('.tab-pane#activity .content_list .event-target-title')).to have_content issue_title end end end diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb index 498775acff3ff4049d52ddb68c0f56190b749e9e..16919fe63adc14ae37c56dd2c468649cadef4cc5 100644 --- a/spec/features/dashboard/project_member_activity_index_spec.rb +++ b/spec/features/dashboard/project_member_activity_index_spec.rb @@ -14,14 +14,15 @@ describe 'Project member activity', :js do wait_for_requests end - subject { page.find(".event-title").text } - context 'when a user joins the project' do before do visit_activities_and_wait_with_event(Event::JOINED) end - it { is_expected.to eq("#{user.name} joined project") } + it "presents the correct message" do + expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}") + expect(page.find('.event-title').text).to eq("joined project") + end end context 'when a user leaves the project' do @@ -29,7 +30,10 @@ describe 'Project member activity', :js do visit_activities_and_wait_with_event(Event::LEFT) end - it { is_expected.to eq("#{user.name} left project") } + it "presents the correct message" do + expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}") + expect(page.find('.event-title').text).to eq("left project") + end end context 'when a users membership expires for the project' do @@ -38,8 +42,8 @@ describe 'Project member activity', :js do end it "presents the correct message" do - message = "#{user.name} removed due to membership expiration from project" - is_expected.to eq(message) + expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}") + expect(page.find('.event-title').text).to eq("removed due to membership expiration from project") end end end diff --git a/spec/features/milestones/user_creates_milestone_spec.rb b/spec/features/milestones/user_creates_milestone_spec.rb index 8fd057d587cba2a3e3454a562b1f273fa2e1568b..5de0c381cdfb903e9dc315714859f4c1ce9a169a 100644 --- a/spec/features/milestones/user_creates_milestone_spec.rb +++ b/spec/features/milestones/user_creates_milestone_spec.rb @@ -24,6 +24,6 @@ describe "User creates milestone", :js do visit(activity_project_path(project)) - expect(page).to have_content("#{user.name} opened milestone") + expect(page).to have_content("#{user.name} #{user.to_reference} opened milestone") end end diff --git a/spec/features/milestones/user_deletes_milestone_spec.rb b/spec/features/milestones/user_deletes_milestone_spec.rb index a8c296b4cd2eaa0b02fa0bbdbd79fc9866f03fa0..f68ed1cde071a2127952a423fffb2f642463521a 100644 --- a/spec/features/milestones/user_deletes_milestone_spec.rb +++ b/spec/features/milestones/user_deletes_milestone_spec.rb @@ -23,7 +23,7 @@ describe "User deletes milestone", :js do visit(activity_project_path(project)) - expect(page).to have_content("#{user.name} destroyed milestone") + expect(page).to have_content("#{user.name} #{user.to_reference} destroyed milestone") end end diff --git a/spec/features/projects/activity/user_sees_activity_spec.rb b/spec/features/projects/activity/user_sees_activity_spec.rb index ebaa137772d0b51b146d140f0e508e0eb0dca9d7..bb4b2abc3c72d08a01bf57112643ae2c65d1eb32 100644 --- a/spec/features/projects/activity/user_sees_activity_spec.rb +++ b/spec/features/projects/activity/user_sees_activity_spec.rb @@ -19,13 +19,13 @@ describe 'Projects > Activity > User sees activity' do it 'shows the last push in the activity page', :js do visit activity_project_path(project) - expect(page).to have_content "#{user.name} pushed new branch fix" + expect(page).to have_content "#{user.name} #{user.to_reference} pushed new branch fix" end it 'allows to filter event with the "event_filter=issue" URL param', :js do visit activity_project_path(project, event_filter: 'issue') - expect(page).not_to have_content "#{user.name} pushed new branch fix" - expect(page).to have_content "#{user.name} opened issue #{issue.to_reference}" + expect(page).not_to have_content "#{user.name} #{user.to_reference} pushed new branch fix" + expect(page).to have_content "#{user.name} #{user.to_reference} opened issue #{issue.to_reference}" end end diff --git a/spec/features/projects/activity/user_sees_private_activity_spec.rb b/spec/features/projects/activity/user_sees_private_activity_spec.rb index d7dc0a6712a913827cc92b6b619660ee61c8f4ae..61ec2ce9d29dc6e0f0639fcca146f2894ab647c3 100644 --- a/spec/features/projects/activity/user_sees_private_activity_spec.rb +++ b/spec/features/projects/activity/user_sees_private_activity_spec.rb @@ -5,7 +5,7 @@ describe 'Project > Activity > User sees private activity', :js do let(:author) { create(:user) } let(:user) { create(:user) } let(:issue) { create(:issue, :confidential, project: project, author: author) } - let(:message) { "#{author.name} opened issue #{issue.to_reference}" } + let(:message) { "#{author.name} #{author.to_reference} opened issue #{issue.to_reference}" } before do project.add_developer(author)