From 74b398d876f9d2df82f6a91cd09388adec387a8f Mon Sep 17 00:00:00 2001 From: ludwiczakpawel Date: Thu, 3 Sep 2020 16:47:01 +0200 Subject: [PATCH] New Profile Header (#10185) * init * profile header * merge * two headers * centerd * link fix * remove comments * whoops * Fix specs Co-authored-by: rhymes --- app/assets/images/behance.svg | 3 + app/assets/images/cake.svg | 3 + app/assets/images/dribbble.svg | 3 + app/assets/images/email.svg | 3 + app/assets/images/external.svg | 3 + app/assets/images/gitlab.svg | 4 +- app/assets/images/linkedin.svg | 3 + app/assets/images/location.svg | 3 + app/assets/images/mastodon.svg | 3 + app/assets/images/medium.svg | 3 + app/assets/images/stackoverflow.svg | 3 + app/assets/images/youtube.svg | 3 + .../initializers/initializeAllChatButtons.js | 24 +- .../initializers/initializeUserProfilePage.js | 28 +- app/assets/stylesheets/crayons.scss | 1 + app/assets/stylesheets/views/profile.scss | 138 ++++++++ app/views/users/_metadata.html.erb | 34 ++ app/views/users/show.html.erb | 313 +++++++++--------- spec/system/user/view_user_index_spec.rb | 4 +- 19 files changed, 398 insertions(+), 181 deletions(-) create mode 100644 app/assets/images/behance.svg create mode 100644 app/assets/images/cake.svg create mode 100644 app/assets/images/dribbble.svg create mode 100644 app/assets/images/email.svg create mode 100644 app/assets/images/external.svg create mode 100644 app/assets/images/linkedin.svg create mode 100644 app/assets/images/location.svg create mode 100644 app/assets/images/mastodon.svg create mode 100644 app/assets/images/medium.svg create mode 100644 app/assets/images/stackoverflow.svg create mode 100644 app/assets/images/youtube.svg create mode 100644 app/assets/stylesheets/views/profile.scss create mode 100644 app/views/users/_metadata.html.erb diff --git a/app/assets/images/behance.svg b/app/assets/images/behance.svg new file mode 100644 index 000000000..f78dac7c2 --- /dev/null +++ b/app/assets/images/behance.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/cake.svg b/app/assets/images/cake.svg new file mode 100644 index 000000000..e3c7d413b --- /dev/null +++ b/app/assets/images/cake.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/dribbble.svg b/app/assets/images/dribbble.svg new file mode 100644 index 000000000..a581d9370 --- /dev/null +++ b/app/assets/images/dribbble.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/email.svg b/app/assets/images/email.svg new file mode 100644 index 000000000..47e4f94db --- /dev/null +++ b/app/assets/images/email.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/external.svg b/app/assets/images/external.svg new file mode 100644 index 000000000..a9886a473 --- /dev/null +++ b/app/assets/images/external.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/gitlab.svg b/app/assets/images/gitlab.svg index c9e35afc9..1097fb86b 100644 --- a/app/assets/images/gitlab.svg +++ b/app/assets/images/gitlab.svg @@ -1,3 +1,3 @@ - - + + diff --git a/app/assets/images/linkedin.svg b/app/assets/images/linkedin.svg new file mode 100644 index 000000000..99cd1f510 --- /dev/null +++ b/app/assets/images/linkedin.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/location.svg b/app/assets/images/location.svg new file mode 100644 index 000000000..2d7dbc2c4 --- /dev/null +++ b/app/assets/images/location.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/mastodon.svg b/app/assets/images/mastodon.svg new file mode 100644 index 000000000..a4f22f95f --- /dev/null +++ b/app/assets/images/mastodon.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/medium.svg b/app/assets/images/medium.svg new file mode 100644 index 000000000..7e0860859 --- /dev/null +++ b/app/assets/images/medium.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/stackoverflow.svg b/app/assets/images/stackoverflow.svg new file mode 100644 index 000000000..16dbb4729 --- /dev/null +++ b/app/assets/images/stackoverflow.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/images/youtube.svg b/app/assets/images/youtube.svg new file mode 100644 index 000000000..03ada93f3 --- /dev/null +++ b/app/assets/images/youtube.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/javascripts/initializers/initializeAllChatButtons.js b/app/assets/javascripts/initializers/initializeAllChatButtons.js index faf3061a1..56957fee3 100644 --- a/app/assets/javascripts/initializers/initializeAllChatButtons.js +++ b/app/assets/javascripts/initializers/initializeAllChatButtons.js @@ -12,20 +12,16 @@ function hideChatModal(modal) { } function toggleModal() { - var modal = document.querySelector('.modal'); - var currentState = modal.style.display; - - if (currentState === 'none') { - showChatModal(modal); - } else { - hideChatModal(modal); - } + var modal = document.querySelector('.crayons-modal'); + modal.classList.toggle('hidden'); } function initModal() { - var modal = document.querySelector('.modal'); + var modal = document.querySelector('.crayons-modal'); modal.querySelector('.close-modal').addEventListener('click', toggleModal); - modal.querySelector('.overlay').addEventListener('click', toggleModal); + modal + .querySelector('.crayons-modal__overlay') + .addEventListener('click', toggleModal); } function handleChatButtonPress(form) { @@ -56,8 +52,8 @@ function addButtonClickHandle(response, button, modalInfo) { linkWrap.removeAttribute('href'); // remove link button.addEventListener('click', toggleModal); // eslint-disable-next-line no-param-reassign - button.style.display = 'initial'; // show button - linkWrap.style.display = 'initial'; // show button + button.classList.remove('hidden'); // show button + linkWrap.classList.remove('hidden'); // show button form.onsubmit = () => { handleChatButtonPress(form); return false; @@ -65,8 +61,8 @@ function addButtonClickHandle(response, button, modalInfo) { } else if (response === 'mutual') { button.removeEventListener('click', toggleModal); // eslint-disable-next-line no-param-reassign - button.style.display = 'initial'; // show button - linkWrap.style.display = 'initial'; // show button + button.classList.remove('hidden'); // show button + linkWrap.classList.remove('hidden'); // show button } } diff --git a/app/assets/javascripts/initializers/initializeUserProfilePage.js b/app/assets/javascripts/initializers/initializeUserProfilePage.js index c79ecbf42..87c2da77b 100644 --- a/app/assets/javascripts/initializers/initializeUserProfilePage.js +++ b/app/assets/javascripts/initializers/initializeUserProfilePage.js @@ -1,23 +1,33 @@ 'use strict'; function initializeUserProfilePage() { - const profileDropdownDiv = document.getElementsByClassName("profile-dropdown")[0]; + const profileDropdownDiv = document.getElementsByClassName( + 'profile-dropdown', + )[0]; if (profileDropdownDiv) { const currentUser = userData(); - if (currentUser && (currentUser.username === profileDropdownDiv.dataset.username)) { + if ( + currentUser && + currentUser.username === profileDropdownDiv.dataset.username + ) { profileDropdownDiv.hidden = true; - } - else { + } else { profileDropdownDiv.hidden = false; - const userProfileDropdownButton = document.getElementById('user-profile-dropdown'); + const userProfileDropdownButton = document.getElementById( + 'user-profile-dropdown', + ); if (userProfileDropdownButton) { - const userProfileDropdownMenu = document.getElementById('user-profile-dropdownmenu'); + const userProfileDropdownMenu = document.getElementById( + 'user-profile-dropdownmenu', + ); userProfileDropdownButton.addEventListener('click', () => { - userProfileDropdownMenu.classList.toggle('showing'); + userProfileDropdownMenu.classList.toggle('block'); // Add actual link location (SEO doesn't like these "useless" links, so adding in here instead of in HTML) - var reportAbuseLink = profileDropdownDiv.querySelector('.report-abuse-link-wrapper'); - reportAbuseLink.innerHTML = `Report Abuse` + var reportAbuseLink = profileDropdownDiv.querySelector( + '.report-abuse-link-wrapper', + ); + reportAbuseLink.innerHTML = `Report Abuse`; }); } } diff --git a/app/assets/stylesheets/crayons.scss b/app/assets/stylesheets/crayons.scss index 43749bf05..459826e39 100644 --- a/app/assets/stylesheets/crayons.scss +++ b/app/assets/stylesheets/crayons.scss @@ -32,5 +32,6 @@ @import 'views/article-form'; @import 'views/listings'; @import 'views/dashboard'; +@import 'views/profile'; @import 'views/signin'; @import 'views/sponsors'; diff --git a/app/assets/stylesheets/views/profile.scss b/app/assets/stylesheets/views/profile.scss new file mode 100644 index 000000000..bb0e63974 --- /dev/null +++ b/app/assets/stylesheets/views/profile.scss @@ -0,0 +1,138 @@ +@import '../config/import'; + +.profile-header { + --padding: var(--su-3); + border-radius: 0; + + @media (min-width: $breakpoint-s) { + --padding: var(--su-4); + } + + @media (min-width: $breakpoint-m) { + border-radius: var(--radius); + text-align: center; + } + + @media (min-width: $breakpoint-l) { + --padding: var(--su-6); + } + + &__top { + margin-top: calc(-1 * var(--su-7)); + margin-bottom: var(--su-4); + position: relative; + padding: 0 var(--padding); + + @media (min-width: $breakpoint-m) { + margin-top: calc(-1 * var(--su-9)); + margin-bottom: var(--su-3); + } + } + + &__actions { + display: flex; + right: 0; + top: var(--su-7); + position: absolute; + padding: var(--padding) var(--padding) 0 0; + + @media (min-width: $breakpoint-m) { + top: var(--su-9); + } + } + + &__details { + padding: var(--padding); + padding-top: 0; + } + + &__meta { + font-size: var(--fs-s); + color: var(--base-60); + margin-bottom: var(--su-2); + display: flex; + flex-wrap: wrap; + align-items: center; + margin-left: calc(-1 * var(--su-1)); + + @media (min-width: $breakpoint-m) { + justify-content: center; + margin-left: 0; + } + + a { + color: var(--link-color-secondary); + + &:hover { + color: var(--link-color-hover); + } + } + + &__item { + display: flex; + align-items: center; + flex-wrap: nowrap; + white-space: nowrap; + padding: var(--su-2) var(--su-2); + + @media (min-width: $breakpoint-m) { + padding: var(--su-1) var(--su-3); + } + } + } + + &__bottom { + border-top: 1px solid var(--base-10); + padding: calc(var(--padding) / 2); + display: flex; + flex-flow: column; + justify-content: space-evenly; + + @media (min-width: $breakpoint-s) { + flex-flow: row; + } + + .crayons-definition { + padding: calc(var(--padding) / 2); + } + } + + .crayons-avatar { + width: var(--su-9); + height: var(--su-9); + border: var(--su-1) solid var(--profile-brand-color); + + @media (min-width: $breakpoint-m) { + border-width: var(--su-2); + width: var(--su-10); + height: var(--su-10); + } + } +} + +.crayons-definition { + font-size: inherit; + + &__title { + font-size: 85%; + font-weight: var(--fw-medium); + color: var(--base-60); + display: block; + } +} + +.brand-bg { + background: linear-gradient( + 180deg, + var(--profile-brand-color) var(--su-9), + transparent var(--su-9) + ); + + @media (min-width: $breakpoint-m) { + background: linear-gradient( + 180deg, + var(--profile-brand-color) var(--su-10), + transparent var(--su-10) + ); + } +} diff --git a/app/views/users/_metadata.html.erb b/app/views/users/_metadata.html.erb new file mode 100644 index 000000000..ca95284fd --- /dev/null +++ b/app/views/users/_metadata.html.erb @@ -0,0 +1,34 @@ +<% if @user.employment_title.present? || (@user.looking_for_work_publicly == true && @user.looking_for_work == true) || @user.education.present? %> +
+ <% if @user.education.present? %> +
+ Education +

<%= @user.education %>

+
+ <% end %> + + <% if @user.employment_title.present? %> +
+ Work +

+ <%= @user.employment_title %> + <% if @user.employer_name.present? %> + at + <% if @user.employer_url.present? %> + <%= @user.employer_name %> + <% else %> + <%= @user.employer_name %> + <% end %> + <% end %> +

+
+ <% end %> + + <% if @user.looking_for_work_publicly == true && @user.looking_for_work == true %> +
+ Work status +

I'm looking for work!

+
+ <% end %> +
+<% end %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index a939c7d83..df6d31412 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -13,169 +13,174 @@ <% end %> <% cache "main-user-profile-header-area-#{@user.id}-#{@user.profile_updated_at}-#{user_signed_in?}", expires_in: 10.days do %> - + +
+

<%= @user.name %>

+

<%= @user.summary.presence || ["404 bio not found"].sample %>

+ +
+ <% if @user.location.present? %> + + <%= inline_svg_tag("location.svg", aria: true, class: "crayons-icon mr-2 shrink-0", title: "Location") %> + <%= @user.location %> + + <% end %> + + + <%= inline_svg_tag("cake.svg", aria: true, class: "crayons-icon mr-2 shrink-0", title: "Joined") %> + Joined on  + <%= local_date(@user.created_at) %> + + + <% if @user.email_public %> + + <%= inline_svg_tag("email.svg", class: "crayons-icon mr-2 shrink-0", aria: true, title: "Email address") %> + <%= @user.email %> + + <% end %> + + <% if @user.twitter_username? %> + + <%= inline_svg_tag("twitter.svg", class: "crayons-icon", aria: true, title: "Twitter logo") %> + + <% end %> + <% if @user.github_username? %> + + <%= inline_svg_tag("github.svg", class: "crayons-icon", aria: true, title: "GitHub logo") %> + + <% end %> + <% if @user.mastodon_url? %> + + <%= inline_svg_tag("mastodon.svg", class: "crayons-icon", aria: true, title: "Mastodon logo") %> + + <% end %> + <% if @user.facebook_url? %> + + <%= inline_svg_tag("facebook.svg", class: "crayons-icon", aria: true, title: "Facebook logo") %> + + <% end %> + <% if @user.youtube_url? %> + + <%= inline_svg_tag("youtube.svg", class: "crayons-icon", aria: true, title: "Youtube logo") %> + + <% end %> + <% if @user.linkedin_url? %> + + <%= inline_svg_tag("linkedin.svg", class: "crayons-icon", aria: true, title: "LinkedIn logo") %> + + <% end %> + <% if @user.behance_url? %> + + <%= inline_svg_tag("behance.svg", class: "crayons-icon", aria: true, title: "Behance logo") %> + + <% end %> + <% if @user.stackoverflow_url? %> + + <%= inline_svg_tag("stackoverflow.svg", class: "crayons-icon", aria: true, title: "StackOverflow logo") %> + + <% end %> + <% if @user.dribbble_url? %> + + <%= inline_svg_tag("dribbble.svg", class: "crayons-icon", aria: true, title: "Dribbble logo") %> + + <% end %> + <% if @user.medium_url? %> + + <%= inline_svg_tag("medium.svg", class: "crayons-icon", aria: true, title: "Medium logo") %> + + <% end %> + <% if @user.gitlab_url? %> + + <%= inline_svg_tag("gitlab.svg", class: "crayons-icon", aria: true, title: "GitLab logo") %> + + <% end %> + <% if @user.instagram_url? %> + + <%= inline_svg_tag("instagram.svg", class: "crayons-icon", aria: true, title: "Instagram logo") %> + + <% end %> + <% if @user.twitch_username? %> + + <%= inline_svg_tag("twitch.svg", class: "crayons-icon", id: "icon-twitch", aria: true, title: "Twitch logo") %> + + <% elsif @user.twitch_url? %> + + <%= inline_svg_tag("twitch.svg", class: "crayons-icon", aria: true, title: "Twitch logo") %> + + <% end %> + <% if @user.website_url? %> + + <%= inline_svg_tag("external.svg", class: "crayons-icon", aria: true, title: "External link icon") %> + + <% end %> + +
+
+ + <%= render "users/metadata" %> + + + <% end %> -<% if @user.currently_streaming_on_twitch? %> - -<% end %> -
" data-which="<%= @list_of %>" data-tag="" diff --git a/spec/system/user/view_user_index_spec.rb b/spec/system/user/view_user_index_spec.rb index ac27e5bcb..4875ce33d 100644 --- a/spec/system/user/view_user_index_spec.rb +++ b/spec/system/user/view_user_index_spec.rb @@ -13,7 +13,7 @@ RSpec.describe "User index", type: :system, stub_elasticsearch: true do it "shows the header", js: true do within("h1") { expect(page).to have_content(user.name) } - within(".profile-details") do + within(".profile-header__actions") do expect(page).to have_button("Follow") end end @@ -80,7 +80,7 @@ RSpec.describe "User index", type: :system, stub_elasticsearch: true do it "shows the header", js: true do within("h1") { expect(page).to have_content(user.name) } - within(".profile-details") do + within(".profile-header__actions") do expect(page).to have_button("Edit profile") end end