Skip to content

Commit 29a1dcd

Browse files
authored
Merge pull request #517 from integer32llc/show-keywords-and-categories
Show most popular keywords and categories on the home page
2 parents 8c00e88 + 59372e1 commit 29a1dcd

File tree

7 files changed

+102
-42
lines changed

7 files changed

+102
-42
lines changed

app/styles/home.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125

126126
#home-crates {
127127
@include flex-wrap(wrap);
128-
@include justify-content(center);
128+
@include justify-content(left);
129129

130130
> div {
131131
margin: 0;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<ul>
2+
{{#each categories as |category|}}
3+
<li>
4+
{{#link-to 'category' category.slug class='name'}}
5+
<span>{{ category.category }} ({{ format-num category.crates_cnt }})</span>
6+
<img class="right-arrow" src="/assets/right-arrow.png"/>
7+
{{/link-to}}
8+
</li>
9+
{{/each}}
10+
</ul>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<ul>
2+
{{#each keywords as |keyword|}}
3+
<li>
4+
{{#link-to 'keyword' keyword class='name'}}
5+
<span>{{ keyword.id }} ({{ format-num keyword.crates_cnt }})</span>
6+
<img class="right-arrow" src="/assets/right-arrow.png"/>
7+
{{/link-to}}
8+
</li>
9+
{{/each}}
10+
</ul>

app/templates/index.hbs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,12 @@
4848
<h2>Just Updated</h2>
4949
{{crate-list crates=model.just_updated}}
5050
</div>
51+
<div id='keywords'>
52+
<h2>Popular Keywords {{#link-to 'keywords'}}(see all){{/link-to}}</h2>
53+
{{keyword-list keywords=model.popular_keywords}}
54+
</div>
55+
<div id='categories'>
56+
<h2>Popular Categories {{#link-to 'categories'}}(see all){{/link-to}}</h2>
57+
{{category-list categories=model.popular_categories}}
58+
</div>
5159
</div>

src/category.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,40 @@ impl Category {
144144
Ok(rows.iter().next().unwrap().get("count"))
145145
}
146146

147+
pub fn toplevel(conn: &GenericConnection,
148+
sort: &str,
149+
limit: i64,
150+
offset: i64) -> CargoResult<Vec<Category>> {
151+
152+
let sort_sql = match sort {
153+
"crates" => "ORDER BY crates_cnt DESC",
154+
_ => "ORDER BY category ASC",
155+
};
156+
157+
// Collect all the top-level categories and sum up the crates_cnt of
158+
// the crates in all subcategories
159+
let stmt = try!(conn.prepare(&format!(
160+
"SELECT c.id, c.category, c.slug, c.description, c.created_at, \
161+
COALESCE (( \
162+
SELECT sum(c2.crates_cnt)::int \
163+
FROM categories as c2 \
164+
WHERE c2.slug = c.slug \
165+
OR c2.slug LIKE c.slug || '::%' \
166+
), 0) as crates_cnt \
167+
FROM categories as c \
168+
WHERE c.category NOT LIKE '%::%' {} \
169+
LIMIT $1 OFFSET $2",
170+
sort_sql
171+
)));
172+
173+
let categories: Vec<_> = try!(stmt.query(&[&limit, &offset]))
174+
.iter()
175+
.map(|row| Model::from_row(&row))
176+
.collect();
177+
178+
Ok(categories)
179+
}
180+
147181
pub fn subcategories(&self, conn: &GenericConnection)
148182
-> CargoResult<Vec<Category>> {
149183
let stmt = try!(conn.prepare("\
@@ -183,34 +217,9 @@ pub fn index(req: &mut Request) -> CargoResult<Response> {
183217
let (offset, limit) = try!(req.pagination(10, 100));
184218
let query = req.query();
185219
let sort = query.get("sort").map_or("alpha", String::as_str);
186-
let sort_sql = match sort {
187-
"crates" => "ORDER BY crates_cnt DESC",
188-
_ => "ORDER BY category ASC",
189-
};
190220

191-
// Collect all the top-level categories and sum up the crates_cnt of
192-
// the crates in all subcategories
193-
let stmt = try!(conn.prepare(&format!(
194-
"SELECT c.id, c.category, c.slug, c.description, c.created_at, \
195-
COALESCE (( \
196-
SELECT sum(c2.crates_cnt)::int \
197-
FROM categories as c2 \
198-
WHERE c2.slug = c.slug \
199-
OR c2.slug LIKE c.slug || '::%' \
200-
), 0) as crates_cnt \
201-
FROM categories as c \
202-
WHERE c.category NOT LIKE '%::%' {} \
203-
LIMIT $1 OFFSET $2",
204-
sort_sql
205-
)));
206-
207-
let categories: Vec<_> = try!(stmt.query(&[&limit, &offset]))
208-
.iter()
209-
.map(|row| {
210-
let category: Category = Model::from_row(&row);
211-
category.encodable()
212-
})
213-
.collect();
221+
let categories = try!(Category::toplevel(conn, sort, limit, offset));
222+
let categories = categories.into_iter().map(Category::encodable).collect();
214223

215224
// Query for the total count of categories
216225
let total = try!(Category::count_toplevel(conn));

src/keyword.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,26 @@ impl Keyword {
5454
}))))
5555
}
5656

57+
pub fn all(conn: &GenericConnection, sort: &str, limit: i64, offset: i64)
58+
-> CargoResult<Vec<Keyword>> {
59+
60+
let sort_sql = match sort {
61+
"crates" => "ORDER BY crates_cnt DESC",
62+
_ => "ORDER BY keyword ASC",
63+
};
64+
65+
let stmt = try!(conn.prepare(&format!("SELECT * FROM keywords {}
66+
LIMIT $1 OFFSET $2",
67+
sort_sql)));
68+
69+
let keywords: Vec<_> = try!(stmt.query(&[&limit, &offset]))
70+
.iter()
71+
.map(|row| Model::from_row(&row))
72+
.collect();
73+
74+
Ok(keywords)
75+
}
76+
5777
pub fn valid_name(name: &str) -> bool {
5878
if name.len() == 0 { return false }
5979
name.chars().next().unwrap().is_alphanumeric() &&
@@ -131,20 +151,9 @@ pub fn index(req: &mut Request) -> CargoResult<Response> {
131151
let (offset, limit) = try!(req.pagination(10, 100));
132152
let query = req.query();
133153
let sort = query.get("sort").map(|s| &s[..]).unwrap_or("alpha");
134-
let sort_sql = match sort {
135-
"crates" => "ORDER BY crates_cnt DESC",
136-
_ => "ORDER BY keyword ASC",
137-
};
138-
139-
// Collect all the keywords
140-
let stmt = try!(conn.prepare(&format!("SELECT * FROM keywords {}
141-
LIMIT $1 OFFSET $2",
142-
sort_sql)));
143-
let mut keywords = Vec::new();
144-
for row in try!(stmt.query(&[&limit, &offset])).iter() {
145-
let keyword: Keyword = Model::from_row(&row);
146-
keywords.push(keyword.encodable());
147-
}
154+
155+
let keywords = try!(Keyword::all(conn, sort, limit, offset));
156+
let keywords = keywords.into_iter().map(Keyword::encodable).collect();
148157

149158
// Query for the total count of keywords
150159
let total = try!(Keyword::count(conn));

src/krate.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,20 +649,34 @@ pub fn summary(req: &mut Request) -> CargoResult<Response> {
649649
let most_downloaded = try!(tx.prepare("SELECT * FROM crates \
650650
ORDER BY downloads DESC LIMIT 10"));
651651

652+
let popular_keywords = try!(Keyword::all(tx, "crates", 10, 0));
653+
let popular_keywords = popular_keywords.into_iter()
654+
.map(Keyword::encodable)
655+
.collect();
656+
657+
let popular_categories = try!(Category::toplevel(tx, "crates", 10, 0));
658+
let popular_categories = popular_categories.into_iter()
659+
.map(Category::encodable)
660+
.collect();
661+
652662
#[derive(RustcEncodable)]
653663
struct R {
654664
num_downloads: i64,
655665
num_crates: i64,
656666
new_crates: Vec<EncodableCrate>,
657667
most_downloaded: Vec<EncodableCrate>,
658668
just_updated: Vec<EncodableCrate>,
669+
popular_keywords: Vec<EncodableKeyword>,
670+
popular_categories: Vec<EncodableCategory>,
659671
}
660672
Ok(req.json(&R {
661673
num_downloads: num_downloads,
662674
num_crates: num_crates,
663675
new_crates: try!(to_crates(new_crates)),
664676
most_downloaded: try!(to_crates(most_downloaded)),
665677
just_updated: try!(to_crates(just_updated)),
678+
popular_keywords: popular_keywords,
679+
popular_categories: popular_categories,
666680
}))
667681
}
668682

0 commit comments

Comments
 (0)