Unverified Commit ccd007ee authored by Seb Brown's avatar Seb Brown Committed by GitHub
Browse files

Merge pull request #97 from neon-jungle/feat_support_wagtail4

Feat support wagtail4
parents d66ec4eb c6198e49
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 = [
path('add/', videos.add, name='add'), path('add/', videos.add, name='add'),
re_path(r'^usage/(\d+)/$', videos.usage, name='video_usage'), re_path(r'^usage/(\d+)/$', videos.usage, name='video_usage'),
...@@ -11,10 +12,6 @@ urlpatterns = [ ...@@ -11,10 +12,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
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.utils.functional import cached_property
from wagtail.admin.forms.search import SearchForm from django.utils.translation import gettext_lazy as _
from wagtail.admin.modal_workflow import render_modal_workflow from django.views.generic.base import View
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
return collections
paginator = Paginator(videos, per_page=12) def get(self, request):
page = paginator.get_page(request.GET.get('p')) self.model = get_video_model()
return super().get(request)
return render_modal_workflow(request, 'wagtailvideos/chooser/chooser.html', None, { def get_context_data(self, **kwargs):
'videos': page, context = super().get_context_data(**kwargs)
'uploadform': uploadform, context.update(
'searchform': searchform, {
'is_searching': False, "collections": self.collections,
'query_string': q, }
'popular_tags': popular_tags_for_model(Video), )
'collections': collections, return context
}, json_data=get_chooser_js_data())
def video_chosen(request, video_id): class VideoChooseViewMixin(ChooseViewMixin):
video = get_object_or_404(get_video_model(), id=video_id) def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["popular_tags"] = popular_tags_for_model(self.model)
return context
return render_modal_workflow( def get_response_json_data(self):
request, None, json_data={ json_data = super().get_response_json_data()
'step': 'video_chosen', json_data["tag_autocomplete_url"] = reverse("wagtailadmin_tag_autocomplete")
'result': get_video_json(video) return json_data
})
@permission_checker.require('add') class VideoChooseView(
def chooser_upload(request): VideoChooseViewMixin, VideoCreationFormMixin, BaseVideoChooseView
Video = get_video_model() ):
VideoForm = get_video_form(Video) pass
searchform = SearchForm()
if request.POST: class VideoChooseResultsView(
video = Video(uploaded_by_user=request.user) ChooseResultsViewMixin, VideoCreationFormMixin, BaseVideoChooseView
form = VideoForm(request.POST, request.FILES, instance=video) ):
pass
if form.is_valid():
video.uploaded_by_user = request.user
video.save()
# Reindex the video to make sure all tags are indexed class VideoChosenView(ChosenViewMixin, VideoChosenResponseMixin, View):
search_index.insert_or_update_object(video) def get(self, request, *args, pk, **kwargs):
self.model = get_video_model()
return super().get(request, *args, pk, **kwargs)
return render_modal_workflow(
request, None, json_data={ class VideoUploadViewMixin(CreateViewMixin):
'step': 'video_chosen', def get(self, request):
'result': get_video_json(video) self.model = get_video_model()
} return super().get(request)
)
else: def post(self, request):
form = VideoForm() self.model = get_video_model()
self.form = self.get_creation_form()
videos = Video.objects.order_by('title')
paginator = Paginator(videos, per_page=12) if self.form.is_valid():
page = paginator.get_page(request.GET.get('p')) image = self.save_form(self.form)
return render_modal_workflow( # not specifying a format; return the image details now
request, 'wagtailvideos/chooser/chooser.html', None, return self.get_chosen_response(image)
template_vars={'videos': page, 'uploadform': form, 'searchform': searchform},
json_data=get_chooser_js_data() 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