Commit 9093adbc authored by Arno Töll's avatar Arno Töll
Browse files

Add weight to tags, reformat user interfaces to honor that situation and...

Add weight to tags, reformat user interfaces to honor that situation and (re-)move additionally some tags who became obsolete now
parent 431d36e9
...@@ -46,7 +46,7 @@ from debexpo.lib.gnupg import GnuPG ...@@ -46,7 +46,7 @@ from debexpo.lib.gnupg import GnuPG
from debexpo.model import meta from debexpo.model import meta
from debexpo.model.users import User from debexpo.model.users import User
from debexpo.model.user_countries import UserCountry from debexpo.model.user_countries import UserCountry
from debexpo.model.sponsor_metrics import SponsorMetrics, SponsorTags from debexpo.model.sponsor_metrics import SponsorMetrics, SponsorMetricsTags, SponsorTags
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
...@@ -183,16 +183,11 @@ class MyController(BaseController): ...@@ -183,16 +183,11 @@ class MyController(BaseController):
else: else:
sm.guidelines = constants.SPONSOR_GUIDELINES_TYPE_NONE sm.guidelines = constants.SPONSOR_GUIDELINES_TYPE_NONE
for tag in meta.session.query(SponsorTags).all():
for tag_set in self.form_result['social_requirements_tags']: if tag.tag in self.form_result:
metrics = SponsorTags(tag_type=constants.SPONSOR_METRICS_TYPE_SOCIAL, tag=tag_set) log.debug("Weighten tag %s to %s" % (tag.tag, self.form_result[tag.tag]))
sm.tags.append(metrics) metrics = SponsorMetricsTags(tag=tag.tag, user_id=session['user_id'], weight=self.form_result[tag.tag])
#log.debug(tag_set) sm.tags.append(metrics)
for tag_set in self.form_result['package_technical_requirements']:
metrics = SponsorTags(tag_type=constants.SPONSOR_METRICS_TYPE_TECHNICAL, tag=tag_set)
sm.tags.append(metrics)
#log.debug(tag_set)
meta.session.merge(sm) meta.session.merge(sm)
meta.session.commit() meta.session.commit()
...@@ -277,12 +272,15 @@ class MyController(BaseController): ...@@ -277,12 +272,15 @@ class MyController(BaseController):
(constants.SPONSOR_CONTACT_METHOD_JABBER, _('Jabber')), (constants.SPONSOR_CONTACT_METHOD_JABBER, _('Jabber')),
] ]
self.metrics = meta.session.query(SponsorMetrics).options(joinedload(SponsorMetrics.tags)).filter_by(user_id=session['user_id']).first() c.metrics = meta.session.query(SponsorMetrics)\
.options(joinedload(SponsorMetrics.user))\
.options(joinedload(SponsorMetrics.tags))\
.filter_by(user_id = session['user_id'])\
.first()
c.technical_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_TECHNICAL).all() c.technical_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_TECHNICAL).all()
c.social_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_SOCIAL).all() c.social_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_SOCIAL).all()
if not self.metrics: if not c.metrics:
self.metrics = SponsorMetrics() c.metrics = SponsorMetrics()
c.metrics = self.metrics
log.debug('Rendering page') log.debug('Rendering page')
return render('/my/index.mako') return render('/my/index.mako')
...@@ -43,7 +43,7 @@ from debexpo.lib import constants ...@@ -43,7 +43,7 @@ from debexpo.lib import constants
from debexpo.model.sponsor_metrics import SponsorMetrics, SponsorTags, SponsorMetricsTags from debexpo.model.sponsor_metrics import SponsorMetrics, SponsorTags, SponsorMetricsTags
from debexpo.model.users import User from debexpo.model.users import User
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload, contains_eager
from debexpo.model import meta from debexpo.model import meta
...@@ -104,20 +104,33 @@ class SponsorController(BaseController): ...@@ -104,20 +104,33 @@ class SponsorController(BaseController):
c.custom_html = '' c.custom_html = ''
c.constants = constants c.constants = constants
query = meta.session.query(SponsorMetrics).join(SponsorMetrics.tags) c.sponsors = meta.session.query(SponsorMetrics)\
.options(joinedload(SponsorMetrics.user))\
.options(joinedload(SponsorMetrics.tags))\
.filter(SponsorMetrics.availability >= constants.SPONSOR_METRICS_RESTRICTED)\
.all()
# The select above works fine, except that it sucks.
# It suffers from a poor performance and it could be significantly improved by querying the tag
# labels and descriptions (i.e. the SponsorTags table by joining them with SponsorMetricsTags.
# However the resulting result set does not quite look like what I imagine. Feel free to replace it
# by something which actually works.
#c.sponsors = meta.session.query(SponsorMetrics, SponsorMetricsTags, SponsorTags, User)\
# .join(User)\
# .join(SponsorMetricsTags)\
# .join(SponsorTags)\
# .filter(SponsorMetrics.availability >= constants.SPONSOR_METRICS_RESTRICTED)\
if 'sponsor_filters' in session: if 'sponsor_filters' in session:
log.debug("Applying tag filter") log.debug("Applying tag filter")
c.sponsor_filter = session['sponsor_filters'] c.sponsor_filter = session['sponsor_filters']
# This does not work for 1+ tags. Hence do the filtering
# in the template. If you happen to know a SQL query which
# allpws to filter all tags fo all developers at once, go on :)
#for filtered_tag in session['sponsor_filters']:
# query = query.filter(SponsorTags.tag == filtered_tag)
else: else:
c.sponsor_filter = [] c.sponsor_filter = []
c.sponsors = query.filter(SponsorMetrics.availability >= constants.SPONSOR_METRICS_RESTRICTED) \
.join(User)
c.technical_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_TECHNICAL).all() c.technical_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_TECHNICAL).all()
c.social_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_SOCIAL).all() c.social_tags = meta.session.query(SponsorTags).filter_by(tag_type=constants.SPONSOR_METRICS_TYPE_SOCIAL).all()
return render('/sponsor/index.mako') return render('/sponsor/index.mako')
...@@ -39,11 +39,14 @@ __license__ = 'MIT' ...@@ -39,11 +39,14 @@ __license__ = 'MIT'
import formencode import formencode
from pylons import config from pylons import config
from debexpo.lib.base import meta
from debexpo.lib import constants from debexpo.lib import constants
from debexpo.lib.validators import NewEmailToSystem, GpgKey, \ from debexpo.lib.validators import NewEmailToSystem, GpgKey, \
CurrentPassword, CheckBox, NewNameToSystem, ValidateSponsorEmail, \ CurrentPassword, CheckBox, NewNameToSystem, ValidateSponsorEmail, \
ValidatePackagingGuidelines, DummyValidator ValidatePackagingGuidelines, DummyValidator
from debexpo.model.sponsor_metrics import SponsorTags
class LoginForm(formencode.Schema): class LoginForm(formencode.Schema):
""" """
...@@ -102,6 +105,12 @@ class MetricsForm(MyForm): ...@@ -102,6 +105,12 @@ class MetricsForm(MyForm):
""" """
Schema for updating the metrics in the controller Schema for updating the metrics in the controller
""" """
def __init__(self, *args, **kwargs):
for tag in meta.session.query(SponsorTags).all():
kwargs[tag.tag] = formencode.validators.Number(min=-10, max=10, not_empty=True)
MyForm.__init__(self, *args, **kwargs)
preferred_contact_method = formencode.compound.All( preferred_contact_method = formencode.compound.All(
formencode.validators.OneOf([ formencode.validators.OneOf([
constants.SPONSOR_CONTACT_METHOD_NONE, constants.SPONSOR_CONTACT_METHOD_NONE,
...@@ -121,8 +130,6 @@ class MetricsForm(MyForm): ...@@ -121,8 +130,6 @@ class MetricsForm(MyForm):
constants.SPONSOR_METRICS_PRIVATE, constants.SPONSOR_METRICS_PRIVATE,
constants.SPONSOR_METRICS_RESTRICTED, constants.SPONSOR_METRICS_RESTRICTED,
constants.SPONSOR_METRICS_PUBLIC]), formencode.validators.Int(not_empty=True)) constants.SPONSOR_METRICS_PUBLIC]), formencode.validators.Int(not_empty=True))
package_technical_requirements = formencode.validators.Set
social_requirements_tags = formencode.validators.Set
social_requirements = formencode.validators.String() social_requirements = formencode.validators.String()
# Postpone validation of packaging_guideline_text, as its validation # Postpone validation of packaging_guideline_text, as its validation
......
...@@ -10,15 +10,14 @@ TAGS = { ...@@ -10,15 +10,14 @@ TAGS = {
('QA uploads','qa', 'Your package is a <a href="http://www.debian.org/doc/manuals/developers-reference/pkgs.html#nmu-qa-upload">QA upload</a>'), ('QA uploads','qa', 'Your package is a <a href="http://www.debian.org/doc/manuals/developers-reference/pkgs.html#nmu-qa-upload">QA upload</a>'),
('Backports','backports', 'Your package is a <a href="http://backports-master.debian.org/">backported package</a>'), ('Backports','backports', 'Your package is a <a href="http://backports-master.debian.org/">backported package</a>'),
('Modified tarballs (but good reasons)','modified-tarballs', 'Your package modified the original source tarball somehow in a way, it does not match the original checksum anymore, but you have a <a href="http://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#bpp-origtargz">good reason</a> to do so'), ('Modified tarballs (but good reasons)','modified-tarballs', 'Your package modified the original source tarball somehow in a way, it does not match the original checksum anymore, but you have a <a href="http://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#bpp-origtargz">good reason</a> to do so'),
('Library package', 'library-package', 'You are packaging a <a href="http://www.debian.org/doc/debian-policy/ch-sharedlibs.html">policy compliant library</a>'),
('VCS snapshot tarballs','vcs-tarball', 'Your package is not based on a original source tarball at all, but is based on a VCS snapshot',), ('VCS snapshot tarballs','vcs-tarball', 'Your package is not based on a original source tarball at all, but is based on a VCS snapshot',),
('contrib/non-free packages', 'non-free-package', 'Your package it targetting the <tt>contrib</tt> or <tt>non-free</tt> branches (<a href="http://www.debian.org/doc/debian-policy/ch-archive.html#s-sections">Information</a>)'), ('contrib/non-free packages', 'non-free-package', 'Your package it targetting the <tt>contrib</tt> or <tt>non-free</tt> branches (<a href="http://www.debian.org/doc/debian-policy/ch-archive.html#s-sections">Information</a>)'),
('1.0 format packages', '1.0-format', 'Your package is using the 1.0 format (the traditional source format that is).'), ('1.0 format packages', '1.0-format', 'Your package is using the 1.0 format (the traditional source format that is).'),
('3.0 format packages', '3.0-format', 'Your package is using the <a href="http://wiki.debian.org/Projects/DebSrc3.0">3.0/quilt</a> format.'), ('3.0 format packages', '3.0-format', 'Your package is using the <a href="http://wiki.debian.org/Projects/DebSrc3.0">3.0/quilt</a> format.'),
('Allow embedded code copies', 'embedded-code-copies', 'Your package can <a href="http://www.debian.org/doc/debian-policy/ch-source.html#s-embeddedfiles">makes use of embedded code copies in a reasonable way</a>.'), ('Embedded code copies', 'embedded-code-copies', 'Your package <a href="http://www.debian.org/doc/debian-policy/ch-source.html#s-embeddedfiles">makes use of embedded code copies in a reasonable way</a>.'),
('DEP-5 copyright', 'dep5', 'Your package does make use of <a href="http://dep.debian.net/deps/dep5/">DEP-5</a> copyright files.'), ('DEP-5 copyright', 'dep5', 'Your package does make use of <a href="http://dep.debian.net/deps/dep5/">DEP-5</a> copyright files.'),
('Non-DEP5 copyright', 'no-dep5', 'Your package does <em>not</em> make use of <a href="http://dep.debian.net/deps/dep5/">DEP-5</a> copyright files.'),
('No Lintian cleanliness (but good reasons)', 'not-lintian-clean', 'Your package is not <a href="http://lintian.debian.org/">Lintian clean</a> down to the informational level, but you have a good reason why not.'), ('No Lintian cleanliness (but good reasons)', 'not-lintian-clean', 'Your package is not <a href="http://lintian.debian.org/">Lintian clean</a> down to the informational level, but you have a good reason why not.'),
('Library package', 'library-package', 'You are packaging a <a href="http://www.debian.org/doc/debian-policy/ch-sharedlibs.html">policy compliant library</a>'),
], ],
debexpo.lib.constants.SPONSOR_METRICS_TYPE_SOCIAL: [ debexpo.lib.constants.SPONSOR_METRICS_TYPE_SOCIAL: [
...@@ -26,7 +25,7 @@ TAGS = { ...@@ -26,7 +25,7 @@ TAGS = {
('(Willing to be) DM', 'applicant-is-dm', 'You are a <a href="http://wiki.debian.org/DebianMaintainer">Debian Maintainer</a> already, or you plan to become one soon.'), ('(Willing to be) DM', 'applicant-is-dm', 'You are a <a href="http://wiki.debian.org/DebianMaintainer">Debian Maintainer</a> already, or you plan to become one soon.'),
('(Willing to enter) NM', 'applicant-is-nm', 'You are in the <a href="https://nm.debian.org/">New Maintainer</a> process to become a developer already, or you plan to apply soon.'), ('(Willing to enter) NM', 'applicant-is-nm', 'You are in the <a href="https://nm.debian.org/">New Maintainer</a> process to become a developer already, or you plan to apply soon.'),
('Signed GPG key', 'signed-gpg-key', 'Your GPG matches the <a href="http://lists.debian.org/debian-devel-announce/2010/09/msg00003.html">guidelines of the Debian keyring maintainers</a> and/or is signed by any Debian developer.'), ('Signed GPG key', 'signed-gpg-key', 'Your GPG matches the <a href="http://lists.debian.org/debian-devel-announce/2010/09/msg00003.html">guidelines of the Debian keyring maintainers</a> and/or is signed by any Debian developer.'),
('No one time uploads', 'no-one-time-upload', 'You want to maintain the package you want to have sponsored in the forseeable future. Your package is not a single shot.'), ('One time uploads', 'no-one-time-upload', 'Your package is a single shot upload.'),
('Sharing a time zone', 'sharing-time-zone', 'You share a time zone with your sponsors. This can be useful to get together more easily.'), ('Sharing a time zone', 'sharing-time-zone', 'You share a time zone with your sponsors. This can be useful to get together more easily.'),
('Possibility to meet-up', 'possibility-to-meetup', 'You are living close to your sponsor and you are willing to meet him eventually'), ('Possibility to meet-up', 'possibility-to-meetup', 'You are living close to your sponsor and you are willing to meet him eventually'),
('Having already packages in Debian', 'maintainer-already', 'You are living close to your sponsor and you are willing to meet him eventually'), ('Having already packages in Debian', 'maintainer-already', 'You are living close to your sponsor and you are willing to meet him eventually'),
......
...@@ -40,6 +40,7 @@ import datetime ...@@ -40,6 +40,7 @@ import datetime
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy import orm from sqlalchemy import orm
from sqlalchemy.ext.associationproxy import association_proxy
from debexpo.model import meta, OrmObject from debexpo.model import meta, OrmObject
from debexpo.model.users import User from debexpo.model.users import User
...@@ -69,14 +70,22 @@ t_sponsor_metrics_tags = sa.Table( ...@@ -69,14 +70,22 @@ t_sponsor_metrics_tags = sa.Table(
'sponsor_metrics_tags', meta.metadata, 'sponsor_metrics_tags', meta.metadata,
sa.Column('tag', sa.Integer, sa.ForeignKey('sponsor_tags.tag'), primary_key=True), sa.Column('tag', sa.Integer, sa.ForeignKey('sponsor_tags.tag'), primary_key=True),
sa.Column('user_id', sa.Integer, sa.ForeignKey('sponsor_metrics.user_id'), primary_key=True), sa.Column('user_id', sa.Integer, sa.ForeignKey('sponsor_metrics.user_id'), primary_key=True),
sa.Column('weight', sa.Integer),
) )
class SponsorMetrics(OrmObject): class SponsorMetrics(OrmObject):
foreign = ['user'] foreign = ['user']
#tags = orm.relationship('SponsorTags', secondary=t_sponsor_metrics_tags, backref=orm.backref('sponsors', lazy='dynamic'))
def get_all_tags_weighted(self, weight = 0):
if weight > 0:
return [x.tag for x in self.tags if x.weight > 0]
elif weight < 0:
return [x.tag for x in self.tags if x.weight < 0]
else:
return [x.tag for x in self.tags]
def get_all_tags(self): def get_all_tags(self):
return [x.tag for x in self.tags] return get_all_tags_weighted(0)
def get_technical_tags(self): def get_technical_tags(self):
return [x.tag for x in self.get_technical_tags_full()] return [x.tag for x in self.get_technical_tags_full()]
...@@ -85,10 +94,16 @@ class SponsorMetrics(OrmObject): ...@@ -85,10 +94,16 @@ class SponsorMetrics(OrmObject):
return [x.tag for x in self.get_social_tags_full()] return [x.tag for x in self.get_social_tags_full()]
def get_technical_tags_full(self): def get_technical_tags_full(self):
return [x for x in self.tags if x.tag_type == constants.SPONSOR_METRICS_TYPE_TECHNICAL] return [x for x in self.tags if x.full_tag.tag_type == constants.SPONSOR_METRICS_TYPE_TECHNICAL]
def get_social_tags_full(self): def get_social_tags_full(self):
return [x for x in self.tags if x.tag_type == constants.SPONSOR_METRICS_TYPE_SOCIAL] return [x for x in self.tags if x.full_tag.tag_type == constants.SPONSOR_METRICS_TYPE_SOCIAL]
def get_tag_weight(self, tag):
for t in self.tags:
if t.tag == tag:
return t.weight
return 0.0
def get_guidelines(self): def get_guidelines(self):
""" """
...@@ -153,20 +168,24 @@ class SponsorMetrics(OrmObject): ...@@ -153,20 +168,24 @@ class SponsorMetrics(OrmObject):
class SponsorTags(OrmObject): class SponsorTags(OrmObject):
pass pass
#keywords = association_proxy('metrics', 'metric')
class SponsorMetricsTags(OrmObject): class SponsorMetricsTags(OrmObject):
# We need to filter on that object, so we must instantiate the M2M class foreign = ['user', 'tags']
pass
orm.mapper(SponsorMetrics, t_sponsor_metrics, properties={ orm.mapper(SponsorMetrics, t_sponsor_metrics, properties={
'user' : orm.relation(User, backref='sponsor_metrics'), 'tags' : orm.relationship(SponsorMetricsTags),
'tags' : orm.relationship(SponsorTags, secondary=t_sponsor_metrics_tags, backref=orm.backref('sponsors', lazy='joined')) 'user' : orm.relationship(User),
}) })
orm.mapper(SponsorMetricsTags, t_sponsor_metrics_tags)
orm.mapper(SponsorTags, t_sponsor_tags) orm.mapper(SponsorTags, t_sponsor_tags)
orm.mapper(SponsorMetricsTags, t_sponsor_metrics_tags, properties={
'full_tag': orm.relationship(SponsorTags)
})
def create_tags(): def create_tags():
import debexpo.model.data.tags import debexpo.model.data.tags
import logging import logging
......
...@@ -195,23 +195,39 @@ allow_unsigned_uploads = 0 ...@@ -195,23 +195,39 @@ allow_unsigned_uploads = 0
</tr> </tr>
<tr> <tr>
<td> <td>${ _('Type of packages you are interested in') }:</td>
<br /> <td><br />${ h.html.tags.textarea('package_types', c.metrics.types, cols=82, rows=10) }</td>
${ _('Type of packages you are interested in') }:
</td>
<td>
<br />
${ h.html.tags.textarea('package_types', c.metrics.types, cols=82, rows=10) }
</td>
</tr> </tr>
<% oneshot = "Sponsoring requirements" %>
% for requirement in c.technical_tags:
<tr>
<td>${ oneshot | n}<% oneshot = "&nbsp;" %></td>
<td>
% for weight,label in [(-1, _("-")), \
(0, _("~")), \
(1, _("+")) ]:
${ h.html.tags.radio(requirement.tag, value=weight, label=label, checked=(c.metrics.get_tag_weight(requirement.tag) == weight)) }
% endfor
&nbsp; ${ requirement.label }
</td>
</tr>
% endfor
<tr> <tr>
<td>${ _('Packaging types and workflows you are accepting') }:</td> <td>&nbsp;</td>
<td> <td>
% for requirement in c.technical_tags: <ul>
${ h.html.tags.checkbox('package_technical_requirements', value=requirement.tag, label=requirement.label, checked=(requirement.tag in c.metrics.get_technical_tags())) } <li><strong>First column</strong> You are not accepting packages qualifying for that tag.</li>
<br/> <li><strong>Middle column</strong> You have no strong opinion on that tag.</li>
% endfor <li><strong>Last column</strong> You endorse usage of the implied meaning of the tag.</li>
</ul>
</td>
</tr>
<tr>
<td>
${ _("Additional technical notes") }
</td>
<td>
<br /> <br />
% for guideline,label in [(c.constants.SPONSOR_GUIDELINES_TYPE_NONE, _("None")), \ % for guideline,label in [(c.constants.SPONSOR_GUIDELINES_TYPE_NONE, _("None")), \
(c.constants.SPONSOR_GUIDELINES_TYPE_TEXT, _("Free text")), \ (c.constants.SPONSOR_GUIDELINES_TYPE_TEXT, _("Free text")), \
...@@ -228,16 +244,36 @@ allow_unsigned_uploads = 0 ...@@ -228,16 +244,36 @@ allow_unsigned_uploads = 0
</td> </td>
</tr> </tr>
<% oneshot = "Social requirements" %>
% for requirement in c.social_tags:
<tr>
<td>${ oneshot | n}<% oneshot = "&nbsp;" %></td>
<td>
% for weight,label in [(-1, _("-")), \
(0, _("~")), \
(1, _("+")) ]:
${ h.html.tags.radio(requirement.tag, value=weight, label=label, checked=(c.metrics.get_tag_weight(requirement.tag) == weight)) |n}
% endfor
&nbsp; ${ requirement.label }
</td>
</tr>
% endfor
<tr>
<td>&nbsp;</td>
<td>
<ul>
<li><strong>First column</strong> You are not accepting packages qualifying for that tag.</li>
<li><strong>Middle column</strong> You have no strong opinion on that tag.</li>
<li><strong>Last column</strong> You endorse usage of the implied meaning of the tag.</li>
</ul>
</td>
</tr>
<tr> <tr>
<td>${ _('Social requirements for sponsored maintainers') }:</td>
<td> <td>
% for requirement in c.social_tags: ${ _("Additional social notes") }
${ h.html.tags.checkbox('social_requirements_tags', value=requirement.tag, label=requirement.label, checked=(requirement.tag in c.metrics.get_social_tags())) } </td>
<br/> <td>
% endfor <br />${ h.html.tags.textarea('social_requirements', c.metrics.social_requirements, cols=82, rows=10) }
<br />
${ h.html.tags.textarea('social_requirements', c.metrics.social_requirements, cols=82, rows=10) }
</td> </td>
</tr> </tr>
......
...@@ -110,7 +110,7 @@ To help you finding a sponsor interested in your package, they can formulate spo ...@@ -110,7 +110,7 @@ To help you finding a sponsor interested in your package, they can formulate spo
%> %>
% for sponsor in c.sponsors: % for sponsor in c.sponsors:
<% <%
sponsor_tags = set(sponsor.get_all_tags()) sponsor_tags = set(sponsor.get_all_tags_weighted(1))
filters = set(c.sponsor_filter) filters = set(c.sponsor_filter)
%> %>
% if len(filters & sponsor_tags) != len(filters): % if len(filters & sponsor_tags) != len(filters):
...@@ -124,6 +124,7 @@ To help you finding a sponsor interested in your package, they can formulate spo ...@@ -124,6 +124,7 @@ To help you finding a sponsor interested in your package, they can formulate spo
<ul> <ul>
% if sponsor.user.email and sponsor.allowed(c.constants.SPONSOR_CONTACT_METHOD_EMAIL): % if sponsor.user.email and sponsor.allowed(c.constants.SPONSOR_CONTACT_METHOD_EMAIL):
<li>Email: ${ sponsor.user.email } ${ preferred(sponsor.contact == c.constants.SPONSOR_CONTACT_METHOD_EMAIL) }</li> <li>Email: ${ sponsor.user.email } ${ preferred(sponsor.contact == c.constants.SPONSOR_CONTACT_METHOD_EMAIL) }</li>
% endif % endif
% if sponsor.user.ircnick and sponsor.allowed(c.constants.SPONSOR_CONTACT_METHOD_IRC): % if sponsor.user.ircnick and sponsor.allowed(c.constants.SPONSOR_CONTACT_METHOD_IRC):
<li>IRC: ${ sponsor.user.ircnick } ${ preferred(sponsor.contact == c.constants.SPONSOR_CONTACT_METHOD_IRC) }</li> <li>IRC: ${ sponsor.user.ircnick } ${ preferred(sponsor.contact == c.constants.SPONSOR_CONTACT_METHOD_IRC) }</li>
...@@ -137,16 +138,24 @@ To help you finding a sponsor interested in your package, they can formulate spo ...@@ -137,16 +138,24 @@ To help you finding a sponsor interested in your package, they can formulate spo
</td> </td>
<td> <td>
<ul> <ul>
% for requirement in sponsor.get_technical_tags_full(): % for tag in sponsor.get_technical_tags_full():
<li>${ h.tags.link_to( requirement.label, h.url.current(anchor=requirement.tag) )}</li> % if tag.weight > 0:
<li> <span style="color: green;">+ ${ tag.full_tag.label }</span> (<a href="${ h.url.current(anchor=tag.tag) }">?</a>)</li>
% elif tag.weight < 0:
<li> <span style="color: red;">- ${ tag.full_tag.label }</span> (<a href="${ h.url.current(anchor=tag.tag) }">?</a>)</li>
% endif
% endfor % endfor
</ul> </ul>
<p>${ sponsor.get_guidelines() | n}</p> <p>${ sponsor.get_guidelines() | n}</p>
</td> </td>
<td> <td>
<ul> <ul>
% for requirement in sponsor.get_social_tags_full(): % for tag in sponsor.get_social_tags_full():
<li>${ h.tags.link_to( requirement.label, h.url.current(anchor=requirement.tag) )}</li> % if tag.weight > 0:
<li> <span style="color: green;">+ ${ tag.full_tag.label }</span> (<a href="${ h.url.current(anchor=tag.tag) }">?</a>)</li>
% elif tag.weight < 0:
<li> <span style="color: red;">- ${ tag.full_tag.label }</span> (<a href="${ h.url.current(anchor=tag.tag) }">?</a>)</li>
% endif
% endfor % endfor
</ul> </ul>
${ sponsor.get_social_requirements() | n} ${ sponsor.get_social_requirements() | n}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment