[Cmfcollectorng-cvs] CMFCollectorNG/skins/collectorng_plone aCompact.py,NONE,1.1 batch_macros.pt,NON
Status: Alpha
Brought to you by:
ajung
Update of /cvsroot/cmfcollectorng/CMFCollectorNG/skins/collectorng_plone
In directory sc8-pr-cvs1:/tmp/cvs-serv12134/skins/collectorng_plone
Added Files:
aCompact.py batch_macros.pt check_escalation.py
check_followup_permission.py collector_add_issue.py
collector_add_issue_form.properties
collector_add_issue_form.pt collector_contents.properties
collector_contents.pt collector_edit.py
collector_edit_form.properties collector_edit_form.pt
collector_edit_issue_properties.py collector_icon.gif
collector_issue_add_issue.py collector_issue_cite_comment.py
collector_issue_comment_header.py
collector_issue_contents.properties
collector_issue_contents.pt collector_issue_edit.py
collector_issue_edit_form.properties
collector_issue_edit_form.pt collector_issue_followup.py
collector_issue_followup_form.properties
collector_issue_followup_form.pt collector_issue_icon.gif
collector_issue_notice.dtml
collector_issue_properties_form.properties
collector_issue_properties_form.pt
collector_issue_references_uploads.properties
collector_issue_references_uploads.pt
collector_issue_reject.py
collector_issue_transcript_form.properties
collector_issue_transcript_form.pt
collector_issue_trim_states.py collector_js.pt
collector_macros.pt collector_notifications.py
collector_notifications_form.pt collector_search.py
collector_search_xml.py collector_staff_form.pt
collector_stats.py collector_transcript_form.pt
collector_transcript_view.py collectorng_stylesheet.css
deadline_class_id.py default_search.py default_search_form.pt
format_textblock.py format_value.py getTrackerRole.py
get_substitute.py issue_subtopic_js.py jump_to_ticket.py
migrate_all.py popcalendar.js.dtml render_property.py
render_property_as_select.py search_macros.pt
shorten_string.py tickets_selection.pt
tracker_overview_short.pt translate.py valid_actions_pairs.py
Log Message:
Added cleaned up skin for Plone
--- NEW FILE: aCompact.py ---
## Script (Python) "aCustom.py"
##parameters=thetime,short=0,nobreak=0
##title=Given a DateTime object, return a slightly more compact aCommon repr.
if same_type(thetime, ""):
import DateTime
dt = DateTime.DateTime(thetime)
else:
dt = thetime
if short:
s = dt.strftime(context.datefmt_short)
else:
s = dt.strftime(context.datefmt_long)
if nobreak:
s = s.replace(' ', ' ')
return s
--- NEW FILE: batch_macros.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
i18n:domain="collectorng">
<body>
<!-- Navigation -->
<div class="listingBar"
metal:define-macro="navigation"
tal:define="request request|here/request|container/request|nothing;
batch batch|nothing;
mq python:modules['ZTUtils'].make_query;
url python:request.get('URL0');
currentpage batch/pagenumber;"
tal:condition="python:test(batch.previous or batch.next, 1, 0)">
<span class="previous"
tal:define="p batch/previous | nothing"
tal:condition="p">
<a href=""
tal:attributes="href python: '%s?' % url + mq( request.form, b_start=p.first )">
«
<span i18n:translate="batch_previous" omit-tag="">Previous</span>
<span tal:replace="p/length">n</span>
<span i18n:translate="batch_items" omit-tag="">hits</span>
</a>
</span>
<span class="next"
tal:define="n batch/next | nothing"
tal:condition="n">
<a href=""
tal:attributes="href python: '%s?' % url + mq( request.form, b_start=n.first )">
<span i18n:translate="batch_next" omit-tag="">Next</span>
<span tal:replace="n/length">n</span>
<span i18n:translate="batch_items" omit-tag="">hits</span>
»
</a>
</span>
<!-- Link to first -->
<span tal:condition="python: 1 not in batch.navlist">
<a href=""
i18n:translate="batch_first_page"
tal:attributes="href python: '%s?%s' % (url, batch.pageurl(request.form,1));">1</a>
<span tal:condition="python: 2 not in (batch.prevlist or batch.leapback)"
tal:omit-tag="">
...
</span>
</span>
<!-- Pagelist with quantum leap links to previous pages for quick navigation -->
<span tal:repeat="linklist python:batch.navurls(request.form, batch.leapback)"
tal:condition="batch/leapback"
tal:omit-tag="" >
<a href=""
tal:define="page python:linklist[0];
query python:linklist[1];"
tal:content="page"
tal:attributes="href python: '%s?%s' % (url,query)" >
</a>
..
</span>
<!-- Pagelist with links to previous pages for quick navigation -->
<span tal:repeat="linklist python:batch.prevurls(request.form)"
tal:condition="batch/prevlist"
tal:omit-tag="" >
<a href=""
tal:define="page python:linklist[0];
query python:linklist[1];"
tal:content="page"
tal:attributes="href python: '%s?%s' % (url,query)" >
</a>
</span>
<!-- Current page -->
<span tal:condition="batch/navlist"
tal:omit-tag="">
[<span tal:content="batch/pagenumber">Current page number</span>]
</span>
<!-- Pagelist with links to next pages for quick navigation -->
<span tal:repeat="linklist python:batch.nexturls(request.form)"
tal:condition="batch/nextlist"
tal:omit-tag="" >
<a href=""
tal:define="page python:linklist[0];
query python:linklist[1];"
tal:content="page"
tal:attributes="href python: '%s?%s' % (url,query)" >
</a>
</span>
<!-- Pagelist with quantum leap links to next pages for quick navigation -->
<span tal:repeat="linklist python:batch.navurls(request.form, batch.leapforward)"
tal:condition="batch/leapforward"
tal:omit-tag="" >
..
<a href=""
tal:define="page python:linklist[0];
query python:linklist[1];"
tal:content="page"
tal:attributes="href python: '%s?%s' % (url,query)" >
</a>
</span>
<!-- Link to last -->
<span tal:condition="python:batch.numpages not in batch.navlist">
<span tal:condition="python: batch.numpages - 1 not in (batch.nextlist or batch.leapforward)"
tal:omit-tag="">
...
</span>
<a href=""
i18n:translate="batch_last_page"
tal:attributes="href python: '%s?%s' % (url,batch.pageurl(request.form,batch.numpages));"
tal:content="batch/numpages">Last page</a>
</span>
</div>
</body>
</html>
--- NEW FILE: check_escalation.py ---
# Check for tickets whose deadline is near
class props:
importance = 'sehr wichtig'
def keys(self):
return ('importance', )
query = {
'status' : {'query': ['Accepted', 'Pending']},
}
now = DateTime()
days_before = 5
brains = list(context.get_internal_catalog()(REQUEST=query))
for brain in brains:
ticket = brain.getObject()
diff = ticket.deadline - now
if diff < days_before:
print ticket.getId(), ticket.deadline, ticket.status(), ticket.importance, diff
properties = props()
got = ticket.do_action('comment',
context.trans('Attention: %2.2f days until deadline!') % diff,
properties=properties)
return printed
--- NEW FILE: check_followup_permission.py ---
##parameters=issue,userId
# We need to check for the limit_followups flag of the Collector
# to find out if were are either on the supporters list for this
# issue or if were are in the manager list.
if issue.limit_followups:
if userId in issue.assigned_to() or userId in issue.managers:
return 1
else:
return 0
else:
return 1
--- NEW FILE: collector_add_issue.py ---
## Script (Python) "collector_add_issue.py"
##parameters=properties, upload=None, reference=None, email_submission=None
##title=Submit a Request
from Products.PythonScripts.standard import url_quote_plus
from zLOG import LOG, DEBUG
from AccessControl import getSecurityManager
LOG("CMFCollectorNG::add_issue", DEBUG, "Props: %s" % properties)
LOG("CMFCollectorNG::add_issue", DEBUG, "Emailsubmission: %s" % email_submission)
# Securitychecks for email submissions
if email_submission is not None: # invoked through email submission
if not context.email_submissions:
context.REQUEST.RESPONSE.setStatus(401)
return "No submissions through email allowed"
if context.participation in ('staff', 'authenticated'):
if email_submission.token != context.newissue_token:
context.REQUEST.RESPONSE.setStatus(401)
return "No valid token"
elif context.participation=="anyone":
pass
REQGET = context.REQUEST.get
id, err = context.add_issue(properties=properties,
upload=upload,
reference=reference)
# Remove comments below to automatically accept the issue
#if email_submission is not None:
# ticket = getattr(context, id)
# got = ticket.do_action('accept', "", notification=0)
dest = "%s/%s" % (context.absolute_url(), id)
if err:
dest += '?portal_status_message=' + url_quote_plus(err)
if email_submission is None:
context.REQUEST.RESPONSE.redirect(dest)
else:
return "Issue created"
--- NEW FILE: collector_add_issue_form.properties ---
title=Add new issue
--- NEW FILE: collector_add_issue_form.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main">
<div tal:define="getProp python: here.issuePropertyManager.getPropertyById;
authenticated python: member.has_role('Authenticated')
or member.has_role('Member')">
<span tal:replace="structure here/issue_subtopic_js" />
<script language="javascript" src="collector_js"> </script>
<script language="javascript" src="popcalendar.js"></script>
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<form method="POST" enctype="multipart/form-data"
name="myform" action="collector_add_issue" >
<div class="group">
<span class="legend" i18n:translate="legend_issue_details">Issue details</span>
<div class="row" tal:repeat="field python:['title','description','classification','solution','importance','topic','subtopic','version_info','operating_system','security_related','progress']">
<div class="label" tal:content="python: here.trans(getProp(field).getDescription())" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(getProp(field))" />
</div> <!-- End row -->
<div class="row">
<div class="label" i18n:translate="heading_assign_to">Assign to:</div>
<div class="field">
<select name="properties.assignees:record:list:string" multiple size="3">
<option SELECTED="1"/>
<option tal:content="supporter"
tal:repeat="supporter here/supporters"
/>
</select>
</div>
</div> <!-- End row -->
</div> <!-- End group -->
<div class="group">
<span class="legend" i18n:translate="legend_contact_info">Contact info</span>
<span tal:repeat="field python:['submitter_company','submitter_name','submitter_position',
'submitter_address','submitter_city','submitter_phone','submitter_fax','submitter_email']">
<div class="row" tal:define="property python: getProp(field)" tal:condition="property/getUsed">
<div class="label" tal:content="python: here.trans(property.getDescription())" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(property,member.getProperty(field,''))"
tal:condition="python: field!='submitter_email'"/>
<div class="field" tal:content="structure python: here.render_property(property, member.getProperty('email',''))"
tal:condition="python: field=='submitter_email'"/>
</div> <!-- End row -->
</span>
</div> <!-- End group -->
<div metal:use-macro="here/collector_macros/macros/add_efforts_table">
add_artifacts_table_row
</div>
<span tal:condition="python: here.getTrackerRole(member) != 'Anonymous'">
<div metal:use-macro="here/collector_macros/macros/add_artifacts_table">
add_artifacts_table_row
</div>
</span>
<div metal:use-macro="here/collector_macros/macros/add_references_table">
add_artifacts_table_row
</div>
<div class="row">
<div class="field">
<input type="submit"
value="Submit"
i18n:attributes="value" />
</div>
</div> <!-- End row -->
<script language="javascript">
select_clear(document.myform['properties.subtopic:record:string']);
</script>
</form>
</div>
</div>
</body>
</html>
--- NEW FILE: collector_contents.properties ---
title=Issue Collector
--- NEW FILE: collector_contents.pt ---
<span tal:define="global page_title string:Ticket Browser" />
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main">
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<span tal:define="global search_bar_position python: member.getProperty('collector_search_position')"/>
<div tal:condition="python: search_bar_position!='bottom'" >
<div metal:use-macro="here/search_macros/macros/simplesearchmask" />
<div metal:use-macro="here/search_macros/macros/searchresults" />
</div>
<div tal:condition="python: search_bar_position=='bottom'" >
<div metal:use-macro="here/search_macros/macros/searchresults" />
<div metal:use-macro="here/search_macros/macros/simplesearchmask" />
</div>
</div>
</body>
</html>
--- NEW FILE: collector_edit.py ---
## Script (Python) "collector_edit.py"
##parameters=properties
##title=Configure Collector
from Products.PythonScripts.standard import url_quote_plus
changes = context.edit(properties)
if not changes:
changes = context.trans("No changes")
recatalog = context.REQUEST.get('recatalog', None)
if recatalog:
if recatalog == 1:
context.reinstate_catalog(internal_only=1)
changes += ", reinstated catalog, reindexed internally"
else:
context.reinstate_catalog(internal_only=0)
changes += ", reinstated catalog, reindexed internally and site wide"
msg = '?portal_status_message=%s.' % url_quote_plus(changes)
if properties.has_key('participation'): target='collector_edit_form'
else: target = 'collector_staff_form'
context.REQUEST.RESPONSE.redirect("%s/%s%s"
% (context.absolute_url(), target, msg))
--- NEW FILE: collector_edit_form.properties ---
title=Collector configuration
--- NEW FILE: collector_edit_form.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main">
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<form action="collector_edit" method="post"
tal:define="getProp python: here.collectorPropertyManager.getPropertyById" >
<div class="group">
<span class="legend" i18n:translate="general_settings">General settings</span>
<div class="row" tal:repeat="field python:['title','abbrev','description','email',]">
<div class="label" i18n:translate="" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')"
tal:content="python: here.trans(getProp(field).getDescription())" />
<div class="field" tal:content="structure python: here.render_property(getProp(field), getattr(here, field))" />
</div> <!-- End row -->
</div> <!-- End group -->
<div class="group">
<span class="legend" i18n:translate="other_settings">Other settings</span>
<div class="row" tal:repeat="field python:['dispatching','hostname','limit_followups','participation','recatalog','ticket_offset','email_submissions','newissue_token']">
<div class="label" tal:content="python: here.trans(getProp(field).getDescription())" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(getProp(field), getattr(here, field))" />
</div> <!-- End row -->
</div> <!-- End group -->
<div class="group">
<span class="legend" i18n:translate="look_and_feel">Look and feel</span>
<div class="row" tal:repeat="field python:['datefmt_long','datefmt_short','batch_size']">
<div class="label" tal:content="python: here.trans(getProp(field).getDescription())" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(getProp(field), getattr(here, field))" />
</div> <!-- End row -->
</div> <!-- End group -->
<div class="row">
<div class="label"> </div>
<div class="field">
<input type="submit"
value="Save"
i18n:attributes="value" />
<input type="reset"
value="Reset"
i18n:attributes="value" />
</div>
</div> <!-- End row -->
</form>
</div>
</body>
</html>
--- NEW FILE: collector_edit_issue_properties.py ---
##parameters=properties,REQUEST
ids = []
IPM = context.issuePropertyManager
for item in properties.keys():
f = item.split('_')
id = '_'.join(f[:-1])
field = f[-1]
if not id in ids:
ids.append( id )
for id in ids:
print id
prop = IPM.getPropertyById(id)
old = prop.getDescription()
new = properties[id + '_description']
prop.setDescription(new)
if old != new:
context.transcript.addTranscriptChangeEvent('Issue description',old, new)
old = prop.getValues()
new = properties[id + '_values']
prop.setValues(new)
if old != new:
context.transcript.addTranscriptChangeEvent('Issue values',old, new)
old = prop.getType()
new = properties[id + '_type']
prop.setType(new)
if old != new:
context.transcript.addTranscriptChangeEvent('Issue type',old, new)
old = prop.getDefaultValue()
new = properties[id + '_default']
prop.setDefaultValue(new)
if old != new:
context.transcript.addTranscriptChangeEvent('Issue default',old, new)
old = prop.getMandatory()
new = properties.get(id + '_mandatory', 0)
if new in ('on',1,'1'):
prop.setMandatory(1)
new = 1
else:
prop.setMandatory(0)
new = 0
if old != new:
context.transcript.addTranscriptChangeEvent('Issue mandatory',old, new)
old = prop.getUsed()
new = properties.get(id + '_used', 0)
if new in ('on',1,'1'):
prop.setUsed(1)
new = 1
else:
prop.setUsed(0)
new = 0
if old != new:
context.transcript.addTranscriptChangeEvent('Issue used',old, new)
REQUEST.RESPONSE.redirect('collector_issue_properties_form?portal_status_message=Changes+saved')
--- NEW FILE: collector_icon.gif ---
(This appears to be a binary file; contents omitted.)
--- NEW FILE: collector_issue_add_issue.py ---
## Script (Python) "collector_issue_add_issue.py"
##title=Submit a Request
typeinfo = context.portal_types.getTypeInfo('CollectorNG')
addissue = typeinfo.getActionById('addissue')
context.REQUEST.RESPONSE.redirect("%s/%s"
% (context.aq_parent.absolute_url(),
addissue))
--- NEW FILE: collector_issue_cite_comment.py ---
## Script (Python) "collector_issue_cite_comment.py"
##parameters=
##title=Redirect to issue contents with cite parameter
context.REQUEST.RESPONSE.redirect(context.absolute_url()
+ '?do_cite=1#comment')
--- NEW FILE: collector_issue_comment_header.py ---
## Script (Python) "collector_issue_comment_header.py"
##title=Form the header for a new comment entry in an issue
##bind container=container
##bind context=context
##parameters=type
"""Return text for the header of a new comment entry in an issue."""
from DateTime import DateTime
import string
user = context.REQUEST.AUTHENTICATED_USER
if string.lower(type) == "comment":
# We number the comments (sequence_number is incremented by add_comment)
lead = "<hr> " + type + " #" + str(context.sequence_number)
else:
# ... but don't number the other entries.
lead = type
return "%s by %s on %s ==>" % (lead, str(user), DateTime().aCommon())
--- NEW FILE: collector_issue_contents.properties ---
title=Issue contents
--- NEW FILE: collector_issue_contents.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main">
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<metal:block tal:condition="here/isVisibleFor">
<div metal:use-macro="here/collector_macros/macros/issue_header" />
<div class="group">
<span class="legend" i18n:translate="legend_history">History</span>
<div metal:use-macro="here/collector_macros/macros/transcript_plain"/>
</div> <!-- End group -->
</metal:block>
<div class="no_permission"
tal:condition="not: here/isVisibleFor"
i18n:translate="issue_no_permission">
You do not have permission to view this issue.
</div>
</div>
</body>
</html>
--- NEW FILE: collector_issue_edit.py ---
## Script (Python) "collector_issue_edit.py"
##parameters=properties
##title=Submit a Request
from Products.PythonScripts.standard import url_quote_plus
changed = context.edit(properties)
whence = context.absolute_url()
if changed:
msg = url_quote_plus(changed)
context.REQUEST.RESPONSE.redirect("%s?portal_status_message=%s"
% (whence, msg))
else:
context.REQUEST.RESPONSE.redirect(whence)
--- NEW FILE: collector_issue_edit_form.properties ---
title=Edit issue
--- NEW FILE: collector_issue_edit_form.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main"
tal:define="getProp python: here.issuePropertyManager.getPropertyById">
<script language="javascript" src="collector_js"> </script>
<script language="javascript" src="popcalendar.js"></script>
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<span tal:condition="here/isVisibleFor">
<span tal:replace="structure here/issue_subtopic_js" />
<form method="POST" enctype="multipart/form-data" action="collector_issue_edit"
name="myform"
tal:condition="python: 'TrackerAdmin'== here.getTrackerRole(member) or
'Manager'==here.getTrackerRole(member) or
member.getUserName() in here.assigned_to()">
<div class="group">
<span class="legend" i18n:translate="legend_issue_details">Issue details</span>
<div class="row" tal:repeat="field python:['title','description','solution','importance','topic','subtopic','version_info','operating_system','classification','security_related']">
<div class="label" tal:content="python: here.trans(getProp(field).getDescription())" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(getProp(field),getattr(here, field))" />
</div> <!-- End row -->
</div> <!-- End group -->
<div class="group">
<span class="legend" i18n:translate="legend_contact_info">Contact info</span>
<div class="row" tal:repeat="field python:['submitter_name','submitter_address','submitter_city','submitter_phone','submitter_fax','submitter_email']">
<div class="label" tal:content="python: here.trans(getProp(field).getDescription())" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(getProp(field),getattr(here, field, ''))" tal:condition="python: hasattr(here,field)"/>
<div class="field" tal:content="structure python: here.render_property(getProp(field))" tal:condition="python: hasattr(here, field)==0"/>
</div> <!-- End row -->
</div> <!-- End group -->
<div class="group">
<span class="legend" i18n:translate="legend_work_effort">Work effort</span>
<div class="row" tal:repeat="field python:['hours_required','hours_needed','progress']">
<div class="label" tal:content="python: here.trans(getProp(field).getDescription())" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(getProp(field),getattr(here, field))" />
</div> <!-- End row -->
<div class="row">
<div class="label" tal:content="python: here.trans(getProp('deadline').getDescription())" tal:attributes="class python:test(here.getProp('deadline').getMandatory(), 'label required', 'label')" />
<div class="field" tal:content="structure python: here.render_property(getProp('deadline'),here.aCompact(here.deadline,short=1))" />
</div> <!-- End row -->
</div> <!-- End group -->
<div class="group" tal:condition="python: 'Authenticated' in member.getRoles() and here.dispatching != 'none'">
<span class="legend" i18n:translate="legend_watchlist">Watchlist</span>
<ul tal:repeat="item here/getWatchers">
<li tal:content="item" />
</ul>
</div> <!-- End group -->
<div class="row">
<div class="label"> </div>
<div class="field">
<input class="context"
type="submit"
name="submit"
value="Save"
i18n:attributes="value" />
<input class="context"
type="reset"
name="reset"
value="Reset"
i18n:attributes="value" />
</div>
</div> <!-- End row -->
<script language="javascript">
var topic_el = document.myform['properties.topic:record:string'];
key = topic_el.options[topic_el.selectedIndex].value;
subtopic_el = document.myform['properties.subtopic:record:string'];
select_clear(subtopic_el);
update_subtopic(topic_el);
</script>
<script language="javascript"
tal:content="python: 'select_selected(subtopic_el, \'%s\')' % here.subtopic" >
</script>
</form>
</span>
<div class="card" tal:condition="not: here/isVisibleFor"
i18n:translate="issue_no_permission">
You do not have permission to view this issue.
</div>
</div>
</body>
</html>
--- NEW FILE: collector_issue_followup.py ---
## Script (Python) "collector_issue_followup.py"
##parameters=comment='', action="comment", reference=None, upload=None, assignees=None, properties=None, email_submission=None
##title=Submit a new comment.
from AccessControl import getSecurityManager
from Products.PythonScripts.standard import url_quote_plus
from zLOG import LOG, DEBUG
LOG("CMFCollectorNG::collector_issue_followup", DEBUG, "Props: %s" % properties)
LOG("CMFCollectorNG::collector_issue_followup", DEBUG, "Emailsubmission: %s" % email_submission)
REQUEST = context.REQUEST
# Securitychecks for email submissions
if email_submission is not None: # invoked through email submission
if not context.aq_parent.email_submissions:
context.REQUEST.RESPONSE.setStatus(401)
return "No submissions through email allowed"
if email_submission.cookie != context.cookie:
context.REQUEST.RESPONSE.setStatus(401)
return "Wrong cookie presented"
if email_submission is not None:
status = context.status().lower()
# LOG("CMFCollectorNG::collector_issue_followup", DEBUG, context.submitter_email)
# LOG("CMFCollectorNG::collector_issue_followup", DEBUG, properties.submitter_email)
## JK: uncomment here
# if context.submitter_email == properties.submitter_email:
# if status == 'resolved': action = 'resubmit'
# else: action = 'comment'
# else:
# if status == 'accepted': action = 'resolve'
# else: action = 'comment'
got = context.do_action(action, comment)
else:
got = context.do_action(action,
comment,
assignees=assignees,
properties=properties,
upload=upload,
reference=reference)
destination = REQUEST['HTTP_REFERER']
if got:
destination += '?portal_status_message=' + url_quote_plus(got)
if email_submission is None:
context.REQUEST.RESPONSE.redirect(destination)
else:
return 'Followup created'
--- NEW FILE: collector_issue_followup_form.properties ---
title=Issue followup
--- NEW FILE: collector_issue_followup_form.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main">
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<span tal:define="userId user/getUserName;
global getProp python: here.issuePropertyManager.getPropertyById;
global is_allowed python: here.check_followup_permission(here, userId)"
tal:condition="here/isVisibleFor">
<div tal:condition="not: collector_issue_header_present|nothing">
<!-- Master template has no "header" macro... -->
<div metal:use-macro="here/collector_macros/macros/issue_header">
ISSUE HEADER
</div>
</div>
<div tal:condition="not: is_allowed" class="no_permission"
i18n:translate="issue_no_followup_permission">
You do not have permission to followup on this issue.
</div>
<form method="POST"
enctype="multipart/form-data"
action="collector_issue_followup"
tal:define="actions_pairs here/valid_actions_pairs"
tal:condition="is_allowed">
<div class="group">
<span class="legend" i18n:translate="followup_new_entry_number">New entry
<span i18n:name="number"
tal:content="python: '#%d' % (len(here) + 1)"
tal:omit-tag="">
number
</span>
</span>
<table border="0" cellspacing="2" cellpadding="2">
<tr>
<th i18n:translate="heading_comment">Comment</th>
<td rowspan="3" width="20px"></td>
<th i18n:translate="heading_workflow">Workflow</th>
<td rowspan="3" width="20px"></td>
<th i18n:translate="heading_assign">Assign</th>
</tr>
<div class="row">
<div class="label" i18n:translate="heading_comment">Comment</div>
<div class="field">
<textarea name="comment" rows="13" cols="80" wrap="soft"
tal:content="python: (request.get('do_cite')
and here.cited_text()) or ''"></textarea>
</div>
</div> <!-- End row -->
<div class="row" tal:condition="actions_pairs"> <!-- NOTE: This may look wrong... -->
<div class="label" i18n:translate="heading_workflow">Workflow</div>
<div class="field">
<input type="radio" name="action" value="comment" CHECKED /><br />
<span tal:repeat="pair actions_pairs">
<metal:block tal:condition="python: pair[0] != 'assign'">
<input type="radio"
name="action"
value="#VALUE"
tal:attributes="value python: pair[0]" />
<span i18n:translate="" tal:content="python: pair[1]" />
</metal:block>
</span>
</div>
</div> <!-- End row -->
<div class="row">
<div class="label" i18n:translate="heading_assign">Assign</div>
<div class="field"
tal:define="assigning python: [1 for i in actions_pairs
if i[1] == 'Assign'];
supporters python: sequence.sort(here.aq_parent.supporters)"
tal:condition="assigning">
<select name="assignees:list" MULTIPLE size="5"
tal:attributes="size python:
max(min(len(supporters), 5), 12)">
<option tal:content="supporter"
tal:repeat="supporter supporters"
tal:attributes="selected python:
supporter in here.assigned_to()" />
</select>
</div>
</div> <!-- End row -->
<div class="group">
<div class="row" tal:condition="python: 1 in [ r in user.getRolesInContext(here) for r in ['Manager', 'TrackerAdmin']] or user.getUserName() in here.assigned_to()"
tal:repeat="field python:['hours_required','hours_needed','progress']" >
<div class="label" align="right" tal:content="python: getProp(field).getDescription()" tal:attributes="class python:test(getProp(field).getMandatory(), 'label required', 'label')" />
<div class="field" colspan="2" tal:content="structure python: here.render_property(getProp(field), getattr(here, field))" />
</div> <!-- End row -->
</div> <!-- End group -->
<div class="row">
<div class="label"> </div>
<div class="field">
<input class="context" type="submit" name="submit" value="Save" i18n:attributes="value" />
<input class="context" type="reset" name="reset" value="Reset" i18n:attributes="value" />
</div>
</div> <!-- End row -->
</div> <!-- End group -->
</form>
<div metal:use-macro="here/collector_macros/macros/transcript_plain"/>
</span>
<div class="card" tal:condition="not: here/isVisibleFor"
i18n:translate="issue_no_permission">
You do not have permission to view this issue.
</div>
</div>
</body>
</html>
--- NEW FILE: collector_issue_icon.gif ---
(This appears to be a binary file; contents omitted.)
--- NEW FILE: collector_issue_notice.dtml ---
<dtml-comment>
Form an email message for issue events.
</dtml-comment>
From: <dtml-var sender>
To: <dtml-var recipients>
Subject: <dtml-var subject>
X-Recipients-debug: <dtml-var candidates>
Issue #<dtml-var issue_id> Update (<dtml-var action>) "<dtml-var title size=200>"
<dtml-if security_related> ** Security Related ** (<dtml-if confidential>Confidential<dtml-else>Public</dtml-if>)
</dtml-if> Status <dtml-var status>, <dtml-var topic>/<dtml-var klass> <dtml-var importance>
To followup, visit:
<dtml-var issue_url>
==============================================================
<dtml-var body>
==============================================================
--- NEW FILE: collector_issue_properties_form.properties ---
title=Issue properties
--- NEW FILE: collector_issue_properties_form.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main">
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<form action="collector_edit_issue_properties" method="post">
<div class="group" tal:repeat="category here/issuePropertyManager/getCategories">
<span class="legend" tal:content="category"
i18n:translate="">Topic</span>
<table class="listing">
<tr>
<th i18n:translate="heading_field">Field</th>
<th style="text-align: center"
i18n:translate="heading_text">Text</th>
<th style="text-align: center"
i18n:translate="heading_values">Values</th>
<th style="text-align: center"
i18n:translate="heading_default">Default</th>
<th style="text-align: center"
i18n:translate="heading_type">Type</th>
<th style="text-align: center"
i18n:translate="heading_required">Required</th>
<th style="text-align: center"
i18n:translate="heading_use">Use</th>
</tr>
<tr tal:repeat="prop python: here.issuePropertyManager.getProperties(category=category, used=0)">
<th tal:content="prop/getId"></th>
<td>
<input type="text" size="25" tal:attributes="value prop/getDescription; name string:properties.${prop/getId}_description:record"/>
</td>
<td>
<input type="text" size="40" tal:attributes="value prop/getValues; name string:properties.${prop/getId}_values:record" />
</td>
<td>
<input type="text" size="10" tal:attributes="value prop/getDefaultValue; name string:properties.${prop/getId}_default:record" />
</td>
<td align="center">
<select tal:attributes="name string:properties.${prop/getId}_type:record">
<option tal:repeat="item python: ['text','textarea','date','date_international','int','float','select','select-multiple']"
tal:attributes="SELECTED python: item == prop.getType(); value item"
tal:content="item"/>
</select>
</td>
<td align="center">
<input type="checkbox" tal:attributes="CHECKED prop/getMandatory; name string:properties.${prop/getId}_mandatory:record" />
</td>
<td align="center">
<input type="checkbox" tal:attributes="CHECKED prop/getUsed; name string:properties.${prop/getId}_used:record" />
</td>
</tr>
</table>
<div class="row">
<div class="label"> </div>
<div class="field">
<input class="context" type="submit" value="Save"
i18n:attributes="value" />
<input class="context" type="reset" value="Reset"
i18n:attributes="value" />
</div>
</div>
</div> <!-- End group -->
</form>
</div>
</body>
</html>
--- NEW FILE: collector_issue_references_uploads.properties ---
title=References and uploads
--- NEW FILE: collector_issue_references_uploads.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main">
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<script language="javascript" src="collector_js"></script>
<form method="POST" enctype="multipart/form-data" action="collector_issue_followup" name="myform"
tal:condition="here/isVisibleFor">
<div metal:use-macro="here/collector_macros/macros/issue_references_table"/>
<div metal:use-macro="here/collector_macros/macros/issue_artifacts_table"/>
<span metal:use-macro= "here/collector_macros/macros/add_references_table" />
<span tal:condition="python: here.getTrackerRole(member) != 'Anonymous'">
<span metal:use-macro= "here/collector_macros/macros/add_artifacts_table" />
</span>
<div class="row">
<div class="label"> </div>
<div class="field">
<input class="context" type="submit" name="submit" value="Save" i18n:attributes="value" />
<input class="context" type="reset" name="reset" value="Reset" i18n:attributes="value" />
</div>
</div>
</form>
<div class="card" tal:condition="not: here/isVisibleFor"
i18n:translate="issue_no_permission">
You do not have permission to view this issue.
</div>
</div>
</body>
</html>
--- NEW FILE: collector_issue_reject.py ---
## Script (Python) "collector_issue_reject.py"
##title=Reject a collector issue
context.REQUEST.RESPONSE.redirect(context.absolute_url())
--- NEW FILE: collector_issue_transcript_form.properties ---
title=Issue transcript
--- NEW FILE: collector_issue_transcript_form.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master"
i18n:domain="collectorng">
<body>
<div metal:fill-slot="main" >
<link rel="stylesheet" href="collectorng_stylesheet" type="text/css">
<div class="group" tal:condition="here/isVisibleFor">
<span class="legend" i18n:translate="legen_issue_transcript">Issue transcript</span>
<div metal:use-macro="here/collector_macros/macros/transcript"/>
</div> <!-- End group -->
<div class="card" tal:condition="not: here/isVisibleFor"
i18n:translate="issue_no_permission">
You do not have permission to view this issue.
</div>
</div>
</body>
</html>
--- NEW FILE: collector_issue_trim_states.py ---
## Script (Python) "collector_issue_trim_states.py"
##title=Return massaged list of states of issues in catalog.
# Pare out irrelevant states and trim '_confidential' from the rest.
import string
states = context.portal_catalog.uniqueValuesFor('review_state')
got = []
for i in states:
if i in ['private', 'published', 'pending']:
continue
trim = string.split(i, '_')[0]
if trim not in got:
got.append(trim)
return got
--- NEW FILE: collector_js.pt ---
<metal:block i18n:domain="collectorng">
function show_tickets() {
el = document.myform["reference.tracker:record:string"];
selected = el.selectedIndex;
if (selected == 0) {
alert("<span tal:omit-tag="" i18n:translate="js_no_collector_chosen">Error: No Collector selected.</span>");
return 0;
}
tracker = el.options[selected].value;
url = tracker + "/tickets_selection";
win = open(url, "tickets", "width=600, height=800, scrollbars=yes");
}
function select_selected(el, value) {
/* select a select option by value */
for (num=0; num<span tal:replace="structure string:<" />el.options.length; num++)
if (el.options[num].value == value)
el.options[num].selected = 1;
}
function select_unselect_all(el) {
/* unselect all selected options */
for (var num=0; num<span tal:replace="structure string:<" />el.length; num++) {
el.options[num].selected = 0;
}
}
function select_clear(el) {
/* clear a select element */
while (el.options.length) el.options[0] = null;
}
</metal:block>
--- NEW FILE: collector_macros.pt ---
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
i18n:domain="collectorng">
<body>
<span tal:replace="nothing">
Collector issue macros:
- top_bar
- collector_header
- issue_header
- issue_metadata
- issue_contact
- issue_references_short
- issue_effort
- issue_artifacts_table
- add_artifacts_table
- add_references_table
- add_efforts_table
- issue_references_table
- transcript
- transcript_plain
</span>
<div metal:define-macro="top_bar">
<!-- Top bar -->
<table class="MasterBar" cellpadding="0" cellspacing="0" border="0"
tal:define="uname python: isAnon and 'Guest' or member.getUserName()" >
<tr>
<td width="10%" align="center" >
<span tal:replace="uname" />
(<span i18n:translate=""
tal:omit-tag=""
tal:content="python: here.getTrackerRole(member)" />)
</td>
<td width="15%" align="center">
<p>
<span tal:repeat="bc here/breadcrumbs"
><a class="trackerNavigation" tal:attributes="href string: ${bc/url}/" tal:content="bc/id"
>ID</a><span tal:condition="not: repeat/bc/end"> / </span>
</span>
</p>
</td>
<td width="50%" align="center" class="ActionLink">
<span tal:condition="python: 'Manager' in user.getRoles()">
<span tal:repeat="action folder_actions">
<a class="trackerNavigation" tal:attributes="href action/url"
tal:content="action/name">Folder contents</a>
</span>
<span tal:condition="workflow_actions" >
<span class="ObjectStatus"
i18n:translate="top_bar_obj_status"> </span>
<span class="ObjectStatus"
tal:content="wf_state" >Private</span>
<span tal:repeat="action workflow_actions">
<a class="trackerNavigation"
i18n:translate=""
tal:attributes="href action/url"
tal:content="action/name">Submit</a>
</span>
</span>
</span>
</td>
<td width="15%" align="right">
<span tal:repeat="action user_actions">
<a class="trackerNavigation"
i18n:translate=""
tal:attributes="href action/url"
tal:content="action/name">Login</a>
<span tal:condition="not: repeat/action/end"> | </span>
</span>
<span tal:condition="nothing"><a href="join_form" i18n:translate="top_bar_join_link">Join</a></span>
</td>
</tr>
</table>
</div> <!-- end of topbar -->
<div metal:define-macro="collector_header">
<table cellspacing="0" cellpadding="0" border="0"
class="TrackerBar">
<tr>
<td rowspan="3" width="1%">
<a href="." tal:attributes="href string:${portal_url}/" >
<img src="Zope_logo.gif" alt="Zope Logo" border="0"
tal:attributes="src string:${portal_url}/Zope_logo.gif" />
</a>
</td>
<td class="CollectorDescription" >
<metal:block tal:condition="here/getCollectorTitle|nothing">
<b class="CollectorTitle"
tal:content="structure here/getCollectorTitle|nothing">
DESCRIPTION
</b>
<span id="CollectorDescription"
tal:replace="string: (${here/getCollectorDescription})"
tal:condition="here/getCollectorDescription" />
</metal:block>
</td>
<td rowspan="3" class="TrackerNavigation" align="right" width="30%">
<table border="0">
<metal:block tal:repeat="action object_actions">
<span tal:replace="structure python: '<tr>'" tal:condition="repeat/action/even" />
<td>
<a class="trackerNavigation" tal:attributes="href action/url" tal:content="action/name" />
</td>
<span tal:replace="structure python: '</tr>'" tal:condition="repeat/action/odd" />
</metal:block>
</table>
</td>
</tr>
<tr>
<td class="IssueDescription" >
<metal:block tal:condition="here/getIssueDescription|nothing">
<span i18n:translate="collector_header_issue_number">
Ticket # <span tal:content="here/id" tal:omit-tag="" i18n:name="id">ID</span>:
</span>
<span tal:replace="here/getIssueTitle" />
<span class="confidential"
tal:condition="here/confidential"
i18n:translate="collector_header_confidential">
(Achtung: Dieses Ticket ist als vertraulich eingestuft !!!)
</span>
</metal:block>
</td>
</tr>
<tr class="TrackerPageTitle" >
<td tal:content="page_title|nothing" colspan="1"/>
</tr>
<tr>
<td colspan="3">
<div metal:use-macro="here/collector_macros/macros/top_bar" />
</td>
</tr>
<tr tal:condition="request/portal_status_message|nothing">
<td id="DesktopStatusBar" colspan="3">
<p tal:content="request/portal_status_message"> Status message. </p>
</td>
</tr>
</table>
<br/>
</div> <!-- End macro: collector_header -->
<div metal:define-macro="issue_header">
<div class="group" tal:condition="here/isVisibleFor">
<span class="legend" i18n:translate="summary">Issue Characteristics</span>
<div metal:use-macro="here/collector_macros/macros/issue_metadata"/>
<div metal:use-macro="here/collector_macros/macros/issue_effort"/>
<div metal:use-macro="here/collector_macros/macros/issue_contact"/>
<div metal:use-macro="here/collector_macros/macros/issue_references_short"/>
</div>
</div> <!-- End macro: collector_issue_header -->
<div metal:define-macro="issue_metadata">
<div class="group"
tal:define="getProp python: here.issuePropertyManager.getPropertyById">
<span class="legend" i18n:translate="legend_issue_details">Issue details</span>
<div class="flexpanel">
<div class="row" tal:repeat="item python:['importance','topic','subtopic','version_info', 'operating_system','classification']">
<div class="label"
i18n:translate=""
tal:content="python: here.trans(getProp(item).getDescription()) + ':'"/>
<div class="field">
<div tal:replace="python: here.format_value(getProp(item).getRepresentation(getattr(here, item)))"/>
</div>
</div> <!-- End row -->
<div class="row">
<div class="label"
i18n:translate=""
tal:content="python: here.trans(getProp('security_related').getDescription()) + ':'"/>
<div class="field" tal:content="string:Yes" tal:condition="python: here.security_related==1"
i18n:translate="" />
<div class="field" tal:content="string:No" tal:condition="python: here.security_related==0"
i18n:translate="" />
</div> <!-- End row -->
</div> <!-- End flexpanel -->
<div class="flexpanel">
<div class="row" tal:repeat="item python:['title','description','solution']">
<div class="label"
i18n:translate=""
tal:content="python: here.trans(getProp(item).getDescription()) + ':'"/>
<div class="field">
<div tal:replace="python: here.format_value(getattr(here, item))" tal:condition="python: item != 'description'"/>
<pre tal:condition="python: item == 'description'"
tal:content="python: here.format_textblock(getattr(here, item))" />
</div>
</div> <!-- End row -->
</div> <!-- End flexpanel -->
<div class="row" tal:condition="python: 'Authenticated' in member.getRoles() and here.dispatching != 'none'">
<div class="label"> </div>
<div class="field">
<span tal:condition="not: python: here.isWatcher(member.getProperty('email',''))">
<a class="context" tal:attributes="href string:${here/absolute_url}/watchlist_action"
i18n:translate="issue_metadata_add_to_watchlist">Add issue to watchlist</a>
</span>
<span tal:condition="python: here.isWatcher(member.getProperty('email',''))">
<a class="context" tal:attributes="href string: ${here/absolute_url}/watchlist_action"
i18n:translate="issue_metadata_remove_from_watchlist">Remove issue from watchlist</a>
</span>
</div>
</div> <!-- End row -->
</div> <!-- End group -->
</div> <!-- End macro: issue_metadata -->
<div metal:define-macro="issue_contact">
<div class="group">
<span class="legend" i18n:translate="legend_contact_info">Contact info</span>
<span tal:repeat="item python:['submitter_company','submitter_name','submitter_position','submitter_address','submitter_city','submitter_phone','submitter_fax','submitter_email']" tal:omit-tag="">
<div class="row" tal:condition="python: getattr(here, item, '')">
<div class="label" i18n:translate="" tal:content="python: here.trans(here.issuePropertyManager.getPropertyById(item).getDescription())" />
<div class="field">
<span tal:replace="python: getattr(here, item)"/>
</div>
</div> <!-- End row -->
</span> <!-- End repeat block -->
</div> <!-- End group -->
</div> <!-- End macro: issue_contact -->
<div metal:define-macro="issue_references_short">
<div class="group">
<span class="legend" i18n:translate="legend_references_uploads">References/Uploads</span>
<div class="row">
<div class="label"><a tal:attributes="href string: ${here/absolute_url}/collector_issue_references_uploads"
i18n:translate="issues_references_uploads">Uploads</a></div>
<div class="field">
<span tal:replace="python: len(here.objectValues())" />
</div>
</div> <!-- End row -->
<div class="row">
<div class="label"><a tal:attributes="href string: ${here/absolute_url}/collector_issue_references_uploads"
i18n:translate="issues_references_upload_references">References</a></div>
<div class="field">
<span tal:replace="python: len(here.references)" />
</div>
</div> <!-- End row -->
</div> <!-- End group -->
</div> <!-- End macro: issue_references_short -->
<div metal:define-macro="issue_effort">
<div class="group">
<span class="legend" i18n:translate="legend_progress">Progress</span>
<div class="flexpanel">
<div class="row">
<div class="label" i18n:translate="issue_effort_status">Status:</div>
<div class="field" i18n:translate=""
tal:content="here/status"/>
</div> <!-- End row -->
<div class="row">
<div class="label" i18n:translate="issue_effort_progress">Progress:</div>
<div class="field" tal:content="string: ${here/progress} %"/>
</div> <!-- End row -->
<div class="row" tal:repeat="item python:['hours_needed']">
<div class="label"
i18n:translate=""
tal:content="python: here.trans(here.issuePropertyManager.getPropertyById(item).getDescription()) + ':'"/>
<div class="field" tal:content="python: getattr(here, item)"/>
</div> <!-- End row -->
<div class="row">
<div class="label" i18n:translate="Created">Created:</div>
<div class="field" tal:content="structure python: here.aCompact(here.created())"/>
</div> <!-- End row -->
<div class="row">
<div class="label" i18n:translate="deadline">Deadline:</div>
<div class="field" tal:content="structure python: here.aCompact(here.deadline, short=1)"/>
</div> <!-- End row -->
<div class="row">
<div class="label" i18n:translate="assigned_on">Assigned on:</div>
<div class="field" tal:content="python: ', '.join(here.assigned_to())"/>
</div> <!-- End row -->
<div class="row" tal:repeat="item python:['hours_required']">
<div class="label"
i18n:translate=""
tal:content="python: here.trans(here.issuePropertyManager.getPropertyById(item).getDescription()) + ':'"/>
<div class="field" tal:content="python: getattr(here, item)"/>
</div> <!-- End row -->
<div class="row">
<div class="label" i18n:translate="Modified">Modified:</div>
<div class="field" tal:content="structure python: here.aCompact(here.modified())"/>
</div>
</div> <!-- End flexpanel -->
</div> <!-- End group -->
</div> <!-- End macro: issue_effort -->
<div metal:define-macro="issue_artifacts_table">
<div class="group">
<span class="legend" i18n:translate="legend_uploads">Uploads</span>
<div class="row" tal:repeat="item here/objectValues">
<div class="label">
<span tal:define="icon item/getIcon|item/icon|nothing">
<span tal:condition="icon">
<a href="" tal:attributes="href item/absolute_url">
<img src="" alt="" border="0"
tal:attributes="src python: here.portal_url() + '/' + icon;
alt item/Type|nothing" />
</a>
</span>
<a href="ITEM URL"
tal:attributes="href item/absolute_url"
tal:content="item/id">ITEM ID</a>
<span tal:replace="python: '(%s, %s)' % (here.aCompact(item.created(),short=0), item.Creator())" />
<a i18n:translate="issue_artifacts_table_info_link"
tal:attributes="href python:item.absolute_url() + '/view'">[Info]</a>
</span>
</div>
<div class="field">
<span tal:replace="item/description"> DESCRIPTION</span>
</div>
</div> <!-- End row -->
<span i18n:translate="issue_artifacts_table_no_uploads_available"
tal:condition="not: here/objectValues">No uploads available</span>
</div> <!-- End group -->
</div> <!-- End macro: issue_artifacts_table -->
<div metal:define-macro="add_artifacts_table">
<div class="group">
<span class="legend" i18n:translate="legend_artifacts_upload">Upload files or images</span>
<div class="row">
<div class="label"> </div>
<div class="field"><input type="file" name="upload.file:record" size="60"/></div>
</div> <!-- End row -->
<div class="row">
<div class="label"> </div>
<div class="field">
<div class="row">
<div class="label">
<span i18n:translate="add_artifacts_table_image">Image</span>
</div>
<div class="field">
<input type="radio" name="upload.filetype:record" value="Image" checked="1"/>
</div>
</div> <!-- End row -->
<div class="row">
<div class="label">
<span i18n:translate="add_artifacts_table_file">File or</span>
</div>
<div class="field">
<input type="radio" name="upload.filetype:record" value="File" />
</div>
</div> <!-- End row -->
...
[truncated message content] |