def take_ownership_form(object): form = T.form(class_='small', action=object.uri, method='post')( T.div(class_='fields')( T.button(type='submit', name='act', value='take_ownership')('Take Ownership'), ), ) return form
def __init__(self, title='pushmaster'): super(Document, self).__init__() self.title = T.title(title) if title else T.title() self.head = T.head( meta_content_type, self.title, favicon, reset_css, jquery_ui_css, pushmaster_css, ) self.dialogs = T.div(id='dialogs') request_form = new_request_form() request_form(id='new-request-form') self.dialogs(request_form) push_form = new_push_form() push_form(id='new-push-form') self.dialogs(push_form) reject_form = reject_request_form() self.dialogs(reject_form) self.body = T.body(session(), navbar(), self.dialogs) self.html(self.head, self.body)
def request_display(request, push): title = T.h2(class_='request-title')( T.span(class_='subject')(request.subject), common.user_home_link(request.owner), common.display_date(request.target_date), ) div = T.div(class_='request')(title) if request.branch: div(T.h3(T.span('Branch: '), T.a(request.branch, href=config.git_branch_url % dict(branch=request.branch)))) if request.reject_reason: div( T.h3('Reject Reason:'), T.p(common.linkify(request.reject_reason), class_='reject-reason'), ) div(T.div(class_='message')(common.linkify(request.message or ''))) if request.urgent: title.attrs['class'] += ' urgent' title(common.request_badges(request)) title(T.span(request.state, class_='state')) if not push or users.get_current_user() == push.owner: div(request_actions_form(request)) return div
def onstage_request_item(request): li = common.request_item(request) if current_user == push.owner: li.children.insert(0, T.div(class_='actions')(mark_tested_form(request), T.span('or', class_='sep'), withdraw_form(request))) elif current_user == request.owner: li.children.insert(0, T.div(class_='actions')(mark_tested_form(request))) return li
def get(self): doc = common.Document(title='pushmaster: recent pushes') pushes = query.open_pushes() doc.body(T.h1('Recent Pushes'), T.ol(map(push_item, pushes), class_='requests')) doc.serialize(self.response.out)
def request_actions_form(request): form = T.form(action=request.uri, method='post', class_='request-actions') if request.state in ('requested', 'rejected'): form(T.button(type='submit', name='act', value='abandon')('Abandon')) return form
def get(self, email): email = urllib.unquote_plus(email) doc = common.Document(title='pushmaster: recent activity: ' + email) doc.body(T.div(class_='bookmarklet')(common.bookmarklet(self.hostname))) user = users.User(email) requests = query.requests_for_user(user) pushes = query.pushes_for_user(user) if requests: doc.body( T.h3('Recent Requests'), T.ol(class_='my requests')(map(request_item, requests)), ) if pushes: doc.body( T.h3('Recent Pushes'), T.ol(class_='pushes')(map(push_item, pushes)), ) doc.serialize(self.response.out)
def get(self): doc = common.Document(title="pushmaster: today's pushes") pushes = query.live_pushes_today() doc.body(T.h1("Today's Pushes"), T.ol(map(push_item_full, pushes))) self.dispatch_daily_push_report_email(doc) doc.serialize(self.response.out)
def session(): user = users.get_current_user() div = T.div(class_='session')( user_home_link(user), T.span(class_='sep')('|'), T.a(href=users.create_logout_url('/'))('Logout') ) return div
def push_item(push): return T.li(class_='push')( T.a(href=push.uri)( common.display_datetime(push.ptime), T.span(' '), T.span(push.name or ''), ), common.user_home_link(push.owner), T.span(class_='state')(common.display_push_state(push)), )
def get(self): requests = query.current_requests() doc = common.Document(title='pushmaster: requests') doc.body( T.h2(('Current Requests (%d)' % len(requests)) if len(requests) > 5 else 'Current Requests'), common.request_list(requests) if requests else T.span('There are no requests at present.'), T.div(common.bookmarklet(self.hostname)), ) doc.serialize(self.response.out)
def accepted_request_item(request): li = common.request_item(request) if current_user == push.owner: li.children.insert(0, T.div(class_='actions')( mark_checked_in_form(request), T.span('or', class_='sep'), withdraw_form(request), T.span('or', class_='sep'), reject_request_link(request), )) return li
def get(self): doc = common.Document(title='pushmaster: pushes') pushes = query.open_pushes() push_list = T.ol(map(push_item, pushes)) doc.body(T.h1('Recent Pushes')) doc.body(push_list) doc.body(common.jquery_js, common.jquery_ui_js, common.pushmaster_js) doc.serialize(self.response.out)
def push_item_full(push): requests = query.push_requests(push) return T.li(class_='push')( T.div( common.display_datetime(push.ptime), T.a(href=push.uri)(push.name or 'push'), common.user_home_link(push.owner, logic.user_info(push.owner)), T.span(class_='state')(common.display_push_state(push)), class_='headline', ), T.ol(map(lambda item: common.request_item(item, full_request=True), requests)) if requests else T.div('No requests.'), )
def new_push_form(): return T.form(action='/pushes', method='post', class_='new-push')( T.div(class_='fields')( T.input(type='hidden', name='act', value='new_push'), T.div(T.label(for_='new-push-name')('Name:')), T.div(T.input(type='text', name='name', class_='push-name', id='new-push-name')), T.div(T.button(type='submit', class_='submit')('Start New Push')), ), )
def render_doc(self, push, current_user, pending_requests): doc = common.Document(title='pushmaster: push: %s %s' % (util.format_datetime(push.ptime), push.name)) doc.funcbar(T.span('|', class_='sep'), common.push_email(push, 'Send Mail to Requesters')) requests = query.push_requests(push) push_div = self.render_push_div(current_user, push, requests, pending_requests) doc.body(push_div) doc.scripts(common.script('/js/push.js')) push_json = ScriptCData('this.push = %s;' % json.dumps(dict(key=str(push.key()), state=push.state))) doc.head(T.script(type='text/javascript')(push_json)) return doc
def sendtostage_form(): return T.form(action='#', method='post', class_='send-to-stage')( T.div(class_='fields')( T.input(type='hidden', name='act', value='sendtostage'), T.div(T.label(for_='dest-stage')('Destination:')), T.div( T.select(name='stage', class_='dest-stage', id='dest-stage')( (T.option(value=stage)(stage)) for stage in model.Push.all_stages ), ), ), T.div(T.button(type='submit', class_='submit')('Mark Deployed to Stage')), )
def request_actions_form(request): form = T.form(action=request.uri, method='post', class_='request-actions') button_count = 0 if request.state in ('requested', 'rejected'): form(T.button(type='submit', name='act', value='abandon')('Abandon')) button_count += 1 elif request.state == 'accepted': if button_count: form(T.span(' or ')) form(T.button(type='submit', name='act', value='markcheckedin')('Mark Checked In')) button_count += 1 elif request.state == 'onstage': if button_count: form(T.span(' or ')) form(T.button(type='submit', name='act', value='marktested')('Mark Tested')) button_count += 1 if request.state in ('accepted', 'checkedin', 'onstage', 'tested'): if button_count: form(T.span(' or ')) form(T.button(type='submit', name='act', value='withdraw')('Withdraw')) button_count += 1 return form
def request_item(request, full_request=False): li = T.li(class_='request clearfix')( display_date(request.target_date), T.span(class_='email')(T.a(href=urls.user_home(request.owner))(logic.user_info(request.owner).full_name), ':'), T.a(href=request.uri, class_='request-subject')(request.subject), ) if full_request: li( T.a(request.branch, href=config.git_branch_url % dict(branch=request.branch)), T.p(class_='content')(request.message), ) if request.target_date > util.tznow().date(): li.attrs['class'] += ' future' if request.urgent: li.attrs['class'] += ' urgent' if request.state == 'rejected': li.attrs['class'] += ' rejected' if request.owner == users.get_current_user(): li.attrs['class'] += ' own' li(request_badges(request), T.span(request.branch, class_='branch'), T.div(linkify(request.message), class_='message')) return li
def push_actions_form(push, requests): form = T.form(action=push.uri, method='post', class_='small') fields = T.div(class_='fields') form(fields) button_count = 0 if push.state in ('accepting', 'onstage') and filter(lambda r: r.state == 'checkedin', requests): if button_count: fields(T.span(' or ')) fields(T.button(type='button', name='sendtostage', id='send-to-stage', value=push.uri)('Mark Deployed to Stage')) button_count +=1 if push.state == 'onstage' and requests and all(r.state == 'tested' for r in requests): if button_count: fields(T.span(' or ')) fields(T.button(type='submit', name='act', value='sendtolive')('Mark Live')) button_count +=1 if push.state in ('accepting', 'onstage'): if button_count: fields(T.span(' or ')) fields(T.button(type='submit', name='act', value='abandon')('Abandon')) button_count +=1 return form
def request_item(request): li = common.request_item(request) if is_push_owner: li.children.insert(0, T.div(class_='actions')( T.form(class_='small', action=request.uri, method='post')( T.div(class_='fields')( T.button(type='submit')('Accept'), common.hidden(push=str(push.key()), act='accept')), ), T.span('or', class_='sep'), reject_request_link(request), ), ) return li
def navbar(current=None): nav = T.div(class_='nav')( T.a(href='/push/current')(T.span('Current Push')), T.span(class_='sep')('|'), T.a(href='/requests')('Requests'), T.span(class_='sep')('|'), T.a(href='/pushes')('Pushes'), T.span(class_='sep')('|'), T.a(href='/lastweek')('Last Week'), ) return nav
def reject_request_form(): return T.form(action='#', method='post', class_='reject-request', id='reject-request-form')( T.div(class_='fields')( hidden(act='reject', push='true', return_url=''), T.h2(class_='subject'), T.label(for_='reject-request-reason')( T.span('Reason:'), T.div(T.textarea(name='reason', id='reject-request-reason')), ), T.div(T.button(type='submit', class_='submit')('Reject')), ), )
def funcbar(): bar = T.div(class_='func')( T.a(id='new-request', href='#')('Make Request'), T.span(class_='sep')('|'), T.a(id='new-push', href='#')('Start Push'), T.span(class_='sep')('|'), T.a(id='details', href='#')(T.span('Show Details', class_='show'), T.span('Hide Details', class_='hide')), ) return bar
def get(self, datestr): from_date, to_date = report_date_range(datestr) doc = common.Document(title='pushmaster: reports') doc.body(T.h1('Report for ', from_date.strftime('%e %b %Y'), ' - ', to_date.strftime('%e %b %Y'))) pushes = query.pushes_for_the_week_of(from_date) for push in pushes: pushdiv = T.div(class_='push') pushdiv(T.h2( T.a(href=push.uri)( push.ltime.replace(tzinfo=timezone.UTC()).astimezone(config.timezone).strftime('%a, %l:%M %p, %e %b %Y'), T.span(' '), push.name or '', ), T.span(' by '), common.display_user_email(push.owner), )) reqlist = T.ol(class_='requests') for request in query.push_requests(push): reqlist(common.request_item(request)) pushdiv(reqlist) doc.body(pushdiv) doc.body(common.jquery_js, common.jquery_ui_js, common.pushmaster_js) doc.serialize(self.response.out)
def get(self): doc = common.Document(title='pushmaster: reports') doc.body(T.h1('Reports')) last_monday = last_monday_datetime() report_dates = [last_monday - datetime.timedelta(days=(7 * n)) for n in xrange(0, 10)] ol = T.ol(class_='reports') for date in report_dates: ol(T.li(T.a(href=urls.report(date))( date.strftime('%e %b %Y'), T.span(' - '), (date + datetime.timedelta(days=6)).strftime('%e %b %Y'), ))) doc.body(ol, common.jquery_js, common.jquery_ui_js, common.pushmaster_js) doc.serialize(self.response.out)
def get(self, datestr=None): if datestr: from_date, to_date = report_date_range(datestr) else: for_date = last_monday_datetime() - datetime.timedelta(days=7) return self.redirect('/lastweek/' + for_date.strftime('%Y%m%d')) pushes = query.pushes_for_the_week_of(from_date) requests = [] for push in pushes: requests.extend(query.push_requests(push)) requests = sorted(requests, key=lambda r: r.mtime) doc = common.Document(title='pushmaster: weekly report: ' + datestr) teams_list = T.ul(class_='teams') doc(teams_list) nothing_messages_list = None for team in config.report_users: team_item = T.li(class_='team')(T.h3(team['name'])) teams_list(team_item) devs_list = T.ul(class_='devs') team_item(devs_list) for dev in sorted(team['dev']): dev_item = T.li(class_='dev')(T.h4(dev)) devs_list(dev_item) dev_requests = filter(lambda r: r.owner.nickname() == dev, requests) if dev_requests: requests_list = T.ol(class_='requests')(map(common.request_item, dev_requests)) dev_item(requests_list) else: # lazy (re)initialize random messages if not nothing_messages_list: nothing_messages_list = list(config.nothing_messages) import random random.shuffle(nothing_messages_list) dev_item(T.div(nothing_messages_list.pop(), class_='nothing')) if 'prod' in team: team_item(T.h4('PM: ' if len(team['prod']) == 1 else 'PMs: ', ', '.join(team['prod']), class_='pm')) doc.serialize(self.response.out)
def render_doc(self, current_user, push, pending_requests): doc = common.Document(title='pushmaster: push: ' + logic.format_datetime(push.ptime)) requests = query.push_requests(push) push_div = self.render_push_div(current_user, push, requests, pending_requests) doc.body(push_div) doc.body(common.jquery_js, common.jquery_ui_js, common.pushmaster_js, common.script('/js/push.js')) push_json = ScriptCData('this.push = %s;' % json.dumps(dict(key=str(push.key()), state=push.state))) doc.head(T.script(type='text/javascript')(push_json)) return doc
def request_item(request): li = T.li(class_='request')( display_date(request.target_date), T.span(class_='email')(T.a(href=urls.user_home(request.owner))(request.owner.nickname())), T.a(href=request.uri, class_='request-subject')(request.subject), ) if request.target_date > logic.tznow().date(): li.attrs['class'] += ' future' if request.urgent: li.attrs['class'] += ' urgent' if request.state == 'rejected': li.attrs['class'] += ' rejected' if request.owner == users.get_current_user(): li.attrs['class'] += ' own' li(request_badges(request)) return li
def push_pending_list(push, requests): is_push_owner = users.get_current_user() == push.owner def request_item(request): li = common.request_item(request) if is_push_owner: li.children.insert(0, T.div(class_='actions')( T.form(class_='small', action=request.uri, method='post')( T.div(class_='fields')( T.button(type='submit')('Accept'), common.hidden(push=str(push.key()), act='accept')), ), T.span('or', class_='sep'), reject_request_link(request), ), ) return li ol = T.ol(class_='requests') if requests: ol(map(request_item, requests)) return ol