Félix Baylac-Jacqué 6 years ago
parent
commit
62699422a3
3 changed files with 180 additions and 35 deletions
  1. 7 0
      ffdnispdb/constants.py
  2. 161 34
      ffdnispdb/forms.py
  3. 12 1
      ffdnispdb/templates/project_form_generic.html

+ 7 - 0
ffdnispdb/constants.py

@@ -26,3 +26,10 @@ LOCALES_FLAGS = {
     'en': 'GB',
     'fr': 'FR',
 }
+
+IPV6_SUPPORT = {
+    1: _('none'),
+    2: _('partial'),
+    3: _('quite good'),
+    4: _('full')
+} 

+ 161 - 34
ffdnispdb/forms.py

@@ -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)
 

+ 12 - 1
ffdnispdb/templates/project_form_generic.html

@@ -35,12 +35,23 @@
           </div>
         </div>
         {{ fm.render_field(form.contact_email) }}
+        {{ fm.render_field(form.chatrooms, class="fieldlist") }}
         {{ fm.render_field(form.main_ml) }}
         {{ fm.render_field(form.creation_date) }}
         {{ fm.render_field(form.step) }}
+        {{ fm.render_field(form.asn) }}
+        {{ fm.render_field(form.arcep_code) }}
+        {{ fm.render_field(form.statutes) }}
+        {{ fm.render_field(form.internal_rules) }}
+        {{ fm.render_field(form.internet_cube) }}
+
         {{ fm.render_field(form.member_count, class_="input-small") }}
         {{ fm.render_field(form.subscriber_count, class_="input-small") }}
-        {{ fm.render_field(form.chatrooms, class="fieldlist") }}
+        {{ fm.render_field(form.xdsl, class_="input-small") }}
+        {{ fm.render_field(form.vpn, class_="input-small") }}
+        {{ fm.render_field(form.wifi, class_="input-small") }}
+        {{ fm.render_field(form.fiber, class_="input-small") }}
+        {{ fm.render_field(form.nlnog_participant) }}
         <div class="control-group required{% if form.covered_areas.errors %} error{% endif %}">
           <label class="control-label" for="coordinates">{{ form.covered_areas.label.text }}</label>
           <div class="controls">