From 61227124d4e71b4aecffc6360a8101c06296fae2 Mon Sep 17 00:00:00 2001 From: bsimpson63 Date: Mon, 5 Dec 2011 18:56:28 -0800 Subject: [PATCH] Modaction display. --- r2/r2/config/routing.py | 1 + r2/r2/controllers/front.py | 55 ++++++++++- r2/r2/lib/menus.py | 1 + r2/r2/lib/pages/pages.py | 4 + r2/r2/models/builder.py | 7 +- r2/r2/models/listing.py | 4 + r2/r2/models/modaction.py | 60 +++++++++--- r2/r2/models/subreddit.py | 5 +- r2/r2/public/static/css/reddit.css | 87 +++++++++++++++++- .../static/modactions_addcontributor.png | Bin 0 -> 589 bytes .../public/static/modactions_addmoderator.png | Bin 0 -> 758 bytes .../static/modactions_approvecomment.png | Bin 0 -> 1507 bytes .../public/static/modactions_approvelink.png | Bin 0 -> 781 bytes r2/r2/public/static/modactions_banuser.png | 1 + r2/r2/public/static/modactions_editflair.png | 1 + .../public/static/modactions_editsettings.png | 1 + .../static/modactions_removecomment.png | Bin 0 -> 670 bytes .../static/modactions_removecontributor.png | Bin 0 -> 603 bytes r2/r2/public/static/modactions_removelink.png | Bin 0 -> 715 bytes .../static/modactions_removemoderator.png | Bin 0 -> 768 bytes r2/r2/public/static/modactions_unbanuser.png | Bin 0 -> 741 bytes r2/r2/public/static/reddit_moderationlog.png | Bin 0 -> 649 bytes r2/r2/templates/modaction.html | 39 ++++++++ r2/r2/templates/tablelisting.html | 64 +++++++++++++ 24 files changed, 312 insertions(+), 18 deletions(-) create mode 100755 r2/r2/public/static/modactions_addcontributor.png create mode 100755 r2/r2/public/static/modactions_addmoderator.png create mode 100755 r2/r2/public/static/modactions_approvecomment.png create mode 100755 r2/r2/public/static/modactions_approvelink.png create mode 120000 r2/r2/public/static/modactions_banuser.png create mode 120000 r2/r2/public/static/modactions_editflair.png create mode 120000 r2/r2/public/static/modactions_editsettings.png create mode 100755 r2/r2/public/static/modactions_removecomment.png create mode 100755 r2/r2/public/static/modactions_removecontributor.png create mode 100755 r2/r2/public/static/modactions_removelink.png create mode 100755 r2/r2/public/static/modactions_removemoderator.png create mode 100755 r2/r2/public/static/modactions_unbanuser.png create mode 100755 r2/r2/public/static/reddit_moderationlog.png create mode 100755 r2/r2/templates/modaction.html create mode 100755 r2/r2/templates/tablelisting.html diff --git a/r2/r2/config/routing.py b/r2/r2/config/routing.py index fefed3676..6a35fc650 100644 --- a/r2/r2/config/routing.py +++ b/r2/r2/config/routing.py @@ -50,6 +50,7 @@ def make_map(global_conf={}, app_conf={}): mc('/account-activity', controller='front', action='account_activity') mc('/about/message/:where', controller='message', action='listing') + mc('/about/log', controller='front', action='moderationlog') mc('/about/:location', controller='front', action='editreddit', location = 'about') diff --git a/r2/r2/controllers/front.py b/r2/r2/controllers/front.py index 6c277cdfa..f0f2f91fa 100644 --- a/r2/r2/controllers/front.py +++ b/r2/r2/controllers/front.py @@ -21,7 +21,7 @@ ################################################################################ from validator import * from pylons.i18n import _, ungettext -from reddit_base import RedditController, base_listing +from reddit_base import RedditController, base_listing, base_cassandra_listing from r2 import config from r2.models import * from r2.lib.pages import * @@ -362,6 +362,59 @@ class FrontController(RedditController): else: return self.abort404() + def _make_moderationlog(self, num, after, reverse, count, mod=None, action=None): + + if mod and action: + query = c.site.get_modactions(mod=mod, action=None) + + def keep_fn(ma): + return ma.action == action + else: + query = c.site.get_modactions(mod=mod, action=action) + + def keep_fn(ma): + return True + + builder = QueryBuilder(query, skip=True, num=num, after=after, + keep_fn=keep_fn, count=count, + reverse=reverse, + wrap=default_thing_wrapper()) + listing = ModActionListing(builder) + pane = listing.listing() + return pane + + @base_cassandra_listing + @validate(mod=VAccountByName('mod'), + action=VOneOf('type', ModAction.actions)) + def GET_moderationlog(self, num, after, reverse, count, mod, action): + + is_moderator = c.user_is_loggedin and c.site.is_moderator(c.user) or c.user_is_admin + + if not is_moderator: + return self.abort404() + + panes = PaneStack() + pane = self._make_moderationlog(num, after, reverse, count, + mod=mod, action=action) + panes.append(pane) + + action_buttons = [NavButton(_('all'), None, opt='type', css_class='primary')] + for a in ModAction.actions: + action_buttons.append(NavButton(ModAction._menu[a], a, opt='type')) + + mod_ids = c.site.moderators + mods = Account._byID(mod_ids) + mod_buttons = [NavButton(_('all'), None, opt='mod', css_class='primary')] + for mod_id in mod_ids: + mod = mods[mod_id] + mod_buttons.append(NavButton(mod.name, mod.name, opt='mod')) + base_path = request.path + menus = [NavMenu(action_buttons, base_path=base_path, + title=_('filter by action'), type='lightdrop', css_class='modaction-drop'), + NavMenu(mod_buttons, base_path=base_path, + title=_('filter by moderator'), type='lightdrop')] + return EditReddit(content=panes, nav_menus=menus, extension_handling=False).render() + def _make_spamlisting(self, location, num, after, reverse, count): if location == 'reports': query = c.site.get_reported() diff --git a/r2/r2/lib/menus.py b/r2/r2/lib/menus.py index caec8b408..4f3284542 100644 --- a/r2/r2/lib/menus.py +++ b/r2/r2/lib/menus.py @@ -131,6 +131,7 @@ menu = MenuHandler(hot = _('hot'), banned = _("ban users"), banusers = _("ban users"), flair = _("edit user flair"), + log = _("moderation log"), popular = _("popular"), create = _("create"), diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index b78456b68..a43e8b212 100644 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -26,6 +26,8 @@ from r2.models import Friends, All, Sub, NotFound, DomainSR, Random, Mod, Random from r2.models import Link, Printable, Trophy, bidding, PromotionWeights, Comment from r2.models import Flair, FlairTemplate, FlairTemplateBySubredditIndex from r2.models.oauth2 import OAuth2Client +from r2.models import ModAction +from r2.models import Thing from r2.config import cache from r2.lib.tracking import AdframeInfo from r2.lib.jsonresponse import json_respond @@ -203,6 +205,7 @@ class Reddit(Templated): NamedButton('spam', css_class = 'reddit-spam'), NamedButton('banned', css_class = 'reddit-ban'), NamedButton('flair', css_class = 'reddit-flair'), + NamedButton('log', css_class = 'reddit-moderationlog'), ]) return [NavMenu(buttons, type = "flat_vert", base_path = "/about/", css_class = "icon-menu", separator = '')] @@ -517,6 +520,7 @@ class SubredditInfoBar(CachedTemplate): NamedButton('traffic'), NavButton(menu.community_settings, 'edit'), NavButton(menu.flair, 'flair'), + NavButton(menu.modactions, 'modactions'), ]) return [NavMenu(buttons, type = "flat_vert", base_path = "/about/", separator = '')] diff --git a/r2/r2/models/builder.py b/r2/r2/models/builder.py index fc7132095..9049fd25a 100644 --- a/r2/r2/models/builder.py +++ b/r2/r2/models/builder.py @@ -45,7 +45,7 @@ EXTRA_FACTOR = 1.5 MAX_RECURSION = 10 class Builder(object): - def __init__(self, wrap = Wrapped, keep_fn = None, stale = True): + def __init__(self, wrap=Wrapped, keep_fn=None, stale=True): self.stale = stale self.wrap = wrap self.keep_fn = keep_fn @@ -272,9 +272,8 @@ class Builder(object): return True class QueryBuilder(Builder): - def __init__(self, query, wrap = Wrapped, keep_fn = None, - skip = False, **kw): - Builder.__init__(self, wrap, keep_fn) + def __init__(self, query, wrap=Wrapped, keep_fn=None, skip=False, **kw): + Builder.__init__(self, wrap=wrap, keep_fn=keep_fn) self.query = query self.skip = skip self.num = kw.get('num') diff --git a/r2/r2/models/listing.py b/r2/r2/models/listing.py index 755122410..fa764c0f0 100644 --- a/r2/r2/models/listing.py +++ b/r2/r2/models/listing.py @@ -89,6 +89,10 @@ class Listing(object): def __iter__(self): return iter(self.things) +class TableListing(Listing): pass + +class ModActionListing(TableListing): pass + class LinkListing(Listing): def __init__(self, *a, **kw): Listing.__init__(self, *a, **kw) diff --git a/r2/r2/models/modaction.py b/r2/r2/models/modaction.py index 09637621d..8cd47d37a 100644 --- a/r2/r2/models/modaction.py +++ b/r2/r2/models/modaction.py @@ -1,6 +1,6 @@ from r2.lib.db import tdb_cassandra from r2.lib.utils import tup -from r2.models import Account, Subreddit, Link, Printable +from r2.models import Account, Subreddit, Link, Comment, Printable from pycassa.system_manager import TIME_UUID_TYPE from uuid import UUID from pylons.i18n import _ @@ -86,7 +86,7 @@ class ModAction(tdb_cassandra.UuidThing, Printable): 'flair_clear_template': _('clear flair templates')} # This stuff won't change - cache_ignore = set(['subreddit']).union(Printable.cache_ignore) + cache_ignore = set(['subreddit', 'target']).union(Printable.cache_ignore) # Thing properties for Printable @property @@ -187,15 +187,54 @@ class ModAction(tdb_cassandra.UuidThing, Printable): from r2.lib.menus import NavButton from r2.lib.db.thing import Thing - from r2.lib.pages import WrappedUser, SimpleLinkDisplay + from r2.lib.pages import WrappedUser + from r2.lib.filters import _force_unicode + + TITLE_MAX_WIDTH = 50 request_path = request.path target_fullnames = [item.target_fullname for item in wrapped if hasattr(item, 'target_fullname')] - targets = Thing._by_fullname(target_fullnames) + targets = Thing._by_fullname(target_fullnames, data=True) + authors = Account._byID([t.author_id for t in targets.values() if hasattr(t, 'author_id')], data=True) + links = Link._byID([t.link_id for t in targets.values() if hasattr(t, 'link_id')], data=True) + subreddits = Subreddit._byID([t.sr_id for t in targets.values() if hasattr(t, 'sr_id')]) + + # Assemble target links + target_links = {} + target_accounts = {} + for fullname, target in targets.iteritems(): + if isinstance(target, Link): + author = authors[target.author_id] + title = _force_unicode(target.title) + if len(title) > TITLE_MAX_WIDTH: + short_title = title[:TITLE_MAX_WIDTH] + '...' + else: + short_title = title + text = '"%(title)s" %(by)s %(author)s' % {'title': short_title, + 'by': _('by'), + 'author': author.name} + path = target.make_permalink(subreddits[target.sr_id]) + target_links[fullname] = (text, path, title) + elif isinstance(target, Comment): + author = authors[target.author_id] + link = links[target.link_id] + title = _force_unicode(link.title) + if len(title) > TITLE_MAX_WIDTH: + short_title = title[:TITLE_MAX_WIDTH] + '...' + else: + short_title = title + text = '%(by)s %(author)s %(on)s "%(title)s"' % {'by': _('by'), + 'author': author.name, + 'on': _('on'), + 'title': short_title} + path = target.make_permalink(link, subreddits[target.sr_id]) + target_links[fullname] = (text, path, title) + elif isinstance(target, Account): + target_accounts[fullname] = WrappedUser(target) for item in wrapped: - # Can I move these buttons somewhere else? Does it make sense to do so? + # Can I move these buttons somewhere else? Not great to have request stuff in here css_class = 'modactions %s' % item.action item.button = NavButton('', item.action, opt='type', css_class=css_class) item.button.build(base_path=request_path) @@ -206,14 +245,13 @@ class ModAction(tdb_cassandra.UuidThing, Printable): item.text = ModAction._text.get(item.action, '') item.details = item.get_extra_text() - # Can extend default_thing_wrapper to also lookup the targets - if hasattr(item, 'target_fullname') and not item.target_fullname == None: + if hasattr(item, 'target_fullname') and item.target_fullname: target = targets[item.target_fullname] if isinstance(target, Account): - item.target = WrappedUser(target) - elif isinstance(target, Comment) or isinstance(target, Link): - item.target = SimpleLinkDisplay(target) - + item.target_wrapped_user = target_accounts[item.target_fullname] + elif isinstance(target, Link) or isinstance(target, Comment): + item.target_text, item.target_path, item.target_title = target_links[item.target_fullname] + Printable.add_props(user, wrapped) class ModActionBySR(tdb_cassandra.View): diff --git a/r2/r2/models/subreddit.py b/r2/r2/models/subreddit.py index ddb4664a4..cae856bae 100644 --- a/r2/r2/models/subreddit.py +++ b/r2/r2/models/subreddit.py @@ -38,7 +38,6 @@ from r2.lib.filters import _force_unicode from r2.lib.db import tdb_cassandra from r2.lib.cache import CL_ONE - import os.path import random @@ -333,6 +332,10 @@ class Subreddit(Thing, Printable): from r2.lib.db import queries return queries.get_sr_comments(self) + def get_modactions(self, mod=None, action=None): + # Get a query that will yield ModAction objects with mod and action + from r2.models import ModAction + return ModAction.get_actions(self, mod=mod, action=action) @classmethod def add_props(cls, user, wrapped): diff --git a/r2/r2/public/static/css/reddit.css b/r2/r2/public/static/css/reddit.css index 0a7aa653c..190871e6e 100644 --- a/r2/r2/public/static/css/reddit.css +++ b/r2/r2/public/static/css/reddit.css @@ -146,7 +146,7 @@ label.disabled { color: gray; } .hover a:hover { text-decoration: underline } -.selected { font-weight: bold; } +.selected, .choice.primary { font-weight: bold; } .flat-list {list-style-type: none; display: inline;} .flat-list li, .flat-list form {display: inline; white-space: nowrap; } @@ -4250,6 +4250,7 @@ dd { margin-left: 20px; } .icon-menu .reddit-spam:before, .icon-menu .reddit-ban:before, .icon-menu .reddit-flair:before, +.icon-menu .reddit-moderationlog:before, .icon-menu .reddit-moderators:before, .icon-menu .moderator-mail:before, .icon-menu .reddit-contributors:before, @@ -4304,6 +4305,10 @@ dd { margin-left: 20px; } /* Work around a centering difference between this icon and reddit_ban.png */ margin-left: 1px; } +.icon-menu .reddit-moderationlog:before { + background-image: url(../reddit_moderationlog.png); /* SPRITE */ + margin-left: 1px; +} .icon-menu .reddit-moderators:before { background-image: url(../shield.png); /* SPRITE */ } @@ -4917,3 +4922,83 @@ tr.gold-accent + tr > td { background: #e4e4e4; box-shadow: inset 0px -1px 0px white; } + +.modactionlisting table { + margin: 0 15px; +} + +.modactionlisting td.timestamp { + white-space: nowrap; + padding-left: 0; + padding-right: 1.5em; +} + +.modactionlisting td.button { + padding-right: 0; + padding-left: 1.5em; +} + +.modactionlisting td.description em { + font-style: italic; +} + +.modactions td { + font-size: small; + text-align: left; + padding: 2px; +} +.modactions.banuser, +.modactions.unbanuser, +.modactions.removelink, +.modactions.approvelink, +.modactions.removecomment, +.modactions.approvecomment, +.modactions.addmoderator, +.modactions.removemoderator, +.modactions.addcontributor, +.modactions.removecontributor, +.modactions.editsettings, +.modactions.editflair { + height: 16px; + width: 16px; + display: block; + content: " "; + float: left; + margin-right: 5px; +} +.modactions.banuser { + background-image: url(../modactions_banuser.png); /* SPRITE */ +} +.modactions.unbanuser { + background-image: url(../modactions_unbanuser.png); /* SPRITE */ +} +.modactions.removelink { + background-image: url(../modactions_removelink.png); /* SPRITE */ +} +.modactions.approvelink { + background-image: url(../modactions_approvelink.png); /* SPRITE */ +} +.modactions.removecomment { + background-image: url(../modactions_removecomment.png); /* SPRITE */ +} +.modactions.approvecomment { + background-image: url(../modactions_approvecomment.png); /* SPRITE */ +} +.modactions.addmoderator { + background-image: url(../modactions_addmoderator.png); /* SPRITE */ +} +.modactions.removemoderator { + background-image: url(../modactions_removemoderator.png); /* SPRITE */ +} +.modactions.addcontributor { + background-image: url(../modactions_addcontributor.png); /* SPRITE */ +} +.modactions.removecontributor { + background-image: url(../modactions_removecontributor.png); /* SPRITE */ +} +.modactions.editsettings { + background-image: url(../modactions_editsettings.png); /* SPRITE */ +} +.modactions.editflair { + background-image: url(../modactions_editflair.png); /* SPRITE */ +} diff --git a/r2/r2/public/static/modactions_addcontributor.png b/r2/r2/public/static/modactions_addcontributor.png new file mode 100755 index 0000000000000000000000000000000000000000..902bbe61b3e64a9e83333fc17bc8dbb38de2cf9f GIT binary patch literal 589 zcmV-T0?rbKYL%|LWA_fWIdu`2D{$SO5OKC8m-@8*p<)!2cUdv;Kd7c=G>` z$EW|Fn(FlbP?O<0Vr~Eb<;wE^KOP?a|MT$~F#djf@Bfn%{QnZA`N!MC|9?DM@&E3+ zoc~|WF9l}pHx`K1jMaes6V!>;jA6jePPPA^p6$b`dFe#2|9Mj)KBe{f z|Bq~O_~cokR|7X-MzVqeNb|$f8~&eInU0}(LBHGo#?^`cw_KU}|H89f|ND1m{SWWg z{coNv*#kCUa<1I}PY+N0|MmRh|E;wq{}0bJ{D0?2?*H?1y#60=Hu)dh?(%)(?Fzp3k#2;Op=9! zVS%RGgcvtB?=hrnT(^1LdEEQ||L^Y{iyPBKvvKOIPJPa&)A<@z<$uZ3-6v zc~$Gk^h9y;%5Y0+$*))mIb#7qgC5d9!ldIb@VnnpFu9T5$YrK&jTjd|MT^t1mgM-l zi=cwqeuBO>+~TDe5+v>*=`WxH zDB^YD#jY{*;V7u!b$6g5&jH-u$57F%uJu6zFoLAQn4AE$>1<~_P>T~PCNq?*1bT)6 zRzMZRM{R&{ERX^dVAKOmgLqjZYY{8*w}EC2R0Gf)APsmZ9%=*BdZ-GBL9K*F0<0k7 z;S|ik4n)A@g5!gewRjZEqxJiE`ktM{PYJ1^!X4M4$r(0~Gs!nsaL3hQLK85q!MFj& z^?C5w(w-@!VR-|4w(O;LaWzcjP~E<&Q-1(e8=fB+?7UC%eKWb`8*vK8;N%7vcaYn! zlPsKDi*+oum8-EPpl(4uz}^wBtX9efI_@#hai37>HjFzH;|vn-OAs<+SwC+-00&oH zV8)~xfcz1FsheLVGO1*BZ?u`-$W^RA1x2fB&I!kl=p3xE?XyZ9830Hn>o()jVx z+;X+D-*LwrDVp8Lxw|)dqa{Tp^)<_wRk4Towq)Bpeg literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/modactions_approvecomment.png b/r2/r2/public/static/modactions_approvecomment.png new file mode 100755 index 0000000000000000000000000000000000000000..d1ab611f5f5ccc2de8f51ee55c07737844f351ae GIT binary patch literal 1507 zcmV<91swW`P)4Tx0C)j~RL^S@K@|QrZmG~B2wH0nvUrdpNm;9CMbtL^5n^i$+aIn^?(HA4aZWV5ov6ELTdbo0FI&wK{O>*+w4vx20?>!`FrQsdJlnHR>OPy zcd~b_n$otK2Za4V;76L-DzNVtaSB-y0*E}{p()372;bw_^6ZZ}PI-92wGS&j#91PI zKs7DSe@(bk%_Y-7gGe}(^>I=@oY#w#*Bu9GZf3^F5WP>3rn}7Ut74&?PWBFvy`A)a zPP5)V!Xd&78LdA?xQ(9mjMYElVd13a#D+Z_7&Y|xU=_C-srWU*6kiZcC!$nw*)9$7 zn6CX+@=AhmkT}X@VSsa5NKe;HZuq)~1$`#h6R+ZTR#D-3j}vF!)ZOnz+5)dI4jl{{ z44Mr{P!L4~VVJN`K!!XTF*LGrKO?IK8z<8w`3e3jI8lUGNUta*C8 zn(P`s>{pjD=7Kek#B;Fw@hxAK%$F&Q6vg9J^Xf~4by_hu-=A!MJ3Znq&n~srbFGPs zH&&aMXZ>nO`|hf|ljc?VPhR!${AbO?W8x_>CU%PFA&Hm8F7cAsOREdwU~R_;ot1_u z(ruCYB-LPGn!NQdT|ZlRy+(fw^-+`=%+gee_kY4FWHg<*4sZI8+sFJD270UUORdLHO0nA4V) z%{fwsET5CQ>B?eK%uw4yQc~9?*JVo2}ze(;aRcp*ceL#HUJSllrgm5wQKR zQu+C;QrUh^8rFfA`ftFz{YAidi-`aL0dlr5!I*H%~7 zc6D9do!ObwxnuTVMjtbC?>YB==jS^k4UbJxQ|BPO6Jaa{t8BuKtQ6x-Ns9mLigfSU zC)&0#6^_hg(ERc5jn1~BYIyG&hd&U;q2lcM8-G@lZ(_zEYfRE~2{BEAq7xK$C^3T7 zV#e0Y zqq?yVro2rlc-}sMZ=N8M>@t$=7Vu;YGE2a1Nl;mr2$vXPM?}?Ov&zVKq+xJ$3Z~+n z>)^~z#f!E91g8~r^!gBsiAv^lQCUn?)1Wa~(R4%DCb(dP+k9B z$~k2rqXp5%LgeSBqo%13uY0`k$NA9VZNydQBdB^5RUfZlG}wP(>2`eut*-z*?z=_h z4MkM@WdP)4-QibtN)VXQDpczE`xXAkUjh%RI>;okxb7K@0kpyQ1k_Y(|Oe7$m(^ zNYX>mI||sUbmn+c3<&FnE=4u#()KBS^SH8e)Qs5i!#lY=$-1gbH6VluzU=m=EP78&5vQ z-?+fFP-G2l&l_QzYealK$;1Rl?FkzXR&Jv@fBPNjCr#AYRyJ7UJQ0v#?)7Ott=>3`#-pV!7>9}>Q1jL)H6h&gkP@3nI=+F3nA~M>u#(n* z8T!#8oEw&-mED4!h4s!N@Jo3S7N&Q6%6l3}nlcd~X@>;uelvPsSkXIgg~e+^T1zSf z3SNj(5%jK~i8@b;Cc;A#1+9e&U9~QBdhb7i%XEvtC8q~e*9 zTGor!c}UBO!Tp8?(pAKoEsCX!Dv~OwaI#?S|7Y+#Qz)whJ4xaq8BjDPqnKjt1re<^tvd-qJefSYq(anuCjd93vneh6K+h(i&yD!a1MnYqE;KZ-O};W0OdWKgI_pLK zle)Hr=PlJ{;*D|xQkXchK9;-N1yEG%b|6WX&N<<4bB3E4Y$IN>=XK}S-Z!3BGt%RR zcEyG7o^?>|EvvpZ=hdbo)D!63ewiH?<=TAz5V4&90#T#$5FJ5q1^@s607*qoM6N<$ Eg00gme*gdg literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/modactions_removecontributor.png b/r2/r2/public/static/modactions_removecontributor.png new file mode 100755 index 0000000000000000000000000000000000000000..d8944e6ead0b65df6cfae11efced49d88a2f5a21 GIT binary patch literal 603 zcmV-h0;K(kP)aJUfxDNBtTRAiRVBdDb0dZd)pL$P{k)kNc7^C;B3}2}V7~LIt{1J-u zhHUbkuFT{RQI})I5UhL)qs;n91WqH1y}Go3nEOb^5S){rk&d_VLp;L=Zv%O94ll;UWY2R65rz&!x17@cl;CAj}Ns6%i zd5nRJ)r9X?F*V{u^c>>t)oOyZLgJ?ibJq@?o8Vd*UvF46f4UHmRbSVF|2SWIEDX1n z;BVSWf5%?^&f2l_?*pt}-!E-L^YwrR>t@D1jikkgEQo!)?mk$6_1@Tor0i`56;e7( zEUJ>)1XO=cFF0!1!ZB+Jo)hId80xNhvbwq9`W=^}E#<#bon_3QUr(ZC9Yc0=ZqO!N pF#MTD>UVajJI?%>LQ;b@|2K$J-BF0k8QA~;002ovPDHLkV1kb~77qXb literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/modactions_removelink.png b/r2/r2/public/static/modactions_removelink.png new file mode 100755 index 0000000000000000000000000000000000000000..08f249365afd29594b51210c6e21ba253897505d GIT binary patch literal 715 zcmV;+0yO=JP)C4}Mrzlg<+1Y8PEBfUp0jJpx4B>@E+cy3`^(Gw`Mf+2&yxZm<$to~Vpgvg&QKNR z_f#1(r6svZt%iF?s+n<8X?B&!h3g9Dbb8_=MX}!;HiQSAh`bp^WMl~Z-44teO7W_Y zV4thSL{h;rJY7!l3%5J4H1!tIzB`Dv+YxO(haWeausGZYkI8^hWj6mzo=L0{%;yxzh{5!Htr?51 zvG|W62MzC8BZ76hRpCyO2zOn<%e)K>NHge!-~)Ap33OdWw6hsLYbCxGNt0%wk_2z7 zfyYvXheSG)5HRK1VB~%mq7Dmurw#bi@hEcOr3&G1ZiF*$M=&9nB#VNf&Q^r$4G5kp zTURh&s)E0%5&hyVD}sp<72~zmAY`Y(9aqO6CXF%=zFHGzO-A&I(pE}v70YQxCPJ{Y z4L+?5-crdLn3ZRPEs!A4ehEY3ZRpL~w9>@aMN+{F4dI@v&>(QDHQum!mG~E^$OS8l z!7?%Uwib*ROP67Hw`ika)gX-(8Ia`-u_IEhxG7U<13kSsMW+$lbb2dUMm5p6pa}cjgA+U$^mJ^AjD?&bdi)8~y+Q002ovPDHLkV1g8IMc@Dc literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/modactions_removemoderator.png b/r2/r2/public/static/modactions_removemoderator.png new file mode 100755 index 0000000000000000000000000000000000000000..22823a70d9d595c91898132ae06b38d956cd75b8 GIT binary patch literal 768 zcmV+b1ONPqP)_wWDzWofpWZjRwL)Vd8iHwR;&_<&#(aXJ|2rC=4&(@vrY3M%S$@!-jW z=* ztyLco*Wo15n0#0=A?aRByJb2o>G^@3N0CJP%2&wrwamVeY0834$+YqI(Vv}@#Oext*GL@6XYIDnd zAA<~q7WqGC@#Xt*&Xd)?q_FV-8}>d63ap%a4-57fJrO-yE8n*)Uk4fa%1QE-Q&{pR z$N*vK66xX>v@g5`GSbyc$m}P2Jbf|&hC&9GgEOo%g^P0(5)=~DO+kUEP^Q~%?f@E| zJ_Q2_EJGp3MFHr5%W+CU30MjU3jqse^mzJY0vQS!QVxoN1V|An3ONcXl7TrCtU!;a zPr)!tiAsA2Yct?BK$Jn$0hd!dSEGJ*p7v4&H|UYV*vK(n_w>o^{pN3HVEj6TFYk3Y$#xl^Q_CE7r%8FT(3 z3r-UM^~Wc7-lAYHMt;+qH;q)78y|02t5m*iYd7}MJgs_{E6Z`n6TR&u@qf;Lxclai ybx&Bz1iyEv%?$mbQ(# zwJpuiQJP8?X_`#S8b+U_G6=ziYB!xPAcq{)ZJ0bECH@ zYx#`n8^Wzn^J!4>=q^bltNO15ry?0ecSLkjpT@vlid!jk)Fjf7&)q_V5zGs#3N%6* zbW~7Hg=&P0&~Y(|g>$hC9FL?;ttzPDZbpZu9OLb33^e2;FNTGJxScp1&q4M+y2ntQ z?C(=hpU$3~`Thx0eHwi0x`q+!d5k@|0_WHe%sG3e-s^MM`xM-ig!VcIA7H}X1ot~L zg=MLB4w-Q;Bi!!u2|I+Qb;0{{4Q53YX6+4_aXena{nmt*!YG7ua~`qc>o=?@U?rOU znS7%>klzi*muXnbM6i@4FR@s^8vTjDgy&%J?w?`u>NYMDFa_2%0SQ(qJE<3=<8Bzo zfdU60e*y(^$RF%r$kl)p7=7tlCDa$+J7w>}DU(O#~fk>pYuRvHi1E9^msg{tLeV XM&GIRvfA7%00000NkvXXu0mjf&%8>| literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/reddit_moderationlog.png b/r2/r2/public/static/reddit_moderationlog.png new file mode 100755 index 0000000000000000000000000000000000000000..779ad58efc5776825ef81064a042eceba274a928 GIT binary patch literal 649 zcmV;40(Sk0P)sm$HQ(N)Ek< zrc#vXMLdW}TWpphCZsGREkUZr{Mg;M&b;luZ0IGA9rnH1`DVU1->eh_0hG(-dw<@) z-1S-xc+D!@wd^?Z=a`M%%phe@J_EnT0QpH7V3 jcG~XA#&PRl)Zh6(yXt(^KFGF}00000NkvXXu0mjfDwr>g literal 0 HcmV?d00001 diff --git a/r2/r2/templates/modaction.html b/r2/r2/templates/modaction.html new file mode 100755 index 000000000..6a6b809e8 --- /dev/null +++ b/r2/r2/templates/modaction.html @@ -0,0 +1,39 @@ +## The contents of this file are subject to the Common Public Attribution +## License Version 1.0. (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License at +## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public +## License Version 1.1, but Sections 14 and 15 have been added to cover use of +## software over a computer network and provide for limited attribution for the +## Original Developer. In addition, Exhibit A has been modified to be consistent +## with Exhibit B. +## +## Software distributed under the License is distributed on an "AS IS" basis, +## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +## the specific language governing rights and limitations under the License. +## +## The Original Code is Reddit. +## +## The Original Developer is the Initial Developer. The Initial Developer of +## the Original Code is CondeNet, Inc. +## +## All portions of the code written by CondeNet are Copyright (c) 2006-2010 +## CondeNet, Inc. All Rights Reserved. +################################################################################ + +<%namespace file="utils.html" import="timestamp, plain_link"/> + + + ${timestamp(thing.date)} ago + ${thing.mod} + ${thing.button} + ${thing.text} + %if hasattr(thing, 'target_text'): + ${plain_link(thing.target_text, thing.target_path, title=thing.target_title, sr_path=False, cname=False, _class="subreddit hover")} + %elif hasattr(thing, 'target_wrapped_user'): + ${thing.target_wrapped_user} + %endif + %if hasattr(thing, 'details') and thing.details: + (${thing.details}) + %endif + + diff --git a/r2/r2/templates/tablelisting.html b/r2/r2/templates/tablelisting.html new file mode 100755 index 000000000..89916f397 --- /dev/null +++ b/r2/r2/templates/tablelisting.html @@ -0,0 +1,64 @@ +## The contents of this file are subject to the Common Public Attribution +## License Version 1.0. (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License at +## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public +## License Version 1.1, but Sections 14 and 15 have been added to cover use of +## software over a computer network and provide for limited attribution for the +## Original Developer. In addition, Exhibit A has been modified to be consistent +## with Exhibit B. +## +## Software distributed under the License is distributed on an "AS IS" basis, +## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +## the specific language governing rights and limitations under the License. +## +## The Original Code is Reddit. +## +## The Original Developer is the Initial Developer. The Initial Developer of +## the Original Code is CondeNet, Inc. +## +## All portions of the code written by CondeNet are Copyright (c) 2006-2010 +## CondeNet, Inc. All Rights Reserved. +################################################################################ +<%! + from r2.models import Sub + %> +<%namespace file="utils.html" import="plain_link" /> + +<% + _id = ("_%s" % thing.parent_name) if hasattr(thing, 'parent_name') else '' + cls = thing.lookups[0].__class__.__name__.lower() + %> + + + +
+ + %for a in thing.things: + ${a} + %endfor +
+
+ +%if thing.nextprev and (thing.prev or thing.next): +

${_("view more:")} + %if thing.prev: + ${plain_link(_("first"), thing.first, _sr_path = (c.site != Sub), rel="nofollow first")} + | + ${plain_link(_("prev"), thing.prev, _sr_path = (c.site != Sub), rel="nofollow prev")} + %endif + %if thing.prev and thing.next: + | + %endif + %if thing.next: + ${plain_link(_("next"), thing.next, _sr_path = (c.site != Sub), rel="nofollow next")} + %endif +

+%endif +%if not thing.things: +

${_("there doesn't seem to be anything here")}

+%endif