--- a/puppet/base.pp Thu Sep 29 00:09:42 2011 -0400
+++ b/puppet/base.pp Thu Sep 29 23:10:14 2011 -0400
@@ -17,7 +17,7 @@
class { "leiningen": }
class { "environ": }
- $niceties = ["htop", "dtach", "sudo", "vim", "curl"]
+ $niceties = ["htop", "dtach", "sudo", "vim", "rlwrap"]
package { $niceties: ensure => "installed" }
}
--- a/resources/public/css/style.less Thu Sep 29 00:09:42 2011 -0400
+++ b/resources/public/css/style.less Thu Sep 29 23:10:14 2011 -0400
@@ -1,3 +1,59 @@
+// Mixins
+.border-radius(@radius: 5px) {
+ -webkit-background-clip: padding-box;
+ -webkit-border-radius: @radius;
+ -moz-background-clip: padding-box;
+ -moz-border-radius: @radius;
+ border-radius: @radius;
+ background-clip: padding-box;
+}
+.box-shadow(@horizontal: 0px, @vertical: 1px, @blur: 2px, @color: #CCC) {
+ -webkit-box-shadow: @horizontal @vertical @blur @color;
+ -moz-box-shadow: @horizontal @vertical @blur @color;
+ box-shadow: @horizontal @vertical @blur @color;
+}
+.inset-box-shadow(@horizontal: 0px, @vertical: 1px, @blur: 2px, @color: #CCC) {
+ -webkit-box-shadow: inset @horizontal @vertical @blur @color;
+ -moz-box-shadow: inset @horizontal @vertical @blur @color;
+ box-shadow: inset @horizontal @vertical @blur @color;
+}
+.multi-color-border(@top, @sides, @bottom) {
+ border-top: 1px solid @top;
+ border-left: 1px solid @sides;
+ border-right: 1px solid @sides;
+ border-bottom: 1px solid @bottom;
+}
+.multi-border-radius(@topLeft: 5px, @topRight: 5px, @bottomRight: 5px, @bottomLeft: 5px) {
+ -webkit-border-top-left-radius: @topLeft;
+ -webkit-border-top-right-radius: @topRight;
+ -webkit-border-bottom-right-radius: @bottomRight;
+ -webkit-border-bottom-left-radius: @bottomLeft;
+ -moz-border-radius-topleft: @topLeft;
+ -moz-border-radius-topright: @topRight;
+ -moz-border-radius-bottomright: @bottomRight;
+ -moz-border-radius-bottomleft: @bottomLeft;
+ border-top-left-radius: @topLeft;
+ border-top-right-radius: @topRight;
+ border-bottom-right-radius: @bottomRight;
+ border-bottom-left-radius: @bottomLeft;
+}
+.vertical-gradient(@start: #000, @stop: #FFF) {
+ background: (@start + @stop) / 2;
+ background: -webkit-gradient(linear, left top, left bottom, from(@start), to(@stop));
+ background: -moz-linear-gradient(center top, @start 0%, @stop 100%);
+ background: -moz-gradient(center top, @start 0%, @stop 100%);
+}
+
+// Utils
+.group:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+}
+
+// Layout
header {
text-align: center;
margin-top: 24px;
@@ -46,3 +102,15 @@
}
}
}
+li.show {
+ margin-top: 12px;
+
+ img {
+ float: left;
+ margin-right: 20px;
+ padding: 4px;
+ border: 1px solid #ccc;
+ width: 60px;
+ height: 60px;
+ }
+}
--- a/src/newseasons/models/shows.clj Thu Sep 29 00:09:42 2011 -0400
+++ b/src/newseasons/models/shows.clj Thu Sep 29 23:10:14 2011 -0400
@@ -0,0 +1,33 @@
+(ns newseasons.models.shows
+ (:use [aleph.redis :only (redis-client)]))
+
+
+(def r (redis-client {:host "localhost" :password "devpass"}))
+
+; "Schema" --------------------------------------------------------------------
+;
+; Shows are stored as hashes.
+;
+; shows:<iTunes artist ID> = {
+; title: show tile
+; image: url to show's image
+; url: url to view the show on iTunes
+; }
+
+; Code ------------------------------------------------------------------------
+(defn- show-key [id]
+ (str "shows:" id))
+
+
+(defn show-get [id]
+ (apply hash-map @(r [:hgetall (show-key id)])))
+
+(defn show-set-title! [id new-title]
+ @(r [:hset (show-key id) "title" new-title]))
+
+(defn show-set-image! [id new-image]
+ @(r [:hset (show-key id) "image" new-image]))
+
+(defn show-set-url! [id new-url]
+ @(r [:hset (show-key id) "url" new-url]))
+
--- a/src/newseasons/templates/main.clj Thu Sep 29 00:09:42 2011 -0400
+++ b/src/newseasons/templates/main.clj Thu Sep 29 23:10:14 2011 -0400
@@ -80,7 +80,8 @@
(defpartial result [r]
- [:li
+ [:li.show.group
+ [:img {:src (r "artworkUrl100")}]
[:h3 (link-to (r "artistViewUrl") (r "artistName"))]
(form-to [:post "/add"]
[:input {:type "hidden" :name "artist-id" :value (r "artistId")}]
--- a/src/newseasons/views/main.clj Thu Sep 29 00:09:42 2011 -0400
+++ b/src/newseasons/views/main.clj Thu Sep 29 23:10:14 2011 -0400
@@ -6,6 +6,7 @@
(:require [clj-http.client :as client])
(:use [cheshire.core :only (parse-string)])
(:require [newseasons.templates.main :as t])
+ (:require [newseasons.models.shows :as shows])
(:require [newseasons.models.users :as users]))
@@ -21,6 +22,34 @@
nil)
+; Utils -----------------------------------------------------------------------
+(defn unique-by
+ "Turn a sequence of maps into a new sequence with duplicated removed, with
+ uniqueness determined by the given keys.
+
+ Ex:
+
+ (def a {:foo 1 :bar 1 :baz 1})
+ (def b {:foo 1 :bar 1 :baz 2})
+ (def c {:foo 1 :bar 2 :baz 3})
+
+ (unique-by [a b c] :foo)
+ ;=> [c]
+ (unique-by [a b c] :foo :bar)
+ ;=> [b c]
+ (unique-by [a b c] :baz)
+ ;=> [a b c]
+ "
+ [coll & ks]
+ (vals (reduce merge {} (map #(vector (select-keys % ks) %) coll))))
+
+(defn unique-shows [seasons]
+ (unique-by seasons "artistId"))
+
+(defn sort-maps-by [coll k]
+ (sort #(compare (%1 k) (%2 k)) coll))
+
+
; iTunes ----------------------------------------------------------------------
(defn itunes-search [params]
((parse-string (:body (client/get "http://itunes.apple.com/search"
@@ -92,13 +121,21 @@
; Search ----------------------------------------------------------------------
+(defn store-show [show]
+ (let [id (show "artistId")]
+ (shows/show-set-title! id (show "artistName"))
+ (shows/show-set-image! id (show "artworkUrl100"))
+ (shows/show-set-url! id (show "artistViewUrl"))))
+
+(defn store-shows [seasons]
+ (dorun (map store-show seasons)))
+
+
(defpage [:get "/search"] {:keys [query]}
(login-required
- ; TODO: Images.
- (let [results (itunes-search-show query)
- artists (distinct (map #(select-keys % ["artistName" "artistId" "artistViewUrl"])
- results))]
- (t/search query artists))))
+ (let [results (unique-shows (itunes-search-show query))]
+ (store-shows (sort-maps-by results "releaseDate"))
+ (t/search query results))))
; Add -------------------------------------------------------------------------