--- a/project.clj Thu Sep 29 23:28:26 2011 -0400
+++ b/project.clj Mon Oct 03 19:52:37 2011 -0400
@@ -2,7 +2,8 @@
:description "FIXME: write this!"
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/clojure-contrib "1.2.0"]
- [noir "1.1.0"]
+ [noir "1.2.0"]
+ [postmark "1.0.0"]
[cheshire "2.0.2"]
[clj-http "0.2.1"]
[aleph "0.2.0-beta2"]]
--- a/resources/public/css/style.less Thu Sep 29 23:28:26 2011 -0400
+++ b/resources/public/css/style.less Mon Oct 03 19:52:37 2011 -0400
@@ -81,8 +81,8 @@
}
section.message {
border-bottom: 2px solid #ddd;
- margin-top: -12px;
- margin-bottom: 32px;
+ margin-top: -26px;
+ margin-bottom: 44px;
}
.page-title {
position: relative;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/newseasons/middleware/session/redis.clj Mon Oct 03 19:52:37 2011 -0400
@@ -0,0 +1,29 @@
+(ns newseasons.middleware.session.redis
+ "Redis session storage."
+ (:use ring.middleware.session.store)
+ (:use [cheshire.core :only (generate-string parse-string)])
+ (:use [aleph.redis :only (redis-client)])
+ (:import java.util.UUID))
+
+
+(deftype RedisStore [r]
+ SessionStore
+
+ (read-session [_ key]
+ (parse-string (or @(r [:get key]) "{}")))
+
+ (write-session [_ key data]
+ (let [key (or key (str (UUID/randomUUID)))]
+ @(r [:set key (generate-string data)])
+ (r [:expire key (* 60 60 24 30)])
+ key))
+
+ (delete-session [_ key]
+ @(r [:del key])
+ nil))
+
+(defn redis-store
+ "Creates a Redis-backed storage engine."
+ [host password] (RedisStore. (redis-client {:host host :password password})))
+
+
--- a/src/newseasons/models/shows.clj Thu Sep 29 23:28:26 2011 -0400
+++ b/src/newseasons/models/shows.clj Mon Oct 03 19:52:37 2011 -0400
@@ -10,6 +10,7 @@
; Shows are stored as hashes.
;
; shows:<iTunes artist ID> = {
+; id: show id
; title: show tile
; image: url to show's image
; url: url to view the show on iTunes
@@ -18,7 +19,15 @@
; Code ------------------------------------------------------------------------
(defn show-get [id]
- (apply hash-map @(r [:hgetall (key-show id)])))
+ (let [show (apply hash-map @(r [:hgetall (key-show id)]))]
+ (when (not (empty? show))
+ {:id (show "id")
+ :title (show "title")
+ :image (show "image")
+ :url (show "url")})))
+
+(defn show-set-id! [id new-id]
+ @(r [:hset (key-show id) "id" new-id]))
(defn show-set-title! [id new-title]
@(r [:hset (key-show id) "title" new-title]))
--- a/src/newseasons/models/users.clj Thu Sep 29 23:28:26 2011 -0400
+++ b/src/newseasons/models/users.clj Mon Oct 03 19:52:37 2011 -0400
@@ -1,5 +1,6 @@
(ns newseasons.models.users
(:use newseasons.models.keys)
+ (:use [newseasons.models.shows :only (show-get)])
(:require [noir.util.crypt :as crypt])
(:use [aleph.redis :only (redis-client)]))
@@ -25,7 +26,7 @@
(let [user (apply hash-map @(r [:hgetall (key-user email)]))]
(when (not (empty? user))
(merge {:email (user "email") :pass (user "pass")}
- {:shows @(r [:smembers (key-user-shows email)])}))))
+ {:shows (map show-get @(r [:smembers (key-user-shows email)]))}))))
(defn user-set-email! [email new-email]
@(r [:hset (key-user email) "email" new-email]))
--- a/src/newseasons/server.clj Thu Sep 29 23:28:26 2011 -0400
+++ b/src/newseasons/server.clj Mon Oct 03 19:52:37 2011 -0400
@@ -1,4 +1,5 @@
(ns newseasons.server
+ (:use [newseasons.middleware.session.redis :only (redis-store)])
(:require [noir.server :as server]))
(server/load-views "src/newseasons/views/")
@@ -7,5 +8,6 @@
(let [mode (keyword (or (first m) :dev))
port (Integer. (get (System/getenv) "PORT" "8000"))]
(server/start port {:mode mode
- :ns 'newseasons})))
+ :ns 'newseasons
+ :session-store (redis-store "localhost" "devpass")})))
--- a/src/newseasons/templates/main.clj Thu Sep 29 23:28:26 2011 -0400
+++ b/src/newseasons/templates/main.clj Mon Oct 03 19:52:37 2011 -0400
@@ -14,6 +14,12 @@
(list [:label {:for (str "id_" field-name)} label]
(fieldfn field-name)))
+(defn pluralize
+ ([coll] (pluralize coll "s"))
+ ([coll plural-suffix] (if (= 1 (count coll))
+ ""
+ plural-suffix)))
+
; Layout ----------------------------------------------------------------------
(defpartial base [& content]
@@ -67,8 +73,17 @@
[:p "New Seasons will notify you when your favorite TV "
"shows have new seasons on iTunes. That's it."]]))
-(defpartial user [email]
- (inner (str "Hello, " email)
+
+(defpartial user-show [show]
+ [:li.show.group
+ [:img {:src (show :image)}]
+ [:h3 (link-to (show :url) (show :title))]
+ (form-to [:post "/rem"]
+ [:input {:type "hidden" :name "artist-id" :value (show :id)}]
+ (submit-button "Remove"))])
+
+(defpartial user [user]
+ (inner (str "Hello, " (:email user))
[:div.eight.columns
[:form {:action "/search"}
(field text-field
@@ -76,7 +91,17 @@
"Which show do you want to keep track of?")
(submit-button "Search")]]
[:div.eight.columns
- [:p "You're not currently waiting for any shows."]]))
+ (let [shows (:shows user)]
+ (if (empty? shows)
+ [:p "You're not currently watching any shows."]
+ (list
+ [:p
+ "You're watching "
+ (count shows)
+ " show"
+ (pluralize shows)
+ "."]
+ [:ul (map user-show shows)])))]))
(defpartial result [r]
--- a/src/newseasons/views/main.clj Thu Sep 29 23:28:26 2011 -0400
+++ b/src/newseasons/views/main.clj Mon Oct 03 19:52:37 2011 -0400
@@ -117,12 +117,14 @@
(login-required
(if (not= email (sess/get :email))
(force-login)
- (t/user email))))
+ (let [user (users/user-get email)]
+ (t/user user)))))
; Search ----------------------------------------------------------------------
(defn store-show [show]
(let [id (show "artistId")]
+ (shows/show-set-id! id id)
(shows/show-set-title! id (show "artistName"))
(shows/show-set-image! id (show "artworkUrl100"))
(shows/show-set-url! id (show "artistViewUrl"))))
@@ -146,6 +148,14 @@
(resp/redirect "/")))
+; Remove ----------------------------------------------------------------------
+(defpage [:post "/rem"] {:keys [artist-id]}
+ (login-required
+ (users/user-rem-show! (sess/get :email) artist-id)
+ (flash! "Removed a show from your list.")
+ (resp/redirect "/")))
+
+
; Change Password -------------------------------------------------------------
(defpage [:get "/password"] []
(login-required