Skip to content
Snippets Groups Projects
Select Git revision
  • 44a9ba1eda3cc7f012ceafd1a78be152b4c3ab74
  • test default protected
  • master protected
  • feat/custom-css
  • feat/redesign-improvements-10
  • feat/redesign-improvements-8
  • feat/redesign-fixes-3
  • feat/pirstan-changes
  • feat/separate-import-thread
  • feat/dary-improvements
  • features/add-pdf-page
  • features/add-typed-table
  • features/fix-broken-calendar-categories
  • features/add-embed-to-articles
  • features/create-mastodon-feed-block
  • features/add-custom-numbering-for-candidates
  • features/add-timeline
  • features/create-wordcloud-from-article-page
  • features/create-collapsible-extra-legal-info
  • features/extend-hero-banner
  • features/add-link-to-images
21 results

blocks.py

Blame
  • user avatar
    Tomáš Valenta authored
    97164f85
    History
    blocks.py 6.95 KiB
    import json
    from uuid import uuid4
    
    from django.forms.utils import ErrorList
    from django.utils.text import slugify
    from wagtail import blocks
    from wagtail.blocks.struct_block import StructBlockValidationError
    from wagtail.images.blocks import ImageChooserBlock
    
    from .const import (
        DEFAULT_MAP_STYLE,
        MAP_STYLES,
        SUPPORTED_FEATURE_TYPES,
        TILE_SERVER_CONFIG,
    )
    from .validation import validators
    
    
    class MapPointBlock(blocks.StructBlock):
        lat = blocks.DecimalBlock(label="Zeměpisná šířka", help_text="Např. 50.04075")
        lon = blocks.DecimalBlock(label="Zeměpisná délka", help_text="Např. 15.77659")
        hex_color = blocks.CharBlock(
            label="Barva špendlíku (HEX)",
            help_text="Zadejte barvu pomocí HEX notace (bez # na začátku).",
            default="000000",
        )
        zoom = blocks.IntegerBlock(
            label="Výchozí zoom", min_value=1, max_value=18, default=15
        )
        style = blocks.ChoiceBlock(
            choices=MAP_STYLES, label="Styl", default=DEFAULT_MAP_STYLE
        )
        height = blocks.IntegerBlock(label="Výška v px", min_value=100, max_value=1000)
    
        class Meta:
            label = "Mapa se špendlíkem"
            template = "maps_utils/blocks/map_point.html"
            icon = "thumbtack"
    
        def get_context(self, value, parent_context=None):
            context = super().get_context(value, parent_context)
            feature_id = str(uuid4())
            context["js_map"] = {
                "tile_server_config": json.dumps(TILE_SERVER_CONFIG),
                "geojson": json.dumps(
                    [
                        {
                            "type": "FeatureCollection",
                            "properties": {
                                "slug": feature_id,
                                "title": None,
                                "collectionTitle": None,
                                "collectionDescription": None,
                            },
                            "features": [
                                {
                                    "type": "Feature",
                                    "geometry": {
                                        "type": "Point",
                                        "coordinates": [
                                            float(value["lon"]),
                                            float(value["lat"]),
                                        ],
                                    },
                                    "properties": {
                                        "id": feature_id,
                                        "slug": feature_id,
                                        "title": None,
                                        "description": None,
                                        "collectionTitle": None,
                                        "collectionDescription": None,
                                        "image": None,
                                        "color": value["hex_color"],
                                    },
                                },
                            ],
                        }
                    ]
                ),
            }
    
            return context
    
    
    class MapFeatureBlock(blocks.StructBlock):
        title = blocks.CharBlock(label="Titulek", required=True)
        description = blocks.TextBlock(label="Popisek", required=False)
        geojson = blocks.TextBlock(
            label="Geodata",
            help_text="Vložte surový GeoJSON objekt typu 'Feature'. Vyrobit jej můžete např. pomocí online služby geojson.io. Pokud u objektu poskytnete properties 'title' a 'description', zobrazí se jak na mapě, tak i v detailu.",
            required=True,
        )
        image = ImageChooserBlock(label="Obrázek", required=False)
        link = blocks.URLBlock(label="Odkaz", required=False)
        hex_color = blocks.CharBlock(
            label="Barva (HEX)",
            help_text="Zadejte barvu pomocí HEX notace (bez # na začátku).",
            default="000000",
        )
    
        class Meta:
            label = "Položka mapové kolekce"
            icon = "list-ul"
    
        def clean(self, value):
            errors = {}
    
            if value["geojson"]:
                try:
                    value["geojson"] = validators.normalize_geojson_feature(
                        value["geojson"], allowed_types=SUPPORTED_FEATURE_TYPES
                    )
                except ValueError as exc:
                    errors["geojson"] = ErrorList(str(exc))
    
            if errors:
                raise StructBlockValidationError(errors)
    
            return super().clean(value)
    
    
    class MapFeatureCollectionBlock(blocks.StructBlock):
        features = blocks.ListBlock(MapFeatureBlock(required=True), label="Součásti")
    
        zoom = blocks.IntegerBlock(
            label="Výchozí zoom", min_value=1, max_value=18, default=15
        )
        style = blocks.ChoiceBlock(
            choices=MAP_STYLES, label="Styl", default=DEFAULT_MAP_STYLE
        )
        height = blocks.IntegerBlock(label="Výška v px", min_value=100, max_value=1000)
    
        class Meta:
            label = "Mapová kolekce"
            template = "maps_utils/blocks/map_feature_collection.html"
            icon = "site"
    
        def get_context(self, value, parent_context=None):
            def _geojson_feature_with_props(feature_id, feature):
                fwp = json.loads(feature["geojson"])
                fwp["properties"].update(
                    {
                        "id": feature_id,
                        "slug": f"0-{feature_id}-{slugify(feature['title'])}",
                        # Individual features are suppressed to emulate collection-like style.
                        "title": None,
                        "description": None,
                        "collectionTitle": feature["title"],
                        "collectionDescription": feature["description"],
                        "image": feature["image"]
                        .get_rendition("fill-1200x675|jpegquality-80")
                        .url
                        if feature["image"]
                        else None,
                        "link": feature["link"],
                        "color": feature["hex_color"],
                    }
                )
                return fwp
    
            features = [
                _geojson_feature_with_props(i, f) for i, f in enumerate(value["features"])
            ]
    
            context = super().get_context(value, parent_context)
            context["js_map"] = {
                "tile_server_config": json.dumps(TILE_SERVER_CONFIG),
                "geojson": json.dumps(
                    [
                        # Each feature dumped as individual collection to make things consistent.
                        {
                            "type": "FeatureCollection",
                            "properties": {
                                "slug": f"{f['properties']['id']}-{slugify(f['properties']['collectionTitle'])}",
                                "collectionTitle": f["properties"]["collectionTitle"],
                                "collectionDescription": f["properties"][
                                    "collectionDescription"
                                ],
                                "image": f["properties"]["image"],
                            },
                            "features": [f],
                        }
                        for f in features
                    ]
                ),
            }
    
            return context