Show last authors
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 #if ($xwiki.hasAccessLevel('edit',$xcontext.user,${targetAttachDocument.fullName}))
49 #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
50 #end
51 #attachmentPicker_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue)
52 #set ($sortedAttachments = $collectiontool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") )
53 #foreach ($attachment in $sortedAttachments)
54 #set ($extension = $attachment.getFilename())
55 #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase())
56 #if ($options.filter.size() == 0 || $options.filter.contains($extension))
57 #attachmentPicker_displayAttachmentBox($attachment $targetDocument $targetAttachDocument, $options $currentValue)
58 #end
59 #end
60 )))
61 #end
62
63 #**
64 * Displays an attachment box.
65 *
66 * @param $attachment the target attachment to display
67 * @param $targetDocument the document being modified
68 * @param $options generic picker options
69 * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value
70 *#
71 #macro (attachmentPicker_displayAttachmentBox $attachment $targetDocument $targetAttachDocument, $options $currentValue)
72 #if ($options.displayImage && $attachment.isImage())
73 #set ($cssClass = 'gallery_image')
74 #else
75 #set ($cssClass = '')
76 #end
77 #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "$!{cssClass}"} $currentValue)
78 #attachmentPicker_displayAttachmentDetails($attachment $options)
79 #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString)))
80 #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") )
81 #set ($viewURL = $targetAttachDocument.getAttachmentURL($attachment.filename) )##{'name' : 'download', 'url' : $viewURL, 'rel' : '__blank'}
82 #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, $escapetool.url({
83 "${options.get('classname')}_${options.get('object')}_${options.get('property')}": ${attachment.filename},
84 'form_token': $!{services.csrf.getToken()}
85 })))
86 #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}, {'name' : 'delete', 'url' : $deleteURL}])
87 #end
88
89 #**
90 * Writes the wiki code used at the start of an attachment box. Outputs the attachment title bar, and opens the inner frame div.
91 *
92 * @param $boxOptions a map of parameters/options for the current attachment, holding, for example, the attachment name (boxOptions.value),
93 * the title to display (boxOptions.text), optional extra CSS classnames to put on the box (boxOptions.cssClass)
94 * @param $currentValue the currently selected file, used for determining if this attachment should be highlighted as the current value
95 *#
96 #macro (attachmentPicker_displayStartFrame $boxOptions $currentValue)
97 (% class="gallery_attachmentbox $!{boxOptions.cssClass} #if ("$!{boxOptions.value}" == $currentValue) current#{end}" %)(((
98 (% class="gallery_attachmenttitle" title="$services.rendering.escape($!{boxOptions.value}, 'xwiki/2.1')" %)(((
99 $services.rendering.escape($boxOptions.text, 'xwiki/2.1')
100 )))
101 (% class="gallery_attachmentframe" %)(((
102 #end
103
104 #**
105 * Displays details about an attachment inside the attachment box. If the attachment is an image and the "displayImage" option is on,
106 * then the image is displayed. Otherwise, some basic information is displayed: the version, the size, the date and the author.
107 *
108 * @param $attachment the target attachment to display
109 * @param $options generic picker options
110 *#
111 #macro (attachmentPicker_displayAttachmentDetails $attachment $options)
112 #if ($attachment)
113 ## Compute the attachment reference because there's no getter.
114 #set ($attachmentReference = $services.model.createAttachmentReference($attachment.document.documentReference,
115 $attachment.filename))
116 #set ($attachmentStringReference = $services.rendering.escape($services.model.serialize($attachmentReference, 'default'), 'xwiki/2.1'))
117 #if ($attachment.isImage() && $options.displayImage)
118 ## We add the version to the query string in order to invalidate the cache when an image attachment is replaced.
119 #set ($queryString = $escapetool.url({'version': $attachment.version}))
120 [[[[image:${attachmentStringReference}||width=180 queryString="$queryString"]]>>attach:$attachmentStringReference]]
121 #else
122 * (% 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')(% %)
123 * v$attachment.getVersion() (#dynamicsize($attachment.longSize))
124 * $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')}])
125 * (% class="buttonwrapper" %)[[${services.localization.render("${translationPrefix}.actions.download")}>>attach:${attachmentStringReference}||title="$services.localization.render("${translationPrefix}.actions.download")" rel="__blank" class="button"]](%%)
126 #end
127 #end
128 #end
129
130 #**
131 * Writes the wiki code used at the end of an attachment box. Closes the inner frame div, and outputs the attachment actions.
132 *
133 * @param $actions a list of maps defining action buttons, where each entry contains a subset of the following:
134 * <dl>
135 * <dt>name</dt>
136 * <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>
137 * <dt>url</dt>
138 * <dd>the destination of the button</dd>
139 * <dt>rel</dt>
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 * </dl>
142 *#
143 #macro (attachmentPicker_displayEndFrame $actions)
144 )))## attachmentframe
145 (% class="gallery_actions" %)(((
146 #foreach ($action in $actions)
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]]##
149 #end
150 )))## actions
151 )))## attachmentbox
152 #end
153
154 #**
155 * Displays the upload box used for adding and selecting a new attachment.
156 *
157 * @param $targetDocument the document with the property being modified
158 * @param $targetAttachDocument the document to upload the attachment to
159 * @param $options generic picker options
160 *#
161 #macro (attachmentPicker_displayUploadForm $targetDocument, $targetAttachDocument, $options)
162 #attachmentPicker_displayStartFrame({
163 'value' : $services.localization.render("${translationPrefix}.upload.title"),
164 'text' : $services.localization.render("${translationPrefix}.upload.title"),
165 'cssClass' : 'gallery_upload'
166 } $NULL)
167 {{html clean="false"}}
168 <form action="$targetAttachDocument.getURL('upload')" enctype="multipart/form-data" method="post" id="uploadAttachment" class="uploadAttachment xform">
169 <div class="gallery_upload_input">
170 #if (${options.rawfilter} != '')
171 <span class="xHint">$escapetool.xml($services.localization.render("${translationPrefix}.upload.hint", [${options.rawfilter}]))</span>
172 #end
173 <input type="file" name="filepath" id="attachfile" class="noitems" title="$!{escapetool.xml($options.rawfilter)}"/>
174 <input type="hidden" name="xredirect" value="$xwiki.getDocument($attachmentPickerDocName).getURL('get', "xaction=postUpload&amp;docAction=$!{escapetool.url($options.get('docAction'))}&amp;targetdocname=$!{escapetool.url($targetAttachDocument.fullName)}&amp;docname=$!{escapetool.url($targetDocument.fullName)}&amp;fieldname=$!{escapetool.url($options.get('classname'))}_$!{escapetool.url($options.get('object'))}_$!{escapetool.url($options.get('property'))}&amp;form_token=$!{services.csrf.getToken()}")" />
175 <input type="hidden" name="docname" value="$!{escapetool.xml($targetDocument.fullName)}" />
176 <input type="hidden" name="classname" value="$!{escapetool.xml($options.get('classname'))}" />
177 <input type="hidden" name="object" value="$!{escapetool.xml($options.get('object'))}" />
178 <input type="hidden" name="property" value="$!{escapetool.xml($options.get('property'))}" />
179 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
180 </div>
181 #if ("$!currentValue" != '' && $currentValue != $options.defaultValue)
182 <div>
183 <label>
184 <input type="checkbox" name="filename" value="$!escapetool.xml($currentValue)"
185 />$services.localization.render('attachmentSelector.replace',
186 ["<strong>$!escapetool.xml($currentValue)</strong>"])
187 </label>
188 <span class="xHint">$escapetool.xml($services.localization.render('attachmentSelector.replace.hint'))</span>
189 </div>
190 #end
191 #if ($xwiki.hasEditComment() && $options.versionSummary)
192 <div>
193 #if ($xwiki.isEditCommentFieldHidden())
194 <input type="hidden" name="comment" value="$!escapetool.xml($request.comment)" />
195 #else
196 <label for="commentinput">$services.localization.render('core.comment')</label>
197 <input type="text" name="comment" id="commentinput" value="$!escapetool.xml($request.comment)"
198 title="$services.localization.render('core.comment.tooltip')" />
199 #end
200 </div>
201 #end
202 <div class="buttons">
203 <span class="buttonwrapper">
204 <input type="submit" name="action_upload" class="button " value='$services.localization.render("${translationPrefix}.upload.submit")' title='$services.localization.render("${translationPrefix}.upload.submit")'/>
205 </span>
206 </div>
207 </form>
208 {{/html}}
209 #attachmentPicker_displayEndFrame ([])
210 #end
211
212 #**
213 * Displays the "empty value" box, used for unsetting the field value.
214 *
215 * @param $targetDocument the document being modified
216 * @param $targetAttachDocument the document that the attachments will the loaded from/saved to
217 * @param $options generic picker options
218 * @param $currentValue the currently selected file, used for determining if the empty box should be highlighted as the current value
219 *#
220 #macro (attachmentPicker_displayAttachmentGalleryEmptyValue $targetDocument, $targetAttachDocument, $options, $currentValue)
221 #if ("$!{options.get('defaultValue')}" != '')
222 #set ($reference = ${options.get('defaultValue')})
223 #set ($docNameLimit = $reference.indexOf('@'))
224 #if ($docNameLimit > 0)
225 #set ($docName = $reference.substring(0, $docNameLimit))
226 #else
227 #set ($docName = $targetAttachDocument.fullName)
228 #end
229 #set ($attachmentName = $reference.substring($mathtool.add($docNameLimit, 1)))
230 #set ($defaultAttachment = $xwiki.getDocument($docName).getAttachment($attachmentName))
231 #if ($defaultAttachment.isImage())
232 #set($dcssClass = 'gallery_image')
233 #end
234 #end
235 #attachmentPicker_displayStartFrame({'cssClass' : "gallery_emptyChoice $!{dcssClass}", 'text' : $services.localization.render("${translationPrefix}.default"), 'value' : "${options.defaultValue}"} $currentValue)
236 #attachmentPicker_displayAttachmentDetails($defaultAttachment $options)
237 #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString)))
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}])
240 #end
241 {{/velocity}}
242
243 {{velocity}}
244 #if ($request.docname)
245 #set ($targetDocument = $xwiki.getDocument($request.docname))
246 #if ($request.targetdocname)
247 ## Use the target document if it exists.
248 #set ($targetAttachDocument = $xwiki.getDocument($request.targetdocname))
249 #else
250 ## Otherwise, just use the current document as the target to save/load attachments
251 #set ($targetAttachDocument = $targetDocument)
252 #end
253 #if ("$!{request.savemode}" == 'direct')
254 #set($docAction = 'save')
255 #else
256 #set($docAction = $targetAttachDocument.getDefaultEditMode())
257 #end
258 #set ($filter = [])
259 #set ($rawfilter = '')
260 #if ("$!{request.filter}" != '')
261 #foreach ($value in $request.filter.trim().split('\s*+[,|; ]\s*+'))
262 #if ("$!value" != '')
263 #set ($discard = $filter.add($value.toLowerCase()))
264 #set ($rawfilter = "${rawfilter}, ${value}")
265 #end
266 #end
267 #if ($rawfilter != '')
268 #set ($rawfilter = $rawfilter.substring(2))
269 #end
270 #end
271 #if ("$!{request.displayImage}" == 'true')
272 #set ($displayImage = true)
273 #else
274 #set ($displayImage = false)
275 #end
276 ### Determine attachment sorting
277 #set($sortAttachmentsBy = "$!{request.sortAttachmentsBy}")
278 #set ($validAttachmentProperties = ['filename', 'date', 'filesize', 'author', 'version', 'mimeType'])
279 #if($sortAttachmentsBy == '' || $validAttachmentProperties.indexOf($sortAttachmentsBy) == -1)
280 ### Default to sorting by filename, sort not requested.
281 #set($sortAttachmentsBy = "filename")
282 #end
283 ### Set attachment sorting direction
284 #if($sortAttachmentsBy == 'date')
285 ### Sort the date descending
286 #set($sortAttachmentsBy = "date:desc")
287 #else
288 ### Sort everything else ascending
289 #set($sortAttachmentsBy = "${sortAttachmentsBy}:asc")
290 #end
291 #set ($options = {
292 'classname' : ${request.get('classname')},
293 'object' : $!{numbertool.toNumber($request.object).intValue()},
294 'property' : ${request.property},
295 'displayImage' : ${displayImage},
296 'docAction' : ${docAction},
297 'defaultValue' : "$!{request.defaultValue}",
298 'rawfilter': "$!{rawfilter}",
299 'filter': ${filter},
300 'sortAttachmentsBy': ${sortAttachmentsBy},
301 'versionSummary': $request.versionSummary.equals('true')
302 })
303 $!targetDocument.use($targetDocument.getObject($options.classname, $options.object))##
304 #attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options)
305
306 (% class="gallery_buttons buttons" %)(((
307 (% class="buttonwrapper secondary" %)[[$services.localization.render("${translationPrefix}.cancel")>>${targetDocument}||class="button secondary" id="attachment-picker-close"]]
308 )))
309 #end
310 {{/velocity}}

Tips

You can click on the arrows next to the breadcrumb elements to quickly navigate to sibling and children pages.

Need help?

If you need help with XWiki you can contact: