mirror of
				https://github.com/sissbruecker/linkding.git
				synced 2025-11-04 04:54:09 +01:00 
			
		
		
		
	Filter tag cloud based on search query
This commit is contained in:
		@@ -1,7 +1,7 @@
 | 
			
		||||
from django.contrib.auth.models import User
 | 
			
		||||
from django.db.models import Q, Count, Aggregate, CharField
 | 
			
		||||
 | 
			
		||||
from bookmarks.models import Bookmark
 | 
			
		||||
from bookmarks.models import Bookmark, Tag
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Concat(Aggregate):
 | 
			
		||||
@@ -22,22 +22,14 @@ def query_bookmarks(user: User, query_string: str):
 | 
			
		||||
        .annotate(tag_count=Count('tags'),
 | 
			
		||||
                  tag_string=Concat('tags__name'))
 | 
			
		||||
 | 
			
		||||
    # Sanitize query params
 | 
			
		||||
    if not query_string:
 | 
			
		||||
        query_string = ''
 | 
			
		||||
 | 
			
		||||
    # Filter for user
 | 
			
		||||
    query_set = query_set.filter(owner=user)
 | 
			
		||||
 | 
			
		||||
    # Split query into search terms and tags
 | 
			
		||||
    keywords = query_string.strip().split(' ')
 | 
			
		||||
    keywords = [word for word in keywords if word]
 | 
			
		||||
 | 
			
		||||
    search_terms = [word for word in keywords if word[0] != '#']
 | 
			
		||||
    tag_names = [word[1:] for word in keywords if word[0] == '#']
 | 
			
		||||
    query = _parse_query_string(query_string)
 | 
			
		||||
 | 
			
		||||
    # Filter for search terms and tags
 | 
			
		||||
    for term in search_terms:
 | 
			
		||||
    for term in query['search_terms']:
 | 
			
		||||
        query_set = query_set.filter(
 | 
			
		||||
            Q(title__contains=term)
 | 
			
		||||
            | Q(description__contains=term)
 | 
			
		||||
@@ -45,7 +37,7 @@ def query_bookmarks(user: User, query_string: str):
 | 
			
		||||
            | Q(website_description__contains=term)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    for tag_name in tag_names:
 | 
			
		||||
    for tag_name in query['tag_names']:
 | 
			
		||||
        query_set = query_set.filter(
 | 
			
		||||
            tags__name=tag_name
 | 
			
		||||
        )
 | 
			
		||||
@@ -54,3 +46,47 @@ def query_bookmarks(user: User, query_string: str):
 | 
			
		||||
    query_set = query_set.order_by('-date_modified')
 | 
			
		||||
 | 
			
		||||
    return query_set
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def query_tags(user: User, query_string: str):
 | 
			
		||||
    query_set = Tag.objects;
 | 
			
		||||
 | 
			
		||||
    # Filter for user
 | 
			
		||||
    query_set = query_set.filter(owner=user)
 | 
			
		||||
 | 
			
		||||
    # Split query into search terms and tags
 | 
			
		||||
    query = _parse_query_string(query_string)
 | 
			
		||||
 | 
			
		||||
    # Filter for search terms and tags
 | 
			
		||||
    for term in query['search_terms']:
 | 
			
		||||
        query_set = query_set.filter(
 | 
			
		||||
            Q(bookmark__title__contains=term)
 | 
			
		||||
            | Q(bookmark__description__contains=term)
 | 
			
		||||
            | Q(bookmark__website_title__contains=term)
 | 
			
		||||
            | Q(bookmark__website_description__contains=term)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    for tag_name in query['tag_names']:
 | 
			
		||||
        query_set = query_set.filter(
 | 
			
		||||
            bookmark__tags__name=tag_name
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    return query_set.distinct()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _parse_query_string(query_string):
 | 
			
		||||
    # Sanitize query params
 | 
			
		||||
    if not query_string:
 | 
			
		||||
        query_string = ''
 | 
			
		||||
 | 
			
		||||
    # Split query into search terms and tags
 | 
			
		||||
    keywords = query_string.strip().split(' ')
 | 
			
		||||
    keywords = [word for word in keywords if word]
 | 
			
		||||
 | 
			
		||||
    search_terms = [word for word in keywords if word[0] != '#']
 | 
			
		||||
    tag_names = [word[1:] for word in keywords if word[0] == '#']
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        'search_terms': search_terms,
 | 
			
		||||
        'tag_names': tag_names,
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ ul.bookmark-list {
 | 
			
		||||
    margin-bottom: 0.4rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .group-label {
 | 
			
		||||
  .highlight-char {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    text-transform: uppercase;
 | 
			
		||||
    color: $alternative-color-dark;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,20 @@
 | 
			
		||||
<div class="tag-cloud">
 | 
			
		||||
    {% for group in groups %}
 | 
			
		||||
        <p class="group">
 | 
			
		||||
            <span class="group-label mr-2">{{ group.char }}</span>
 | 
			
		||||
            {% for tag in group.tags %}
 | 
			
		||||
                <a href="?{% append_query_param q=tag.name|hash_tag %}">
 | 
			
		||||
                    <span class="mr-2">{{ tag.name }}</span>
 | 
			
		||||
                </a>
 | 
			
		||||
                {# Highlight first char of first tag in group #}
 | 
			
		||||
                {% if forloop.counter == 1 %}
 | 
			
		||||
                    <a href="?{% append_query_param q=tag.name|hash_tag %}"
 | 
			
		||||
                       class="mr-2">
 | 
			
		||||
                        <span class="highlight-char">{{ tag.name|first_char }}</span><span>{{ tag.name|remaining_chars:1 }}</span>
 | 
			
		||||
                    </a>
 | 
			
		||||
                {% else %}
 | 
			
		||||
                    {# Render remaining tags normally #}
 | 
			
		||||
                    <a href="?{% append_query_param q=tag.name|hash_tag %}"
 | 
			
		||||
                       class="mr-2">
 | 
			
		||||
                        <span>{{ tag.name }}</span>
 | 
			
		||||
                    </a>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
        </p>
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,3 +33,13 @@ def append_query_param(context, **kwargs):
 | 
			
		||||
@register.filter(name='hash_tag')
 | 
			
		||||
def hash_tag(tag_name):
 | 
			
		||||
    return '#' + tag_name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.filter(name='first_char')
 | 
			
		||||
def first_char(text):
 | 
			
		||||
    return text[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.filter(name='remaining_chars')
 | 
			
		||||
def remaining_chars(text, index):
 | 
			
		||||
    return text[index:]
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ from django.shortcuts import render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
 | 
			
		||||
from bookmarks import queries
 | 
			
		||||
from bookmarks.models import Bookmark, BookmarkForm, Tag
 | 
			
		||||
from bookmarks.models import Bookmark, BookmarkForm
 | 
			
		||||
from bookmarks.services.bookmarks import create_bookmark, update_bookmark
 | 
			
		||||
 | 
			
		||||
_default_page_size = 30
 | 
			
		||||
@@ -16,7 +16,7 @@ def index(request):
 | 
			
		||||
    query_set = queries.query_bookmarks(request.user, query_string)
 | 
			
		||||
    paginator = Paginator(query_set, _default_page_size)
 | 
			
		||||
    bookmarks = paginator.get_page(page)
 | 
			
		||||
    tags = Tag.objects.all()
 | 
			
		||||
    tags = queries.query_tags(request.user, query_string)
 | 
			
		||||
 | 
			
		||||
    if request.GET.get('tag'):
 | 
			
		||||
        mod = request.GET.copy()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user