Source code for translator_directory.layout

from __future__ import annotations

from functools import cached_property
from datetime import datetime
from dateutil.relativedelta import relativedelta
from purl import URL
from urllib.parse import urlencode
import pytz

from onegov.translator_directory import _
from onegov.core.elements import Block, Link, LinkGroup, Confirm, Intercooler
from onegov.core.utils import linkify
from onegov.town6.layout import DefaultLayout as BaseLayout
from onegov.town6.layout import TicketLayout as TownTicketLayout
from onegov.org.models import Organisation
from onegov.org.utils import get_current_tickets_url
from onegov.translator_directory.collections.documents import \
    TranslatorDocumentCollection
from onegov.translator_directory.collections.language import LanguageCollection
from onegov.translator_directory.collections.translator import (
    TranslatorCollection,
)
from onegov.translator_directory.constants import (
    member_can_see, editor_can_see, translator_can_see,
    GENDERS, ADMISSIONS, PROFESSIONAL_GUILDS,
    INTERPRETING_TYPES, TIME_REPORT_INTERPRETING_TYPES)


from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
    from collections.abc import Iterable
    from decimal import Decimal
    from onegov.translator_directory.collections.time_report import (
        TimeReportCollection,
    )
    from onegov.translator_directory.models.language import Language
    from markupsafe import Markup
    from onegov.translator_directory.models.translator import (
        AdmissionState, Gender, Translator)
    from onegov.translator_directory.request import TranslatorAppRequest


[docs] class DefaultLayout(BaseLayout):
[docs] request: TranslatorAppRequest
@staticmethod
[docs] def linkify(text: str | None) -> Markup: # type:ignore[override] return linkify(text)
@staticmethod
[docs] def format_languages(languages: Iterable[Language] | None) -> str: return ', '.join(sorted(lang.name for lang in languages or ()))
[docs] def format_gender(self, gender: Gender) -> str: return self.request.translate(GENDERS[gender])
@staticmethod
[docs] def format_drive_distance(number: float | None) -> str: if not number: return '' return f'{number} km'
[docs] def format_boolean(self, val: bool | None) -> str: assert isinstance(val, bool) or val is None return self.request.translate(_('Yes') if val else _('No'))
[docs] def format_admission(self, val: AdmissionState) -> str: return self.request.translate(ADMISSIONS[val])
[docs] def show(self, attribute_name: str) -> bool: """Some attributes on the translator are hidden for less privileged users""" if self.request.is_admin: return True if self.request.is_editor: return attribute_name in editor_can_see if self.request.is_member: return attribute_name in member_can_see if self.request.is_translator: return attribute_name in translator_can_see return False
[docs] def color_class(self, count: int) -> str | None: """ Depending how rare a language is offered by translators, apply a color code using the returned css class """ if count <= 5: return 'text-orange' return None
[docs] def format_prof_guild(self, key: str) -> str: if key in PROFESSIONAL_GUILDS: return self.request.translate(PROFESSIONAL_GUILDS[key]) return key
[docs] def format_interpreting_type(self, key: str) -> str: if key in INTERPRETING_TYPES: return self.request.translate(INTERPRETING_TYPES[key]) if key in TIME_REPORT_INTERPRETING_TYPES: return self.request.translate(TIME_REPORT_INTERPRETING_TYPES[key]) return key
@staticmethod
[docs] def format_currency(amount: Decimal | float | None) -> str: """Format amount as Swiss Francs.""" if amount is None: return 'CHF 0.00' return f'CHF {amount:.2f}'
[docs] class TranslatorLayout(DefaultLayout): if TYPE_CHECKING:
[docs] model: Translator
def __init__( self, model: Translator, request: TranslatorAppRequest ) -> None: ...
[docs] def translator_data_outdated(self) -> bool: if self.request.is_translator: tz = pytz.timezone('Europe/Zurich') year_ago = datetime.now(tz=tz) - relativedelta(years=1) if self.model.modified: return self.model.modified < year_ago else: return self.model.created < year_ago else: return False
@cached_property
[docs] def file_collection(self) -> TranslatorDocumentCollection: return TranslatorDocumentCollection( self.request.session, translator_id=self.model.id, category=None )
@cached_property @cached_property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) if self.request.is_translator: links.append( Link( text=_('Personal Information'), url=self.request.link(self.model) ), ) else: links.append( Link( text=_('Translators'), url=self.request.class_link(TranslatorCollection) ), ) links.append( Link( text=self.model.title, url=self.request.link(self.model) ) ) return links
[docs] class EditTranslatorLayout(TranslatorLayout): @cached_property
[docs] def title(self) -> str: return _('Edit translator')
@cached_property @cached_property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs links.append(Link(_('Edit'))) return links
[docs] class ReportTranslatorChangesLayout(TranslatorLayout): @cached_property
[docs] def title(self) -> str: return _('Report change')
@cached_property @cached_property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs links.append(Link(_('Report change'))) return links
[docs] class ApplyTranslatorChangesLayout(TranslatorLayout): @cached_property
[docs] def title(self) -> str: return _('Report change')
@cached_property @cached_property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs links.append(Link(_('Apply proposed changes'))) return links
[docs] class MailTemplatesLayout(TranslatorLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: return [ *super().breadcrumbs, Link( text=_('Mail templates'), url=self.request.link( self.model, name='mail-templates' ) ) ]
[docs] class TranslatorCollectionLayout(DefaultLayout):
[docs] model: TranslatorCollection
@cached_property
[docs] def title(self) -> str: return _('Search for translators')
@cached_property
[docs] def breadcrumbs(self) -> list[Link]: return [ # type:ignore[misc] *super().breadcrumbs, Link( text=_('Translators'), url=self.request.class_link(TranslatorCollection) ) ]
@cached_property @cached_property
[docs] class AddTranslatorLayout(TranslatorCollectionLayout): @cached_property
[docs] def title(self) -> str: return _('Add translator')
@cached_property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs links.append(Link(_('Add'))) return links
@property
[docs] class TranslatorDocumentsLayout(DefaultLayout): def __init__(self, model: Any, request: TranslatorAppRequest) -> None: super().__init__(model, request) request.include('upload') request.include('prompt') @cached_property
[docs] def breadcrumbs(self) -> list[Link]: return [ # type:ignore[misc] *super().breadcrumbs, Link( text=_('Translators'), url=self.request.class_link(TranslatorCollection) ), Link( text=self.model.translator.title, url=self.request.link(self.model.translator) ), Link(text=_('Documents')) ]
@cached_property
[docs] def upload_url(self) -> str: url = URL(self.request.link(self.model, name='upload')) url = url.query_param('category', self.model.category) return self.csrf_protected_url(url.as_string())
[docs] class LanguageCollectionLayout(DefaultLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) links.append(Link(_('Languages'))) return links
@property
[docs] class LanguageLayout(DefaultLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) links.append( Link(_('Languages'), url=self.request.class_link(LanguageCollection)) ) return links
[docs] class EditLanguageLayout(LanguageLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs links.append(Link(self.model.name)) links.append(Link(_('Edit'))) return links
@cached_property
[docs] class AddLanguageLayout(LanguageLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs links.append(Link(_('Add'))) return links
@property
[docs] class AccreditationLayout(DefaultLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) links.append( Link( text=_('Accreditation'), url=self.request.link(self.model.ticket) ) ) return links
[docs] class RequestAccreditationLayout(DefaultLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) links.append( Link( text=_('Accreditation'), url=self.request.class_link( Organisation, name='request-accreditation' ) ) ) return links
[docs] class GrantAccreditationLayout(DefaultLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) links.append( Link( text=_('Accreditation'), url=self.request.link(self.model.ticket) ) ) links.append(Link(_('Grant admission'))) return links
[docs] class RefuseAccreditationLayout(DefaultLayout): @property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) links.append( Link( text=_('Accreditation'), url=self.request.link(self.model.ticket) ) ) links.append(Link(_('Refuse admission'))) return links
[docs] class TimeReportCollectionLayout(DefaultLayout): if TYPE_CHECKING:
[docs] model: TimeReportCollection
@cached_property
[docs] def title(self) -> str: return _('Time Reports')
@cached_property
[docs] def breadcrumbs(self) -> list[Link]: links = super().breadcrumbs assert isinstance(links, list) links.append(Link(_('Time Reports'))) return links
[docs] class TicketLayout(TownTicketLayout): @cached_property