Skip to content

Commit d0cfe51

Browse files
committed
Enable ZMI History tab for OFS.Image.File
Modernize a bit the condition to display online text editor: support editing json inline and tolerate larger file content.
1 parent 1595981 commit d0cfe51

File tree

4 files changed

+70
-21
lines changed

4 files changed

+70
-21
lines changed

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst
1010
5.11.2 (unreleased)
1111
-------------------
1212

13+
- Enable ZMI History tab for ``OFS.Image.File``.
14+
(`#396 <https://github.com/zopefoundation/Zope/pull/396>`_)
15+
1316
- Fix error messages from spam/pen test requests.
1417

1518
- Fix a ``ResourceWarning`` emitted when uploading large files.

src/OFS/Image.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
from App.special_dtml import DTMLFile
3434
from DateTime.DateTime import DateTime
3535
from OFS.Cache import Cacheable
36+
from OFS.History import Historical
37+
from OFS.History import html_diff
3638
from OFS.interfaces import IWriteLock
3739
from OFS.PropertyManager import PropertyManager
3840
from OFS.role import RoleManager
@@ -167,6 +169,7 @@ class File(
167169
PropertyManager,
168170
RoleManager,
169171
Item_w__name__,
172+
Historical,
170173
Cacheable
171174
):
172175
"""A File object is a content object for arbitrary files."""
@@ -201,7 +204,9 @@ class File(
201204
+ PropertyManager.manage_options
202205
+ RoleManager.manage_options
203206
+ Item_w__name__.manage_options
204-
+ Cacheable.manage_options)
207+
+ Cacheable.manage_options
208+
+ Historical.manage_options
209+
)
205210

206211
_properties = (
207212
{'id': 'title', 'type': 'string'},
@@ -657,6 +662,31 @@ def manage_upload(self, file='', REQUEST=None):
657662
return self.manage_main(
658663
self, REQUEST, manage_tabs_message=msg)
659664

665+
@security.protected(change_images_and_files)
666+
def manage_is_editable_inline(self):
667+
return (
668+
self.content_type
669+
and (
670+
self.content_type.startswith('text')
671+
or self.content_type.endswith('javascript')
672+
or self.content_type == 'application/json'
673+
)
674+
and self.get_size() < 2**17
675+
)
676+
677+
def manage_historyCompare(self, rev1, rev2, REQUEST,
678+
historyComparisonResults=''):
679+
if self.manage_is_editable_inline():
680+
return File.inheritedAttribute('manage_historyCompare')(
681+
self, rev1, rev2, REQUEST,
682+
historyComparisonResults=html_diff(
683+
str(rev1.data),
684+
str(rev2.data)))
685+
return File.inheritedAttribute('manage_historyCompare')(
686+
self, rev1, rev2, REQUEST,
687+
historyComparisonResults=historyComparisonResults
688+
)
689+
660690
def _get_content_type(self, file, body, id, content_type=None):
661691
headers = getattr(file, 'headers', None)
662692
if headers and 'content-type' in headers:

src/OFS/dtml/fileEdit.dtml

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,28 +38,26 @@
3838
</div>
3939
</div>
4040

41-
<dtml-let ct=getContentType>
42-
<dtml-if "(ct.startswith('text') or ct.endswith('javascript')) and this().get_size() < 65536">
43-
<div class="form-group">
44-
<dtml-try>
45-
<textarea id="content" <dtml-if content_type>data-contenttype="&dtml-content_type;"</dtml-if>
46-
class="form-control zmi-file zmi-code col-sm-12"
47-
name="filedata:text" wrap="off" rows="20"><dtml-var __str__ html_quote></textarea>
48-
<dtml-except UnicodeDecodeError>
49-
<div class="alert alert-warning" role="alert">
50-
The file could not be decoded with '<dtml-var "error_value.encoding">'.
51-
</div>
52-
</dtml-try>
53-
</div>
54-
<dtml-else>
55-
<div class="form-group row">
56-
<label for="size" class="form-label col-sm-3 col-md-2">File Size</label>
57-
<div class="form-text col-sm-9 col-md-10">
58-
<dtml-var size thousands_commas> bytes
41+
<dtml-if manage_is_editable_inline>
42+
<div class="form-group">
43+
<dtml-try>
44+
<textarea id="content" <dtml-if content_type>data-contenttype="&dtml-content_type;"</dtml-if>
45+
class="form-control zmi-file zmi-code col-sm-12"
46+
name="filedata:text" wrap="off" rows="20"><dtml-var __str__ html_quote></textarea>
47+
<dtml-except UnicodeDecodeError>
48+
<div class="alert alert-warning" role="alert">
49+
The file could not be decoded with '<dtml-var "error_value.encoding">'.
5950
</div>
51+
</dtml-try>
52+
</div>
53+
<dtml-else>
54+
<div class="form-group row">
55+
<label for="size" class="form-label col-sm-3 col-md-2">File Size</label>
56+
<div class="form-text col-sm-9 col-md-10">
57+
<dtml-var size thousands_commas> bytes
6058
</div>
61-
</dtml-if>
62-
</dtml-let>
59+
</div>
60+
</dtml-if>
6361

6462
<div class="zmi-controls">
6563
<dtml-if wl_isLocked>

src/OFS/tests/testFileAndImage.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,24 @@ def test_text_representation_is_tag(self):
391391
'<img src="http://nohost/file"'
392392
' alt="" title="" height="16" width="16" />')
393393

394+
def test_history_compare(self):
395+
self.file.manage_edit(
396+
'a',
397+
'text/plain',
398+
filedata=b'content_of_a')
399+
getattr(
400+
self.app,
401+
self.factory)(
402+
'b',
403+
file=b'content_of_b',
404+
content_type='text/plain')
405+
page = self.file.manage_historyCompare(
406+
self.file,
407+
self.app.b,
408+
self.app.REQUEST)
409+
self.assertIn('content_of_a', page)
410+
self.assertIn('content_of_b', page)
411+
394412

395413
class SVGTests(ImageTests):
396414
content_type = 'image/svg+xml'

0 commit comments

Comments
 (0)