Изменения документа AdminUsersSheet
Редактировал(а) Alexey Semenihin 23.10.2026, 15:12
От версии 4.1
отредактировано Alexey Semenihin
на 23.10.2026, 15:12
на 23.10.2026, 15:12
Изменить комментарий:
Install extension [org.xwiki.platform:xwiki-platform-administration-ui/17.10.12]
К версии 1.1
отредактировано Admin xWiKi
на 15.10.2019, 13:19
на 15.10.2019, 13:19
Изменить комментарий:
Install extension [org.xwiki.platform:xwiki-platform-administration-ui/11.8.1]
Сводка
-
Свойства страницы (3 изменено, 0 добавлено, 0 удалено)
-
Объекты (2 изменено, 0 добавлено, 0 удалено)
Подробности
- Свойства страницы
-
- Автор документа
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. semenihinaa1 +XWiki.admin - Синтаксис
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki 2. 11 +XWiki 2.0 - Содержимое
-
... ... @@ -1,93 +1,52 @@ 1 1 {{velocity output="false"}} 2 -#macro (displayUsersLiveData) 3 - #set ($properties = ['name', 'first_name', 'last_name', '_actions']) 4 - #set ($sourceParameters = { 5 - 'template': 'getusers.vm', 6 - 'translationPrefix': 'xe.admin.users.' 2 +#macro (userScopeFilter) 3 + <select name="wiki"> 4 + <option selected="selected" value="local"> 5 + $escapetool.xml($services.localization.render('rightsmanager.local')) 6 + </option> 7 + <option value="global"> 8 + $escapetool.xml($services.localization.render('rightsmanager.global')) 9 + </option> 10 + <option value="both"> 11 + $escapetool.xml($services.localization.render('rightsmanager.both')) 12 + </option> 13 + </select> 14 +#end 15 + 16 +#macro (displayUsersLiveTable) 17 + #set ($columnOptions = { 18 + 'name': {'type': 'text', 'sortable': false, 'html': true}, 19 + 'first_name': {'type': 'text', 'sortable': false}, 20 + 'last_name': {'type': 'text', 'sortable': false}, 21 + 'scope': {'type': 'list', 'sortable': false}, 22 + '_actions': { 23 + 'actions': [ 24 + 'edit', 25 + {'id': 'disable', 'icon': 'lock'}, 26 + {'id': 'enable', 'icon': 'unlock'}, 27 + 'delete' 28 + ], 29 + 'labels': false 30 + } 7 7 }) 32 + #set ($columns = ['name', 'first_name', 'last_name', '_actions']) 33 + #set ($liveTableOptions = { 34 + 'url': $doc.getURL('view', 'xpage=getusers'), 35 + 'translationPrefix': 'xe.admin.users.', 36 + 'outputOnlyHtml': true 37 + }) 8 8 #if (!$xcontext.isMainWiki()) 9 - #set ($discard = $properties.add(3, 'scope')) 39 + #set ($discard = $columns.add(3, 'scope')) 40 + ## We use the top filters option to show only the local users by default because the JavaScript code from the sheet 41 + ## is executed after the livetable is loaded. The JavaScript code removes the top filters and updates the scope filter 42 + ## afterwards. 43 + #set ($liveTableOptions.topFilters = "#userScopeFilter") 10 10 #end 11 11 <div class="medium-avatars"> 12 - $services.liveData.render({ 13 - 'id': 'userstable', 14 - 'source': 'liveTable', 15 - 'properties': $stringtool.join($properties, ','), 16 - 'sourceParameters': $escapetool.url($sourceParameters) 17 - }, { 18 - 'query': { 19 - 'filters': [ 20 - { 21 - 'property': 'scope', 22 - 'constraints': [{ 23 - 'operator': 'contains', 24 - 'value': 'local' 25 - }] 26 - } 27 - ] 28 - }, 29 - 'meta': { 30 - 'propertyDescriptors': [ 31 - { 32 - 'id': 'name', 33 - 'displayer': 'html', 34 - 'sortable': false, 35 - 'editable': false 36 - }, 37 - { 38 - 'id': 'first_name', 39 - 'sortable': false, 40 - 'editable': false 41 - }, 42 - { 43 - 'id': 'last_name', 44 - 'sortable': false, 45 - 'editable': false 46 - }, 47 - { 48 - 'id': 'scope', 49 - 'sortable': false, 50 - 'editable': false, 51 - 'filter': { 52 - 'id': 'list', 53 - 'options': [ 54 - {'value': 'local', 'label': $services.localization.render('rightsmanager.local')}, 55 - {'value': 'global', 'label': $services.localization.render('rightsmanager.global')}, 56 - {'value': 'both', 'label': $services.localization.render('rightsmanager.both')} 57 - ] 58 - } 59 - }, 60 - { 61 - 'id': '_actions', 62 - 'displayer': { 63 - 'id': 'actions', 64 - 'actions': ['edit', 'disable', 'enable', 'delete'] 65 - } 66 - } 67 - ], 68 - 'actions': [ 69 - { 70 - 'id': 'disable', 71 - 'icon': 'lock', 72 - 'allowProperty': 'doc.hasdisable', 73 - 'urlProperty': 'doc.disable_url', 74 - 'extraIconClasses': 'text-warning' 75 - }, 76 - { 77 - 'id': 'enable', 78 - 'icon': 'unlock', 79 - 'allowProperty': 'doc.hasenable', 80 - 'urlProperty': 'doc.enable_url', 81 - 'extraIconClasses': 'text-success' 82 - } 83 - ] 84 - } 85 - }) 46 + #livetable('userstable' $columns $columnOptions $liveTableOptions) 86 86 </div> 87 87 <p> 88 - <button type="button" class="btn btn-primary" data-toggle="modal" data-target="${escapetool.h}createUserModal" 89 - ## Disable the button until the JavaScript code that handles the user creation is ready. 90 - disabled="disabled"> 49 + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="${escapetool.h}createUserModal"> 91 91 $escapetool.xml($services.localization.render('rightsmanager.addnewuser')) 92 92 </button> 93 93 </p> ... ... @@ -111,9 +111,7 @@ 111 111 <button type="button" class="btn btn-default" data-dismiss="modal"> 112 112 $escapetool.xml($services.localization.render('cancel')) 113 113 </button> 114 - ## The registration form is not present on page load so we can't bind the submit button without triggerig an 115 - ## HTML validation error. That's why we set the form attribute from JavaScript instead. 116 - <button type="submit" class="btn btn-primary" disabled="disabled"> 73 + <button type="button" class="btn btn-primary" disabled="disabled"> 117 117 $escapetool.xml($services.localization.render('create')) 118 118 </button> 119 119 </div> ... ... @@ -124,7 +124,7 @@ 124 124 125 125 #macro (editUserModal) 126 126 <div class="modal" id="editUserModal" tabindex="-1" role="dialog" aria-labelledby="editUserModal-label" 127 - data-backdrop="static" data-keyboard="false" data-live -data="#userstable" data-live-data-action="edit">84 + data-backdrop="static" data-keyboard="false" data-liveTable="#userstable" data-liveTableAction="edit"> 128 128 <div class="modal-dialog modal-lg" role="document"> 129 129 <div class="modal-content"> 130 130 <div class="modal-header"> ... ... @@ -154,7 +154,7 @@ 154 154 ## have script or programming rights. 155 155 #userPicker_import 156 156 <div class="modal" id="deleteUserModal" tabindex="-1" role="dialog" aria-labelledby="deleteUserModal-label" 157 - data-live -data="#userstable" data-live-data-action="delete">114 + data-liveTable="#userstable" data-liveTableAction="delete"> 158 158 <div class="modal-dialog" role="document"> 159 159 <div class="modal-content"> 160 160 <div class="modal-header"> ... ... @@ -208,13 +208,11 @@ 208 208 #macro (maybeShowDeleteUserWarning $userReference $right) 209 209 #countPagesLastModifiedBy($userReference) 210 210 #if ($pageCount > 0) 211 - {{/html}} 212 - 213 - {{error cssClass="xform"}} 214 - {{html}} 168 + <div class="box errormessage xform"> 215 215 #set ($pageIndexReference = $services.model.createDocumentReference( 216 216 $userReference.wikiReference.name, 'Main', 'AllDocs')) 217 - #set ($pageIndexURL = $xwiki.getURL($pageIndexReference, 'view', "doc.author=${escapetool.url($services.model.serialize($userReference, 'local'))}")) 171 + #set ($pageIndexURL = $xwiki.getURL($pageIndexReference) + '#|t=alldocs&doc.author=' + 172 + $escapetool.url($services.model.serialize($userReference, 'local'))) 218 218 #set ($translationKey = "administration.section.users.deleteUser.${right}RightsWarning") 219 219 $services.localization.render($translationKey, ["<a href='$pageIndexURL'>", $pageCount, '</a>']) 220 220 <dl> ... ... @@ -239,10 +239,7 @@ 239 239 [$rightTranslation]))</span> 240 240 </dd> 241 241 </dl> 242 - {{/html}} 243 - {{/error}} 244 - 245 - {{html clean="false"}} 197 + </div> 246 246 #end 247 247 #end 248 248 ... ... @@ -295,10 +295,10 @@ 295 295 #set ($discard = $xwiki.jsx.use("XWiki.AdminUsersSheet")) 296 296 297 297 {{html clean="false"}} 298 - #displayUsersLive Data()299 - #createUserModal ()300 - #editUserModal ()301 - #deleteUserModal ()250 + #displayUsersLiveTable 251 + #createUserModal 252 + #editUserModal 253 + #deleteUserModal 302 302 {{/html}} 303 303 #end 304 304 #end
- XWiki.JavaScriptExtension[0]
-
- Код
-
... ... @@ -1,25 +1,31 @@ 1 1 require.config({ 2 2 paths: { 3 - 'xwiki-live data-modal': new XWiki.Document('AdminGroupsSheet', 'XWiki').getURL('jsx', 'r=1')3 + 'xwiki-livetable-modal': new XWiki.Document('AdminGroupsSheet', 'XWiki').getURL('jsx', 'r=1') 4 4 } 5 5 }); 6 6 7 -require(['jquery', 'xwiki-meta', 'xwiki-livedata-modal', 'xwiki-events-bridge'], function($, xm) { 7 +// 8 +// Scope Filtering 9 +// 10 +require(['jquery'], function($) { 11 + var options = $('#userstable').prev('.tipfilters').remove().find('select[name="wiki"]').html(); 12 + var scopeFilter = $('#userstable .xwiki-livetable-display-filters select[name="scope"]') 13 + scopeFilter.attr('name', 'wiki').html(options); 14 +}); 15 + 16 +require(['jquery', 'xwiki-meta', 'xwiki-livetable-modal', 'xwiki-events-bridge'], function($, xm) { 8 8 // 9 9 // User Creation 10 10 // 11 - const createUserModal = $('#createUserModal'); 12 - // We set the form attribute from JavaScript in order to avoid HTML validation errors because the form is not present 13 - // on page load (we load it the first time the modal is shown, see below). 14 - const createUserButton = createUserModal.find('.btn-primary').attr('form', 'register'); 20 + var createUserModal = $('#createUserModal'); 15 15 16 16 var validateCreateUserForm = function(form) { 17 - return form. length&& (!window.LiveValidation ||23 + return form.size() > 0 && (!window.LiveValidation || 18 18 LiveValidation.massValidate(LiveValidationForm.getInstance(form[0]).fields)); 19 19 }; 20 20 21 21 createUserModal.on('show.bs.modal', function() { 22 - createUserButton.prop('disabled', true); 28 + var createUserButton = createUserModal.find('.btn-primary').prop('disabled', true); 23 23 var createUserURL = XWiki.currentDocument.getURL('view', 'xpage=registerinline'); 24 24 var createUserModalBody = createUserModal.find('.modal-body').empty().addClass('loading'); 25 25 $.get(createUserURL, function(html) { ... ... @@ -29,27 +29,26 @@ 29 29 createUserModalBody.removeClass('loading').append(createUserForm); 30 30 $(document).trigger('xwiki:dom:updated', {'elements': createUserModalBody.toArray()}); 31 31 createUserForm.find(':input').filter(':visible').first().focus(); 32 - createUserButton.prop('disabled', !createUserForm.length);38 + createUserButton.prop('disabled', createUserForm.size() === 0); 33 33 }); 34 - }).on('submit', 'form#register', function(event) { 35 - event.preventDefault(); 40 + }).on('click', '.btn-primary', function(event) { 36 36 var createUserForm = createUserModal.find('form#register'); 37 37 if (!validateCreateUserForm(createUserForm)) { 38 38 return; 39 39 } 40 - createUserButton.prop('disabled', true); 45 + var createUserButton = $(this).prop('disabled', true); 41 41 var notification = new XWiki.widgets.Notification( 42 42 $jsontool.serialize($services.localization.render('xe.admin.users.create.inProgress')), 43 43 'inprogress' 44 44 ); 45 - $.post(createUserForm.attr('action'), createUserForm.serialize()). then(html=>{50 + $.post(createUserForm.attr('action'), createUserForm.serialize()).done(function(html) { 46 46 var errorMessage = $('<div/>').html(html).find('.errormessage, .LV_validation_message.LV_invalid'); 47 - if (errorMessage. length) {52 + if (errorMessage.size() > 0) { 48 48 createUserButton.prop('disabled', false); 49 49 notification.replace(new XWiki.widgets.Notification(errorMessage.text(), 'error')); 50 50 } else { 51 51 createUserModal.modal('hide'); 52 - $('#userstable').data('liveData').updateEntries();57 + window.livetable_userstable.refresh(); 53 53 $('#userstable').trigger('xwiki:user:created'); 54 54 notification.replace(new XWiki.widgets.Notification( 55 55 $jsontool.serialize($services.localization.render('xe.admin.users.create.done')), ... ... @@ -56,7 +56,7 @@ 56 56 'done' 57 57 )); 58 58 } 59 - }). catch(()=>{64 + }).fail(function (response) { 60 60 createUserButton.prop('disabled', false); 61 61 notification.replace(new XWiki.widgets.Notification( 62 62 $jsontool.serialize($services.localization.render('xe.admin.users.create.failed')), ... ... @@ -73,22 +73,20 @@ 73 73 var loadEditForm = function(forceLock) { 74 74 var saveButton = editUserModal.find('.btn-primary').prop('disabled', true); 75 75 var rowData = editUserModal.data('rowData'); 76 - var userReference = XWiki.Model.resolve(rowData ['doc.fullName'], XWiki.EntityType.DOCUMENT, [rowData['doc.wiki']]);81 + var userReference = XWiki.Model.resolve(rowData.doc_fullName, XWiki.EntityType.DOCUMENT, [rowData.doc_wiki]); 77 77 var userDocument = new XWiki.Document(userReference); 78 78 var editUserURL = userDocument.getURL('edit'); 79 79 var parameters = {xpage: 'edituser'}; 80 80 if (forceLock === true) { 81 - parameters.force_token = xm.form_token; 82 82 parameters.force = 1; 83 83 } 84 84 editUserModal.find('.modal-body').first().empty().addClass('loading').load(editUserURL, parameters, function() { 85 - var self = $(this); 86 - self.removeClass('loading'); 87 - self.find('.column.half').removeClass('half').addClass('full'); 88 - $(document).trigger('xwiki:dom:updated', {'elements': self.toArray()}); 89 + this.removeClass('loading'); 90 + this.find('.column.half').removeClass('half').addClass('full'); 91 + $(document).trigger('xwiki:dom:updated', {'elements': this.toArray()}); 89 89 var editUserForm = editUserModal.find('form#edituser'); 90 90 editUserForm.find(':input').filter(':visible').first().focus(); 91 - saveButton.prop('disabled', !editUserForm.length);94 + saveButton.prop('disabled', editUserForm.size() === 0); 92 92 }); 93 93 }; 94 94 ... ... @@ -106,14 +106,14 @@ 106 106 'inprogress' 107 107 ); 108 108 $(document).trigger('xwiki:actions:beforeSave'); 109 - $.post(editForm.attr('action'), editForm.serialize()). then(()=>{112 + $.post(editForm.attr('action'), editForm.serialize()).done(function() { 110 110 $(document).trigger('xwiki:document:saved'); 111 - editUserModal.modal('hide').data('live DataElement').data('liveData').updateEntries();114 + editUserModal.modal('hide').data('liveTable').refresh(); 112 112 notification.replace(new XWiki.widgets.Notification( 113 113 $jsontool.serialize($services.localization.render('core.editors.saveandcontinue.notification.done')), 114 114 'done' 115 115 )); 116 - }). catch(response=>{119 + }).fail(function (response) { 117 117 saveButton.prop('disabled', false); 118 118 var message = $jsontool.serialize($services.localization.render('core.editors.saveandcontinue.notification.error', 119 119 ['__reason__'])); ... ... @@ -142,32 +142,29 @@ 142 142 failed: $jsontool.serialize($services.localization.render('administration.section.users.disableUser.failed')) 143 143 } 144 144 } 145 - 146 - function onToggleUser(action) { 147 - return function (event) { 148 - event.preventDefault(); 149 - var actionTrigger = $(this); 150 - if (actionTrigger.hasClass('pending')) { 151 - // Another request is already in progress. 152 - return; 153 - } 154 - actionTrigger.addClass('pending'); 155 - var notification = new XWiki.widgets.Notification(notificationMessage[action].inProgress, 'inprogress'); 156 - // The enable and disable actions redirect to the user profile by default which may take a lot of time to 157 - // render so we redirect to a URL that doesn't render anything. 158 - var emptyResponseURL = new XWiki.Document('AdminUsersSheet', 'XWiki').getURL('get', 'outputSyntax=plain'); 159 - Promise.resolve($.post(actionTrigger.attr('href'), {'xredirect': emptyResponseURL})).then(function () { 160 - $('#userstable').data('liveData').updateEntries(); 161 - notification.replace(new XWiki.widgets.Notification(notificationMessage[action].done, 'done')); 162 - }).catch(function () { 163 - notification.replace(new XWiki.widgets.Notification(notificationMessage[action].failed, 'error')); 164 - }).finally(function () { 165 - actionTrigger.removeClass('pending'); 166 - }); 167 - }; 168 - } 169 - $(document).on('click', '#userstable a.action_enable', onToggleUser('enable')); 170 - $(document).on('click', '#userstable a.action_disable', onToggleUser('disable')); 148 + var onToggleUser = function(action, event) { 149 + event.preventDefault(); 150 + var actionTrigger = $(this); 151 + if (actionTrigger.hasClass('pending')) { 152 + // Another request is already in progress. 153 + return; 154 + } 155 + actionTrigger.addClass('pending'); 156 + var notification = new XWiki.widgets.Notification(notificationMessage[action].inProgress, 'inprogress'); 157 + // The enable and disable actions redirect to the user profile by default which may take a lot of time to render so 158 + // we redirect to a URL that doesn't render anything. 159 + var emptyResponseURL = new XWiki.Document('AdminUsersSheet', 'XWiki').getURL('get', 'outputSyntax=plain'); 160 + $.post(actionTrigger.attr('href'), {'xredirect': emptyResponseURL}).done(function() { 161 + window['livetable_userstable'].refresh(); 162 + notification.replace(new XWiki.widgets.Notification(notificationMessage[action].done, 'done')); 163 + }).fail(function() { 164 + notification.replace(new XWiki.widgets.Notification(notificationMessage[action].failed, 'error')); 165 + }).always(function() { 166 + actionTrigger.removeClass('pending'); 167 + }); 168 + }; 169 + $('#userstable').on('click', 'a.actionenable', $.proxy(onToggleUser, null, 'enable')); 170 + $('#userstable').on('click', 'a.actiondisable', $.proxy(onToggleUser, null, 'disable')); 171 171 })(); 172 172 173 173 // ... ... @@ -201,9 +201,9 @@ 201 201 202 202 deleteUserModal.on('show.bs.modal', function() { 203 203 var rowData = deleteUserModal.data('rowData'); 204 - var userReference = rowData ['doc.fullName'];205 - if (XWiki.currentWiki !== rowData ['doc.wiki']) {206 - userReference = XWiki.Model.resolve(userReference, XWiki.EntityType.DOCUMENT, [rowData ['doc.wiki']]);204 + var userReference = rowData.doc_fullName; 205 + if (XWiki.currentWiki !== rowData.doc_wiki) { 206 + userReference = XWiki.Model.resolve(userReference, XWiki.EntityType.DOCUMENT, [rowData.doc_wiki]); 207 207 userReference = XWiki.Model.serialize(userReference); 208 208 } 209 209 deleteUserModal.data('userReference', userReference); ... ... @@ -224,9 +224,9 @@ 224 224 newAuthor: newAuthor, 225 225 requiredRight: requiredRight 226 226 }); 227 - return Promise.resolve(newAuthorValidationRequest);227 + return newAuthorValidationRequest; 228 228 } else { 229 - return Promise.resolve({valid: true});229 + return $.Deferred().resolve({valid: true}).promise(); 230 230 } 231 231 }; 232 232 deleteUserModal.on('change', '#newAuthor', function(event) { ... ... @@ -235,17 +235,17 @@ 235 235 var newAuthorField = $(event.target); 236 236 // Hide the previous error message. 237 237 newAuthorField.nextAll('.xErrorMsg').addClass('hidden'); 238 - validateNewAuthor(newAuthorField.val(), newAuthorField.data('requiredRight')). then(function(result) {238 + validateNewAuthor(newAuthorField.val(), newAuthorField.data('requiredRight')).done(function(result) { 239 239 if (result.valid === false) { 240 240 newAuthorField.nextAll('.xErrorMsg').removeClass('hidden'); 241 241 } 242 - }). finally(function() {242 + }).always(function() { 243 243 // Re-enable the modal submit button. 244 244 deleteUserButton.prop('disabled', false); 245 245 }); 246 246 }); 247 247 248 - deleteUserButton. on('click',function() {248 + deleteUserButton.click(function() { 249 249 var notification = new XWiki.widgets.Notification( 250 250 $jsontool.serialize($services.localization.render('xe.admin.users.delete.inProgress')), 251 251 'inprogress' ... ... @@ -256,14 +256,14 @@ 256 256 docname: userReference, 257 257 newAuthor: deleteUserModal.find('#newAuthor').val(), 258 258 form_token: xm.form_token 259 - }). then(()=>{260 - deleteUserModal.data('live DataElement').data('liveData').updateEntries();261 - deleteUserModal.data('live DataElement').trigger('xwiki:user:deleted', {reference: userReference});259 + }).done(function() { 260 + deleteUserModal.data('liveTable').deleteRow(deleteUserModal.data('rowIndex')); 261 + deleteUserModal.data('liveTableElement').trigger('xwiki:user:deleted', {reference: userReference}); 262 262 notification.replace(new XWiki.widgets.Notification( 263 263 $jsontool.serialize($services.localization.render('xe.admin.users.delete.done')), 264 264 'done' 265 265 )); 266 - }). catch(()=>{266 + }).fail(function() { 267 267 notification.replace(new XWiki.widgets.Notification( 268 268 $jsontool.serialize($services.localization.render('xe.admin.users.delete.failed')), 269 269 'error' ... ... @@ -270,7 +270,4 @@ 270 270 )); 271 271 }); 272 272 }); 273 - 274 - // Finally, enable the user creation. 275 - $('button[data-target="#createUserModal"]').prop('disabled', false); 276 276 });
- XWiki.StyleSheetExtension[0]
-
- Код
-
... ... @@ -1,4 +1,19 @@ 1 +#template('colorThemeInit.vm') 2 + 1 1 /** 4 + * Users Live Table 5 + */ 6 +#userstable td[data-title] { 7 + vertical-align: middle; 8 +} 9 +#userstable .actiondisable .action-icon { 10 + color: $theme.notificationWarningColor; 11 +} 12 +#userstable .actionenable .action-icon { 13 + color: $theme.notificationSuccessColor; 14 +} 15 + 16 +/** 2 2 * Delete User Modal 3 3 */ 4 4 #deleteUserModal .userName { - Content Type
-
... ... @@ -1,1 +1,1 @@ 1 - LESS1 +CSS - Разбор содержимого
-
... ... @@ -1,1 +1,1 @@ 1 - Нет1 +Да