mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-28 16:28:01 -05:00
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:
@@ -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():
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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*/ }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
 - <span class="stickied-tagline" title="selected by this subreddit's moderators">stickied post</span>
|
||||
%endif
|
||||
</%def>
|
||||
|
||||
<%def name="child()">
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user