# Wiki source code of LiveTableEditSheet

Last modified by Richard Johnson on 2021/05/08 19:21
Export
Office Formats
Export as PDF
Other Formats
Export as HTML

Show last authors

author | version | line-number | content
--- | --- | --- | ---
|  | 1 | {{include reference="XWiki.TemplateProviderMacros" /}}
|  | 2 |
|  | 3 | {{include reference="AppWithinMinutes.VelocityMacros" /}}
|  | 4 |
|  | 5 | {{velocity output="false"}}
|  | 6 | #macro (listAvailableColumns $classReference)
|  | 7 | <select id="availableColumns">
|  | 8 | #set ($classFields = $xwiki.getDocument($classReference).getxWikiClass().properties)
|  | 9 | #if ($classFields.size() > 0)
|  | 10 | <optgroup label="$escapetool.xml($services.localization.render(
|  | 11 | 'platform.appwithinminutes.liveTableEditorClassFieldColumnGroupLabel'))" id="classFields">
|  | 12 | #foreach ($field in $classFields)
|  | 13 | <option value="$field.name">$escapetool.xml($field.translatedPrettyName)</option>
|  | 14 | #end
|  | 15 | </optgroup>
|  | 16 | #end
|  | 17 | <optgroup label="$escapetool.xml($services.localization.render(
|  | 18 | 'platform.appwithinminutes.liveTableEditorGenericColumnGroupLabel'))">
|  | 19 | #foreach ($entry in $genericColumns.entrySet())
|  | 20 | <option value="$entry.key" title="$escapetool.xml($entry.value.get(1))">
|  | 21 | $escapetool.xml($entry.value.get(0))
|  | 22 | </option>
|  | 23 | #end
|  | 24 | </optgroup>
|  | 25 | </select>
|  | 26 | <a href="#addColumn" class="addColumn" title="$services.localization.render(
|  | 27 | 'platform.appwithinminutes.liveTableEditorAddColumnHint')">$services.icon.renderHTML('add')</a>
|  | 28 | #end
|  | 29 |
|  | 30 | #macro (displayHelpPanel)
|  | 31 | #set ($genericColumns = {
|  | 32 | 'doc.title': [
|  | 33 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocTitleColumnName'),
|  | 34 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocTitleColumnDescription')
|  | 35 | ],
|  | 36 | 'doc.name': [
|  | 37 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocNameColumnName'),
|  | 38 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocNameColumnDescription')
|  | 39 | ],
|  | 40 | 'doc.location': [
|  | 41 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocLocationColumnName'),
|  | 42 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocLocationColumnDescription')
|  | 43 | ],
|  | 44 | 'doc.author': [
|  | 45 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocAuthorColumnName'),
|  | 46 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocAuthorColumnDescription')
|  | 47 | ],
|  | 48 | 'doc.creator': [
|  | 49 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocCreatorColumnName'),
|  | 50 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocCreatorColumnDescription')
|  | 51 | ],
|  | 52 | 'doc.date': [
|  | 53 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocDateColumnName'),
|  | 54 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocDateColumnDescription')
|  | 55 | ],
|  | 56 | 'doc.creationDate': [
|  | 57 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocCreationDateColumnName'),
|  | 58 | $services.localization.render('platform.appwithinminutes.liveTableEditorDocCreationDateColumnDescription')
|  | 59 | ],
|  | 60 | '_actions': [
|  | 61 | $services.localization.render('platform.appwithinminutes.liveTableEditorActionsColumnName'),
|  | 62 | $services.localization.render('platform.appwithinminutes.liveTableEditorActionsColumnDescription')
|  | 63 | ],
|  | 64 | '_attachments': [
|  | 65 | $services.localization.render('platform.appwithinminutes.liveTableEditorAttachmentsColumnName'),
|  | 66 | $services.localization.render('platform.appwithinminutes.liveTableEditorAttachmentsColumnDescription')
|  | 67 | ],
|  | 68 | '_images': [
|  | 69 | $services.localization.render('platform.appwithinminutes.liveTableEditorImagesColumnName'),
|  | 70 | $services.localization.render('platform.appwithinminutes.liveTableEditorImagesColumnDescription')
|  | 71 | ]
|  | 72 | })
|  | 73 | <div class="wizard-help">
|  | 74 | <p>
|  | 75 | <strong>$services.localization.render('platform.appwithinminutes.liveTableEditorHelpTitle')</strong>
|  | 76 | $services.localization.render('platform.appwithinminutes.liveTableEditorHelpDescription')
|  | 77 | </p>
|  | 78 | <dl>
|  | 79 | #foreach ($columnId in ['doc.title', 'doc.location', 'doc.date', 'doc.author', '_actions'])
|  | 80 | <dt>$genericColumns.get($columnId).get(0)</dt>
|  | 81 | <dd>$genericColumns.get($columnId).get(1)</dd>
|  | 82 | #end
|  | 83 | </dl>
|  | 84 | </div>
|  | 85 | #end
|  | 86 |
|  | 87 | #macro (displayFormFields)
|  | 88 | <div class="hidden">
|  | 89 | ## Make sure that only the sheet content is rendered when the class is saved using AJAX.
|  | 90 | <input type="hidden" name="xpage" value="plain" />
|  | 91 | ## We prevent the class name and the data space from being edited directly. They can be specified in the URL.
|  | 92 | #getAppClassReference($doc)
|  | 93 | <input type="hidden" name="AppWithinMinutes.LiveTableClass_0_class"
|  | 94 | value="$escapetool.xml($services.model.serialize($classReference, 'local'))" />
|  | 95 | #displayPropertyValue('dataSpace', 'hidden')
|  | 96 | ## We have to pass the list of available columns to the JavaScript code.
|  | 97 | #listAvailableColumns($classReference)
|  | 98 | </div>
|  | 99 | <dl>
|  | 100 | <dt>
|  | 101 | <label for="xwikidoctitleinput">$services.localization.render('core.editors.content.titleField.label')</label>
|  | 102 | <span class="xHint">$services.localization.render('platform.appwithinminutes.liveTableEditorTitleHint')</span>
|  | 103 | </dt>
|  | 104 | <dd><input id="xwikidoctitleinput" type="text" name="title" value="$escapetool.xml($doc.title)"/></dd>
|  | 105 | <dt>
|  | 106 | <label for="AppWithinMinutes.LiveTableClass_0_description">
|  | 107 | $doc.displayPrettyName('description', false, false)
|  | 108 | </label>
|  | 109 | <span class="xHint">
|  | 110 | $services.localization.render('platform.appwithinminutes.liveTableEditorDescriptionHint')
|  | 111 | </span>
|  | 112 | </dt>
|  | 113 | <dd>#displayPropertyValue('description')</dd>
|  | 114 | <dt>
|  | 115 | <label for="AppWithinMinutes.LiveTableClass_0_columns">$doc.displayPrettyName('columns', false, false)</label>
|  | 116 | <span class="xHint">$services.localization.render('platform.appwithinminutes.liveTableEditorColumnsHint')</span>
|  | 117 | </dt>
|  | 118 | <dd>#displayPropertyValue('columns')</dd>
|  | 119 | </dl>
|  | 120 | #end
|  | 121 |
|  | 122 | #macro (getApplicationIcon $classReference)
|  | 123 | #set ($applicationIcon = '')
|  | 124 | ## Look for the corresponding UI extension.
|  | 125 | #set ($uixPointId = 'org.xwiki.platform.panels.Applications')
|  | 126 | #set ($uixObject = $doc.getObject('XWiki.UIExtensionClass', 'extensionPointId', $uixPointId))
|  | 127 | #set ($uixId = $uixObject.getValue('name'))
|  | 128 | #foreach ($uix in $services.uix.getExtensions($uixPointId))
|  | 129 | #if ($uix.id == $uixId)
|  | 130 | #set ($applicationIcon = $uix.parameters.icon)
|  | 131 | #end
|  | 132 | #end
|  | 133 | #if ("$!applicationIcon" == '')
|  | 134 | ## Fallback on the entry icon.
|  | 135 | #set ($templateProviderReference = $services.model.createDocumentReference(
|  | 136 | "$stringtool.removeEnd($classReference.name, 'Class')TemplateProvider",
|  | 137 | $classReference.parent
|  | 138 | ))
|  | 139 | #set ($entryIcon = $xwiki.getDocument($templateProviderReference).getValue('icon'))
|  | 140 | #if ("$!entryIcon" != '')
|  | 141 | #set ($applicationIcon = "icon:$entryIcon")
|  | 142 | #else
|  | 143 | #set ($applicationIcon = 'icon:application')
|  | 144 | #end
|  | 145 | #end
|  | 146 | #end
|  | 147 |
|  | 148 | #macro (displayIcon)
|  | 149 | #if ($services.uix)
|  | 150 | #getApplicationIcon($classReference)
|  | 151 | <dl>
|  | 152 | <dt>
|  | 153 | <label for="applicationIcon">
|  | 154 | $services.localization.render('platform.appwithinminutes.liveTableEditorIcon')
|  | 155 | </label>
|  | 156 | <span class="xHint">
|  | 157 | $services.localization.render('platform.appwithinminutes.liveTableEditorIconHintWithPicker',
|  | 158 | [$xwiki.getSkinFile('icons/silk/index_abc.png')])
|  | 159 | </span>
|  | 160 | </dt>
|  | 161 | <dd>
|  | 162 | <input id="applicationIcon" name="applicationIcon" type="text" size="10"
|  | 163 | value="$!escapetool.xml($applicationIcon)" />
|  | 164 | </dd>
|  | 165 | </dl>
|  | 166 | #end
|  | 167 | #end
|  | 168 |
|  | 169 | #macro (doEdit)
|  | 170 | {{html clean="false"}}
|  | 171 | #set ($liveTableObj = $doc.getObject('AppWithinMinutes.LiveTableClass', true))
|  | 172 | #set ($discard = $doc.use($liveTableObj))
|  | 173 | #set ($discard = $xwiki.jsfx.use('js/scriptaculous/effects.js'))
|  | 174 | #set ($discard = $xwiki.jsfx.use('js/scriptaculous/dragdrop.js'))
|  | 175 | #set ($discard = $xwiki.ssx.use('AppWithinMinutes.LiveTableEditSheet'))
|  | 176 | #set ($discard = $xwiki.jsx.use('AppWithinMinutes.LiveTableEditSheet'))
|  | 177 | #if ("$!request.wizard" == 'true')
|  | 178 | #appWizardHeader('presentation')
|  | 179 | #end
|  | 180 | #displayHelpPanel()
|  | 181 | <div class="form-body">
|  | 182 | #displayFormFields()
|  | 183 | #displayIcon()
|  | 184 | #if ("$!request.wizard" == 'true')
|  | 185 | #appWizardFooter('presentation')
|  | 186 | #end
|  | 187 | </div>
|  | 188 | <div class="clearfloats"></div>
|  | 189 | {{/html}}
|  | 190 |
|  | 191 | {{iconPicker id="applicationIcon" prefix="icon:" /}}
|  | 192 | #end
|  | 193 |
|  | 194 | #macro (maybeGrantSpaceAdminRight $spaceRef)
|  | 195 | ## Grant space administration rights only if the space is new. Don't overwrite existing space preferences.
|  | 196 | #set ($spaceHomeRef = $services.model.resolveDocument('', 'default', $spaceRef))
|  | 197 | #set ($spacePrefsRef = $services.model.resolveDocument('WebPreferences', 'explicit', $spaceRef))
|  | 198 | #if (!$xwiki.exists($spaceHomeRef) && !$xwiki.exists($spacePrefsRef))
|  | 199 | #set ($spacePrefsDoc = $xwiki.getDocument($spacePrefsRef))
|  | 200 | #set ($discard = $spacePrefsDoc.use($spacePrefsDoc.getObject('XWiki.XWikiGlobalRights', true)))
|  | 201 | #set ($discard = $spacePrefsDoc.set('allow', 1))
|  | 202 | #set ($discard = $spacePrefsDoc.set('levels', 'admin'))
|  | 203 | #set ($discard = $spacePrefsDoc.set('users', $services.model.serialize($xcontext.userReference, 'default')))
|  | 204 | #set ($discard = $spacePrefsDoc.setTitle('$services.localization.render(''admin.preferences.title'')'))
|  | 205 | #set ($discard = $spacePrefsDoc.setParent($services.model.serialize($spaceHomeRef, 'default')))
|  | 206 | #set ($discard = $spacePrefsDoc.setHidden(true))
|  | 207 | #set ($discard = $spacePrefsDoc.saveWithProgrammingRights($services.localization.render(
|  | 208 | 'platform.appwithinminutes.grantSpaceAdminRightsSaveComment')))
|  | 209 | #end
|  | 210 | #end
|  | 211 |
|  | 212 | #macro (maybeGrantSpaceAdminRights)
|  | 213 | ## Application space
|  | 214 | #set ($appReference = $doc.documentReference.parent)
|  | 215 | #maybeGrantSpaceAdminRight($appReference)
|  | 216 | ## Code space (if it's not nested inside the application space)
|  | 217 | #set ($className = $request.get('AppWithinMinutes.LiveTableClass_0_class'))
|  | 218 | #set ($classReference = $services.model.resolveDocument($className))
|  | 219 | #if (!$classReference.hasParent($appReference))
|  | 220 | #maybeGrantSpaceAdminRight($classReference.parent)
|  | 221 | #end
|  | 222 | #end
|  | 223 |
|  | 224 | #macro (updateAndSaveLiveTable)
|  | 225 | #set ($discard = $doc.updateObjectFromRequest('AppWithinMinutes.LiveTableClass'))
|  | 226 | #set ($liveTableGeneratorDoc = $xwiki.getDocument('AppWithinMinutes.LiveTableGenerator'))
|  | 227 |
|  | 228 | ## Generate the LiveTable by displaying the LiveTableGenerator document in the context of the current document.
|  | 229 | #set ($displayParameters = $services.display.createDocumentDisplayerParameters())
|  | 230 | #set ($discard = $displayParameters.setExecutionContextIsolated(false))
|  | 231 | #set ($discard = $displayParameters.setContentTranslated(true))
|  | 232 | #set ($generatedLiveTableContent = $services.display.content($liveTableGeneratorDoc, {
|  | 233 | 'outputSyntaxId': 'plain/1.0',
|  | 234 | 'displayerParameters': $displayParameters
|  | 235 | }))
|  | 236 |
|  | 237 | ## Use the generated LiveTable content for the data home page.
|  | 238 | #set ($dataSpaceReference = $services.model.resolveSpace($doc.getValue('dataSpace')))
|  | 239 | #set ($dataSpaceHomeReference = $services.model.resolveDocument('', 'default', $dataSpaceReference))
|  | 240 | #if ($dataSpaceHomeReference.equals($doc.documentReference) || !$xwiki.exists($dataSpaceHomeReference))
|  | 241 | ## Either the application space and the data space are one and the same or this is a new application and we don't
|  | 242 | ## want to promote the data space anymore.
|  | 243 | #set ($dataHomePage = $doc)
|  | 244 | #else
|  | 245 | ## The application data is stored in a different space.
|  | 246 | #set ($dataHomePage = $xwiki.getDocument($dataSpaceHomeReference))
|  | 247 | #set ($discard = $dataHomePage.setHidden(true))
|  | 248 | #set ($escapedAppName = $doc.documentReference.parent.name.toLowerCase().replace("'", "''"))
|  | 249 | #set ($discard = $dataHomePage.setTitle("${escapetool.d}services.localization.render('${escapedAppName}.dataSpace.title')"))
|  | 250 |
|  | 251 | ## Update the home page content.
|  | 252 | #set ($homePageContent = '')
|  | 253 | #if ("$!generatedLiveTableContent" != '')
|  | 254 | ## Include the entries live table in the application home page.
|  | 255 | #set ($escapedReference = $services.model.serialize($dataSpaceHomeReference).replaceAll('([~"])', '~$1'))
|  | 256 | #set ($homePageContent = "{{include reference=""$escapedReference"" /}}")
|  | 257 | #end
|  | 258 | #set ($discard = $doc.setContent($homePageContent))
|  | 259 | #end
|  | 260 | #set ($discard = $dataHomePage.setContent($generatedLiveTableContent))
|  | 261 | ## We assume for now that the output produced by the live table generator uses the same syntax as the code of the live
|  | 262 | ## table generator. We have to set the syntax because the default wiki syntax (used when creating new wiki pages)
|  | 263 | ## could be different than the one used by the live table generator.
|  | 264 | #set ($discard = $dataHomePage.setSyntax($liveTableGeneratorDoc.syntax))
|  | 265 |
|  | 266 | #set ($minorEdit = "$!request.minorEdit" != '')
|  | 267 | #set ($comment = $request.comment)
|  | 268 | #if ("$!comment" == '')
|  | 269 | #set ($comment = $services.localization.render('platform.appwithinminutes.liveTableEditorSaveComment'))
|  | 270 | #end
|  | 271 |
|  | 272 | #if ($dataHomePage != $doc)
|  | 273 | ## Save the data home page.
|  | 274 | #set ($discard = $dataHomePage.save($comment, $minorEdit))
|  | 275 | #end
|  | 276 |
|  | 277 | ## Save the application home page.
|  | 278 | #set ($discard = $doc.save($comment, $minorEdit))
|  | 279 | #end
|  | 280 |
|  | 281 | #macro (updateAndSaveIcon)
|  | 282 | #set ($uix = $doc.getObject('XWiki.UIExtensionClass', true))
|  | 283 | #set ($discard = $uix.set('name', "platform.panels.${doc.space}Application"))
|  | 284 | #set ($discard = $uix.set('extensionPointId', 'org.xwiki.platform.panels.Applications'))
|  | 285 | #set ($uixParams = [
|  | 286 | "label=$doc.plainTitle",
|  | 287 | "target=$doc.fullName",
|  | 288 | "icon=$request.applicationIcon"
|  | 289 | ])
|  | 290 | #set ($discard = $uix.set('parameters', $stringtool.join($uixParams, $util.newline)))
|  | 291 | #set ($hasWikiAdminRights = $services.security.authorization.hasAccess('admin', $doc.documentReference.wikiReference))
|  | 292 | #set ($discard = $uix.set('scope', "#if ($hasWikiAdminRights)wiki#{else}user#end"))
|  | 293 | #set ($discard = $doc.save('Updated application icon', true))
|  | 294 | #end
|  | 295 |
|  | 296 | #macro (doSave)
|  | 297 | #maybeGrantSpaceAdminRights()
|  | 298 | #updateAndSaveLiveTable()
|  | 299 | #updateAndSaveIcon()
|  | 300 | #if ($action == 'save')
|  | 301 | #if ($errorMessage)
|  | 302 | {{html clean="false"}}
|  | 303 | <div class="box errormessage">$errorMessage</div>
|  | 304 | {{/html}}
|  | 305 | #else
|  | 306 | ## Redirect to view mode.
|  | 307 | $response.sendRedirect($doc.getURL())
|  | 308 | #end
|  | 309 | #else
|  | 310 | #if ($errorMessage)
|  | 311 | $response.sendError(400, $errorMessage)
|  | 312 | #else
|  | 313 | $response.setStatus(204)
|  | 314 | #end
|  | 315 | #end
|  | 316 | #end
|  | 317 | {{/velocity}}
|  | 318 |
|  | 319 | {{velocity}}
|  | 320 | #if ("$!request.wizard" == 'true')
|  | 321 | {{include reference="AppWithinMinutes.WizardStep" /}}
|  | 322 | #end
|  | 323 | {{/velocity}}
|  | 324 |
|  | 325 | {{velocity}}
|  | 326 | ## Determine the action button that triggered the request
|  | 327 | #set ($action = $xcontext.action)
|  | 328 | #foreach ($paramName in $request.getParameterMap().keySet())
|  | 329 | #if ($paramName.startsWith('xaction_'))
|  | 330 | #set ($action = $paramName.substring(8))
|  | 331 | #break
|  | 332 | #end
|  | 333 | #end
|  | 334 | #if ($action == 'edit')
|  | 335 | #doEdit()
|  | 336 | #elseif ($action == 'save' || $action == 'saveandcontinue')
|  | 337 | #if ($services.csrf.isTokenValid($request.form_token))
|  | 338 | #doSave()
|  | 339 | #else
|  | 340 | $response.sendRedirect($services.csrf.getResubmissionURL())
|  | 341 | #end
|  | 342 | #end
|  | 343 | {{/velocity}}

# Applications

# Tips

When editing in WYSIWYG, type @ and then start typing letters to get suggestions to mention a user.

# Need help?

If you need help with XWiki you can contact:

- Community Support
- Professional Support

XWiki Debian 13.10.2