Commit cc49cd6d authored by Craig Weber's avatar Craig Weber Committed by Seb
Browse files

Add support for Wagtail 4.0

parent d66ec4eb
...@@ -18,8 +18,8 @@ setup( ...@@ -18,8 +18,8 @@ setup(
url='https://github.com/neon-jungle/wagtailvideos', url='https://github.com/neon-jungle/wagtailvideos',
install_requires=[ install_requires=[
'wagtail>=2.5', 'wagtail>=4.0',
'Django>=2.0', 'Django>=3.2',
'django-enumchoicefield>=1.1.0', 'django-enumchoicefield>=1.1.0',
'bcp47==0.0.4', 'bcp47==0.0.4',
], ],
......
...@@ -11,7 +11,7 @@ class VideoChooserBlock(ChooserBlock): ...@@ -11,7 +11,7 @@ class VideoChooserBlock(ChooserBlock):
@cached_property @cached_property
def widget(self): def widget(self):
from wagtailvideos.widgets import AdminVideoChooser from wagtailvideos.widgets import AdminVideoChooser
return AdminVideoChooser return AdminVideoChooser()
def render_basic(self, value, context=None): def render_basic(self, value, context=None):
if value: if value:
......
from wagtail.admin.edit_handlers import BaseChooserPanel from wagtail.admin.panels import FieldPanel
from .widgets import AdminVideoChooser from .widgets import AdminVideoChooser
class VideoChooserPanel(BaseChooserPanel): class VideoChooserPanel(FieldPanel):
model = None model = None
field_name = None field_name = None
_target_model = None _target_model = None
......
var VIDEO_CHOOSER_MODAL_ONLOAD_HANDLERS = {
chooser: function(modal, jsonData) {
var searchUrl = $('form.video-search', modal.body).attr('action');
/* currentTag stores the tag currently being filtered on, so that we can
preserve this when paginating */
var currentTag;
function ajaxifyLinks(context) {
$('.listing a', context).click(function() {
modal.loadUrl(this.href);
return false;
});
$('.pagination a', context).click(function() {
var page = this.getAttribute('data-page');
setPage(page);
return false;
});
}
function fetchResults(requestData) {
$.ajax({
url: searchUrl,
data: requestData,
success: function(data, status) {
$('#image-results').html(data);
ajaxifyLinks($('#image-results'));
}
});
}
function search() {
/* Searching causes currentTag to be cleared - otherwise there's
no way to de-select a tag */
currentTag = null;
fetchResults({
q: $('#id_q').val(),
collection_id: $('#collection_chooser_collection_id').val()
});
return false;
}
function setPage(page) {
var params = { p: page };
if ($('#id_q').val().length) {
params['q'] = $('#id_q').val();
}
if (currentTag) {
params['tag'] = currentTag;
}
params['collection_id'] = $('#collection_chooser_collection_id').val();
fetchResults(params);
return false;
}
ajaxifyLinks(modal.body);
$('form.video-upload', modal.body).submit(function() {
var formdata = new FormData(this);
$.ajax({
url: this.action,
data: formdata,
processData: false,
contentType: false,
type: 'POST',
dataType: 'text',
success: function(response) {
modal.loadResponseText(response);
},
error: function(response, textStatus, errorThrown) {
var message = jsonData['error_message'] + '<br />' + errorThrown + ' - ' + response.status;
$('#upload').append(
'<div class="help-block help-critical">' + '<strong>' + jsonData['error_label'] + ': </strong>' + message + '</div>'
);
}
});
return false;
});
$('form.video-search', modal.body).submit(search);
$('#id_q').on('input', function() {
clearTimeout($.data(this, 'timer'));
var wait = setTimeout(search, 200);
$(this).data('timer', wait);
});
$('#collection_chooser_collection_id').change(search);
$('a.suggested-tag').click(function() {
currentTag = $(this).text();
$('#id_q').val('');
fetchResults({
tag: currentTag,
collection_id: $('#collection_chooser_collection_id').val()
});
return false;
});
/* Add tag entry interface (with autocompletion) to the tag field of the image upload form */
// $('#id_tags', modal.body).tagit({
// autocomplete: {source: "{{ autocomplete_url|addslashes }}"}
// });
},
video_chosen: function(modal, jsonData) {
modal.respond('videoChosen', jsonData['result']);
modal.close();
}
};
const ImageChooserFactory = window.telepath.constructors['wagtail.images.widgets.ImageChooser'];
class VideoChooserFactory extends ImageChooserFactory {
// eslint-disable-next-line no-undef
widgetClass = VideoChooser;
}
window.telepath.register('wagtailvideos.widgets.VideoChooser', VideoChooserFactory);
function createVideoChooser(id) { class VideoChooser extends window.ImageChooser {
var chooserElement = $('#' + id + '-chooser');
var previewVideo = chooserElement.find('.preview-image img');
var input = $('#' + id);
var editLink = chooserElement.find('.edit-link');
document.addEventListener('DOMContentLoaded', event => {
$.ajax(window.chooserUrls.videoChooser + input.val()).done(data => {
let videoData = data.result
input.val(videoData.id);
previewVideo.attr({
src: videoData.preview.url,
alt: videoData.title
});
chooserElement.removeClass('blank');
editLink.attr('href', videoData.edit_link);
});
});
$('.action-choose', chooserElement).click(function() {
ModalWorkflow({
url: window.chooserUrls.videoChooser,
onload: VIDEO_CHOOSER_MODAL_ONLOAD_HANDLERS,
responses: {
videoChosen: function(videoData) {
input.val(videoData.id);
previewVideo.attr({
src: videoData.preview.url,
alt: videoData.title
});
chooserElement.removeClass('blank');
editLink.attr('href', videoData.edit_link);
}
}
});
});
$('.action-clear', chooserElement).click(function() {
input.val('');
chooserElement.addClass('blank');
});
} }
window.VideoChooser = VideoChooser;
{% load i18n %} {% extends "wagtailadmin/generic/chooser/chooser.html" %}
{% trans "Choose a video" as choose_str %}
{% include "wagtailadmin/shared/header.html" with title=choose_str merged=1 tabbed=1 icon="media" %}
{% if uploadform %} {% load i18n wagtailadmin_tags %}
<ul class="tab-nav merged" data-tab-nav>
<li class="{% if not uploadform.errors %}active{% endif %}"><a href="#search" >{% trans "Search" %}</a></li>
<li class="{% if uploadform.errors %}active{% endif %}"><a href="#upload">{% trans "Upload" %}</a></li>
</ul>
{% endif %}
<div class="tab-content"> {% block filter_form %}
<section id="search" class="{% if not uploadform.errors %}active{% endif %} nice-padding"> <form
<form class="video-search search-bar" action="{% url 'wagtailvideos:chooser' %}" method="GET" autocomplete="off"> data-chooser-modal-search
<ul class="fields"> class="search-bar"
{% for field in searchform %} action="{{ results_url }}"
{% include "wagtailadmin/shared/field_as_li.html" with field=field %} method="GET"
{% endfor %} autocomplete="off"
{% if collections %} novalidate
{% include "wagtailadmin/shared/collection_chooser.html" %} >
{% endif %} <ul class="fields">
{% if popular_tags %} {% for field in filter_form %}
<li class="taglist"> {% include "wagtailadmin/shared/field_as_li.html" with field=field %}
<h3>{% trans 'Popular tags' %}</h3> {% endfor %}
{% for tag in popular_tags %} {% if popular_tags %}
<a class="suggested-tag tag" href="{% url 'wagtailvideos:index' %}?tag={{ tag.name|urlencode }}">{{ tag.name }}</a> <li class="taglist w-label-3">
{% endfor %} <h3>{% trans 'Popular tags' %}</h3>
</li> {% for tag in popular_tags %}
{% endif %} <a class="suggested-tag tag" href="{% url 'wagtailvideos:index' %}?tag={{ tag.name|urlencode }}">{{ tag.name }}</a>
</ul>
</form>
<div id="image-results">
{% include "wagtailvideos/chooser/results.html" %}
</div>
</section>
{% if uploadform %}
<section id="upload" class="{% if uploadform.errors %}active{% endif %} nice-padding">
<form class="video-upload" action="{% url 'wagtailvideos:chooser_upload' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<ul class="fields">
{% for field in uploadform %}
{% if field.is_hidden %}
{{ field }}
{% else %}
{% include "wagtailadmin/shared/field_as_li.html" with field=field %}
{% endif %}
{% endfor %} {% endfor %}
<li> </li>
<button type="submit" class="button button-longrunning" data-clicked-text="{% trans 'Uploading...' %}"><span class="icon icon-spinner"></span><em>{% trans 'Upload' %}</em></button> {% endif %}
</li> </ul>
</ul> </form>
</form> {% endblock %}
</section>
{% endif %}
</div>
{% load wagtailadmin_tags %} {% extends "wagtailadmin/generic/chooser/results.html" %}
{% load i18n %} {% load i18n wagtailadmin_tags %}
{% if videos %}
{% if is_searching %}
<h2>
{% blocktrans count counter=videos.paginator.count %}
There is one match
{% plural %}
There are {{ counter }} matches
{% endblocktrans %}
</h2>
{% else %}
<h2>{% trans "Latest videos" %}</h2>
{% endif %}
{% block listing_title %}<h2>{% trans "Latest videos" %}</h2>{% endblock %}
{% block results_listing %}
<ul class="listing horiz images chooser"> <ul class="listing horiz images chooser">
{% for video in videos %} {% for video in results %}
<li> <li>
<a class="image-choice" href="{% if will_select_format %}{% url 'wagtailvideos:chooser_select_format' video.id %}{% else %}{% url 'wagtailvideos:video_chosen' video.id %}{% endif %}"> <a
data-chooser-modal-choice
class="image-choice"
title="{{ video.title }}"
href="{% url 'wagtailvideos_chooser:chosen' video.id %}"
>
<div class="image"> <div class="image">
{% if video.thumbnail %} {% if video.thumbnail %}
<img src="{{ video.thumbnail.url }}" width="165" height="165" class="show-transparency" alt="{% trans 'Video thumbnail' %}"/> <img
src="{{ video.thumbnail.url }}"
width="165"
height="165"
class="show-transparency"
alt="{% trans 'Video thumbnail' %}"
/>
{% else %} {% else %}
<img width="165" height="165" class="show-transparency" alt=""/> <img
width="165"
height="165"
class="show-transparency"
alt=""
/>
{% endif %} {% endif %}
</div> </div>
<h3>{{ video.title|ellipsistrim:60 }}</h3> <h3>{{ video.title|ellipsistrim:60 }}</h3>
...@@ -29,5 +36,19 @@ ...@@ -29,5 +36,19 @@
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{% include "wagtailadmin/shared/ajax_pagination_nav.html" with items=videos %} {% endblock %}
{% endif %}
{% block no_items_message %}
<p>
{% if is_filtering_by_collection %}
{% trans "You haven't uploaded any videos in this collection." %}
{% else %}
{% trans "You haven't uploaded any videos." %}
{% endif %}
{% if can_create %}
{% blocktrans trimmed %}
Why not <a class="upload-one-now" href="#tab-upload" data-tab-trigger>upload one now</a>?
{% endblocktrans %}
{% endif %}
</p>
{% endblock %}
{% load i18n wagtailadmin_tags %} {% load i18n wagtailadmin_tags %}
<li class="icon icon-media"> <li>
{% icon name="media" %}
<a href="{% url 'wagtailvideos:index' %}"> <a href="{% url 'wagtailvideos:index' %}">
{% blocktrans count counter=total_videos with total_videos|intcomma as total %} {% blocktrans count counter=total_videos with total_videos|intcomma as total %}
<span>{{ total }}</span> Video <span class="visuallyhidden">created in {{ site_name }}</span> <span>{{ total }}</span> Video <span class="visuallyhidden">created in {{ site_name }}</span>
{% plural %} {% plural %}
<span>{{ total }}</span> Videos <span class="visuallyhidden">created in {{ site_name }}</span> <span>{{ total }}</span> Videos <span class="visuallyhidden">created in {{ site_name }}</span>
{% endblocktrans %} {% endblocktrans %}
</a> </a>
</li> </li>
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
window.headerSearch = { window.headerSearch = {
url: "{% url 'wagtailvideos:index' %}", url: "{% url 'wagtailvideos:index' %}",
termInput: "#id_q", termInput: "#id_q",
targetOutput: "#video-results" targetOutput: "#image-results"
} }
$(function() { $(function() {
......
{% extends "wagtailadmin/widgets/chooser.html" %} {% extends "wagtailadmin/widgets/chooser.html" %}
{% load i18n %} {% load i18n %}
{% block chooser_class %}image-chooser{% endblock %}
{% block chosen_state_view %} {% block chosen_icon %}
<div class="preview-image"> {# Empty alt because the chosen item’s title is already displayed next to the image. #}
{% if video and video.thumbnail %} <img
<img src="{{ video.thumbnail.url }}" width="165" height="165" class="show-transparency" alt="{% trans 'Video thumbnail' %}"/> class="chooser__image"
{% else %} data-chooser-image
<img width="165" height="165" class="show-transparency" alt=""/> alt=""
{% endif %} class="show-transparency"
</div> height="{{ preview.height }}"
{% endblock %} width="{{ preview.width }}"
src="{{ preview.url }}"
{% block edit_chosen_item_url %}{% if video %}{% url 'wagtailvideos:edit' video.id %}{% endif %}{% endblock %} />
{% endblock chosen_icon %}
from django.urls import path, re_path from django.urls import path, re_path
from wagtailvideos.views import chooser, multiple, videos from wagtailvideos.views import multiple, videos
app_name = 'wagtailvideos' app_name = 'wagtailvideos'
urlpatterns = [ urlpatterns = [
...@@ -11,10 +11,6 @@ urlpatterns = [ ...@@ -11,10 +11,6 @@ urlpatterns = [
re_path(r'^multiple/(\d+)/delete/$', multiple.delete, name='delete_multiple'), re_path(r'^multiple/(\d+)/delete/$', multiple.delete, name='delete_multiple'),
re_path(r'^multiple/(\d+)/$', multiple.edit, name='edit_multiple'), re_path(r'^multiple/(\d+)/$', multiple.edit, name='edit_multiple'),
path('chooser/upload/', chooser.chooser_upload, name='chooser_upload'),
re_path(r'^chooser/(\d+)/$', chooser.video_chosen, name='video_chosen'),
path('chooser/', chooser.chooser, name='chooser'),
re_path(r'^(\d+)/delete/$', videos.delete, name='delete'), re_path(r'^(\d+)/delete/$', videos.delete, name='delete'),
re_path(r'^(\d+)/create_transcode/$', videos.create_transcode, name='create_transcode'), re_path(r'^(\d+)/create_transcode/$', videos.create_transcode, name='create_transcode'),
re_path(r'^(\d+)/$', videos.edit, name='edit'), re_path(r'^(\d+)/$', videos.edit, name='edit'),
......
from distutils.version import LooseVersion from django.conf import settings
from django.utils.translation import gettext_lazy as _
import wagtail
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404, render
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext as _ from django.views.generic.base import View
from wagtail.admin.forms.search import SearchForm from django.utils.functional import cached_property
from wagtail.admin.modal_workflow import render_modal_workflow
from wagtail.core.models import Collection from wagtail.admin.auth import PermissionPolicyChecker
from wagtail.search import index as search_index from wagtail.admin.models import popular_tags_for_model
from wagtail.admin.views.generic.chooser import (
BaseChooseView,
ChooseResultsViewMixin,
ChooseViewMixin,
ChosenResponseMixin,
ChosenViewMixin,
CreateViewMixin,
CreationFormMixin,
)
from wagtail.admin.viewsets.chooser import ChooserViewSet
from wagtailvideos import get_video_model from wagtailvideos import get_video_model
from wagtailvideos.forms import get_video_form from wagtailvideos.forms import get_video_form
from wagtailvideos.permissions import permission_policy from wagtailvideos.permissions import permission_policy
if LooseVersion(wagtail.__version__) >= LooseVersion('2.7'):
from wagtail.admin.auth import PermissionPolicyChecker
from wagtail.admin.models import popular_tags_for_model
else:
from wagtail.admin.utils import (
PermissionPolicyChecker, popular_tags_for_model)
permission_checker = PermissionPolicyChecker(permission_policy) permission_checker = PermissionPolicyChecker(permission_policy)
def get_chooser_js_data(): class VideoChosenResponseMixin(ChosenResponseMixin):
"""construct context variables needed by the chooser JS""" def get_chosen_response_data(self, video):
return { response_data = super().get_chosen_response_data(video)
'step': 'chooser', response_data["preview"] = {
'error_label': _("Server Error"), "url": video.thumbnail.url if video.thumbnail else "",
'error_message': _("Report this error to your webmaster with the following information:"), "width": 165,
'tag_autocomplete_url': reverse('wagtailadmin_tag_autocomplete'), "height": 165,
}
def get_video_json(video):
"""
helper function: given a video, return the json to pass back to the
video chooser panel
"""
return {
'id': video.id,
'edit_link': reverse('wagtailvideos:edit', args=(video.id,)),
'title': video.title,
'preview': {
'url': video.thumbnail.url if video.thumbnail else '',
} }
} return response_data
def chooser(request): class VideoCreationFormMixin(CreationFormMixin):
Video = get_video_model() creation_tab_id = "upload"
VideoForm = get_video_form(Video) create_action_label = _("Upload")
uploadform = VideoForm() create_action_clicked_label = _("Uploading…")
permission_policy = permission_policy
videos = Video.objects.order_by('-created_at')
def get_creation_form_class(self):
q = None return get_video_form(self.model)
if (
'q' in request.GET or 'p' in request.GET or 'tag' in request.GET def get_creation_form_kwargs(self):
or 'collection_id' in request.GET kwargs = super().get_creation_form_kwargs()
): if self.request.method in ("POST", "PUT"):
# this request is triggered from search, pagination or 'popular tags'; kwargs["instance"] = self.model(uploaded_by_user=self.request.user)
# we will just render the results.html fragment return kwargs
collection_id = request.GET.get('collection_id')
if collection_id:
videos = videos.filter(collection=collection_id) class BaseVideoChooseView(BaseChooseView):
template_name = "wagtailvideos/chooser/chooser.html"
collections = permission_policy.collections_user_has_any_permission_for( results_template_name = "wagtailvideos/chooser/results.html"
request.user, ['choose']) per_page = getattr(settings, "WAGTAILVIDEOS_CHOOSER_PAGE_SIZE", 12)
ordering = "-created_at"
if len(collections) > 0:
videos = videos.filter(collection__in=collections) def get_object_list(self):
return (
searchform = SearchForm(request.GET) permission_policy.instances_user_has_any_permission_for(
if searchform.is_valid(): self.request.user, ["choose"]
q = searchform.cleaned_data['q'] )
.select_related("collection")
videos = videos.search(q)
is_searching = True
else:
is_searching = False
tag_name = request.GET.get('tag')
if tag_name:
videos = videos.filter(tags__name=tag_name)
# Pagination
paginator = Paginator(videos, per_page=12)
page = paginator.get_page(request.GET.get('p'))
return render(request, "wagtailvideos/chooser/results.html", {
'videos': page,
'is_searching': is_searching,
'query_string': q,
})
else:
searchform = SearchForm()
collections = permission_policy.collections_user_has_permission_for(
request.user, 'choose'
) )
def filter_object_list(self, objects):
tag_name = self.request.GET.get("tag")
if tag_name:
objects = objects.filter(tags__name=tag_name)
return super().filter_object_list(objects)
def get_filter_form(self):
FilterForm = self.get_filter_form_class()
return FilterForm(self.request.GET, collections=self.collections)
@cached_property
def collections(self):
collections = self.permission_policy.collections_user_has_permission_for(
self.request.user, "choose"
)
if len(collections) < 2: if len(collections) < 2:
collections = None return None
paginator = Paginator(videos, per_page=12) return collections
page = paginator.get_page(request.GET.get('p'))
return render_modal_workflow(request, 'wagtailvideos/chooser/chooser.html', None, { def get(self, request):
'videos': page, self.model = get_video_model()
'uploadform': uploadform, return super().get(request)
'searchform': searchform,
'is_searching': False,
'query_string': q,
'popular_tags': popular_tags_for_model(Video),
'collections': collections,
}, json_data=get_chooser_js_data())
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update(
{
"collections": self.collections,
}
)
return context
def video_chosen(request, video_id):
video = get_object_or_404(get_video_model(), id=video_id)
return render_modal_workflow( class VideoChooseViewMixin(ChooseViewMixin):
request, None, json_data={ def get_context_data(self, **kwargs):
'step': 'video_chosen', context = super().get_context_data(**kwargs)
'result': get_video_json(video) context["popular_tags"] = popular_tags_for_model(self.model)
}) return context
def get_response_json_data(self):
json_data = super().get_response_json_data()
json_data["tag_autocomplete_url"] = reverse("wagtailadmin_tag_autocomplete")
return json_data
@permission_checker.require('add')
def chooser_upload(request):
Video = get_video_model()
VideoForm = get_video_form(Video)
searchform = SearchForm() class VideoChooseView(
VideoChooseViewMixin, VideoCreationFormMixin, BaseVideoChooseView
):
pass
if request.POST:
video = Video(uploaded_by_user=request.user)
form = VideoForm(request.POST, request.FILES, instance=video)
if form.is_valid(): class VideoChooseResultsView(
video.uploaded_by_user = request.user ChooseResultsViewMixin, VideoCreationFormMixin, BaseVideoChooseView
video.save() ):
pass
# Reindex the video to make sure all tags are indexed
search_index.insert_or_update_object(video)
return render_modal_workflow( class VideoChosenView(ChosenViewMixin, VideoChosenResponseMixin, View):
request, None, json_data={ def get(self, request, *args, pk, **kwargs):
'step': 'video_chosen', self.model = get_video_model()
'result': get_video_json(video) return super().get(request, *args, pk, **kwargs)
}
)
else: class VideoUploadViewMixin(CreateViewMixin):
form = VideoForm() def get(self, request):
self.model = get_video_model()
videos = Video.objects.order_by('title') return super().get(request)
paginator = Paginator(videos, per_page=12)
page = paginator.get_page(request.GET.get('p')) def post(self, request):
self.model = get_video_model()
return render_modal_workflow( self.form = self.get_creation_form()
request, 'wagtailvideos/chooser/chooser.html', None,
template_vars={'videos': page, 'uploadform': form, 'searchform': searchform}, if self.form.is_valid():
json_data=get_chooser_js_data() image = self.save_form(self.form)
)
# not specifying a format; return the image details now
return self.get_chosen_response(image)
else: # form is invalid
return self.get_reshow_creation_form_response()
class VideoUploadView(
VideoUploadViewMixin, VideoCreationFormMixin, VideoChosenResponseMixin, View
):
pass
class VideoChooserViewSet(ChooserViewSet):
choose_view_class = VideoChooseView
choose_results_view_class = VideoChooseResultsView
chosen_view_class = VideoChosenView
create_view_class = VideoUploadView
permission_policy = permission_policy
register_widget = False
icon = "media"
choose_one_text = _("Choose a video")
create_action_label = _("Upload")
create_action_clicked_label = _("Uploading…")
viewset = VideoChooserViewSet(
"wagtailvideos_chooser",
model=get_video_model(),
url_prefix="videos/chooser",
)
...@@ -13,6 +13,7 @@ from wagtail.core import hooks ...@@ -13,6 +13,7 @@ from wagtail.core import hooks
from wagtailvideos import get_video_model, is_modeladmin_installed, urls from wagtailvideos import get_video_model, is_modeladmin_installed, urls
from wagtailvideos.edit_handlers import VideoChooserPanel from wagtailvideos.edit_handlers import VideoChooserPanel
from wagtailvideos.forms import GroupVideoPermissionFormSet from wagtailvideos.forms import GroupVideoPermissionFormSet
from wagtailvideos.views.chooser import viewset as chooser_viewset
from .permissions import permission_policy from .permissions import permission_policy
...@@ -55,7 +56,7 @@ def editor_js(): ...@@ -55,7 +56,7 @@ def editor_js():
window.chooserUrls.videoChooser = '{0}'; window.chooserUrls.videoChooser = '{0}';
</script> </script>
""", """,
reverse('wagtailvideos:chooser') reverse('wagtailvideos_chooser:choose')
) )
...@@ -103,9 +104,9 @@ def hide_track_listing_main(request, menu_items): ...@@ -103,9 +104,9 @@ def hide_track_listing_main(request, menu_items):
class VideoSummaryItem(SummaryItem): class VideoSummaryItem(SummaryItem):
order = 300 order = 300
template = "wagtailvideos/homepage/videos_summary.html" template_name = "wagtailvideos/homepage/videos_summary.html"
def get_context(self): def get_context_data(self, parent_context):
return { return {
"total_videos": Video.objects.count(), "total_videos": Video.objects.count(),
} }
...@@ -142,3 +143,8 @@ def register_media_search_area(): ...@@ -142,3 +143,8 @@ def register_media_search_area():
@hooks.register('insert_global_admin_css') @hooks.register('insert_global_admin_css')
def summary_css(): def summary_css():
return format_html('<link rel="stylesheet" href="{}">', static('wagtailvideos/css/summary-override.css')) return format_html('<link rel="stylesheet" href="{}">', static('wagtailvideos/css/summary-override.css'))
@hooks.register("register_admin_viewset")
def register_image_chooser_viewset():
return chooser_viewset
import json import json
from django.template.loader import render_to_string from django import forms
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from wagtail.admin.widgets import AdminChooser
from wagtail.admin.staticfiles import versioned_static
from wagtail.admin.widgets import BaseChooser, BaseChooserAdapter
from wagtail.telepath import register
from wagtailvideos import get_video_model from wagtailvideos import get_video_model
class AdminVideoChooser(AdminChooser): class AdminVideoChooser(BaseChooser):
choose_one_text = _('Choose a video') choose_one_text = _('Choose a video')
choose_another_text = _('Choose another video') template_name = "wagtailvideos/widgets/video_chooser.html"
link_to_chosen_text = _('Edit this video') chooser_modal_url_name = "wagtailvideos_chooser:choose"
icon = "media"
classname = "image-chooser"
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(AdminVideoChooser, self).__init__(**kwargs) super().__init__(**kwargs)
self.video_model = get_video_model() self.model = get_video_model()
def render_html(self, name, value, attrs): def get_value_data_from_instance(self, instance):
instance, value_data = self.get_instance_and_id(self.video_model, value) data = super().get_value_data_from_instance(instance)
data["preview"] = {
original_field_html = super(AdminVideoChooser, self).render_html(name, value, attrs) "url": instance.thumbnail.url if instance.thumbnail else "",
"width": 165,
return render_to_string("wagtailvideos/widgets/video_chooser.html", { "height": 165,
'widget': self, }
'original_field_html': original_field_html, return data
'attrs': attrs,
'value': value_data, def get_context(self, name, value_data, attrs):
'video': instance, context = super().get_context(name, value_data, attrs)
}) context["preview"] = value_data.get("preview", {})
return context
def render_js_init(self, id_, name, value):
return "createVideoChooser({0});".format(json.dumps(id_)) def render_js_init(self, id_, name, value_data):
return "new VideoChooser({0});".format(json.dumps(id_))
class Media:
js = [ @property
'wagtailvideos/js/video-chooser-modal.js', def media(self):
'wagtailvideos/js/video-chooser.js', return forms.Media(
] js=[
versioned_static("wagtailimages/js/image-chooser-modal.js"),
versioned_static("wagtailimages/js/image-chooser.js"),
versioned_static("wagtailvideos/js/video-chooser.js"),
]
)
class VideoChooserAdapter(BaseChooserAdapter):
js_constructor = "wagtailvideos.widgets.VideoChooser"
@cached_property
def media(self):
return forms.Media(
js=[
versioned_static("wagtailimages/js/image-chooser-telepath.js"),
versioned_static("wagtailvideos/js/video-chooser-telepath.js"),
]
)
register(VideoChooserAdapter(), AdminVideoChooser)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment