1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
"""Django CMS come with a set of ready to use widgets that you can enable |
3
|
|
|
in the admin via a placeholder tag in your template.""" |
4
|
|
|
|
5
|
|
|
from pages.settings import PAGES_MEDIA_URL, PAGES_STATIC_URL |
6
|
|
|
from pages.settings import PAGE_LANGUAGES |
7
|
|
|
from pages.models import Page |
8
|
|
|
from pages.widgets_registry import register_widget |
9
|
|
|
|
10
|
|
|
from django import forms |
11
|
|
|
from django.forms import TextInput, Textarea |
12
|
|
|
from django.forms import MultiWidget |
13
|
|
|
from django.forms import FileInput as DFileInput |
14
|
|
|
from django.contrib.admin.widgets import AdminTextInputWidget |
15
|
|
|
from django.contrib.admin.widgets import AdminTextareaWidget |
16
|
|
|
from django.utils.safestring import mark_safe |
17
|
|
|
from django.template.loader import render_to_string |
18
|
|
|
from django.utils.translation import ugettext_lazy as _ |
19
|
|
|
|
20
|
|
|
from os.path import join |
21
|
|
|
|
22
|
|
|
register_widget(TextInput) |
23
|
|
|
register_widget(Textarea) |
24
|
|
|
register_widget(AdminTextInputWidget) |
25
|
|
|
register_widget(AdminTextareaWidget) |
26
|
|
|
|
27
|
|
|
|
28
|
|
|
class RichTextarea(Textarea): |
29
|
|
|
"""A RichTextarea widget.""" |
30
|
|
|
class Media: |
31
|
|
|
js = [join(PAGES_STATIC_URL, path) for path in ( |
32
|
|
|
'javascript/jquery.js', |
33
|
|
|
'javascript/jquery.rte.js' |
34
|
|
|
)] |
35
|
|
|
css = { |
36
|
|
|
'all': [join(PAGES_STATIC_URL, path) for path in ( |
37
|
|
|
'css/rte.css', |
38
|
|
|
'css/font-awesome.min.css' |
39
|
|
|
)] |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
def __init__(self, language=None, attrs=None, **kwargs): |
43
|
|
|
attrs = {'class': 'rte'} |
44
|
|
|
self.language = language |
45
|
|
|
super(RichTextarea, self).__init__(attrs) |
46
|
|
|
|
47
|
|
|
def render(self, name, value, attrs=None, **kwargs): |
48
|
|
|
rendered = super(RichTextarea, self).render(name, value, attrs) |
49
|
|
|
context = { |
50
|
|
|
'name': name, |
51
|
|
|
'PAGES_STATIC_URL': PAGES_STATIC_URL, |
52
|
|
|
'PAGES_MEDIA_URL': PAGES_MEDIA_URL, |
53
|
|
|
} |
54
|
|
|
return rendered + mark_safe(render_to_string( |
55
|
|
|
'pages/widgets/richtextarea.html', context)) |
56
|
|
|
|
57
|
|
|
|
58
|
|
|
register_widget(RichTextarea) |
59
|
|
|
|
60
|
|
|
|
61
|
|
|
insert_image_link = u''' |
62
|
|
|
<br> |
63
|
|
|
<button title='insert image from the media library' class='image-lookup-{name}'> |
64
|
|
|
From media library |
65
|
|
|
</button> |
66
|
|
|
<input name="{name}-selected" id="{name}-selected" type="hidden"> |
67
|
|
|
<span id="{name}-selected-value"> |
68
|
|
|
</span> |
69
|
|
|
|
70
|
|
|
<br><label for="{name}-delete"> |
71
|
|
|
<input name="{name}-delete" style="display:inline-block" id="{name}-delete" type="checkbox" value="true"> {del_msg} |
72
|
|
|
</label> |
73
|
|
|
<br style="clear:both"> |
74
|
|
|
|
75
|
|
|
|
76
|
|
|
<script> |
77
|
|
|
$(function(){{ |
78
|
|
|
function dismissRelatedLookupPopup(win, chosenId) {{ |
79
|
|
|
$.get('/admin/pages/page/' + chosenId + '/media-url/', function(response) {{ |
80
|
|
|
console.log(response); |
81
|
|
|
$('#{name}-selected').val(response); |
82
|
|
|
$('#{name}-selected-value').text(response); |
83
|
|
|
}}); |
84
|
|
|
win.close(); |
85
|
|
|
window.dismissRelatedLookupPopup = oldDismissRelatedLookupPopup; |
86
|
|
|
window.dismissAddRelatedObjectPopup = oldDismissAddRelatedObjectPopup; |
87
|
|
|
}} |
88
|
|
|
function showMediaAdminPopup() {{ |
89
|
|
|
var name = 'mediaWindowSelect'; |
90
|
|
|
var href = '/admin/pages/media/?_to_field=id&_popup=1'; |
91
|
|
|
window.dismissRelatedLookupPopup = dismissRelatedLookupPopup; |
92
|
|
|
window.dismissAddRelatedObjectPopup = dismissRelatedLookupPopup; |
93
|
|
|
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); |
94
|
|
|
win.focus(); |
95
|
|
|
return false; |
96
|
|
|
}} |
97
|
|
|
$('.image-lookup-{name}').click(function(e) {{ |
98
|
|
|
e.preventDefault(); |
99
|
|
|
showMediaAdminPopup(); |
100
|
|
|
return false; |
101
|
|
|
}}); |
102
|
|
|
}}); |
103
|
|
|
|
104
|
|
|
</script> |
105
|
|
|
''' |
106
|
|
|
|
107
|
|
|
class FileInput(DFileInput): |
108
|
|
|
|
109
|
|
|
def __init__(self, page=None, language=None, attrs=None, **kwargs): |
110
|
|
|
self.language = language |
111
|
|
|
self.page = page |
112
|
|
|
super(FileInput, self).__init__(attrs) |
113
|
|
|
|
114
|
|
|
please_save_msg = _('Please save the page to show the file field') |
115
|
|
|
delete_msg = _('Delete file') |
116
|
|
|
|
117
|
|
|
def render(self, name, value, attrs=None, **kwargs): |
118
|
|
|
if not self.page: |
119
|
|
|
field_content = self.please_save_msg |
120
|
|
|
else: |
121
|
|
|
field_content = '<span class="placeholder-fileinput">' |
122
|
|
|
if value: |
123
|
|
|
field_content += _('Current file: %s<br/>') % value |
124
|
|
|
field_content += '<hr>' |
125
|
|
|
field_content += super(FileInput, self).render(name, attrs) |
126
|
|
|
field_content += insert_image_link.format( |
127
|
|
|
name=name, |
128
|
|
|
del_msg=self.delete_msg, |
129
|
|
|
value=value) |
130
|
|
|
field_content += '</span>' |
131
|
|
|
return mark_safe(field_content) |
132
|
|
|
register_widget(FileInput) |
133
|
|
|
|
134
|
|
|
|
135
|
|
|
class ImageInput(FileInput): |
136
|
|
|
|
137
|
|
|
please_save_msg = _('Please save the page to show the image field') |
138
|
|
|
delete_msg = _('Delete image') |
139
|
|
|
|
140
|
|
|
register_widget(ImageInput) |
141
|
|
|
|
142
|
|
|
|
143
|
|
|
class LanguageChoiceWidget(TextInput): |
144
|
|
|
|
145
|
|
|
def __init__(self, language=None, attrs=None, **kwargs): |
146
|
|
|
self.language = language |
147
|
|
|
self.page = kwargs.get('page') |
148
|
|
|
# page is None |
149
|
|
|
super(LanguageChoiceWidget, self).__init__(attrs) |
150
|
|
|
|
151
|
|
|
def render(self, name, value, attrs=None, **kwargs): |
152
|
|
|
context = { |
153
|
|
|
'name': name, |
154
|
|
|
'value': value, |
155
|
|
|
'page': self.page, |
156
|
|
|
'language': value, |
157
|
|
|
'page_languages': PAGE_LANGUAGES |
158
|
|
|
} |
159
|
|
|
return mark_safe(render_to_string( |
160
|
|
|
'pages/widgets/languages.html', context)) |
161
|
|
|
|
162
|
|
|
|
163
|
|
|
class PageLinkWidget(MultiWidget): |
164
|
|
|
'''A page link `Widget` for the admin.''' |
165
|
|
|
|
166
|
|
|
def __init__( |
167
|
|
|
self, attrs=None, page=None, language=None, |
168
|
|
|
video_url=None, linkedpage=None, text=None): |
169
|
|
|
l = [('', '----')] |
170
|
|
|
for p in Page.objects.all(): |
171
|
|
|
l.append((p.id, str(p))) |
172
|
|
|
widgets = [ |
173
|
|
|
forms.Select(choices=l), |
174
|
|
|
TextInput(attrs=attrs) |
175
|
|
|
] |
176
|
|
|
super(PageLinkWidget, self).__init__(widgets, attrs) |
177
|
|
|
|
178
|
|
|
def decompress(self, value): |
179
|
|
|
import json |
180
|
|
|
try: |
181
|
|
|
return json.loads(value) |
182
|
|
|
except: |
183
|
|
|
pass |
184
|
|
|
return [] |
185
|
|
|
|
186
|
|
|
def value_from_datadict(self, data, files, name): |
187
|
|
|
import json |
188
|
|
|
value = ['', ''] |
189
|
|
|
for da in [x for x in data if x.startswith(name)]: |
190
|
|
|
index = int(da[len(name) + 1:]) |
191
|
|
|
value[index] = data[da] |
192
|
|
|
if value[0] == value[1] == '': |
193
|
|
|
return None |
194
|
|
|
return json.dumps(value) |
195
|
|
|
|
196
|
|
|
def _has_changed(self, initial, data): |
197
|
|
|
"""Need to be reimplemented to be correct.""" |
198
|
|
|
if data == initial: |
199
|
|
|
return False |
200
|
|
|
return bool(initial) != bool(data) |
201
|
|
|
|
202
|
|
|
def format_output(self, rendered_widgets): |
203
|
|
|
""" |
204
|
|
|
Given a list of rendered widgets (as strings), it inserts an HTML |
205
|
|
|
linebreak between them. |
206
|
|
|
|
207
|
|
|
Returns a Unicode string representing the HTML for the whole lot. |
208
|
|
|
""" |
209
|
|
|
return """<table> |
210
|
|
|
<tr><td>page</td><td>%s</td></tr> |
211
|
|
|
<tr><td>text</td><td>%s</td></tr> |
212
|
|
|
</table>""" % tuple(rendered_widgets) |
213
|
|
|
register_widget(PageLinkWidget) |
214
|
|
|
|