diff --git a/Handler/Package.hs b/Handler/Package.hs index 31377ab..68c6f02 100644 --- a/Handler/Package.hs +++ b/Handler/Package.hs @@ -43,15 +43,27 @@ getPackageR pn = do return (packages, downloads, recentDownloads, nLikes, liked, metadata) - tags <- fmap (map (\(E.Value v) -> v)) - (runDB (E.selectDistinct + myTags <- + case muid of + Nothing -> return [] + Just uid -> + fmap (map (\(E.Value v) -> v)) + (runDB (E.select + (E.from (\t -> + do E.where_ (t ^. TagPackage E.==. E.val pn E.&&. + t ^. TagVoter E.==. E.val uid) + E.orderBy [E.asc (t ^. TagTag)] + return (t ^. TagTag))))) + tags <- fmap (map (\(E.Value v,E.Value count) -> (v,count::Int,any (==v) myTags))) + (runDB (E.select (E.from (\(t `E.LeftOuterJoin` bt) -> do E.on $ t E.^. TagTag E.==. bt E.^. BannedTagTag E.where_ $ (t ^. TagPackage E.==. E.val pn) E.&&. (E.isNothing $ E.just $ bt E.^. BannedTagTag) + E.groupBy (t ^. TagTag) E.orderBy [E.asc (t ^. TagTag)] - return (t ^. TagTag))))) + return (t ^. TagTag,E.count (t ^. TagTag)))))) let likeTitle = if liked then "You liked this!" @@ -191,3 +203,20 @@ postPackageTagR packageName = do slug <- mkSlugLen 1 20 tag void (runDB (P.insert (Tag packageName slug uid))) Nothing -> error "Need a slug" + +postPackageUntagR :: PackageName -> Handler () +postPackageUntagR packageName = + maybeAuthId >>= + \muid -> + case muid of + Nothing -> return () + Just uid -> + do mtag <- lookupPostParam "slug" + case mtag of + Just tag -> + do slug <- mkSlugLen 1 20 tag + void (runDB (P.deleteWhere + [TagPackage ==. packageName + ,TagTag ==. slug + ,TagVoter ==. uid])) + Nothing -> error "Need a slug" diff --git a/config/routes b/config/routes index 6607eaf..134e34c 100644 --- a/config/routes +++ b/config/routes @@ -30,6 +30,7 @@ /package/#PackageName/like PackageLikeR POST /package/#PackageName/unlike PackageUnlikeR POST /package/#PackageName/tag PackageTagR POST +/package/#PackageName/untag PackageUntagR POST /tags TagListR GET /tag/#Slug TagR GET /banned-tags BannedTagsR GET PUT diff --git a/templates/package.hamlet b/templates/package.hamlet index 41cde6b..3a1cf9a 100644 --- a/templates/package.hamlet +++ b/templates/package.hamlet @@ -21,10 +21,12 @@ $newline never $if null tags No tags yet. # - $forall tag <- tags + $forall (tag,count,tagged) <- tags - - #{tag} + + #{tag} # + + #{count} , #
diff --git a/templates/package.julius b/templates/package.julius index 001b283..947fff5 100644 --- a/templates/package.julius +++ b/templates/package.julius @@ -1,8 +1,35 @@ $(function(){ var loggedIn = $('.user-handle').length > 0; var tags = Object.create(null); + + function toggleClick(){ + if (!loggedIn) { + login(); + return false; + } + + var $this = $(this); + var normalized = $this.data('slug'); + var upvote = !$this.hasClass('tagged'); + $this.text($this.text() * 1 + (upvote? 1 : -1)); + $this.toggleClass('tagged'); + if (upvote) + $.ajax({ + method: 'POST', + url: '@{PackageTagR pn}', + data: {slug:normalized} + }); + else + $.ajax({ + method: 'POST', + url: '@{PackageUntagR pn}', + data: {slug:normalized} + }); + } + + $('.tags').find('.tag').each(function(){ - tags[$(this).find('a').text()] = true; + tags[$(this).find('.tag-name').text()] = true; }); $('.expanding').each(function(){ var $this = $(this); @@ -41,6 +68,7 @@ $(function(){ login(); } }); + $('.tag-toggle').click(toggleClick); $('#add-tag').click(function(){ if (!loggedIn) login(); $('#add-tag-form').toggleClass('hidden'); @@ -79,15 +107,23 @@ $(function(){ if (!tags[normalized]) { var tag = $(''); - tag.find('a').text(normalized).attr('href','/tag/' + normalized); + tag.find('a').text(normalized + ' ').attr('href','/tag/' + normalized); $('.tags').prepend(', '); + var count = $('1') + .addClass('tag-count') + .addClass('tag-toggle') + .addClass('tagged') + .data('slug',normalized) + .attr('title','Add/remove vote for: ' + normalized) + .click(toggleClick); + $('.tags').prepend(count); $('.tags').prepend(tag); } tags[normalized] = true; }, error: function(err){ - $('#tag-msg').text('invalid slug; too short or too long').show(); + $('#tag-msg').text("Couldn't add that tag").show(); } }); } diff --git a/templates/package.lucius b/templates/package.lucius index f1a90a2..62c5177 100644 --- a/templates/package.lucius +++ b/templates/package.lucius @@ -192,3 +192,22 @@ h2.changes-title { .no-tags { color: #888; } +.tag-count { + border: 0.1em solid #d8d8d8; + text-shadow: none; + padding: 0 0.25em; + border-radius: 0.25em; + color: #999; + font-size: 0.8em; +} +.tag-count:hover { + border: 0.1em solid #333; + color: #333; + cursor: pointer; + text-decoration: none; +} +.tag-count.tagged { + background: #06537d; + border: none; + color: #fff; +}