Changes for page Attachments
Last modified by Сергей Коршунов on 2025/09/03 11:22
From version 5.1
edited by Сергей Коршунов
on 2022/07/28 11:01
on 2022/07/28 11:01
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-attachment-ui/14.6]
To version 18.1
edited by Сергей Коршунов
on 2025/09/03 11:22
on 2025/09/03 11:22
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-attachment-ui/17.7.0]
Summary
-
Page properties (1 modified, 0 added, 0 removed)
-
Objects (3 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -38,7 +38,7 @@ 38 38 * @param $targetAttachDocument the document to list/save attachments to 39 39 * @param $options generic picker options 40 40 *# 41 -#macro (attachmentPicker_displayAttachmentGallery $targetDocument, $targetAttachDocument, $options) 41 +#macro (_attachmentPicker_displayAttachmentGallery $targetDocument, $targetAttachDocument, $options) 42 42 #set ($currentValue = $targetDocument.getValue($options.property)) 43 43 #if ("$!{targetAttachDocument.getAttachment($currentValue)}" == '') 44 44 #set ($currentValue = "$!{options.defaultValue}") ... ... @@ -45,16 +45,19 @@ 45 45 #end 46 46 (% class="gallery" %)((( 47 47 ## Only display the upload form if they have edit permission on targetAttachDocument 48 - #if ($xwiki.hasAccessLevel('edit',$xcontext.user,${targetAttachDocument.fullName})) 49 - #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options) 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}") ) 50 50 #end 51 - #attachmentPicker_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue) 52 - #set ($sortedAttachments = $collectiontool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") ) 53 53 #foreach ($attachment in $sortedAttachments) 54 54 #set ($extension = $attachment.getFilename()) 55 55 #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase()) 56 56 #if ($options.filter.size() == 0 || $options.filter.contains($extension)) 57 - #attachmentPicker_displayAttachmentBox($attachment $targetDocument $targetAttachDocument, $options $currentValue) 60 + #_attachmentPicker_displayAttachmentBox($attachment $targetDocument $targetAttachDocument, $options $currentValue) 58 58 #end 59 59 #end 60 60 ))) ... ... @@ -68,14 +68,26 @@ 68 68 * @param $options generic picker options 69 69 * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value 70 70 *# 71 -#macro (attachmentPicker_displayAttachmentBox $attachment $targetDocument $targetAttachDocument, $options $currentValue) 72 - #if ($options.displayImage && $attachment.isImage()) 73 - #set ($cssClass = 'gallery_image') 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) 74 74 #else 75 - #set ($cssClass = '') 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) 76 76 #end 77 - #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "$!{cssClass}"} $currentValue) 78 - #attachmentPicker_displayAttachmentDetails($attachment $options) 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) 93 + #_attachmentPicker_displayAttachmentDetails($attachment $options) 79 79 #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString))) 80 80 #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") ) 81 81 #set ($viewURL = $targetAttachDocument.getAttachmentURL($attachment.filename) )##{'name' : 'download', 'url' : $viewURL, 'rel' : '__blank'} ... ... @@ -83,7 +83,20 @@ 83 83 "${options.get('classname')}_${options.get('object')}_${options.get('property')}": ${attachment.filename}, 84 84 'form_token': $!{services.csrf.getToken()} 85 85 }))) 86 - #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}, {'name' : 'delete', 'url' : $deleteURL}]) 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, 'icon' : 'check', 'extraCssClass' : 'btn btn-xs btn-success'}]) 104 + #if($canDeleteAttachment) 105 + #set ($discard = $attachmentActions.add({'name' : 'delete', 'url' : $deleteURL, 'icon' : 'cross', 'extraCssClass' : 'btn btn-xs btn-danger'})) 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) 87 87 #end 88 88 89 89 #** ... ... @@ -93,9 +93,10 @@ 93 93 * the title to display (boxOptions.text), optional extra CSS classnames to put on the box (boxOptions.cssClass) 94 94 * @param $currentValue the currently selected file, used for determining if this attachment should be highlighted as the current value 95 95 *# 96 -#macro (attachmentPicker_displayStartFrame $boxOptions $currentValue) 124 +#macro (_attachmentPicker_displayStartFrame $boxOptions $currentValue) 97 97 (% class="gallery_attachmentbox $!{boxOptions.cssClass} #if ("$!{boxOptions.value}" == $currentValue) current#{end}" %)((( 98 98 (% class="gallery_attachmenttitle" title="$services.rendering.escape($!{boxOptions.value}, 'xwiki/2.1')" %)((( 127 + #if($!{boxOptions.cssClass} == 'gallery_upload')$services.icon.render('add') #end## 99 99 $services.rendering.escape($boxOptions.text, 'xwiki/2.1') 100 100 ))) 101 101 (% class="gallery_attachmentframe" %)((( ... ... @@ -108,7 +108,7 @@ 108 108 * @param $attachment the target attachment to display 109 109 * @param $options generic picker options 110 110 *# 111 -#macro (attachmentPicker_displayAttachmentDetails $attachment $options) 140 +#macro (_attachmentPicker_displayAttachmentDetails $attachment $options) 112 112 #if ($attachment) 113 113 ## Compute the attachment reference because there's no getter. 114 114 #set ($attachmentReference = $services.model.createAttachmentReference($attachment.document.documentReference, ... ... @@ -139,14 +139,18 @@ 139 139 * <dt>rel</dt> 140 140 * <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> 141 141 * </dl> 171 + * @param $additionalContent optional additional content that does not follow the structure of the actions 142 142 *# 143 -#macro (attachmentPicker_displayEndFrame $actions) 173 +#macro (_attachmentPicker_displayEndFrame $actions $additionalContent) 144 144 )))## attachmentframe 145 145 (% class="gallery_actions" %)((( 146 146 #foreach ($action in $actions) 147 147 #set( $actionname = $services.localization.render("${translationPrefix}.actions.${action.name}") ) 148 - [[${actionname}>>path:${action.url}||class="tool ${action.name}" title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]## 178 + [[${services.icon.render($action.icon)}(% class="sr-only"%)${actionname}(%%)>>## 179 + path:${action.url}||class="tool ${action.name} $!{action.extraCssClass}"## 180 + title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]## 149 149 #end 182 + $!additionalContent 150 150 )))## actions 151 151 )))## attachmentbox 152 152 #end ... ... @@ -158,8 +158,8 @@ 158 158 * @param $targetAttachDocument the document to upload the attachment to 159 159 * @param $options generic picker options 160 160 *# 161 -#macro (attachmentPicker_displayUploadForm $targetDocument, $targetAttachDocument, $options) 162 -#attachmentPicker_displayStartFrame({ 194 +#macro (_attachmentPicker_displayUploadForm $targetDocument, $targetAttachDocument, $options) 195 +#_attachmentPicker_displayStartFrame({ 163 163 'value' : $services.localization.render("${translationPrefix}.upload.title"), 164 164 'text' : $services.localization.render("${translationPrefix}.upload.title"), 165 165 'cssClass' : 'gallery_upload' ... ... @@ -206,7 +206,7 @@ 206 206 </div> 207 207 </form> 208 208 {{/html}} 209 -#attachmentPicker_displayEndFrame ([]) 242 +#_attachmentPicker_displayEndFrame ([]) 210 210 #end 211 211 212 212 #** ... ... @@ -217,7 +217,7 @@ 217 217 * @param $options generic picker options 218 218 * @param $currentValue the currently selected file, used for determining if the empty box should be highlighted as the current value 219 219 *# 220 -#macro (attachmentPicker_displayAttachmentGalleryEmptyValue $targetDocument, $targetAttachDocument, $options, $currentValue) 253 +#macro (_attachmentPicker_displayAttachmentGalleryEmptyValue $targetDocument, $targetAttachDocument, $options, $currentValue) 221 221 #if ("$!{options.get('defaultValue')}" != '') 222 222 #set ($reference = ${options.get('defaultValue')}) 223 223 #set ($docNameLimit = $reference.indexOf('@')) ... ... @@ -232,11 +232,11 @@ 232 232 #set($dcssClass = 'gallery_image') 233 233 #end 234 234 #end 235 - #attachmentPicker_displayStartFrame({'cssClass' : "gallery_emptyChoice $!{dcssClass}", 'text' : $services.localization.render("${translationPrefix}.default"), 'value' : "${options.defaultValue}"} $currentValue) 236 - #attachmentPicker_displayAttachmentDetails($defaultAttachment $options) 268 + #_attachmentPicker_displayStartFrame({'cssClass' : "gallery_emptyChoice $!{dcssClass}", 'text' : $services.localization.render("${translationPrefix}.default"), 'value' : "${options.defaultValue}"} $currentValue) 269 + #_attachmentPicker_displayAttachmentDetails($defaultAttachment $options) 237 237 #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString))) 238 238 #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, "${options.get('classname')}_${options.get('object')}_${options.get('property')}=&form_token=$!{services.csrf.getToken()}")) 239 - #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}]) 272 + #_attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL, 'icon' : 'check', 'extraCssClass' : 'btn btn-xs btn-success'}]) 240 240 #end 241 241 {{/velocity}} 242 242 ... ... @@ -301,10 +301,12 @@ 301 301 'versionSummary': $request.versionSummary.equals('true') 302 302 }) 303 303 $!targetDocument.use($targetDocument.getObject($options.classname, $options.object))## 304 - #attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options) 337 + #_attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options) 305 305 339 + #set ($cancelLinkName = $services.rendering.escape($services.rendering.escape($services.localization.render("${translationPrefix}.cancel"), 'xwiki/2.1'), 'xwiki/2.1')) 340 + #set ($cancelLinkTarget = $services.rendering.escape($services.model.serialize($targetDocument), 'xwiki/2.1')) 306 306 (% class="gallery_buttons buttons" %)((( 307 - (% class="buttonwrapper secondary" %)[[$ services.localization.render("${translationPrefix}.cancel")>>${targetDocument}||class="button secondary" id="attachment-picker-close"]]342 + (% class="buttonwrapper secondary" %)[[$cancelLinkName>>$cancelLinkTarget||class="button secondary" id="attachment-picker-close"]] 308 308 ))) 309 309 #end 310 310 {{/velocity}}
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,4 +1,66 @@ 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 + 2 2 /** Handles the gallery buttons directly in the current page without reloading the window. */ 3 3 XWiki.AttachmentPicker = Class.create({ 4 4 /** ... ... @@ -60,21 +60,23 @@ 60 60 new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.error.badExtension')", 'error'); 61 61 hasErrors = true; 62 62 } 125 + const beforeUploadEvent = Event.fire(document, 'xwiki:actions:beforeUpload', { 126 + file: fileInput.files[0] 127 + }); 128 + 129 + if (beforeUploadEvent.defaultPrevented) { 130 + hasErrors = true; 131 + } 63 63 }.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 66 66 if (!hasErrors) { 67 67 if (this.directSave) { 68 68 uploadForm.submit(); 69 69 } else { 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')}); 137 + if ("$!services.temporaryAttachments" != '') { 138 + uploadTemporaryAttachment.call(this); 139 + } else { 140 + directUploadAttachment.call(this, uploadForm); 141 + } 78 78 } 79 79 } 80 80 }.bindAsEventListener(this));
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -25,9 +25,12 @@ 25 25 margin: 0; 26 26 } 27 27 .gallery_attachmentbox { 28 + display: grid; 29 + gap: .2rem; 28 28 background: $theme.pageContentBackgroundColor; 31 + padding: .2rem; 29 29 border: 1px solid $theme.borderColor; 30 - border-radius: 5px;33 + border-radius: var(--border-radius-base); 31 31 float: left; 32 32 margin: ${boxMargin}px; 33 33 overflow: hidden; ... ... @@ -36,8 +36,6 @@ 36 36 } 37 37 .gallery .current { 38 38 background-color: $theme.highlightColor; 39 - border-width: 3px; 40 - margin: 3px; 41 41 } 42 42 .gallery .current .gallery_attachmenttitle { 43 43 font-weight: bold; ... ... @@ -47,9 +47,7 @@ 47 47 } 48 48 49 49 .gallery_attachmenttitle { 50 - background: $theme.backgroundSecondaryColor; 51 - border-bottom: 1px dotted $theme.borderColor; 52 - border-radius: 5px 5px 0px 0px; 51 + grid-area: 1 / 1 / 2 / 2; 53 53 font-size: 85%; 54 54 padding: 3px ${boxPadding}px; 55 55 overflow: hidden; ... ... @@ -62,7 +62,7 @@ 62 62 } 63 63 64 64 .gallery_attachmentframe { 65 - padding:${boxPadding}px;64 + grid-area: 2 / 1 / 3 / 3; 66 66 height: ${imgSize}px; 67 67 overflow: hidden; 68 68 position: relative; ... ... @@ -101,39 +101,16 @@ 101 101 } 102 102 103 103 /* Actions */ 104 -.gallery_actions { 105 - width:auto;106 - position:absolute;107 - bottom:0px;108 - right: ${boxPadding}px;103 +.gallery_actions p { 104 + grid-area: 1 / 2 / 2 / 3; 105 + display: flex; 106 + justify-content: flex-end; 107 + gap: .2rem; 109 109 } 110 110 .gallery_actions .tool { 111 - background: none no-repeat 50% transparent; 112 112 cursor: pointer; 113 113 display: block; 114 - float: left; 115 - height: ${actionsHeight}px; 116 - padding: 0 !important; 117 - overflow: hidden; 118 - text-indent: -1000em; 119 - opacity: 0.6; 120 - width: ${actionsWidth}px; 121 121 } 122 -.gallery_actions .tool:hover { 123 - opacity: 1; 124 -} 125 -.gallery_actions .select { 126 - background-image: url("$xwiki.getSkinFile('icons/silk/tick.png')"); 127 -} 128 -.gallery_actions .delete { 129 - background-image: url("$xwiki.getSkinFile('icons/silk/cross.png')"); 130 -} 131 -.gallery_actions .view { 132 - background-image: url("$xwiki.getSkinFile('icons/silk/link.png')"); 133 -} 134 -.gallery_actions .download { 135 - background-image: url("$xwiki.getSkinFile('icons/silk/arrow_down.png')"); 136 -} 137 137 /*--------------------------------------------------*/ 138 138 /* Upload form */ 139 139 .gallery_upload { ... ... @@ -144,12 +144,6 @@ 144 144 background-color: $theme.backgroundSecondaryColor; 145 145 } 146 146 147 -.gallery_upload .gallery_attachmenttitle { 148 - background-position: 1px center; 149 - background-image: url("$xwiki.getSkinFile('icons/silk/bullet_add.png')"); 150 - background-repeat: no-repeat; 151 - padding-left: 16px; 152 -} 153 153 .gallery_upload .gallery_attachmentframe { 154 154 height: auto; 155 155 }
- XWiki.WikiMacroClass[0]
-
- Macro code
-
... ... @@ -33,7 +33,7 @@ 33 33 #set ($property = "$!{xcontext.macro.params.property}") 34 34 #set ($object = $numbertool.toNumber("$!{xcontext.macro.params.object}").intValue()) 35 35 #if ("$!{object}" != $!{xcontext.macro.params.object}) 36 - #set ($object = ${doc.getObject($classname).number}) 36 + #set ($object = ${targetdoc.getObject($classname).number}) 37 37 #if ("$!{object}" == '') 38 38 #set ($object = 0) 39 39 #end ... ... @@ -94,10 +94,10 @@ 94 94 #set ($savemode = 'form') 95 95 #end 96 96 97 -#set ($propValue = "$!{doc.getObject($classname, $object).getProperty($property).value}") 97 +#set ($propValue = "$!{targetdoc.getObject($classname, $object).getProperty($property).value}") 98 98 ## 99 99 100 -#macro (attachmentPicker_displayAttachment $name $displayImage $withLink $forceElement) 100 +#macro (_attachmentPicker_displayAttachment $name $displayImage $withLink $forceElement) 101 101 #set ($attachment = $targetdoc.getAttachment("$!{name}")) 102 102 #if ("$!{name}" != '' && "$!{attachment}" != '') 103 103 #set ($attachmentRef = $services.model.createAttachmentReference(${targetdoc.documentReference}, ${name})) ... ... @@ -123,7 +123,7 @@ 123 123 #if ($displayImage) 124 124 (% class="$!{cssClass}#if (!$attachment) hidden#end" %)(((#if ("$!{attachmentResource}" != '' || $forceElement)#if($withLink)[[#end[[image:$services.rendering.escape(${attachmentResource}, 'xwiki/2.1')$!{imageParams}]]#if($withLink)>>attach:$services.rendering.escape(${attachmentResource},'xwiki/2.1')||rel=lightbox]]#{end}#end)))## 125 125 #else 126 - (% class="$!{cssClass}" %)#if ("$!{attachmentResource}" != '' || $forceElement)#if ($withLink)[[attach:${attachmentResource}||rel=__blank]]#{else}(% class="displayed" %)#if($targetPermView)$services.rendering.escape($!{attachmentName}, 'xwiki/2.1')#{else}Access Denied#{end}(% %)#{end}#end(%%)## 126 + (% class="$!{cssClass}" %)#if ("$!{attachmentResource}" != '' || $forceElement)#if ($withLink)[[attach:${attachmentResource}||rel=__blank]]#{else}(% class="displayed" %)#if($targetPermView)$!{services.rendering.escape($!{attachmentName}, 'xwiki/2.1')}#{else}Access Denied#{end}(% %)#{end}#end(%%)## 127 127 #end 128 128 #end 129 129 ... ... @@ -130,8 +130,8 @@ 130 130 ## Display the "Choose an attachment" button if they can: 131 131 ## 1. Edit the current page 132 132 ## 2. View the target attachment page. (can be the same page) 133 -#macro (attachmentPicker_displayButton) 134 - #if ($ hasEdit&& $targetPermView)133 +#macro (_attachmentPicker_displayButton) 134 + #if ($targetPermView) 135 135 #set ($queryString = { 136 136 'docname': $doc.fullName, 137 137 'classname': $classname, ... ... @@ -155,13 +155,13 @@ 155 155 156 156 {{velocity}} 157 157 #if ("${savemode}" == 'direct') 158 - (% class="attachment-picker" %)(((#attachmentPicker_displayAttachment($propValue $displayImage $link true) #attachmentPicker_displayButton()))) 158 + (% class="attachment-picker" %)(((#_attachmentPicker_displayAttachment($propValue $displayImage $link true) #_attachmentPicker_displayButton()))) 159 159 #elseif ($xcontext.action == 'inline' || $xcontext.action == 'edit') 160 160 (% class="attachment-picker" %)(((## 161 - #attachmentPicker_displayAttachment($propValue $displayImage false true) #attachmentPicker_displayButton()## 162 - {{html}}<input type="hidden" name="${classname}_${object}_${property}" value="${propValue}"/>{{/html}}## 161 + #_attachmentPicker_displayAttachment($propValue $displayImage false true) #_attachmentPicker_displayButton()## 162 + {{html}}<input type="hidden" name="$escapetool.xml("${classname}_${object}_${property}")" value="$escapetool.xml("${propValue}")" class="property-reference"/>{{/html}}## 163 163 ))) 164 164 #else 165 - #attachmentPicker_displayAttachment($propValue $displayImage $link false) 165 + #_attachmentPicker_displayAttachment($propValue $displayImage $link false) 166 166 #end 167 167 {{/velocity}}