diff --git a/.gitignore b/.gitignore
index b3ba0b7b..302584e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,9 @@ htmlcov/
node_modules/
.next/
example/db.sqlite3
+
+# Emacs Temp/Autosaves
+*~
+\#*\#
+.#*.*
+*_flymake*
\ No newline at end of file
diff --git a/djedi/admin/api.py b/djedi/admin/api.py
index e18d0560..223853fb 100644
--- a/djedi/admin/api.py
+++ b/djedi/admin/api.py
@@ -1,4 +1,6 @@
from collections import defaultdict
+from djedi.plugins.base import DjediPlugin
+
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse, Http404, HttpResponseBadRequest
from django.utils.http import urlunquote
@@ -193,11 +195,16 @@ def get(self, request, uri):
try:
uri = self.decode_uri(uri)
uri = URI(uri)
- plugins.resolve(uri)
+ plugin = plugins.resolve(uri)
+ plugin_context = self.get_context_data(uri=uri)
+
+ if isinstance(plugin, DjediPlugin):
+ plugin_context = plugin.get_editor_context(**plugin_context)
+
except UnknownPlugin:
raise Http404
else:
- return self.render_plugin(request, self.get_context_data(uri=uri))
+ return self.render_plugin(request, plugin_context)
@never_cache
def post(self, request, uri):
diff --git a/djedi/plugins/base.py b/djedi/plugins/base.py
new file mode 100644
index 00000000..d6796236
--- /dev/null
+++ b/djedi/plugins/base.py
@@ -0,0 +1,9 @@
+from cio.plugins.base import BasePlugin
+
+
+class DjediPlugin(BasePlugin):
+ def get_editor_context(self, **kwargs):
+ """
+ Returns custom context
+ """
+ return kwargs
diff --git a/djedi/plugins/form.py b/djedi/plugins/form.py
new file mode 100644
index 00000000..e2ba83ae
--- /dev/null
+++ b/djedi/plugins/form.py
@@ -0,0 +1,67 @@
+import json
+from djedi.plugins.base import DjediPlugin
+from django import forms
+
+
+def deprefix(s):
+ # Remove prefix (anything including and before __)
+ return s.rpartition('__')[-1]
+
+
+def get_custom_render_widget(cls):
+ class CustomRenderWidget(cls):
+ def render(self, *args, **kwargs):
+ name = kwargs.pop("name", None)
+
+ if not name:
+ name = args[0]
+ args = args[1:]
+
+ name = deprefix(name)
+
+ return super(CustomRenderWidget, self).render(
+ "data[%s]" % name,
+ *args,
+ **kwargs
+ )
+
+ return CustomRenderWidget
+
+
+class BaseEditorForm(forms.Form):
+ def __init__(self, *args, **kwargs):
+ super(BaseEditorForm, self).__init__(*args, **kwargs)
+
+ for field in list(self.fields.keys()):
+ self.fields[field].widget.__class__ = get_custom_render_widget(
+ self.fields[field].widget.__class__
+ )
+
+
+class FormsBasePlugin(DjediPlugin):
+ ext = None
+
+ @property
+ def forms(self):
+ return {}
+
+ def get_editor_context(self, **context):
+ context.update(
+ {"forms": {
+ tab: form()
+ for tab, form in self.forms.items()
+ }}
+ )
+
+ return context
+
+ def save(self, data, dumps=True):
+ data = self.collect_forms_data(data)
+ return json.dumps(data) if dumps else data
+
+ def collect_forms_data(self, data):
+ return {
+ deprefix(field): data.get(deprefix(field))
+ for tab, form in self.forms.items()
+ for field in form.base_fields.keys()
+ }
diff --git a/djedi/plugins/img.py b/djedi/plugins/img.py
index ea5f4c91..69debb15 100644
--- a/djedi/plugins/img.py
+++ b/djedi/plugins/img.py
@@ -1,16 +1,44 @@
import json
import six
from django.utils.html import escape
-from cio.plugins.base import BasePlugin
from django.core.files.uploadedfile import InMemoryUploadedFile
+from django import forms
from hashlib import sha1
from os import path
+from .form import FormsBasePlugin, BaseEditorForm
-class ImagePluginBase(BasePlugin):
+class DataForm(BaseEditorForm):
+ data__id = forms.CharField(
+ label="ID",
+ max_length=255,
+ required=False,
+ widget=forms.TextInput(attrs={"class": "form-control"}),
+ )
+
+ data__alt = forms.CharField(
+ label="Alt text",
+ max_length=255,
+ required=False,
+ widget=forms.TextInput(attrs={"class": "form-control"}),
+ )
+
+ data__class = forms.CharField(
+ label="Class",
+ max_length=255,
+ required=False,
+ widget=forms.TextInput(attrs={"class": "form-control"}),
+ )
+
+
+class ImagePluginBase(FormsBasePlugin):
ext = 'img'
+ @property
+ def forms(self):
+ return {'HTML': DataForm}
+
def _open(self, filename):
raise NotImplementedError
@@ -101,14 +129,12 @@ def save(self, data):
if file:
file.close()
- content = {
+ content = super(ImagePluginBase, self).save(data, dumps=False)
+ content.update({
'filename': filename,
'width': width,
'height': height,
- 'id': data.get('id') or None,
- 'class': data.get('class') or None,
- 'alt': data.get('alt') or None
- }
+ })
return json.dumps(content)
@@ -126,23 +152,27 @@ def render(self, data):
'width': 160,
'height': 90
}
+
if data:
url = data.get('url')
- width = data.get('width') or 0
- height = data.get('height') or 0
- alt = data.get('alt') or ''
- tag_id = data.get('id')
- tag_class = data.get('class')
if url:
attrs['src'] = url
- attrs['alt'] = alt
+
+ width = data.get('width') or 0
+ height = data.get('height') or 0
if width and height:
attrs['width'] = width
attrs['height'] = height
- if tag_id:
- attrs['id'] = tag_id
- if tag_class:
- attrs['class'] = tag_class
+
+ attrs['alt'] = data.get('alt') or ''
+
+ attr_id = data.get('id')
+ if attr_id:
+ attrs['id'] = attr_id
+
+ attr_class = data.get('class')
+ if attr_class:
+ attrs['class'] = attr_class
html_attrs = (u'{0}="{1}"'.format(attr, escape(attrs[attr])) for attr in sorted(attrs.keys()))
return u''.format(u' '.join(html_attrs))
diff --git a/djedi/static/djedi/plugins/img/js/img.coffee b/djedi/static/djedi/plugins/img/js/img.coffee
index 1f0ae0df..29b407e1 100644
--- a/djedi/static/djedi/plugins/img/js/img.coffee
+++ b/djedi/static/djedi/plugins/img/js/img.coffee
@@ -375,13 +375,19 @@ class window.ImageEditor extends window.Editor
@firstRender = false
updateForm: (data) ->
+ # Hardcoded fields
$("input[name='data[filename]']").val data.filename
+ $("input[name='data[crop]']").val ''
$("input[name='data[width]']").val data.width
$("input[name='data[height]']").val data.height
- $("input[name='data[crop]']").val ''
- $("input[name='data[id]']").val data.id
- $("input[name='data[class]']").val data.class
- $("input[name='data[alt]']").val data.alt
+ delete data.filename
+ delete data.width
+ delete data.height
+
+ # Form fields
+ for k, v of data
+ $("input[name='data[#{k}]']").val v
+
@ratioButton.removeClass 'active'
renderThumbnail: (url) ->
diff --git a/djedi/static/djedi/plugins/img/js/img.js b/djedi/static/djedi/plugins/img/js/img.js
index 990aed44..419e8b4e 100644
--- a/djedi/static/djedi/plugins/img/js/img.js
+++ b/djedi/static/djedi/plugins/img/js/img.js
@@ -425,13 +425,18 @@
};
ImageEditor.prototype.updateForm = function(data) {
+ var k, v;
$("input[name='data[filename]']").val(data.filename);
+ $("input[name='data[crop]']").val('');
$("input[name='data[width]']").val(data.width);
$("input[name='data[height]']").val(data.height);
- $("input[name='data[crop]']").val('');
- $("input[name='data[id]']").val(data.id);
- $("input[name='data[class]']").val(data["class"]);
- $("input[name='data[alt]']").val(data.alt);
+ delete data.filename;
+ delete data.width;
+ delete data.height;
+ for (k in data) {
+ v = data[k];
+ $("input[name='data[" + k + "]']").val(v);
+ }
return this.ratioButton.removeClass('active');
};
diff --git a/djedi/templates/djedi/plugins/img/editor.html b/djedi/templates/djedi/plugins/img/editor.html
index 4b94ff3c..5769f38b 100644
--- a/djedi/templates/djedi/plugins/img/editor.html
+++ b/djedi/templates/djedi/plugins/img/editor.html
@@ -9,7 +9,9 @@
{% block tabs %}