""" open/dulcinea/lib/ui/issues.qpy """ from dulcinea.common import format_user from dulcinea.issue import Issue, get_issue_db from dulcinea.user import text_format_user from dulcinea.ui.lib.search import SearchForm from dulcinea.ui.user.util import ensure_admin_access from dulcinea.ui.util import none_quote, format_yes_or_no from qp.fill.directory import Directory from qp.fill.form import Form from qp.fill.html import href from qp.fill.widget import CheckboxWidget, SubmitWidget from qp.fill.widget import StringWidget, TextWidget, RadiobuttonsWidget from qp.mail.send import sendmail from qp.pub.common import get_path, redirect, get_user, header, footer from qp.pub.common import complete_path class IssueDirectory(Directory): def get_exports(self): ensure_admin_access() yield ('', '_q_index', 'Issues', 'Current software issues') yield ('new', 'new', 'New', 'Create a new issue') def _q_index(self): return IssueSearchForm(get_issue_db().get_issues()).handle() def new(self): return issue_form(Issue()) def _q_lookup(self, component): issue = get_issue_db().get_issue(component) if issue: return issue_form(issue) else: return None def issue_link(issue): return href(complete_path('/issues/%s' % issue.get_key()), issue.get_title()) def format_priority (issue): priority = issue.get_priority() if priority: return '%.2f' % priority def format_status:xml(issue): approvers = issue.get_approvers() if approvers: 'Approved by %d of %d' % (len(approvers), len(issue.get_voters())) users = get_issue_db().get_users_on_issue(issue) if users: '
' ', '.join([format_user(user, name=False, email=False) for user in users]) '
' class IssueSearchForm(SearchForm): def get_search_text_fields(self, issue): return [issue.get_key(), str(issue.get_timestamp()), issue.get_title(), (issue.get_description() or ''), ' '.join([text_format_user(user) for user in issue.get_voters()])] def get_title(self): return 'Issues' def format_search_results_headings:xml(self): ''' Title Business Value Cost Priority Status ''' def format_search_results_table_row:xml(self, issue): '%s' % issue_link(issue) '%s' % issue.get_bang_description( issue.get_combined_bang()) '%s' % issue.get_buck_description( issue.get_combined_buck()) '%s' % none_quote(format_priority(issue)) '%s' % none_quote(format_status(issue)) def footer:xml(self, title): href('new', 'Report a new issue.') SearchForm.footer(self, title) def issue_form(issue): form = Form() user = get_user() form.add(StringWidget, 'title', value=issue.get_title(), title='Title', size=70, required=1) form.add(TextWidget, 'description', value=issue.get_description(), title='Description and Comments', rows=20, cols=80) form.add(RadiobuttonsWidget, 'bang', title='Business Value', value=issue.get_individual_bang(user), options=zip(issue.BANG_OPTIONS, issue.BANG_DESCRIPTIONS)) form.add(RadiobuttonsWidget, 'buck', title='Cost Estimate', value=issue.get_individual_buck(user), options=zip(issue.BUCK_OPTIONS, issue.BUCK_DESCRIPTIONS)) form.add(CheckboxWidget,'approval', title='Resolved?', value=issue.is_approved_by(user)) if issue.get_key() is None: form.add(SubmitWidget, 'save', 'Save') else: form.add(SubmitWidget, 'save', 'Update') form.add(SubmitWidget, 'in_progress', 'I\'m on it!') form.add(SubmitWidget, 'cancel', 'Return to issues') if form.get('cancel'): redirect('.') issue_db = get_issue_db() if not form.is_submitted() or form.has_errors(): def render:xml(): if issue.get_key(): title = 'Issue %s' % issue.get_key() else: title = 'New issue' header(title) form.render() voters = issue.get_voters() if voters: '
' '' '' '' '' '' '' '' '' for user in voters: '' '' % format_user(user, name=False, email=False) '' % issue.get_bang_description( issue.get_individual_bang(user)) '' % issue.get_buck_description( issue.get_individual_buck(user)) '' % format_yes_or_no( issue.is_approved_by(user)) '' % format_yes_or_no( issue_db.get_issue_in_progress(user) is issue) '' '' '' '' % issue.get_bang_description( issue.get_combined_bang()) '' % issue.get_buck_description( issue.get_combined_buck()) '' % none_quote( format_priority(issue)) '' '
UserBusiness ValueCostApproved ResolutionThey\'re on it!
%s%s%s%s%s
Combined:%s%sPriority:%s
' '
' footer(title=title) return render() issue.set_title(form['title']) issue.set_description(form['description']) issue.set_bang(user, form['bang']) issue.set_buck(user, form['buck']) issue.set_approval(user, form['approval']) if issue.is_approved_by(user): issue_db.clear_issue_in_progress(user, issue) if form.get('in_progress'): issue_db.set_issue_in_progress(user, issue) if issue.get_key() is None: issue_db.add_issue(issue) url = './' + issue.get_key() else: url = get_path() if issue.is_resolved(): notify_issue_resolved(issue) issue_db.remove_issue(issue) url = '.' redirect(url) def notify_issue_resolved(issue): """ Notify the involved parties that an issue has been resolved """ to_addrs = [user.get_email() for user in issue.get_approvers() if user.get_email()] subject = "RESOLVED: %s" % issue.get_title() body = "" body += 'title: %s\n' % issue.get_title() body += 'timestamp: %s\n' % issue.get_timestamp() body += 'key: %s\n' % issue.get_key() body += 'description:\n%s' % issue.get_description() sendmail(subject, body, to_addrs)