Пример #1
0
def view_notices_statistics_xlsx(self, request):
    """ View the statistics as XLSX. """

    output = BytesIO()
    workbook = Workbook(output)
    for title, row, content in (
        (_("Organizations"), _("Organization"), self.count_by_organization),
        (_("Categories"), _("Category"), self.count_by_category),
        (_("Groups"), _("Group"), self.count_by_group),
        (_("Rejected"), _("Name"), self.count_rejected),
    ):
        worksheet = workbook.add_worksheet()
        worksheet.name = request.translate(title)
        worksheet.write_row(0, 0, (
            request.translate(row),
            request.translate(_("Count"))
        ))
        for index, row in enumerate(content()):
            worksheet.write_row(index + 1, 0, row)
    workbook.close()
    output.seek(0)

    response = Response()
    response.content_type = (
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    )
    response.content_disposition = 'inline; filename={}-{}-{}.xlsx'.format(
        request.translate(_("Statistics")).lower(),
        normalize_for_url(request.translate(TRANSLATIONS.get(self.state, ''))),
        datetime.utcnow().strftime('%Y%m%d%H%M')
    )
    response.body = output.read()

    return response
Пример #2
0
    def id(self):
        """ An ID based on the title. """

        id = normalize_for_url(self.title.data or 'page')
        query = self.request.session.query(TranslatablePage)
        while query.filter_by(id=id).first():
            id = increment_name(id)
        return id
Пример #3
0
def attendees_by_username(request, username):
    """ Loads the given attendees linked to the given username, sorted by
    their name.

    """

    a = AttendeeCollection(request.session).by_username(username).all()
    a.sort(key=lambda a: normalize_for_url(a.name))

    return a
Пример #4
0
def get_unique_notice_name(name, session, model_class):
    """ Create a unique, URL-friendly name. """

    # it's possible for `normalize_for_url` to return an empty string...
    name = normalize_for_url(name) or "notice"

    while session.query(model_class.name).\
            filter(model_class.name == name).first():
        name = increment_name(name)

    return name
Пример #5
0
    def id_from_title(self, session):
        """ Returns a unique, user friendly id derived from the title. """

        title = self.get_title(self.session_manager.default_locale)
        id = normalize_for_url(title or self.__class__.__name__)
        while True:
            query = session.query(self.polymorphic_base).filter_by(id=id)
            items = [item for item in query if item != self]
            if not items:
                return id
            id = increment_name(id)
    def svg_name(self):
        """ Returns a nice to read SVG filename. """

        return '{}.svg'.format(
            normalize_for_url(
                '{}-{}'.format(
                    self.model.id,
                    self.request.translate(self.title() or '')
                )
            )
        )
Пример #7
0
    def add(self, title, html, lead=None, meta=None, content=None):

        name = normalize_for_url(title)

        if self.by_name(name):
            raise AlreadyExistsError(name)

        newsletter = Newsletter(
            name=normalize_for_url(title),
            title=title,
            html=html,
            lead=lead,
            meta=meta or {},
            content=content or {}
        )

        self.session.add(newsletter)
        self.session.flush()

        return newsletter
Пример #8
0
    def _get_unique_name(self, name):
        """ Create a unique, URL-friendly name. """

        # it's possible for `normalize_for_url` to return an empty string...
        name = normalize_for_url(name) or "event"

        session = self.session
        while session.query(Event.name).filter(Event.name == name).first():
            name = increment_name(name)

        return name
Пример #9
0
    def parse_definition(definition):
        for service in yaml.safe_load(definition):
            service_id = normalize_for_url(service['titel'])
            days = (d.strip() for d in service['tage'].split(','))

            yield service_id, Bunch(
                id=service_id,
                title=service['titel'],
                percentage=Decimal(service['prozent']),
                days=OrderedSet(SERVICE_DAYS[d.lower()[:2]] for d in days),
            )
Пример #10
0
def preview_notice_pdf(self, request):
    """ Preview the notice as PDF. """

    pdf = NoticesPdf.from_notice(self, request)

    filename = normalize_for_url('{}-{}-{}'.format(
        request.translate(_("Gazette")), request.app.principal.name,
        self.title))

    return Response(pdf.read(),
                    content_type='application/pdf',
                    content_disposition=f'inline; filename={filename}.pdf')
Пример #11
0
def view_election_compound_data_as_csv(self, request):

    """ View the raw data as CSV. """

    @request.after
    def add_last_modified(response):
        add_last_modified_header(response, self.last_modified)

    return Response(
        convert_list_of_dicts_to_csv(self.export()),
        content_type='text/csv',
        content_disposition='inline; filename={}.csv'.format(
            normalize_for_url(self.title)
        )
    )
Пример #12
0
def view_election_compound_data_as_json(self, request):

    """ View the raw data as JSON. """

    @request.after
    def add_last_modified(response):
        add_last_modified_header(response, self.last_modified)

    return Response(
        json.dumps(self.export(), sort_keys=True, indent=2).encode('utf-8'),
        content_type='application/json',
        content_disposition='inline; filename={}.json'.format(
            normalize_for_url(self.title)
        )
    )
Пример #13
0
    def pdf_file(self, value):
        """ Sets the PDF content for the agency (and all its
        suborganizations). Automatically sets a nice filename. Replaces only
        the reference, if possible.

        """

        filename = '{}.pdf'.format(normalize_for_url(self.title))
        if self.pdf:
            self.pdf.reference = as_fileintent(value, filename)
            self.pdf.name = filename
        else:
            pdf = AgencyPdf(id=random_token())
            pdf.reference = as_fileintent(value, filename)
            pdf.name = filename
            self.pdf = pdf
Пример #14
0
def migrate_file_metadata_to_jsonb(context):
    context.session.execute("""
        ALTER TABLE files
        ALTER COLUMN reference
        TYPE JSONB USING reference::jsonb
    """)

    context.operations.drop_index('files_by_type_and_name')

    context.add_column_with_defaults(
        table='files',
        column=Column('order', Text, nullable=False),
        default=lambda r: normalize_for_url(r.name))

    context.operations.create_index(
        'files_by_type_and_order', 'files', ['type', 'order'])
Пример #15
0
 def set_filename(response):
     bfs_number = self.linked_swissvotes[0].bfs_number
     name = self.name.split('-')[0]
     extension = {'results_by_domain': 'xlsx'}.get(name, 'pdf')
     title = {
         'voting_text': _("Voting text"),
         'brief_description': _("Brief description Swissvotes"),
         'realization': _("Realization"),
         'federal_council_message': _("Federal council message"),
         'parliamentary_debate': _("Parliamentary debate"),
         'voting_booklet': _("Voting booklet"),
         'ad_analysis': _("Analysis of the advertising campaign"),
         'resolution': _("Resolution"),
         'results_by_domain':
         _("Result by canton, district and municipality")
     }.get(name, '')
     title = normalize_for_url(request.translate(title))
     response.headers['Content-Disposition'] = (
         f'inline; filename={bfs_number}-{title}.{extension}')
Пример #16
0
def view_election_parties_data_as_csv(self, request):

    """ View the raw parties data as CSV. """

    @request.after
    def add_last_modified(response):
        add_last_modified_header(response, self.last_modified)

    return Response(
        convert_list_of_dicts_to_csv(self.export_parties()),
        content_type='text/csv',
        content_disposition='inline; filename={}.csv'.format(
            normalize_for_url(
                '{}-{}'.format(
                    self.title,
                    request.translate(_("Parties")).lower()
                )
            )
        )
    )
Пример #17
0
def view_election_compound_pdf(self, request):

    """ View the generated PDF. """

    layout = ElectionCompoundLayout(self, request)

    if not layout.pdf_path:
        return Response(status='503 Service Unavailable')

    content = None
    with request.app.filestorage.open(layout.pdf_path, 'rb') as f:
        content = f.read()

    return Response(
        content,
        content_type='application/pdf',
        content_disposition='inline; filename={}.pdf'.format(
            normalize_for_url(self.title)
        )
    )
Пример #18
0
    def add(self, title, timezone, type=None, name=None, meta={}, content={},
            definition=None, group=None):

        # look up the right class depending on the type (we need to do
        # this a bit akwardly here, because Resource does not use the
        # ModelBase as declarative base)
        resource = Resource.get_polymorphic_class(type, Resource)()
        resource.id == uuid4()
        resource.name = name or normalize_for_url(title)
        resource.title = title
        resource.timezone = timezone
        resource.meta = meta
        resource.content = content
        resource.definition = definition
        resource.group = group

        self.session.add(resource)
        self.session.flush()

        return self.bind(resource)
Пример #19
0
def view_notices_index(self, request):
    """ Export the index to the notices as PDF.

    This view is only visible by a publisher.

    """

    pdf = IndexPdf.from_notices(self, request)

    filename = normalize_for_url(
        '{}-{}'.format(
            request.translate(_("Gazette")),
            request.app.principal.name
        )
    )

    return Response(
        pdf.read(),
        content_type='application/pdf',
        content_disposition=f'inline; filename={filename}.pdf'
    )
Пример #20
0
    def load_homepage_pages(self):
        pages = PageCollection(self.session()).query()
        pages = pages.filter(Topic.type == 'topic')

        # XXX use JSON/JSONB for this (the attribute is not there if it's
        # false, so this is not too bad speed-wise but it's still awful)
        pages = pages.filter(Topic.meta.contains(
            'is_visible_on_homepage'
        ))

        result = defaultdict(list)
        for page in pages.all():
            if page.is_visible_on_homepage:
                result[page.root.id].append(page)

        for key in result:
            result[key] = list(sorted(
                result[key],
                key=lambda p: utils.normalize_for_url(p.title)
            ))

        return result
Пример #21
0
def get_root_pdf(self, request):

    if not request.app.root_pdf_exists:
        return Response(status='503 Service Unavailable')

    @request.after
    def cache_headers(response):
        last_modified = request.app.root_pdf_modified
        if last_modified:
            max_age = 1 * 24 * 60 * 60
            expires = datetime.now() + timedelta(seconds=max_age)
            fmt = '%a, %d %b %Y %H:%M:%S GMT'

            response.headers.add('Cache-Control', f'max-age={max_age}, public')
            response.headers.add('ETag', last_modified.isoformat())
            response.headers.add('Expires', expires.strftime(fmt))
            response.headers.add('Last-Modified', last_modified.strftime(fmt))

    return Response(request.app.root_pdf,
                    content_type='application/pdf',
                    content_disposition='inline; filename={}.pdf'.format(
                        normalize_for_url(request.app.org.name)))
Пример #22
0
def handle_new_definition(self, request, form):

    if form.submitted(request):

        model = Bunch(
            title=None, definition=None, type='custom', meta={}, content={}
        )
        form.update_model(model)

        if self.definitions.by_name(normalize_for_url(model.title)):
            request.alert(_("A form with this name already exists"))
        else:

            # forms added online are always custom forms
            new_form = self.definitions.add(
                title=model.title,
                definition=model.definition,
                type='custom',
                meta=model.meta,
                content=model.content
            )

            request.success(_("Added a new form"))
            return morepath.redirect(request.link(new_form))

    layout = FormEditorLayout(self, request)
    layout.breadcrumbs = [
        Link(_("Homepage"), layout.homepage_url),
        Link(_("Forms"), request.link(self)),
        Link(_("New Form"), request.link(self, name='neu'))
    ]

    return {
        'layout': layout,
        'title': _("New Form"),
        'form': form,
        'form_width': 'large',
    }
Пример #23
0
def view_rdf(self, request):

    """ Returns an XML / RDF / DCAT-AP for Switzerland format for
    opendata.swiss.

    See http://handbook.opendata.swiss/en/library/ch-dcat-ap for more
    information.

    """

    principal_name = request.app.principal.name
    publisher_id = self.open_data.get('id')
    publisher_name = self.open_data.get('name')
    publisher_mail = self.open_data.get('mail')
    if not publisher_id or not publisher_name or not publisher_mail:
        raise HTTPNotImplemented()

    @request.after
    def set_headers(response):
        response.headers['Content-Type'] = 'application/rdf+xml; charset=UTF-8'

    layout = DefaultLayout(self, request)
    domains = dict(self.domains_election)
    domains.update(self.domains_vote)
    locales = {k: k[:2] for k in request.app.locales}
    default_locale = request.default_locale

    rdf = Element('rdf:RDF', attrib={
        'xmlns:dct': 'http://purl.org/dc/terms/',
        'xmlns:dc': 'http://purl.org/dc/elements/1.1/',
        'xmlns:dcat': 'http://www.w3.org/ns/dcat#',
        'xmlns:foaf': 'http://xmlns.com/foaf/0.1/',
        'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema#',
        'xmlns:rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
        'xmlns:rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
        'xmlns:vcard': 'http://www.w3.org/2006/vcard/ns#',
        'xmlns:odrs': 'http://schema.theodi.org/odrs#',
        'xmlns:schema': 'http://schema.org/',
    })
    catalog = sub(rdf, 'dcat:Catalog')

    session = request.session
    items = session.query(Election).all()
    items.extend(session.query(ElectionCompound).all())
    items.extend(session.query(Vote).all())

    translations = request.app.translations

    def translate(text, locale):
        translator = translations.get(locale)
        if translator:
            return text.interpolate(translator.gettext(text))
        return text.interpolate(text)

    for item in sorted(items, key=lambda i: i.date, reverse=True):
        is_vote = isinstance(item, Vote)

        # IDs
        item_id = '{}-{}'.format('vote' if is_vote else 'election', item.id)
        ds = sub(catalog, 'dcat:dataset')
        ds = sub(ds, 'dcat:Dataset', {
            'rdf:about': 'http://{}/{}'.format(publisher_id, item_id)}
        )
        sub(ds, 'dct:identifier', {}, '{}@{}'.format(item_id, publisher_id))

        # Dates
        sub(
            ds, 'dct:issued',
            {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#dateTime'},
            datetime(
                item.date.year, item.date.month, item.date.day
            ).isoformat()
        )
        sub(
            ds, 'dct:modified',
            {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#dateTime'},
            item.last_modified.replace(microsecond=0).isoformat()
        )
        sub(
            ds, 'dct:accrualPeriodicity',
            {'rdf:resource': 'http://purl.org/cld/freq/completelyIrregular'}
        )

        # Theme
        sub(
            ds, 'dcat:theme',
            {'rdf:resource': 'http://opendata.swiss/themes/politics'}
        )

        # Landing page
        sub(ds, 'dcat:landingPage', {}, request.link(item, 'data'))

        # Keywords
        for keyword in (
            _("Vote") if is_vote else _("Election"),
            domains[item.domain]
        ):
            for locale, lang in locales.items():
                value = translate(keyword, locale).lower()
                sub(ds, 'dcat:keyword', {'xml:lang': lang}, value)

        # Title
        for locale, lang in locales.items():
            title = item.get_title(locale, default_locale) or ''
            sub(ds, 'dct:title', {'xml:lang': lang}, title)

        # Description
        for locale, lang in locales.items():
            locale = locale
            if is_vote:
                if item.domain == 'canton':
                    des = _(
                        "Final results of the cantonal vote \"${title}\", "
                        "${date}, ${principal}, "
                        "broken down by municipalities.",
                        mapping={
                            'title': (
                                item.get_title(locale, default_locale) or ''
                            ),
                            'date': format_date(
                                item.date, format='long', locale=locale
                            ),
                            'principal': principal_name
                        }
                    )
                else:
                    des = _(
                        "Final results of the federal vote \"${title}\", "
                        "${date}, ${principal}, "
                        "broken down by municipalities.",
                        mapping={
                            'title': (
                                item.get_title(locale, default_locale) or ''
                            ),
                            'date': format_date(
                                item.date, format='long', locale=locale
                            ),
                            'principal': principal_name
                        }
                    )
            else:
                if item.domain == 'canton':
                    des = _(
                        "Final results of the cantonal election \"${title}\", "
                        "${date}, ${principal}, "
                        "broken down by candidates and municipalities.",
                        mapping={
                            'title': (
                                item.get_title(locale, default_locale) or ''
                            ),
                            'date': format_date(
                                item.date, format='long', locale=locale
                            ),
                            'principal': principal_name
                        }
                    )
                elif item.domain == 'region':
                    des = _(
                        "Final results of the regional election \"${title}\", "
                        "${date}, ${principal}, "
                        "broken down by candidates and municipalities.",
                        mapping={
                            'title': (
                                item.get_title(locale, default_locale) or ''
                            ),
                            'date': format_date(
                                item.date, format='long', locale=locale
                            ),
                            'principal': principal_name
                        }
                    )
                else:
                    des = _(
                        "Final results of the federal election \"${title}\", "
                        "${date}, ${principal}, "
                        "broken down by candidates and municipalities.",
                        mapping={
                            'title': (
                                item.get_title(locale, default_locale) or ''
                            ),
                            'date': format_date(
                                item.date, format='long', locale=locale
                            ),
                            'principal': principal_name
                        }
                    )
            des = translate(des, locale)
            sub(ds, 'dct:description', {'xml:lang': lang}, des)

        # Format description
        for locale, lang in locales.items():
            label = translate(_("Format Description"), locale)
            url = layout.get_opendata_link(lang)

            fmt_des = sub(ds, 'dct:relation')
            fmt_des = sub(fmt_des, 'rdf:Description', {'rdf:about': url})
            sub(fmt_des, 'rdfs:label', {}, label)

        # Publisher
        pub = sub(ds, 'dct:publisher')
        pub = sub(pub, 'rdf:Description')
        sub(pub, 'rdfs:label', {}, publisher_name)
        mail = sub(ds, 'dcat:contactPoint')
        mail = sub(mail, 'vcard:Organization')
        sub(mail, 'vcard:fn', {}, publisher_name)
        sub(mail, 'vcard:hasEmail', {
            'rdf:resource': 'mailto:{}'.format(publisher_mail)
        })

        # Date
        date = sub(ds, 'dct:temporal')
        date = sub(date, 'dct:PeriodOfTime')
        sub(
            date, 'schema:startDate',
            {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#date'},
            item.date.isoformat()
        )
        sub(
            date, 'schema:endDate',
            {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#date'},
            item.date.isoformat()
        )

        # Distributions
        for fmt, media_type in (
            ('csv', 'text/csv'),
            ('json', 'application/json'),
        ):
            url = request.link(item, 'data-{}'.format(fmt))

            # IDs
            dist = sub(ds, 'dcat:distribution')
            dist = sub(dist, 'dcat:Distribution', {
                'rdf:about': 'http://{}/{}/{}'.format(
                    publisher_id, item_id, fmt
                )
            })
            sub(dist, 'dct:identifier', {}, fmt)

            # Title
            for locale, lang in locales.items():
                title = item.get_title(locale, default_locale) or item.id
                title = '{}.{}'.format(normalize_for_url(title), fmt)
                sub(dist, 'dct:title', {'xml:lang': lang}, title)

            # Dates
            sub(
                dist, 'dct:issued',
                {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#dateTime'},
                item.created.replace(microsecond=0).isoformat()
            )
            sub(
                dist, 'dct:modified',
                {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#dateTime'},
                item.last_modified.replace(microsecond=0).isoformat()
            )

            # URLs
            sub(
                dist, 'dcat:accessURL',
                {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#anyURI'},
                url
            )
            sub(
                dist, 'dcat:downloadURL',
                {'rdf:datatype': 'http://www.w3.org/2001/XMLSchema#anyURI'},
                url
            )

            # Legal
            sub(
                dist, 'dct:rights',
                {},
                'NonCommercialAllowed-CommercialAllowed-ReferenceRequired'
            )

            # Media Type
            sub(dist, 'dcat:mediaType', {}, media_type)

    out = BytesIO()
    ElementTree(rdf).write(out, encoding='utf-8', xml_declaration=True)
    out.seek(0)
    return out.read()
Пример #24
0
 def name_observer(self, name):
     self.order = normalize_for_url(name)
Пример #25
0
    def validate_name(self, key, name):
        assert normalize_for_url(name) == name, (
            "The given name was not normalized"
        )

        return name
Пример #26
0
 def get_subdomain(self, name):
     return utils.normalize_for_url(name)
Пример #27
0
def view_occasion_bookings_table(self, request):
    layout = DefaultLayout(self, request)

    wishlist_phase = self.period.wishlist_phase
    booking_phase = self.period.booking_phase
    phase_title = wishlist_phase and _("Wishlist") or _("Bookings")

    users = UserCollection(request.session).query()
    users = users.with_entities(User.username, User.id)
    users = {u.username: u.id.hex for u in users}

    def occasion_links(oid):
        if self.period.finalized:
            yield Link(
                text=_("Signup Attendee"),
                url='#',
                traits=(
                    Block(_(
                        "The period has already been finalized. No new "
                        "attendees may be added."
                    ), no=_("Cancel")),
                )
            )
        else:
            yield Link(
                text=_("Signup Attendee"),
                url=request.return_to(
                    request.class_link(Occasion, {'id': oid}, 'book'),
                    request.class_link(MatchCollection)
                )
            )

    @lru_cache(maxsize=10)
    def bookings_link(username):
        return request.class_link(
            BookingCollection, {
                'period_id': self.period.id,
                'username': username
            }
        )

    @lru_cache(maxsize=10)
    def user_link(username):
        return request.return_here(
            request.class_link(
                User, {'id': users[username]}
            )
        )

    @lru_cache(maxsize=10)
    def attendee_link(attendee_id):
        return request.return_here(
            request.class_link(
                Attendee, {'id': attendee_id}
            )
        )

    @lru_cache(maxsize=10)
    def group_link(group_code):
        return request.class_link(
            GroupInvite, {
                'group_code': group_code
            }
        )

    def booking_links(booking):
        yield Link(_("User"), user_link(booking.attendee.username))
        yield Link(_("Attendee"), attendee_link(booking.attendee_id))
        yield Link(phase_title, bookings_link(booking.attendee.username))

        if booking.group_code:
            yield Link(_("Group"), group_link(booking.group_code))

        if wishlist_phase:
            yield Link(
                text=_("Remove Wish"),
                url=layout.csrf_protected_url(
                    request.class_link(Booking, {'id': booking.id})
                ),
                traits=(
                    Confirm(_(
                        "Do you really want to remove ${attendee}'s wish?",
                        mapping={
                            'attendee': booking.attendee.name
                        }
                    ), yes=_("Remove Wish"), no=_("Cancel")),
                    Intercooler(
                        request_method='DELETE',
                        target='#{}'.format(booking.id)
                    )
                )
            )

        elif booking_phase and booking.state != 'accepted':
            yield Link(
                text=_("Remove Booking"),
                url=layout.csrf_protected_url(
                    request.class_link(Booking, {'id': booking.id})
                ),
                traits=(
                    Confirm(_(
                        "Do you really want to delete ${attendee}'s booking?",
                        mapping={
                            'attendee': booking.attendee.name
                        }
                    ), yes=_("Remove Booking"), no=_("Cancel")),
                    Intercooler(
                        request_method='DELETE',
                        target='#{}'.format(booking.id)
                    )
                )
            )
        elif booking_phase and booking.state == 'accepted':
            yield Link(
                text=_("Cancel Booking"),
                url=layout.csrf_protected_url(
                    request.class_link(
                        Booking, {'id': booking.id}, 'cancel'
                    )
                ),
                traits=(
                    Confirm(
                        _(
                            "Do you really want to cancel ${attendee}'s "
                            "booking?",
                            mapping={
                                'attendee': booking.attendee.name
                            }
                        ),
                        _("This cannot be undone."),
                        _("Cancel Booking"),
                        _("Cancel")
                    ),
                    Intercooler(
                        request_method='POST',
                    )
                )
            )

    bookings = {'accepted': [], 'other': []}

    q = request.session.query(Booking).filter_by(occasion_id=self.id)
    q = q.options(joinedload(Booking.attendee))

    for booking in q:
        state = booking.state == 'accepted' and 'accepted' or 'other'
        bookings[state].append(booking)

    bookings['accepted'].sort(key=lambda b: normalize_for_url(b.attendee.name))
    bookings['other'].sort(key=lambda b: normalize_for_url(b.attendee.name))

    return {
        'layout': layout,
        'bookings': bookings,
        'oid': self.id,
        'occasion_links': occasion_links,
        'booking_links': booking_links,
        'period': self.period
    }
Пример #28
0
 def get_subdomain(self, name):
     return utils.normalize_for_url(name)
Пример #29
0
 def by_title(choice):
     return normalize_for_url(choice[1])
Пример #30
0
def view_activities(self, request):
    active_period = request.app.active_period
    show_activities = bool(active_period or request.is_organiser)
    layout = VacationActivityCollectionLayout(self, request)

    filters = {}

    def link(text, active, url, rounded=False):
        return Link(text=text, active=active, url=url, rounded=rounded, attrs={
            'ic-get-from': url
        })

    if show_activities:
        filters['timelines'] = [
            link(
                text=request.translate(_("Elapsed")),
                active='past' in self.filter.timelines,
                url=request.link(self.for_filter(timeline='past'))
            ),
            link(
                text=request.translate(_("Now")),
                active='now' in self.filter.timelines,
                url=request.link(self.for_filter(timeline='now'))
            ),
            link(
                text=request.translate(_("Scheduled")),
                active='future' in self.filter.timelines,
                url=request.link(self.for_filter(timeline='future'))
            ),
        ]

        if request.is_organiser:
            filters['timelines'].insert(0, link(
                text=request.translate(_("Without")),
                active='undated' in self.filter.timelines,
                url=request.link(self.for_filter(timeline='undated'))
            ))

        filters['tags'] = [
            link(
                text=request.translate(_(tag)),
                active=tag in self.filter.tags,
                url=request.link(self.for_filter(tag=tag)),
            ) for tag in self.used_tags
        ]
        filters['tags'].sort(key=lambda l: l.text)

        filters['durations'] = tuple(
            link(
                text=request.translate(text),
                active=duration in self.filter.durations,
                url=request.link(self.for_filter(duration=duration))
            ) for text, duration in (
                (_("Half day"), DAYS.half),
                (_("Full day"), DAYS.full),
                (_("Multiple days"), DAYS.many),
            )
        )

        ages = self.available_ages()
        if ages:

            def age_filters():
                for age in range(*ages):
                    if age < 16:
                        yield str(age), (age, age)
                    else:
                        yield "16+", (16, 99)
                        break

            filters['ages'] = tuple(
                link(
                    text=request.translate(text),
                    active=self.filter.contains_age_range(age_range),
                    url=request.link(self.for_filter(age_range=age_range))
                ) for text, age_range in age_filters()
            )

        filters['price_range'] = tuple(
            link(
                text=request.translate(text),
                active=self.filter.contains_price_range(price_range),
                url=request.link(self.for_filter(price_range=price_range))
            ) for text, price_range in (
                (_("Free of Charge"), (0, 0)),
                (_("Up to 25 CHF"), (1, 25)),
                (_("Up to 50 CHF"), (26, 50)),
                (_("Up to 100 CHF"), (51, 100)),
                (_("More than 100 CHF"), (101, 100000)),
            )
        )

        if active_period:
            filters['weeks'] = tuple(
                link(
                    text='{} - {}'.format(
                        layout.format_date(daterange[0], 'date'),
                        layout.format_date(daterange[1], 'date')
                    ),
                    active=daterange in self.filter.dateranges,
                    url=request.link(self.for_filter(daterange=daterange))
                ) for nth, daterange in enumerate(
                    self.available_weeks(active_period),
                    start=1
                )
            )

        filters['weekdays'] = tuple(
            link(
                text=WEEKDAYS[weekday],
                active=weekday in self.filter.weekdays,
                url=request.link(self.for_filter(weekday=weekday))
            ) for weekday in range(0, 7)
        )

        filters['available'] = tuple(
            link(
                text=request.translate(text),
                active=available in self.filter.available,
                url=request.link(self.for_filter(available=available))
            ) for text, available in (
                (_("None"), 'none'),
                (_("Few"), 'few'),
                (_("Many"), 'many'),
            )
        )

        filters['municipalities'] = [
            link(
                text=municipality,
                active=municipality in self.filter.municipalities,
                url=request.link(self.for_filter(municipality=municipality))
            ) for municipality in self.used_municipalities
        ]
        filters['municipalities'].sort(key=lambda l: normalize_for_url(l.text))

        if request.is_organiser:
            if request.app.periods:
                filters['periods'] = [
                    link(
                        text=period.title,
                        active=period.id in self.filter.period_ids,
                        url=request.link(self.for_filter(period_id=period.id))
                    ) for period in request.app.periods if period
                ]
                filters['periods'].sort(key=lambda l: l.text)

            filters['own'] = (
                link(
                    text=request.translate(_("Own")),
                    active=request.current_username in self.filter.owners,
                    url=request.link(
                        self.for_filter(owner=request.current_username)
                    )
                ),
            )

            filters['states'] = tuple(
                link(
                    text=ACTIVITY_STATE_TRANSLATIONS[state],
                    active=state in self.filter.states,
                    url=request.link(self.for_filter(state=state))
                ) for state in ACTIVITY_STATES
            )

    def get_period_bound_occasions(activity):
        if not active_period:
            return []

        return [
            o for o in activity.occasions
            if o.period_id == active_period.id
        ]

    def get_ages(a):
        return tuple(o.age for o in get_period_bound_occasions(a))

    def get_available_spots(a):
        if not active_period:
            return 0

        if not active_period.confirmed:
            return sum(
                o.max_spots for o in get_period_bound_occasions(a)
            )
        else:
            return sum(
                o.available_spots for o in get_period_bound_occasions(a)
            )

    def get_min_cost(a):
        occasions = get_period_bound_occasions(a)

        if not occasions:
            return None

        if active_period.all_inclusive:
            extra = 0
        else:
            extra = active_period.booking_cost or 0

        return min((o.cost or 0) + extra for o in occasions)

    filtered = next(
        (
            True
            for links in filters.values()
            for link in links
            if link.active
        ), False
    )

    return {
        'activities': self.batch if show_activities else None,
        'layout': layout,
        'title': _("Activities"),
        'filters': filters,
        'filtered': filtered,
        'period': active_period,
        'get_ages': get_ages,
        'get_min_cost': get_min_cost,
        'get_available_spots': get_available_spots,
    }