Unverified Commit 1431539f authored by seb-b's avatar seb-b Committed by GitHub
Browse files

Merge pull request #36 from neon-jungle/2.4+

Wagtail 2.4+ compat
parents 100796bf 7c8552c4
language: python language: python
cache: pip cache: pip
dist: trusty
env: env:
global: global:
- DJANGO_SETTINGS_MODULE="tests.app.settings" - DJANGO_SETTINGS_MODULE="tests.app.settings"
- TOX_ENV=
matrix:
- TOX_ENV=flake8,isort
python:
- 3.4
- 3.5
- 3.6
env:
- DJANGO='111' WAGTAIL='20'
- DJANGO='111' WAGTAIL='21'
- DJANGO='20' WAGTAIL='20'
- DJANGO='20' WAGTAIL='21'
matrix: matrix:
include: include:
- env: TOX_ENV='flake8,isort' - env: TOXENV=py35-dj20-wt24
python: 3.5
- env: TOXENV=py35-dj21-wt24
python: 3.5
- env: TOXENV=py36-dj20-wt24
python: 3.6
- env: TOXENV=py36-dj21-wt24
python: 3.6
- env: TOXENV=py35-dj20-wt25
python: 3.5
- env: TOXENV=py35-dj21-wt25
python: 3.5
- env: TOXENV=py36-dj20-wt25
python: 3.6
- env: TOXENV=py36-dj21-wt25
python: 3.6
# - env: TOXENV=py36-dj22-wt25
# python: 3.6
- env: TOXENV='flake8,isort'
python: 3.5 python: 3.5
before_install: before_install:
...@@ -41,6 +45,4 @@ cache: ...@@ -41,6 +45,4 @@ cache:
- $HOME/virtualenv - $HOME/virtualenv
script: script:
# Run tox using either a specific environment from TOX_ENV, - tox
# or building one from the environment variables
- tox -e "${TOX_ENV:-py${TRAVIS_PYTHON_VERSION/./}-dj${DJANGO}-wt${WAGTAIL}}"
...@@ -8,7 +8,7 @@ html5 compliant codec using ffmpeg. ...@@ -8,7 +8,7 @@ html5 compliant codec using ffmpeg.
Requirements Requirements
------------ ------------
- Wagtail >= 2.0 - Wagtail >= 2.4
- `ffmpeg <https://ffmpeg.org/>`__ - `ffmpeg <https://ffmpeg.org/>`__
Installing Installing
......
...@@ -18,9 +18,9 @@ setup( ...@@ -18,9 +18,9 @@ setup(
url='https://github.com/takeflight/wagtailvideos', url='https://github.com/takeflight/wagtailvideos',
install_requires=[ install_requires=[
'wagtail>=2.0', 'wagtail>=2.4',
'Django>=1.11', 'Django>=1.11',
'django-enumchoicefield==1.0.0', 'django-enumchoicefield==1.1.0',
], ],
extras_require={ extras_require={
'testing': [ 'testing': [
......
...@@ -20,6 +20,7 @@ INSTALLED_APPS = [ ...@@ -20,6 +20,7 @@ INSTALLED_APPS = [
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
] ]
......
...@@ -3,15 +3,16 @@ from __future__ import unicode_literals ...@@ -3,15 +3,16 @@ from __future__ import unicode_literals
import re import re
from django.conf import settings from django.conf import settings
from django.conf.urls import include, url from django.conf.urls import include
from django.urls import path, re_path
from django.views.static import serve from django.views.static import serve
from wagtail.admin import urls as wagtailadmin_urls from wagtail.admin import urls as wagtailadmin_urls
from wagtail.core import urls as wagtail_urls from wagtail.core import urls as wagtail_urls
urlpatterns = [ urlpatterns = [
url(r'^admin/', include(wagtailadmin_urls)), path('admin/', include(wagtailadmin_urls)),
url(r'', include(wagtail_urls)), path('', include(wagtail_urls)),
# For media serving # For media serving
url(r'^%s(?P<path>.*)$' % re.escape( re_path(r'^%s(?P<path>.*)$' % re.escape(
settings.MEDIA_URL.lstrip('/')), serve, kwargs={'document_root': settings.MEDIA_ROOT}) settings.MEDIA_URL.lstrip('/')), serve, kwargs={'document_root': settings.MEDIA_ROOT})
] ]
...@@ -315,8 +315,8 @@ class TestVideoChooserView(TestCase, WagtailTestUtils): ...@@ -315,8 +315,8 @@ class TestVideoChooserView(TestCase, WagtailTestUtils):
def test_simple(self): def test_simple(self):
response = self.get() response = self.get()
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailvideos/chooser/chooser.html') response_json = json.loads(response.content.decode())
self.assertTemplateUsed(response, 'wagtailvideos/chooser/chooser.js') self.assertEqual(response_json['step'], 'chooser')
def test_search(self): def test_search(self):
response = self.get({'q': "Hello"}) response = self.get({'q': "Hello"})
...@@ -364,7 +364,8 @@ class TestVideoChooserChosenView(TestCase, WagtailTestUtils): ...@@ -364,7 +364,8 @@ class TestVideoChooserChosenView(TestCase, WagtailTestUtils):
def test_simple(self): def test_simple(self):
response = self.get() response = self.get()
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailvideos/chooser/video_chosen.js') response_json = json.loads(response.content.decode())
self.assertEqual(response_json['step'], 'video_chosen')
class TestVideoChooserUploadView(TestCase, WagtailTestUtils): class TestVideoChooserUploadView(TestCase, WagtailTestUtils):
...@@ -378,7 +379,8 @@ class TestVideoChooserUploadView(TestCase, WagtailTestUtils): ...@@ -378,7 +379,8 @@ class TestVideoChooserUploadView(TestCase, WagtailTestUtils):
response = self.get() response = self.get()
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailvideos/chooser/chooser.html') self.assertTemplateUsed(response, 'wagtailvideos/chooser/chooser.html')
self.assertTemplateUsed(response, 'wagtailvideos/chooser/chooser.js') response_json = json.loads(response.content.decode())
self.assertEqual(response_json['step'], 'chooser')
def test_upload(self): def test_upload(self):
response = self.client.post(reverse('wagtailvideos:chooser_upload'), { response = self.client.post(reverse('wagtailvideos:chooser_upload'), {
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
skip_missing_interpreters = True skip_missing_interpreters = True
envlist = envlist =
py{34,35,36}-dj{110,20}-wt{20,21} py{35,36,37}-dj{20,21}-wt24
py{35,36,37}-dj{20,21,22}-wt25
# Enforce good style # Enforce good style
flake8,isort flake8,isort
...@@ -15,10 +16,11 @@ pip_pre = True ...@@ -15,10 +16,11 @@ pip_pre = True
deps = deps =
{[base]deps} {[base]deps}
dj111: Django~=1.11.0
dj20: Django~=2.0.0 dj20: Django~=2.0.0
wt20: wagtail~=2.0.0 dj21: Django~=2.1.0
wt21: wagtail~=2.1.0 dj22: Django~=2.2.0
wt24: wagtail~=2.4.0
wt25: wagtail~=2.5.0
[testenv:flake8] [testenv:flake8]
deps = flake8 deps = flake8
......
...@@ -3,7 +3,7 @@ from django.forms.models import modelform_factory ...@@ -3,7 +3,7 @@ from django.forms.models import modelform_factory
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from enumchoicefield.forms import EnumField from enumchoicefield.forms import EnumField
from wagtail.admin import widgets from wagtail.admin import widgets
from wagtail.admin.forms import ( from wagtail.admin.forms.collections import (
BaseCollectionMemberForm, collection_member_permission_formset_factory) BaseCollectionMemberForm, collection_member_permission_formset_factory)
from wagtailvideos.fields import WagtailVideoField from wagtailvideos.fields import WagtailVideoField
......
...@@ -18,7 +18,7 @@ from django.dispatch.dispatcher import receiver ...@@ -18,7 +18,7 @@ from django.dispatch.dispatcher import receiver
from django.forms.utils import flatatt from django.forms.utils import flatatt
from django.urls import reverse from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.text import mark_safe from django.utils.html import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from enumchoicefield import ChoiceEnum, EnumChoiceField from enumchoicefield import ChoiceEnum, EnumChoiceField
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
......
{% load i18n %} VIDEO_CHOOSER_MODAL_ONLOAD_HANDLERS = {
function(modal) { 'chooser': function(modal, jsonData) {
var searchUrl = $('form.video-search', modal.body).attr('action'); var searchUrl = $('form.video-search', modal.body).attr('action');
/* currentTag stores the tag currently being filtered on, so that we can /* currentTag stores the tag currently being filtered on, so that we can
...@@ -69,12 +69,10 @@ function(modal) { ...@@ -69,12 +69,10 @@ function(modal) {
modal.loadResponseText(response); modal.loadResponseText(response);
}, },
error: function(response, textStatus, errorThrown) { error: function(response, textStatus, errorThrown) {
{% trans "Server Error" as error_label %} message = jsonData['error_message'] + '<br />' + errorThrown + ' - ' + response.status;
{% trans "Report this error to your webmaster with the following information:" as error_message %} $('#upload').append(
message = '{{ error_message|escapejs }}<br />' + errorThrown + ' - ' + response.status; '<div class="help-block help-critical">' +
$('#upload').append( '<strong>' + jsonData['error_label'] + ': </strong>' + message + '</div>');
'<div class="help-block help-critical">' +
'<strong>{{ error_label|escapejs }}: </strong>' + message + '</div>');
} }
}); });
...@@ -98,11 +96,13 @@ function(modal) { ...@@ -98,11 +96,13 @@ function(modal) {
}); });
return false; return false;
}); });
{% url 'wagtailadmin_tag_autocomplete' as autocomplete_url %}
/* Add tag entry interface (with autocompletion) to the tag field of the image upload form */ /* Add tag entry interface (with autocompletion) to the tag field of the image upload form */
$('#id_tags', modal.body).tagit({ // $('#id_tags', modal.body).tagit({
autocomplete: {source: "{{ autocomplete_url|addslashes }}"} // autocomplete: {source: "{{ autocomplete_url|addslashes }}"}
}); // });
},
'video_chosen': function(modal, jsonData) {
modal.respond('videoChosen', jsonData['result']);
modal.close();
},
} }
...@@ -7,6 +7,7 @@ function createVideoChooser(id) { ...@@ -7,6 +7,7 @@ function createVideoChooser(id) {
$('.action-choose', chooserElement).click(function() { $('.action-choose', chooserElement).click(function() {
ModalWorkflow({ ModalWorkflow({
url: window.chooserUrls.videoChooser, url: window.chooserUrls.videoChooser,
onload: VIDEO_CHOOSER_MODAL_ONLOAD_HANDLERS,
responses: { responses: {
videoChosen: function(videoData) { videoChosen: function(videoData) {
input.val(videoData.id); input.val(videoData.id);
......
function(modal) {
modal.respond('videoChosen', {{ video_json|safe }});
modal.close();
}
{% extends "wagtailadmin/base.html" %} {% load staticfiles wagtailadmin_tags i18n wagtailvideos_tags %} {% block titletag %}{% blocktrans with title=video.title %}Editing video {{ title }}{% endblocktrans %}{% endblock %} {% block extra_css %} {% extends "wagtailadmin/base.html" %}
{% load staticfiles wagtailadmin_tags i18n wagtailvideos_tags %}
{% block titletag %}{% blocktrans with title=video.title %}Editing video {{ title }}{% endblocktrans %}{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'wagtailvideos/css/edit-video.css' %}" type="text/css" /> {% endblock %} {% block extra_js %} {{ block.super }} {% url 'wagtailadmin_tag_autocomplete' as autocomplete_url %} <link rel="stylesheet" href="{% static 'wagtailvideos/css/edit-video.css' %}" type="text/css" /> {% endblock %} {% block extra_js %} {{ block.super }} {% url 'wagtailadmin_tag_autocomplete' as autocomplete_url %}
<script> <script>
$(function() { $(function() {
...@@ -9,7 +15,11 @@ ...@@ -9,7 +15,11 @@
}); });
}); });
</script> </script>
{% endblock %} {% block content %} {% trans "Editing" as editing_str %} {% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=video.title icon="media" %} {% endblock %}
{% block content %}
{% trans "Editing" as editing_str %}
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=video.title icon="media" %}
<div class="row row-flush nice-padding"> <div class="row row-flush nice-padding">
...@@ -17,7 +27,15 @@ ...@@ -17,7 +27,15 @@
<form action="{% url 'wagtailvideos:edit' video.id %}" method="POST" enctype="multipart/form-data"> <form action="{% url 'wagtailvideos:edit' video.id %}" method="POST" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
<ul class="fields"> <ul class="fields">
{% for field in form %} {% if field.name == 'file' %} {% include "wagtailvideos/videos/_file_field_as_li.html" %} {% elif field.is_hidden %} {{ field }} {% else %} {% include "wagtailadmin/shared/field_as_li.html" %} {% endif %} {% endfor %} {% for field in form %}
{% if field.name == 'file' %}
{% include "wagtailvideos/videos/_file_field_as_li.html" %}
{% elif field.is_hidden %}
{{ field }}
{% else %}
{% include "wagtailadmin/shared/field_as_li.html" %}
{% endif %}
{% endfor %}
<li> <li>
<input type="submit" class="button" value="{% trans 'Save' %}" /> {% if user_can_delete %} <input type="submit" class="button" value="{% trans 'Save' %}" /> {% if user_can_delete %}
<a href="{% url 'wagtailvideos:delete' video.id %}" class="button button-secondary no">{% trans "Delete video" %}</a> {% endif %} <a href="{% url 'wagtailvideos:delete' video.id %}" class="button button-secondary no">{% trans "Delete video" %}</a> {% endif %}
...@@ -48,7 +66,9 @@ ...@@ -48,7 +66,9 @@
<h3 class="label">Create transcode</h3> <h3 class="label">Create transcode</h3>
<form action="{% url 'wagtailvideos:create_transcode' video.id %}" method="POST"> <form action="{% url 'wagtailvideos:create_transcode' video.id %}" method="POST">
<ul class="fields"> <ul class="fields">
{% csrf_token %} {% include "wagtailadmin/shared/field_as_li.html" with field=transcode_form.media_format %} {% include "wagtailadmin/shared/field_as_li.html" with field=transcode_form.quality %} {% csrf_token %}
{% include "wagtailadmin/shared/field_as_li.html" with field=transcode_form.media_format %}
{% include "wagtailadmin/shared/field_as_li.html" with field=transcode_form.quality %}
<li> <li>
<input class="button" type='submit' value="Start" /> <input class="button" type='submit' value="Start" />
</li> </li>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
{% block chooser_class %}image-chooser{% endblock %} {% block chooser_class %}image-chooser{% endblock %}
{% block chosen_state_view %} {% block chosen_state_view %}
<div class="video-thumb"> <div class="preview-image">
{% if video and video.thumbnail %} {% if video and video.thumbnail %}
<img src='{{video.thumbnail.url}}' width="165" height="165" class="show-transparency"> <img src='{{video.thumbnail.url}}' width="165" height="165" class="show-transparency">
{% else %} {% else %}
......
import json
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from django.urls import reverse from django.urls import reverse
from wagtail.admin.forms import SearchForm from wagtail.admin.forms.search import SearchForm
from wagtail.admin.modal_workflow import render_modal_workflow from wagtail.admin.modal_workflow import render_modal_workflow
from wagtail.admin.utils import PermissionPolicyChecker, popular_tags_for_model from wagtail.admin.utils import PermissionPolicyChecker, popular_tags_for_model
from wagtail.core.models import Collection from wagtail.core.models import Collection
from wagtail.images.views.chooser import get_chooser_js_data
from wagtail.search import index as search_index from wagtail.search import index as search_index
from wagtail.utils.pagination import paginate from wagtail.utils.pagination import paginate
...@@ -22,14 +21,14 @@ def get_video_json(video): ...@@ -22,14 +21,14 @@ def get_video_json(video):
image chooser panel image chooser panel
""" """
return json.dumps({ return {
'id': video.id, 'id': video.id,
'edit_link': reverse('wagtailvideos:edit', args=(video.id,)), 'edit_link': reverse('wagtailvideos:edit', args=(video.id,)),
'title': video.title, 'title': video.title,
'preview': { 'preview': {
'url': video.thumbnail.url if video.thumbnail else '', 'url': video.thumbnail.url if video.thumbnail else '',
} }
}) }
def chooser(request): def chooser(request):
...@@ -79,7 +78,7 @@ def chooser(request): ...@@ -79,7 +78,7 @@ def chooser(request):
paginator, videos = paginate(request, videos, per_page=12) paginator, videos = paginate(request, videos, per_page=12)
return render_modal_workflow(request, 'wagtailvideos/chooser/chooser.html', 'wagtailvideos/chooser/chooser.js', { return render_modal_workflow(request, 'wagtailvideos/chooser/chooser.html', None, {
'videos': videos, 'videos': videos,
'uploadform': uploadform, 'uploadform': uploadform,
'searchform': searchform, 'searchform': searchform,
...@@ -87,16 +86,17 @@ def chooser(request): ...@@ -87,16 +86,17 @@ def chooser(request):
'query_string': q, 'query_string': q,
'popular_tags': popular_tags_for_model(Video), 'popular_tags': popular_tags_for_model(Video),
'collections': collections, 'collections': collections,
}) }, json_data=get_chooser_js_data())
def video_chosen(request, video_id): def video_chosen(request, video_id):
video = get_object_or_404(Video, id=video_id) video = get_object_or_404(Video, id=video_id)
return render_modal_workflow( return render_modal_workflow(
request, None, 'wagtailvideos/chooser/video_chosen.js', request, None, json_data={
{'video_json': get_video_json(video)} 'step': 'video_chosen',
) 'result': get_video_json(video)
})
@permission_checker.require('add') @permission_checker.require('add')
...@@ -117,8 +117,10 @@ def chooser_upload(request): ...@@ -117,8 +117,10 @@ def chooser_upload(request):
search_index.insert_or_update_object(video) search_index.insert_or_update_object(video)
return render_modal_workflow( return render_modal_workflow(
request, None, 'wagtailvideos/chooser/video_chosen.js', request, None, json_data={
{'video_json': get_video_json(video)} 'step': 'video_chosen',
'result': get_video_json(video)
}
) )
else: else:
form = VideoForm() form = VideoForm()
...@@ -127,6 +129,7 @@ def chooser_upload(request): ...@@ -127,6 +129,7 @@ def chooser_upload(request):
paginator, videos = paginate(request, videos, per_page=12) paginator, videos = paginate(request, videos, per_page=12)
return render_modal_workflow( return render_modal_workflow(
request, 'wagtailvideos/chooser/chooser.html', 'wagtailvideos/chooser/chooser.js', request, 'wagtailvideos/chooser/chooser.html', None,
{'videos': videos, 'uploadform': form, 'searchform': searchform} template_vars={'videos': videos, 'uploadform': form, 'searchform': searchform},
json_data=get_chooser_js_data()
) )
...@@ -4,7 +4,7 @@ from django.urls import reverse ...@@ -4,7 +4,7 @@ from django.urls import reverse
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.decorators.vary import vary_on_headers from django.views.decorators.vary import vary_on_headers
from wagtail.admin import messages from wagtail.admin import messages
from wagtail.admin.forms import SearchForm from wagtail.admin.forms.search import SearchForm
from wagtail.admin.utils import PermissionPolicyChecker, popular_tags_for_model from wagtail.admin.utils import PermissionPolicyChecker, popular_tags_for_model
from wagtail.core.models import Collection from wagtail.core.models import Collection
from wagtail.search.backends import get_search_backends from wagtail.search.backends import get_search_backends
......
from django.conf.urls import include, url from django.conf.urls import include, url
from django.contrib.staticfiles.templatetags.staticfiles import static
from django.urls import reverse from django.urls import reverse
from django.utils.html import format_html, format_html_join from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from wagtail.admin.menu import MenuItem from wagtail.admin.menu import MenuItem
from wagtail.core import hooks from wagtail.core import hooks
...@@ -19,14 +18,7 @@ def register_admin_urls(): ...@@ -19,14 +18,7 @@ def register_admin_urls():
@hooks.register('insert_editor_js') @hooks.register('insert_editor_js')
def editor_js(): def editor_js():
js_files = [ return format_html(
static('wagtailvideos/js/video-chooser.js'),
]
js_includes = format_html_join(
'\n', '<script src="{0}"></script>',
((filename, ) for filename in js_files)
)
return js_includes + format_html(
""" """
<script> <script>
window.chooserUrls.videoChooser = '{0}'; window.chooserUrls.videoChooser = '{0}';
......
...@@ -30,3 +30,9 @@ class AdminVideoChooser(AdminChooser): ...@@ -30,3 +30,9 @@ class AdminVideoChooser(AdminChooser):
def render_js_init(self, id_, name, value): def render_js_init(self, id_, name, value):
return "createVideoChooser({0});".format(json.dumps(id_)) return "createVideoChooser({0});".format(json.dumps(id_))
class Media:
js = [
'wagtailvideos/js/video-chooser-modal.js',
'wagtailvideos/js/video-chooser.js',
]
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