Skip to content

Commit

Permalink
User profile page (#28)
Browse files Browse the repository at this point in the history
* User profile page

Profile page url: `/users/:login`
Search by user login url: `/?user=login&type=blog_post`

Partially fixes #3

* User#me & profile navigation links

* Allow searching by user together with other queries

* Improve sidebar

* Save space on sidebar
  • Loading branch information
veelenga committed Aug 10, 2017
1 parent cbbbf35 commit a5ae689
Show file tree
Hide file tree
Showing 16 changed files with 248 additions and 65 deletions.
2 changes: 2 additions & 0 deletions config/routes.cr
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Amber::Server.instance.config do |app|
get "/sessions/new", SessionsController, :new
delete "/sessions", SessionsController, :destroy
get "/github/auth", SessionsController, :create
get "/me", UserController, :me
get "/users/:login", UserController, :show
get "/", AnnouncementController, :index
end
end
67 changes: 30 additions & 37 deletions public/stylesheets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -1643,17 +1643,14 @@ a.post-thumbnail:focus {
}

.author-info {
border-top: 1px solid #eaeaea;
border-top: 1px solid rgba(51, 51, 51, 0.1);
margin: 0 3.6923%;
padding: 3.6923% 0;
}

.author-info .avatar {
float: left;
height: 36px;
margin: 0 1.6em 1.6em 0;
width: 36px;
height: 120px;
margin: 0 1.6em 0 0;
width: 120px;
}

.author-heading {
Expand All @@ -1668,6 +1665,8 @@ a.post-thumbnail:focus {
}

.author-title {
margin-top: 0px !important;
margin-bottom: 0px !important;
clear: none;
}

Expand All @@ -1688,7 +1687,7 @@ a.post-thumbnail:focus {
}

.author-description a {
border-bottom: 1px solid #333;
border-bottom: 0;
}

.author-description a:hover,
Expand Down Expand Up @@ -2211,7 +2210,6 @@ a.post-thumbnail:focus {

.site-info a {
border-bottom: 1px solid transparent;
color: #707070;
color: rgba(51, 51, 51, 0.7);
}

Expand Down Expand Up @@ -2663,7 +2661,7 @@ p > video {
.pagination {
border-top: 0;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.15);
margin: 3.6923% 7.6923% 0;
margin: 3.6923% 3.6923% 0;
padding: 0;
}

Expand Down Expand Up @@ -3142,15 +3140,10 @@ p > video {
top: 2px;
}

.author-info {
margin: 0 9.0909%;
padding: 9.0909% 0;
}

.author-info .avatar {
height: 42px;
margin: 0 1.6471em 1.6471em 0;
width: 42px;
height: 180px;
margin: 0 1.6471em 0 0;
width: 180px;
}

.author-link:after {
Expand Down Expand Up @@ -3714,9 +3707,9 @@ p > video {
}

.author-info .avatar {
height: 56px;
margin: 0 1.6842em 1.6842em 0;
width: 56px;
height: 180px;
margin: 0 1.6842em 0 0;
width: 180px;
}

.author-link:after {
Expand Down Expand Up @@ -4016,7 +4009,7 @@ p > video {
.main-navigation {
font-size: 12px;
font-size: 1.2rem;
margin: 0 20% 20%;
margin: 0 20% 15%;
}

.main-navigation a {
Expand Down Expand Up @@ -4053,7 +4046,7 @@ p > video {
}

.social-navigation li {
width: 25%;
width: 20%;
}

.social-navigation a {
Expand Down Expand Up @@ -4100,7 +4093,7 @@ p > video {
}

.pagination {
margin: 8.333% 8.333% 0;
margin: 3.333% 8.333% 0;
}

.pagination .nav-links {
Expand Down Expand Up @@ -4167,7 +4160,7 @@ p > video {
.site-header {
background-color: transparent;
border-bottom: 0;
margin: 20% 0;
margin: 15% 0;
padding: 0 20%;
}

Expand All @@ -4190,7 +4183,7 @@ p > video {
.widget {
font-size: 12px;
font-size: 1.2rem;
margin: 0 0 20%;
margin: 0 0 15%;
padding: 0 20%;
}

Expand Down Expand Up @@ -4381,14 +4374,14 @@ p > video {
}

.author-info {
margin: 0 10%;
padding: 10% 0;
margin: 0 0;
padding: 0 0;
}

.author-info .avatar {
height: 36px;
margin: 0 1.5em 1.5em 0;
width: 36px;
height: 180px;
margin: 0 1.5em 0 0;
width: 180px;
}

.author-link:after {
Expand Down Expand Up @@ -4706,7 +4699,7 @@ p > video {
}

.social-navigation li {
width: 20%;
width: 25%;
}

.social-navigation a {
Expand Down Expand Up @@ -4958,9 +4951,9 @@ p > video {
}

.author-info .avatar {
height: 42px;
margin: 0 1.6471em 1.6471em 0;
width: 42px;
height: 180px;
margin: 0 1.6471em 0 0;
width: 180px;
}

.author-link:after {
Expand Down Expand Up @@ -5511,9 +5504,9 @@ p > video {
}

.author-info .avatar {
height: 56px;
margin: 0 1.6842em 1.6842em 0;
width: 56px;
height: 180px;
margin: 0 1.6842em 0 0;
width: 180px;
}

.author-link:after {
Expand Down
17 changes: 17 additions & 0 deletions spec/controllers/announcement_controller_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,23 @@ describe AnnouncementController do
expect(response.body.includes? a3.typename).to be_false
end
end

context "with user param" do
it "can find announcements by user login" do
user1 = user(login: "Superman").tap &.save
user2 = user(login: "Batman").tap &.save

a1 = announcement(user1, title: "Announcement1").tap &.save
a2 = announcement(user1, title: "Announcement2").tap &.save
a3 = announcement(user2, title: "Announcement3").tap &.save

get "/announcements", body: "user=#{user1.login}"

expect(response.body.includes? a1.title.to_s).to be_true
expect(response.body.includes? a2.title.to_s).to be_true
expect(response.body.includes? a3.title.to_s).to be_false
end
end
end

describe "GET show" do
Expand Down
39 changes: 39 additions & 0 deletions spec/controllers/user_controller_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require "./spec_helper"

describe UserController do
let(:user) { user(login: "UserControllerTest").tap &.save }

before do
Announcement.clear
User.clear
end

describe "GET #show" do
it "renders show template if user is found" do
get "/users/#{user.login}"
expect(response.status_code).to eq 200
expect(response.body.includes? user.login.not_nil!).to be_true
end

it "redirects to root if user is not found" do
get "/users/no-such-login"
expect(response.status_code).to eq 302
expect(response).to redirect_to "/"
end
end

describe "GET #me" do
it "renders user#show template if user is signed in" do
login_as user
get "/me"
expect(response.status_code).to eq 200
expect(response.body.includes? user.login.not_nil!).to be_true
end

it "redirects to root if user is not signed in" do
get "/me"
expect(response.status_code).to eq 302
expect(response).to redirect_to "/"
end
end
end
51 changes: 51 additions & 0 deletions spec/models/user_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ describe User do
it "requires provider not to be blank" do
expect(user(provider: "").valid?).to be_false
end

it "allows role to be blank" do
expect(user(role: "").valid?).to be_true
end
end

describe "#admin?" do
Expand Down Expand Up @@ -51,4 +55,51 @@ describe User do
expect(user(role: "admin").can_update? announcement).to be_true
end
end

describe "#avatar_url" do
it "returns url to user's avatar" do
expect(user.avatar_url).not_to be_nil
end
end

describe "#github_url" do
it "returns url to user's github profile" do
expect(user.github_url).not_to be_nil
end
end

describe "#total_announcements" do
before do
Announcement.clear
User.clear
end

let(:user) { user(login: "john").tap &.save }

it "returns number of announcements that belong to user" do
an = announcement(user: user).tap &.save
expect(user.total_announcements).to eq 1
end

it "returns 0 if there are no announcements that belong to user" do
expect(user.total_announcements).to eq 0
end
end

describe "#find_by_login" do
before do
Announcement.clear
User.clear
end

let(:user) { user(login: "john").tap &.save }

it "can find user by it's login" do
expect(User.find_by_login(user.login)).not_to be_nil
end

it "returns nil if such user does not exist" do
expect(User.find_by_login("bad-login")).to be_nil
end
end
end
10 changes: 7 additions & 3 deletions src/controllers/announcement_controller.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ class AnnouncementController < ApplicationController
PER_PAGE = 10

def index
query, current_page, type = query_param, page_param, type_param
total_pages = Announcement.count(query, type).fdiv(PER_PAGE).ceil.to_i
query, current_page, type, user_id = query_param, page_param, type_param, user_id_param
total_pages = Announcement.count(query, type, user_id).fdiv(PER_PAGE).ceil.to_i

announcements = Announcement.search(query, per_page: PER_PAGE, page: current_page, type: type)
announcements = Announcement.search(query, per_page: PER_PAGE, page: current_page, type: type, user_id: user_id)
render("index.slang")
end

Expand Down Expand Up @@ -102,4 +102,8 @@ class AnnouncementController < ApplicationController
private def type_param
(type = params["type"]?) && Announcement::TYPES.key(type) { -1 }
end

private def user_id_param
User.find_by_login(params["user"]?).try(&.id)
end
end
17 changes: 17 additions & 0 deletions src/controllers/user_controller.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class UserController < ApplicationController
def show
if user = User.find_by_login params["login"]
render "show.slang"
else
redirect_to "/"
end
end

def me
if user = current_user
render "show.slang"
else
redirect_to "/"
end
end
end

0 comments on commit a5ae689

Please sign in to comment.