Changes for page Attachments

Last modified by Sebastian Marsching on 2024/01/08 23:13

From version 6.1
edited by Sebastian Marsching
on 2022/11/02 11:24
Change comment: Install extension [org.xwiki.platform:xwiki-platform-attachment-ui/14.9]
To version 4.1
edited by Sebastian Marsching
on 2022/08/02 11:45
Change comment: Migrated property [defaultCategories] from class [XWiki.WikiMacroClass]

Summary

Details

Page properties
Content
... ... @@ -45,14 +45,11 @@
45 45   #end
46 46   (% class="gallery" %)(((
47 47   ## Only display the upload form if they have edit permission on targetAttachDocument
48 - #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
49 - #attachmentPicker_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue)
50 - #if ("$!services.temporaryAttachments" != '')
51 - #set ($unsortedAttachments = $services.temporaryAttachments.listAllAttachments($targetAttachDocument))
52 - #set ($sortedAttachments = $collectiontool.sort($unsortedAttachments, "${options.sortAttachmentsBy}"))
53 - #else
54 - #set ($sortedAttachments = $collectiontool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") )
48 + #if ($xwiki.hasAccessLevel('edit',$xcontext.user,${targetAttachDocument.fullName}))
49 + #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
55 55   #end
51 + #attachmentPicker_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue)
52 + #set ($sortedAttachments = $collectiontool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") )
56 56   #foreach ($attachment in $sortedAttachments)
57 57   #set ($extension = $attachment.getFilename())
58 58   #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase())
... ... @@ -72,24 +72,12 @@
72 72   * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value
73 73   *#
74 74  #macro (attachmentPicker_displayAttachmentBox $attachment $targetDocument $targetAttachDocument, $options $currentValue)
75 - #set ($hasTemporaryAttachment = "$!services.temporaryAttachments" != '')
76 - #set ($canEdit = $xwiki.hasAccessLevel('edit', $xcontext.user, ${targetAttachDocument.fullName}))
77 - #set ($isTemporaryAttachment = false)
78 - #if(!$hasTemporaryAttachment)
79 - #set ($canDeleteAttachment = $canEdit)
72 + #if ($options.displayImage && $attachment.isImage())
73 + #set ($cssClass = 'gallery_image')
80 80   #else
81 - #set ($isTemporaryAttachment = $services.temporaryAttachments.temporaryAttachmentExists($attachment))
82 - ## TODO: Update once it is made possible to delete temporary attachments (see XWIKI-20225).
83 - #set ($canDeleteAttachment = !$isTemporaryAttachment && $canEdit)
75 + #set ($cssClass = '')
84 84   #end
85 - #set ($cssClasses = [])
86 - #if ($options.displayImage && $attachment.isImage())
87 - #set ($discard = $cssClasses.add('gallery_image'))
88 - #end
89 - #if ($isTemporaryAttachment)
90 - #set ($discard = $cssClasses.add('temporary_attachment'))
91 - #end
92 - #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "${stringtool.join($cssClasses, ' ')}"} $currentValue)
77 + #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "$!{cssClass}"} $currentValue)
93 93   #attachmentPicker_displayAttachmentDetails($attachment $options)
94 94   #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString)))
95 95   #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") )
... ... @@ -98,20 +98,7 @@
98 98   "${options.get('classname')}_${options.get('object')}_${options.get('property')}": ${attachment.filename},
99 99   'form_token': $!{services.csrf.getToken()}
100 100   })))
101 - ## Delete action is only proposed for users with the edit right on the document.
102 - ## If the temporary attachment is available, the delete action is only allowed for non-temporary attachments.
103 - #set ($attachmentActions = [{'name' : 'select', 'url' : $selectURL}])
104 - #if($canDeleteAttachment)
105 - #set ($discard = $attachmentActions.add({'name' : 'delete', 'url' : $deleteURL}))
106 - #end
107 - #define($additionalContent)
108 - #if ($isTemporaryAttachment)
109 - #set ($titleMessage = $services.localization.render('attachment.attachmentSelector.attachmentBox.temporaryAttachmentTitle'))
110 - #set ($titleMessage = $services.rendering.escape($titleMessage, 'xwiki/2.1'))
111 - (% title="$titleMessage" %)$services.icon.render('clock')(%%)
112 - #end
113 - #end
114 - #attachmentPicker_displayEndFrame ($attachmentActions $additionalContent)
86 + #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}, {'name' : 'delete', 'url' : $deleteURL}])
115 115  #end
116 116  
117 117  #**
... ... @@ -167,9 +167,8 @@
167 167   * <dt>rel</dt>
168 168   * <dd>an optional parameter to be used in the "rel" HTML attribute; for example "__blank" can be used to open the link in a new tab/window</dd>
169 169   * </dl>
170 - * @param $additionalContent optional additional content that does not follow the structure of the actions
171 171   *#
172 -#macro (attachmentPicker_displayEndFrame $actions $additionalContent)
143 +#macro (attachmentPicker_displayEndFrame $actions)
173 173   )))## attachmentframe
174 174   (% class="gallery_actions" %)(((
175 175   #foreach ($action in $actions)
... ... @@ -176,7 +176,6 @@
176 176   #set( $actionname = $services.localization.render("${translationPrefix}.actions.${action.name}") )
177 177   [[${actionname}>>path:${action.url}||class="tool ${action.name}" title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]##
178 178   #end
179 - $!additionalContent
180 180   )))## actions
181 181   )))## attachmentbox
182 182  #end
XWiki.JavaScriptExtension[0]
Code
... ... @@ -1,66 +1,4 @@
1 1  var XWiki = (function(XWiki) {
2 - function uploadTemporaryAttachment() {
3 - // Require jquery locally until we are able to fully migrate this code away from prototype.
4 - const form = this.property.up('form');
5 - require(['jquery'], function ($) {
6 - const data = new FormData();
7 - const uploadedFile = $('#attachfile')[0].files[0];
8 - const filenameCheckbox = $("#uploadAttachment input[name='filename']");
9 -
10 - // TODO: Fix replace currently selected checkbox (see XWIKI-20181).
11 - data.append('upload', uploadedFile);
12 - const notification = new XWiki.widgets.Notification(
13 - "$services.localization.render('xe.attachmentSelector.upload.inProgress')", 'inprogress');
14 - const params = {
15 - 'form_token': $(form).find('[name="form_token"]').val(),
16 - 'sheet': 'CKEditor.FileUploader',
17 - 'outputSyntax': 'plain'
18 - };
19 -
20 - // Update the name of the file with the name of the currently selected attachment if required.
21 - if (filenameCheckbox.prop('checked')) {
22 - params['filename'] = filenameCheckbox.val()
23 - }
24 -
25 - $.ajax({
26 - 'url': XWiki.currentDocument.getURL('get', new URLSearchParams(params).toString()),
27 - method: 'POST',
28 - data: data,
29 - processData: false,
30 - contentType: false, // Sets the 'multipart/form-data' automatically
31 - headers: {
32 - 'X-XWiki-Temporary-Attachment-Support': true
33 - }
34 - }).done(function (response) {
35 - #set ($successMessage = $escapetool.javascript($services.localization.render('attachment.attachmentSelector.temporaryUpload.success')))
36 - notification.replace(new XWiki.widgets.Notification("$successMessage", 'done'));
37 - // Add a field with the name of the uploaded file so that it is moved from the temporary
38 - // attachments to the persisded ones on save.
39 - $(form).append($('<input/>')
40 - .prop('type', 'hidden')
41 - .prop('name', 'uploadedFiles')
42 - .prop('value', response.fileName))
43 - $(form).find('input[type="hidden"].property-reference').prop('value', response.fileName);
44 - this.updateAttachment(response.fileName, response.url);
45 - this.dialog.closeDialog();
46 - }.bind(this)).fail(function () {
47 - #set ($errorMessage = $escapetool.javascript($services.localization.render('attachment.attachmentSelector.temporaryUpload.failure')))notification.replace(new XWiki.widgets.Notification("$errorMessage", 'error'));
48 - });
49 - }.bind(this));
50 - }
51 -
52 - function directUploadAttachment(uploadForm) {
53 - // FIXME This fails in HTML5, will deal with it later:
54 - // this.property.down('input').value = uploadForm.down('input[type="file"]').value;
55 - // uploadForm.xredirect.value = window.location.pathname;
56 - document.observe('xwiki:document:saved', function () {
57 - new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.inProgress')",
58 - 'inprogress');
59 - uploadForm.submit();
60 - })
61 - document.fire('xwiki:actions:save', {'continue': true, form: this.property.up('form')});
62 - }
63 -
64 64   /** Handles the gallery buttons directly in the current page without reloading the window. */
65 65   XWiki.AttachmentPicker = Class.create({
66 66   /**
... ... @@ -123,15 +123,20 @@
123 123   hasErrors = true;
124 124   }
125 125   }.bind(this));
64 + // No form submission by AJAX right now, because file uploads can't be done this way without HTML5, this is future work
65 + // Save the document before submitting, since the current form data will be lost otherwise
126 126   if (!hasErrors) {
127 127   if (this.directSave) {
128 128   uploadForm.submit();
129 129   } else {
130 - if ("$!services.temporaryAttachments" != '') {
131 - uploadTemporaryAttachment.call(this);
132 - } else {
133 - directUploadAttachment.call(this, uploadForm);
134 - }
70 + // FIXME This fails in HTML5, will deal with it later:
71 + // this.property.down('input').value = uploadForm.down('input[type="file"]').value;
72 + // uploadForm.xredirect.value = window.location.pathname;
73 + document.observe('xwiki:document:saved', function() {
74 + new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.inProgress')", 'inprogress');
75 + uploadForm.submit();
76 + })
77 + document.fire('xwiki:actions:save', {'continue': true, form: this.property.up('form')});
135 135   }
136 136   }
137 137   }.bindAsEventListener(this));
XWiki.WikiMacroClass[0]
Macro code
... ... @@ -131,7 +131,7 @@
131 131  ## 1. Edit the current page
132 132  ## 2. View the target attachment page. (can be the same page)
133 133  #macro (attachmentPicker_displayButton)
134 - #if ($targetPermView)
134 + #if ($hasEdit && $targetPermView)
135 135   #set ($queryString = {
136 136   'docname': $doc.fullName,
137 137   'classname': $classname,
... ... @@ -159,7 +159,7 @@
159 159  #elseif ($xcontext.action == 'inline' || $xcontext.action == 'edit')
160 160   (% class="attachment-picker" %)(((##
161 161   #attachmentPicker_displayAttachment($propValue $displayImage false true) #attachmentPicker_displayButton()##
162 - {{html}}<input type="hidden" name="${classname}_${object}_${property}" value="${propValue}" class="property-reference"/>{{/html}}##
162 + {{html}}<input type="hidden" name="${classname}_${object}_${property}" value="${propValue}"/>{{/html}}##
163 163   )))
164 164  #else
165 165   #attachmentPicker_displayAttachment($propValue $displayImage $link false)
Default categories
... ... @@ -1,1 +1,0 @@
1 -Development
Default category
... ... @@ -1,0 +1,1 @@
1 +Development