forked from treehouse/mastodon
Adding public following and followers pages, fix #3
parent
c349200761
commit
71ae4dd3d2
|
@ -2,7 +2,7 @@
|
|||
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;
|
||||
|
@ -64,8 +64,45 @@
|
|||
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;
|
||||
|
@ -145,3 +182,87 @@
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,14 @@ class AccountsController < ApplicationController
|
|||
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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
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
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
.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
|
|
@ -0,0 +1,20 @@
|
|||
.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
|
|
@ -0,0 +1 @@
|
|||
%p.nothing-here There is nothing here!
|
|
@ -0,0 +1,14 @@
|
|||
- 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
|
|
@ -0,0 +1,15 @@
|
|||
- 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
|
|
@ -5,26 +5,10 @@
|
|||
%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
|
||||
|
|
|
@ -14,6 +14,11 @@ Rails.application.routes.draw do
|
|||
|
||||
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]
|
||||
|
|
|
@ -4,14 +4,28 @@ RSpec.describe AccountsController, type: :controller do
|
|||
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
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'rails_helper'
|
|||
|
||||
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
|
||||
|
|
|
@ -5,12 +5,12 @@ RSpec.describe StreamEntriesController, type: :controller do
|
|||
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
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'rails_helper'
|
|||
|
||||
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
|
||||
|
@ -11,12 +11,12 @@ RSpec.describe XrdController, type: :controller do
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue