Wiki source code of #if ($request.docname)$xwiki.getDocument($request.docname).plainTitle ($request.docname): #end$services.localization.render('xe.attachmentSelector.gallery.title')
Version 11.1 by Sebastian Marsching on 2023/08/13 16:19
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{velocity output="false"}} | ||
2 | #set ($translationPrefix = 'xe.attachmentSelector') | ||
3 | |||
4 | #if ($request.xaction == 'postUpload') | ||
5 | #set ($targetDocument = $xwiki.getDocument($request.get('docname'))) | ||
6 | #set ($targetAttachDocument = $xwiki.getDocument($request.get('targetdocname'))) | ||
7 | |||
8 | #set ($fieldname = $request.get('fieldname')) | ||
9 | #set ($comment = $services.localization.render("${translationPrefix}.postUpload.comment", [$fieldname])) | ||
10 | #set ($docAction = $request.get('docAction')) | ||
11 | #set ($attachmentList = $targetAttachDocument.getAttachmentList()) | ||
12 | #if ($attachmentList && $attachmentList.size() > 0) | ||
13 | #set ($sortedAttachments = $collectiontool.sort($attachmentList, 'date:desc')) | ||
14 | #set ($lastAttachment = $sortedAttachments.get(0)) | ||
15 | #end | ||
16 | $response.sendRedirect($targetDocument.getURL($docAction, $escapetool.url({ | ||
17 | $fieldname: $lastAttachment.filename, | ||
18 | 'comment': $comment, | ||
19 | 'form_token': $request.form_token | ||
20 | }))) | ||
21 | #stop | ||
22 | #end | ||
23 | {{/velocity}} | ||
24 | |||
25 | {{velocity output="false"}} | ||
26 | ## | ||
27 | ## Macros | ||
28 | ## | ||
29 | #set ($attachmentPickerDocName = 'XWiki.AttachmentSelector') | ||
30 | |||
31 | $xwiki.ssx.use($attachmentPickerDocName) | ||
32 | $xwiki.jsx.use($attachmentPickerDocName) | ||
33 | |||
34 | #** | ||
35 | * Displays the attachment gallery as a list of attachment boxes, starting with special boxes for uploading a new attachment and for setting a default value. | ||
36 | * | ||
37 | * @param $targetDocument the document to recieve the field value being modified | ||
38 | * @param $targetAttachDocument the document to list/save attachments to | ||
39 | * @param $options generic picker options | ||
40 | *# | ||
41 | #macro (attachmentPicker_displayAttachmentGallery $targetDocument, $targetAttachDocument, $options) | ||
42 | #set ($currentValue = $targetDocument.getValue($options.property)) | ||
43 | #if ("$!{targetAttachDocument.getAttachment($currentValue)}" == '') | ||
44 | #set ($currentValue = "$!{options.defaultValue}") | ||
45 | #end | ||
46 | (% class="gallery" %)((( | ||
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}") ) | ||
55 | #end | ||
56 | #foreach ($attachment in $sortedAttachments) | ||
57 | #set ($extension = $attachment.getFilename()) | ||
58 | #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase()) | ||
59 | #if ($options.filter.size() == 0 || $options.filter.contains($extension)) | ||
60 | #attachmentPicker_displayAttachmentBox($attachment $targetDocument $targetAttachDocument, $options $currentValue) | ||
61 | #end | ||
62 | #end | ||
63 | ))) | ||
64 | #end | ||
65 | |||
66 | #** | ||
67 | * Displays an attachment box. | ||
68 | * | ||
69 | * @param $attachment the target attachment to display | ||
70 | * @param $targetDocument the document being modified | ||
71 | * @param $options generic picker options | ||
72 | * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value | ||
73 | *# | ||
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) | ||
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) | ||
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) | ||
93 | #attachmentPicker_displayAttachmentDetails($attachment $options) | ||
94 | #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString))) | ||
95 | #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") ) | ||
96 | #set ($viewURL = $targetAttachDocument.getAttachmentURL($attachment.filename) )##{'name' : 'download', 'url' : $viewURL, 'rel' : '__blank'} | ||
97 | #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, $escapetool.url({ | ||
98 | "${options.get('classname')}_${options.get('object')}_${options.get('property')}": ${attachment.filename}, | ||
99 | 'form_token': $!{services.csrf.getToken()} | ||
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) | ||
115 | #end | ||
116 | |||
117 | #** | ||
118 | * Writes the wiki code used at the start of an attachment box. Outputs the attachment title bar, and opens the inner frame div. | ||
119 | * | ||
120 | * @param $boxOptions a map of parameters/options for the current attachment, holding, for example, the attachment name (boxOptions.value), | ||
121 | * the title to display (boxOptions.text), optional extra CSS classnames to put on the box (boxOptions.cssClass) | ||
122 | * @param $currentValue the currently selected file, used for determining if this attachment should be highlighted as the current value | ||
123 | *# | ||
124 | #macro (attachmentPicker_displayStartFrame $boxOptions $currentValue) | ||
125 | (% class="gallery_attachmentbox $!{boxOptions.cssClass} #if ("$!{boxOptions.value}" == $currentValue) current#{end}" %)((( | ||
126 | (% class="gallery_attachmenttitle" title="$services.rendering.escape($!{boxOptions.value}, 'xwiki/2.1')" %)((( | ||
127 | $services.rendering.escape($boxOptions.text, 'xwiki/2.1') | ||
128 | ))) | ||
129 | (% class="gallery_attachmentframe" %)((( | ||
130 | #end | ||
131 | |||
132 | #** | ||
133 | * Displays details about an attachment inside the attachment box. If the attachment is an image and the "displayImage" option is on, | ||
134 | * then the image is displayed. Otherwise, some basic information is displayed: the version, the size, the date and the author. | ||
135 | * | ||
136 | * @param $attachment the target attachment to display | ||
137 | * @param $options generic picker options | ||
138 | *# | ||
139 | #macro (attachmentPicker_displayAttachmentDetails $attachment $options) | ||
140 | #if ($attachment) | ||
141 | ## Compute the attachment reference because there's no getter. | ||
142 | #set ($attachmentReference = $services.model.createAttachmentReference($attachment.document.documentReference, | ||
143 | $attachment.filename)) | ||
144 | #set ($attachmentStringReference = $services.rendering.escape($services.model.serialize($attachmentReference, 'default'), 'xwiki/2.1')) | ||
145 | #if ($attachment.isImage() && $options.displayImage) | ||
146 | ## We add the version to the query string in order to invalidate the cache when an image attachment is replaced. | ||
147 | #set ($queryString = $escapetool.url({'version': $attachment.version})) | ||
148 | [[[[image:${attachmentStringReference}||width=180 queryString="$queryString"]]>>attach:$attachmentStringReference]] | ||
149 | #else | ||
150 | * (% class="mime" %){{html wiki=false clean=false}}#mimetypeimg($attachment.getMimeType().toLowerCase() $attachment.getFilename().toLowerCase()){{/html}}(%%) (% class="filename" %)$services.rendering.escape($attachment.getFilename(), 'xwiki/2.1')(% %) | ||
151 | * v$attachment.getVersion() (#dynamicsize($attachment.longSize)) | ||
152 | * $services.localization.render('core.viewers.attachments.author', [$!{xwiki.getUserName($attachment.author, false)}]) $services.localization.render('core.viewers.attachments.date', [$!{xwiki.formatDate($attachment.date, 'dd/MM/yyyy hh:mm')}]) | ||
153 | * (% class="buttonwrapper" %)[[${services.localization.render("${translationPrefix}.actions.download")}>>attach:${attachmentStringReference}||title="$services.localization.render("${translationPrefix}.actions.download")" rel="__blank" class="button"]](%%) | ||
154 | #end | ||
155 | #end | ||
156 | #end | ||
157 | |||
158 | #** | ||
159 | * Writes the wiki code used at the end of an attachment box. Closes the inner frame div, and outputs the attachment actions. | ||
160 | * | ||
161 | * @param $actions a list of maps defining action buttons, where each entry contains a subset of the following: | ||
162 | * <dl> | ||
163 | * <dt>name</dt> | ||
164 | * <dd>identifies the action; the name is used as a CSS classname, and in the translation key for the display text, as "xe.attachmentSelector.actions.<name>"</dd> | ||
165 | * <dt>url</dt> | ||
166 | * <dd>the destination of the button</dd> | ||
167 | * <dt>rel</dt> | ||
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 | * </dl> | ||
170 | * @param $additionalContent optional additional content that does not follow the structure of the actions | ||
171 | *# | ||
172 | #macro (attachmentPicker_displayEndFrame $actions $additionalContent) | ||
173 | )))## attachmentframe | ||
174 | (% class="gallery_actions" %)((( | ||
175 | #foreach ($action in $actions) | ||
176 | #set( $actionname = $services.localization.render("${translationPrefix}.actions.${action.name}") ) | ||
177 | [[${actionname}>>path:${action.url}||class="tool ${action.name}" title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]## | ||
178 | #end | ||
179 | $!additionalContent | ||
180 | )))## actions | ||
181 | )))## attachmentbox | ||
182 | #end | ||
183 | |||
184 | #** | ||
185 | * Displays the upload box used for adding and selecting a new attachment. | ||
186 | * | ||
187 | * @param $targetDocument the document with the property being modified | ||
188 | * @param $targetAttachDocument the document to upload the attachment to | ||
189 | * @param $options generic picker options | ||
190 | *# | ||
191 | #macro (attachmentPicker_displayUploadForm $targetDocument, $targetAttachDocument, $options) | ||
192 | #attachmentPicker_displayStartFrame({ | ||
193 | 'value' : $services.localization.render("${translationPrefix}.upload.title"), | ||
194 | 'text' : $services.localization.render("${translationPrefix}.upload.title"), | ||
195 | 'cssClass' : 'gallery_upload' | ||
196 | } $NULL) | ||
197 | {{html clean="false"}} | ||
198 | <form action="$targetAttachDocument.getURL('upload')" enctype="multipart/form-data" method="post" id="uploadAttachment" class="uploadAttachment xform"> | ||
199 | <div class="gallery_upload_input"> | ||
200 | #if (${options.rawfilter} != '') | ||
201 | <span class="xHint">$escapetool.xml($services.localization.render("${translationPrefix}.upload.hint", [${options.rawfilter}]))</span> | ||
202 | #end | ||
203 | <input type="file" name="filepath" id="attachfile" class="noitems" title="$!{escapetool.xml($options.rawfilter)}"/> | ||
204 | <input type="hidden" name="xredirect" value="$xwiki.getDocument($attachmentPickerDocName).getURL('get', "xaction=postUpload&docAction=$!{escapetool.url($options.get('docAction'))}&targetdocname=$!{escapetool.url($targetAttachDocument.fullName)}&docname=$!{escapetool.url($targetDocument.fullName)}&fieldname=$!{escapetool.url($options.get('classname'))}_$!{escapetool.url($options.get('object'))}_$!{escapetool.url($options.get('property'))}&form_token=$!{services.csrf.getToken()}")" /> | ||
205 | <input type="hidden" name="docname" value="$!{escapetool.xml($targetDocument.fullName)}" /> | ||
206 | <input type="hidden" name="classname" value="$!{escapetool.xml($options.get('classname'))}" /> | ||
207 | <input type="hidden" name="object" value="$!{escapetool.xml($options.get('object'))}" /> | ||
208 | <input type="hidden" name="property" value="$!{escapetool.xml($options.get('property'))}" /> | ||
209 | <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" /> | ||
210 | </div> | ||
211 | #if ("$!currentValue" != '' && $currentValue != $options.defaultValue) | ||
212 | <div> | ||
213 | <label> | ||
214 | <input type="checkbox" name="filename" value="$!escapetool.xml($currentValue)" | ||
215 | />$services.localization.render('attachmentSelector.replace', | ||
216 | ["<strong>$!escapetool.xml($currentValue)</strong>"]) | ||
217 | </label> | ||
218 | <span class="xHint">$escapetool.xml($services.localization.render('attachmentSelector.replace.hint'))</span> | ||
219 | </div> | ||
220 | #end | ||
221 | #if ($xwiki.hasEditComment() && $options.versionSummary) | ||
222 | <div> | ||
223 | #if ($xwiki.isEditCommentFieldHidden()) | ||
224 | <input type="hidden" name="comment" value="$!escapetool.xml($request.comment)" /> | ||
225 | #else | ||
226 | <label for="commentinput">$services.localization.render('core.comment')</label> | ||
227 | <input type="text" name="comment" id="commentinput" value="$!escapetool.xml($request.comment)" | ||
228 | title="$services.localization.render('core.comment.tooltip')" /> | ||
229 | #end | ||
230 | </div> | ||
231 | #end | ||
232 | <div class="buttons"> | ||
233 | <span class="buttonwrapper"> | ||
234 | <input type="submit" name="action_upload" class="button " value='$services.localization.render("${translationPrefix}.upload.submit")' title='$services.localization.render("${translationPrefix}.upload.submit")'/> | ||
235 | </span> | ||
236 | </div> | ||
237 | </form> | ||
238 | {{/html}} | ||
239 | #attachmentPicker_displayEndFrame ([]) | ||
240 | #end | ||
241 | |||
242 | #** | ||
243 | * Displays the "empty value" box, used for unsetting the field value. | ||
244 | * | ||
245 | * @param $targetDocument the document being modified | ||
246 | * @param $targetAttachDocument the document that the attachments will the loaded from/saved to | ||
247 | * @param $options generic picker options | ||
248 | * @param $currentValue the currently selected file, used for determining if the empty box should be highlighted as the current value | ||
249 | *# | ||
250 | #macro (attachmentPicker_displayAttachmentGalleryEmptyValue $targetDocument, $targetAttachDocument, $options, $currentValue) | ||
251 | #if ("$!{options.get('defaultValue')}" != '') | ||
252 | #set ($reference = ${options.get('defaultValue')}) | ||
253 | #set ($docNameLimit = $reference.indexOf('@')) | ||
254 | #if ($docNameLimit > 0) | ||
255 | #set ($docName = $reference.substring(0, $docNameLimit)) | ||
256 | #else | ||
257 | #set ($docName = $targetAttachDocument.fullName) | ||
258 | #end | ||
259 | #set ($attachmentName = $reference.substring($mathtool.add($docNameLimit, 1))) | ||
260 | #set ($defaultAttachment = $xwiki.getDocument($docName).getAttachment($attachmentName)) | ||
261 | #if ($defaultAttachment.isImage()) | ||
262 | #set($dcssClass = 'gallery_image') | ||
263 | #end | ||
264 | #end | ||
265 | #attachmentPicker_displayStartFrame({'cssClass' : "gallery_emptyChoice $!{dcssClass}", 'text' : $services.localization.render("${translationPrefix}.default"), 'value' : "${options.defaultValue}"} $currentValue) | ||
266 | #attachmentPicker_displayAttachmentDetails($defaultAttachment $options) | ||
267 | #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString))) | ||
268 | #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, "${options.get('classname')}_${options.get('object')}_${options.get('property')}=&form_token=$!{services.csrf.getToken()}")) | ||
269 | #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}]) | ||
270 | #end | ||
271 | {{/velocity}} | ||
272 | |||
273 | {{velocity}} | ||
274 | #if ($request.docname) | ||
275 | #set ($targetDocument = $xwiki.getDocument($request.docname)) | ||
276 | #if ($request.targetdocname) | ||
277 | ## Use the target document if it exists. | ||
278 | #set ($targetAttachDocument = $xwiki.getDocument($request.targetdocname)) | ||
279 | #else | ||
280 | ## Otherwise, just use the current document as the target to save/load attachments | ||
281 | #set ($targetAttachDocument = $targetDocument) | ||
282 | #end | ||
283 | #if ("$!{request.savemode}" == 'direct') | ||
284 | #set($docAction = 'save') | ||
285 | #else | ||
286 | #set($docAction = $targetAttachDocument.getDefaultEditMode()) | ||
287 | #end | ||
288 | #set ($filter = []) | ||
289 | #set ($rawfilter = '') | ||
290 | #if ("$!{request.filter}" != '') | ||
291 | #foreach ($value in $request.filter.trim().split('\s*+[,|; ]\s*+')) | ||
292 | #if ("$!value" != '') | ||
293 | #set ($discard = $filter.add($value.toLowerCase())) | ||
294 | #set ($rawfilter = "${rawfilter}, ${value}") | ||
295 | #end | ||
296 | #end | ||
297 | #if ($rawfilter != '') | ||
298 | #set ($rawfilter = $rawfilter.substring(2)) | ||
299 | #end | ||
300 | #end | ||
301 | #if ("$!{request.displayImage}" == 'true') | ||
302 | #set ($displayImage = true) | ||
303 | #else | ||
304 | #set ($displayImage = false) | ||
305 | #end | ||
306 | ### Determine attachment sorting | ||
307 | #set($sortAttachmentsBy = "$!{request.sortAttachmentsBy}") | ||
308 | #set ($validAttachmentProperties = ['filename', 'date', 'filesize', 'author', 'version', 'mimeType']) | ||
309 | #if($sortAttachmentsBy == '' || $validAttachmentProperties.indexOf($sortAttachmentsBy) == -1) | ||
310 | ### Default to sorting by filename, sort not requested. | ||
311 | #set($sortAttachmentsBy = "filename") | ||
312 | #end | ||
313 | ### Set attachment sorting direction | ||
314 | #if($sortAttachmentsBy == 'date') | ||
315 | ### Sort the date descending | ||
316 | #set($sortAttachmentsBy = "date:desc") | ||
317 | #else | ||
318 | ### Sort everything else ascending | ||
319 | #set($sortAttachmentsBy = "${sortAttachmentsBy}:asc") | ||
320 | #end | ||
321 | #set ($options = { | ||
322 | 'classname' : ${request.get('classname')}, | ||
323 | 'object' : $!{numbertool.toNumber($request.object).intValue()}, | ||
324 | 'property' : ${request.property}, | ||
325 | 'displayImage' : ${displayImage}, | ||
326 | 'docAction' : ${docAction}, | ||
327 | 'defaultValue' : "$!{request.defaultValue}", | ||
328 | 'rawfilter': "$!{rawfilter}", | ||
329 | 'filter': ${filter}, | ||
330 | 'sortAttachmentsBy': ${sortAttachmentsBy}, | ||
331 | 'versionSummary': $request.versionSummary.equals('true') | ||
332 | }) | ||
333 | $!targetDocument.use($targetDocument.getObject($options.classname, $options.object))## | ||
334 | #attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options) | ||
335 | |||
336 | #set ($cancelLinkName = $services.rendering.escape($services.rendering.escape($services.localization.render("${translationPrefix}.cancel"), 'xwiki/2.1'), 'xwiki/2.1')) | ||
337 | #set ($cancelLinkTarget = $services.rendering.escape($services.model.serialize($targetDocument), 'xwiki/2.1')) | ||
338 | (% class="gallery_buttons buttons" %)((( | ||
339 | (% class="buttonwrapper secondary" %)[[$cancelLinkName>>$cancelLinkTarget||class="button secondary" id="attachment-picker-close"]] | ||
340 | ))) | ||
341 | #end | ||
342 | {{/velocity}} |