kopia lustrzana https://github.com/wagtail/wagtail
Move verdantembeds to the django-wagtail package
rodzic
7f248bdf63
commit
2f1663157e
|
@ -14,7 +14,7 @@
|
|||
<script type="text/coffeescript" src="{{ STATIC_URL }}wagtailadmin/js/hallo-plugins/hallo-verdantlink.coffee"></script>
|
||||
<script type="text/coffeescript" src="{{ STATIC_URL }}wagtailadmin/js/hallo-plugins/hallo-hr.coffee"></script>
|
||||
<script type="text/coffeescript" src="{{ STATIC_URL }}wagtailimages/js/hallo-plugins/hallo-verdantimage.coffee"></script>
|
||||
<script type="text/coffeescript" src="{{ STATIC_URL }}verdantembeds/js/hallo-plugins/hallo-verdantembeds.coffee"></script>
|
||||
<script type="text/coffeescript" src="{{ STATIC_URL }}wagtailembeds/js/hallo-plugins/hallo-verdantembeds.coffee"></script>
|
||||
<script type="text/coffeescript" src="{{ STATIC_URL }}wagtaildocs/js/hallo-plugins/hallo-verdantdoclink.coffee"></script>
|
||||
<script src="{{ STATIC_URL }}wagtailadmin/js/page-editor.js"></script>
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ class MediaEmbedHandler(object):
|
|||
Given a dict of attributes from the <embed> tag, return the real HTML
|
||||
representation.
|
||||
"""
|
||||
from verdantembeds import format
|
||||
from wagtail.wagtailembeds import format
|
||||
if for_editor:
|
||||
return format.embed_to_editor_html(attrs['url'])
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
from .models import Embed
|
||||
from .embeds import get_embed
|
|
@ -0,0 +1,40 @@
|
|||
from datetime import datetime
|
||||
from django.conf import settings
|
||||
from embedly import Embedly
|
||||
from .models import Embed
|
||||
|
||||
|
||||
def get_embed(url, max_width=None):
|
||||
# Check database
|
||||
try:
|
||||
return Embed.objects.get(url=url, max_width=max_width)
|
||||
except Embed.DoesNotExist:
|
||||
pass
|
||||
|
||||
# Call embedly API
|
||||
client = Embedly(key=settings.EMBEDLY_KEY)
|
||||
if max_width is not None:
|
||||
oembed = client.oembed(url, maxwidth=max_width, better=False)
|
||||
else:
|
||||
oembed = client.oembed(url, better=False)
|
||||
|
||||
# Check for error
|
||||
if oembed.error:
|
||||
return None
|
||||
|
||||
# Save result to database
|
||||
row, created = Embed.objects.get_or_create(url=url, max_width=max_width,
|
||||
defaults={'type': oembed.type, 'title': oembed.title, 'thumbnail_url': oembed.thumbnail_url, 'width': oembed.width, 'height': oembed.height})
|
||||
|
||||
if oembed.type == 'photo':
|
||||
html = '<img src="%s" />' % (oembed.url, )
|
||||
else:
|
||||
html = oembed.html
|
||||
|
||||
if html:
|
||||
row.html = html
|
||||
row.last_updated = datetime.now()
|
||||
row.save()
|
||||
|
||||
# Return new embed
|
||||
return row
|
|
@ -0,0 +1,26 @@
|
|||
from __future__ import division # Use true division
|
||||
from .embeds import get_embed
|
||||
from django.utils.html import escape
|
||||
|
||||
|
||||
def embed_to_frontend_html(url):
|
||||
embed = get_embed(url)
|
||||
if embed is not None:
|
||||
# Work out ratio
|
||||
if embed.width and embed.height:
|
||||
ratio = str(embed.height / embed.width * 100) + "%"
|
||||
else:
|
||||
ratio = "0"
|
||||
|
||||
# Build html
|
||||
return '<div style="padding-bottom: %s;" class="responsive-object">%s</div>' % (ratio, embed.html)
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
||||
def embed_to_editor_html(url):
|
||||
# Check that the embed exists
|
||||
embed = get_embed(url)
|
||||
if embed is None:
|
||||
return ''
|
||||
return '<div class="embed-placeholder" contenteditable="false" data-embedtype="media" data-url="%s"><h3>%s</h3><p>%s</p><img src="%s"></div>' % (url, escape(embed.title), url, embed.thumbnail_url)
|
|
@ -0,0 +1,15 @@
|
|||
from django import forms
|
||||
from django.core.validators import URLValidator
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
def validate_url(url):
|
||||
validator = URLValidator()
|
||||
try:
|
||||
validator(url)
|
||||
except ValidationError:
|
||||
raise ValidationError("Please enter a valid URL")
|
||||
|
||||
|
||||
class EmbedForm(forms.Form):
|
||||
url = forms.CharField(label="URL", validators=[validate_url])
|
|
@ -0,0 +1,58 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
depends_on = (
|
||||
("wagtailcore", "0002_initial_data"),
|
||||
)
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'Embed'
|
||||
db.create_table(u'wagtailembeds_embed', (
|
||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('url', self.gf('django.db.models.fields.URLField')(max_length=200)),
|
||||
('max_width', self.gf('django.db.models.fields.SmallIntegerField')(null=True, blank=True)),
|
||||
('type', self.gf('django.db.models.fields.CharField')(max_length=10)),
|
||||
('html', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
('title', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
('thumbnail_url', self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True)),
|
||||
('width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
|
||||
('height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
|
||||
('last_updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal(u'wagtailembeds', ['Embed'])
|
||||
|
||||
# Adding unique constraint on 'Embed', fields ['url', 'max_width']
|
||||
db.create_unique(u'wagtailembeds_embed', ['url', 'max_width'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Removing unique constraint on 'Embed', fields ['url', 'max_width']
|
||||
db.delete_unique(u'wagtailembeds_embed', ['url', 'max_width'])
|
||||
|
||||
# Deleting model 'Embed'
|
||||
db.delete_table(u'wagtailembeds_embed')
|
||||
|
||||
|
||||
models = {
|
||||
u'wagtailembeds.embed': {
|
||||
'Meta': {'unique_together': "(('url', 'max_width'),)", 'object_name': 'Embed'},
|
||||
'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'html': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'max_width': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'thumbnail_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
|
||||
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
|
||||
'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['wagtailembeds']
|
|
@ -0,0 +1,27 @@
|
|||
from django.db import models
|
||||
|
||||
|
||||
EMBED_TYPES = (
|
||||
('video', 'Video'),
|
||||
('photo', 'Photo'),
|
||||
('link', 'Link'),
|
||||
('rich', 'Rich'),
|
||||
)
|
||||
|
||||
|
||||
class Embed(models.Model):
|
||||
url = models.URLField()
|
||||
max_width = models.SmallIntegerField(null=True, blank=True)
|
||||
type = models.CharField(max_length=10, choices=EMBED_TYPES)
|
||||
html = models.TextField(blank=True)
|
||||
title = models.TextField(blank=True)
|
||||
thumbnail_url = models.URLField(null=True, blank=True)
|
||||
width = models.IntegerField(null=True, blank=True)
|
||||
height = models.IntegerField(null=True, blank=True)
|
||||
last_updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('url', 'max_width')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.url
|
|
@ -0,0 +1,36 @@
|
|||
# plugin for hallo.js to allow inserting embeds
|
||||
|
||||
(($) ->
|
||||
$.widget "IKS.halloverdantembeds",
|
||||
options:
|
||||
uuid: ''
|
||||
editable: null
|
||||
|
||||
populateToolbar: (toolbar) ->
|
||||
widget = this
|
||||
|
||||
# Create an element for holding the button
|
||||
button = $('<span></span>')
|
||||
button.hallobutton
|
||||
uuid: @options.uuid
|
||||
editable: @options.editable
|
||||
label: 'Embed'
|
||||
icon: 'icon-media'
|
||||
command: null
|
||||
|
||||
# Append the button to toolbar
|
||||
toolbar.append button
|
||||
|
||||
button.on "click", (event) ->
|
||||
lastSelection = widget.options.editable.getSelection()
|
||||
insertionPoint = $(lastSelection.endContainer).parentsUntil('.richtext').last()
|
||||
ModalWorkflow
|
||||
url: '/admin/embeds/chooser/' # TODO: don't hard-code this, as it may be changed in urls.py
|
||||
responses:
|
||||
embedChosen: (embedData) ->
|
||||
elem = $(embedData).get(0)
|
||||
lastSelection.insertNode(elem)
|
||||
if elem.getAttribute('contenteditable') == 'false'
|
||||
insertRichTextDeleteControl(elem)
|
||||
widget.options.editable.element.trigger('change')
|
||||
)(jQuery)
|
|
@ -0,0 +1,19 @@
|
|||
{% load image_tags ellipsistrim%}
|
||||
|
||||
<header class="merged">
|
||||
<h1>Insert embed</h1>
|
||||
</header>
|
||||
|
||||
<div class="tab-content">
|
||||
<section id="form" class="active nice-padding">
|
||||
<form class="embed-form" action="{% url 'wagtailembeds_chooser_upload' %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<ul class="fields">
|
||||
{% for field in form %}
|
||||
{% include "wagtailadmin/shared/field_as_li.html" with field=field %}
|
||||
{% endfor %}
|
||||
<li><input type="submit" value="Insert" /></li>
|
||||
</ul>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
|
@ -0,0 +1,19 @@
|
|||
function(modal) {
|
||||
$('form.embed-form', 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);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
function(modal) {
|
||||
modal.respond('embedChosen', '{{ embed_html|safe }}');
|
||||
modal.close();
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import re
|
||||
from django import template
|
||||
from django.utils.safestring import mark_safe
|
||||
from wagtail.wagtailembeds.embeds import get_embed
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def embedly(url, max_width=None):
|
||||
embed = get_embed(url, max_width=max_width)
|
||||
if embed is not None:
|
||||
return mark_safe(embed.html)
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
||||
@register.filter
|
||||
def embed(url):
|
||||
return embedly(url)
|
|
@ -0,0 +1,9 @@
|
|||
from .embeds import get_embed
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class TestEmbeds(TestCase):
|
||||
def test_get_embed(self):
|
||||
# This test will fail if the video is removed or the title is changed
|
||||
embed = get_embed('http://www.youtube.com/watch?v=S3xAeTmsJfg')
|
||||
self.assertEqual(embed.title, 'Animation: Ferret dance (A series of tubes)')
|
|
@ -0,0 +1,7 @@
|
|||
from django.conf.urls import patterns, url
|
||||
|
||||
|
||||
urlpatterns = patterns('wagtail.wagtailembeds.views',
|
||||
url(r'^chooser/$', 'chooser.chooser', name='wagtailembeds_chooser'),
|
||||
url(r'^chooser/upload/$', 'chooser.chooser_upload', name='wagtailembeds_chooser_upload'),
|
||||
)
|
|
@ -0,0 +1,37 @@
|
|||
from wagtail.wagtailadmin.modal_workflow import render_modal_workflow
|
||||
from wagtail.wagtailembeds.forms import EmbedForm
|
||||
from wagtail.wagtailembeds.format import embed_to_editor_html
|
||||
from django.forms.util import ErrorList
|
||||
|
||||
|
||||
def chooser(request):
|
||||
form = EmbedForm()
|
||||
|
||||
return render_modal_workflow(request, 'wagtailembeds/chooser/chooser.html', 'wagtailembeds/chooser/chooser.js',{
|
||||
'form': form,
|
||||
})
|
||||
|
||||
|
||||
def chooser_upload(request):
|
||||
if request.POST:
|
||||
form = EmbedForm(request.POST, request.FILES)
|
||||
|
||||
if form.is_valid():
|
||||
embed_html = embed_to_editor_html(form.cleaned_data['url'])
|
||||
if embed_html != "":
|
||||
return render_modal_workflow(
|
||||
request, None, 'wagtailembeds/chooser/embed_chosen.js',
|
||||
{'embed_html': embed_html}
|
||||
)
|
||||
else:
|
||||
errors = form._errors.setdefault('url', ErrorList())
|
||||
errors.append('This URL is not recognised')
|
||||
return render_modal_workflow(request, 'wagtailembeds/chooser/chooser.html', 'wagtailembeds/chooser/chooser.js',{
|
||||
'form': form,
|
||||
})
|
||||
else:
|
||||
form = EmbedForm()
|
||||
|
||||
return render_modal_workflow(request, 'wagtailembeds/chooser/chooser.html', 'wagtailembeds/chooser/chooser.js',{
|
||||
'form': form,
|
||||
})
|
Ładowanie…
Reference in New Issue