From 9fa7e0b515804bde927baf4e6402c16c6ea7638d Mon Sep 17 00:00:00 2001 From: Chad Birch Date: Mon, 29 Jul 2013 14:45:07 -0600 Subject: [PATCH] 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. --- r2/r2/controllers/api.py | 19 ++++++++++++++++++- r2/r2/controllers/listingcontroller.py | 15 +++++++++++++++ r2/r2/lib/jsontemplates.py | 3 ++- r2/r2/models/link.py | 19 ++++++++++++++++--- r2/r2/models/subreddit.py | 2 ++ r2/r2/public/static/css/compact.css | 4 ++++ r2/r2/public/static/css/compact.scss | 7 +++++++ r2/r2/public/static/css/reddit.less | 15 ++++++++++++++- r2/r2/templates/createsubreddit.html | 9 +++++++++ r2/r2/templates/link.compact | 11 +++++++++-- r2/r2/templates/link.html | 7 ++++++- r2/r2/templates/printable.html | 2 ++ 12 files changed, 104 insertions(+), 9 deletions(-) diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index a9521aea4..95091bada 100755 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -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(): diff --git a/r2/r2/controllers/listingcontroller.py b/r2/r2/controllers/listingcontroller.py index 9ea0a5ecf..68ce09671 100755 --- a/r2/r2/controllers/listingcontroller.py +++ b/r2/r2/controllers/listingcontroller.py @@ -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): diff --git a/r2/r2/lib/jsontemplates.py b/r2/r2/lib/jsontemplates.py index 265c97b5e..8bbff9a5a 100755 --- a/r2/r2/lib/jsontemplates.py +++ b/r2/r2/lib/jsontemplates.py @@ -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): diff --git a/r2/r2/models/link.py b/r2/r2/models/link.py index b047c1ef3..11dd59357 100755 --- a/r2/r2/models/link.py +++ b/r2/r2/models/link.py @@ -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 diff --git a/r2/r2/models/subreddit.py b/r2/r2/models/subreddit.py index 429ffe6e8..76ca78966 100644 --- a/r2/r2/models/subreddit.py +++ b/r2/r2/models/subreddit.py @@ -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, diff --git a/r2/r2/public/static/css/compact.css b/r2/r2/public/static/css/compact.css index 8dd30c2c1..3f5eaffb9 100644 --- a/r2/r2/public/static/css/compact.css +++ b/r2/r2/public/static/css/compact.css @@ -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*/ } diff --git a/r2/r2/public/static/css/compact.scss b/r2/r2/public/static/css/compact.scss index c4cd074c2..fa42d9857 100644 --- a/r2/r2/public/static/css/compact.scss +++ b/r2/r2/public/static/css/compact.scss @@ -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; diff --git a/r2/r2/public/static/css/reddit.less b/r2/r2/public/static/css/reddit.less index 1729af670..73d875de8 100755 --- a/r2/r2/public/static/css/reddit.less +++ b/r2/r2/public/static/css/reddit.less @@ -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;} diff --git a/r2/r2/templates/createsubreddit.html b/r2/r2/templates/createsubreddit.html index 1c997ceda..d9154ccdd 100644 --- a/r2/r2/templates/createsubreddit.html +++ b/r2/r2/templates/createsubreddit.html @@ -275,6 +275,15 @@
+
+ + + ${error_field("BAD_URL", "sticky_permalink")} +
%if thing.site: diff --git a/r2/r2/templates/link.compact b/r2/r2/templates/link.compact index 579dae0c7..455f4f0a7 100644 --- a/r2/r2/templates/link.compact +++ b/r2/r2/templates/link.compact @@ -39,9 +39,16 @@ %endif -