From c5856a0d115cb46760a359d45a3a734fc1d51b52 Mon Sep 17 00:00:00 2001 From: raylu Date: Sun, 7 Aug 2011 18:48:51 -0700 Subject: move (reorder) and move updates --- Makefile | 4 +- db.go | 60 ++++++++++++++++++++++++++++++ main.go | 101 +++++++++++++++++++++++++++++++++++--------------- static/base.css | 25 +++++++++++-- static/down-arrow.png | Bin 0 -> 540 bytes static/remove.png | Bin 0 -> 505 bytes static/script.js | 58 ++++++++++++++++++++++++++--- static/up-arrow.png | Bin 0 -> 468 bytes updates.go | 10 +++-- 9 files changed, 213 insertions(+), 45 deletions(-) create mode 100644 db.go create mode 100644 static/down-arrow.png create mode 100644 static/remove.png create mode 100644 static/up-arrow.png diff --git a/Makefile b/Makefile index b3a5966..94e6269 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: aa -main.6: main.go updates.go - 6g main.go updates.go +main.6: main.go db.go updates.go + 6g main.go db.go updates.go aa: main.6 6l -o aa main.6 diff --git a/db.go b/db.go new file mode 100644 index 0000000..f161c54 --- /dev/null +++ b/db.go @@ -0,0 +1,60 @@ +package main + +import ( + "os" +) + +func queryInt(sql string, params ...interface{}) (int, os.Error) { + query, err := db.Prepare(sql) + if err != nil { + return 0, err + } + err = query.BindParams(params...) + if err != nil { + return 0, err + } + err = query.Execute() + if err != nil { + return 0, err + } + var result int + query.BindResult(&result) + eof, err := query.Fetch() + if err != nil { + return 0, err + } else if eof { + return 0, os.EOF + } + err = query.FreeResult() + if err != nil { + return 0, err + } + return result, nil +} + +// given an id ('abcd1234'), return the pid (1) +func getpid(id string) int { + query, err := db.Prepare("SELECT `pid` FROM `playlist` WHERE `id` = ?") + if err != nil { + return -1 + } + err = query.BindParams(id) + if err != nil { + return -1 + } + err = query.Execute() + if err != nil { + return -1 + } + var pid int + query.BindResult(&pid) + _, err = query.Fetch() + if err != nil { + return -1 + } + err = query.FreeResult() + if err != nil { + return -1 + } + return pid +} diff --git a/main.go b/main.go index 29724b2..c5023f6 100644 --- a/main.go +++ b/main.go @@ -24,33 +24,6 @@ var templates map[string]*template.Template const debug = true var db *mysql.Client -// given an id ('abcd1234'), return the pid (1) -func getpid(id string) int { - query, err := db.Prepare("SELECT `pid` FROM `playlist` WHERE `id` = ?;") - if err != nil { - return -1 - } - err = query.BindParams(id) - if err != nil { - return -1 - } - err = query.Execute() - if err != nil { - return -1 - } - var pid int - query.BindResult(&pid) - _, err = query.Fetch() - if err != nil { - return -1 - } - err = query.FreeResult() - if err != nil { - return -1 - } - return pid -} - func home(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "path is %s", r.URL.Path[1:]) } @@ -91,7 +64,7 @@ func add(w http.ResponseWriter, r *http.Request) { return } - sql :="INSERT INTO `song` (`pid`,`yid`,`title`,`user`) VALUES(%d,'%s','%s','%s')" + sql := "INSERT INTO `song` (`pid`,`yid`,`title`,`user`) VALUES(%d,'%s','%s','%s')" sql = fmt.Sprintf(sql, pid, db.Escape(q.Get("yid")), db.Escape(q.Get("title")), @@ -115,7 +88,7 @@ func remove(w http.ResponseWriter, r *http.Request) { return } - sql :="DELETE FROM `song` WHERE `pid` = %d AND yid = '%s'" + sql := "DELETE FROM `song` WHERE `pid` = %d AND yid = '%s'" sql = fmt.Sprintf(sql, pid, q.Get("yid")) err := db.Query(sql) if err != nil { @@ -127,11 +100,78 @@ func remove(w http.ResponseWriter, r *http.Request) { addUpdate(pid, removeAction, &Song{Yid: q.Get("yid")}) } +func move(w http.ResponseWriter, r *http.Request) { + q := r.URL.Query() + pid := getpid(q.Get("pid")) + if pid == -1 { + http.Error(w, "invalid pid", http.StatusInternalServerError) + return + } + + direction, err := strconv.Atoui(q.Get("direction")) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + + err = db.Start() + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + + order, err := queryInt("SELECT `order` FROM `song` WHERE `yid` = ? AND `pid` = ?", + q.Get("yid"), pid) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + newOrder := order + if direction == moveUpAction && order > 0 { + newOrder-- + } else if direction == moveDownAction { + newOrder++ + } else { + http.Error(w, "invalid direction or cannot move up", http.StatusInternalServerError) + return + } + + sql := "UPDATE `song` SET `order` = %d WHERE `order` = %d AND pid = %d" + sql = fmt.Sprintf(sql, order, newOrder, pid) + err = db.Query(sql) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } else if db.AffectedRows != 1 { + db.Rollback() + http.Error(w, "invalid direction for this song", http.StatusInternalServerError) + return + } + // there are now two songs with that order, so also check yid + sql = "UPDATE `song` SET `order` = %d WHERE `order` = %d AND pid = %d AND yid = '%s'" + sql = fmt.Sprintf(sql, newOrder, order, pid, q.Get("yid")) + err = db.Query(sql) + if err != nil { + db.Rollback() + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + + err = db.Commit() + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + + w.Write([]byte("1")) + addUpdate(pid, direction, &Song{Yid: q.Get("yid")}) +} + func poll(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() timestamp := q.Get("timestamp") if timestamp == "0" { - query, err := db.Prepare("SELECT `yid`,`title`,`user` FROM `playlist` JOIN `song` WHERE `id` = ?;") + query, err := db.Prepare("SELECT `yid`,`title`,`user` FROM `playlist` JOIN `song` WHERE `id` = ? ORDER BY `order` ASC") if err != nil { http.Error(w, err.String(), http.StatusInternalServerError) return @@ -227,6 +267,7 @@ func main() { http.HandleFunc("/p/", playlist) http.HandleFunc("/add/", add) http.HandleFunc("/remove/", remove) + http.HandleFunc("/move/", move) http.HandleFunc("/poll/", poll) err = http.ListenAndServe("localhost:8000", nil) if err != nil { diff --git a/static/base.css b/static/base.css index fb01a40..438e4c1 100644 --- a/static/base.css +++ b/static/base.css @@ -136,14 +136,31 @@ section.song div.info { } section.song div.user { float: right; - margin-right: 8px; + margin-right: 20px; } section.song div.remove { position: absolute; top: 0; right: 5px; - font-weight: bold; - cursor: pointer; +} +section.song div.remove img { + opacity: 0.6; +} +section.song div.remove img:hover { + opacity: 1.0; +} +section.song div.reorder { + position: absolute; + bottom: 0; + right: 5px; +} +section.song div.reorder img { + display: block; + margin-bottom: 5px; + opacity: 0.6; +} +section.song div.reorder img:hover { + opacity: 1.0; } section.song div.thumb { float: left; @@ -156,7 +173,7 @@ section.song div.thumb img { } section.song canvas, section.song > img { position: relative; - left: 10px; + left: 5px; } section.song > img[src$='pause.png'] { display: none; diff --git a/static/down-arrow.png b/static/down-arrow.png new file mode 100644 index 0000000..00c106d Binary files /dev/null and b/static/down-arrow.png differ diff --git a/static/remove.png b/static/remove.png new file mode 100644 index 0000000..a033c4e Binary files /dev/null and b/static/remove.png differ diff --git a/static/script.js b/static/script.js index 3be5775..8687b0e 100644 --- a/static/script.js +++ b/static/script.js @@ -14,6 +14,10 @@ $(document).ready(function () { case 1: drawRemove(update.yid); break; + case 2: + case 3: + drawMove(update.yid, update.action); + break; } } } @@ -167,12 +171,11 @@ function search(query) { } function add(id, title) { - var user = $('#user').val(); params = { pid: pid, yid: id, title: title, - user: user + user: $('#user').val() } $.getJSON('/add/', params); } @@ -187,7 +190,19 @@ function drawAdd(s) { ' + s.title + '\ \
' + s.user + '
\ -
×
\ +
\ + \ + remove\ + \ +
\ +
\ + \ + up\ + \ + \ + down\ + \ +
\ \
\ Play\ @@ -201,7 +216,6 @@ function drawAdd(s) { } function remove(id) { - var user = $('#user').val(); params = { pid: pid, yid: id, @@ -211,8 +225,42 @@ function remove(id) { function drawRemove(id) { var element = $('#' + id); + stop(id); element.slideUp(100, function () { - stop(id); element.remove(); }); } + +function move(id, dir) { + params = { + pid: pid, + yid: id, + direction: dir // see updates.go:moveUpAction + } + $.getJSON('/move/', params); +} + +function drawMove(id, dir) { + var element1 = document.getElementById(id); + if (dir == 2) { //up + var element2 = element1.previousElementSibling; + if (!element2) return; + element1 = $('#' + id); + element2 = $('#' + element2.id); + element1.fadeOut(200, function () { + element1.detach(); + element2.before(element1); + element1.fadeIn(200); + }); + } else if (dir == 3) { //down + var element2 = element1.nextElementSibling; + if (!element2) return; + element1 = $('#' + id); + element2 = $('#' + element2.id); + element1.fadeOut(200, function () { + element1.detach(); + element2.after(element1); + element1.fadeIn(200); + }); + } +} diff --git a/static/up-arrow.png b/static/up-arrow.png new file mode 100644 index 0000000..29ca702 Binary files /dev/null and b/static/up-arrow.png differ diff --git a/updates.go b/updates.go index c36bda8..33f12a9 100644 --- a/updates.go +++ b/updates.go @@ -5,12 +5,14 @@ import ( ) const ( - addAction = 0 - removeAction = 1 + addAction = 0 + removeAction = 1 + moveUpAction = 2 + moveDownAction = 3 ) type Update struct { Song *Song - Action uint8 + Action uint Timestamp int64 Next *Update } @@ -22,7 +24,7 @@ func init() { tailUpdates = make(map[int]*Update) } -func addUpdate(pid int, action uint8, song *Song) { +func addUpdate(pid int, action uint, song *Song) { update := new(Update) update.Song = song update.Action = action -- cgit v1.2.3