Skip to content

Commit

Permalink
WebTV features (#1233)
Browse files Browse the repository at this point in the history
* add speaker features
* add duplication feature
* fix optional firstname
* feat: additional_owners in duplicate
* feat: duplicate confirmation button
* fix: confirmation text
* feat: jsdoc confirmDuplication function
* fix: remove useless comment
* fix: importation error
* fix: duplication error
* fix: video_duplicate docstring
* feat: REQUIRED_SPEAKER_FIRSTNAME in setting
* settings modification
  • Loading branch information
Naihl authored Jan 22, 2025
1 parent 2d84b42 commit 98c2e1d
Show file tree
Hide file tree
Showing 30 changed files with 480 additions and 22 deletions.
Empty file added pod/duplicate/__init__.py
Empty file.
Empty file added pod/duplicate/admin.py
Empty file.
7 changes: 7 additions & 0 deletions pod/duplicate/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _


class DuplicateConfig(AppConfig):
name = 'pod.duplicate'
verbose_name = _("Video duplicates")
12 changes: 12 additions & 0 deletions pod/duplicate/context_processors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Esup-Pod duplicate context processor."""

from django.conf import settings as django_settings

USE_DUPLICATE = getattr(django_settings, "USE_DUPLICATE", False)


def context_settings(request):
"""Return all context settings for duplicate app."""
new_settings = {}
new_settings["USE_DUPLICATE"] = USE_DUPLICATE
return new_settings
Empty file added pod/duplicate/models.py
Empty file.
70 changes: 70 additions & 0 deletions pod/duplicate/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# pod/video/tests/test_video_duplicate.py

from django.test import TestCase
from django.urls import reverse
from django.contrib.auth.models import User
from pod.video.models import Video, Type, Discipline, Channel, Theme


class VideoDuplicateViewTest(TestCase):
"""Test case for duplicating videos."""

def setUp(self):
"""Set up required objects for the tests."""
self.user = User.objects.create_user(username="testuser", password="password")
self.type = Type.objects.create(title="Test Type")
self.discipline = Discipline.objects.create(title="Test Discipline")
self.channel = Channel.objects.create(title="Test Channel", slug="test-channel")
self.theme = Theme.objects.create(title="Test Theme")
self.video = Video.objects.create(
title="Original Video",
slug="original-video",
type=self.type,
owner=self.user,
description="Original description",
description_fr="Description originale",
description_en="Original description",
date_evt="2023-01-01",
main_lang="en",
licence="CC BY-SA",
is_draft=False,
is_restricted=False,
allow_downloading=True,
is_360=False,
date_delete="2024-01-01",
disable_comment=False,
)
self.video.discipline.add(self.discipline)
self.video.channel.add(self.channel)
self.video.theme.add(self.theme)
self.client.login(username="testuser", password="password")

def test_video_duplicate(self):
"""Test duplicating a video."""
response = self.client.post(reverse("video_duplicate", args=[self.video.slug]))

# Check that the duplicated video exists
duplicated_video = Video.objects.get(slug="original-video-copy")
self.assertEqual(duplicated_video.title, "Copy of Original Video")
self.assertEqual(duplicated_video.type, self.type)
self.assertEqual(duplicated_video.owner, self.user)
self.assertEqual(duplicated_video.description, "Original description")
self.assertEqual(duplicated_video.description_fr, "Description originale")
self.assertEqual(duplicated_video.description_en, "Original description")
self.assertEqual(duplicated_video.date_evt, "2023-01-01")
self.assertEqual(duplicated_video.main_lang, "en")
self.assertEqual(duplicated_video.licence, "CC BY-SA")
self.assertTrue(duplicated_video.is_draft)
self.assertEqual(duplicated_video.is_restricted, False)
self.assertEqual(duplicated_video.allow_downloading, True)
self.assertEqual(duplicated_video.is_360, False)
self.assertEqual(duplicated_video.date_delete, "2024-01-01")
self.assertEqual(duplicated_video.disable_comment, False)

# Check many-to-many relations
self.assertEqual(list(duplicated_video.discipline.all()), [self.discipline])
self.assertEqual(list(duplicated_video.channel.all()), [self.channel])
self.assertEqual(list(duplicated_video.theme.all()), [self.theme])

# Check the response status code
self.assertEqual(response.status_code, 302) # Redirect after successful duplication
8 changes: 8 additions & 0 deletions pod/duplicate/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.urls import path
from .views import video_duplicate

app_name = 'duplicate'

urlpatterns = [
path('video_duplicate/<slug:slug>/', video_duplicate, name='video_duplicate'),
]
129 changes: 129 additions & 0 deletions pod/duplicate/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from pod.completion.models import Contributor, Document
from pod.speaker.models import JobVideo
from pod.video.models import Video
from django.contrib.auth.decorators import login_required
from django.utils.translation import gettext as _
from django.utils.text import slugify


def generate_unique_slug(base_slug):
"""
Generates a unique slug based on the given base slug.
Args:
base_slug (str): The base slug to be made unique.
Returns:
str: A unique slug based on the given base slug
"""
slug = base_slug
counter = 1
while Video.objects.filter(slug=slug).exists():
slug = f"{base_slug}-{counter}"
counter += 1
return slug


@login_required
def video_duplicate(request, slug):
"""
Duplicates a video and its related objects (contributors, speakers, documents) based on the given slug.
Args:
request (HttpRequest): The HTTP request object containing user information.
slug (str): The slug of the original video to be duplicated.
Returns:
HttpResponseRedirect: A redirect to the newly duplicated video's detail page.
Raises:
Http404: If the original video with the given slug does not exist.
The duplicated video will have the following properties copied from the original video:
- title (prefixed with "Copy of ")
- slug (suffixed with "-copy")
- type
- owner (set to the current user)
- description, description_fr, description_en
- date_evt
- cursus
- main_lang
- licence
- thumbnail
- is_draft (set to True)
- is_restricted
- password
- allow_downloading
- is_360
- transcript
- date_delete
- disable_comment
- tags
Additionally, the following many-to-many relationships are copied:
- discipline
- restrict_access_to_groups
- channel
- theme
- additional_owners
The following related objects are also duplicated:
- Contributors
- JobVideo (speakers)
- Documents
"""

original_video = get_object_or_404(Video, slug=slug)
new_slug = generate_unique_slug(slugify(_("%(slug)s-copy") % {'slug': original_video.slug}))

duplicated_video = Video.objects.create(
title=_("Copy of %(title)s") % {'title': original_video.title},
slug=new_slug,
type=original_video.type,
owner=request.user,
description=original_video.description,
description_fr=original_video.description_fr,
description_en=original_video.description_en,
date_evt=original_video.date_evt,
cursus=original_video.cursus,
main_lang=original_video.main_lang,
licence=original_video.licence,
thumbnail=original_video.thumbnail,
is_draft=True,
is_restricted=original_video.is_restricted,
password=original_video.password,
allow_downloading=original_video.allow_downloading,
is_360=original_video.is_360,
transcript=original_video.transcript,
date_delete=original_video.date_delete,
disable_comment=original_video.disable_comment,
tags=original_video.tags,
)

# Many-to-Many Relations
duplicated_video.discipline.set(original_video.discipline.all())
duplicated_video.restrict_access_to_groups.set(original_video.restrict_access_to_groups.all())
duplicated_video.channel.set(original_video.channel.all())
duplicated_video.theme.set(original_video.theme.all())
duplicated_video.additional_owners.set(original_video.additional_owners.all())

# Copying contributors
for contributor in Contributor.objects.filter(video=original_video):
Contributor.objects.create(
video=duplicated_video,
name=contributor.name,
email_address=contributor.email_address,
role=contributor.role,
weblink=contributor.weblink,
)

# Copying speakers
for job_video in JobVideo.objects.filter(video=original_video):
JobVideo.objects.create(
job=job_video.job,
video=duplicated_video,
)

# Copying documents
for document in Document.objects.filter(video=original_video):
Document.objects.create(
video=duplicated_video,
document=document.document,
private=document.private,
)

return redirect(reverse('video:video_edit', args=[duplicated_video.slug]))
Binary file modified pod/locale/fr/LC_MESSAGES/django.mo
Binary file not shown.
28 changes: 27 additions & 1 deletion pod/locale/fr/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Pod\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-11 15:32+0000\n"
"POT-Creation-Date: 2025-01-20 09:49+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: obado <[email protected]>\n"
"Language-Team: Pod Team [email protected]\n"
Expand Down Expand Up @@ -2167,6 +2167,20 @@ msgstr "Vous ne pouvez pas supprimer cet habillage."
msgid "Deleting the dressing “%s”"
msgstr "Supprimer l’habillage « %s »"

#: pod/duplicate/apps.py
msgid "Video duplicates"
msgstr "Duplication de vidéo"

#: pod/duplicate/views.py
#, python-format
msgid "%(slug)s-copy"
msgstr "%(slug)s-copie"

#: pod/duplicate/views.py
#, python-format
msgid "Copy of %(title)s"
msgstr "Copie de %(title)s"

#: pod/enrichment/apps.py pod/enrichment/models.py
msgid "Enrichments"
msgstr "Enrichissements"
Expand Down Expand Up @@ -9803,6 +9817,14 @@ msgstr "Chapitrer la vidéo"
msgid "Dress the video"
msgstr "Habiller la vidéo"

#: pod/video/templates/videos/link_video_dropdown_menu.html
msgid "Duplicate the video"
msgstr "Dupliquer la vidéo"

#: pod/video/templates/videos/link_video_dropdown_menu.html
msgid "Are you sure you want to duplicate this video?"
msgstr "Voulez-vous vraiment dupliquer cette vidéo ?"

#: pod/video/templates/videos/link_video_dropdown_menu.html
#: pod/video/templates/videos/video_edit.html
msgid "Delete the video"
Expand Down Expand Up @@ -10328,6 +10350,10 @@ msgstr "Description du thème"
msgid "The video is currently waiting for Aristote AI treatment."
msgstr "La vidéo est actuellement en attente du traitement par l’IA Aristote."

#: pod/video/templates/videos/video_page_content.html
msgid "The form does not contain a video."
msgstr "La fiche ne contient pas de vidéo."

#: pod/video/templates/videos/video_row_select.html
msgid "Selected"
msgstr "Sélectionné"
Expand Down
2 changes: 1 addition & 1 deletion pod/locale/fr/LC_MESSAGES/djangojs.po
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Esup-Pod\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-11 11:36+0000\n"
"POT-Creation-Date: 2025-01-20 09:49+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: obado <[email protected]>\n"
"Language-Team: \n"
Expand Down
28 changes: 27 additions & 1 deletion pod/locale/nl/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Pod\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-11 15:32+0000\n"
"POT-Creation-Date: 2025-01-20 09:49+0100\n"
"PO-Revision-Date: 2024-07-04 17:54+0200\n"
"Last-Translator: obado <[email protected]>\n"
"Language-Team: \n"
Expand Down Expand Up @@ -2077,6 +2077,20 @@ msgstr ""
msgid "Deleting the dressing “%s”"
msgstr ""

#: pod/duplicate/apps.py
msgid "Video duplicates"
msgstr ""

#: pod/duplicate/views.py
#, python-format
msgid "%(slug)s-copy"
msgstr ""

#: pod/duplicate/views.py
#, python-format
msgid "Copy of %(title)s"
msgstr ""

#: pod/enrichment/apps.py pod/enrichment/models.py
msgid "Enrichments"
msgstr ""
Expand Down Expand Up @@ -9156,6 +9170,14 @@ msgstr ""
msgid "Dress the video"
msgstr ""

#: pod/video/templates/videos/link_video_dropdown_menu.html
msgid "Duplicate the video"
msgstr ""

#: pod/video/templates/videos/link_video_dropdown_menu.html
msgid "Are you sure you want to duplicate this video?"
msgstr ""

#: pod/video/templates/videos/link_video_dropdown_menu.html
#: pod/video/templates/videos/video_edit.html
msgid "Delete the video"
Expand Down Expand Up @@ -9649,6 +9671,10 @@ msgstr ""
msgid "The video is currently waiting for Aristote AI treatment."
msgstr ""

#: pod/video/templates/videos/video_page_content.html
msgid "The form does not contain a video."
msgstr ""

#: pod/video/templates/videos/video_row_select.html
msgid "Selected"
msgstr ""
Expand Down
2 changes: 1 addition & 1 deletion pod/locale/nl/LC_MESSAGES/djangojs.po
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Esup-Pod\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-11 11:36+0000\n"
"POT-Creation-Date: 2025-01-20 09:49+0100\n"
"PO-Revision-Date: 2024-06-04 16:20+0200\n"
"Last-Translator: obado <[email protected]>\n"
"Language-Team: \n"
Expand Down
Loading

0 comments on commit 98c2e1d

Please sign in to comment.