示例#1
0
    def get_context(self):
        context = super(OrganizationDashboardView, self).get_context()

        context['metrics'] = [{
            # 'title': _('Data'),
            'widgets': [
                {
                    'title': _('Datasets'),
                    'metric': 'datasets',
                    'type': 'line',
                    'endpoint': 'datasets.list',
                    'args': {'org': self.organization}
                },
                {
                    'title': _('Reuses'),
                    'metric': 'reuses',
                    'type': 'line',
                    'endpoint': 'reuses.list',
                    'args': {'org': self.organization}
                },
                {
                    'title': _('Followers'),
                    'metric': 'followers',
                    'type': 'line',
                }
            ]
        }]

        return context
示例#2
0
文件: tasks.py 项目: ldolberg/udata
def notify_membership_response(org, request):
    if request.status == "accepted":
        subject = _('You are now a member of the organization "%(org)s"', org=org)
        template = "new_member"
    else:
        subject, template = _("Membership refused"), "membership_refused"
    mail.send(subject, request.user, template, org=org, request=request)
示例#3
0
文件: tasks.py 项目: grouan/udata
def notify_membership_response(org, request):
    if request.status == 'accepted':
        subject, template = _(
            'You are now a member of the organization "%(org)s"', org=org),
        'new_member'
    else:
        subject, template = _('Membership refused'), 'membership_refused'
    mail.send(subject, request.user, template, org=org, request=request)
示例#4
0
文件: fields.py 项目: grouan/udata
 def pre_validate(self, form):
     if self.data:
         if current_user.is_anonymous():
             raise validators.ValidationError(
                 _('You must be authenticated'))
         elif not admin_permission and current_user.id != self.data.id:
             raise validators.ValidationError(
                 _('You can only set yourself as owner'))
     return True
示例#5
0
    def test_labelize(self):
        self.assertEqual(self.facet.labelize('label', True),
                         'label: {0}'.format(_('yes')))
        self.assertEqual(self.facet.labelize('label', False),
                         'label: {0}'.format(_('no')))

        self.assertEqual(self.facet.labelize('label', 'true'),
                         'label: {0}'.format(_('yes')))
        self.assertEqual(self.facet.labelize('label', 'false'),
                         'label: {0}'.format(_('no')))
示例#6
0
文件: fields.py 项目: guillo-w/udata
 def pre_validate(self, form):
     if not self.data:
         return
     for tag in self.data:
         if not MIN_TAG_LENGTH <= len(tag) <= MAX_TAG_LENGTH:
             message = _('Tag "%(tag)s" must be between %(min)d and %(max)d characters long.',
                 min=MIN_TAG_LENGTH, max=MAX_TAG_LENGTH, tag=tag)
             raise validators.ValidationError(message)
         if not RE_TAG.match(tag):
             message = _('Tag "%(tag)s" must be alphanumeric characters or symbols: -_.', tag=tag)
             raise validators.ValidationError(message)
示例#7
0
文件: tasks.py 项目: guillo-w/udata
def notify_new_follower(follow):
    if isinstance(follow.following, User):
        subject =_('%(user)s followed you', user=follow.follower)
        mail.send(subject, follow.following, 'new_follower', follow=follow)
    elif isinstance(follow.following, Organization):
        subject = _('%(user)s followed your organization', user=follow.follower)
        recipients = [m.user for m in follow.following.members]
        mail.send(subject, recipients, 'new_follower_org', follow=follow)
    elif isinstance(follow.following, Dataset):
        pass
    elif isinstance(follow.following, Reuse):
        pass
示例#8
0
def recent_feed():
    feed = AtomFeed(_('Last datasets'),
                    feed_url=request.url, url=request.url_root)
    datasets = (Dataset.objects.visible().order_by('-created_at')
                .limit(current_site.feed_size))
    for dataset in datasets:
        author = None
        if dataset.organization:
            author = {
                'name': dataset.organization.name,
                'uri': url_for('organizations.show',
                               org=dataset.organization.id, _external=True),
            }
        elif dataset.owner:
            author = {
                'name': dataset.owner.fullname,
                'uri': url_for('users.show',
                               user=dataset.owner.id, _external=True),
            }
        feed.add(dataset.title,
                 render_template('dataset/feed_item.html', dataset=dataset),
                 content_type='html',
                 author=author,
                 url=url_for('datasets.show',
                             dataset=dataset.id, _external=True),
                 updated=dataset.last_modified,
                 published=dataset.created_at)
    return feed.get_response()
示例#9
0
文件: tasks.py 项目: anukat2015/udata
def send_frequency_reminder(self):
    # We exclude irrelevant frequencies.
    frequencies = [f for f in UPDATE_FREQUENCIES.keys()
                   if f not in ('unknown', 'realtime', 'punctual')]
    now = datetime.now()
    reminded_orgs = {}
    reminded_people = []
    allowed_delay = current_app.config['DELAY_BEFORE_REMINDER_NOTIFICATION']
    for org in Organization.objects.visible():
        outdated_datasets = []
        for dataset in Dataset.objects.filter(
                frequency__in=frequencies, organization=org).visible():
            if dataset.next_update + timedelta(days=allowed_delay) < now:
                dataset.outdated = now - dataset.next_update
                dataset.frequency_str = UPDATE_FREQUENCIES[dataset.frequency]
                outdated_datasets.append(dataset)
        if outdated_datasets:
            reminded_orgs[org] = outdated_datasets
    for reminded_org, datasets in reminded_orgs.iteritems():
        print(u'{org.name} will be emailed for {datasets_nb} datasets'.format(
              org=reminded_org, datasets_nb=len(datasets)))
        recipients = [m.user for m in reminded_org.members]
        reminded_people.append(recipients)
        subject = _('You need to update some frequency-based datasets')
        mail.send(subject, recipients, 'frequency_reminder',
                  org=reminded_org, datasets=datasets)

    print('{nb_orgs} orgs concerned'.format(nb_orgs=len(reminded_orgs)))
    reminded_people = flatten(reminded_people)
    print('{nb_emails} people contacted ({nb_emails_twice} twice)'.format(
        nb_emails=len(reminded_people),
        nb_emails_twice=len(reminded_people) - len(Set(reminded_people))))
    print('Done')
示例#10
0
文件: views.py 项目: odtvince/udata
def recent_feed():
    feed = AtomFeed(_('Last reuses'),
                    feed_url=request.url, url=request.url_root)
    reuses = Reuse.objects.visible().order_by('-created_at').limit(15)
    for reuse in reuses:
        author = None
        if reuse.organization:
            author = {
                'name': reuse.organization.name,
                'uri': url_for('organizations.show',
                               org=reuse.organization.id, _external=True),
            }
        elif reuse.owner:
            author = {
                'name': reuse.owner.fullname,
                'uri': url_for('users.show',
                               user=reuse.owner.id, _external=True),
            }
        feed.add(reuse.title,
                 render_template('reuse/feed_item.html', reuse=reuse),
                 content_type='html',
                 author=author,
                 url=url_for('reuses.show', reuse=reuse.id, _external=True),
                 updated=reuse.created_at,
                 published=reuse.created_at)
    return feed.get_response()
示例#11
0
 def pre_validate(self, form):
     if self.data:
         try:
             uris.validate(self.data)
         except uris.ValidationError:
             raise validators.ValidationError(_('Invalid URL'))
     return True
示例#12
0
文件: fields.py 项目: guillo-w/udata
 def iter_choices(self):
     localized_choices = [
         (value, _(label) if label else '', selected)
         for value, label, selected in super(SelectField, self).iter_choices()
     ]
     for value, label, selected in sorted(localized_choices, key=lambda c: c[1]):
         yield (value, label, selected)
示例#13
0
文件: tasks.py 项目: guillo-w/udata
def notify_new_issue(issue):
    if isinstance(issue.subject, (Dataset, Reuse)):
        recipients = owner_recipients(issue)
        subject = _('Your %(type)s have a new issue', type=issue.subject.verbose_name)
        mail.send(subject, recipients, 'new_issue', issue=issue)
    else:
        log.warning('Unrecognized issue subject type %s', type(issue.subject))
示例#14
0
文件: models.py 项目: odtvince/udata
 def mark_as_deleted(self):
     copied_user = copy(self)
     self.email = '{}@deleted'.format(self.id)
     self.password = None
     self.active = False
     self.first_name = 'DELETED'
     self.last_name = 'DELETED'
     self.avatar = None
     self.avatar_url = None
     self.website = None
     self.about = None
     self.extras = None
     self.deleted = datetime.now()
     self.save()
     for organization in self.organizations:
         organization.members = [member
                                 for member in organization.members
                                 if member.user != self]
         organization.save()
     for discussion in Discussion.objects(discussion__posted_by=self):
         for message in discussion.discussion:
             if message.posted_by == self:
                 message.content = 'DELETED'
         discussion.save()
     Follow.objects(follower=self).delete()
     Follow.objects(following=self).delete()
     mail.send(_('Account deletion'), copied_user, 'account_deleted')
示例#15
0
文件: api.py 项目: odtvince/udata
    def get(self, level):
        '''List each zone for a given level with their datasets count'''
        level = GeoLevel.objects.get_or_404(id=level)
        features = []

        for zone in GeoZone.objects(level=level.id):
            # fetch nested levels IDs
            ids = GeoZone.objects(parents=zone.id).only('id').distinct('id')
            ids.append(zone.id)
            # Count datasets in zone
            nb_datasets = Dataset.objects(spatial__zones__in=ids).count()
            features.append({
                'id': zone.id,
                'type': 'Feature',
                'geometry': zone.geom,
                'properties': {
                    'name': _(zone.name),
                    'code': zone.code,
                    'level': zone.level,
                    'datasets': nb_datasets
                }
            })

        return {
            'type': 'FeatureCollection',
            'features': features
        }
示例#16
0
文件: api.py 项目: odtvince/udata
 def get(self):
     '''List all known levels'''
     return [{
         'id': level.id,
         'name': _(level.name),
         'parents': [p.id for p in level.parents],
     } for level in GeoLevel.objects]
示例#17
0
文件: tasks.py 项目: anukat2015/udata
def notify_badge_added(badge):
    if isinstance(badge.subject, Organization):
        recipients = owner_recipients(badge)
        subject = _('Your %(type)s gain a new badge',
                    type=badge.subject.verbose_name)
        mail.send(subject, recipients, 'badge_added', badge=badge)
    else:
        log.warning('Unrecognized badge subject type %s', type(badge.subject))
示例#18
0
文件: fields.py 项目: grouan/udata
 def process_formdata(self, valuelist):
     if valuelist and len(valuelist) == 1 and valuelist[0]:
         try:
             self.data = self.model.objects.get(id=clean_oid(valuelist[0],
                                                             self.model))
         except self.model.DoesNotExist:
             message = _('{0} does not exists').format(self.model.__name__)
             raise validators.ValidationError(message)
示例#19
0
文件: fields.py 项目: grouan/udata
 def __call__(self, **kwargs):
     placeholder = kwargs.pop('placeholder', _(self.label.text))
     if placeholder:
         kwargs['placeholder'] = placeholder
     required = kwargs.pop('required', self.flags.required)
     if required is True:
         kwargs['required'] = required
     return super(FieldHelper, self).__call__(**kwargs)
示例#20
0
文件: fields.py 项目: grouan/udata
 def pre_validate(self, form):
     if self.data:
         if not current_user.is_authenticated():
             raise validators.ValidationError(
                 _('You must be authenticated'))
         elif not OrganizationPrivatePermission(self.data).can():
             raise validators.ValidationError(
                 _("Permission denied for this organization"))
         # Ensure either owner field or this field value is unset
         owner_field = form._fields[self.owner_field]
         if self.raw_data:
             owner_field.data = None
         elif getattr(form._obj, self.short_name) and not owner_field.data:
             pass
         else:
             self.data = None
     return True
示例#21
0
文件: tasks.py 项目: guillo-w/udata
def notify_new_issue_comment(issue, **kwargs):
    if isinstance(issue.subject, (Dataset, Reuse)):
        comment = kwargs['message']
        recipients = owner_recipients(issue) + [m.posted_by for m in issue.discussion]
        recipients = filter(lambda u: u != comment.posted_by, set(recipients))
        subject = _('%(user)s commented your issue', user=comment.posted_by.fullname)
        mail.send(subject, recipients, 'new_issue_comment', issue=issue, comment=comment)
    else:
        log.warning('Unrecognized issue subject type %s', type(issue.subject))
示例#22
0
文件: tasks.py 项目: guillo-w/udata
def notify_issue_closed(issue, **kwargs):
    if isinstance(issue.subject, (Dataset, Reuse)):
        comment = kwargs['message']
        recipients = owner_recipients(issue) + [m.posted_by for m in issue.discussion]
        recipients = filter(lambda u: u != comment.posted_by, set(recipients))
        subject = _('An issue has been closed')
        mail.send(subject, recipients, 'issue_closed', issue=issue, comment=comment)
    else:
        log.warning('Unrecognized issue subject type %s', type(issue.subject))
示例#23
0
文件: tasks.py 项目: anukat2015/udata
def notify_new_discussion(discussion):
    if isinstance(discussion.subject, (Dataset, Reuse)):
        recipients = owner_recipients(discussion)
        subject = _('Your %(type)s have a new discussion',
                    type=discussion.subject.verbose_name)
        mail.send(subject, recipients, 'new_discussion', discussion=discussion)
    else:
        log.warning('Unrecognized discussion subject type %s',
                    type(discussion.subject))
示例#24
0
 def process_formdata(self, valuelist):
     self.data = []
     for name in valuelist:
         role = datastore.find_role(name)
         if role is not None:
             self.data.append(role)
         else:
             raise validators.ValidationError(
                 _('The role {role} does not exist').format(role=name))
示例#25
0
文件: tasks.py 项目: odtvince/udata
def notify_new_reuse(reuse):
    for dataset in reuse.datasets:
        if dataset.organization:
            recipients = [m.user for m in dataset.organization.members]
        elif dataset.owner:
            recipients = dataset.owner
        else:
            recipients = None
        if recipients:
            mail.send(_('New reuse'), recipients, 'new_reuse', reuse=reuse,
                      dataset=dataset)
示例#26
0
文件: models.py 项目: odtvince/udata
 def top_label(self):
     if not self.zones:
         return None
     top = None
     for zone in self.zones:
         if not top:
             top = zone
             continue
         if zone.id in top.parents:
             top = zone
     return _(top.name)
示例#27
0
文件: tasks.py 项目: odtvince/udata
def notify_issue_closed(issue, **kwargs):
    if isinstance(issue.subject, (Dataset, Reuse)):
        message = kwargs['message']
        recipients = owner_recipients(issue) + [
            m.posted_by for m in issue.discussion]
        recipients = [u for u in set(recipients) if u != message.posted_by]
        subject = _('An issue has been closed')
        mail.send(subject, recipients, 'issue_closed',
                  issue=issue, message=message)
    else:
        log.warning('Unrecognized issue subject type %s', type(issue.subject))
示例#28
0
文件: fields.py 项目: grouan/udata
 def process_formdata(self, valuelist):
     if valuelist and len(valuelist) == 1 and valuelist[0]:
         for model in self.models:
             try:
                 self.data = model.objects.get(id=clean_oid(valuelist[0],
                                                            model))
             except model.DoesNotExist:
                 pass
         if not self.data:
             message = _('Model for {0} not found').format(valuelist[0])
             raise validators.ValidationError(message)
示例#29
0
 def pre_validate(self, form):
     if not self.data:
         return
     for tag in self.data:
         if not tags.MIN_TAG_LENGTH <= len(tag) <= tags.MAX_TAG_LENGTH:
             message = _(
                 'Tag "%(tag)s" must be between %(min)d '
                 'and %(max)d characters long.',
                 min=tags.MIN_TAG_LENGTH,
                 max=tags.MAX_TAG_LENGTH, tag=tag)
             raise validators.ValidationError(message)
示例#30
0
文件: search.py 项目: michelbl/udata
def labels_for_zone(zone):
    '''
    Extract all known zone labels
    - main code
    - keys (postal...)
    - name translation in every supported languages
    '''
    labels = set([zone.name, zone.code] + zone.keys_values)
    for lang in current_app.config['LANGUAGES'].keys():
        with language(lang):
            labels.add(_(zone.name))
    return list(labels)
示例#31
0
class OrganizationSearch(search.ModelSearchAdapter):
    model = Organization
    fuzzy = True

    class Meta:
        doc_type = 'Organization'

    name = String(analyzer=search.i18n_analyzer,
                  fields={'raw': String(index='not_analyzed')})
    acronym = String(index='not_analyzed')
    description = String(analyzer=search.i18n_analyzer)
    badges = String(index='not_analyzed')
    url = String(index='not_analyzed')
    created = Date(format='date_hour_minute_second')
    metrics = search.metrics_mapping_for(Organization)
    org_suggest = Completion(analyzer=simple,
                             search_analyzer=simple,
                             payloads=True)

    sorts = {
        'name': 'name.raw',
        'reuses': 'metrics.reuses',
        'datasets': 'metrics.datasets',
        'followers': 'metrics.followers',
        'views': 'metrics.views',
        'created': 'created',
        'last_modified': 'last_modified',
    }
    facets = {
        'reuses':
        RangeFacet(field='metrics.reuses',
                   ranges=[('none', (None, 1)), ('few', (1, 5)),
                           ('many', (5, None))],
                   labels={
                       'none': _('No reuses'),
                       'few': _('Few reuses'),
                       'many': _('Many reuses'),
                   }),
        'badge':
        TermsFacet(field='badges', labelizer=organization_badge_labelizer),
        'datasets':
        RangeFacet(field='metrics.datasets',
                   ranges=[('none', (None, 1)), ('few', (1, 5)),
                           ('many', (5, None))],
                   labels={
                       'none': _('No datasets'),
                       'few': _('Few datasets'),
                       'many': _('Many datasets'),
                   }),
        'followers':
        RangeFacet(field='metrics.followers',
                   ranges=[('none', (None, 1)), ('few', (1, 5)),
                           ('many', (5, None))],
                   labels={
                       'none': _('No followers'),
                       'few': _('Few followers'),
                       'many': _('Many followers'),
                   }),
    }
    boosters = [
        search.GaussDecay('metrics.followers',
                          max_followers,
                          decay=lazy('followers_decay')),
        search.GaussDecay('metrics.reuses',
                          max_reuses,
                          decay=lazy('reuses_decay')),
        search.GaussDecay('metrics.datasets',
                          max_datasets,
                          decay=lazy('datasets_decay')),
    ]

    @classmethod
    def is_indexable(cls, org):
        return org.deleted is None

    @classmethod
    def serialize(cls, organization):
        completions = cls.completer_tokenize(organization.name)
        completions.append(organization.id)
        if organization.acronym:
            completions.append(organization.acronym)
        return {
            'name': organization.name,
            'acronym': organization.acronym,
            'description': organization.description,
            'url': organization.url,
            'metrics': organization.metrics,
            'badges': [badge.kind for badge in organization.badges],
            'created': to_iso_datetime(organization.created_at),
            'org_suggest': {
                'input': completions,
                'output': str(organization.id),
                'payload': {
                    'name': organization.name,
                    'acronym': organization.acronym,
                    'image_url': organization.logo(40, external=True),
                    'slug': organization.slug,
                },
            }
        }
示例#32
0
class UserFollowedUser(FollowActivity, Activity):
    key = 'user:followed'
    label = _('followed a user')
    related_to = db.ReferenceField(User)
    template = 'activity/user.html'
示例#33
0
class DiscussionCreateForm(Form):
    title = fields.StringField(_('Title'), [validators.required()])
    comment = fields.StringField(_('Comment'), [validators.required()])
    subject = fields.DatasetOrReuseField(_('Subject'), [validators.required()])
示例#34
0
文件: search.py 项目: mayjolux/udata
class DatasetSearch(ModelSearchAdapter):
    model = Dataset
    fuzzy = True
    exclude_fields = ['spatial.geom', 'spatial.zones.geom']

    class Meta:
        doc_type = 'Dataset'

    title = String(analyzer=i18n_analyzer,
                   fields={'raw': String(index='not_analyzed')})
    description = String(analyzer=i18n_analyzer)
    license = String(index='not_analyzed')
    frequency = String(index='not_analyzed')
    organization = String(index='not_analyzed')
    owner = String(index='not_analyzed')
    tags = String(index='not_analyzed',
                  fields={'i18n': String(index='not_analyzed')})
    badges = String(index='not_analyzed')
    tag_suggest = Completion(analyzer=simple,
                             search_analyzer=simple,
                             payloads=False)
    resources = Object(
        properties={
            'title': String(),
            'description': String(),
            'format': String(index='not_analyzed')
        })
    format_suggest = Completion(analyzer=simple,
                                search_analyzer=simple,
                                payloads=False)
    dataset_suggest = Completion(analyzer=simple,
                                 search_analyzer=simple,
                                 payloads=True)
    created = Date(format='date_hour_minute_second')
    last_modified = Date(format='date_hour_minute_second')
    metrics = metrics_mapping_for(Dataset)
    featured = Boolean()
    temporal_coverage = Nested(multi=False,
                               properties={
                                   'start': Long(),
                                   'end': Long()
                               })
    temporal_weight = Long(),
    geozones = Object(
        properties={
            'id': String(index='not_analyzed'),
            'name': String(index='not_analyzed'),
            'keys': String(index='not_analyzed')
        })
    granularity = String(index='not_analyzed')
    spatial_weight = Long()
    from_certified = Boolean()

    fields = (
        'geozones.keys^9',
        'geozones.name^9',
        'acronym^7',
        'title^6',
        'tags.i18n^3',
        'description',
    )
    sorts = {
        'title': 'title.raw',
        'created': 'created',
        'last_modified': 'last_modified',
        'reuses': 'metrics.reuses',
        'followers': 'metrics.followers',
        'views': 'metrics.views',
    }

    facets = {
        'tag':
        TermsFacet(field='tags'),
        'badge':
        TermsFacet(field='badges', labelizer=dataset_badge_labelizer),
        'organization':
        ModelTermsFacet(field='organization', model=Organization),
        'owner':
        ModelTermsFacet(field='owner', model=User),
        'license':
        ModelTermsFacet(field='license', model=License),
        'geozone':
        ModelTermsFacet(field='geozones.id',
                        model=GeoZone,
                        labelizer=zone_labelizer),
        'granularity':
        TermsFacet(field='granularity', labelizer=granularity_labelizer),
        'format':
        TermsFacet(field='resources.format'),
        'resource_type':
        TermsFacet(field='resources.type', labelizer=resource_type_labelizer),
        'reuses':
        RangeFacet(field='metrics.reuses',
                   ranges=[('none', (None, 1)), ('few', (1, 5)),
                           ('quite', (5, 10)), ('many', (10, None))],
                   labels={
                       'none': _('Never reused'),
                       'few': _('Little reused'),
                       'quite': _('Quite reused'),
                       'many': _('Heavily reused'),
                   }),
        'temporal_coverage':
        TemporalCoverageFacet(field='temporal_coverage'),
        'featured':
        BoolFacet(field='featured'),
    }
    boosters = [
        BoolBooster('featured', 1.5),
        BoolBooster('from_certified', 1.2),
        ValueFactor('spatial_weight', missing=1),
        ValueFactor('temporal_weight', missing=1),
        GaussDecay('metrics.reuses', max_reuses, decay=0.1),
        GaussDecay('metrics.followers',
                   max_followers,
                   max_followers,
                   decay=0.1),
    ]

    @classmethod
    def is_indexable(cls, dataset):
        return (dataset.deleted is None and len(dataset.resources) > 0
                and not dataset.private)

    @classmethod
    def get_suggest_weight(cls, temporal_weight, spatial_weight, featured):
        '''Compute the suggest part of the indexation payload'''
        featured_weight = 1 if not featured else FEATURED_WEIGHT
        return int(temporal_weight * spatial_weight * featured_weight * 10)

    @classmethod
    def serialize(cls, dataset):
        organization = None
        owner = None
        image_url = None
        spatial_weight = DEFAULT_SPATIAL_WEIGHT
        temporal_weight = DEFAULT_TEMPORAL_WEIGHT

        if dataset.organization:
            organization = Organization.objects(
                id=dataset.organization.id).first()
            image_url = organization.logo(40, external=True)
        elif dataset.owner:
            owner = User.objects(id=dataset.owner.id).first()
            image_url = owner.avatar(40, external=True)

        certified = organization and organization.certified

        document = {
            'title':
            dataset.title,
            'description':
            dataset.description,
            'license':
            getattr(dataset.license, 'id', None),
            'tags':
            dataset.tags,
            'badges': [badge.kind for badge in dataset.badges],
            'tag_suggest':
            dataset.tags,
            'resources': [{
                'title': r.title,
                'description': r.description,
                'format': r.format,
                'type': r.type,
            } for r in dataset.resources],
            'format_suggest':
            [r.format.lower() for r in dataset.resources if r.format],
            'frequency':
            dataset.frequency,
            'organization':
            str(organization.id) if organization else None,
            'owner':
            str(owner.id) if owner else None,
            'dataset_suggest': {
                'input':
                cls.completer_tokenize(dataset.title) + [str(dataset.id)],
                'output': dataset.title,
                'payload': {
                    'id': str(dataset.id),
                    'slug': dataset.slug,
                    'acronym': dataset.acronym,
                    'image_url': image_url,
                },
            },
            'created':
            dataset.created_at.strftime('%Y-%m-%dT%H:%M:%S'),
            'last_modified':
            dataset.last_modified.strftime('%Y-%m-%dT%H:%M:%S'),
            'metrics':
            dataset.metrics,
            'featured':
            dataset.featured,
            'from_certified':
            certified,
        }
        if (dataset.temporal_coverage is not None
                and dataset.temporal_coverage.start
                and dataset.temporal_coverage.end):
            start = dataset.temporal_coverage.start.toordinal()
            end = dataset.temporal_coverage.end.toordinal()
            temporal_weight = min((end - start) / 365, MAX_TEMPORAL_WEIGHT)
            document.update({
                'temporal_coverage': {
                    'start': start,
                    'end': end
                },
                'temporal_weight': temporal_weight,
            })

        if dataset.spatial is not None:
            # Index precise zone labels and parents zone identifiers
            # to allow fast filtering.
            zone_ids = [z.id for z in dataset.spatial.zones]
            zones = GeoZone.objects(id__in=zone_ids).exclude('geom')
            parents = set()
            geozones = []
            coverage_level = ADMIN_LEVEL_MAX
            for zone in zones:
                geozones.append({
                    'id': zone.id,
                    'name': zone.name,
                    'keys': zone.keys_values
                })
                parents |= set(zone.parents)
                coverage_level = min(coverage_level, admin_levels[zone.level])

            geozones.extend([{'id': p} for p in parents])

            spatial_weight = ADMIN_LEVEL_MAX / coverage_level
            document.update({
                'geozones': geozones,
                'granularity': dataset.spatial.granularity,
                'spatial_weight': spatial_weight,
            })

        document['dataset_suggest']['weight'] = cls.get_suggest_weight(
            temporal_weight, spatial_weight, dataset.featured)

        if dataset.acronym:
            document['dataset_suggest']['input'].append(dataset.acronym)

        return document
示例#35
0
class UserFollowedOrganization(FollowActivity, OrgRelatedActivity, Activity):
    key = 'organization:followed'
    label = _('followed an organization')
示例#36
0
class OrganizationExtraForm(Form):
    key = fields.StringField(_('Key'), [validators.required()])
    value = fields.StringField(_('Value'), [validators.required()])
    old_key = fields.StringField(_('Old key'))
示例#37
0
class UserFollowedDataset(FollowActivity, DatasetRelatedActivity, Activity):
    key = 'dataset:followed'
    label = _('followed a dataset')
示例#38
0
class UserDiscussedReuse(DiscussActivity, ReuseRelatedActivity, Activity):
    key = 'reuse:discussed'
    label = _('discussed a reuse')
示例#39
0
class UserDiscussedDataset(DiscussActivity, DatasetRelatedActivity, Activity):
    key = 'dataset:discussed'
    label = _('discussed a dataset')
示例#40
0
def payload_name(payload):
    '''extract payload name and localize it'''
    name = payload['name']
    return _(name)  # Avoid dict quotes in gettext
示例#41
0
class MembershipRefuseForm(Form):
    comment = fields.StringField(_('Comment'), [validators.required()])
示例#42
0
class CommunityResourceForm(BaseResourceForm):
    model_class = CommunityResource

    dataset = fields.DatasetField(_('Related dataset'))
    owner = fields.CurrentUserField()
    organization = fields.PublishAsField(_('Publish as'))
示例#43
0
class DiscussionCommentForm(Form):
    comment = fields.StringField(_('Comment'), [validators.required()])
    close = fields.BooleanField(default=False)
示例#44
0
class DatasetForm(ModelForm):
    model_class = Dataset

    title = fields.StringField(_('Title'), [validators.required()])
    description = fields.MarkdownField(
        _('Description'), [validators.required()],
        description=_('The details about the dataset '
                      '(collection process, specifics...).'))
    license = fields.ModelSelectField(_('License'),
                                      model=License,
                                      allow_blank=True)
    frequency = fields.SelectField(
        _('Update frequency'),
        choices=UPDATE_FREQUENCIES.items(),
        default=DEFAULT_FREQUENCY,
        validators=[validators.optional()],
        preprocessors=[map_legacy_frequencies],
        description=_('The frequency at which data are updated.'))
    frequency_date = fields.DateTimeField(_('Expected frequency date'))
    temporal_coverage = fields.DateRangeField(
        _('Temporal coverage'),
        description=_('The period covered by the data'))
    spatial = SpatialCoverageField(
        _('Spatial coverage'),
        description=_('The geographical area covered by the data.'))
    tags = fields.TagField(_('Tags'), description=_('Some taxonomy keywords'))
    private = fields.BooleanField(
        _('Private'),
        description=_('Restrict the dataset visibility to you or '
                      'your organization only.'))

    owner = fields.CurrentUserField()
    organization = fields.PublishAsField(_('Publish as'))
    extras = fields.ExtrasField(extras=Dataset.extras)
    resources = fields.NestedModelList(ResourceForm)
示例#45
0
 def __html__(self):
     """In use within the admin."""
     return '{name} <i>({code})</i>'.format(name=_(self.name),
                                            code=self.code)
示例#46
0
class HarvestSourceValidationForm(Form):
    state = fields.SelectField(choices=VALIDATION_STATES.items())
    comment = fields.StringField(
        _('Comment'), [validators.RequiredIfVal('state', VALIDATION_REFUSED)])
示例#47
0
class BaseResourceForm(ModelForm):
    title = fields.StringField(_('Title'), [validators.required()])
    description = fields.MarkdownField(_('Description'))
    filetype = fields.RadioField(
        _('File type'), [validators.required(), enforce_filetype_file],
        choices=RESOURCE_FILETYPES.items(),
        default='file',
        description=_('Whether the resource is an uploaded file, '
                      'a remote file or an API'))
    type = fields.RadioField(
        _('Type'), [validators.required()],
        choices=RESOURCE_TYPES.items(),
        default='other',
        description=_('Resource type (documentation, API...)'))
    url = fields.UploadableURLField(_('URL'), [validators.required()],
                                    storage=resources)
    format = fields.StringField(
        _('Format'),
        filters=[normalize_format],
    )
    checksum = fields.FormField(ChecksumForm)
    mime = fields.StringField(_('Mime type'),
                              description=_(
                                  'The mime type associated to the extension. '
                                  '(ex: text/plain)'))
    filesize = fields.IntegerField(_('Size'), [validators.optional()],
                                   description=_('The file size in bytes'))
    published = fields.DateTimeField(
        _('Publication date'),
        description=_('The publication date of the resource'))
示例#48
0
def get_spatial_granularities(lang):
    with language(lang):
        return [(l.id, _(l.name)) for l in GeoLevel.objects
                ] + [(id, label.value) for id, label in BASE_GRANULARITIES]
示例#49
0
def notify_new_member(org, member):
    subject = _('You are now a member of the organization "%(org)s"', org=org)
    mail.send(subject, member.user, 'new_member', org=org)
示例#50
0
class UserCreatedDataset(DatasetRelatedActivity, Activity):
    key = 'dataset:created'
    icon = 'fa fa-plus'
    badge_type = 'success'
    label = _('created a dataset')
示例#51
0
def notify_membership_request(org, request):
    recipients = [m.user for m in org.by_role('admin')]
    mail.send(
        _('New membership request'), recipients, 'membership_request',
        org=org, request=request)
示例#52
0
class UserUpdatedDataset(DatasetRelatedActivity, Activity):
    key = 'dataset:updated'
    icon = 'fa fa-pencil'
    label = _('updated a dataset')
示例#53
0
class Organization(WithMetrics, BadgeMixin, db.Datetimed, db.Document):
    name = db.StringField(required=True)
    acronym = db.StringField(max_length=128)
    slug = db.SlugField(max_length=255,
                        required=True,
                        populate_from='name',
                        update=True,
                        follow=True)
    description = db.StringField(required=True)
    url = db.StringField()
    image_url = db.StringField()
    logo = db.ImageField(fs=avatars,
                         basename=default_image_basename,
                         max_size=LOGO_MAX_SIZE,
                         thumbnails=LOGO_SIZES)

    members = db.ListField(db.EmbeddedDocumentField(Member))
    teams = db.ListField(db.EmbeddedDocumentField(Team))
    requests = db.ListField(db.EmbeddedDocumentField(MembershipRequest))

    ext = db.MapField(db.GenericEmbeddedDocumentField())
    zone = db.StringField()
    extras = db.ExtrasField()

    deleted = db.DateTimeField()

    meta = {
        'indexes': ['-created_at', 'slug'],
        'ordering': ['-created_at'],
        'queryset_class': OrganizationQuerySet,
    }

    def __unicode__(self):
        return self.name or ''

    __badges__ = {
        PUBLIC_SERVICE: _('Public Service'),
        CERTIFIED: _('Certified'),
    }

    before_save = Signal()
    after_save = Signal()
    on_create = Signal()
    on_update = Signal()
    before_delete = Signal()
    after_delete = Signal()

    @classmethod
    def pre_save(cls, sender, document, **kwargs):
        cls.before_save.send(document)

    @classmethod
    def post_save(cls, sender, document, **kwargs):
        cls.after_save.send(document)
        if kwargs.get('created'):
            cls.on_create.send(document)
        else:
            cls.on_update.send(document)

    def url_for(self, *args, **kwargs):
        return url_for('organizations.show', org=self, *args, **kwargs)

    display_url = property(url_for)

    @property
    def external_url(self):
        return self.url_for(_external=True)

    @property
    def pending_requests(self):
        return [r for r in self.requests if r.status == 'pending']

    @property
    def refused_requests(self):
        return [r for r in self.requests if r.status == 'refused']

    @property
    def accepted_requests(self):
        return [r for r in self.requests if r.status == 'accepted']

    @property
    def certified(self):
        return any(b.kind == CERTIFIED for b in self.badges)

    @property
    def public_service(self):
        is_public_service = any(b.kind == PUBLIC_SERVICE for b in self.badges)
        return self.certified and is_public_service

    def member(self, user):
        for member in self.members:
            if member.user == user:
                return member
        return None

    def is_member(self, user):
        return self.member(user) is not None

    def is_admin(self, user):
        member = self.member(user)
        return member is not None and member.role == 'admin'

    def pending_request(self, user):
        for request in self.requests:
            if request.user == user and request.status == 'pending':
                return request
        return None

    @classmethod
    def get(cls, id_or_slug):
        obj = cls.objects(slug=id_or_slug).first()
        return obj or cls.objects.get_or_404(id=id_or_slug)

    def by_role(self, role):
        return filter(lambda m: m.role == role, self.members)

    def check_availability(self):
        from udata.models import Dataset  # Circular imports.
        # Performances: only check the first 20 datasets for now.
        return chain(*[
            dataset.check_availability()
            for dataset in Dataset.objects(organization=self).visible()[:20]
        ])

    @cached_property
    def json_ld(self):
        type_ = 'GovernmentOrganization' if self.public_service \
                else 'Organization'

        result = {
            '@context': 'http://schema.org',
            '@type': type_,
            'alternateName': self.slug,
            'url': url_for('organizations.show', org=self, _external=True),
            'name': self.name,
        }

        if self.description:
            result['description'] = mdstrip(self.description)

        logo = self.logo(external=True)
        if logo:
            result['logo'] = logo

        return result
示例#54
0
class UserDeletedDataset(DatasetRelatedActivity, Activity):
    key = 'dataset:deleted'
    icon = 'fa fa-remove'
    badge_type = 'error'
    label = _('deleted a dataset')
示例#55
0
from blinker import Signal
from flask import url_for
from mongoengine.signals import pre_save, post_save
from werkzeug import cached_property

from udata.core.storages import avatars, default_image_basename
from udata.frontend.markdown import mdstrip
from udata.models import db, BadgeMixin, WithMetrics
from udata.i18n import lazy_gettext as _

__all__ = ('Organization', 'Team', 'Member', 'MembershipRequest', 'ORG_ROLES',
           'MEMBERSHIP_STATUS', 'PUBLIC_SERVICE', 'CERTIFIED')

ORG_ROLES = {
    'admin': _('Administrator'),
    'editor': _('Editor'),
}
DEFAULT_ROLE = 'editor'

MEMBERSHIP_STATUS = {
    'pending': _('Pending'),
    'accepted': _('Accepted'),
    'refused': _('Refused'),
}

LOGO_MAX_SIZE = 500
LOGO_SIZES = [100, 60, 25]

PUBLIC_SERVICE = 'public-service'
CERTIFIED = 'certified'
示例#56
0
文件: metrics.py 项目: guillo-w/udata
class FollowersMetric(SiteMetric):
    name = 'followers'
    display_name = _('Followers')

    def get_value(self):
        return Follow.objects(until=None).count()
示例#57
0
文件: metrics.py 项目: guillo-w/udata
class DatasetsMetric(SiteMetric):
    name = 'datasets'
    display_name = _('Datasets')

    def get_value(self):
        return Dataset.objects.visible().count()
示例#58
0
def source_tooltip_callback(attrs, new=False):
    """
    Add a `data-tooltip` attribute with `Source` content for embeds.
    """
    attrs[(None, 'data-tooltip')] = _('Source')
    return attrs
示例#59
0
class UserFollowedReuse(FollowActivity, ReuseRelatedActivity, Activity):
    key = 'reuse:followed'
    label = _('followed a reuse')
示例#60
0
class MembershipRequestForm(UserModelForm):
    model_class = MembershipRequest
    user_field = 'user'

    comment = fields.StringField(_('Comment'), [validators.required()])