~linuxgoose/bocpress

849fe77446d4c2485f9f0409f02cbbc7c3cfa756 — Jordan Robinson 2 months ago 089af2c
update tags filtering functionality to allow for multiple tags to be filtered on
M main/templates/assets/style.css => main/templates/assets/style.css +5 -0
@@ 320,6 320,11 @@ footer {
    text-decoration: dotted underline;
}

.active {
    font-weight: 700;
    text-decoration: underline;
}

/* mods
 * they override specific classes with specific styles */
.type-approve {

M main/templates/main/blog_posts.html => main/templates/main/blog_posts.html +21 -27
@@ 43,12 43,6 @@

    <h2 itemprop="name">{% if blog_user.posts_page_title %}{{ blog_user.posts_page_title }}{% else %}Posts{% endif %}</h2>

    {% if filter_tag %}
    <p>
        Active tag filter: <strong>{{ filter_tag }}</strong> (<a href="{% url 'post_list' %}">clear filter</a>)
    </p>
    {% endif %}

    {% if request.user.is_authenticated and request.subdomain == request.user.username and drafts %}
    <div class="drafts">
        <strong>


@@ 64,25 58,34 @@
    </div>
    {% endif %}

    {% if tag_cloud and request.user.show_tags_in_post_list %}
    <div class="tag-cloud">
        All tags:
        {% for tag, url, is_active in tag_cloud %}
            <a href="{{ url }}" class="tag {% if is_active %}active{% endif %}">{{ tag }}</a>
        {% endfor %}
    </div>
    {% endif %}

    <ul class="posts">
        {% for p in posts %}
        {% if p.published_at %}
        {% for item in posts_with_tag_urls %}
        {% if item.post.published_at %}
        <li>
            <a href="{% url 'post_detail' p.slug %}">{{ p.title }}</a>
            {% if p.tag_list and request.user.show_tags_in_post_list %}
            <small>
                <b>Tags</b>:
                {% for tag in p.tag_list %}
                    <a href="{% url 'post_list_filter' tag %}" class="tag">{{ tag }}</a>{% if not forloop.last %}, {% endif %}
                {% endfor %}
            </small>
            <a href="{% url 'post_detail' item.post.slug %}">{{ item.post.title }}</a>
            {% if item.post.tag_list and request.user.show_tags_in_post_list %}
                <small>
                    — <b>Tags</b>:
                    {% for tag, url, is_active in item.tag_urls %}
                        <a href="{{ url }}" class="tag {% if is_active %}active{% endif %}">{{ tag }}</a>
                        {% if not forloop.last %}, {% endif %}
                    {% endfor %}
                </small>
            {% endif %}
            <small>
                <b>Published on</b>:
                <time datetime="{{ p.published_at|date:'Y-m-d' }}" itemprop="datePublished">
                    {{ p.published_at|date:'F j, Y' }}
                    {{ item.post.published_at|date:'F j, Y' }}
                </time>
                {% if not p.is_published %}
                — SCHEDULED


@@ 91,15 94,6 @@
        </li>
        {% endif %}
        {% endfor %}

        {% if all_tags and request.user.show_tags_in_post_list %}
        <hr>
        <p><strong>All tags:</strong>
            {% for tag in all_tags %}
                <a href="{% url 'post_list_filter' tag %}" class="tag{% if tag == tag %} active{% endif %}">{{ tag }}</a>{% if not forloop.last %}, {% endif %}
            {% endfor %}
        </p>
        {% endif %}
    </ul>
</main>


M main/templates/main/post_list.html => main/templates/main/post_list.html +23 -28
@@ 9,39 9,43 @@
        <a href="{% url 'post_create' %}">Create a new post »</a>
    </p>
    {% if post_list %}
    {% if filter_tag %}
    <p>
        Active tag filter: <strong>{{ filter_tag }}</strong> (<a href="{% url 'post_list' %}">clear filter</a>)
    </p>

    {% if tag_cloud and request.user.show_tags_in_post_list %}
    <div class="tag-cloud">
        All tags:
        {% for tag, url, is_active in tag_cloud %}
            <a href="{{ url }}" class="tag {% if is_active %}active{% endif %}">{{ tag }}</a>
        {% endfor %}
    </div>
    {% endif %}

    <p>
        List of posts:
    </p>
    <ul>
        {% for post in post_list %}
        {% for item in posts_with_tag_urls %}
        <li>
            <a href="{% url 'post_detail' post.slug %}">
                {{ post.title }}
            <a href="{% url 'post_detail' item.post.slug %}">
                {{ item.post.title }}
            </a>
            {% if p.tag_list and request.user.show_tags_in_post_list %}
            <small>
                <b>Tags</b>:
                {% for tag in p.tag_list %}
                    <a href="{% url 'post_list_filter' tag %}" class="tag">{{ tag }}</a>{% if not forloop.last %}, {% endif %}
                {% endfor %}
            </small>
            {% if item.post.tag_list and request.user.show_tags_in_post_list %}
                <small>
                    — <b>Tags</b>:
                    {% for tag, url, is_active in item.tag_urls %}
                        <a href="{{ url }}" class="tag {% if is_active %}active{% endif %}">{{ tag }}</a>
                        {% if not forloop.last %}, {% endif %}
                    {% endfor %}
                </small>
            {% endif %}
            <small>
                <b>Published on</b>:
                {% if post.is_published %}
                <time datetime="{{ post.published_at|date:'Y-m-d' }}" itemprop="datePublished">
                    — {{ post.published_at|date:'F j, Y' }}
                {% if item.post.is_published %}
                <time datetime="{{ item.itempost.published_at|date:'Y-m-d' }}" itemprop="datePublished">
                    — {{ item.post.published_at|date:'F j, Y' }}
                </time>
                {% endif %}
                {% if not post.is_published %}
                {% if not item.post.is_published %}
                — DRAFT/SCHEDULED
                {% endif %}
            </small>


@@ 49,14 53,5 @@
        {% endfor %}
    </ul>
    {% endif %}

    {% if all_tags and request.user.show_tags_in_post_list %}
    <hr>
    <p><strong>All tags:</strong>
        {% for tag in all_tags %}
            <a href="{% url 'post_list_dashboard_filter' tag %}" class="tag{% if filter_tag == tag %} active{% endif %}">{{ tag }}</a>{% if not forloop.last %}, {% endif %}
        {% endfor %}
    </p>
    {% endif %}
</main>
{% endblock content %}

M main/urls.py => main/urls.py +0 -2
@@ 80,7 80,6 @@ urlpatterns += [
# blog posts and post snapshots
urlpatterns += [
    path("posts-workshop/", general.PostList.as_view(), name="post_list_dashboard"),
    path("posts-workshop/tag/<slug:tag>/", general.PostList.as_view(), name="post_list_dashboard_filter"),
    path(
        "post-backups/create/", general.SnapshotCreate.as_view(), name="snapshot_create"
    ),


@@ 93,7 92,6 @@ urlpatterns += [
    ),
    path("new/post/", general.PostCreate.as_view(), name="post_create"),
    path("posts/", general.post_list, name="post_list"),
    path("posts/tag/<slug:tag>/", general.post_list_filter, name="post_list_filter"),
    path("blog/<slug:slug>/", general.PostDetail.as_view(), name="post_detail"),
    path("posts/<slug:slug>/", general.post_detail_redir, name="post_detail_redir_a"),
    path("post/<slug:slug>/", general.post_detail_redir, name="post_detail_redir_b"),

M main/views/general.py => main/views/general.py +87 -63
@@ 141,59 141,44 @@ def post_list(request):

            license_url = request.build_absolute_uri(reverse('rsl_license'))

            response = render(
                request,
                "main/blog_posts.html",
                {
                    "subdomain": request.subdomain,
                    "blog_user": request.blog_user,
                    "posts": posts,
                    "drafts": drafts,
                    "pages": models.Page.objects.filter(
                        owner=request.blog_user, is_hidden=False
                    ).defer("body"),
                    "license_url": license_url,
                    "all_tags": models.Post.objects.all_unique_tags()
                },
            )
        
            # add Link header for license if applicable
            obj, created = models.ReallySimpleLicensing.objects.get_or_create(user=request.blog_user)
            if request.blog_user.reallysimplelicensing.license and request.blog_user.reallysimplelicensing.show_http:
                response["Link"] = f'<{license_url}>; rel="license"; type="application/rsl+xml"'

            return response
        else:
            return redirect("//" + settings.CANONICAL_HOST + reverse("index"))
    else:
        if request.user.is_authenticated:
            return redirect("post_list_dashboard")
        
        return render(request, "404.html")

def post_list_filter(request, tag = None):
    if hasattr(request, "subdomain"):
        if models.User.objects.filter(username=request.subdomain).exists():
            drafts = []
            if request.user.is_authenticated and request.user == request.blog_user:
                posts = models.Post.objects.filter(Q(tags__regex=rf"(^|,){re.escape(tag)}(,|$)"),owner=request.blog_user).defer(
                    "body",
                )
                drafts = models.Post.objects.filter(
                    owner=request.blog_user,
                    published_at__isnull=True,
                    tags__icontains=tag,
                ).defer("body")
            else:
                models.AnalyticPage.objects.create(user=request.blog_user, path="index")
                posts = models.Post.objects.filter(
                    Q(tags__regex=rf"(^|,){re.escape(tag)}(,|$)"),
                    owner=request.blog_user,
                    published_at__isnull=False,
                    published_at__lte=timezone.now().date(),
                ).defer("body")

            license_url = request.build_absolute_uri(reverse('rsl_license'))
            # active tags as list
            active_tags = request.GET.get("tags", "")
            active_tags = [t.strip() for t in active_tags.split(",") if t.strip()]

            # all unique tags for the user
            all_tags = models.Post.objects.filter(
                owner=request.user
            ).all_unique_tags()

            # generate tag cloud with URLs
            tag_cloud = []
            for tag in all_tags:
                if tag in active_tags:
                    remaining_tags = [t for t in active_tags if t != tag]
                    url = f"{reverse('post_list')}?tags={','.join(remaining_tags)}" if remaining_tags else reverse('post_list')
                    is_active = True
                else:
                    new_tags = active_tags + [tag]
                    url = f"{reverse('post_list')}?tags={','.join(new_tags)}"
                    is_active = False
                tag_cloud.append((tag, url, is_active))

            # generate tag URLs for each post
            posts_with_tag_urls = []
            for post in posts:
                tag_urls = []
                for tag in post.tag_list:
                    if tag in active_tags:
                        remaining = [t for t in active_tags if t != tag]
                        url = f"{reverse('post_list')}?tags={','.join(remaining)}" if remaining else reverse('post_list')
                        tag_urls.append((tag, url, True))
                    else:
                        url = f"{reverse('post_list')}?tags={','.join(active_tags + [tag])}"
                        tag_urls.append((tag, url, False))
                posts_with_tag_urls.append({
                    "post": post,
                    "tag_urls": tag_urls
                })

            response = render(
                request,


@@ 201,14 186,13 @@ def post_list_filter(request, tag = None):
                {
                    "subdomain": request.subdomain,
                    "blog_user": request.blog_user,
                    "posts": posts,
                    "drafts": drafts,
                    "pages": models.Page.objects.filter(
                        owner=request.blog_user, is_hidden=False
                    ).defer("body"),
                    "license_url": license_url,
                    "filter_tag": tag,
                    "all_tags": models.Post.objects.all_unique_tags()
                    "posts_with_tag_urls": posts_with_tag_urls,
                    "tag_cloud": tag_cloud,
                },
            )
        


@@ 225,26 209,66 @@ def post_list_filter(request, tag = None):
            return redirect("post_list_dashboard")
        
        return render(request, "404.html")
    
 
class PostList(LoginRequiredMixin, ListView):
    model = models.Post

    def get_queryset(self):
        qs = models.Post.objects.filter(owner=self.request.user)

        #tag = self.request.GET.get("tag")
        tag = self.kwargs.get("tag")
        if tag:
            qs = qs.with_tag(tag)
        tags = self.request.GET.get("tags")
        if tags:
            tag_list = [t.strip() for t in tags.split(",") if t.strip()]
            for tag in tag_list:
                qs = qs.with_tag(tag)

        return qs

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["filter_tag"] = self.kwargs.get("tag")
        context["all_tags"] = models.Post.objects.filter(

        # active tags as list
        active_tags = self.request.GET.get("tags", "")
        active_tags = [t.strip() for t in active_tags.split(",") if t.strip()]

        # all unique tags for the user
        all_tags = models.Post.objects.filter(
            owner=self.request.user
        ).all_unique_tags()

        # generate tag cloud with URLs
        tag_cloud = []
        for tag in all_tags:
            if tag in active_tags:
                remaining_tags = [t for t in active_tags if t != tag]
                url = f"{reverse('post_list_dashboard')}?tags={','.join(remaining_tags)}" if remaining_tags else reverse('post_list_dashboard')
                is_active = True
            else:
                new_tags = active_tags + [tag]
                url = f"{reverse('post_list_dashboard')}?tags={','.join(new_tags)}"
                is_active = False
            tag_cloud.append((tag, url, is_active))

        context["tag_cloud"] = tag_cloud

        # generate tag URLs for each post
        posts_with_tag_urls = []
        for post in context['object_list']:
            tag_urls = []
            for tag in post.tag_list:
                if tag in active_tags:
                    remaining = [t for t in active_tags if t != tag]
                    url = f"{reverse('post_list_dashboard')}?tags={','.join(remaining)}" if remaining else reverse('post_list_dashboard')
                    tag_urls.append((tag, url, True))
                else:
                    url = f"{reverse('post_list_dashboard')}?tags={','.join(active_tags + [tag])}"
                    tag_urls.append((tag, url, False))
            posts_with_tag_urls.append({
                "post": post,
                "tag_urls": tag_urls
            })

        context["posts_with_tag_urls"] = posts_with_tag_urls
        return context

def domain_check(request):