Changes for page LiveTable View Sheet

Last modified by Mark Kohlmann on 2025/01/19 06:47

From version 1.1
edited by Mark Kohlmann
on 2020/04/02 23:25
Change comment: Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui-9.4]
To version 3.1
edited by Mark Kohlmann
on 2024/07/26 08:06
Change comment: Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/16.5.0]

Summary

Details

Page properties
Author
... ... @@ -1,1 +1,1 @@
1 -XWiki.MarkKohlmann
1 +XWiki.mark\.kohlmann@chiefintegrations\.com
Content
... ... @@ -1,110 +1,217 @@
1 -{{velocity}}
2 -#set($liveTableObj = $doc.getObject('AppWithinMinutes.LiveTableClass'))
3 -#if($liveTableObj)
4 - #set($discard = $doc.use($liveTableObj))
5 - #set($discard = $xwiki.ssx.use('AppWithinMinutes.LiveTableViewSheet'))
6 - #set($discard = $xwiki.jsx.use('AppWithinMinutes.LiveTableViewSheet'))
1 +{{template name="locationPicker_macros.vm" /}}
2 +
3 +{{velocity output="false"}}
4 +#macro (displayApp)
5 + #set ($discard = $xwiki.ssx.use('AppWithinMinutes.LiveTableViewSheet'))
6 + #set ($discard = $xwiki.jsx.use('AppWithinMinutes.LiveTableViewSheet', {'currentApp': $doc.getDocumentReference()}))
7 7   #if (!$isReadOnly)
8 - ## Determine the user's rights
9 - #set($classFullName = $liveTableObj.getProperty('class').value)
10 - #set($className = $stringtool.removeEnd($classFullName, 'Class'))
11 - #set ($templateProviderReference = $services.model.resolveDocument("${className}TemplateProvider"))
12 - #set ($creationRestrictions = $xwiki.getDocument($templateProviderReference).getValue('creationRestrictions'))
13 - #if ($creationRestrictions)
14 - #if ($creationRestrictions.size() > 0)
15 - #set ($dataSpaceRef = $services.model.resolveSpace($creationRestrictions.get(0)))
16 - #else
17 - ## There is no data space as the user can create application entries anywhere. Let's use the application space
18 - ## when the user clicks on the Add New Entry link from the home page.
19 - #set ($dataSpaceRef = $doc.documentReference.parent)
20 - #end
21 - #else
22 - ## The template provider is missing. Fall-back on the old 'dataSpace' property.
23 - #set ($dataSpaceRef = $services.model.resolveSpace($liveTableObj.getValue('dataSpace'), 'explicit',
24 - $doc.documentReference))
25 - #end
26 - #set($hasCreateData = $services.security.authorization.hasAccess('edit', $dataSpaceRef))
27 - #set($hasDeleteData = $services.security.authorization.hasAccess('admin', $dataSpaceRef))
28 - #set($classRef = $services.model.resolveDocument($classFullName))
29 - #set($hasEditApplication = $services.security.authorization.hasAccess('edit', $classRef))
30 - #set($translationsRef = $services.model.resolveDocument("${className}Translations"))
31 - #set($hasEditTranslations = $xwiki.isMultiLingual() && $xwiki.exists($translationsRef)
32 - && $services.security.authorization.hasAccess('edit', $translationsRef))
33 - #set($hasDeleteApplication = $hasDeleteData
34 - && $services.security.authorization.hasAccess('admin', $doc.documentReference.parent)
35 - && $services.security.authorization.hasAccess('admin', $classRef.parent))
36 - ## Display the application actions based on the user's rights
37 - #if($hasCreateData || $hasDeleteData || $hasEditApplication || $hasEditTranslations || $hasDeleteApplication)
38 - (% id="actionBox" class="floatinginfobox" %)
39 - (((
40 - = $services.localization.render('platform.appwithinminutes.appHomePageActionsHeading') =
41 - #if($hasCreateData)
42 - * [[$services.localization.render('platform.appwithinminutes.appHomePageAddEntryHint')>>||anchor="AddNewEntry" class="action add"]]##
43 - #set($entryDoc = $services.model.resolveDocument('__entryName__', 'explicit', $dataSpaceRef))
44 - ## We need to set the title if we want to be able to sort or filter the doc.title live table column.
45 - #set ($params = {
46 - 'template': "${className}Template",
47 - 'title': '__entryName__',
48 - 'parent': $services.model.serialize($doc.documentReference, 'local')
49 - })
50 - #if ($xwiki.getDocument($classRef).xWikiClass.properties.size() > 0)
51 - ## The entry has properties so go in edit mode to edit them.
52 - #set ($action = 'edit')
53 - #set ($params.editor = 'inline')
54 - #else
55 - ## There are no properties to edit so create the new entry and get back to the home page.
56 - #set ($action = 'save')
57 - #set ($discard = $params.putAll({
58 - 'xredirect': $doc.getURL(),
59 - 'form_token': $services.csrf.token
60 - }))
61 - #end
62 - {{html}}<input type="hidden" value="$xwiki.getURL($entryDoc, $action, $escapetool.url($params))" />{{/html}}
63 - #end
64 - #if($hasEditApplication)
65 - #set ($queryString = $escapetool.url({
66 - 'appName': $doc.space,
67 - 'resolve': true
68 - }))
69 - * [[$services.localization.render('platform.appwithinminutes.appHomePageEditAppLabel')>>AppWithinMinutes.CreateApplication||queryString="$queryString" class="action edit"]]
70 - #end
71 - #if($hasEditTranslations)
72 - * [[$services.localization.render('platform.appwithinminutes.appHomePageTranslateAppLabel')>>path:$xwiki.getURL($translationsRef, 'edit', 'editor=wiki')||class="action translate"]]
73 - #end
74 - #if($hasDeleteData)
75 - #set ($deleteDataURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({
76 - 'appName': $doc.space,
77 - 'resolve': true,
78 - 'scope': 'entries',
79 - 'xredirect': $doc.getURL()
80 - })))
81 - * [[$services.localization.render('platform.appwithinminutes.appHomePageDeleteEntriesLabel')>>path:$deleteDataURL||class="action deleteData"]]
82 - #end
83 - #if($hasDeleteApplication)
84 - #set ($deleteAppURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({
85 - 'appName': $doc.space,
86 - 'resolve': true,
87 - 'xredirect': $doc.getURL()
88 - })))
89 - * [[$services.localization.render('platform.appwithinminutes.appHomePageDeleteAppLabel')>>path:$deleteAppURL||class="action delete"]]
90 - #end
91 - )))
92 - #end
8 + #displayAppActions
93 93   #end
94 94   $doc.display('description')
95 95   ## Display the live table only if it was generated.
96 - #if($doc.content.length() > 0)
12 + #if ($doc.content.length() > 0)
97 97   = $services.localization.render('platform.appwithinminutes.appLiveTableHeading') =
98 - ## We don't use the Include macro (with empty reference) because we want the content to be executed with the rights
99 - ## of the current document rather than the rights of the sheet. This is important because the user can modify the
100 - ## content of the application home page which means we could execute untrusted content with the rights of the sheet.
101 - ## Ideally we should use the Display macro with a parameter to disable the sheet, but we don't have this parameter.
102 - ## We don't clean the HTML content because getRenderedContent() should produce clean HTML, unless the user has
103 - ## disabled the HTML cleaning, in which case he will get what he asked for. Note that one good reason to disable
104 - ## HTML cleaning is to preserve the whitespaces in the attribute values.
105 - ## Escape {{ in the rendered content to be sure that the HTML macro is not closed unintentionally.
106 - {{html clean="false"}}$doc.getRenderedContent($doc.content,
107 - $doc.syntax.toIdString()).replace('{{', '&amp;#123;&amp;#123;'){{/html}}
14 +
15 + {{include reference="" author="target"/}}
108 108   #end
109 109  #end
18 +
19 +#macro (displayAppActions)
20 + ## Determine the user's rights
21 + #set ($className = $stringtool.removeEnd($classFullName, 'Class'))
22 + #set ($templateProviderReference = $services.model.resolveDocument("${className}TemplateProvider"))
23 + #set ($templateProvider = $xwiki.getDocument($templateProviderReference))
24 + #set ($creationRestrictions = $templateProvider.getValue('creationRestrictions'))
25 + #if ($creationRestrictions)
26 + #if ($creationRestrictions.size() > 0)
27 + #set ($dataSpaceRef = $services.model.resolveSpace($creationRestrictions.get(0)))
28 + #else
29 + ## There is no data space as the user can create application entries anywhere. Let's use the application space
30 + ## when the user clicks on the Add New Entry link from the home page.
31 + #set ($dataSpaceRef = $doc.documentReference.parent)
32 + #end
33 + #else
34 + ## The template provider is missing. Fall-back on the old 'dataSpace' property.
35 + #set ($dataSpaceRef = $services.model.resolveSpace($doc.getValue('dataSpace'), 'explicit',
36 + $doc.documentReference))
37 + #end
38 + #set ($hasCreateData = $services.security.authorization.hasAccess('edit', $dataSpaceRef))
39 + #set ($hasDeleteData = $services.security.authorization.hasAccess('admin', $dataSpaceRef))
40 + #set ($translationsRef = $services.model.resolveDocument("${className}Translations"))
41 + #set ($hasEditTranslations = $xwiki.isMultiLingual() && $xwiki.exists($translationsRef)
42 + && $services.security.authorization.hasAccess('edit', $translationsRef))
43 + #set ($classRef = $services.model.resolveDocument($classFullName))
44 + #set ($hasEditApplication = $services.security.authorization.hasAccess('edit', $classRef))
45 + #set ($hasDeleteApplication = $hasDeleteData
46 + && $services.security.authorization.hasAccess('admin', $doc.documentReference.parent)
47 + && $services.security.authorization.hasAccess('admin', $classRef.parent))
48 + ## Display the application actions based on the user's rights
49 + #if ($hasCreateData || $hasDeleteData || $hasEditApplication || $hasEditTranslations || $hasDeleteApplication)
50 + (% id="actionBox" class="floatinginfobox" %)
51 + (((
52 + = $services.localization.render('platform.appwithinminutes.appHomePageActionsHeading') =
53 + #if ($hasCreateData)
54 + * [[{{displayIcon name="add"/}} $services.localization.render('platform.appwithinminutes.appHomePageAddEntryHint')>>||anchor="AddNewEntry" class="action add"]]##
55 + #if ("$!templateProvider.getValue('terminal')" == '1')
56 + #set ($entryReference = $services.model.createDocumentReference('__entryName__', $dataSpaceRef))
57 + #else
58 + #set ($entryReference = $services.model.resolveDocument('', 'default',
59 + $services.model.createSpaceReference('__entryName__', $dataSpaceRef)))
60 + #end
61 + ## We need to set the title if we want to be able to sort or filter the doc.title live table column.
62 + #set ($params = {
63 + 'form_token': $services.csrf.token,
64 + 'template': "${className}Template",
65 + 'title': '__entryName__',
66 + 'parent': $services.model.serialize($doc.documentReference, 'local')
67 + })
68 + #if ($xwiki.getDocument($classRef).xWikiClass.properties.size() > 0)
69 + ## The entry has properties so go in edit mode to edit them.
70 + #set ($action = 'edit')
71 + #set ($params.editor = 'inline')
72 + #else
73 + ## There are no properties to edit so create the new entry and get back to the home page.
74 + #set ($action = 'save')
75 + #set ($discard = $params.putAll({
76 + 'xredirect': $doc.getURL(),
77 + 'form_token': $services.csrf.token
78 + }))
79 + #end
80 + {{html}}<input type="hidden" value="$xwiki.getURL($entryReference, $action, $escapetool.url($params))" />{{/html}}
81 + #end
82 + #if ($hasEditApplication)
83 + #set ($queryString = $escapetool.url({
84 + 'appName': $doc.space,
85 + 'resolve': true
86 + }))
87 + * [[{{displayIcon name="edit"/}} $services.localization.render('platform.appwithinminutes.appHomePageEditAppLabel')>>AppWithinMinutes.CreateApplication||queryString="$queryString" class="action edit"]]
88 + #end
89 + #if ($hasEditTranslations)
90 + * [[{{displayIcon name="translate"/}} $services.localization.render('platform.appwithinminutes.appHomePageTranslateAppLabel')>>path:${xwiki.getURL($translationsRef, 'edit', 'editor=wiki')}||class="action translate"]]
91 + #end
92 + #if ($hasDeleteData)
93 + #set ($deleteDataURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({
94 + 'appName': $doc.space,
95 + 'resolve': true,
96 + 'scope': 'entries',
97 + 'xredirect': $doc.getURL()
98 + })))
99 + * [[{{displayIcon name="cross"/}} $services.localization.render('platform.appwithinminutes.appHomePageDeleteEntriesLabel')>>path:${deleteDataURL}||class="action deleteData"]]
100 + #end
101 + #if ($hasDeleteApplication)
102 + #set ($deleteAppURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({
103 + 'appName': $doc.space,
104 + 'resolve': true,
105 + 'xredirect': $doc.getURL()
106 + })))
107 + * [[{{displayIcon name="trash"/}} $services.localization.render('platform.appwithinminutes.appHomePageDeleteAppLabel')>>path:${deleteAppURL}||class="action delete"]]
108 + #end
109 + )))
110 + #end
111 +#end
112 +
113 +#macro (renameAppModal)
114 + <div class="modal" id="renameAppModal" tabindex="-1" role="dialog" aria-labelledby="renameAppModal-label"
115 + data-backdrop="static" data-keyboard="false">
116 + <div class="modal-dialog" role="document">
117 + <form class="modal-content xform">
118 + ## The fieldset allows us to disable and enable the entire form quickly and easy.
119 + <fieldset>
120 + <div class="modal-header">
121 + <button type="button" class="close" data-dismiss="modal"
122 + title="$escapetool.xml($services.localization.render('appWithinMinutes.renameApp.close'))"
123 + aria-label="$escapetool.xml($services.localization.render('appWithinMinutes.renameApp.close'))">
124 + <span aria-hidden="true">&times;</span>
125 + </button>
126 + <span class="modal-title" id="renameAppModal-label">
127 + $escapetool.xml($services.localization.render('appWithinMinutes.renameApp.label'))
128 + </span>
129 + </div>
130 + <div class="modal-body">
131 + #renameAppModalBody
132 + </div>
133 + <div class="modal-footer">
134 + <button type="button" class="btn btn-default" data-dismiss="modal">
135 + $escapetool.xml($services.localization.render('cancel'))
136 + </button>
137 + <button type="submit" class="btn btn-primary" disabled="disabled">
138 + $escapetool.xml($services.localization.render('core.rename.submit'))
139 + </button>
140 + </div>
141 + </fieldset>
142 + </form>
143 + </div>
144 + </div>
145 +#end
146 +
147 +#macro (renameAppModalBody)
148 + <div class="box infomessage">
149 + $services.icon.renderHTML('info')
150 + $services.localization.render('appWithinMinutes.renameApp.changeAppTitleInfo')
151 + </div>
152 + <div class="box warningmessage">
153 + $services.icon.renderHTML('warning')
154 + $services.localization.render('appWithinMinutes.renameApp.regenerateAppCodeWarning')
155 + </div>
156 + <div class="hidden">
157 + <input type="hidden" name="form_token" value="$!escapetool.xml($services.csrf.token)" />
158 + <input type="hidden" name="oldAppReference" value="$escapetool.xml(
159 + $services.model.serialize($doc.documentReference.parent, 'local'))"/>
160 + <span class="appNameEmptyError xErrorMsg">
161 + $services.localization.render("platform.appwithinminutes.appNameEmptyError")
162 + </span>
163 + <span class="pageExistsError xErrorMsg">
164 + $services.localization.render("appWithinMinutes.renameApp.pageExistsError")
165 + </span>
166 + <span class="locationForbiddenError xErrorMsg">
167 + $services.localization.render("appWithinMinutes.renameApp.locationForbiddenError")
168 + </span>
169 + </div>
170 + #set ($appName = $doc.pageReference.name)
171 + #set ($isNestedPage = $doc.documentReference.name == $services.model.getEntityReference('DOCUMENT', 'default').name)
172 + #set ($parentReference = $doc.documentReference.parent)
173 + #if ($isNestedPage)
174 + #set ($parentReference = $parentReference.parent)
175 + #end
176 + #locationPicker({
177 + 'id': 'renameApp',
178 + 'title': {
179 + 'label': 'appWithinMinutes.renameApp.newName.label',
180 + 'hint': 'platform.appwithinminutes.appNameHint',
181 + 'name': 'newAppName',
182 + 'value': $appName,
183 + 'placeholder': 'appWithinMinutes.renameApp.newName.label'
184 + },
185 + 'preview': {
186 + 'label': 'appWithinMinutes.renameApp.location.label',
187 + 'hint': 'appWithinMinutes.renameApp.location.hint'
188 + },
189 + 'parent': {
190 + 'label': 'appWithinMinutes.renameApp.parent.label',
191 + 'hint': 'appWithinMinutes.renameApp.parent.hint',
192 + 'name': 'newAppParentReference',
193 + 'reference': $parentReference,
194 + 'placeholder': 'appWithinMinutes.createApp.parent.placeholder'
195 + }
196 + })
197 +#end
110 110  {{/velocity}}
199 +
200 +{{velocity}}
201 +#set ($liveTableObj = $doc.getObject('AppWithinMinutes.LiveTableClass'))
202 +#if ($liveTableObj)
203 + #set ($discard = $doc.use($liveTableObj))
204 + #set ($classFullName = $doc.getValue('class'))
205 + #if ("$!classFullName" == '' || !$xwiki.exists($classFullName))
206 + {{warning}}
207 + $services.icon.render('warning') {{translation key="platform.appwithinminutes.appHomePageMovedWarning"/}}
208 + {{/warning}}
209 +
210 + #end
211 + #displayApp()
212 +
213 + {{html clean="false"}}
214 + #renameAppModal()
215 + {{/html}}
216 +#end
217 +{{/velocity}}
locate.png
Author
... ... @@ -1,1 +1,0 @@
1 -XWiki.MarkKohlmann
Size
... ... @@ -1,1 +1,0 @@
1 -746 bytes
Content
XWiki.JavaScriptExtension[0]
Code
... ... @@ -6,7 +6,11 @@
6 6   this.urlTemplate = trigger.up().next('input[type=hidden]').value;
7 7  
8 8   this.input = new Element('input', {type: 'text'});
9 - this.addButton = new Element('input', {type: 'image', src: '$xwiki.getSkinFile('icons/silk/add.png')', alt: '$escapetool.javascript($services.localization.render('platform.appwithinminutes.appHomePageAddEntryLabel'))'});
9 + this.addButton = new Element('input', {
10 + type: 'image',
11 + src: '$xwiki.getSkinFile('icons/silk/add.png')',
12 + alt: '$escapetool.javascript($services.localization.render('platform.appwithinminutes.appHomePageAddEntryLabel'))'
13 + });
10 10  
11 11   var container = new Element('div', {id: 'entryNamePopup'});
12 12   container.insert(this.input);
... ... @@ -50,3 +50,177 @@
50 50  
51 51  return XWiki;
52 52  }(XWiki || {}));
57 +
58 +/**
59 + * Rename Application
60 + */
61 +require(['jquery', 'bootstrap', 'xwiki-form-validation-async'], function($) {
62 + ## Note: if not currentApp request param is not passed, we default to the wiki home page reference to avoid a NPE
63 + #set ($currentDocReference = $xwiki.getDocument("$!request.currentApp").getDocumentReference())
64 + // if we cannot find any extension related to this page app, it's not part of an extension.
65 + var isNotAnExtension = $services.extension.xar.getInstalledExtensions($currentDocReference).isEmpty();
66 +
67 + // double negation! if it's an extension, we stop there: we don't want to add custom AWM rename capabilities
68 + if (!isNotAnExtension) {
69 + return;
70 + }
71 + // Hijack the rename page action.
72 + var renameAppModal = $('#renameAppModal');
73 + $('#tmActionRename').on('click', function(event) {
74 + event.preventDefault();
75 + renameAppModal.modal();
76 + });
77 +
78 + // Form validation.
79 + var appNameInput = $('#renameAppTitle');
80 + var appParentInput = $('#renameAppParentReference');
81 +
82 + var appNameEmptyError = renameAppModal.find('.appNameEmptyError');
83 + var pageExistsError = renameAppModal.find('.pageExistsError');
84 + var locationForbiddenError = renameAppModal.find('.locationForbiddenError');
85 + appNameEmptyError.add(pageExistsError).add(locationForbiddenError).hide().insertAfter(appNameInput);
86 +
87 + var getNewAppReference = function(local) {
88 + var appParentReference = local ? null : new XWiki.WikiReference(XWiki.currentWiki);
89 + if (appParentInput.val() !== '') {
90 + appParentReference = XWiki.Model.resolve(appParentInput.val(), XWiki.EntityType.SPACE, appParentReference);
91 + }
92 + return new XWiki.EntityReference(appNameInput.val(), XWiki.EntityType.SPACE, appParentReference);
93 + };
94 +
95 + var getNewAppHomePage = function() {
96 + var newAppReference = getNewAppReference();
97 + var newAppHomePageReference = new XWiki.EntityReference('WebHome', XWiki.EntityType.DOCUMENT, newAppReference);
98 + return new XWiki.Document(newAppHomePageReference);
99 + };
100 +
101 + var startValidation = function() {
102 + if (appNameInput.val() === '') {
103 + return Promise.reject(appNameEmptyError);
104 + } else {
105 + var newAppHomePage = getNewAppHomePage();
106 + if (newAppHomePage.documentReference.equals(XWiki.currentDocument.documentReference)) {
107 + return Promise.reject(pageExistsError);
108 + } else {
109 + return new Promise((resolve, reject) => {
110 + $.ajax({
111 + type: 'HEAD',
112 + url: newAppHomePage.getURL()
113 + }).then(reject.bind(null, pageExistsError), response => {
114 + if (response.status === 404) {
115 + $.ajax({
116 + type: 'HEAD',
117 + url: newAppHomePage.getURL('edit')
118 + }).then(
119 + () => resolve(),
120 + () => reject(locationForbiddenError)
121 + );
122 + } else if (response.status === 403) {
123 + reject(locationForbiddenError);
124 + } else {
125 + resolve();
126 + }
127 + });
128 + });
129 + }
130 + }
131 + };
132 +
133 + var scheduleValidation = function() {
134 + // Hide all error messages before starting the asynchronous validation.
135 + renameAppModal.find('.xErrorMsg').hide();
136 + appNameInput.addClass('loading').validateAsync(startValidation, 500, 'awm').catch((error) => {
137 + error.show();
138 + }).finally(() => {
139 + appNameInput.removeClass('loading');
140 + });
141 + };
142 +
143 + appNameInput.add(appParentInput).on('input', scheduleValidation);
144 +
145 + var locationPickerModal = renameAppModal.find('.location-picker .modal');
146 + renameAppModal.on('shown.bs.modal', function(event) {
147 + // Nested modals are not supported so we have to move the location picker modal outside, but we shouldn't do this
148 + // before the location picker has been initialized. That's why we wait for the rename application modal to be shown
149 + // first.
150 + renameAppModal.after(locationPickerModal);
151 + appNameInput.focus();
152 + });
153 +
154 + // Hide the rename application modal when the location picker modal is shown.
155 + locationPickerModal.removeClass('fade').on('show.bs.modal', function(event) {
156 + renameAppModal.modal('hide');
157 + // Show the rename application modal when the location picker modal is hidden.
158 + }).on('hidden.bs.modal', function(event) {
159 + renameAppModal.modal('show');
160 + });
161 +
162 + renameAppModal.find('form').on('submit', function(event) {
163 + event.preventDefault();
164 + renameApp(getRenameData($(this)));
165 + });
166 +
167 + var getRenameData = function(form) {
168 + var data = getFormData(form);
169 + data.newAppReference = XWiki.Model.serialize(getNewAppReference(true));
170 + delete data.newAppName;
171 + delete data.newAppParentReference;
172 + data.outputSyntax = 'plain';
173 + return data;
174 + };
175 +
176 + var getFormData = function(form) {
177 + var data = {};
178 + form.serializeArray().forEach(function(parameter) {
179 + // Keep the first value;
180 + if (!data.hasOwnProperty(parameter.name)) {
181 + data[parameter.name] = parameter.value;
182 + }
183 + });
184 + return data;
185 + };
186 +
187 + var renameApp = function(data) {
188 + // Disable the form to prevent it from being submitted twice.
189 + renameAppModal.find('fieldset').prop('disabled', true);
190 + var notification = new XWiki.widgets.Notification(
191 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.inProgress')),
192 + 'inprogress'
193 + );
194 + var renameAppURL = new XWiki.Document('RenameApplication', 'AppWithinMinutes').getURL('get');
195 + Promise.resolve($.post(renameAppURL, data)).then(updateAppHomePage).then(function() {
196 + renameAppModal.modal('hide');
197 + notification.replace(new XWiki.widgets.Notification(
198 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.done')),
199 + 'done'
200 + ));
201 + // Delay a bit the redirect so that the user notices the success message.
202 + setTimeout(function() {
203 + window.location.href = getNewAppHomePage().getURL();
204 + }, 0);
205 + }).catch(function() {
206 + notification.replace(new XWiki.widgets.Notification(
207 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.failed')),
208 + 'error'
209 + ));
210 + }).finally(function() {
211 + // Re-enable the form.
212 + renameAppModal.find('fieldset').prop('disabled', false);
213 + });
214 + };
215 +
216 + var updateAppHomePage = function() {
217 + return new Promise((resolve, reject) => {
218 + var newAppHomePageEditURL = getNewAppHomePage().getURL('edit');
219 + $('<div/>').load(newAppHomePageEditURL + ' #inline', function() {
220 + var formData = $(this).children('form#inline').serializeArray();
221 + if (formData.length) {
222 + formData.push({name: 'xaction_save', value: true});
223 + $.post(newAppHomePageEditURL, formData).then(resolve, reject);
224 + } else {
225 + reject();
226 + }
227 + });
228 + });
229 + }
230 +});
XWiki.StyleSheetExtension[0]
Code
... ... @@ -16,30 +16,10 @@
16 16   background: none no-repeat scroll 0 center transparent;
17 17   display: block;
18 18   font-size: .8em;
19 - padding: .3em .3em .3em 20px;
19 + padding: .3em .3em .3em .3em;
20 20   text-transform: uppercase;
21 21  }
22 22  
23 -#actionBox .action.edit {
24 - background-image: url("$xwiki.getSkinFile('icons/silk/application_edit.png')");
25 -}
26 -
27 -#actionBox .action.translate {
28 - background-image: url("$doc.getAttachmentURL('locate.png')");
29 -}
30 -
31 -#actionBox .action.delete {
32 - background-image: url("$xwiki.getSkinFile('icons/silk/application_delete.png')");
33 -}
34 -
35 -#actionBox .action.deleteData {
36 - background-image: url("$xwiki.getSkinFile('icons/silk/application_form_delete.png')");
37 -}
38 -
39 -#actionBox .action.add {
40 - background-image: url("$xwiki.getSkinFile('icons/silk/add.png')");
41 -}
42 -
43 43  #entryNamePopup {
44 44   margin-right: 20px;
45 45  }
... ... @@ -58,3 +58,12 @@
58 58   /* Make sure the live table doesn't overflow the action panel. */
59 59   clear: right;
60 60  }
41 +
42 +/**
43 + * Rename Application
44 + */
45 +#renameAppTitle.loading {
46 + background-position: right .3em center;
47 + padding-left: 12px;
48 + padding-right: 2em;
49 +}