background: #282c37;
background-size: cover;
padding: 60px 0;
- padding-bottom: 10px;
+ padding-bottom: 0;
border-radius: 4px 4px 0 0;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
overflow: hidden;
width: 80px;
color: #9baec8;
padding: 0 10px;
+ margin-bottom: 10px;
border-right: 1px solid #9baec8;
cursor: default;
+ position: relative;
+
+ a {
+ display: block;
+ }
+
+ &:after {
+ display: block;
+ content: "";
+ position: absolute;
+ bottom: -10px;
+ left: 0;
+ width: 100%;
+ border-bottom: 4px solid #9baec8;
+ opacity: 0.5;
+ transition: all 0.8s ease;
+ }
+
+ &.active {
+ &:after {
+ border-bottom: 4px solid #2b90d9;
+ opacity: 1;
+ }
+ }
+
+ &:hover {
+ &:after {
+ opacity: 1;
+ transition-duration: 0.2s;
+ }
+ }
+
+ a {
+ text-decoration: none;
+ color: inherit;
+ }
.counter-label {
font-size: 12px;
color: lighten(#282c37, 10%);
}
}
+
+.accounts-grid {
+ clear: both;
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+ background: #fff;
+ border-radius: 0 0 4px 4px;
+ padding: 20px 10px;
+ padding-bottom: 10px;
+ overflow: hidden;
+
+ .account-grid-card {
+ box-sizing: border-box;
+ width: 335px;
+ float: left;
+ border: 1px solid #d9e1e8;
+ border-radius: 4px;
+ color: #282c37;
+ height: 160px;
+ margin-bottom: 10px;
+
+ &:nth-child(odd) {
+ margin-right: 10px;
+ }
+
+ .account-grid-card__header {
+ overflow: hidden;
+ padding: 10px;
+ border-bottom: 1px solid #d9e1e8;
+ }
+
+ .avatar {
+ width: 60px;
+ height: 60px;
+ float: left;
+ margin-right: 15px;
+
+ img {
+ display: block;
+ width: 60px;
+ height: 60px;
+ border-radius: 60px;
+ }
+ }
+
+ .name {
+ padding-top: 10px;
+
+ a {
+ color: #282c37;
+ text-decoration: none;
+
+ &:hover {
+ .display_name {
+ text-decoration: underline;
+ }
+ }
+ }
+ }
+
+ .display_name {
+ font-size: 14px;
+ display: block;
+ }
+
+ .username {
+ color: #2b90d9;
+ }
+
+ .note {
+ padding: 10px;
+ padding-top: 15px;
+ color: #9baec8;
+ }
+ }
+}
+
+.nothing-here {
+ color: #9baec8;
+ font-size: 14px;
+ font-weight: 500;
+ text-align: center;
+ padding: 15px 0;
+ cursor: default;
+}
end
end
+ def followers
+ @followers = @account.followers.paginate(page: params[:page], per_page: 6)
+ end
+
+ def following
+ @following = @account.following.paginate(page: params[:page], per_page: 6)
+ end
+
private
def set_account
module AccountsHelper
-
+ def pagination_options
+ { previous_label: "#{fa_icon('chevron-left')} Prev".html_safe, next_label: "Next #{fa_icon('chevron-right')}".html_safe, inner_window: 2 }
+ end
end
--- /dev/null
+.account-grid-card
+ .account-grid-card__header
+ .avatar= image_tag account.avatar.url(:medium)
+ .name
+ = link_to url_for_target(account) do
+ %span.display_name= display_name(account)
+ %span.username= "@#{account.acct}"
+ %p.note= account.note
--- /dev/null
+.card{ style: "background-image: url(#{@account.header.url(:medium)})" }
+ .avatar= image_tag @account.avatar.url(:large)
+ %h1.name
+ = display_name(@account)
+ %small= "@#{@account.username}"
+ .details
+ .counter{ class: active_nav_class(account_url(@account)) }
+ = link_to account_url(@account) do
+ %span.counter-label Posts
+ %span.counter-number= @account.statuses.count
+ .counter{ class: active_nav_class(following_account_url(@account)) }
+ = link_to following_account_url(@account) do
+ %span.counter-label Following
+ %span.counter-number= @account.following.count
+ .counter{ class: active_nav_class(followers_account_url(@account)) }
+ = link_to followers_account_url(@account) do
+ %span.counter-label Followers
+ %span.counter-number= @account.followers.count
+ .bio
+ %p= @account.note
--- /dev/null
+%p.nothing-here There is nothing here!
--- /dev/null
+- content_for :page_title do
+ People who follow
+ = display_name(@account)
+
+= render partial: 'header'
+
+.accounts-grid
+ - @followers.each do |f|
+ = render partial: 'grid_card', locals: { account: f }
+
+ - if @followers.empty?
+ = render partial: 'nothing_here'
+
+= will_paginate @followers, pagination_options
--- /dev/null
+- content_for :page_title do
+ People whom
+ = display_name(@account)
+ follows
+
+= render partial: 'header'
+
+.accounts-grid
+ - @following.each do |f|
+ = render partial: 'grid_card', locals: { account: f }
+
+ - if @following.empty?
+ = render partial: 'nothing_here'
+
+= will_paginate @following, pagination_options
%link{ rel: 'salmon', href: api_salmon_url(@account.id) }/
%link{ rel: 'alternate', type: 'application/atom+xml', href: account_url(@account, format: 'atom') }/
-.card{ style: "background-image: url(#{@account.header.url(:medium)})" }
- .avatar= image_tag @account.avatar.url(:large)
- %h1.name
- = display_name(@account)
- %small= "@#{@account.username}"
- .details
- .counter
- %span.counter-label Posts
- %span.counter-number= @account.statuses.count
- .counter
- %span.counter-label Following
- %span.counter-number= @account.following.count
- .counter
- %span.counter-label Followers
- %span.counter-number= @account.followers.count
- .bio
- %p= @account.note
+= render partial: 'header'
.activity-stream
- @statuses.each do |status|
= render partial: 'stream_entries/status', locals: { status: status, include_threads: false, is_successor: false, is_predecessor: false }
-= will_paginate @statuses, previous_label: "#{fa_icon('chevron-left')} Prev".html_safe, next_label: "Next #{fa_icon('chevron-right')}".html_safe, inner_window: 2
+= will_paginate @statuses, pagination_options
resources :accounts, path: 'users', only: [:show], param: :username do
resources :stream_entries, path: 'updates', only: [:show]
+
+ member do
+ get :followers
+ get :following
+ end
end
resource :settings, only: [:show, :update]
let(:alice) { Fabricate(:account, username: 'alice') }
describe 'GET #show' do
- it 'returns 200' do
+ it 'returns http success' do
get :show, username: alice.username
expect(response).to have_http_status(:success)
end
- it 'returns 200 with Atom' do
+ it 'returns http success with Atom' do
get :show, username: alice.username, format: 'atom'
expect(response).to have_http_status(:success)
end
end
+
+ describe 'GET #followers' do
+ it 'returns http success' do
+ get :followers, username: alice.username
+ expect(response).to have_http_status(:success)
+ end
+ end
+
+ describe 'GET #following' do
+ it 'returns http success' do
+ get :following, username: alice.username
+ expect(response).to have_http_status(:success)
+ end
+ end
end
RSpec.describe HomeController, type: :controller do
describe 'GET #index' do
- it 'returns 200' do
+ it 'redirects to login page' do
get :index
expect(response).to redirect_to(new_user_session_path)
end
let(:status) { Fabricate(:status, account: alice) }
describe 'GET #show' do
- it 'returns 200 with HTML' do
+ it 'returns http success with HTML' do
get :show, account_username: alice.username, id: status.stream_entry.id
expect(response).to have_http_status(:success)
end
- it 'returns 200 with Atom' do
+ it 'returns http success with Atom' do
get :show, account_username: alice.username, id: status.stream_entry.id, format: 'atom'
expect(response).to have_http_status(:success)
end
RSpec.describe XrdController, type: :controller do
describe 'GET #host_meta' do
- it 'returns 200' do
+ it 'returns http success' do
get :host_meta
expect(response).to have_http_status(:success)
end
describe 'GET #webfinger' do
let(:alice) { Fabricate(:account, username: 'alice') }
- it 'returns 200 when account can be found' do
+ it 'returns http success when account can be found' do
get :webfinger, resource: "acct:#{alice.username}@anything.com"
expect(response).to have_http_status(:success)
end
- it 'returns 404 when account cannot be found' do
+ it 'returns http not found when account cannot be found' do
get :webfinger, resource: 'acct:not@existing.com'
expect(response).to have_http_status(:not_found)
end