-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DONE] Feature dressing video (#1006)
* feature_dressing_video * make lang * flake * unit test + pydoc * Unit tests * fix dark theme * some fixes * Create migrations/__init__.py * fix encode when add watermark only * fix * Remove field site * add tests for dressing utilities * fix * Replace css by bootstrap classes * add table-sm * Use path instead url * fix * fix flake * remove id watermark * fix * fix flake * fix * fix panel admin * fix flake * [DONE] Patch elasticsearch options (#1009) * Update configuration.json * Update views.py * Update utils.py * Auto-update configuration files * [DONE] Feature import external video, add mediacad platform (#1014) * Add documentation about video platforms * Add tests * Add functions to manage import videos from Mediacad platform, and refactor some code * Add functions to manage import videos from Mediacad platform; improved error message handling * Add translations about Pod informations and Mediacad platform * Modification of a test due to improved error message handling * Add translations about Pod informations and Mediacad platform * Add translations about Pod informations and Mediacad platform * Change translation : Impossible to upload to Pod the video => Unable to upload the video to Pod; and remove fuzzy translations * Add role='alert' to one error message * Fixup. Format code with Black * [DONE] Fix jsi18n (#1011) * * Replace every `<script src="/admin/jsi18n/"></script>` by `<script id="jsi18n" src="{% url 'javascript-catalog' %}"></script>` * Add js-catalog in theme_edit.html * Add jsi18n in more scripts * Add JS catalog in caption maker * Remove every `javascript-catalog` as it is already in base.html * rename i18njs as jsi18n * Remove the "version" number in base html, as webpush also load it without version number and we do not want it to be downloaded twice. * [WIP] Fix CSS z-index for audio enrichment slide to keep them over the sound wave element (#1013) * Update views.py * 🐛 Fix z-index in audio enrichment to keep enrichement slides over the sound wave element --------- Co-authored-by: Ptitloup <nicolas.can@univ-lille.fr> * Fixup. Format code with Prettier * make lang * some fixes * fix lang * improve test settigns to add use docker setting - default to true (#1019) * Fixup. Format code with Black * [DONE] WebTV - Add private field (#1016) * init * trad * compil trad * fix * make lang * some fixes * fix * fix * [DONE] Feature import external video, add mediacad platform (#1014) * Add documentation about video platforms * Add tests * Add functions to manage import videos from Mediacad platform, and refactor some code * Add functions to manage import videos from Mediacad platform; improved error message handling * Add translations about Pod informations and Mediacad platform * Modification of a test due to improved error message handling * Add translations about Pod informations and Mediacad platform * Add translations about Pod informations and Mediacad platform * Change translation : Impossible to upload to Pod the video => Unable to upload the video to Pod; and remove fuzzy translations * Add role='alert' to one error message * Fixup. Format code with Black * make lang * some fixes * fix lang * conflits lang * compilemessages * fix * fix completion * fix * lang * fix * change Agreement required --------- Co-authored-by: PierreC <heraknoshsdj@hotmail.fr> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Loïc Bonavent <56730254+LoicBonavent@users.noreply.github.com> Co-authored-by: Olivier Bado-Faustin <bado@unice.fr> Co-authored-by: gcondess <guillaume.condesse@u-bordeaux.fr> Co-authored-by: Ptitloup <nicolas.can@univ-lille.fr>
- Loading branch information
1 parent
6eda22a
commit e205b21
Showing
38 changed files
with
1,836 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from django.contrib import admin | ||
from .models import Dressing | ||
from .forms import DressingAdminForm | ||
|
||
|
||
class DressingAdmin(admin.ModelAdmin): | ||
"""Dressing admin page.""" | ||
|
||
def get_form(self, request, obj=None, **kwargs): | ||
ModelForm = super(DressingAdmin, self).get_form(request, obj, **kwargs) | ||
|
||
class ModelFormMetaClass(ModelForm): | ||
def __new__(cls, *args, **kwargs): | ||
kwargs["request"] = request | ||
return ModelForm(*args, **kwargs) | ||
|
||
return ModelFormMetaClass | ||
|
||
form = DressingAdminForm | ||
|
||
list_display = ( | ||
"title", | ||
"watermark", | ||
"opacity", | ||
"position", | ||
"opening_credits", | ||
"ending_credits" | ||
) | ||
|
||
autocomplete_fields = [ | ||
"opening_credits", | ||
"ending_credits", | ||
] | ||
|
||
class Media: | ||
css = { | ||
"all": ( | ||
# "bootstrap/dist/css/bootstrap.min.css", | ||
# "bootstrap/dist/css/bootstrap-grid.min.css", | ||
# "css/pod.css", | ||
) | ||
} | ||
js = ( | ||
"js/main.js", | ||
"podfile/js/filewidget.js", | ||
"bootstrap/dist/js/bootstrap.min.js", | ||
) | ||
|
||
|
||
admin.site.register(Dressing, DressingAdmin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from django.apps import AppConfig | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
|
||
class DressingConfig(AppConfig): | ||
default_auto_field = 'django.db.models.BigAutoField' | ||
name = 'pod.dressing' | ||
verbose_name = _("Video dressings") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
from django import forms | ||
from django.conf import settings | ||
from pod.main.forms_utils import add_placeholder_and_asterisk | ||
from django.contrib.sites.models import Site | ||
from django_select2 import forms as s2forms | ||
from django.db.models import Q | ||
from django.utils.translation import ugettext_lazy as _ | ||
|
||
from django.contrib import admin | ||
from django.contrib.admin import widgets | ||
|
||
from pod.video.models import Video | ||
from .models import Dressing | ||
|
||
__FILEPICKER__ = False | ||
if getattr(settings, "USE_PODFILE", False): | ||
__FILEPICKER__ = True | ||
from pod.podfile.widgets import CustomFileWidget | ||
|
||
|
||
class AddOwnerWidget(s2forms.ModelSelect2MultipleWidget): | ||
"""Class AddOwnerWidget.""" | ||
search_fields = [ | ||
"username__icontains", | ||
"email__icontains", | ||
] | ||
|
||
|
||
class AddAccessGroupWidget(s2forms.ModelSelect2MultipleWidget): | ||
"""Class AddAccessGroupWidget.""" | ||
search_fields = [ | ||
"display_name__icontains", | ||
"code_name__icontains", | ||
] | ||
|
||
|
||
class AddVideoHoldWidget(s2forms.ModelSelect2Widget): | ||
"""Class AddVideoHoldWidget.""" | ||
search_fields = [ | ||
"slug__icontains", | ||
"title__icontains" | ||
] | ||
|
||
|
||
class DressingForm(forms.ModelForm): | ||
"""Form to add or edit a dressing.""" | ||
is_staff = True | ||
is_superuser = False | ||
admin_form = True | ||
|
||
def __init__(self, *args, **kwargs): | ||
"""Init method.""" | ||
self.is_staff = ( | ||
kwargs.pop("is_staff") if "is_staff" in kwargs.keys() else self.is_staff | ||
) | ||
self.is_superuser = ( | ||
kwargs.pop("is_superuser") | ||
if ("is_superuser" in kwargs.keys()) | ||
else self.is_superuser | ||
) | ||
self.user = kwargs.pop("user", None) | ||
|
||
super(DressingForm, self).__init__(*args, **kwargs) | ||
if __FILEPICKER__: | ||
self.fields["watermark"].widget = CustomFileWidget(type="image") | ||
if not self.is_superuser or not hasattr(self, "admin_form"): | ||
self.fields["owners"].queryset = self.fields["owners"].queryset.filter( | ||
owner__sites=Site.objects.get_current() | ||
) | ||
self.fields["users"].queryset = self.fields["users"].queryset.filter( | ||
owner__sites=Site.objects.get_current() | ||
) | ||
query_videos = Video.objects.filter(is_video=True).filter( | ||
Q(owner=self.user) | Q(additional_owners__in=[self.user]) | ||
) | ||
self.fields["opening_credits"].queryset = query_videos.all() | ||
self.fields["ending_credits"].queryset = query_videos.all() | ||
|
||
# change ckeditor config for no staff user | ||
if not hasattr(self, "admin_form") and ( | ||
self.is_staff is False and self.is_superuser is False | ||
): | ||
del self.fields["watermark"] | ||
# hide default langage | ||
if self.fields.get("title_%s" % settings.LANGUAGE_CODE): | ||
self.fields["title_%s" % settings.LANGUAGE_CODE].widget = forms.HiddenInput() | ||
|
||
self.fields = add_placeholder_and_asterisk(self.fields) | ||
self.fields["opacity"].widget.attrs.update({'max': '100'}) | ||
self.fields["owners"].initial = self.user | ||
|
||
class Meta(object): | ||
"""Meta class.""" | ||
model = Dressing | ||
fields = "__all__" | ||
exclude = ['videos'] | ||
widgets = { | ||
"owners": AddOwnerWidget, | ||
"users": AddOwnerWidget, | ||
"allow_to_groups": AddAccessGroupWidget, | ||
"opening_credits": AddVideoHoldWidget, | ||
"ending_credits": AddVideoHoldWidget, | ||
} | ||
|
||
|
||
class DressingDeleteForm(forms.Form): | ||
"""Form to delete a dressing.""" | ||
agree = forms.BooleanField( | ||
label=_("I agree"), | ||
help_text=_("Delete video dressing cannot be undone"), | ||
widget=forms.CheckboxInput(), | ||
) | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(DressingDeleteForm, self).__init__(*args, **kwargs) | ||
self.fields = add_placeholder_and_asterisk(self.fields) | ||
|
||
|
||
class DressingAdminForm(forms.ModelForm): | ||
"""Form for admin panel.""" | ||
def __init__(self, *args, **kwargs): | ||
self.request = kwargs.pop("request", None) | ||
super(DressingAdminForm, self).__init__(*args, **kwargs) | ||
if __FILEPICKER__ and self.fields.get("watermark"): | ||
self.fields["watermark"].widget = CustomFileWidget(type="image") | ||
|
||
def clean(self): | ||
super(DressingAdminForm, self).clean() | ||
|
||
class Meta(object): | ||
model = Dressing | ||
fields = "__all__" | ||
exclude = ['videos'] | ||
widgets = { | ||
"owners": widgets.AutocompleteSelectMultiple( | ||
Dressing._meta.get_field("owners"), | ||
admin.site, | ||
attrs={"style": "width: 20em"}, | ||
), | ||
"users": widgets.AutocompleteSelectMultiple( | ||
Dressing._meta.get_field("users"), | ||
admin.site, | ||
attrs={"style": "width: 20em"}, | ||
), | ||
"allow_to_groups": widgets.AutocompleteSelectMultiple( | ||
Dressing._meta.get_field("allow_to_groups"), | ||
admin.site, | ||
attrs={"style": "width: 20em"}, | ||
), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
"""Esup-Pod dressing models.""" | ||
from django.db import models | ||
from django.core.validators import MinValueValidator, MaxValueValidator | ||
|
||
from django.contrib.auth.models import User | ||
from pod.authentication.models import AccessGroup | ||
from pod.podfile.models import CustomImageModel | ||
from django.utils.translation import ugettext_lazy as _ | ||
from pod.video.models import Video | ||
|
||
|
||
class Dressing(models.Model): | ||
"""Class describing Dressing objects.""" | ||
TOP_RIGHT = 'top_right' | ||
TOP_LEFT = 'top_left' | ||
BOTTOM_RIGHT = 'bottom_right' | ||
BOTTOM_LEFT = 'bottom_left' | ||
POSITIONS = ( | ||
(TOP_RIGHT, _('Top right')), | ||
(TOP_LEFT, _('Top left')), | ||
(BOTTOM_RIGHT, _('Bottom right')), | ||
(BOTTOM_LEFT, _('Bottom left')), | ||
) | ||
|
||
title = models.CharField( | ||
_("Title"), | ||
max_length=100, | ||
unique=True, | ||
help_text=_( | ||
"Please choose a title as short and accurate as " | ||
"possible, reflecting the main subject / context " | ||
"of the content.(max length: 100 characters)" | ||
), | ||
) | ||
|
||
owners = models.ManyToManyField( | ||
User, | ||
related_name="owners_dressing", | ||
verbose_name=_("Owners"), | ||
blank=True, | ||
) | ||
|
||
users = models.ManyToManyField( | ||
User, | ||
related_name="users_dressing", | ||
verbose_name=_("Users"), | ||
blank=True, | ||
) | ||
|
||
allow_to_groups = models.ManyToManyField( | ||
AccessGroup, | ||
blank=True, | ||
verbose_name=_("Groups"), | ||
help_text=_("Select one or more groups who can manage and use this video dressing."), | ||
) | ||
|
||
watermark = models.ForeignKey( | ||
CustomImageModel, | ||
models.SET_NULL, | ||
blank=True, | ||
null=True, | ||
verbose_name=_("Watermark"), | ||
) | ||
|
||
position = models.CharField( | ||
verbose_name=_("Position"), | ||
max_length=200, | ||
choices=POSITIONS, | ||
default=TOP_RIGHT, | ||
blank=True, | ||
null=True, | ||
) | ||
|
||
opacity = models.PositiveIntegerField( | ||
default=100, | ||
validators=[MinValueValidator(1), MaxValueValidator(100)], | ||
blank=True, | ||
null=True, | ||
verbose_name=_("Opacity"), | ||
) | ||
|
||
opening_credits = models.ForeignKey( | ||
Video, | ||
verbose_name=_("Opening credits"), | ||
related_name="opening_credits", | ||
on_delete=models.CASCADE, | ||
null=True, | ||
blank=True, | ||
) | ||
|
||
ending_credits = models.ForeignKey( | ||
Video, | ||
verbose_name=_("Ending credits"), | ||
related_name="ending_credits", | ||
on_delete=models.CASCADE, | ||
null=True, | ||
blank=True, | ||
) | ||
|
||
videos = models.ManyToManyField( | ||
Video, | ||
related_name="videos_dressing", | ||
verbose_name=_("Videos"), | ||
blank=True, | ||
) | ||
|
||
class Meta: | ||
"""Metadata for Dressing model.""" | ||
verbose_name = _("Video dressing") | ||
verbose_name_plural = _("Video dressings") | ||
|
||
def to_json(self): | ||
"""Convert to json format for encoding logs""" | ||
return { | ||
"id": self.id, | ||
"title": self.title, | ||
"owners": list(self.owners.values_list('id', flat=True)), | ||
"users": list(self.users.values_list('id', flat=True)), | ||
"allow_to_groups": list(self.allow_to_groups.values_list('id', flat=True)), | ||
"watermark": self.watermark.file.url if self.watermark else None, | ||
"position": self.get_position_display(), | ||
"opacity": self.opacity, | ||
"opening_credits": self.opening_credits.slug if self.opening_credits else None, | ||
"ending_credits": self.ending_credits.slug if self.ending_credits else None, | ||
} |
Oops, something went wrong.