Beispiel #1
0
class LocationAdmin(ContentEditor):
    search_fields = [
        'name',
        'street',
        'city',
    ]

    list_display = [
        'name',
        'slug',
        'street',
        'city',
        'lng',
        'lat',
    ]

    list_filter = ['city']

    prepopulated_fields = {'slug': ('name', )}

    fieldsets = (
        (None, {
            'fields': (
                'name',
                'street',
                (
                    'city',
                    'zip_code',
                ),
                'country',
            )
        }),
        (_('advanced'), {
            'classes': ('tabbed', ),
            'fields':
            ('slug', 'lat', 'lng', 'header_image', 'header_image_ppoi')
        }),
        MetaMixin.admin_fieldset(),
    )

    inlines = [
        plugins.image.ImageInline.create(models.LocationImage),
    ]

    def save_model(self, request, obj, form, change):
        if (not change):
            locator = Nominatim(user_agent=settings.NOMINATIM_USER_AGENT)
            location = locator.geocode(
                f"{obj.street}, {obj.zip_code} {obj.city}, {obj.country}")
            obj.lat = location.latitude
            obj.lng = location.longitude
        super().save_model(request, obj, form, change)
Beispiel #2
0
class CategoryAdmin(VersionAdmin, TreeAdmin):
    list_display = [
        "indented_title",
        "move_column",
        "name",
        "slug",
        "parent",
        "language_code",
    ]
    list_filter = ["language_code"]
    search_fields = ["name", "slug"]
    prepopulated_fields = {"slug": ("name", )}

    autocomplete_fields = ["parent", "translations"]

    fieldsets = (
        (
            None,
            {
                "fields": (
                    "name",
                    "slug",
                    "language_code",
                    "parent",
                    "header_image",
                    "header_image_ppoi",
                    "color",
                )
            },
        ),
        MetaMixin.admin_fieldset(),
        (_("translations"), {
            "classes": ("collapse", ),
            "fields": ("translations", ),
        }),
    )
Beispiel #3
0
class PageAdmin(ContentEditor, TreeAdmin):
    list_display = [
        "indented_title",
        "move_column",
        'slug',
        'static_path',
        'path',
        "is_active",
        'language_code',
        "template_key",
        'application',
        "position",
    ]
    actions = ['copy_selected']

    prepopulated_fields = {'slug': ('title', )}

    autocomplete_fields = [
        'parent',
        'namespace',
        'redirect_to_page',
        'collection',
    ]

    search_fields = ['title']

    list_editable = [
        'is_active',
        'slug',
        'static_path',
        'path',
        'language_code',
    ]

    list_filter = ['is_active', 'menu', 'language_code', 'site']

    inlines = [
        plugins.richtext.RichTextInline.create(models.RichText),
        plugins.image.ImageInline.create(models.Image),
        plugins.html.HTMLInline.create(models.HTML),
        plugins.external.ExternalInline.create(models.External),
        ButtonInline.create(models.Button),
        events_plugins.EventPluginInline.create(models.EventPlugin),
        blog_plugins.ArticlePluginInline.create(models.ArticlePlugin),
    ]

    fieldsets = (
        (None, {
            'fields': (
                'title',
                'parent',
            )
        }),
        (_('settings'), {
            'classes': ('tabbed', ),
            'fields': ('is_active', 'menu', 'language_code', 'template_key',
                       'image', 'image_ppoi'),
        }),
        (_('path'), {
            'classes': ('tabbed', ),
            'fields': (
                'slug',
                'static_path',
                'path',
                'site',
            )
        }),
        (_('application'), {
            'classes': ('tabbed', ),
            'fields': (
                'application',
                'namespace',
                'collection',
            )
        }),
        MetaMixin.admin_fieldset(),
        (_('redirect'), {
            'classes': ('tabbed', ),
            'fields': (
                'redirect_to_page',
                'redirect_to_url',
            )
        }),
    )

    mptt_level_indent = 30

    class Media:
        js = (
            'admin/js/jquery.init.js',
            JS('https://use.fontawesome.com/0fc4ca6dfe.js', {
                'async': 'async',
                'crossorigin': 'anonymous',
            },
               static=False),
            'admin/plugin_buttons.js',
        )
Beispiel #4
0
class ArticleAdmin(VersionAdmin, ContentEditor, CopyContentMixin):

    list_display = (
        "title",
        "slug",
        "publication_date",
        "category",
        "section",
        "language_code",
        "namespace",
    )

    list_filter = (
        "namespace",
        "section",
        "language_code",
        "category",
    )

    list_editable = (
        "language_code",
        "slug",
    )

    date_hierarchy = "publication_date"

    autocomplete_fields = (
        "category",
        "namespace",
        "author",
        "section",
        "translations",
    )

    search_fields = (
        "title",
        "blog_richtext_set__text",
    )

    prepopulated_fields = {
        "slug": ("title", ),
    }

    readonly_fields = (
        "created_date",
        "edited_date",
    )

    fieldsets = (
        (
            None,
            {
                "fields": (
                    "title",
                    "author",
                    "category",
                    "tags",
                    "header_image",
                    "header_image_ppoi",
                )
            },
        ),
        (
            _("settings"),
            {
                "classes": ("tabbed", ),
                "fields": (
                    "language_code",
                    "slug",
                    ("publication_date", "created_date", "edited_date"),
                    "section",
                    "namespace",
                    "template_key",
                ),
            },
        ),
        MetaMixin.admin_fieldset(),
        (_("translations"), {
            "classes": ("tabbed", ),
            "fields": ("translations", )
        }),
    )

    inlines = (
        plugins.richtext.RichTextInline.create(models.RichText),
        plugins.image.ImageInline.create(models.Image),
        plugins.html.HTMLInline.create(models.HTML),
        plugins.external.ExternalInline.create(models.External),
        ButtonInline.create(models.Button),
        download.DownloadInline.create(models.Download),
        people_plugins.TeamPluginInline.create(models.Team),
        people_plugins.CandidateListPluginInline.create(
            models.CandidaturePlugin),
        GlossaryContentInline.create(models.GlossaryRichText),
        blog_plugins.ArticlePluginInline.create(models.ArticlePlugin),
        event_plugins.EventPluginInline.create(models.EventPlugin),
        form_plugins.FormPluginInline.create(models.FormPlugin),
    )

    plugins = models.plugins
    actions = ("copy_selected", "send_webpush")

    class Media:
        js = (
            "admin/js/jquery.init.js",
            JS(
                "https://kit.fontawesome.com/91a6274901.js",
                {
                    "async": "async",
                    "crossorigin": "anonymous",
                },
                static=False,
            ),
            "admin/plugin_buttons.js",
        )

    def send_webpush(self, request, queryset):
        for article in queryset:
            pages = Page.objects.filter(
                (Q(application="blog")
                 & Q(language_code=article.language_code))
                & (Q(category__isnull=True) | Q(category=article.category))
                & (Q(blog_namespace__isnull=True)
                   | Q(blog_namespace=article.namespace))
                & (Q(site__section=article.section)
                   | Q(sections=article.section)))

            for page in pages:
                subscriptions = webpush.Subscription.objects.filter(page=page)
                data = article.webpush_data(page)
                for subscription in subscriptions:
                    tasks.send_data_to.delay(data, subscription.pk)

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)

        section_field = form.base_fields["section"]

        sections = request.user.section_set.all()
        section_field.initial = sections[0]

        return form

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        sections = request.user.section_set.all()
        return qs.filter(section__in=sections)
Beispiel #5
0
class LocationAdmin(VersionAdmin, ContentEditor):
    search_fields = [
        "name",
        "street",
        "city",
    ]

    list_display = [
        "name",
        "slug",
        "street",
        "city",
        "lng",
        "lat",
    ]

    list_filter = ["city"]

    prepopulated_fields = {"slug": ("name", )}

    autocomplete_fields = ["section", "translations"]

    fieldsets = (
        (None, {
            "fields": (
                "name",
                "street",
                (
                    "city",
                    "zip_code",
                ),
                "country",
            )
        }),
        (
            _("advanced"),
            {
                "classes": ("tabbed", ),
                "fields": (
                    "section",
                    "slug",
                    "is_physical",
                    "lat",
                    "lng",
                    "header_image",
                    "header_image_ppoi",
                ),
            },
        ),
        MetaMixin.admin_fieldset(),
        (_("translations"), {
            "classes": ("tabbed", ),
            "fields": ("translations", )
        }),
    )

    inlines = [
        plugins.image.ImageInline.create(models.LocationImage),
    ]

    def has_change_permission(self, request, obj=None):
        if obj is None or obj.section is None:
            return super().has_change_permission(request, obj)
        sections = request.user.section_set.all()
        return obj.section in sections

    def save_model(self, request, obj, form, change):
        if not change and obj.is_physical:
            locator = Nominatim(user_agent=settings.NOMINATIM_USER_AGENT)
            location = locator.geocode(
                f"{obj.street}, {obj.zip_code} {obj.city}, {obj.country}")
            obj.lat = location.latitude
            obj.lng = location.longitude
        super().save_model(request, obj, form, change)
Beispiel #6
0
class EventAdmin(ContentEditor):
    list_display = [
        'title',
        'slug',
        'start_date',
        'end_date',
        'location',
        'language_code',
    ]

    list_filter = [
        'language_code',
    ]

    search_fields = [
        'location',
        'title',
        'description',
    ]

    date_hierarchy = 'start_date'

    autocomplete_fields = [
        'location',
    ]

    search_fields = [
        'title',
    ]

    prepopulated_fields = {
        "slug": ("title", ),
    }

    fieldsets = (
        (None, {
            'fields': (
                'title',
                'author',
                (
                    'start_date',
                    'end_date',
                ),
                'location',
            )
        }),
        (_('settings'), {
            'classes': ('tabbed', ),
            'fields': ('language_code', 'slug', 'template_key', 'header_image',
                       'header_image_ppoi')
        }),
        MetaMixin.admin_fieldset(),
    )

    inlines = [
        plugins.richtext.RichTextInline.create(models.RichText),
        plugins.image.ImageInline.create(models.Image),
        plugins.html.HTMLInline.create(models.HTML),
        plugins.external.ExternalInline.create(models.External),
        blog_plugins.ArticlePluginInline.create(models.ArticlePlugin),
        event_plugins.EventPluginInline.create(models.EventPlugin),
        ButtonInline.create(models.Button),
    ]

    class Media:
        js = (
            'admin/js/jquery.init.js',
            JS('https://use.fontawesome.com/0fc4ca6dfe.js', {
                'async': 'async',
                'crossorigin': 'anonymous',
            },
               static=False),
            'admin/plugin_buttons.js',
        )
Beispiel #7
0
class PageAdmin(VersionAdmin, CopyContentMixin, ContentEditor, TreeAdmin):
    list_display = [
        "indented_title",
        "move_column",
        "slug",
        "static_path",
        "path",
        "is_active",
        "language_code",
        "template_key",
        "application",
        "position",
    ]
    actions = ["open_duplicate_form"]

    list_per_page = 50

    prepopulated_fields = {"slug": ("title", )}

    autocomplete_fields = [
        "site",
        "parent",
        "blog_namespace",
        "category",
        "redirect_to_page",
        "translations",
        "featured_categories",
        "sections",
        "collection",
    ]

    search_fields = ["title"]
    list_editable = []

    list_filter = ["is_active", "menu", "language_code", "site"]

    inlines = [
        plugins.richtext.RichTextInline.create(models.RichText),
        plugins.image.ImageInline.create(models.Image),
        plugins.html.HTMLInline.create(models.HTML),
        plugins.external.ExternalInline.create(models.External),
        download.DownloadInline.create(models.Download),
        ButtonInline.create(models.Button),
        people_plugins.TeamPluginInline.create(models.Team),
        people_plugins.CandidateListPluginInline.create(
            models.CandidaturePlugin),
        event_plugins.EventPluginInline.create(models.EventPlugin),
        blog_plugins.ArticlePluginInline.create(models.ArticlePlugin),
        GlossaryContentInline.create(models.GlossaryRichText),
        form_plugins.FormPluginInline.create(models.FormPlugin),
        form_plugins.EntryCounterInline.create(models.FormEntryCounterPlugin),
        NavigationPluginInline.create(models.NavigationPlugin),
        CategoryLinkingInline,
    ]

    plugins = models.plugins
    readonly_fields = ["app_instance_namespace"]

    fieldsets = (
        (None, {
            "fields": (
                "title",
                "parent",
            )
        }),
        (
            _("settings"),
            {
                "classes": ("tabbed", ),
                "fields": (
                    "is_active",
                    "menu",
                    "language_code",
                    "template_key",
                    "is_landing_page",
                    "header_image",
                    "header_image_ppoi",
                ),
            },
        ),
        (
            _("path"),
            {
                "classes": ("tabbed", ),
                "fields": (
                    "slug",
                    "static_path",
                    "path",
                    "site",
                ),
            },
        ),
        (
            _("application"),
            {
                "classes": ("tabbed", ),
                "fields": (
                    "application",
                    "category",
                    "blog_namespace",
                    "featured_categories",
                    "sections",
                    "collection",
                    "app_instance_namespace",
                ),
            },
        ),
        MetaMixin.admin_fieldset(),
        (
            _("redirect"),
            {
                "classes": ("tabbed", ),
                "fields": (
                    "redirect_to_page",
                    "redirect_to_url",
                ),
            },
        ),
        (_("translations"), {
            "classes": ("tabbed", ),
            "fields": ("translations", )
        }),
        (
            _("advanced"),
            {
                "classes": ("tabbed", ),
                "fields": (
                    "in_meta",
                    "is_navigation",
                    "position",
                    "logo",
                    "favicon",
                    "primary_color",
                    "css_vars",
                    "fonts",
                    "prefetches",
                    "google_site_verification",
                ),
            },
        ),
    )

    mptt_level_indent = 30

    def move_view(self, request, obj):
        return self.action_form_view(request,
                                     obj,
                                     form_class=ResctrictedMoveForm,
                                     title=_("Move %s") % obj)

    class Media:
        js = (
            "admin/js/jquery.init.js",
            JS(
                "https://kit.fontawesome.com/91a6274901.js",
                {
                    "async": "async",
                    "crossorigin": "anonymous",
                },
                static=False,
            ),
            "admin/plugin_buttons.js",
        )

    def get_inline_instances(self, request, obj=None):
        inlines = super().get_inline_instances(request, obj)
        if (hasattr(obj, "pk")
                and models.Page.objects.get(pk=obj.pk).application
                == "categories"):
            return inlines
        return inlines[:-1]

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)

        site_field = form.base_fields["site"]
        site_field.required = True

        sections = request.user.section_set.all()
        site_field.initial = Site.objects.filter(section__in=sections)[0]

        return form

    def indented_title(self, instance):
        """
        Use Unicode box-drawing characters to visualize the tree hierarchy.
        """
        box_drawing = []
        for i in range(instance.tree_depth - 1):
            box_drawing.append('<i class="l"></i>')
        if instance.tree_depth > 0:
            box_drawing.append('<i class="a"></i>')

        return format_html(
            '<div class="box">'
            '<div class="box-drawing">{}</div>'
            '<div class="box-text" style="text-indent:{}px">{}</div>'
            "</div>",
            mark_safe("".join(box_drawing)),
            instance.tree_depth * 30,
            instance.title,
        )

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        sections = request.user.section_set.all()
        return qs.filter(site__section__in=sections)

    def open_duplicate_form(self, request, queryset):
        return redirect(
            reverse(
                "admin:pages_Page_duplicate_page_tree",
                kwargs={"pk": queryset[0].pk},
            ))

    open_duplicate_form.short_description = _("Duplicate page-tree")

    def get_urls(self):
        urls = super().get_urls()
        return [
            path(
                "<int:pk>/duplicate/",
                self.admin_site.admin_view(self.duplicate_page_tree),
                name="pages_Page_duplicate_page_tree",
            )
        ] + urls

    def duplicate_page_tree(self, request, pk):
        page = models.Page.objects.get(pk=pk)
        form = DuplicateForm(page=page, request=request)
        if request.method == "POST":
            form = DuplicateForm(request.POST, page=page, request=request)

            if form.is_valid():
                old_pk = page.pk
                new_root = page
                language_code = form.cleaned_data["language_code"]
                site = form.cleaned_data["site"]
                link_translations = form.cleaned_data["link_translations"]
                children = page.children.all()

                new_root.pk = None
                new_root.language_code = language_code
                new_root.site = site
                new_root.slug = form.cleaned_data["new_slug"]
                new_root.path = form.cleaned_data["new_path"]
                new_root.static_path = True
                new_root.title = form.cleaned_data["new_title"]
                new_root.save()

                if link_translations:
                    new_root.translations.add(old_pk)
                    new_root.save()

                def copy_children(page, children):
                    for child in children:
                        new_children = child.children.all()
                        child.parent = page
                        old_pk = child.pk
                        child.pk = None
                        child.language_code = language_code
                        child.site = site
                        child.save()
                        if link_translations:
                            child.translations.add(old_pk)
                            child.save()
                        copy_children(child, new_children)

                copy_children(new_root, children)

                return redirect("admin:pages_page_changelist")
        context = dict(
            self.admin_site.each_context(request),
            form=form,
            title=_("Duplicate Page-Tree"),
            app_label="pages",
            opts=models.Page._meta,
            model=models.Page,
        )

        return render(request, "admin/duplicate_page_tree.html", context)