Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show user details. #416

Merged
merged 14 commits into from
Sep 28, 2016
19 changes: 19 additions & 0 deletions app/controllers/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Ember from 'ember';
import PaginationMixin from '../mixins/pagination';

const { computed } = Ember;

// TODO: reduce duplication with controllers/crates

export default Ember.Controller.extend(PaginationMixin, {
queryParams: ['page', 'per_page', 'sort'],
page: '1',
per_page: 10,
sort: 'alpha',

totalItems: computed.readOnly('model.crates.meta.total'),

currentSortBy: computed('sort', function() {
return (this.get('sort') === 'downloads') ? 'Downloads' : 'Alphabetical';
}),
});
1 change: 1 addition & 0 deletions app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Router.map(function() {
this.route('crates');
this.route('following');
});
this.route('user', { path: '/users/:user_id' });
this.route('install');
this.route('search');
this.route('dashboard');
Expand Down
37 changes: 37 additions & 0 deletions app/routes/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Ember from 'ember';

export default Ember.Route.extend({
queryParams: {
page: { refreshModel: true },
sort: { refreshModel: true },
},
data: {},

setupController(controller, model) {
this._super(controller, model);

controller.set('fetchingFeed', true);
controller.set('crates', this.get('data.crates'));
},

model(params) {
const { user_id } = params;
return this.store.find('user', user_id).then(
(user) => {
params.user_id = user.get('id');
return Ember.RSVP.hash({
crates: this.store.query('crate', params),
user
});
},
(e) => {
if (e.errors.any(e => e.detail === 'Not Found')) {
this
.controllerFor('application')
.set('nextFlashError', `User '${params.user_id}' does not exist`);
return this.replaceWith('index');
}
}
);
},
});
5 changes: 4 additions & 1 deletion app/styles/crate.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
@include display-flex;
@include align-items(center);
}
h1 { padding-left: 10px; }
h1 {
padding-left: 10px;
padding-right: 10px;
}
h2 { color: $main-color-light; padding-left: 10px; }
.right {
@include flex(2);
Expand Down
6 changes: 3 additions & 3 deletions app/templates/crate/version.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@
<ul class='owners'>
{{#each crate.owners as |owner|}}
<li>
{{#user-link user=owner}}
{{user-avatar user=owner size='medium-small'}}
{{/user-link}}
{{#link-to 'user' owner.login}}
{{user-avatar user=owner size='medium-small'}}
{{/link-to}}
</li>
{{/each}}
</ul>
Expand Down
67 changes: 67 additions & 0 deletions app/templates/user.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<div id='crates-heading'>
{{user-avatar user=model.user size='medium'}}
<h1>
{{ model.user.login }}
</h1>
{{#user-link user=model.user}}
<img alt="GitHub profile" title="GitHub profile" src="/assets/GitHub-Mark-32px.png"/>
{{/user-link}}
</div>

<div id='user-profile'>
<div class='info'>
{{! TODO: reduce duplication with templates/crates.hbs }}

<div id='results'>
<div class='nav'>
<span class='amt small'>
Displaying
<span class='cur'>{{ currentPageStart }}-{{ currentPageEnd }}</span>
of <span class='total'>{{ totalItems }}</span> total results
</span>
</div>

<div class='sort'>
<span class='small'>Sort by</span>
{{#rl-dropdown-container class="dropdown-container"}}
{{#rl-dropdown-toggle tagName="a" class="dropdown"}}
<img class="sort" src="/assets/sort.png"/>
{{ currentSortBy }}
<span class='arrow'></span>
{{/rl-dropdown-toggle}}

{{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}}
<li>
{{#link-to (query-params sort="alpha")}}
Alphabetical
{{/link-to}}
</li>
<li>
{{#link-to (query-params sort="downloads")}}
Downloads
{{/link-to}}
</li>
{{/rl-dropdown}}
{{/rl-dropdown-container}}
</div>
</div>

<div id='crates' class='white-rows'>
{{#each model.crates as |crate|}}
{{crate-row crate=crate}}
{{/each}}
</div>

<div class='pagination'>
{{#link-to (query-params page=prevPage) class="prev" rel="prev" title="previous page"}}
<img class="left-pag" src="/assets/left-pag.png"/>
{{/link-to}}
{{#each pages as |page|}}
{{#link-to (query-params page=page)}}{{ page }}{{/link-to}}
{{/each}}
{{#link-to (query-params page=nextPage) class="next" rel="next" title="next page"}}
<img class="right-pag" src="/assets/right-pag.png"/>
{{/link-to}}
</div>
</div>
</div>
Binary file added public/assets/GitHub-Mark-32px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub fn middleware(app: Arc<App>) -> MiddlewareBuilder {
api_router.get("/versions/:version_id", C(version::show));
api_router.get("/keywords", C(keyword::index));
api_router.get("/keywords/:keyword_id", C(keyword::show));
api_router.get("/users/:user_id", C(user::show));
let api_router = Arc::new(R404(api_router));

let mut router = RouteBuilder::new();
Expand Down
15 changes: 15 additions & 0 deletions src/user/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::collections::HashMap;

use conduit::{Request, Response};
use conduit_cookie::{RequestSession};
use conduit_router::RequestParams;
use pg::GenericConnection;
use pg::rows::Row;
use pg::types::Slice;
Expand Down Expand Up @@ -288,6 +289,20 @@ pub fn me(req: &mut Request) -> CargoResult<Response> {
Ok(req.json(&R{ user: user.clone().encodable(), api_token: token }))
}

/// Handles the `GET /users/:user_id` route.
pub fn show(req: &mut Request) -> CargoResult<Response> {
let name = &req.params()["user_id"];
let conn = try!(req.tx());
let user = try!(User::find_by_login(conn, &name));

#[derive(RustcEncodable)]
struct R {
user: EncodableUser,
}
Ok(req.json(&R{ user: user.clone().encodable() }))
}


/// Handles the `GET /me/updates` route.
pub fn updates(req: &mut Request) -> CargoResult<Response> {
let user = try!(req.user());
Expand Down