Skip to content

Commit

Permalink
Merge pull request #773 from maykinmedia/feature/1714-video-homepage
Browse files Browse the repository at this point in the history
[#1713, #1714] Added basic video model, player & cms-plugin
  • Loading branch information
alextreme authored Sep 28, 2023
2 parents 5370fee + a9ffd61 commit b938865
Show file tree
Hide file tree
Showing 32 changed files with 508 additions and 0 deletions.
Empty file.
1 change: 1 addition & 0 deletions src/open_inwoner/cms/plugins/cms_plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .videoplayer import VideoPlayerPlugin
18 changes: 18 additions & 0 deletions src/open_inwoner/cms/plugins/cms_plugins/videoplayer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.utils.translation import gettext as _

from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool

from open_inwoner.cms.plugins.models.videoplayer import VideoPlayer


@plugin_pool.register_plugin
class VideoPlayerPlugin(CMSPluginBase):
model = VideoPlayer
module = _("Media")
name = _("Video Player")
render_template = "cms/plugins/videoplayer/videoplayer.html"

def render(self, context, instance, placeholder):
context.update({"instance": instance})
return context
46 changes: 46 additions & 0 deletions src/open_inwoner/cms/plugins/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generated by Django 3.2.20 on 2023-09-19 13:04

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
("media", "0001_initial"),
("cms", "0022_auto_20180620_1551"),
]

operations = [
migrations.CreateModel(
name="VideoPlayer",
fields=[
(
"cmsplugin_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
related_name="plugins_videoplayer",
serialize=False,
to="cms.cmsplugin",
),
),
(
"video",
models.ForeignKey(
help_text="The video from the catalog.",
on_delete=django.db.models.deletion.PROTECT,
to="media.video",
),
),
],
options={
"abstract": False,
},
bases=("cms.cmsplugin",),
),
]
Empty file.
1 change: 1 addition & 0 deletions src/open_inwoner/cms/plugins/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .videoplayer import VideoPlayer
20 changes: 20 additions & 0 deletions src/open_inwoner/cms/plugins/models/videoplayer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from django.db import models
from django.utils.translation import gettext_lazy as _

from cms.models import CMSPlugin

from open_inwoner.media.models import Video


class VideoPlayer(CMSPlugin):
video = models.ForeignKey(
Video,
help_text=_("The video from the catalog."),
on_delete=models.PROTECT,
)

def __str__(self):
if self.video_id:
return str(self.video)
else:
return super().__str__()
Empty file.
16 changes: 16 additions & 0 deletions src/open_inwoner/cms/plugins/tests/test_videoplayer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.test import TestCase

from open_inwoner.cms.tests import cms_tools
from open_inwoner.media.tests.factories import VideoFactory

from ..cms_plugins import VideoPlayerPlugin


class TestVideoPlayerPlugin(TestCase):
def test_plugin(self):
video = VideoFactory()
html, context = cms_tools.render_plugin(
VideoPlayerPlugin, plugin_data={"video": video}
)
self.assertIn(video.player_url, html)
self.assertIn("<iframe ", html)
3 changes: 3 additions & 0 deletions src/open_inwoner/conf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@
"open_inwoner.questionnaire",
"open_inwoner.extended_sessions",
"open_inwoner.custom_csp",
"open_inwoner.media",
"open_inwoner.cms.profile",
"open_inwoner.cms.cases",
"open_inwoner.cms.inbox",
Expand All @@ -217,6 +218,7 @@
"open_inwoner.cms.banner",
"open_inwoner.cms.extensions",
"open_inwoner.cms.footer",
"open_inwoner.cms.plugins",
]

MIDDLEWARE = [
Expand Down Expand Up @@ -533,6 +535,7 @@
"plugins": [
# "TextPlugin",
"PicturePlugin",
"VideoPlayerPlugin",
"CategoriesPlugin",
"ActivePlansPlugin",
"QuestionnairePlugin",
Expand Down
Empty file.
1 change: 1 addition & 0 deletions src/open_inwoner/media/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .video import VideoAdmin
46 changes: 46 additions & 0 deletions src/open_inwoner/media/admin/video.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from django.contrib import admin
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _

from ..models import Video


@admin.register(Video)
class VideoAdmin(admin.ModelAdmin):
fields = [
"link_id",
"title",
"player_type",
"language",
"external_url_link",
]
list_display_links = [
"link_id",
"title",
]
list_display = list_display_links + [
"player_type",
"language",
"external_url_link",
]
search_fields = [
"link_id",
"title",
]
list_filter = [
"player_type",
]
readonly_fields = [
"external_url_link",
]

@admin.display(description=_("External URL"), ordering=("player_type", "link_id"))
def external_url_link(self, video):
if not video.link_id:
return "-"
url = video.external_url
return format_html(
'<a href="{url}" rel="noopener" target="_blank">{text}</a>',
url=url,
text=url,
)
8 changes: 8 additions & 0 deletions src/open_inwoner/media/choices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.utils.translation import ugettext_lazy as _

from djchoices import ChoiceItem, DjangoChoices


class VideoPlayerChoices(DjangoChoices):
vimeo = ChoiceItem("vimeo", _("Vimeo"))
youtube = ChoiceItem("youtube", _("Youtube"))
63 changes: 63 additions & 0 deletions src/open_inwoner/media/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Generated by Django 3.2.20 on 2023-09-19 11:53

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = []

operations = [
migrations.CreateModel(
name="Video",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"link_id",
models.CharField(
help_text="https://vimeo.com/[Video ID] | https://www.youtube.com/watch?v=[Video ID]",
max_length=100,
verbose_name="video ID",
),
),
(
"player_type",
models.CharField(
choices=[("vimeo", "Vimeo"), ("youtube", "Youtube")],
default="vimeo",
max_length=200,
verbose_name="Player type",
),
),
(
"title",
models.CharField(
blank=True, default="", max_length=200, verbose_name="title"
),
),
(
"language",
models.CharField(
choices=[("nl", "Dutch")],
default="nl",
max_length=20,
verbose_name="language",
),
),
],
options={
"verbose_name": "Video",
"ordering": ("title",),
},
),
]
30 changes: 30 additions & 0 deletions src/open_inwoner/media/migrations/0002_alter_video_link_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 3.2.20 on 2023-09-25 10:01

import re

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("media", "0001_initial"),
]

operations = [
migrations.AlterField(
model_name="video",
name="link_id",
field=models.CharField(
help_text="https://vimeo.com/[Video ID] | https://www.youtube.com/watch?v=[Video ID]",
max_length=100,
validators=[
django.core.validators.RegexValidator(
"[a-z0-9_-]", flags=re.RegexFlag["IGNORECASE"]
)
],
verbose_name="video ID",
),
),
]
Empty file.
1 change: 1 addition & 0 deletions src/open_inwoner/media/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .video import Video # noqa
66 changes: 66 additions & 0 deletions src/open_inwoner/media/models/video.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import re

from django.conf import settings
from django.core.validators import RegexValidator
from django.db import models
from django.utils.translation import ugettext_lazy as _

from open_inwoner.media.choices import VideoPlayerChoices
from open_inwoner.utils.text import middle_truncate


class Video(models.Model):
link_id = models.CharField(
_("video ID"),
max_length=100,
help_text=_(
"https://vimeo.com/[Video ID] | https://www.youtube.com/watch?v=[Video ID]"
),
validators=[RegexValidator(r"[a-z0-9_-]", flags=re.IGNORECASE)],
)
player_type = models.CharField(
_("Player type"),
max_length=200,
default=VideoPlayerChoices.vimeo,
choices=VideoPlayerChoices.choices,
)
title = models.CharField(
_("title"),
max_length=200,
default="",
blank=True,
)
language = models.CharField(
_("language"),
max_length=20,
choices=settings.LANGUAGES,
default=settings.LANGUAGE_CODE,
)

class Meta:
verbose_name = _("Video")
ordering = ("title",)

def __str__(self):
if not self.title:
return self.link_id

return f"{middle_truncate(self.title, 50)} ({self.player_type}: {self.link_id}, {self.language})"

@property
def external_url(self):
if self.player_type == VideoPlayerChoices.youtube:
return f"https://www.youtube.com/watch?v={self.link_id}&enablejsapi=1"
elif self.player_type == VideoPlayerChoices.vimeo:
return f"https://vimeo.com/{self.link_id}"
else:
raise Exception("unsupported player_type")

@property
def player_url(self):
if self.player_type == VideoPlayerChoices.youtube:
return f"https://www.youtube.com/embed/{self.link_id}?enablejsapi=1&modestbranding=1"
elif self.player_type == VideoPlayerChoices.vimeo:
return f"https://player.vimeo.com/video/{self.link_id}"
else:
raise Exception("unsupported player_type")
Empty file.
12 changes: 12 additions & 0 deletions src/open_inwoner/media/tests/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import factory

from open_inwoner.media.choices import VideoPlayerChoices


class VideoFactory(factory.django.DjangoModelFactory):
link_id = factory.Faker("ean13")
title = factory.Faker("sentence")
player_type = VideoPlayerChoices.vimeo

class Meta:
model = "media.Video"
Loading

0 comments on commit b938865

Please sign in to comment.