mirror of
https://github.com/commercialhaskell/stackage-server.git
synced 2026-01-24 01:41:55 +01:00
Add tag voting (#35)
This commit is contained in:
parent
3fb5375230
commit
f36df17c01
@ -43,15 +43,27 @@ getPackageR pn = do
|
|||||||
|
|
||||||
return (packages, downloads, recentDownloads, nLikes, liked, metadata)
|
return (packages, downloads, recentDownloads, nLikes, liked, metadata)
|
||||||
|
|
||||||
tags <- fmap (map (\(E.Value v) -> v))
|
myTags <-
|
||||||
(runDB (E.selectDistinct
|
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.from (\(t `E.LeftOuterJoin` bt) -> do
|
||||||
E.on $ t E.^. TagTag E.==. bt E.^. BannedTagTag
|
E.on $ t E.^. TagTag E.==. bt E.^. BannedTagTag
|
||||||
E.where_
|
E.where_
|
||||||
$ (t ^. TagPackage E.==. E.val pn) E.&&.
|
$ (t ^. TagPackage E.==. E.val pn) E.&&.
|
||||||
(E.isNothing $ E.just $ bt E.^. BannedTagTag)
|
(E.isNothing $ E.just $ bt E.^. BannedTagTag)
|
||||||
|
E.groupBy (t ^. TagTag)
|
||||||
E.orderBy [E.asc (t ^. TagTag)]
|
E.orderBy [E.asc (t ^. TagTag)]
|
||||||
return (t ^. TagTag)))))
|
return (t ^. TagTag,E.count (t ^. TagTag))))))
|
||||||
|
|
||||||
let likeTitle = if liked
|
let likeTitle = if liked
|
||||||
then "You liked this!"
|
then "You liked this!"
|
||||||
@ -191,3 +203,20 @@ postPackageTagR packageName =
|
|||||||
do slug <- mkSlugLen 1 20 tag
|
do slug <- mkSlugLen 1 20 tag
|
||||||
void (runDB (P.insert (Tag packageName slug uid)))
|
void (runDB (P.insert (Tag packageName slug uid)))
|
||||||
Nothing -> error "Need a slug"
|
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"
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
/package/#PackageName/like PackageLikeR POST
|
/package/#PackageName/like PackageLikeR POST
|
||||||
/package/#PackageName/unlike PackageUnlikeR POST
|
/package/#PackageName/unlike PackageUnlikeR POST
|
||||||
/package/#PackageName/tag PackageTagR POST
|
/package/#PackageName/tag PackageTagR POST
|
||||||
|
/package/#PackageName/untag PackageUntagR POST
|
||||||
/tags TagListR GET
|
/tags TagListR GET
|
||||||
/tag/#Slug TagR GET
|
/tag/#Slug TagR GET
|
||||||
/banned-tags BannedTagsR GET PUT
|
/banned-tags BannedTagsR GET PUT
|
||||||
|
|||||||
@ -21,10 +21,12 @@ $newline never
|
|||||||
$if null tags
|
$if null tags
|
||||||
<span .no-tags>
|
<span .no-tags>
|
||||||
No tags yet. #
|
No tags yet. #
|
||||||
$forall tag <- tags
|
$forall (tag,count,tagged) <- tags
|
||||||
<span .tag>
|
<span .tag>
|
||||||
<a href=@{TagR tag}>
|
<a href=@{TagR tag} .tag-name>
|
||||||
#{tag}
|
#{tag} #
|
||||||
|
<a .tag-count .tag-toggle data-slug=#{tag} :tagged:.tagged title="Add/remove vote for: #{tag}">
|
||||||
|
#{count}
|
||||||
, #
|
, #
|
||||||
<i #add-tag class="fa fa-plus-square" title="Show/hide tag form">
|
<i #add-tag class="fa fa-plus-square" title="Show/hide tag form">
|
||||||
<form #add-tag-form .hidden>
|
<form #add-tag-form .hidden>
|
||||||
|
|||||||
@ -1,8 +1,35 @@
|
|||||||
$(function(){
|
$(function(){
|
||||||
var loggedIn = $('.user-handle').length > 0;
|
var loggedIn = $('.user-handle').length > 0;
|
||||||
var tags = Object.create(null);
|
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').find('.tag').each(function(){
|
||||||
tags[$(this).find('a').text()] = true;
|
tags[$(this).find('.tag-name').text()] = true;
|
||||||
});
|
});
|
||||||
$('.expanding').each(function(){
|
$('.expanding').each(function(){
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
@ -41,6 +68,7 @@ $(function(){
|
|||||||
login();
|
login();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
$('.tag-toggle').click(toggleClick);
|
||||||
$('#add-tag').click(function(){
|
$('#add-tag').click(function(){
|
||||||
if (!loggedIn) login();
|
if (!loggedIn) login();
|
||||||
$('#add-tag-form').toggleClass('hidden');
|
$('#add-tag-form').toggleClass('hidden');
|
||||||
@ -79,15 +107,23 @@ $(function(){
|
|||||||
|
|
||||||
if (!tags[normalized]) {
|
if (!tags[normalized]) {
|
||||||
var tag = $('<span><a></a></span>');
|
var tag = $('<span><a></a></span>');
|
||||||
tag.find('a').text(normalized).attr('href','/tag/' + normalized);
|
tag.find('a').text(normalized + ' ').attr('href','/tag/' + normalized);
|
||||||
$('.tags').prepend(', ');
|
$('.tags').prepend(', ');
|
||||||
|
var count = $('<a>1</a>')
|
||||||
|
.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').prepend(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
tags[normalized] = true;
|
tags[normalized] = true;
|
||||||
},
|
},
|
||||||
error: function(err){
|
error: function(err){
|
||||||
$('#tag-msg').text('invalid slug; too short or too long').show();
|
$('#tag-msg').text("Couldn't add that tag").show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -192,3 +192,22 @@ h2.changes-title {
|
|||||||
.no-tags {
|
.no-tags {
|
||||||
color: #888;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user