Changes for page Main
Last modified by Administrator on 2026/02/17 22:15
From version
9.1
edited by Administrator
on 2026/02/17 22:15
on 2026/02/17 22:15
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/17.10.3]
To version 1.1
edited by Administrator
on 2018/07/24 00:25
on 2018/07/24 00:25
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/9.11.7]
Summary
Details
- Page properties
-
- Title
-
... ... @@ -1,1 +1,1 @@ 1 -#if ("$!appTitle" !='')$appTitle#else$doc.pageReference.name#end1 +#if(!$doc.name.endsWith('Sheet'))$services.localization.render('appWithinMinutes.classEditor.title', [$stringtool.removeEnd($doc.title, 'Class').trim()])#{else}$doc.name#end - Syntax
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki 2. 11 +XWiki 2.0 - Content
-
... ... @@ -1,5 +3,3 @@ 1 -{{include reference="AppWithinMinutes.VelocityMacros" /}} 2 - 3 3 {{groovy}} 4 4 import com.xpn.xwiki.XWikiContext; 5 5 import com.xpn.xwiki.api.Context; ... ... @@ -54,102 +54,95 @@ 54 54 #** 55 55 * Displays the field palette. 56 56 *# 57 -#macro (displayFieldPalette) 58 - <div id="palette"> 59 - <p><strong>$services.localization.render('platform.appwithinminutes.classEditorPaletteTitle')</strong></p> 60 - <p class="xHint">$services.localization.render('platform.appwithinminutes.classEditorPaletteHint')</p> 55 +#macro(displayFieldPalette) 56 + (% id="palette" %) 57 + ((( 58 + **$services.localization.render('platform.appwithinminutes.classEditorPaletteTitle')** 59 + 60 + (% class="xHint" %) 61 + $services.localization.render('platform.appwithinminutes.classEditorPaletteHint') 62 + 61 61 ## List all form field types, grouped by category. 62 - #set ($formFieldDocs = []) 63 - #set ($formFieldClassName = 'AppWithinMinutes.FormFieldClass') 64 - #set ($categoryListStatement = 'from doc.object(AppWithinMinutes.FormFieldCategoryClass) as category order by category.priority') 65 - <ul> 66 - #foreach ($category in $services.query.xwql($categoryListStatement).execute()) 67 - #set ($categoryDoc = $xwiki.getDocument($category)) 68 - <li> 69 - <div class="category">$escapetool.xml($categoryDoc.plainTitle)</div> 70 - #set ($formFieldsForCategoryStatement = "from doc.object($formFieldClassName) as field where field.category = :category order by field.priority") 71 - #set ($formFieldsForCategoryQuery = $services.query.xwql($formFieldsForCategoryStatement).bindValue('category', $category)) 72 - <ul> 73 - #foreach ($formField in $formFieldsForCategoryQuery.execute()) 74 - #set ($formFieldDoc = $xwiki.getDocument($formField)) 75 - #set ($discard = $formFieldDocs.add($formFieldDoc)) 76 - #set ($formFieldIcon = $formFieldDoc.getObject($formFieldClassName).getProperty('icon').value) 77 - #set ($formFieldIconRendered = $services.icon.renderHTML($formFieldIcon)) 78 - #if ("$!formFieldIconRendered" == "") 79 - #if ($formFieldIcon.contains('/')) 80 - #set ($formFieldIconURL = $xwiki.getSkinFile($formFieldIcon)) 81 - #else 82 - #set ($formFieldIconURL = $formFieldDoc.getAttachmentURL($formFieldIcon)) 83 - #end 84 - #set ($formFieldIconRendered = "<img src='$escapetool.xml($formFieldIconURL)' alt='$escapetool.xml($formFieldDoc.plainTitle)' class='icon' />") 64 + #set($formFieldDocs = []) 65 + #set($formFieldClassName = 'AppWithinMinutes.FormFieldClass') 66 + #set($categoryListStatement = 'from doc.object(AppWithinMinutes.FormFieldCategoryClass) as category order by category.priority') 67 + #foreach($category in $services.query.xwql($categoryListStatement).execute()) 68 + #set($categoryDoc = $xwiki.getDocument($category)) 69 + * (% class="category" %)$categoryDoc.plainTitle 70 + #set($formFieldsForCategoryStatement = "from doc.object($formFieldClassName) as field where field.category = :category order by field.priority") 71 + #set($formFieldsForCategoryQuery = $services.query.xwql($formFieldsForCategoryStatement).bindValue('category', $category)) 72 + #foreach($formField in $formFieldsForCategoryQuery.execute()) 73 + #set($formFieldDoc = $xwiki.getDocument($formField)) 74 + #set($discard = $formFieldDocs.add($formFieldDoc)) 75 + #set($formFieldIcon = $formFieldDoc.getObject($formFieldClassName).getProperty('icon').value) 76 + #if($formFieldIcon.contains('/')) 77 + #set($formFieldIconURL = $xwiki.getSkinFile($formFieldIcon)) 78 + #else 79 + #set($formFieldIconURL = $formFieldDoc.getAttachmentURL($formFieldIcon)) 85 85 #end 86 - <li class="field"> 87 - $formFieldIconRendered 88 - $escapetool.xml($formFieldDoc.plainTitle) 89 - ## FIXME: We should use the 'get' action instead to prevent the stats module from recording this AJAX request. 90 - ## The 'edit' action is a temporary solution until the sheet module is modified to allow a sheet to be enforced through 91 - ## the query string even if it doesn't match the action (e.g. the 'get' action). 92 - ## The sheet parameter is required when editing a new class because the request will be made to a document that doesn't exist. 93 - ## FIXME2: In the future don't force the text editor type and instead use the default editor. This means 94 - ## that if the WYSIWYG editor is used, we'll need to convert the HTML into the target syntax so that the 95 - ## Template in #updateAndSaveTemplate is saved with target syntax and not HTML. 96 - ## See https://jira.xwiki.org/browse/XWIKI-13789 97 - #set ($fieldURL = $doc.getURL('edit', $escapetool.url({ 98 - 'xpage': 'plain', 99 - 'sheet': 'AppWithinMinutes.ClassEditSheet', 100 - 'form_token': $services.csrf.getToken(), 101 - 'template': 'AppWithinMinutes.ClassTemplate', 102 - 'field': $formFieldDoc.fullName, 103 - 'xeditmode': 'text' 104 - }))) 105 - <input type="hidden" value="$escapetool.xml($fieldURL)" class="data"/> 106 - </li> 81 + ** (% class="field" %){{html}} 82 + <img src="$formFieldIconURL" alt="$escapetool.xml($formFieldDoc.plainTitle)" class="icon" /> 83 + $escapetool.xml($formFieldDoc.plainTitle) 84 + ## FIXME: We should use the 'get' action instead to prevent the stats module from recording this AJAX request. 85 + ## The 'edit' action is a temporary solution until the sheet module is modified to allow a sheet to be enforced through 86 + ## the query string even if it doesn't match the action (e.g. the 'get' action). 87 + ## The sheet parameter is required when editing a new class because the request will be made to a document that doesn't exist. 88 + ## FIXME2: In the future don't force the text editor type and instead use the default editor. This means 89 + ## that if the WYSIWYG editor is used, we'll need to convert the HTML into the target syntax so that the 90 + ## Template in #updateAndSaveTemplate is saved with target syntax and not HTML. 91 + ## See https://jira.xwiki.org/browse/XWIKI-13789 92 + <input type="hidden" value="$doc.getURL('edit', "xpage=plain&sheet=AppWithinMinutes.ClassEditSheet&field=$escapetool.url($formFieldDoc.fullName)&xeditmode=text")" class="data"/> 93 + {{/html}} 107 107 #end 108 - </ul> 109 - </li> 110 110 #end 111 - </ul> 112 - </div> 96 + ))) 113 113 #end 114 114 115 115 #** 116 116 * Displays the field canvas. 117 117 *# 118 -#macro (displayFieldCanvas)119 - #set ($propertyType2FormField = {})120 - #foreach ($formFieldDoc in $formFieldDocs)102 +#macro(displayFieldCanvas) 103 + #set($propertyType2FormField = {}) 104 + #foreach($formFieldDoc in $formFieldDocs) 121 121 ## Use the type of the field template. 122 - #set ($type = $formFieldDoc.getxWikiClass().properties.get(0).classType)123 - #set ($discard = $propertyType2FormField.put($type, $formFieldDoc))106 + #set($type = $formFieldDoc.getxWikiClass().properties.get(0).classType) 107 + #set($discard = $propertyType2FormField.put($type, $formFieldDoc)) 124 124 #end 125 - <div id="canvas"> 126 - <p class="hint"> 127 - $services.localization.render('platform.appwithinminutes.classEditorCanvasHint') 128 - </p> 129 - <ul> 130 - #set ($unknownFields = []) 131 - #foreach ($field in $doc.getxWikiClass().properties) 132 - #set ($formFieldDoc = $propertyType2FormField.get($field.classType)) 133 - #if ($formFieldDoc) 134 - <li>#displayField($field $formFieldDoc)</li> 135 - #else 136 - #set($discard = $unknownFields.add($field)) 137 - #end 109 + (% id="canvas" %) 110 + ((( 111 + (% class="hint" %) 112 + $services.localization.render('platform.appwithinminutes.classEditorCanvasHint') 113 + 114 + #set($unknownFields = []) 115 + #set($empty = true) 116 + #foreach ($field in $doc.getxWikiClass().properties) 117 + #set($formFieldDoc = $propertyType2FormField.get($field.classType)) 118 + #if($formFieldDoc) 119 + #set($empty = false) 120 + * (((#displayField($field $formFieldDoc)))) 121 + #else 122 + #set($discard = $unknownFields.add($field)) 138 138 #end 139 - </ul> 140 - <div class="hidden"> 124 + #end 125 + #if(!$empty) 126 + ## Leave an empty line to separate the blocks. 127 + 128 + #end 129 + ## 130 + (% class="hidden" %) 131 + {{html}} 141 141 ## Output the field meta data even if the field is not supported to preserve it when the class is saved. 142 - #foreach ($field in $unknownFields)133 + #foreach($field in $unknownFields) 143 143 #displayFieldMetaData($field) 144 144 #end 145 - </div>146 - </div>136 + {{/html}} 137 + ))) 147 147 #end 148 148 149 149 #** 150 150 * Display the options to create/update the class template, the class sheet and the class translation bundle. 151 151 *# 152 -#macro (displayClassOptions)143 +#macro(displayClassOptions) 153 153 #set ($className = $stringtool.removeEnd($doc.fullName, 'Class')) 154 154 #set ($templateReference = $services.model.resolveDocument("${className}Template")) 155 155 #set ($translationsReference = $services.model.resolveDocument("${className}Translations")) ... ... @@ -160,6 +160,7 @@ 160 160 #elseif ($classSheets.size() == 1) 161 161 #set ($sheetReference = $classSheets.get(0)) 162 162 #end 154 + {{html}} 163 163 ## Hide the options if neither the sheet nor the template nor the translation bundle exists. They don't have to be 164 164 ## updated, they have to be created. 165 165 <dl id="options" #if (!$xwiki.exists($sheetReference) && !$xwiki.exists($templateReference) ... ... @@ -190,7 +190,9 @@ 190 190 ["#pageLink($sheetReference)"]) 191 191 </span> 192 192 #else 193 - #inlineWarning($services.localization.render('platform.appwithinminutes.classEditorMultipleSheetsWarning')) 185 + <span class="warningmessage"> 186 + $services.localization.render('platform.appwithinminutes.classEditorMultipleSheetsWarning') 187 + </span> 194 194 #end 195 195 </dd> 196 196 <dt> ... ... @@ -206,6 +206,7 @@ 206 206 </span> 207 207 </dd> 208 208 </dl> 203 + {{/html}} 209 209 #end 210 210 211 211 #macro (pageLink $reference) ... ... @@ -217,56 +217,58 @@ 217 217 #set ($action = 'create') 218 218 #set ($discard = $params.put('parent', $doc.fullName)) 219 219 #end 220 - <span class="$class"><a href="$escapetool.xml($xwiki.getURL($reference, $action, $escapetool.url($params)))" 221 - >$escapetool.xml($reference.name)</a></span>## 215 + <span class="$class">## 216 + <a href="$escapetool.xml($xwiki.getURL($reference, $action, $escapetool.url($params)))">## 217 + $escapetool.xml($reference.name)## 218 + </a>## 219 + </span>## 222 222 #end 223 223 224 224 #** 225 225 * Display a form field. 226 226 *# 227 -#macro (displayField $field $formFieldDoc)228 - #if ($formFieldDoc.getObject('XWiki.StyleSheetExtension'))229 - #set ($discard = $xwiki.ssx.use($formFieldDoc.fullName))225 +#macro(displayField $field $formFieldDoc) 226 + #if($formFieldDoc.getObject('XWiki.StyleSheetExtension')) 227 + #set($discard = $xwiki.ssx.use($formFieldDoc.fullName)) 230 230 #end 231 - #if ($formFieldDoc.getObject('XWiki.JavaScriptExtension'))232 - #set ($discard = $xwiki.jsx.use($formFieldDoc.fullName))229 + #if($formFieldDoc.getObject('XWiki.JavaScriptExtension')) 230 + #set($discard = $xwiki.jsx.use($formFieldDoc.fullName)) 233 233 #end 234 - <div class="hidden"> 232 + (% class="hidden" %) 233 + {{html}} 235 235 #displayFieldMetaData($field) 236 236 ## We need this information to avoid querying and loading all FormField documents twice. 237 237 ## NOTE: We use a different ID format to avoid collisions with the field meta properties. 238 - <input type="hidden" id="template-$field.name" name="template-$field.name" 239 - value="$escapetool.xml($formFieldDoc.fullName)" 240 - data-propertyName="$escapetool.xml($formFieldDoc.getxWikiClass().propertyNames[0])" /> 241 - </div> 242 - #set ($className = $stringtool.removeEnd($doc.fullName, 'Class')) 243 - #set ($templateRef = $services.model.resolveDocument("${className}Template")) 244 - #set ($templateDoc = $xwiki.getDocument($templateRef)) 237 + <input type="hidden" id="template-$field.name" name="template-$field.name" value="$escapetool.xml($formFieldDoc.fullName)" /> 238 + {{/html}} 239 + 240 + #set($className = $stringtool.removeEnd($doc.fullName, 'Class')) 241 + #set($templateRef = $services.model.resolveDocument("${className}Template")) 242 + #set($templateDoc = $xwiki.getDocument($templateRef)) 245 245 ## Simulate the editing of the class instance from the template document. 246 246 ## Note that we can't simply call display on the template document because $field could be a new field that hasn't 247 247 ## been added to the class yet (so the object from the template doesn't have this field yet). 248 - <dl class="field-viewer"> 249 - #displayFieldProperty($field "${doc.fullName}_0_" $templateDoc.getObject($doc.fullName, true)) 250 - </dl> 251 - #set ($propertyNames = ['name', 'prettyName', 'number', 'required', 'hint']) 252 - #set ($formFieldObj = $formFieldDoc.getObject('AppWithinMinutes.FormFieldClass')) 253 - #set ($customPropertyNames = $formFieldObj.getProperty('properties').value.split('\s+')) 254 - #set ($discard = $customPropertyNames.removeAll($propertyNames)) 255 - #set ($discard = $propertyNames.addAll($customPropertyNames.subList(0, $customPropertyNames.size()))) 256 - <dl class="field-config"> 257 - #foreach ($propertyName in $propertyNames) 258 - #set ($propertyDefinition = $field.xWikiClass.get($propertyName)) 259 - #if ($propertyDefinition) 260 - #displayFieldProperty($propertyDefinition "field-${field.name}_" $field) 261 - #end 246 + (% class="field-viewer" %) 247 + #displayFieldProperty($field "${doc.fullName}_0_" $templateDoc.getObject($doc.fullName, true)) 248 + 249 + #set($propertyNames = ['name', 'prettyName', 'number', 'required', 'hint']) 250 + #set($formFieldObj = $formFieldDoc.getObject('AppWithinMinutes.FormFieldClass')) 251 + #set($customPropertyNames = $formFieldObj.getProperty('properties').value.split('\s+')) 252 + #set($discard = $customPropertyNames.removeAll($propertyNames)) 253 + #set($discard = $propertyNames.addAll($customPropertyNames.subList(0, $customPropertyNames.size()))) 254 + (% class="field-config" %) 255 + #foreach($propertyName in $propertyNames) 256 + #set($propertyDefinition = $field.xWikiClass.get($propertyName)) 257 + #if($propertyDefinition) 258 + #displayFieldProperty($propertyDefinition "field-${field.name}_" $field) 262 262 #end 263 - </dl>260 + #end 264 264 #end 265 265 266 266 #** 267 267 * Display the field meta data. This is needed to preserve the field when its type is not supported by the editor. 268 268 *# 269 -#macro (displayFieldMetaData $field)266 +#macro(displayFieldMetaData $field) 270 270 <input type="hidden" id="type-$field.name" name="type-$field.name" value="$field.classType" /> 271 271 #end 272 272 ... ... @@ -273,19 +273,13 @@ 273 273 #** 274 274 * Displays a configuration property of a class field. This macro can also be used to display a property of an object. 275 275 *# 276 -#macro (displayFieldProperty $property $prefix $field) 277 - ## This 'displayFormType' property only exists for boolean fields. 278 - #set ($displayFormType = $property.getProperty('displayFormType')) 279 - #if ($property.classType == 'Boolean' && (!$displayFormType || $displayFormType.value == 'checkbox')) 280 - <dt> 281 - <label for="$!{prefix}$property.name"> 282 - #displayPropertyEditInput($property, $prefix, $field)$escapetool.xml($property.prettyName) 283 - </label> 284 - </dt> 285 - <dd></dd> 273 +#macro(displayFieldProperty $property $prefix $field) 274 + #set($displayFormType = $property.getProperty('displayFormType')) 275 + #if($property.classType == 'Boolean' && (!$displayFormType || $displayFormType.value == 'checkbox')) 276 + ; {{html clean="false"}}<label for="$!{prefix}$property.name">#displayPropertyEditInput($property, $prefix, $field)$escapetool.xml($property.prettyName)</label>{{/html}} 286 286 #else 287 - <dt><label for="${prefix}$property.name">$escapetool.xml($property.prettyName)</label></dt>288 - <dd>#displayPropertyEditInput($property, $prefix, $field)</dd>278 + ; {{html}}<label for="${prefix}$property.name">$escapetool.xml($property.prettyName)</label>{{/html}} 279 + : {{html clean="false"}}#displayPropertyEditInput($property, $prefix, $field){{/html}} 289 289 #end 290 290 #end 291 291 ... ... @@ -292,18 +292,12 @@ 292 292 #** 293 293 * Displays the input used to edit the specified property of the given object. The given object can be either an 294 294 * instance of an XWiki class or a class field. In the first case the property represents an object field and in the 295 - * second case the property represents a field meta property. We currently don't use custom display for metaproperty, 296 - * so in that case we fallback on displayEdit. 286 + * second case the property represents a field meta property. 297 297 *# 298 -#macro (displayPropertyEditInput $property $prefix $object) 299 - #set ($wrappedProperty = $property.propertyClass) 300 - #if ($wrappedProperty.isCustomDisplayed($xcontext.context)) 301 - #set ($customDisplayer = $!xcontext.get('propertyCustomDisplayer').display($property, $prefix, $object)) 302 - #if ((! $customDisplayer) && ("$!customDisplayer" == "")) 303 - $doc.displayEdit($property, $prefix, $object) 304 - #else 305 - $customDisplayer 306 - #end 288 +#macro(displayPropertyEditInput $property $prefix $object) 289 + #set($wrappedProperty = $property.propertyClass) 290 + #if($wrappedProperty.isCustomDisplayed($xcontext.context)) 291 + $xcontext.get('propertyCustomDisplayer').display($property, $prefix, $object) 307 307 #else 308 308 $doc.displayEdit($property, $prefix, $object) 309 309 #end ... ... @@ -312,23 +312,22 @@ 312 312 #** 313 313 * Called when a new form field is added via AJAX. 314 314 *# 315 -#macro (displayNewField)300 +#macro(displayNewField) 316 316 ## Output the SkinExtension hooks to allow field displayers to pull JavaScript/CSS resources. 317 - ## Output also the LinkExtension hook because $xwiki.linkx.use() is used to load CSS files from WebJars. 318 318 ## The class editor moves this resource includes in the HTML page head. 319 - <!-- com.xpn.xwiki.plugin.skinx.LinkExtensionPlugin -->303 + {{html}} 320 320 #skinExtensionHooks 321 - #set ($formFieldDoc = $xwiki.getDocument($request.field)) 322 - #set ($formFieldDocClassFields = $formFieldDoc.getxWikiClass().getXWikiClass().properties) 323 - #if ($formFieldDocClassFields.size() > 0) 305 + {{/html}} 306 + 307 + #set($formFieldDoc = $xwiki.getDocument($request.field)) 308 + #set($formFieldDocClassFields = $formFieldDoc.getxWikiClass().getXWikiClass().properties) 309 + #if($formFieldDocClassFields.size() > 0) 324 324 ## Clone the field template. 325 - #set ($field = $formFieldDocClassFields.get(0).clone())326 - #if ("$!field.prettyName" == '')327 - #set ($discard = $field.setPrettyName($formFieldDoc.title))311 + #set($field = $formFieldDocClassFields.get(0).clone()) 312 + #if("$!field.prettyName" == '') 313 + #set($discard = $field.setPrettyName($formFieldDoc.title)) 328 328 #end 329 - #set ($xclass = $doc.getxWikiClass().getXWikiClass()) 330 - #set ($discard = $xclass.addField($field.name, $field)) 331 - #set ($discard = $field.setObject($xclass)) 315 + #set($discard = $doc.getxWikiClass().getXWikiClass().addField($field.name, $field)) 332 332 #displayField($doc.getxWikiClass().get($field.name) $formFieldDoc) 333 333 #else 334 334 Unsupported form field. ... ... @@ -338,90 +338,88 @@ 338 338 #** 339 339 * Preview a class field (requires Programming Right). 340 340 *# 341 -#macro (previewField)325 +#macro(previewField) 342 342 ## Find the request parameter that specifies the field template. 343 - #foreach ($paramName in $request.getParameterMap().keySet())344 - #if ($paramName.startsWith('template-'))345 - #set ($fieldName = $paramName.substring(9))346 - #set ($fieldTemplateDoc = $xwiki.getDocument($request.getParameter($paramName)))327 + #foreach($paramName in $request.getParameterMap().keySet()) 328 + #if($paramName.startsWith('template-')) 329 + #set($fieldName = $paramName.substring(9)) 330 + #set($fieldTemplateDoc = $xwiki.getDocument($request.getParameter($paramName))) 347 347 #break 348 348 #end 349 349 #end 350 350 ## 351 351 ## Clone the field template. 352 - #set ($field = $fieldTemplateDoc.getxWikiClass().getXWikiClass().properties.get(0).clone())336 + #set($field = $fieldTemplateDoc.getxWikiClass().getXWikiClass().properties.get(0).clone()) 353 353 ## 354 354 ## Update the field meta properties based on the submitted data. 355 - #set ($valuesFromRequest = $xcontext.context.getForm().getObject("field-$fieldName"))356 - #set ($discard = $field.getxWikiClass().fromMap($valuesFromRequest, $field))339 + #set($valuesFromRequest = $xcontext.context.getForm().getObject("field-$fieldName")) 340 + #set($discard = $field.getxWikiClass().fromMap($valuesFromRequest, $field)) 357 357 ## 358 358 ## Don't rename the field (ignore the submitted name). 359 - #set ($discard = $field.setName($fieldName))343 + #set($discard = $field.setName($fieldName)) 360 360 ## 361 361 ## We have to add the field to the class before setting its value. 362 362 ## (otherwise the field value from the request is ignored). 363 - #set ($xclass = $doc.getxWikiClass().getXWikiClass()) 364 - #set ($discard = $xclass.addField($fieldName, $field)) 365 - #set ($discard = $field.setObject($xclass)) 347 + #set($xclass = $doc.getxWikiClass().getXWikiClass()) 348 + #set($discard = $xclass.addField($fieldName, $field)) 366 366 ## 367 367 ## Create an object that has this field and set its value from request. 368 - #set ($object = $fieldTemplateDoc.getObject($doc.fullName, true))351 + #set($object = $fieldTemplateDoc.getObject($doc.fullName, true)) 369 369 ## 370 370 ## Filter empty values from the request, otherwise the update method could try to select an invalid value. 371 - #set ($values = [])372 - #foreach ($value in $request.getParameterValues("${doc.fullName}_0_$fieldName"))373 - #if ($value != '')374 - #set ($discard = $values.add($value))354 + #set($values = []) 355 + #foreach($value in $request.getParameterValues("${doc.fullName}_0_$fieldName")) 356 + #if($value != '') 357 + #set($discard = $values.add($value)) 375 375 #end 376 376 #end 377 - #if ($values.size() > 0)378 - #set ($stringArray = $request.getParameterValues("template-$fieldName"))379 - #set ($discard = $xclass.fromMap({$fieldName: $values.toArray($stringArray)}, $object.getXWikiObject()))360 + #if($values.size() > 0) 361 + #set($stringArray = $request.getParameterValues("template-$fieldName")) 362 + #set($discard = $xclass.fromMap({$fieldName: $values.toArray($stringArray)}, $object.getXWikiObject())) 380 380 #end 381 381 ## 382 - ## Display the field. 383 - #set ($field = $doc.getxWikiClass().get($fieldName)) 384 - #displayPropertyEditInput($field, "${doc.fullName}_0_", $object) 365 + ## Display the field (with the rights of the current user). 366 + #set($field = $doc.getxWikiClass().get($fieldName)) 367 + ## Note that we don't modify the cached document because the previous line has cloned it. 368 + #set ($discard = $doc.document.setAuthorReference($xcontext.userReference)) 369 + {{html clean="false"}}#displayPropertyEditInput($field, "${doc.fullName}_0_", $object){{/html}} 385 385 #end 386 386 387 387 #** 388 388 * Display the edit class form. 389 389 *# 390 -#macro (displayEditForm) 391 - #set ($discard = $xwiki.jsx.use('AppWithinMinutes.ClassEditSheet')) 392 - #set ($discard = $xwiki.ssx.use('AppWithinMinutes.ClassEditSheet')) 393 - #set ($discard = $xwiki.ssx.use('AppWithinMinutes.ClassSheetGenerator')) 394 - #if ("$!request.wizard" == 'true') 375 +#macro(displayEditForm) 376 + $xwiki.jsfx.use('js/scriptaculous/dragdrop.js')## 377 + $xwiki.jsx.use('AppWithinMinutes.ClassEditSheet')## 378 + $xwiki.ssx.use('AppWithinMinutes.ClassEditSheet')## 379 + $xwiki.ssx.use('AppWithinMinutes.ClassSheetGenerator')## 380 + #if("$!request.wizard" == 'true') 395 395 #appWizardHeader('structure') 382 + 396 396 #end 397 397 #displayFieldPalette() 398 398 #displayFieldCanvas() 399 399 #displayClassOptions() 400 400 #if("$!request.wizard" == 'true') 388 + 401 401 #appWizardFooter('structure') 402 402 #end 403 - <divclass="clearfloats"></div>391 + (% class="clearfloats" %)((())) 404 404 #end 405 405 406 406 #** 407 407 * Displays either the edit class form or a new form field. The later is used when adding a new form field via AJAX. 408 408 *# 409 -#macro (doEdit)410 - #if ("$!request.field" != '')397 +#macro(doEdit) 398 + #if("$!request.field" != '') 411 411 #displayNewField() 412 - #elseif ("$!request.preview" == 'true')400 + #elseif("$!request.preview" == 'true') 413 413 #previewField() 414 414 #else 415 415 ## Make sure that only the sheet content is rendered when the class is saved using AJAX. 416 - <div class="hidden"> 417 - <input type="hidden" name="xpage" value="plain" /> 418 - #if ($request.wizard == 'true') 419 - ## Preserve the wizard mode. 420 - <input type="hidden" name="wizard" value="true" /> 421 - #end 422 - ## Compute the application title to be used as the wizard step title. 423 - #getAppTitle 424 - </div> 404 + (% class="hidden" %) 405 + {{html}}<input type="hidden" name="xpage" value="plain" />{{/html}} 406 + 425 425 #displayEditForm() 426 426 #end 427 427 #end ... ... @@ -437,7 +437,10 @@ 437 437 #try() 438 438 #set ($discard = $copyAsJob.join()) 439 439 #set ($copyAsJobStatus = $services.job.getJobStatus($copyAsJob.request.id)) 440 - #set ($errorMessage = $copyAsJobStatus.logTail.getFirstLogEvent('ERROR').toString()) 422 + #set ($errorLogs = $copyAsJobStatus.log.getLogs('ERROR')) 423 + #if ($errorLogs.size() > 0) 424 + #set ($errorMessage = $errorLogs.get(0).toString()) 425 + #end 441 441 #end 442 442 #end 443 443 #end ... ... @@ -576,7 +576,7 @@ 576 576 #set($className = $stringtool.removeEnd($doc.fullName, 'Class')) 577 577 #set($templateRef = $services.model.resolveDocument("${className}Template")) 578 578 #set($templateDoc = $xwiki.getDocument($templateRef)) 579 - #set($discard = $templateDoc.setParent($doc. documentReference.name))564 + #set($discard = $templateDoc.setParent($doc.name)) 580 580 #if ($request.templateTitle) 581 581 #set($discard = $templateDoc.setTitle($request.templateTitle)) 582 582 #end ... ... @@ -614,13 +614,9 @@ 614 614 #if($sheetReference) 615 615 #set($sheetDoc = $xwiki.getDocument($sheetReference)) 616 616 #set($sheetGeneratorDoc = $xwiki.getDocument('AppWithinMinutes.ClassSheetGenerator')) 617 - #set($discard = $sheetDoc.setParent($doc. documentReference.name))602 + #set($discard = $sheetDoc.setParent($doc.name)) 618 618 #set($discard = $sheetDoc.setContent($doc.getRenderedContent($sheetGeneratorDoc.content, 619 619 $sheetGeneratorDoc.syntax.toIdString(), 'plain/1.0'))) 620 - ## We assume for now that the output produced by the sheet generator uses the same syntax as the code of the sheet 621 - ## generator. We have to set the syntax because the default wiki syntax (used when creating new wiki pages) could 622 - ## be different than the one used by the sheet generator. 623 - #set($discard = $sheetDoc.setSyntax($sheetGeneratorDoc.syntax)) 624 624 #set($discard = $sheetDoc.setHidden(true)) 625 625 #set($discard = $sheetDoc.save($services.localization.render('platform.appwithinminutes.classEditorSheetSaveComment'), 626 626 $minorEdit)) ... ... @@ -642,11 +642,10 @@ 642 642 #set ($scope = 'WIKI') 643 643 #end 644 644 #set($discard = $translationsObj.set('scope', $scope)) 645 - #set($discard = $translationsDoc.setParent($doc. documentReference.name))626 + #set($discard = $translationsDoc.setParent($doc.name)) 646 646 #set($translationsGeneratorDoc = $xwiki.getDocument('AppWithinMinutes.ClassTranslationsGenerator')) 647 647 #set($discard = $translationsDoc.setContent($doc.getRenderedContent($translationsGeneratorDoc.content, 648 648 $translationsGeneratorDoc.syntax.toIdString(), 'plain/1.0'))) 649 - #set($discard = $translationsDoc.setSyntaxId('plain/1.0')) 650 650 #set($discard = $translationsDoc.setHidden(true)) 651 651 #set($discard = $translationsDoc.save( 652 652 $services.localization.render('platform.appwithinminutes.classEditorTranslationsSaveComment'), ... ... @@ -657,17 +657,17 @@ 657 657 #** 658 658 * Updates and saves the class definition, the class sheet and the class template. 659 659 *# 660 -#macro (doSave)661 - #set ($minorEdit = "$!request.minorEdit" != '')640 +#macro(doSave) 641 + #set($minorEdit = "$!request.minorEdit" != '') 662 662 #maybeCreateCodeSpace 663 663 #updateAndSaveClass 664 664 #updateAndSaveTemplate 665 665 #updateAndSaveSheet 666 666 #updateAndSaveTranslations 667 - #if ($action == 'save')668 - #if ($errorMessage)669 - #error($errorMessage)670 - #elseif ("$!request.wizard" == 'true')647 + #if($action == 'save') 648 + #if($errorMessage) 649 + {{error}}{{html}}$errorMessage{{/html}}{{/error}} 650 + #elseif("$!request.wizard" == 'true') 671 671 ## Redirect to next wizard step. 672 672 #set ($className = $stringtool.removeEnd($doc.fullName, 'Class')) 673 673 #set ($templateProviderReference = $services.model.resolveDocument("${className}TemplateProvider")) ... ... @@ -677,7 +677,6 @@ 677 677 }) 678 678 #if (!$xwiki.exists($templateProviderReference)) 679 679 #set ($discard = $queryString.putAll({ 680 - 'form_token': $services.csrf.getToken(), 681 681 'template': 'XWiki.TemplateProviderTemplate', 682 682 'parent': $doc.fullName 683 683 })) ... ... @@ -688,7 +688,7 @@ 688 688 $response.sendRedirect($doc.getURL()) 689 689 #end 690 690 #else 691 - #if ($errorMessage)670 + #if($errorMessage) 692 692 $response.sendError(400, $errorMessage) 693 693 #else 694 694 $response.setStatus(204) ... ... @@ -704,23 +704,21 @@ 704 704 {{/velocity}} 705 705 706 706 {{velocity}} 707 -{{html clean="false"}} 708 708 ## Determine the action button that triggered the request 709 -#set ($action = 'edit')710 -#foreach ($paramName in $request.getParameterMap().keySet())711 - #if ($paramName.startsWith('xaction_'))712 - #set ($action = $paramName.substring(8))687 +#set($action = 'edit') 688 +#foreach($paramName in $request.getParameterMap().keySet()) 689 + #if($paramName.startsWith('xaction_')) 690 + #set($action = $paramName.substring(8)) 713 713 #break 714 714 #end 715 715 #end 716 -#if ($action == 'edit')694 +#if($action == 'edit') 717 717 #doEdit() 718 -#elseif ($action == 'save' || $action == 'saveandcontinue')719 - #if ($services.csrf.isTokenValid($request.form_token))696 +#elseif($action == 'save' || $action == 'saveandcontinue') 697 + #if($services.csrf.isTokenValid($request.form_token)) 720 720 #doSave() 721 721 #else 722 - $response.sendRedirect($services.csrf.getResubmissionURL()) 700 + $response.sendRedirect($services.csrf.getResubmissionURL()); 723 723 #end 724 724 #end 725 -{{/html}} 726 726 {{/velocity}}
- XWiki.JavaScriptExtension[2]
-
- Code
-
... ... @@ -300,10 +300,8 @@ 300 300 var label = previousDT.down('label'); 301 301 prettyNameInput.title = label.textContent || label.innerText; 302 302 } 303 - prettyNameInput.ariaLabel = '$escapetool.javascript($services.localization.render('platform.appwithinminutes.classEditorFieldPrettyNameToolTip'))'; 304 304 // Replace the preview label with the pretty name input. 305 305 var previewLabel = field.getViewer().down('label'); 306 - // We unset the for attribute, so that this label will not be set implicitely OR explicitely anymore. 307 307 previewLabel.writeAttribute('for', ''); 308 308 previewLabel.removeChild(previewLabel.lastChild); 309 309 previewLabel.insert(prettyNameInput); ... ... @@ -328,12 +328,10 @@ 328 328 _enhanceFieldDefaultValue : function(event) { 329 329 var field = event.memo.field; 330 330 var fieldName = field.getName(); 331 - // We select the default field input and update it. 332 - field.getViewer().select('dd :input').each(function(input) { 329 + field.getViewer().select('input[type=text]', 'textarea').each(function(input) { 333 333 if (!input.title && input.name.endsWith('_0_' + fieldName)) { 334 334 input.title = '$escapetool.javascript($services.localization.render('platform.appwithinminutes.classEditorFieldDefaultValueToolTip'))'; 335 335 } 336 - input.ariaLabel = '$escapetool.javascript($services.localization.render('platform.appwithinminutes.classEditorFieldDefaultValueToolTip'))'; 337 337 }); 338 338 }, 339 339 _onSave : function() { ... ... @@ -368,15 +368,10 @@ 368 368 if (hintInput) { 369 369 hintInput.addClassName('xHint'); 370 370 if (!hintInput.title) { 371 - hintInput.title = '$escapetool.javascript($services.localization.render('platform.appwithinminutes.classEditorFieldHintToolTip'))'; 372 - hintInput.ariaLabel = '$escapetool.javascript($services.localization.render('platform.appwithinminutes.classEditorFieldHintToolTip'))'; 367 + hintInput.title = 'Hint'; 373 373 } 374 374 // Move the hint input below the pretty name input, in the field viewer. 375 - var dd = hintInput.up('dd'); 376 - var dt = dd.previous('dt'); 377 377 field.getViewer().down('label').insert({after: hintInput}); 378 - dt.remove(); 379 - dd.remove(); 380 380 // Enhance the hint input. 381 381 new XWiki.InputWithTitle(hintInput); 382 382 new XWiki.AutoResizeInput(hintInput); ... ... @@ -435,7 +435,7 @@ 435 435 }); 436 436 }, 437 437 _onDrop : function(field) { 438 - var fieldContainer = new Element('li' , {'data-new': 'true'});429 + var fieldContainer = new Element('li'); 439 439 this.fields.insert(fieldContainer); 440 440 this.container.removeClassName('empty'); 441 441 new XWiki.FormField(fieldContainer).enhance(field.down('.data').value); ... ... @@ -520,11 +520,15 @@ 520 520 }(XWiki || {})); 521 521 522 522 (function() { 523 - function initForm(form) { 524 - // Let the sheet handle the form submit. The form is submitted by default to the preview action which dispatches the 525 - // request to the save action if the save button is detected on the request parameters. By submitting to the edit 526 - // action the edit sheet is evaluated and thus it can handle the save by itself. 527 - form.action = XWiki.currentDocument.getURL('edit'); 514 + function init() { 515 + var form = $('inline'); 516 + if (!form) { 517 + return false; 518 + } 519 + // Let the sheet handle the form submit. 520 + // NOTE: The code that handles Save&Continue uses this URL to make the AJAX request and Firefox 3.6 doesn't resolve 521 + // the empty string to the current page URL so we have to explicitly specify it. 522 + form.action = window.location.href; 528 528 529 529 // Apply the vertical form layout standard. 530 530 form.addClassName('xform'); ... ... @@ -558,58 +558,8 @@ 558 558 // Make the palette and the canvas live. 559 559 new XWiki.FormFieldPalette('palette'); 560 560 new XWiki.FormCanvas('canvas'); 561 - } 562 562 563 - function init() { 564 - var form = $('inline'); 565 - if (form) { 566 - require(['scriptaculous/dragdrop'], function() { 567 - initForm(form); 568 - }); 569 - } 570 - return form; 557 + return true; 571 571 } 572 - 573 573 (XWiki.domIsLoaded && init()) || document.observe('xwiki:dom:loaded', init); 574 574 }).call(); 575 - 576 -require(['jquery', 'xwiki-events-bridge'], function($) { 577 - $(document).on('xwiki:class:displayField xwiki:class:previewField', function(event, data) { 578 - var container = $(data.field.getContainer()); 579 - if (container.attr('data-new') === 'true') { 580 - // We can't suggest property values for properties that don't exist yet (have not been saved) so we provide 581 - // suggestions for the template property that was used to create them. Note that the suggested values depend on 582 - // the saved property meta data so changing the property (field) meta data may not affect the suggestions until 583 - // those changes are saved. 584 - var templateHiddenInput = container.find('#' + 'template-' + data.field.getName()); 585 - var propertyValueSuggester = container.find('.field-viewer .suggest-propertyValues').first(); 586 - propertyValueSuggester.attr({ 587 - 'data-className': templateHiddenInput.val(), 588 - 'data-propertyName': templateHiddenInput.attr('data-propertyName') 589 - }); 590 - } 591 - }).on('xwiki:document:saved', function(event) { 592 - // We need to update the property value suggesters because: 593 - // * newly saved properties should have their own suggestions instead of relying on the template property 594 - // * for renamed properties we need to fetch the suggestions from a different location 595 - $('ul#fields > li').each(function() { 596 - var container = $(this); 597 - container.removeAttr('data-new'); 598 - var propertyValueSuggester = container.find('.field-viewer .suggest-propertyValues').first(); 599 - if (propertyValueSuggester.length > 0) { 600 - // We need to preserve the selected values because they are lost when the suggester is destroyed. 601 - var selectedValues = propertyValueSuggester.children(); 602 - propertyValueSuggester[0].selectize.destroy(); 603 - // Restore the selected values. 604 - propertyValueSuggester.empty().append(selectedValues); 605 - var className = XWiki.Model.serialize(XWiki.currentDocument.documentReference.relativeTo( 606 - new XWiki.WikiReference(XWiki.currentWiki))); 607 - propertyValueSuggester.attr({ 608 - 'data-className': className, 609 - 'data-propertyName': propertyValueSuggester.attr('name').substr((className + '_0_').length) 610 - }); 611 - propertyValueSuggester.suggestPropertyValues(); 612 - } 613 - }); 614 - }); 615 -});
- XWiki.StyleSheetExtension[1]
-
- Code
-
... ... @@ -38,9 +38,7 @@ 38 38 } 39 39 40 40 #fields input.xHint { 41 - color: $theme.textSecondaryColor; 42 - font-size: smaller; 43 - font-weight: normal; 41 + border: 0 none; 44 44 } 45 45 46 46 #fields .labelLine label {