Changes for page ClassEditSheet
Last modified by Xwiki Admin on 2019/12/20 09:53
edited by Xwiki Admin
on 2018/03/14 16:00
on 2018/03/14 16:00
edited by Xwiki Admin
on 2019/12/20 09:53
on 2019/12/20 09:53
Change comment: Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/11.10.1]
Summary
-
Page properties (3 modified, 0 added, 0 removed)
-
Objects (2 modified, 0 added, 0 removed)
Details
- Page properties
-
- Title
-
... ... @@ -1,1 +1,1 @@ 1 -#if( !$doc.name.endsWith('Sheet'))$services.localization.render('appWithinMinutes.classEditor.title', [$stringtool.removeEnd($doc.title, 'Class').trim()])#{else}$doc.name#end1 +#if ("$!appTitle" != '')$appTitle#else$doc.pageReference.name#end - Syntax
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki 2. 01 +XWiki 2.1 - Content
-
... ... @@ -1,3 +1,5 @@ 1 +{{include reference="AppWithinMinutes.VelocityMacros" /}} 2 + 1 1 {{groovy}} 2 2 import com.xpn.xwiki.XWikiContext; 3 3 import com.xpn.xwiki.api.Context; ... ... @@ -52,95 +52,100 @@ 52 52 #** 53 53 * Displays the field palette. 54 54 *# 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 - 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> 63 63 ## List all form field types, grouped by category. 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)) 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">$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='$formFieldIconURL' alt='$escapetool.xml($formFieldDoc.plainTitle)' class='icon' />") 80 80 #end 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}} 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 + 'field': $formFieldDoc.fullName, 101 + 'xeditmode': 'text' 102 + }))) 103 + <input type="hidden" value="$fieldURL" class="data"/> 104 + </li> 94 94 #end 106 + </ul> 107 + </li> 95 95 #end 96 - ))) 109 + </ul> 110 + </div> 97 97 #end 98 98 99 99 #** 100 100 * Displays the field canvas. 101 101 *# 102 -#macro(displayFieldCanvas) 103 - #set($propertyType2FormField = {}) 104 - #foreach($formFieldDoc in $formFieldDocs) 116 +#macro (displayFieldCanvas) 117 + #set ($propertyType2FormField = {}) 118 + #foreach ($formFieldDoc in $formFieldDocs) 105 105 ## Use the type of the field template. 106 - #set($type = $formFieldDoc.getxWikiClass().properties.get(0).classType) 107 - #set($discard = $propertyType2FormField.put($type, $formFieldDoc)) 120 + #set ($type = $formFieldDoc.getxWikiClass().properties.get(0).classType) 121 + #set ($discard = $propertyType2FormField.put($type, $formFieldDoc)) 108 108 #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)) 123 + <div id="canvas"> 124 + <p class="hint"> 125 + $services.localization.render('platform.appwithinminutes.classEditorCanvasHint') 126 + </p> 127 + <ul> 128 + #set ($unknownFields = []) 129 + #foreach ($field in $doc.getxWikiClass().properties) 130 + #set ($formFieldDoc = $propertyType2FormField.get($field.classType)) 131 + #if ($formFieldDoc) 132 + <li>#displayField($field $formFieldDoc)</li> 133 + #else 134 + #set($discard = $unknownFields.add($field)) 135 + #end 123 123 #end 124 - #end 125 - #if(!$empty) 126 - ## Leave an empty line to separate the blocks. 127 - 128 - #end 129 - ## 130 - (% class="hidden" %) 131 - {{html}} 137 + </ul> 138 + <div class="hidden"> 132 132 ## Output the field meta data even if the field is not supported to preserve it when the class is saved. 133 - #foreach($field in $unknownFields) 140 + #foreach ($field in $unknownFields) 134 134 #displayFieldMetaData($field) 135 135 #end 136 - {{/html}}137 - )))143 + </div> 144 + </div> 138 138 #end 139 139 140 140 #** 141 141 * Display the options to create/update the class template, the class sheet and the class translation bundle. 142 142 *# 143 -#macro(displayClassOptions) 150 +#macro (displayClassOptions) 144 144 #set ($className = $stringtool.removeEnd($doc.fullName, 'Class')) 145 145 #set ($templateReference = $services.model.resolveDocument("${className}Template")) 146 146 #set ($translationsReference = $services.model.resolveDocument("${className}Translations")) ... ... @@ -151,7 +151,6 @@ 151 151 #elseif ($classSheets.size() == 1) 152 152 #set ($sheetReference = $classSheets.get(0)) 153 153 #end 154 - {{html}} 155 155 ## Hide the options if neither the sheet nor the template nor the translation bundle exists. They don't have to be 156 156 ## updated, they have to be created. 157 157 <dl id="options" #if (!$xwiki.exists($sheetReference) && !$xwiki.exists($templateReference) ... ... @@ -200,7 +200,6 @@ 200 200 </span> 201 201 </dd> 202 202 </dl> 203 - {{/html}} 204 204 #end 205 205 206 206 #macro (pageLink $reference) ... ... @@ -212,58 +212,56 @@ 212 212 #set ($action = 'create') 213 213 #set ($discard = $params.put('parent', $doc.fullName)) 214 214 #end 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>## 220 + <span class="$class"><a href="$escapetool.xml($xwiki.getURL($reference, $action, $escapetool.url($params)))" 221 + >$escapetool.xml($reference.name)</a></span>## 220 220 #end 221 221 222 222 #** 223 223 * Display a form field. 224 224 *# 225 -#macro(displayField $field $formFieldDoc) 226 - #if($formFieldDoc.getObject('XWiki.StyleSheetExtension')) 227 - #set($discard = $xwiki.ssx.use($formFieldDoc.fullName)) 227 +#macro (displayField $field $formFieldDoc) 228 + #if ($formFieldDoc.getObject('XWiki.StyleSheetExtension')) 229 + #set ($discard = $xwiki.ssx.use($formFieldDoc.fullName)) 228 228 #end 229 - #if($formFieldDoc.getObject('XWiki.JavaScriptExtension')) 230 - #set($discard = $xwiki.jsx.use($formFieldDoc.fullName)) 231 + #if ($formFieldDoc.getObject('XWiki.JavaScriptExtension')) 232 + #set ($discard = $xwiki.jsx.use($formFieldDoc.fullName)) 231 231 #end 232 - (% class="hidden" %) 233 - {{html}} 234 + <div class="hidden"> 234 234 #displayFieldMetaData($field) 235 235 ## We need this information to avoid querying and loading all FormField documents twice. 236 236 ## NOTE: We use a different ID format to avoid collisions with the field meta properties. 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)) 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)) 243 243 ## Simulate the editing of the class instance from the template document. 244 244 ## Note that we can't simply call display on the template document because $field could be a new field that hasn't 245 245 ## been added to the class yet (so the object from the template doesn't have this field yet). 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) 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 259 259 #end 260 - #end263 + </dl> 261 261 #end 262 262 263 263 #** 264 264 * Display the field meta data. This is needed to preserve the field when its type is not supported by the editor. 265 265 *# 266 -#macro(displayFieldMetaData $field) 269 +#macro (displayFieldMetaData $field) 267 267 <input type="hidden" id="type-$field.name" name="type-$field.name" value="$field.classType" /> 268 268 #end 269 269 ... ... @@ -270,13 +270,18 @@ 270 270 #** 271 271 * Displays a configuration property of a class field. This macro can also be used to display a property of an object. 272 272 *# 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}} 276 +#macro (displayFieldProperty $property $prefix $field) 277 + #set ($displayFormType = $property.getProperty('displayFormType')) 278 + #if ($property.classType == 'Boolean' && (!$displayFormType || $displayFormType.value == 'checkbox')) 279 + <dt> 280 + <label for="$!{prefix}$property.name"> 281 + #displayPropertyEditInput($property, $prefix, $field)$escapetool.xml($property.prettyName) 282 + </label> 283 + </dt> 284 + <dd></dd> 277 277 #else 278 - ; {{html}}<label for="${prefix}$property.name">$escapetool.xml($property.prettyName)</label>{{/html}}279 - : {{html clean="false"}}#displayPropertyEditInput($property, $prefix, $field){{/html}}286 + <dt><label for="${prefix}$property.name">$escapetool.xml($property.prettyName)</label></dt> 287 + <dd>#displayPropertyEditInput($property, $prefix, $field)</dd> 280 280 #end 281 281 #end 282 282 ... ... @@ -283,12 +283,18 @@ 283 283 #** 284 284 * Displays the input used to edit the specified property of the given object. The given object can be either an 285 285 * instance of an XWiki class or a class field. In the first case the property represents an object field and in the 286 - * second case the property represents a field meta property. 294 + * second case the property represents a field meta property. We currently don't use custom display for metaproperty, 295 + * so in that case we fallback on displayEdit. 287 287 *# 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) 297 +#macro (displayPropertyEditInput $property $prefix $object) 298 + #set ($wrappedProperty = $property.propertyClass) 299 + #if ($wrappedProperty.isCustomDisplayed($xcontext.context)) 300 + #set ($customDisplayer = $!xcontext.get('propertyCustomDisplayer').display($property, $prefix, $object)) 301 + #if ((! $customDisplayer) && ("$!customDisplayer" == "")) 302 + $doc.displayEdit($property, $prefix, $object) 303 + #else 304 + $customDisplayer 305 + #end 292 292 #else 293 293 $doc.displayEdit($property, $prefix, $object) 294 294 #end ... ... @@ -297,22 +297,23 @@ 297 297 #** 298 298 * Called when a new form field is added via AJAX. 299 299 *# 300 -#macro(displayNewField) 314 +#macro (displayNewField) 301 301 ## Output the SkinExtension hooks to allow field displayers to pull JavaScript/CSS resources. 316 + ## Output also the LinkExtension hook because $xwiki.linkx.use() is used to load CSS files from WebJars. 302 302 ## The class editor moves this resource includes in the HTML page head. 303 - {{html}}318 + <!-- com.xpn.xwiki.plugin.skinx.LinkExtensionPlugin --> 304 304 #skinExtensionHooks 305 - {{/html}} 306 - 307 - #set($formFieldDoc = $xwiki.getDocument($request.field)) 308 - #set($formFieldDocClassFields = $formFieldDoc.getxWikiClass().getXWikiClass().properties) 309 - #if($formFieldDocClassFields.size() > 0) 320 + #set ($formFieldDoc = $xwiki.getDocument($request.field)) 321 + #set ($formFieldDocClassFields = $formFieldDoc.getxWikiClass().getXWikiClass().properties) 322 + #if ($formFieldDocClassFields.size() > 0) 310 310 ## Clone the field template. 311 - #set($field = $formFieldDocClassFields.get(0).clone()) 312 - #if("$!field.prettyName" == '') 313 - #set($discard = $field.setPrettyName($formFieldDoc.title)) 324 + #set ($field = $formFieldDocClassFields.get(0).clone()) 325 + #if ("$!field.prettyName" == '') 326 + #set ($discard = $field.setPrettyName($formFieldDoc.title)) 314 314 #end 315 - #set($discard = $doc.getxWikiClass().getXWikiClass().addField($field.name, $field)) 328 + #set ($xclass = $doc.getxWikiClass().getXWikiClass()) 329 + #set ($discard = $xclass.addField($field.name, $field)) 330 + #set ($discard = $field.setObject($xclass)) 316 316 #displayField($doc.getxWikiClass().get($field.name) $formFieldDoc) 317 317 #else 318 318 Unsupported form field. ... ... @@ -322,88 +322,91 @@ 322 322 #** 323 323 * Preview a class field (requires Programming Right). 324 324 *# 325 -#macro(previewField) 340 +#macro (previewField) 326 326 ## Find the request parameter that specifies the field template. 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))) 342 + #foreach ($paramName in $request.getParameterMap().keySet()) 343 + #if ($paramName.startsWith('template-')) 344 + #set ($fieldName = $paramName.substring(9)) 345 + #set ($fieldTemplateDoc = $xwiki.getDocument($request.getParameter($paramName))) 331 331 #break 332 332 #end 333 333 #end 334 334 ## 335 335 ## Clone the field template. 336 - #set($field = $fieldTemplateDoc.getxWikiClass().getXWikiClass().properties.get(0).clone()) 351 + #set ($field = $fieldTemplateDoc.getxWikiClass().getXWikiClass().properties.get(0).clone()) 337 337 ## 338 338 ## Update the field meta properties based on the submitted data. 339 - #set($valuesFromRequest = $xcontext.context.getForm().getObject("field-$fieldName")) 340 - #set($discard = $field.getxWikiClass().fromMap($valuesFromRequest, $field)) 354 + #set ($valuesFromRequest = $xcontext.context.getForm().getObject("field-$fieldName")) 355 + #set ($discard = $field.getxWikiClass().fromMap($valuesFromRequest, $field)) 341 341 ## 342 342 ## Don't rename the field (ignore the submitted name). 343 - #set($discard = $field.setName($fieldName)) 358 + #set ($discard = $field.setName($fieldName)) 344 344 ## 345 345 ## We have to add the field to the class before setting its value. 346 346 ## (otherwise the field value from the request is ignored). 347 - #set($xclass = $doc.getxWikiClass().getXWikiClass()) 348 - #set($discard = $xclass.addField($fieldName, $field)) 362 + #set ($xclass = $doc.getxWikiClass().getXWikiClass()) 363 + #set ($discard = $xclass.addField($fieldName, $field)) 364 + #set ($discard = $field.setObject($xclass)) 349 349 ## 350 350 ## Create an object that has this field and set its value from request. 351 - #set($object = $fieldTemplateDoc.getObject($doc.fullName, true)) 367 + #set ($object = $fieldTemplateDoc.getObject($doc.fullName, true)) 352 352 ## 353 353 ## Filter empty values from the request, otherwise the update method could try to select an invalid value. 354 - #set($values = []) 355 - #foreach($value in $request.getParameterValues("${doc.fullName}_0_$fieldName")) 356 - #if($value != '') 357 - #set($discard = $values.add($value)) 370 + #set ($values = []) 371 + #foreach ($value in $request.getParameterValues("${doc.fullName}_0_$fieldName")) 372 + #if ($value != '') 373 + #set ($discard = $values.add($value)) 358 358 #end 359 359 #end 360 - #if($values.size() > 0) 361 - #set($stringArray = $request.getParameterValues("template-$fieldName")) 362 - #set($discard = $xclass.fromMap({$fieldName: $values.toArray($stringArray)}, $object.getXWikiObject())) 376 + #if ($values.size() > 0) 377 + #set ($stringArray = $request.getParameterValues("template-$fieldName")) 378 + #set ($discard = $xclass.fromMap({$fieldName: $values.toArray($stringArray)}, $object.getXWikiObject())) 363 363 #end 364 364 ## 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}} 381 + ## Display the field. 382 + #set ($field = $doc.getxWikiClass().get($fieldName)) 383 + #displayPropertyEditInput($field, "${doc.fullName}_0_", $object) 370 370 #end 371 371 372 372 #** 373 373 * Display the edit class form. 374 374 *# 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') 389 +#macro (displayEditForm) 390 + #set ($discard = $xwiki.jsfx.use('js/scriptaculous/dragdrop.js')) 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') 381 381 #appWizardHeader('structure') 382 - 383 383 #end 384 384 #displayFieldPalette() 385 385 #displayFieldCanvas() 386 386 #displayClassOptions() 387 387 #if("$!request.wizard" == 'true') 388 - 389 389 #appWizardFooter('structure') 390 390 #end 391 - (%class="clearfloats"%)((()))403 + <div class="clearfloats"></div> 392 392 #end 393 393 394 394 #** 395 395 * Displays either the edit class form or a new form field. The later is used when adding a new form field via AJAX. 396 396 *# 397 -#macro(doEdit) 398 - #if("$!request.field" != '') 409 +#macro (doEdit) 410 + #if ("$!request.field" != '') 399 399 #displayNewField() 400 - #elseif("$!request.preview" == 'true') 412 + #elseif ("$!request.preview" == 'true') 401 401 #previewField() 402 402 #else 403 403 ## Make sure that only the sheet content is rendered when the class is saved using AJAX. 404 - (% class="hidden" %) 405 - {{html}}<input type="hidden" name="xpage" value="plain" />{{/html}} 406 - 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> 407 407 #displayEditForm() 408 408 #end 409 409 #end ... ... @@ -419,10 +419,7 @@ 419 419 #try() 420 420 #set ($discard = $copyAsJob.join()) 421 421 #set ($copyAsJobStatus = $services.job.getJobStatus($copyAsJob.request.id)) 422 - #set ($errorLogs = $copyAsJobStatus.log.getLogs('ERROR')) 423 - #if ($errorLogs.size() > 0) 424 - #set ($errorMessage = $errorLogs.get(0).toString()) 425 - #end 440 + #set ($errorMessage = $copyAsJobStatus.logTail.getFirstLogEvents('ERROR').toString()) 426 426 #end 427 427 #end 428 428 #end ... ... @@ -561,7 +561,7 @@ 561 561 #set($className = $stringtool.removeEnd($doc.fullName, 'Class')) 562 562 #set($templateRef = $services.model.resolveDocument("${className}Template")) 563 563 #set($templateDoc = $xwiki.getDocument($templateRef)) 564 - #set($discard = $templateDoc.setParent($doc.name)) 579 + #set($discard = $templateDoc.setParent($doc.documentReference.name)) 565 565 #if ($request.templateTitle) 566 566 #set($discard = $templateDoc.setTitle($request.templateTitle)) 567 567 #end ... ... @@ -599,7 +599,7 @@ 599 599 #if($sheetReference) 600 600 #set($sheetDoc = $xwiki.getDocument($sheetReference)) 601 601 #set($sheetGeneratorDoc = $xwiki.getDocument('AppWithinMinutes.ClassSheetGenerator')) 602 - #set($discard = $sheetDoc.setParent($doc.name)) 617 + #set($discard = $sheetDoc.setParent($doc.documentReference.name)) 603 603 #set($discard = $sheetDoc.setContent($doc.getRenderedContent($sheetGeneratorDoc.content, 604 604 $sheetGeneratorDoc.syntax.toIdString(), 'plain/1.0'))) 605 605 #set($discard = $sheetDoc.setHidden(true)) ... ... @@ -623,7 +623,7 @@ 623 623 #set ($scope = 'WIKI') 624 624 #end 625 625 #set($discard = $translationsObj.set('scope', $scope)) 626 - #set($discard = $translationsDoc.setParent($doc.name)) 641 + #set($discard = $translationsDoc.setParent($doc.documentReference.name)) 627 627 #set($translationsGeneratorDoc = $xwiki.getDocument('AppWithinMinutes.ClassTranslationsGenerator')) 628 628 #set($discard = $translationsDoc.setContent($doc.getRenderedContent($translationsGeneratorDoc.content, 629 629 $translationsGeneratorDoc.syntax.toIdString(), 'plain/1.0'))) ... ... @@ -637,17 +637,17 @@ 637 637 #** 638 638 * Updates and saves the class definition, the class sheet and the class template. 639 639 *# 640 -#macro(doSave) 641 - #set($minorEdit = "$!request.minorEdit" != '') 655 +#macro (doSave) 656 + #set ($minorEdit = "$!request.minorEdit" != '') 642 642 #maybeCreateCodeSpace 643 643 #updateAndSaveClass 644 644 #updateAndSaveTemplate 645 645 #updateAndSaveSheet 646 646 #updateAndSaveTranslations 647 - #if($action == 'save') 648 - #if($errorMessage) 649 - {{error}}{{html}}$errorMessage{{/html}}{{/error}}650 - #elseif("$!request.wizard" == 'true') 662 + #if ($action == 'save') 663 + #if ($errorMessage) 664 + <div class="box errormessage">$errorMessage</div> 665 + #elseif ("$!request.wizard" == 'true') 651 651 ## Redirect to next wizard step. 652 652 #set ($className = $stringtool.removeEnd($doc.fullName, 'Class')) 653 653 #set ($templateProviderReference = $services.model.resolveDocument("${className}TemplateProvider")) ... ... @@ -667,7 +667,7 @@ 667 667 $response.sendRedirect($doc.getURL()) 668 668 #end 669 669 #else 670 - #if($errorMessage) 685 + #if ($errorMessage) 671 671 $response.sendError(400, $errorMessage) 672 672 #else 673 673 $response.setStatus(204) ... ... @@ -683,21 +683,23 @@ 683 683 {{/velocity}} 684 684 685 685 {{velocity}} 701 +{{html clean="false"}} 686 686 ## Determine the action button that triggered the request 687 -#set($action = 'edit') 688 -#foreach($paramName in $request.getParameterMap().keySet()) 689 - #if($paramName.startsWith('xaction_')) 690 - #set($action = $paramName.substring(8)) 703 +#set ($action = 'edit') 704 +#foreach ($paramName in $request.getParameterMap().keySet()) 705 + #if ($paramName.startsWith('xaction_')) 706 + #set ($action = $paramName.substring(8)) 691 691 #break 692 692 #end 693 693 #end 694 -#if($action == 'edit') 710 +#if ($action == 'edit') 695 695 #doEdit() 696 -#elseif($action == 'save' || $action == 'saveandcontinue') 697 - #if($services.csrf.isTokenValid($request.form_token)) 712 +#elseif ($action == 'save' || $action == 'saveandcontinue') 713 + #if ($services.csrf.isTokenValid($request.form_token)) 698 698 #doSave() 699 699 #else 700 - $response.sendRedirect($services.csrf.getResubmissionURL()) ;716 + $response.sendRedirect($services.csrf.getResubmissionURL()) 701 701 #end 702 702 #end 719 +{{/html}} 703 703 {{/velocity}}
- XWiki.JavaScriptExtension[2]
-
- code
-
... ... @@ -367,7 +367,11 @@ 367 367 hintInput.title = 'Hint'; 368 368 } 369 369 // Move the hint input below the pretty name input, in the field viewer. 370 + var dd = hintInput.up('dd'); 371 + var dt = dd.previous('dt'); 370 370 field.getViewer().down('label').insert({after: hintInput}); 373 + dt.remove(); 374 + dd.remove(); 371 371 // Enhance the hint input. 372 372 new XWiki.InputWithTitle(hintInput); 373 373 new XWiki.AutoResizeInput(hintInput); ... ... @@ -426,7 +426,7 @@ 426 426 }); 427 427 }, 428 428 _onDrop : function(field) { 429 - var fieldContainer = new Element('li'); 433 + var fieldContainer = new Element('li', {'data-new': 'true'}); 430 430 this.fields.insert(fieldContainer); 431 431 this.container.removeClassName('empty'); 432 432 new XWiki.FormField(fieldContainer).enhance(field.down('.data').value); ... ... @@ -516,10 +516,10 @@ 516 516 if (!form) { 517 517 return false; 518 518 } 519 - // Let the sheet handle the form submit. 520 - // NOTE: Thecodethat handlesSave&ContinueusesthisURLto make theAJAXrequest and Firefox 3.6doesn'tresolve521 - // the e mptystringtothecurrentpageURL so wehavetoexplicitlyspecify it.522 - form.action = window.location.href;523 + // Let the sheet handle the form submit. The form is submitted by default to the preview action which dispatches the 524 + // request to the save action if the save button is detected on the request parameters. By submitting to the edit 525 + // action the edit sheet is evaluated and thus it can handle the save by itself. 526 + form.action = XWiki.currentDocument.getURL('edit'); 523 523 524 524 // Apply the vertical form layout standard. 525 525 form.addClassName('xform'); ... ... @@ -558,3 +558,44 @@ 558 558 } 559 559 (XWiki.domIsLoaded && init()) || document.observe('xwiki:dom:loaded', init); 560 560 }).call(); 565 + 566 +require(['jquery', 'xwiki-events-bridge'], function($) { 567 + $(document).on('xwiki:class:displayField xwiki:class:previewField', function(event, data) { 568 + var container = $(data.field.getContainer()); 569 + if (container.attr('data-new') === 'true') { 570 + // We can't suggest property values for properties that don't exist yet (have not been saved) so we provide 571 + // suggestions for the template property that was used to create them. Note that the suggested values depend on 572 + // the saved property meta data so changing the property (field) meta data may not affect the suggestions until 573 + // those changes are saved. 574 + var templateHiddenInput = container.find('#' + 'template-' + data.field.getName()); 575 + var propertyValueSuggester = container.find('.field-viewer .suggest-propertyValues').first(); 576 + propertyValueSuggester.attr({ 577 + 'data-className': templateHiddenInput.val(), 578 + 'data-propertyName': templateHiddenInput.attr('data-propertyName') 579 + }); 580 + } 581 + }).on('xwiki:document:saved', function(event) { 582 + // We need to update the property value suggesters because: 583 + // * newly saved properties should have their own suggestions instead of relying on the template property 584 + // * for renamed properties we need to fetch the suggestions from a different location 585 + $('ul#fields > li').each(function() { 586 + var container = $(this); 587 + container.removeAttr('data-new'); 588 + var propertyValueSuggester = container.find('.field-viewer .suggest-propertyValues').first(); 589 + if (propertyValueSuggester.length > 0) { 590 + // We need to preserve the selected values because they are lost when the suggester is destroyed. 591 + var selectedValues = propertyValueSuggester.children(); 592 + propertyValueSuggester[0].selectize.destroy(); 593 + // Restore the selected values. 594 + propertyValueSuggester.empty().append(selectedValues); 595 + var className = XWiki.Model.serialize(XWiki.currentDocument.documentReference.relativeTo( 596 + new XWiki.WikiReference(XWiki.currentWiki))); 597 + propertyValueSuggester.attr({ 598 + 'data-className': className, 599 + 'data-propertyName': propertyValueSuggester.attr('name').substr((className + '_0_').length) 600 + }); 601 + propertyValueSuggester.suggestPropertyValues(); 602 + } 603 + }); 604 + }); 605 +});
- XWiki.StyleSheetExtension[1]
-
- code
-
... ... @@ -38,7 +38,9 @@ 38 38 } 39 39 40 40 #fields input.xHint { 41 - border: 0 none; 41 + color: $theme.textSecondaryColor; 42 + font-size: smaller; 43 + font-weight: normal; 42 42 } 43 43 44 44 #fields .labelLine label {
Field Palette
Drag & drop fields from the palette to create the form that will be used to input your data.
- Standard
Short Text
Long Text
Number
Boolean
Static List
- Standard
-
Short Text
-
Long Text
-
Number
-
Boolean
-
Static List
-
- Pickers
Page
Date
User
Group
- Pickers
- Page
- Date
- User
- Group
- Page
Content
Title
- Page
- Content
- Title
- Advanced
Database List
- Advanced
-
Database List
-
Drag fields from the palette and drop them in this area.
Drag fields from the palette and drop them in this area.
- The template (ClassEditSheetTemplate) stores the default field values.
- The sheet (ClassEditSheetSheet) is used to display and edit the structured data.
- Update the translation of field pretty names and list values (ClassEditSheetTranslations).