Cambios para el documento ClassEditSheet

Última modificación por Administrator el 2024/06/06 11:40

Desde la versión 2.1
editado por Administrator
el 2024/06/05 19:09
Cambiar el comentario: Migrated property [contentType] from class [XWiki.StyleSheetExtension]
Hasta la versión 3.1
editado por Administrator
el 2024/06/06 11:40
Cambiar el comentario: Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/15.10.10]

Resumen

Detalles

Propiedades de página
Título
... ... @@ -1,1 +1,1 @@
1 -#if(!$doc.name.endsWith('Sheet'))Class: $stringtool.removeEnd($doc.title, 'Class')#{else}$doc.name#end
1 +#if ("$!appTitle" != '')$appTitle#else$doc.pageReference.name#end
Syntax
... ... @@ -1,1 +1,1 @@
1 -XWiki 2.0
1 +XWiki 2.1
Contenido
... ... @@ -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;
... ... @@ -46,167 +46,227 @@
46 46  #**
47 47   * Constants
48 48   *#
49 -## Magic date used to mark in AWM that the date field is not set for the current entry. See http://jira.xwiki.org/browse/XWIKI-10296
51 +## Magic date used to mark in AWM that the date field is not set for the current entry. See https://jira.xwiki.org/browse/XWIKI-10296
50 50  #set($MAGIC_DATE = $datetool.toDate('yyyy-MM-dd', '9999-12-31'))
51 51  
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">$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' />")
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 - <input type="hidden" value="$doc.getURL('edit', "xpage=plain&sheet=AppWithinMinutes.ClassEditSheet&field=$escapetool.url($formFieldDoc.fullName)")" class="data"/>
89 - {{/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 + '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>
90 90   #end
108 + </ul>
109 + </li>
91 91   #end
92 - )))
111 + </ul>
112 + </div>
93 93  #end
94 94  
95 95  #**
96 96   * Displays the field canvas.
97 97   *#
98 -#macro(displayFieldCanvas)
99 - #set($propertyType2FormField = {})
100 - #foreach($formFieldDoc in $formFieldDocs)
118 +#macro (displayFieldCanvas)
119 + #set ($propertyType2FormField = {})
120 + #foreach ($formFieldDoc in $formFieldDocs)
101 101   ## Use the type of the field template.
102 - #set($type = $formFieldDoc.getxWikiClass().properties.get(0).classType)
103 - #set($discard = $propertyType2FormField.put($type, $formFieldDoc))
122 + #set ($type = $formFieldDoc.getxWikiClass().properties.get(0).classType)
123 + #set ($discard = $propertyType2FormField.put($type, $formFieldDoc))
104 104   #end
105 - (% id="canvas" %)
106 - (((
107 - (% class="hint" %)
108 - $services.localization.render('platform.appwithinminutes.classEditorCanvasHint')
109 -
110 - #set($unknownFields = [])
111 - #set($empty = true)
112 - #foreach ($field in $doc.getxWikiClass().properties)
113 - #set($formFieldDoc = $propertyType2FormField.get($field.classType))
114 - #if($formFieldDoc)
115 - #set($empty = false)
116 - * (((#displayField($field $formFieldDoc))))
117 - #else
118 - #set($discard = $unknownFields.add($field))
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
119 119   #end
120 - #end
121 - #if(!$empty)
122 - ## Leave an empty line to separate the blocks.
123 -
124 - #end
125 - ##
126 - (% class="hidden" %)
127 - {{html}}
139 + </ul>
140 + <div class="hidden">
128 128   ## Output the field meta data even if the field is not supported to preserve it when the class is saved.
129 - #foreach($field in $unknownFields)
142 + #foreach ($field in $unknownFields)
130 130   #displayFieldMetaData($field)
131 131   #end
132 - {{/html}}
133 - )))
145 + </div>
146 + </div>
134 134  #end
135 135  
136 136  #**
137 137   * Display the options to create/update the class template, the class sheet and the class translation bundle.
138 138   *#
139 -#macro(displayClassOptions)
140 - #set($className = $stringtool.removeEnd($doc.name, 'Class'))
141 - #set($templateName = "${className}Template")
142 - #set($translationsName = "${className}Translations")
143 - #set($classSheets = $services.sheet.getClassSheets($doc))
144 - #if($classSheets.isEmpty())
145 - #set($sheetName = "${className}Sheet")
146 - #elseif($classSheets.size() == 1)
147 - #set($sheetName = $services.model.serialize($classSheets.get(0)))
152 +#macro (displayClassOptions)
153 + #set ($className = $stringtool.removeEnd($doc.fullName, 'Class'))
154 + #set ($templateReference = $services.model.resolveDocument("${className}Template"))
155 + #set ($translationsReference = $services.model.resolveDocument("${className}Translations"))
156 + #set ($classSheets = $services.sheet.getClassSheets($doc))
157 + #set ($sheetReference = $null)
158 + #if ($classSheets.isEmpty())
159 + #set ($sheetReference = $services.model.resolveDocument("${className}Sheet"))
160 + #elseif ($classSheets.size() == 1)
161 + #set ($sheetReference = $classSheets.get(0))
148 148   #end
149 - {{html wiki="true"}}
150 - ## Hide the options if neither the sheet nor the template nor the translation bundle exists. They don't have to be updated, they have to be created.
151 - (% id="options" #if(!$xwiki.exists($sheetName) && !$xwiki.exists($templateName) && !$xwiki.exists($translationsName))class="hidden" #end%)
152 - ; <label for="updateClassTemplate"><input type="checkbox" id="updateClassTemplate" name="updateClassTemplate" checked="checked" />$services.localization.render('platform.appwithinminutes.classEditorUpdateTemplateLabel')</label>
153 - : (% class="xHint" %)$services.localization.render('platform.appwithinminutes.classEditorUpdateTemplateHint', "[[$templateName]]")
154 - ; <label for="updateClassSheet"><input type="checkbox" id="updateClassSheet" name="updateClassSheet" #if($sheetName)checked="checked" #{else}disabled="disabled" #end/>$services.localization.render('platform.appwithinminutes.classEditorUpdateSheetLabel')</label>
155 - : #if($sheetName)
156 - (% class="xHint" %)$services.localization.render('platform.appwithinminutes.classEditorUpdateSheetHint', "[[$sheetName]]")
163 + ## Hide the options if neither the sheet nor the template nor the translation bundle exists. They don't have to be
164 + ## updated, they have to be created.
165 + <dl id="options" #if (!$xwiki.exists($sheetReference) && !$xwiki.exists($templateReference)
166 + && !$xwiki.exists($translationsReference))class="hidden"#end>
167 + <dt>
168 + <label for="updateClassTemplate">
169 + <input type="checkbox" id="updateClassTemplate" name="updateClassTemplate" checked="checked" />
170 + $services.localization.render('platform.appwithinminutes.classEditorUpdateTemplateLabel')
171 + </label>
172 + </dt>
173 + <dd>
174 + <span class="xHint">
175 + $services.localization.render('platform.appwithinminutes.classEditorUpdateTemplateHint',
176 + ["#pageLink($templateReference)"])
177 + </span>
178 + </dd>
179 + <dt>
180 + <label for="updateClassSheet">
181 + <input type="checkbox" id="updateClassSheet" name="updateClassSheet"
182 + #if ($sheetReference)checked="checked" #{else}disabled="disabled" #end/>
183 + $services.localization.render('platform.appwithinminutes.classEditorUpdateSheetLabel')
184 + </label>
185 + </dt>
186 + <dd>
187 + #if ($sheetReference)
188 + <span class="xHint">
189 + $services.localization.render('platform.appwithinminutes.classEditorUpdateSheetHint',
190 + ["#pageLink($sheetReference)"])
191 + </span>
157 157   #else
158 - (% class="warningmessage" %)$services.localization.render('platform.appwithinminutes.classEditorMultipleSheetsWarning')
193 + <span class="warningmessage">
194 + $services.localization.render('platform.appwithinminutes.classEditorMultipleSheetsWarning')
195 + </span>
159 159   #end
160 - ; <label for="updateClassTranslations"><input type="checkbox" id="updateClassTranslations" name="updateClassTranslations" checked="checked" />$services.localization.render('platform.appwithinminutes.classEditorUpdateTranslationsLabel')</label>
161 - : (% class="xHint" %)$services.localization.render('platform.appwithinminutes.classEditorUpdateTranslationsHint', "[[$translationsName]]")
162 - {{/html}}
197 + </dd>
198 + <dt>
199 + <label for="updateClassTranslations">
200 + <input type="checkbox" id="updateClassTranslations" name="updateClassTranslations" checked="checked" />
201 + $services.localization.render('platform.appwithinminutes.classEditorUpdateTranslationsLabel')
202 + </label>
203 + </dt>
204 + <dd>
205 + <span class="xHint">
206 + $services.localization.render('platform.appwithinminutes.classEditorUpdateTranslationsHint',
207 + ["#pageLink($translationsReference)"])
208 + </span>
209 + </dd>
210 + </dl>
163 163  #end
164 164  
213 +#macro (pageLink $reference)
214 + #set ($class = 'wikilink')
215 + #set ($action = 'view')
216 + #set ($params = {})
217 + #if (!$xwiki.exists($reference))
218 + #set ($class = 'wikicreatelink')
219 + #set ($action = 'create')
220 + #set ($discard = $params.put('parent', $doc.fullName))
221 + #end
222 + <span class="$class"><a href="$escapetool.xml($xwiki.getURL($reference, $action, $escapetool.url($params)))"
223 + >$escapetool.xml($reference.name)</a></span>##
224 +#end
225 +
165 165  #**
166 166   * Display a form field.
167 167   *#
168 -#macro(displayField $field $formFieldDoc)
169 - #if($formFieldDoc.getObject('XWiki.StyleSheetExtension'))
170 - #set($discard = $xwiki.ssx.use($formFieldDoc.fullName))
229 +#macro (displayField $field $formFieldDoc)
230 + #if ($formFieldDoc.getObject('XWiki.StyleSheetExtension'))
231 + #set ($discard = $xwiki.ssx.use($formFieldDoc.fullName))
171 171   #end
172 - #if($formFieldDoc.getObject('XWiki.JavaScriptExtension'))
173 - #set($discard = $xwiki.jsx.use($formFieldDoc.fullName))
233 + #if ($formFieldDoc.getObject('XWiki.JavaScriptExtension'))
234 + #set ($discard = $xwiki.jsx.use($formFieldDoc.fullName))
174 174   #end
175 - (% class="hidden" %)
176 - {{html}}
236 + <div class="hidden">
177 177   #displayFieldMetaData($field)
178 178   ## We need this information to avoid querying and loading all FormField documents twice.
179 179   ## NOTE: We use a different ID format to avoid collisions with the field meta properties.
180 - <input type="hidden" id="template-$field.name" name="template-$field.name" value="$escapetool.xml($formFieldDoc.fullName)" />
181 - {{/html}}
182 -
183 - #set($className = $stringtool.removeEnd($doc.name, 'Class'))
184 - #set($templateRef = $services.model.createDocumentReference($doc.wiki, $doc.space, "${className}Template"))
185 - #set($templateDoc = $xwiki.getDocument($templateRef))
240 + <input type="hidden" id="template-$field.name" name="template-$field.name"
241 + value="$escapetool.xml($formFieldDoc.fullName)"
242 + data-propertyName="$escapetool.xml($formFieldDoc.getxWikiClass().propertyNames[0])" />
243 + </div>
244 + #set ($className = $stringtool.removeEnd($doc.fullName, 'Class'))
245 + #set ($templateRef = $services.model.resolveDocument("${className}Template"))
246 + #set ($templateDoc = $xwiki.getDocument($templateRef))
186 186   ## Simulate the editing of the class instance from the template document.
187 187   ## Note that we can't simply call display on the template document because $field could be a new field that hasn't
188 188   ## been added to the class yet (so the object from the template doesn't have this field yet).
189 - (% class="field-viewer" %)
190 - #displayFieldProperty($field "${doc.fullName}_0_" $templateDoc.getObject($doc.fullName, true))
191 -
192 - #set($propertyNames = ['name', 'prettyName', 'number', 'required', 'hint'])
193 - #set($formFieldObj = $formFieldDoc.getObject('AppWithinMinutes.FormFieldClass'))
194 - #set($customPropertyNames = $formFieldObj.getProperty('properties').value.split('\s+'))
195 - #set($discard = $customPropertyNames.removeAll($propertyNames))
196 - #set($discard = $propertyNames.addAll($customPropertyNames.subList(0, $customPropertyNames.size())))
197 - (% class="field-config" %)
198 - #foreach($propertyName in $propertyNames)
199 - #set($propertyDefinition = $field.xWikiClass.get($propertyName))
200 - #if($propertyDefinition)
201 - #displayFieldProperty($propertyDefinition "field-${field.name}_" $field)
250 + <dl class="field-viewer">
251 + #displayFieldProperty($field "${doc.fullName}_0_" $templateDoc.getObject($doc.fullName, true))
252 + </dl>
253 + #set ($propertyNames = ['name', 'prettyName', 'number', 'required', 'hint'])
254 + #set ($formFieldObj = $formFieldDoc.getObject('AppWithinMinutes.FormFieldClass'))
255 + #set ($customPropertyNames = $formFieldObj.getProperty('properties').value.split('\s+'))
256 + #set ($discard = $customPropertyNames.removeAll($propertyNames))
257 + #set ($discard = $propertyNames.addAll($customPropertyNames.subList(0, $customPropertyNames.size())))
258 + <dl class="field-config">
259 + #foreach ($propertyName in $propertyNames)
260 + #set ($propertyDefinition = $field.xWikiClass.get($propertyName))
261 + #if ($propertyDefinition)
262 + #displayFieldProperty($propertyDefinition "field-${field.name}_" $field)
263 + #end
202 202   #end
203 - #end
265 + </dl>
204 204  #end
205 205  
206 206  #**
207 207   * Display the field meta data. This is needed to preserve the field when its type is not supported by the editor.
208 208   *#
209 -#macro(displayFieldMetaData $field)
271 +#macro (displayFieldMetaData $field)
210 210   <input type="hidden" id="type-$field.name" name="type-$field.name" value="$field.classType" />
211 211  #end
212 212  
... ... @@ -213,13 +213,18 @@
213 213  #**
214 214   * Displays a configuration property of a class field. This macro can also be used to display a property of an object.
215 215   *#
216 -#macro(displayFieldProperty $property $prefix $field)
217 - #set($displayFormType = $property.getProperty('displayFormType'))
218 - #if($property.classType == 'Boolean' && (!$displayFormType || $displayFormType.value == 'checkbox'))
219 - ; {{html clean="false"}}<label for="$!{prefix}$property.name">#displayPropertyEditInput($property, $prefix, $field)$escapetool.xml($property.prettyName)</label>{{/html}}
278 +#macro (displayFieldProperty $property $prefix $field)
279 + #set ($displayFormType = $property.getProperty('displayFormType'))
280 + #if ($property.classType == 'Boolean' && (!$displayFormType || $displayFormType.value == 'checkbox'))
281 + <dt>
282 + <label for="$!{prefix}$property.name">
283 + #displayPropertyEditInput($property, $prefix, $field)$escapetool.xml($property.prettyName)
284 + </label>
285 + </dt>
286 + <dd></dd>
220 220   #else
221 - ; {{html}}<label for="${prefix}$property.name">$escapetool.xml($property.prettyName)</label>{{/html}}
222 - : {{html clean="false"}}#displayPropertyEditInput($property, $prefix, $field){{/html}}
288 + <dt><label for="${prefix}$property.name">$escapetool.xml($property.prettyName)</label></dt>
289 + <dd>#displayPropertyEditInput($property, $prefix, $field)</dd>
223 223   #end
224 224  #end
225 225  
... ... @@ -226,12 +226,18 @@
226 226  #**
227 227   * Displays the input used to edit the specified property of the given object. The given object can be either an
228 228   * instance of an XWiki class or a class field. In the first case the property represents an object field and in the
229 - * second case the property represents a field meta property.
296 + * second case the property represents a field meta property. We currently don't use custom display for metaproperty,
297 + * so in that case we fallback on displayEdit.
230 230   *#
231 -#macro(displayPropertyEditInput $property $prefix $object)
232 - #set($wrappedProperty = $property.propertyClass)
233 - #if($wrappedProperty.isCustomDisplayed($xcontext.context))
234 - $xcontext.get('propertyCustomDisplayer').display($property, $prefix, $object)
299 +#macro (displayPropertyEditInput $property $prefix $object)
300 + #set ($wrappedProperty = $property.propertyClass)
301 + #if ($wrappedProperty.isCustomDisplayed($xcontext.context))
302 + #set ($customDisplayer = $!xcontext.get('propertyCustomDisplayer').display($property, $prefix, $object))
303 + #if ((! $customDisplayer) && ("$!customDisplayer" == ""))
304 + $doc.displayEdit($property, $prefix, $object)
305 + #else
306 + $customDisplayer
307 + #end
235 235   #else
236 236   $doc.displayEdit($property, $prefix, $object)
237 237   #end
... ... @@ -240,22 +240,23 @@
240 240  #**
241 241   * Called when a new form field is added via AJAX.
242 242   *#
243 -#macro(displayNewField)
316 +#macro (displayNewField)
244 244   ## Output the SkinExtension hooks to allow field displayers to pull JavaScript/CSS resources.
318 + ## Output also the LinkExtension hook because $xwiki.linkx.use() is used to load CSS files from WebJars.
245 245   ## The class editor moves this resource includes in the HTML page head.
246 - {{html}}
320 + <!-- com.xpn.xwiki.plugin.skinx.LinkExtensionPlugin -->
247 247   #skinExtensionHooks
248 - {{/html}}
249 -
250 - #set($formFieldDoc = $xwiki.getDocument($request.field))
251 - #set($formFieldDocClassFields = $formFieldDoc.getxWikiClass().getXWikiClass().properties)
252 - #if($formFieldDocClassFields.size() > 0)
322 + #set ($formFieldDoc = $xwiki.getDocument($request.field))
323 + #set ($formFieldDocClassFields = $formFieldDoc.getxWikiClass().getXWikiClass().properties)
324 + #if ($formFieldDocClassFields.size() > 0)
253 253   ## Clone the field template.
254 - #set($field = $formFieldDocClassFields.get(0).clone())
255 - #if("$!field.prettyName" == '')
256 - #set($discard = $field.setPrettyName($formFieldDoc.title))
326 + #set ($field = $formFieldDocClassFields.get(0).clone())
327 + #if ("$!field.prettyName" == '')
328 + #set ($discard = $field.setPrettyName($formFieldDoc.title))
257 257   #end
258 - #set($discard = $doc.getxWikiClass().getXWikiClass().addField($field.name, $field))
330 + #set ($xclass = $doc.getxWikiClass().getXWikiClass())
331 + #set ($discard = $xclass.addField($field.name, $field))
332 + #set ($discard = $field.setObject($xclass))
259 259   #displayField($doc.getxWikiClass().get($field.name) $formFieldDoc)
260 260   #else
261 261   Unsupported form field.
... ... @@ -263,93 +263,113 @@
263 263  #end
264 264  
265 265  #**
266 - * Preview a class field.
340 + * Preview a class field (requires Programming Right).
267 267   *#
268 -#macro(previewField)
342 +#macro (previewField)
269 269   ## Find the request parameter that specifies the field template.
270 - #foreach($paramName in $request.getParameterMap().keySet())
271 - #if($paramName.startsWith('template-'))
272 - #set($fieldName = $paramName.substring(9))
273 - #set($fieldTemplateDoc = $xwiki.getDocument($request.getParameter($paramName)))
344 + #foreach ($paramName in $request.getParameterMap().keySet())
345 + #if ($paramName.startsWith('template-'))
346 + #set ($fieldName = $paramName.substring(9))
347 + #set ($fieldTemplateDoc = $xwiki.getDocument($request.getParameter($paramName)))
274 274   #break
275 275   #end
276 276   #end
277 277   ##
278 278   ## Clone the field template.
279 - #set($field = $fieldTemplateDoc.getxWikiClass().getXWikiClass().properties.get(0).clone())
353 + #set ($field = $fieldTemplateDoc.getxWikiClass().getXWikiClass().properties.get(0).clone())
280 280   ##
281 281   ## Update the field meta properties based on the submitted data.
282 - #set($valuesFromRequest = $xcontext.context.getForm().getObject("field-$fieldName"))
283 - #set($discard = $field.getxWikiClass().fromMap($valuesFromRequest, $field))
356 + #set ($valuesFromRequest = $xcontext.context.getForm().getObject("field-$fieldName"))
357 + #set ($discard = $field.getxWikiClass().fromMap($valuesFromRequest, $field))
284 284   ##
285 285   ## Don't rename the field (ignore the submitted name).
286 - #set($discard = $field.setName($fieldName))
360 + #set ($discard = $field.setName($fieldName))
287 287   ##
288 288   ## We have to add the field to the class before setting its value.
289 289   ## (otherwise the field value from the request is ignored).
290 - #set($xclass = $doc.getxWikiClass().getXWikiClass())
291 - #set($discard = $xclass.addField($fieldName, $field))
364 + #set ($xclass = $doc.getxWikiClass().getXWikiClass())
365 + #set ($discard = $xclass.addField($fieldName, $field))
366 + #set ($discard = $field.setObject($xclass))
292 292   ##
293 293   ## Create an object that has this field and set its value from request.
294 - #set($object = $fieldTemplateDoc.getObject($doc.fullName, true))
369 + #set ($object = $fieldTemplateDoc.getObject($doc.fullName, true))
295 295   ##
296 296   ## Filter empty values from the request, otherwise the update method could try to select an invalid value.
297 - #set($values = [])
298 - #foreach($value in $request.getParameterValues("${doc.fullName}_0_$fieldName"))
299 - #if($value != '')
300 - #set($discard = $values.add($value))
372 + #set ($values = [])
373 + #foreach ($value in $request.getParameterValues("${doc.fullName}_0_$fieldName"))
374 + #if ($value != '')
375 + #set ($discard = $values.add($value))
301 301   #end
302 302   #end
303 - #if($values.size() > 0)
304 - #set($stringArray = $request.getParameterValues("template-$fieldName"))
305 - #set($discard = $xclass.fromMap({$fieldName: $values.toArray($stringArray)}, $object.getXWikiObject()))
378 + #if ($values.size() > 0)
379 + #set ($stringArray = $request.getParameterValues("template-$fieldName"))
380 + #set ($discard = $xclass.fromMap({$fieldName: $values.toArray($stringArray)}, $object.getXWikiObject()))
306 306   #end
307 307   ##
308 308   ## Display the field.
309 - #set($field = $doc.getxWikiClass().get($fieldName))
310 - {{html clean="false"}}#displayPropertyEditInput($field, "${doc.fullName}_0_", $object){{/html}}
384 + #set ($field = $doc.getxWikiClass().get($fieldName))
385 + #displayPropertyEditInput($field, "${doc.fullName}_0_", $object)
311 311  #end
312 312  
313 313  #**
314 314   * Display the edit class form.
315 315   *#
316 -#macro(displayEditForm)
317 - $xwiki.jsfx.use('js/scriptaculous/dragdrop.js')##
318 - $xwiki.jsx.use('AppWithinMinutes.ClassEditSheet')##
319 - $xwiki.ssx.use('AppWithinMinutes.ClassEditSheet')##
320 - $xwiki.ssx.use('AppWithinMinutes.ClassSheetGenerator')##
321 - #if("$!request.wizard" == 'true')
322 - #appWizardHeader(2)
323 -
391 +#macro (displayEditForm)
392 + #set ($discard = $xwiki.jsx.use('AppWithinMinutes.ClassEditSheet'))
393 + #set ($discard = $xwiki.ssx.use('AppWithinMinutes.ClassEditSheet'))
394 + #set ($discard = $xwiki.ssx.use('AppWithinMinutes.ClassSheetGenerator'))
395 + #if ("$!request.wizard" == 'true')
396 + #appWizardHeader('structure')
324 324   #end
325 325   #displayFieldPalette()
326 326   #displayFieldCanvas()
327 327   #displayClassOptions()
328 328   #if("$!request.wizard" == 'true')
329 -
330 - #appWizardFooter(2)
402 + #appWizardFooter('structure')
331 331   #end
332 - (% class="clearfloats" %)((()))
404 + <div class="clearfloats"></div>
333 333  #end
334 334  
335 335  #**
336 336   * Displays either the edit class form or a new form field. The later is used when adding a new form field via AJAX.
337 337   *#
338 -#macro(doEdit)
339 - #if("$!request.field" != '')
410 +#macro (doEdit)
411 + #if ("$!request.field" != '')
340 340   #displayNewField()
341 - #elseif("$!request.preview" == 'true')
413 + #elseif ("$!request.preview" == 'true')
342 342   #previewField()
343 343   #else
344 344   ## Make sure that only the sheet content is rendered when the class is saved using AJAX.
345 - (% class="hidden" %)
346 - {{html}}<input type="hidden" name="xpage" value="plain" />{{/html}}
347 -
417 + <div class="hidden">
418 + <input type="hidden" name="xpage" value="plain" />
419 + #if ($request.wizard == 'true')
420 + ## Preserve the wizard mode.
421 + <input type="hidden" name="wizard" value="true" />
422 + #end
423 + ## Compute the application title to be used as the wizard step title.
424 + #getAppTitle
425 + </div>
348 348   #displayEditForm()
349 349   #end
350 350  #end
351 351  
352 352  #**
431 + * Create the home page of the application code space, if it doesn't exist already.
432 + *#
433 +#macro (maybeCreateCodeSpace)
434 + #set ($codeHomePageReference = $services.model.resolveDocument('', 'default', $doc.documentReference.parent))
435 + #if (!$xwiki.exists($codeHomePageReference))
436 + #set ($codeSpaceTemplate = $services.model.resolveDocument('AppWithinMinutes.CodeSpaceTemplate'))
437 + #set ($copyAsJob = $services.refactoring.copyAs($codeSpaceTemplate, $codeHomePageReference))
438 + #try()
439 + #set ($discard = $copyAsJob.join())
440 + #set ($copyAsJobStatus = $services.job.getJobStatus($copyAsJob.request.id))
441 + #set ($errorMessage = $copyAsJobStatus.logTail.getFirstLogEvent('ERROR').toString())
442 + #end
443 + #end
444 +#end
445 +
446 +#**
353 353   * Updates and saves the class definition based on the submitted data.
354 354   *#
355 355  #macro(updateAndSaveClass)
... ... @@ -406,7 +406,7 @@
406 406   ## The field name has changed.
407 407   #if($xclass.get($field.name))
408 408   ## There is already a field with the same name.
409 - #set($errorMessage = $services.localization.render('platform.appwithinminutes.classEditorDuplicateFieldNameError', $field.name))
503 + #set($errorMessage = $services.localization.render('platform.appwithinminutes.classEditorDuplicateFieldNameError', [$field.name]))
410 410   #break
411 411   #else
412 412   #set($discard = $xclass.removeField($fieldName))
... ... @@ -444,11 +444,12 @@
444 444   ## FIXME: even if it is not a good practice to have an object in the class document, it is still possible. We should handle field renames for the class document
445 445   ## as well. Note that there is a possibility that objects in the class' document are automatically updated. Needs checking.
446 446   ##
447 - #set($instancesStatement = "from doc.object($doc.fullName) as obj where doc.fullName not in (:className,:templateName)")
448 - #set($className = $stringtool.removeEnd($doc.name, 'Class'))
449 - #set($templateRef = $services.model.createDocumentReference($doc.wiki, $doc.space, "${className}Template"))
450 - #set($templateFullName = $services.model.serialize($templateRef, 'local'))
451 - #set($instancesQuery = $services.query.xwql($instancesStatement).bindValue('className', $doc.fullName).bindValue('templateName', $templateFullName))
541 + ## We use HQL because XWQL doesn't allow us to escape the special characters from the class name.
542 + #set($instancesStatement = ', BaseObject as obj where doc.fullName = obj.name and obj.className = :className'
543 + + ' and doc.fullName not in (:className, :templateName)')
544 + #set($className = $stringtool.removeEnd($doc.fullName, 'Class'))
545 + #set($instancesQuery = $services.query.hql($instancesStatement).bindValue('className', $doc.fullName).bindValue(
546 + 'templateName', "${className}Template"))
452 452   #foreach($instanceDocName in $instancesQuery.execute())
453 453   #set($instanceDoc = $xwiki.getDocument($instanceDocName))
454 454   #set($discard = $instanceDoc.document.renameProperties($doc.documentReference, $fieldsToRename))
... ... @@ -455,21 +455,17 @@
455 455   #set($discard = $instanceDoc.save($services.localization.render('core.comment.updateClassPropertyName'), true))
456 456   #end
457 457   #end
458 - ##
459 - ## Clear cache.
460 - ##
461 - #if(!$errorMessage)
462 - #set($discard = $xwiki.getXWiki().flushCache($xcontext.context))
463 - #end
464 464  #end
465 465  
466 466  #**
467 - * Handle Date fields that have the "Empty is today" option checked in the class edit form. See http://jira.xwiki.org/browse/XWIKI-10296
556 + * Handle Date fields that have the "Empty is today" option checked in the class edit form.
557 + * See https://jira.xwiki.org/browse/XWIKI-10296
468 468   **#
469 469  #macro(handleEmptyIsTodayDateFields $templateDoc)
470 470   #foreach($property in $doc.xWikiClass.properties)
471 - ## We check directly on the request if the user provided an empty date. We can not check from the template document's object that we've just
472 - ## parsed from the request using the updateObjectFromRequest method because it already applies the emtpyIsToday mechanism and that would not be good for us.
561 + ## We check directly on the request if the user provided an empty date. We can not check from the template
562 + ## document's object that we've just parsed from the request using the updateObjectFromRequest method because it
563 + ## already applies the emtpyIsToday mechanism and that would not be good for us.
473 473   #set($newValueRequestParameterName = "${doc.fullName}_0_${property.name}")
474 474   #set($newDateStringValue = "$!{request.getParameter($newValueRequestParameterName)}")
475 475   #if($property.classType == 'Date' && $property.getValue('emptyIsToday') == 1 && $newDateStringValue == '')
... ... @@ -483,10 +483,10 @@
483 483   *#
484 484  #macro(updateAndSaveTemplate)
485 485   #if(!$errorMessage && $request.updateClassTemplate)
486 - #set($className = $stringtool.removeEnd($doc.name, 'Class'))
487 - #set($templateRef = $services.model.createDocumentReference($doc.wiki, $doc.space, "${className}Template"))
577 + #set($className = $stringtool.removeEnd($doc.fullName, 'Class'))
578 + #set($templateRef = $services.model.resolveDocument("${className}Template"))
488 488   #set($templateDoc = $xwiki.getDocument($templateRef))
489 - #set($discard = $templateDoc.setParent($doc.name))
580 + #set($discard = $templateDoc.setParent($doc.documentReference.name))
490 490   #if ($request.templateTitle)
491 491   #set($discard = $templateDoc.setTitle($request.templateTitle))
492 492   #end
... ... @@ -500,7 +500,9 @@
500 500   ##
501 501   #handleEmptyIsTodayDateFields($templateDoc)
502 502   #set($discard = $templateDoc.setHidden(true))
503 - #set($discard = $templateDoc.save($services.localization.render('platform.appwithinminutes.classEditorTemplateSaveComment'), $minorEdit))
594 + #set($discard = $templateDoc.save(
595 + $services.localization.render('platform.appwithinminutes.classEditorTemplateSaveComment'),
596 + $minorEdit))
504 504   #end
505 505  #end
506 506  
... ... @@ -511,10 +511,11 @@
511 511   #if(!$errorMessage && $request.updateClassSheet)
512 512   #set($classSheets = $services.sheet.getClassSheets($doc))
513 513   #if($classSheets.isEmpty())
514 - #set($className = $stringtool.removeEnd($doc.name, 'Class'))
515 - #set($sheetReference = $services.model.createDocumentReference($doc.wiki, $doc.space, "${className}Sheet"))
607 + #set($className = $stringtool.removeEnd($doc.fullName, 'Class'))
608 + #set($sheetReference = $services.model.resolveDocument("${className}Sheet"))
516 516   #set($discard = $services.sheet.bindClassSheet($doc, $sheetReference))
517 - #set($discard = $doc.save($services.localization.render('platform.appwithinminutes.classEditorBindSheetSaveComment'), $minorEdit))
610 + #set($discard = $doc.save($services.localization.render('platform.appwithinminutes.classEditorBindSheetSaveComment'),
611 + $minorEdit))
518 518   #elseif($classSheets.size() == 1)
519 519   #set($sheetReference = $classSheets.get(0))
520 520   #end
... ... @@ -521,10 +521,16 @@
521 521   #if($sheetReference)
522 522   #set($sheetDoc = $xwiki.getDocument($sheetReference))
523 523   #set($sheetGeneratorDoc = $xwiki.getDocument('AppWithinMinutes.ClassSheetGenerator'))
524 - #set($discard = $sheetDoc.setParent($doc.name))
525 - #set($discard = $sheetDoc.setContent($doc.getRenderedContent($sheetGeneratorDoc.content, $sheetGeneratorDoc.syntax.toIdString(), 'plain/1.0')))
618 + #set($discard = $sheetDoc.setParent($doc.documentReference.name))
619 + #set($discard = $sheetDoc.setContent($doc.getRenderedContent($sheetGeneratorDoc.content,
620 + $sheetGeneratorDoc.syntax.toIdString(), 'plain/1.0')))
621 + ## We assume for now that the output produced by the sheet generator uses the same syntax as the code of the sheet
622 + ## generator. We have to set the syntax because the default wiki syntax (used when creating new wiki pages) could
623 + ## be different than the one used by the sheet generator.
624 + #set($discard = $sheetDoc.setSyntax($sheetGeneratorDoc.syntax))
526 526   #set($discard = $sheetDoc.setHidden(true))
527 - #set($discard = $sheetDoc.save($services.localization.render('platform.appwithinminutes.classEditorSheetSaveComment'), $minorEdit))
626 + #set($discard = $sheetDoc.save($services.localization.render('platform.appwithinminutes.classEditorSheetSaveComment'),
627 + $minorEdit))
528 528   #end
529 529   #end
530 530  #end
... ... @@ -534,19 +534,24 @@
534 534   *#
535 535  #macro(updateAndSaveTranslations)
536 536   #if(!$errorMessage && $request.updateClassTranslations)
537 - #set($className = $stringtool.removeEnd($doc.name, 'Class'))
538 - #set($translationsRef = $services.model.createDocumentReference($doc.wiki, $doc.space, "${className}Translations"))
637 + #set($className = $stringtool.removeEnd($doc.fullName, 'Class'))
638 + #set($translationsRef = $services.model.resolveDocument("${className}Translations"))
539 539   #set($translationsDoc = $xwiki.getDocument($translationsRef))
540 540   #set($translationsObj = $translationsDoc.getObject('XWiki.TranslationDocumentClass', true))
541 - ## We use the translation bundle on demand because none of the available scopes suits our needs. Simple users can't
542 - ## register document translation bundles at WIKI level and the SPACE scope doesn't remove the need to create a
543 - ## custom live table results page in the same space as the application.
544 - #set($discard = $translationsObj.set('scope', 'ON_DEMAND'))
545 - #set($discard = $translationsDoc.setParent($doc.name))
641 + #set ($scope = 'USER')
642 + #if ($services.security.authorization.hasAccess('admin', $doc.documentReference.wikiReference))
643 + #set ($scope = 'WIKI')
644 + #end
645 + #set($discard = $translationsObj.set('scope', $scope))
646 + #set($discard = $translationsDoc.setParent($doc.documentReference.name))
546 546   #set($translationsGeneratorDoc = $xwiki.getDocument('AppWithinMinutes.ClassTranslationsGenerator'))
547 - #set($discard = $translationsDoc.setContent($doc.getRenderedContent($translationsGeneratorDoc.content, $translationsGeneratorDoc.syntax.toIdString(), 'plain/1.0')))
648 + #set($discard = $translationsDoc.setContent($doc.getRenderedContent($translationsGeneratorDoc.content,
649 + $translationsGeneratorDoc.syntax.toIdString(), 'plain/1.0')))
650 + #set($discard = $translationsDoc.setSyntaxId('plain/1.0'))
548 548   #set($discard = $translationsDoc.setHidden(true))
549 - #set($discard = $translationsDoc.save($services.localization.render('platform.appwithinminutes.classEditorTranslationsSaveComment'), $minorEdit))
652 + #set($discard = $translationsDoc.save(
653 + $services.localization.render('platform.appwithinminutes.classEditorTranslationsSaveComment'),
654 + $minorEdit))
550 550   #end
551 551  #end
552 552  
... ... @@ -553,35 +553,38 @@
553 553  #**
554 554   * Updates and saves the class definition, the class sheet and the class template.
555 555   *#
556 -#macro(doSave)
557 - #set($minorEdit = "$!request.minorEdit" != '')
558 - #updateAndSaveClass()
559 - #updateAndSaveTemplate()
560 - #updateAndSaveSheet()
561 - #updateAndSaveTranslations()
562 - #if($action == 'save')
563 - #if($errorMessage)
564 - {{error}}{{html}}$errorMessage{{/html}}{{/error}}
565 - #elseif("$!request.wizard" == 'true')
661 +#macro (doSave)
662 + #set ($minorEdit = "$!request.minorEdit" != '')
663 + #maybeCreateCodeSpace
664 + #updateAndSaveClass
665 + #updateAndSaveTemplate
666 + #updateAndSaveSheet
667 + #updateAndSaveTranslations
668 + #if ($action == 'save')
669 + #if ($errorMessage)
670 + <div class="box errormessage">$errorMessage</div>
671 + #elseif ("$!request.wizard" == 'true')
566 566   ## Redirect to next wizard step.
567 - #set($appName = $doc.getValue('dataSpaceName'))
568 - #if("$!appName" == '')
569 - ## Backwards compatibility for apps created before 6.3M2 when the code space was not properly cleaned and the data space name was restricted as a consequence.
570 - #set($appName = $stringtool.removeEnd($doc.title, ' Class'))
673 + #set ($className = $stringtool.removeEnd($doc.fullName, 'Class'))
674 + #set ($templateProviderReference = $services.model.resolveDocument("${className}TemplateProvider"))
675 + #set ($queryString = {
676 + 'wizard': true,
677 + 'sheet': 'AppWithinMinutes.TemplateProviderEditSheet'
678 + })
679 + #if (!$xwiki.exists($templateProviderReference))
680 + #set ($discard = $queryString.putAll({
681 + 'form_token': $services.csrf.getToken(),
682 + 'template': 'XWiki.TemplateProviderTemplate',
683 + 'parent': $doc.fullName
684 + }))
571 571   #end
572 - #set($homePageRef = $services.model.createDocumentReference($doc.wiki, $appName, 'WebHome'))
573 - #set($queryString = 'wizard=true')
574 - #if(!$xwiki.exists($homePageRef))
575 - #set($homePageTitle = '$services.localization.render(''platform.appwithinminutes.appHomePageTitle'', [$doc.space])')
576 - #set($queryString = "$queryString&editor=inline&template=AppWithinMinutes.LiveTableTemplate&AppWithinMinutes.LiveTableClass_0_class=$escapetool.url($doc.fullName)&title=$escapetool.url($homePageTitle)&parent=AppWithinMinutes.WebHome")
577 - #end
578 - $response.sendRedirect($xwiki.getURL($homePageRef, 'edit', $queryString));
686 + $response.sendRedirect($xwiki.getURL($templateProviderReference, 'edit', $escapetool.url($queryString)))
579 579   #else
580 580   ## Redirect to view mode.
581 581   $response.sendRedirect($doc.getURL())
582 582   #end
583 583   #else
584 - #if($errorMessage)
692 + #if ($errorMessage)
585 585   $response.sendError(400, $errorMessage)
586 586   #else
587 587   $response.setStatus(204)
... ... @@ -597,21 +597,23 @@
597 597  {{/velocity}}
598 598  
599 599  {{velocity}}
708 +{{html clean="false"}}
600 600  ## Determine the action button that triggered the request
601 -#set($action = 'edit')
602 -#foreach($paramName in $request.getParameterMap().keySet())
603 - #if($paramName.startsWith('xaction_'))
604 - #set($action = $paramName.substring(8))
710 +#set ($action = 'edit')
711 +#foreach ($paramName in $request.getParameterMap().keySet())
712 + #if ($paramName.startsWith('xaction_'))
713 + #set ($action = $paramName.substring(8))
605 605   #break
606 606   #end
607 607  #end
608 -#if($action == 'edit')
717 +#if ($action == 'edit')
609 609   #doEdit()
610 -#elseif($action == 'save' || $action == 'saveandcontinue')
611 - #if($services.csrf.isTokenValid($request.form_token))
719 +#elseif ($action == 'save' || $action == 'saveandcontinue')
720 + #if ($services.csrf.isTokenValid($request.form_token))
612 612   #doSave()
613 613   #else
614 - $response.sendRedirect($services.csrf.getResubmissionURL());
723 + $response.sendRedirect($services.csrf.getResubmissionURL())
615 615   #end
616 616  #end
726 +{{/html}}
617 617  {{/velocity}}
XWiki.JavaScriptExtension[2]
Código
... ... @@ -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);
... ... @@ -511,15 +511,11 @@
511 511  }(XWiki || {}));
512 512  
513 513  (function() {
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;
518 + function initForm(form) {
519 + // Let the sheet handle the form submit. The form is submitted by default to the preview action which dispatches the
520 + // request to the save action if the save button is detected on the request parameters. By submitting to the edit
521 + // action the edit sheet is evaluated and thus it can handle the save by itself.
522 + form.action = XWiki.currentDocument.getURL('edit');
523 523  
524 524   // Apply the vertical form layout standard.
525 525   form.addClassName('xform');
... ... @@ -553,8 +553,58 @@
553 553   // Make the palette and the canvas live.
554 554   new XWiki.FormFieldPalette('palette');
555 555   new XWiki.FormCanvas('canvas');
556 + }
556 556  
557 - return true;
558 + function init() {
559 + var form = $('inline');
560 + if (form) {
561 + require(['scriptaculous/dragdrop'], function() {
562 + initForm(form);
563 + });
564 + }
565 + return form;
558 558   }
567 +
559 559   (XWiki.domIsLoaded && init()) || document.observe('xwiki:dom:loaded', init);
560 560  }).call();
570 +
571 +require(['jquery', 'xwiki-events-bridge'], function($) {
572 + $(document).on('xwiki:class:displayField xwiki:class:previewField', function(event, data) {
573 + var container = $(data.field.getContainer());
574 + if (container.attr('data-new') === 'true') {
575 + // We can't suggest property values for properties that don't exist yet (have not been saved) so we provide
576 + // suggestions for the template property that was used to create them. Note that the suggested values depend on
577 + // the saved property meta data so changing the property (field) meta data may not affect the suggestions until
578 + // those changes are saved.
579 + var templateHiddenInput = container.find('#' + 'template-' + data.field.getName());
580 + var propertyValueSuggester = container.find('.field-viewer .suggest-propertyValues').first();
581 + propertyValueSuggester.attr({
582 + 'data-className': templateHiddenInput.val(),
583 + 'data-propertyName': templateHiddenInput.attr('data-propertyName')
584 + });
585 + }
586 + }).on('xwiki:document:saved', function(event) {
587 + // We need to update the property value suggesters because:
588 + // * newly saved properties should have their own suggestions instead of relying on the template property
589 + // * for renamed properties we need to fetch the suggestions from a different location
590 + $('ul#fields > li').each(function() {
591 + var container = $(this);
592 + container.removeAttr('data-new');
593 + var propertyValueSuggester = container.find('.field-viewer .suggest-propertyValues').first();
594 + if (propertyValueSuggester.length > 0) {
595 + // We need to preserve the selected values because they are lost when the suggester is destroyed.
596 + var selectedValues = propertyValueSuggester.children();
597 + propertyValueSuggester[0].selectize.destroy();
598 + // Restore the selected values.
599 + propertyValueSuggester.empty().append(selectedValues);
600 + var className = XWiki.Model.serialize(XWiki.currentDocument.documentReference.relativeTo(
601 + new XWiki.WikiReference(XWiki.currentWiki)));
602 + propertyValueSuggester.attr({
603 + 'data-className': className,
604 + 'data-propertyName': propertyValueSuggester.attr('name').substr((className + '_0_').length)
605 + });
606 + propertyValueSuggester.suggestPropertyValues();
607 + }
608 + });
609 + });
610 +});
XWiki.StyleSheetExtension[1]
Código
... ... @@ -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 {