Skip to content

Commit

Permalink
Display a tag cloud with tags assigned to videos
Browse files Browse the repository at this point in the history
+ Store tag list in CACHE
+ add a reindex_videos script to recreate ES video index
  • Loading branch information
Badatos committed Dec 3, 2024
1 parent e6ed3f7 commit abd6cdc
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 47 deletions.
36 changes: 24 additions & 12 deletions pod/main/configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -5541,7 +5541,7 @@
},
"settings": {
"CAS": {
"default_value": "1.5.2",
"default_value": "1.5.3",
"description": {
"en": "",
"fr": [
Expand All @@ -5553,7 +5553,7 @@
"pod_version_init": "3.1"
},
"ModelTranslation": {
"default_value": "0.18.7",
"default_value": "0.19.11",
"description": {
"en": "",
"fr": [
Expand All @@ -5566,7 +5566,7 @@
"pod_version_init": "3.1"
},
"captcha": {
"default_value": "0.5.17",
"default_value": "0.6.0",
"description": {
"en": "",
"fr": [
Expand Down Expand Up @@ -5619,7 +5619,7 @@
"pod_version_init": "3.1"
},
"honeypot": {
"default_value": "1.0.3",
"default_value": "1.2.1",
"description": {
"en": "",
"fr": [
Expand All @@ -5632,7 +5632,7 @@
"pod_version_init": "3.1"
},
"mozilla_django_oidc": {
"default_value": "3.0.0",
"default_value": "4.0.1",
"description": {
"en": "",
"fr": [
Expand All @@ -5644,7 +5644,7 @@
"pod_version_init": "3.1"
},
"pwa": {
"default_value": "1.1.0",
"default_value": "2.0.1",
"description": {
"en": "",
"fr": [
Expand Down Expand Up @@ -5676,11 +5676,11 @@
"pod_version_init": "3.4"
},
"rest_framework": {
"default_value": "3.14.0",
"default_value": "3.15.2",
"description": {
"en": "",
"fr": [
"version 3.14.0 : mise en place de l’API rest pour l’application",
"mise en place de l’API rest pour l’application",
"[django-rest-framework.org](https://www.django-rest-framework.org/)"
]
},
Expand All @@ -5700,7 +5700,7 @@
"pod_version_init": "3.1"
},
"sorl.thumbnail": {
"default_value": "12.9.0",
"default_value": "12.11.0",
"description": {
"en": "",
"fr": [
Expand All @@ -5720,13 +5720,25 @@
"[django-tagging.readthedocs.io](https://django-tagging.readthedocs.io/en/develop/#settings)"
]
},
"pod_version_end": "",
"pod_version_end": "4.0.0",
"pod_version_init": "3.1"
},
"tagulous": {
"default_value": "2.1.0",
"description": {
"en": "",
"fr": [
"Gestion des mots-clés associés à un objet Django",
"[django-tagulous.readthedocs.io](https://django-tagulous.readthedocs.io)"
]
},
"pod_version_end": "",
"pod_version_init": "4.0.0"
}
},
"title": {
"en": "",
"fr": "Information générale"
"en": "General information",
"fr": "Informations générales"
}
}
}
Expand Down
29 changes: 29 additions & 0 deletions pod/main/static/css/pod.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
--pod-alert: #fc8670;
--pod-alert-dark: #b11030;

/* Tag cloud colors */
--pod-tag-color1: 16, 131, 22;
--pod-tag-color2: 51, 51, 170;
--pod-tag-color3: 197, 53, 143;

/**** font family ****/

/* For better accessibility, avoid fonts where [1, i, L] or [O, 0] are the same. */
Expand Down Expand Up @@ -162,6 +167,30 @@ tr,
margin-right: 0.5em;
}

/** TAGs Cloud */
.tag-cloud{
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-evenly;
}

.tag-cloud>a {
line-height: 1.5;
}

.tag-cloud>*:nth-child(2n+1) { --bs-link-color-rgb: var(--pod-tag-color1); }
.tag-cloud>*:nth-child(3n+1) { --bs-link-color-rgb: var(--pod-tag-color2); }
.tag-cloud>*:nth-child(4n+1) { --bs-link-color-rgb: var(--pod-tag-color3); }

.tag-1{font-size: 1em;}
.tag-2{font-size: 1.1em;}
.tag-3{font-size: 1.2em;}
.tag-4{font-size: 1.3em;}
.tag-5{font-size: 1.4em;}
.tag-6{font-size: 1.5em;}


.pod-card--video a:not(.btn) {
color: inherit;
}
Expand Down
15 changes: 7 additions & 8 deletions pod/main/templates/aside.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{% load i18n %}
{% load video_tags %}
{% load i18n video_tags %}
{% spaceless %}

{% if HIDE_SHARE == False %}
Expand All @@ -24,7 +23,7 @@ <h2 class="card-title pod-card__title h4">
<div class="card card-body p-3" id="card-disciplines">
<h2 class="card-title pod-card__title h4">
<label for="discipline">
<i class="bi bi-book"></i>&nbsp;{% trans 'Disciplines' %}
<i class="bi bi-book" aria-hidden="true"></i>&nbsp;{% trans 'Disciplines' %}
</label>
</h2>
<div class="card-text">
Expand All @@ -45,7 +44,7 @@ <h2 class="card-title pod-card__title h4">
<div class="card card-body p-3" id="card-types">
<h2 class="card-title pod-card__title h4">
<label for="type">
<i class="bi bi-tv"></i>&nbsp;{% trans 'Types' %}
<i class="bi bi-tv" aria-hidden="true"></i>&nbsp;{% trans 'Types' %}
</label>
</h2>
<div class="card-text">
Expand All @@ -63,14 +62,14 @@ <h2 class="card-title pod-card__title h4">
{% endif %}

{% if HIDE_TAGS == False %}
{% if tag_cloud|length > 0 %}
{% if TAGS|length > 0 %}
<div class="card card-body p-3" id="card-tags">
<h2 class="card-title pod-card__title h4">
<i class="bi bi-tag" aria-hidden="true"></i>&nbsp;{% trans 'Tags' %}
</h2>
<p class="card-text">
{% for tag in tag_cloud %}
<a href="{{ tag.get_absolute_url }}" class="tag_{{ tag.weight }}">
<p class="card-text tag-cloud">
{% for tag in TAGS %}
<a href="{% url 'videos:videos' %}?tag={{ tag.slug }}" class="btn-link pe-1 tag-{{ tag.weight }}">
{{ tag.name }}
</a>
{% endfor %}
Expand Down
4 changes: 2 additions & 2 deletions pod/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@

urlpatterns = [
path("select2/", include("django_select2.urls")),
re_path("robots.txt", robots_txt),
re_path("info_pod.json", info_pod),
path("robots.txt", robots_txt),
path("info_pod.json", info_pod),
re_path(r"^admin/", admin.site.urls),
# Translation
path("i18n/", include("django.conf.urls.i18n")),
Expand Down
8 changes: 8 additions & 0 deletions pod/video/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from pod.video.models import Discipline
from pod.video.models import Video

from pod.video.utils import get_tag_cloud

from django.db.models import Count, Sum
from django.db.models import Q
from django.db.models import Exists
Expand Down Expand Up @@ -97,6 +99,11 @@ def context_video_data(request):
)
cache.set("TYPES", types, timeout=CACHE_VIDEO_DEFAULT_TIMEOUT)

tags = cache.get("TAGS")
if tags is None:
tags = get_tag_cloud()
cache.set("TAGS", tags, timeout=CACHE_VIDEO_DEFAULT_TIMEOUT)

disciplines = cache.get("DISCIPLINES")
if disciplines is None:
disciplines = (
Expand Down Expand Up @@ -132,4 +139,5 @@ def context_video_data(request):
"VIDEOS_COUNT": VIDEOS_COUNT,
"VIDEOS_DURATION": VIDEOS_DURATION,
"CHANNELS_PER_BATCH": CHANNELS_PER_BATCH,
"TAGS": tags
}
4 changes: 2 additions & 2 deletions pod/video/management/commands/cache_video_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ class Command(BaseCommand):
+ "types, discipline, video count and videos duration"
)

def handle(self, *args, **options):
def handle(self, *args, **options) -> None:
"""Store video data in cache."""
cache.delete_many(["DISCIPLINES", "VIDEOS_COUNT", "VIDEOS_DURATION", "TYPES"])
cache.delete_many(["DISCIPLINES", "VIDEOS_COUNT", "VIDEOS_DURATION", "TYPES", "TAGS"])
video_data = context_video_data(request=None)
msg = "Successfully store video data in cache"
for data in video_data:
Expand Down
54 changes: 54 additions & 0 deletions pod/video/management/commands/reindex_videos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Script reindexing all videos (useful in case of loss of the ElasticSearch database)"""

from django.core.management.base import BaseCommand
from pod.video.models import Video
from pod.video_search.models import index_video


def reindex_all_videos(dry_run: bool) -> int:
"""Reindex all videos."""
print("\nReindexing all videos...")
videos = Video.objects.all()
nb_videos = 0
for vid in videos:
print(".", end="")
if not dry_run:
index_video(vid)
nb_videos += 1
print("")
return nb_videos


class Command(BaseCommand):
"""Reindex all videos."""

help = "Reindex all videos (useful in case of loss of the ElasticSearch database)"

def add_arguments(self, parser) -> None:
"""Allow arguments to be used with the command."""
parser.add_argument(
"--dry",
help="Simulate what would be reindexed.",
action="store_true",
default=False,
)

def handle(self, *args, **options) -> None:
"""Handle the clean_video_files command call."""
if options["dry"]:
print("Simulation mode ('dry'). Nothing will be deleted.")
self.nb_reindexed = reindex_all_videos(options["dry"])

self.print_resume(options["dry"])

def print_resume(self, dry_run: bool) -> None:
"""Print summary of reindexed objects."""

if dry_run:
print(
"[DRY RUN] %i video(s) would have been reindexed."
% (self.nb_reindexed)
)
else:
print("%i video(s) reindexed." % self.nb_reindexed)
print("Have a nice day ;)")
38 changes: 29 additions & 9 deletions pod/video/templates/videos/filter_aside.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{% load i18n %}
{% load video_tags %}
{% load thumbnail %}
{% load i18n video_tags thumbnail %}

{% spaceless %}
<div class="card card-body">
Expand Down Expand Up @@ -92,12 +90,34 @@ <h2 class="card-title pod-card__title h4">
</fieldset>
{% endif %}
{% if HIDE_TAGS == False %}
<fieldset class="border-right border-bottom mt-2">
<legend class="h5"><i class="bi bi-tag" aria-hidden="true"></i>&nbsp;{% trans 'Tags' %}</legend>
<div id="filterTag">
TODO: DISPLAY TAG CLOUD HERE.
</div>
</fieldset>
{% if TAGS|length > 0 %}
<fieldset class="border-right border-bottom mt-2">
<legend class="h5">
<i class="bi bi-tag" aria-hidden="true"></i>&nbsp;{% trans 'Tags' %}
</legend>
<div id="filterTag">
<div class="form-group collapse" id="collapseFilterTag">
{% for tag in TAGS %}
<div class="form-check">
<input class="form-check-input" type="checkbox" name="tag"
value="{{tag.slug}}" id="id{{tag.slug.split|join:'-'}}_tag" {% if tag.slug in tags_slug %}checked{% endif %}>
<label class="form-check-label" for="id{{tag.slug.split|join:'-'}}_tag">
{{tag.name}}
</label>
</div>
{% endfor %}
</div>
{% if TAGS|length > 5 %}
<span class="badge badge-light float-end">
<a class="collapsed btn-link" data-bs-toggle="collapse"
href="#collapseFilterTag" role="button"
aria-expanded="false" aria-controls="collapseFilterTag"
title="{% trans 'Fold/Unfold “Tags” filters' %}"></a>
</span>
{% endif %}
</div>
</fieldset>
{% endif %}
{% endif %}
{% if HIDE_CURSUS == False %}
<fieldset class="border-right border-bottom mt-2">
Expand Down
19 changes: 10 additions & 9 deletions pod/video/templatetags/video_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,11 @@ def get_video_infos(video):


"""
No more used functions.
To Delete in 4.0.1
class getTagsForModelNode(TagsForModelNode):
def __init__(self, model, context_var, counts):
def __init__(self, model, context_var, counts) -> None:
super(getTagsForModelNode, self).__init__(model, context_var, counts)
def render(self, context):
Expand Down Expand Up @@ -219,11 +222,10 @@ def do_tags_for_model(parser, token):
return getTagsForModelNode(bits[1], bits[3], counts=False)
else:
return getTagsForModelNode(bits[1], bits[3], counts=True)
"""
# def do_tag_cloud_for_model(parser, token):
"""
def do_tag_cloud_for_model(parser, token) -> None:
###
Retrieve a list of `Tag` objects with tag cloud attributes set.
Retriev tags for a given model,
Expand Down Expand Up @@ -260,8 +262,7 @@ def do_tags_for_model(parser, token):
{% tag_cloud_for_model products.Widget as widget_tags
with steps=9 min_count=3 distribution=log %}
"""
"""
###
bits = token.contents.split()
len_bits = len(bits)
if len_bits != 4 and len_bits not in range(6, 9):
Expand Down Expand Up @@ -341,7 +342,7 @@ def update_kwargs_from_bits(kwargs, name, value, bits):
}
)
return kwargs
"""
# register.tag("tags_for_model", do_tags_for_model)
# register.tag("tag_cloud_for_model", do_tag_cloud_for_model)
register.tag("tags_for_model", do_tags_for_model)
register.tag("tag_cloud_for_model", do_tag_cloud_for_model)
"""
Loading

0 comments on commit abd6cdc

Please sign in to comment.