Subreddit settings: add ability to define a sticky

This allows subreddits to define a single self-post from inside the same
subreddit, which will be "stuck" to the top of the subreddit's hot page,
with distinct styling. Outside of viewing the subreddit's hot page
individually, the post will behave as normal. It also can only be hidden
by the user manually, and will not automatically hide due to being below
their score threshold, or being upvoted/downvoted with one of the user
preferences that normally hides posts they vote on.
This commit is contained in:
Chad Birch
2013-07-29 14:45:07 -06:00
parent 5cdd6f7530
commit 9fa7e0b515
12 changed files with 104 additions and 9 deletions

View File

@@ -1748,6 +1748,7 @@ class ApiController(RedditController, OAuth2ResourceController):
show_cname_sidebar = VBoolean('show_cname_sidebar'),
type = VOneOf('type', ('public', 'private', 'restricted', 'gold_restricted', 'archived')),
link_type = VOneOf('link_type', ('any', 'link', 'self')),
sticky_permalink=VUrl('sticky_permalink'),
submit_link_label=VLength('submit_link_label', max_length=60),
submit_text_label=VLength('submit_text_label', max_length=60),
comment_score_hide_mins=VInt('comment_score_hide_mins',
@@ -1794,7 +1795,8 @@ class ApiController(RedditController, OAuth2ResourceController):
if k in ('name', 'title', 'domain', 'description',
'show_media', 'exclude_banned_modqueue',
'show_cname_sidebar', 'type', 'public_traffic',
'link_type', 'submit_link_label', 'comment_score_hide_mins',
'link_type', 'sticky_permalink',
'submit_link_label', 'comment_score_hide_mins',
'submit_text_label', 'lang', 'css_on_cname',
'header_title', 'over_18', 'wikimode', 'wiki_edit_karma',
'wiki_edit_age', 'allow_top', 'public_description'))
@@ -1841,6 +1843,17 @@ class ApiController(RedditController, OAuth2ResourceController):
if cname_sr and (not sr or sr != cname_sr):
c.errors.add(errors.USED_CNAME)
sticky_fullname = None
if kw['sticky_permalink']:
sticky_url = UrlParser(kw['sticky_permalink']).path
if sticky_url:
try:
sticky_fullname = Link._by_url(sticky_url, sr)._fullname
except NotFound:
c.errors.add(errors.BAD_URL, field='sticky_permalink')
else:
c.errors.add(errors.BAD_URL, field='sticky_permalink')
can_set_archived = c.user_is_admin or (sr and sr.type == 'archived')
if kw['type'] == 'archived' and not can_set_archived:
c.errors.add(errors.INVALID_OPTION, field='type')
@@ -1869,6 +1882,8 @@ class ApiController(RedditController, OAuth2ResourceController):
elif (form.has_errors(('wiki_edit_karma', 'wiki_edit_age'),
errors.BAD_NUMBER)):
pass
elif form.has_errors('sticky_permalink', errors.BAD_URL):
pass
elif form.has_errors('comment_score_hide_mins', errors.BAD_NUMBER):
pass
#creating a new reddit
@@ -1902,6 +1917,8 @@ class ApiController(RedditController, OAuth2ResourceController):
success = update_wiki_text(sr)
sr.sticky_fullname = sticky_fullname
if not sr.domain:
del kw['css_on_cname']
for k, v in kw.iteritems():

View File

@@ -358,6 +358,21 @@ class HotController(FixListing, ListingController):
elif isinstance(c.site, MultiReddit):
return normalized_hot(c.site.kept_sr_ids, obey_age_limit=False)
else:
if c.site.sticky_fullname:
link_list = [c.site.sticky_fullname]
wrapped = wrap_links(link_list,
wrapper=self.builder_wrapper,
keep_fn=self.keep_fn(),
skip=True)
# add all other items and decrement count if sticky is visible
if wrapped.things:
link_list += [l for l in c.site.get_links('hot', 'all')
if l != c.site.sticky_fullname]
if not self.after:
self.count -= 1
return link_list
# no sticky or sticky hidden
return c.site.get_links('hot', 'all')
def content(self):

View File

@@ -371,7 +371,8 @@ class LinkJsonTemplate(ThingJsonTemplate):
subreddit_id = "subreddit_id",
is_self = "is_self",
permalink = "permalink",
edited = "editted"
edited = "editted",
stickied = "stickied",
)
def thing_attr(self, thing, attr):

View File

@@ -242,13 +242,24 @@ class Link(Thing, Printable):
#return False
if user and not c.ignore_hide_rules:
if user.pref_hide_ups and wrapped.likes == True and self.author_id != user._id:
# whether the user must deliberately hide the item
# (not automatic due to score or having upvoted/downvoted it)
require_explicit_hide = wrapped.stickied
if (user.pref_hide_ups and
wrapped.likes == True and
self.author_id != user._id and
not require_explicit_hide):
return False
if user.pref_hide_downs and wrapped.likes == False and self.author_id != user._id:
if (user.pref_hide_downs and
wrapped.likes == False and
self.author_id != user._id and
not require_explicit_hide):
return False
if wrapped._score < user.pref_min_link_score:
if (wrapped._score < user.pref_min_link_score and
not require_explicit_hide):
return False
if wrapped.hidden:
@@ -483,6 +494,8 @@ class Link(Thing, Printable):
# is this link a member of a different (non-c.site) subreddit?
item.different_sr = (isinstance(site, FakeSubreddit) or
site.name != item.subreddit.name)
item.stickied = (not item.different_sr and
site.sticky_fullname == item._fullname)
if user_is_loggedin and item.author_id == user._id:
item.nofollow = False

View File

@@ -206,6 +206,8 @@ class Subreddit(Thing, Printable, BaseSite):
mod_actions=0,
# do we allow self-posts, links only, or any?
link_type='any', # one of ('link', 'self', 'any')
sticky_permalink=None,
sticky_fullname=None,
submit_link_label='',
submit_text_label='',
comment_score_hide_mins=0,

View File

@@ -196,6 +196,8 @@ body[orient="landscape"] > #topbar > h1 { margin-left: -125px; width: 250px; }
.link p.title > a { text-overflow: ellipsis; overflow: hidden; color: #25A; }
.link.stickied p.title > a { color: #228822; }
.link .domain { color: #737373; font-size: 9px; margin-left: 5px; }
.link .domain a, .link .domain a:hover { color: inherit; }
@@ -205,6 +207,8 @@ body[orient="landscape"] > #topbar > h1 { margin-left: -125px; width: 250px; }
.link .tagline a { font-weight: bold; }
.link .tagline .stickied-tagline { color: #228822; }
/*Expando*/
.link .expando-button { float: left; display: block; height: auto; line-height: inherit; margin: 3px 10px 2px 0; width: 30px; height: 30px; background-image: url("../compact/selftext.png"); /*SPRITE*/ }
.link .expando-button.expanded { background-image: url("../compact/selftext-active.png"); /*SPRITE*/ }

View File

@@ -621,6 +621,9 @@ body[orient="landscape"] > #topbar > h1 {
text-overflow: ellipsis; overflow: hidden;
color: #25A;
}
.link.stickied p.title > a {
color: #228822;
}
.link .domain {
color: hsl(0,0%,45%);
@@ -652,6 +655,10 @@ body[orient="landscape"] > #topbar > h1 {
font-weight: bold;
}
.link .tagline .stickied-tagline {
color: #228822;
}
/*Expando*/
.link .expando-button {
float: left;

View File

@@ -744,16 +744,19 @@ ul.flat-vert {text-align: left;}
font-size:x-small;
}
@moderator-color: #228822;
.tagline { color:#888; font-size:x-small; }
.tagline a {color: #369; text-decoration: none; }
.tagline .friend { color: orangered }
.tagline .submitter { color: #0055df }
.tagline .moderator, .green { color: #228822 }
.tagline .moderator, .green { color: @moderator-color }
.tagline .admin { color: #ff0011; }
.tagline .alum { color: #BE1337; }
.tagline a.author.admin { font-weight: bold }
.tagline a:hover { text-decoration: underline }
.tagline .edited-timestamp{ cursor: default }
.tagline .stickied-tagline { color: @moderator-color }
a.author { margin-right: 0.5em; }
@@ -930,6 +933,16 @@ a.author { margin-right: 0.5em; }
.thing .title.loggedin.click { color: #551a8b }
.thing .title.loggedin.click:visited { color: #551a8b }
.stickied-link { font-weight: bold; color: @moderator-color; }
.thing.stickied {
a.title { .stickied-link }
a.title:visited { .stickied-link }
a.title.loggedin { .stickied-link }
a.title.loggedin:visited { .stickied-link }
a.title.loggedin.click { .stickied-link }
a.title.loggedin.click:visited { .stickied-link }
}
.sitetable { list-style-type: none; }
.ajaxhook { position: absolute; top: -1000px; left: 0px; }
.nextprev { color: gray; font-size: larger; margin-top: 10px;}

View File

@@ -275,6 +275,15 @@
</ul>
</div>
<div class="usertext-edit">
<div class="delete-field">
<label for="sticky_permalink">${_('Permalink to stickied self-post (blank for none):')}</label>
<input id="sticky_permalink" type="text" name="sticky_permalink"
%if thing.site:
value="${thing.site.sticky_permalink}"
%endif
>
${error_field("BAD_URL", "sticky_permalink")}
</div>
<div class="delete-field">
<label for="comment_score_hide_mins">${_('Minutes to hide comment scores:')}</label>
%if thing.site:

View File

@@ -39,9 +39,16 @@
%endif
</%def>
<div class="thing link id-${thing._fullname}">
<%
div_class = "thing link id-%s" % thing._fullname
if thing.stickied:
div_class += " stickied"
%>
<div class="${div_class}">
<span class="rank" style="width:${thing.numcolmargin};">
${thing.num}
%if thing.num > 0:
${thing.num}
%endif
</span>
<%
like_cls = "unvoted"

View File

@@ -35,7 +35,9 @@
<%def name="numcol()">
<% num = thing.num %>
<span class="rank" style="width:${thing.numcolmargin};">
${thing.num}
%if thing.num > 0:
${thing.num}
%endif
</span>
</%def>
@@ -215,6 +217,9 @@ ${parent.thing_data_attributes(what)} data-ups="${what.upvotes}" data-downs="${w
author=WrappedUser(thing.author, thing.attribs, thing).render(),
lastedited=capture(edited, thing, thing.lastedited)
))}
%if thing.stickied:
&#32;-&#32;<span class="stickied-tagline" title="selected by this subreddit's moderators">stickied post</span>
%endif
</%def>
<%def name="child()">

View File

@@ -76,6 +76,8 @@ ${self.RenderPrintable()}
rowclass += " gilded"
if hasattr(what, "user_gilded") and what.user_gilded:
rowclass += " user-gilded"
if getattr(what, "stickied", False):
rowclass += " stickied"
%>
${rowclass}
</%def>