|
@@ -7,7 +7,7 @@ from flask import current_app
|
|
|
from flask.ext.wtf import Form
|
|
|
from wtforms import Form as InsecureForm
|
|
|
from wtforms import (TextField, DateField, DecimalField, IntegerField,
|
|
|
- SelectField, SelectMultipleField, FieldList, FormField)
|
|
|
+ SelectField, SelectMultipleField, FieldList, FormField, BooleanField)
|
|
|
from wtforms.widgets import (TextInput, ListWidget, html_params, HTMLString,
|
|
|
CheckboxInput, Select, TextArea)
|
|
|
from wtforms.validators import (DataRequired, Optional, URL, Email, Length,
|
|
@@ -15,7 +15,7 @@ from wtforms.validators import (DataRequired, Optional, URL, Email, Length,
|
|
|
from flask.ext.babel import lazy_gettext as _, gettext
|
|
|
from babel.support import LazyProxy
|
|
|
from ispformat.validator import validate_geojson
|
|
|
-from .constants import STEPS
|
|
|
+from .constants import STEPS, IPV6_SUPPORT
|
|
|
from .models import ISP
|
|
|
from .utils import check_geojson_spatialite, filesize_fmt
|
|
|
|
|
@@ -135,40 +135,123 @@ STEP_CHOICES = [(k, LazyProxy(lambda k, s: u'%u - %s' % (k, s), k, STEPS[k], ena
|
|
|
|
|
|
|
|
|
class ProjectForm(Form):
|
|
|
- name = TextField(_(u'full name'), description=[_(u'E.g. French Data Network')],
|
|
|
- validators=[DataRequired(), Length(min=2), Unique(ISP, ISP.name)])
|
|
|
- shortname = TextField(_(u'short name'), description=[_(u'E.g. FDN')],
|
|
|
- validators=[Optional(), Length(min=2, max=15), Unique(ISP, ISP.shortname)])
|
|
|
- description = TextField(_(u'description'), description=[None, _(u'Short text describing the project')])
|
|
|
- logo_url = TextField(_(u'logo url'), validators=[Optional(), URL(require_tld=True)])
|
|
|
- website = TextField(_(u'website'), validators=[Optional(), URL(require_tld=True)])
|
|
|
- other_websites = FieldList(MyFormField(OtherWebsites, widget=partial(InputListWidget(), class_='formfield')),
|
|
|
- min_entries=1, widget=InputListWidget(),
|
|
|
- description=[None, _(u'Additional websites that you host (e.g. wiki, etherpad...)')])
|
|
|
+ name = TextField(_(u'full name'),
|
|
|
+ description=[_(u'E.g. French Data Network')],
|
|
|
+ validators=[DataRequired(), Length(min=2),
|
|
|
+ Unique(ISP, ISP.name)])
|
|
|
+
|
|
|
+ shortname = TextField(_(u'short name'),
|
|
|
+ description=[_(u'E.g. FDN')],
|
|
|
+ validators=[Optional(), Length(min=2, max=15), Unique(ISP, ISP.shortname)])
|
|
|
+
|
|
|
+ description = TextField(_(u'description'),
|
|
|
+ description=[None, _(u'Short text describing the project')])
|
|
|
+
|
|
|
+ logo_url = TextField(_(u'logo url'),
|
|
|
+ validators=[Optional(), URL(require_tld=True)])
|
|
|
+
|
|
|
+ website = TextField(_(u'website'),
|
|
|
+ validators=[Optional(), URL(require_tld=True)])
|
|
|
+ other_websites = FieldList(MyFormField(OtherWebsites,
|
|
|
+ widget=partial(InputListWidget(), class_='formfield')),
|
|
|
+ min_entries=1, widget=InputListWidget(),
|
|
|
+ description=[None, _(u'Additional websites that you host (e.g. wiki, etherpad...)')])
|
|
|
+
|
|
|
contact_email = TextField(_(u'contact email'), validators=[Optional(), Email()],
|
|
|
- description=[None, _(u'General contact email address')])
|
|
|
+ description=[None, _(u'General contact email address')])
|
|
|
+
|
|
|
main_ml = TextField(_(u'main mailing list'), validators=[Optional(), Email()],
|
|
|
- description=[None, _(u'Address of your main mailing list')])
|
|
|
- creation_date = DateField(_(u'creation date'), validators=[Optional()], widget=partial(TextInput(), placeholder=_(u'YYYY-mm-dd')),
|
|
|
- description=[None, _(u'Date at which the legal structure for your project was created')])
|
|
|
+ description=[None, _(u'Address of your main mailing list')])
|
|
|
+
|
|
|
+ creation_date = DateField(_(u'creation date'),
|
|
|
+ validators=[Optional()],
|
|
|
+ widget=partial(TextInput(), placeholder=_(u'YYYY-mm-dd')),
|
|
|
+ description=[None, _(u'Date at which the legal structure for your project was created')])
|
|
|
+
|
|
|
chatrooms = FieldList(TextField(_(u'chatrooms')), min_entries=1, widget=InputListWidget(),
|
|
|
- description=[None, _(u'In URI form, e.g. <code>irc://irc.isp.net/#isp</code> or ' +
|
|
|
- '<code>xmpp:isp@chat.isp.net?join</code>')])
|
|
|
- covered_areas = FieldList(MyFormField(CoveredArea, _('Covered Areas'), widget=partial(InputListWidget(), class_='formfield')),
|
|
|
- min_entries=1, widget=InputListWidget(),
|
|
|
- description=[None, _(u'Descriptive name of the covered areas and technologies deployed')])
|
|
|
- latitude = DecimalField(_(u'latitude'), validators=[Optional(), NumberRange(min=-90, max=90)],
|
|
|
- description=[None, _(u'Coordinates of your registered office or usual meeting location. '
|
|
|
- '<strong>Required in order to appear on the map.</strong>')])
|
|
|
- longitude = DecimalField(_(u'longitude'), validators=[Optional(), NumberRange(min=-180, max=180)])
|
|
|
- step = SelectField(_(u'progress step'), choices=STEP_CHOICES, coerce=int)
|
|
|
- member_count = IntegerField(_(u'members'), validators=[Optional(), NumberRange(min=0)],
|
|
|
- description=[None, _('Number of members')])
|
|
|
- subscriber_count = IntegerField(_(u'subscribers'), validators=[Optional(), NumberRange(min=0)],
|
|
|
- description=[None, _('Number of subscribers to an internet access')])
|
|
|
-
|
|
|
- tech_email = TextField(_('Email'), validators=[Email(), DataRequired()], description=[None,
|
|
|
- _('Technical contact, in case of problems with your submission')])
|
|
|
+ description=[None, _(u'In URI form, e.g. <code>irc://irc.isp.net/#isp</code> or ' +
|
|
|
+ '<code>xmpp:isp@chat.isp.net?join</code>')])
|
|
|
+
|
|
|
+ covered_areas = FieldList(MyFormField(CoveredArea, _('Covered Areas'),
|
|
|
+ widget=partial(InputListWidget(), class_='formfield')),
|
|
|
+ min_entries=1, widget=InputListWidget(),
|
|
|
+ description=[None, _(u'Descriptive name of the covered areas and technologies deployed')])
|
|
|
+
|
|
|
+ latitude = DecimalField(_(u'latitude'),
|
|
|
+ validators=[Optional(), NumberRange(min=-90, max=90)],
|
|
|
+ description=[None, _(u'Coordinates of your registered office or usual meeting location. '
|
|
|
+ '<strong>Required in order to appear on the map.</strong>')])
|
|
|
+
|
|
|
+ longitude = DecimalField(_(u'longitude'),
|
|
|
+ validators=[Optional(), NumberRange(min=-180, max=180)])
|
|
|
+
|
|
|
+ step = SelectField(_(u'progress step'),
|
|
|
+ choices=STEP_CHOICES, coerce=int)
|
|
|
+
|
|
|
+ member_count = IntegerField(_(u'members'),
|
|
|
+ validators=[Optional(), NumberRange(min=0)],
|
|
|
+ description=[None, _(u'Number of members')])
|
|
|
+
|
|
|
+ subscriber_count = IntegerField(_(u'subscribers'),
|
|
|
+ validators=[Optional(), NumberRange(min=0)],
|
|
|
+ description=[None, _(u'Number of subscribers to an internet access')])
|
|
|
+
|
|
|
+ tech_email = TextField(_('Email'),
|
|
|
+ validators=[Email(), DataRequired()], description=[None,
|
|
|
+ _('Technical contact, in case of problems with your submission')])
|
|
|
+
|
|
|
+ ########################################
|
|
|
+ # Fields introduced by ISP format V0.2 #
|
|
|
+ ########################################
|
|
|
+ asn = IntegerField(_(u'asn'), validators=[Optional(), NumberRange(min=0)],
|
|
|
+ description=[None, _('Autonomous System (AS) number.')])
|
|
|
+
|
|
|
+ arcep_code = TextField(_(u'arcep code'),
|
|
|
+ validators=[Optional()],
|
|
|
+ description=[None, _(u'The identifier assigned by the ARCEP')])
|
|
|
+
|
|
|
+ xdsl = IntegerField(_(u'xdsl subscribers'),
|
|
|
+ validators=[Optional(), NumberRange(min=0)],
|
|
|
+ description=[None, _(u'Number of xdsl subscribers')])
|
|
|
+
|
|
|
+ vpn = IntegerField(_(u'vpn subscribers'),
|
|
|
+ validators=[Optional(), NumberRange(min=0)],
|
|
|
+ description=[None, _(u'Number of vpn subscribers')])
|
|
|
+
|
|
|
+ wifi = IntegerField(_(u'wifi subscribers'),
|
|
|
+ validators=[Optional(), NumberRange(min=0)],
|
|
|
+ description=[None, _(u'Number of wifi subscribers')])
|
|
|
+
|
|
|
+ fiber = IntegerField(_(u'fiber subscribers'),
|
|
|
+ validators=[Optional(), NumberRange(min=0)],
|
|
|
+ description=[None, _(u'Number of fiber subscribers')])
|
|
|
+
|
|
|
+ statutes = TextField(_(u'statutes',
|
|
|
+ validators=[Optional(), URL(require_tld=True)],
|
|
|
+ description=[None, _(u'URL pointing to the organisation statutes.')]))
|
|
|
+
|
|
|
+ internal_rules = TextField(_(u'internal rules',
|
|
|
+ validators=[Optional(), URL(require_tld=True)],
|
|
|
+ description=[None, _(u'URL pointing to the organisation internal rules.')]))
|
|
|
+
|
|
|
+ internet_cube = BooleanField(_(u'internet cube'),
|
|
|
+ validators=[Optional()],
|
|
|
+ description=[None, _(u'Participating to the internetcube project (collective purchases, install parties)')])
|
|
|
+
|
|
|
+ nlnog_participant = BooleanField(_(u'nlnog participant'),
|
|
|
+ validators=[Optional()],
|
|
|
+ description=[None, _(u'Participating to the NL-NOG RING? See <code>https://ring.nlnog.net/</code>')])
|
|
|
+
|
|
|
+ ipv6_servers = SelectField(_(u'ipv6 servers'),
|
|
|
+ choices=IPV6_SUPPORT,
|
|
|
+ coerce=int,
|
|
|
+ validators=[Optional()],
|
|
|
+ description=[None, _(u'Servers can be reached in IPV6?')])
|
|
|
+
|
|
|
+ ipv6_subscribers = SelectField(_(u'ipv6 subscribers'),
|
|
|
+ choices=IPV6_SUPPORT, validators=[Optional()],
|
|
|
+ coerce=int,
|
|
|
+ description=[None, _(u'Subscribers are provided with IPV6 connectivity?')])
|
|
|
|
|
|
def validate(self, *args, **kwargs):
|
|
|
r = super(ProjectForm, self).validate(*args, **kwargs)
|
|
@@ -195,6 +278,11 @@ class ProjectForm(Form):
|
|
|
|
|
|
json['name'] = self.name.data
|
|
|
|
|
|
+ def optobj(k, d):
|
|
|
+ filtered_none = {k: v for k,v in d.iteritems() if v != None}
|
|
|
+ if filtered_none != {}:
|
|
|
+ json[k] = filtered_none
|
|
|
+
|
|
|
def optstr(k, v):
|
|
|
if k in json or v:
|
|
|
json[k] = v
|
|
@@ -221,11 +309,27 @@ class ProjectForm(Form):
|
|
|
optstr('creationDate', self.creation_date.data.isoformat() if self.creation_date.data else None)
|
|
|
optstr('progressStatus', self.step.data)
|
|
|
optstr('memberCount', self.member_count.data)
|
|
|
- optstr('subscriberCount', self.subscriber_count.data)
|
|
|
optlist('chatrooms', filter(bool, self.chatrooms.data)) # remove empty strings
|
|
|
optstr('coordinates', {'latitude': self.latitude.data, 'longitude': self.longitude.data}
|
|
|
if self.latitude.data else {})
|
|
|
optlist('coveredAreas', list(transform_covered_areas(self.covered_areas.data)))
|
|
|
+
|
|
|
+ optstr('asn', self.asn.data)
|
|
|
+ optstr('arcepCode', self.arcep_code.data)
|
|
|
+ optstr('internetcube', self.internet_cube.data)
|
|
|
+ optstr('nlnogParticipant', self.nlnog_participant)
|
|
|
+ optobj('publicDocuments', {
|
|
|
+ 'statutes': self.statutes.data,
|
|
|
+ 'internalRules': self.internal_rules.data})
|
|
|
+ optobj('subscriberCount', {
|
|
|
+ 'xdsl': self.xdsl.data,
|
|
|
+ 'vpn': self.vpn.data,
|
|
|
+ 'wifi': self.wifi.data,
|
|
|
+ 'fiber': self.fiber.data})
|
|
|
+ optobj('ipv6Support', {
|
|
|
+ 'infra': self.ipv6_servers.data,
|
|
|
+ 'subscribers': self.ipv6_subscribers.data})
|
|
|
+
|
|
|
return json
|
|
|
|
|
|
@classmethod
|
|
@@ -258,6 +362,29 @@ class ProjectForm(Form):
|
|
|
if 'otherWebsites' in json:
|
|
|
setattr(obj, 'other_websites', [{'name': n, 'url': w} for n, w in json['otherWebsites'].iteritems()])
|
|
|
set_attr('covered_areas', 'coveredAreas')
|
|
|
+
|
|
|
+ # V0.2
|
|
|
+ set_attr('asn')
|
|
|
+ set_attr('arcep_code', 'arcepCode')
|
|
|
+ set_attr('internet_cube', 'internetcube')
|
|
|
+ set_attr('nlnog_participant', 'nlnogParticipant')
|
|
|
+ # TODO: refactor that. I don't know python enough to find it but I'm
|
|
|
+ # sure there's a clever trick to make set_attr support nested structures.
|
|
|
+ if 'publicDocuments' in json:
|
|
|
+ pubd = json['publicDocuments']
|
|
|
+ set_attr('statutes', 'statutes', pubd)
|
|
|
+ set_attr('internal_rules', 'internalRules', pubd)
|
|
|
+ if 'ipv6Support' in json:
|
|
|
+ ipd = json['ipv6Support']
|
|
|
+ set_attr('ipv6_servers', 'infra', ipd)
|
|
|
+ set_attr('ipv6_sibscribers', 'subscribers', ipd)
|
|
|
+ if 'subscriberCount' in json:
|
|
|
+ scd = json['subscriberCount']
|
|
|
+ set_attr('xdsl', None, scd)
|
|
|
+ set_attr('vpn', None, scd)
|
|
|
+ set_attr('wifi', None, scd)
|
|
|
+ set_attr('fiber', None, scd)
|
|
|
+
|
|
|
obj.tech_email = isp.tech_email
|
|
|
return cls(obj=obj)
|
|
|
|