2 * Class and function collection for WCF ACP
4 * @author Alexander Ebert, Matthias Schmidt
5 * @copyright 2001-2014 WoltLab GmbH
6 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
10 * Initialize WCF.ACP namespace
15 * Namespace for ACP application management.
17 WCF
.ACP
.Application
= { };
20 * Provides the ability to set an application as primary.
22 * @param integer packageID
24 WCF
.ACP
.Application
.SetAsPrimary
= Class
.extend({
26 * application package id
32 * Initializes the WCF.ACP.Application.SetAsPrimary class.
34 * @param integer packageID
36 init: function(packageID
) {
37 this._packageID
= packageID
;
39 $('#setAsPrimary').click($.proxy(this._click
, this));
43 * Shows a confirmation dialog to set current application as primary.
46 WCF
.System
.Confirmation
.show(WCF
.Language
.get('wcf.acp.application.setAsPrimary.confirmMessage'), $.proxy(function(action
) {
47 if (action
=== 'confirm') {
54 * Sets an application as primary.
56 _setAsPrimary: function() {
57 new WCF
.Action
.Proxy({
60 actionName
: 'setAsPrimary',
61 className
: 'wcf\\data\\application\\ApplicationAction',
62 objectIDs
: [ this._packageID
]
64 success
: $.proxy(function(data
, textStatus
, jqXHR
) {
65 var $notification
= new WCF
.System
.Notification(WCF
.Language
.get('wcf.global.success'));
69 $('#setAsPrimary').parent().remove();
72 $headline
= $('.boxHeadline > h1');
73 $headline
.html($headline
.html() + ' ');
74 $('<span class="icon icon16 icon-ok-sign jsTooltip" title="' + WCF
.Language
.get('wcf.acp.application.primaryApplication') + '" />').appendTo($headline
);
76 WCF
.DOMNodeInsertedHandler
.execute();
83 * Namespace for ACP cronjob management.
85 WCF
.ACP
.Cronjob
= { };
88 * Handles the manual execution of cronjobs.
90 WCF
.ACP
.Cronjob
.ExecutionHandler
= Class
.extend({
93 * @var WCF.System.Notification
99 * @var WCF.Action.Proxy
104 * Initializes WCF.ACP.Cronjob.ExecutionHandler object.
107 this._proxy
= new WCF
.Action
.Proxy({
108 success
: $.proxy(this._success
, this)
111 $('.jsCronjobRow .jsExecuteButton').click($.proxy(this._click
, this));
113 this._notification
= new WCF
.System
.Notification(WCF
.Language
.get('wcf.global.success'), 'success');
117 * Handles a click on an execute button.
119 * @param object event
121 _click: function(event
) {
122 this._proxy
.setOption('data', {
123 actionName
: 'execute',
124 className
: 'wcf\\data\\cronjob\\CronjobAction',
125 objectIDs
: [ $(event
.target
).data('objectID') ]
128 this._proxy
.sendRequest();
132 * Handles successful cronjob execution.
135 * @param string textStatus
136 * @param jQuery jqXHR
138 _success: function(data
, textStatus
, jqXHR
) {
139 $('.jsCronjobRow').each($.proxy(function(index
, row
) {
140 var $button
= $(row
).find('.jsExecuteButton');
141 var $objectID
= ($button
).data('objectID');
143 if (WCF
.inArray($objectID
, data
.objectIDs
)) {
144 if (data
.returnValues
[$objectID
]) {
145 // insert feedback here
146 $(row
).find('td.columnNextExec').html(data
.returnValues
[$objectID
].formatted
);
147 $(row
).wcfHighlight();
150 this._notification
.show();
159 * Handles the cronjob log list.
161 WCF
.ACP
.Cronjob
.LogList
= Class
.extend({
163 * error message dialog
169 * Initializes WCF.ACP.Cronjob.LogList object.
172 // bind event listener to delete cronjob log button
173 $('.jsCronjobLogDelete').click(function() {
174 WCF
.System
.Confirmation
.show(WCF
.Language
.get('wcf.acp.cronjob.log.clear.confirm'), function(action
) {
175 if (action
== 'confirm') {
176 new WCF
.Action
.Proxy({
179 actionName
: 'clearAll',
180 className
: 'wcf\\data\\cronjob\\log\\CronjobLogAction'
182 success: function() {
183 window
.location
.reload();
190 // bind event listeners to error badges
191 $('.jsCronjobError').click($.proxy(this._showError
, this));
195 * Shows certain error message
197 * @param object event
199 _showError: function(event
) {
200 var $errorBadge
= $(event
.currentTarget
);
202 if (this._dialog
=== null) {
203 this._dialog
= $('<div style="overflow: auto"><pre>' + $errorBadge
.next().html() + '</pre></div>').hide().appendTo(document
.body
);
204 this._dialog
.wcfDialog({
205 title
: WCF
.Language
.get('wcf.acp.cronjob.log.error.details')
209 this._dialog
.html('<pre>' + $errorBadge
.next().html() + '</pre>');
210 this._dialog
.wcfDialog('open');
218 * @param array<string> activeMenuItems
220 WCF
.ACP
.Menu
= Class
.extend({
222 * Initializes ACPMenu.
224 * @param array activeMenuItems
226 init: function(activeMenuItems
) {
227 this._headerNavigation
= $('nav#mainMenu');
228 this._sidebarNavigation
= $('aside.collapsibleMenu > div');
230 this._prepareElements(activeMenuItems
);
234 * Resets all elements and binds event listeners.
236 _prepareElements: function(activeMenuItems
) {
237 this._headerNavigation
.find('li').removeClass('active');
239 this._sidebarNavigation
.find('legend').each($.proxy(function(index
, menuHeader
) {
240 $(menuHeader
).click($.proxy(this._toggleItem
, this));
243 // close all navigation groups
244 this._sidebarNavigation
.find('nav ul').each(function() {
248 this._headerNavigation
.find('li').click($.proxy(this._toggleSidebar
, this));
250 if (activeMenuItems
.length
=== 0) {
251 this._renderSidebar(this._headerNavigation
.find('li:first').data('menuItem'), []);
254 this._renderSidebar('', activeMenuItems
);
259 * Toggles a navigation group entry.
261 _toggleItem: function(event
) {
262 var $menuItem
= $(event
.currentTarget
);
264 $menuItem
.parent().find('nav ul').stop(true, true).toggle('blind', { }, 200).end();
265 $menuItem
.toggleClass('active');
269 * Handles clicks on main menu.
271 * @param object event
273 _toggleSidebar: function(event
) {
274 var $target
= $(event
.currentTarget
);
276 if ($target
.hasClass('active')) {
280 this._renderSidebar($target
.data('menuItem'), []);
284 * Renders sidebar including highlighting of currently active menu items.
286 * @param string menuItem
287 * @param array activeMenuItems
289 _renderSidebar: function(menuItem
, activeMenuItems
) {
290 // reset visible and active items
291 this._headerNavigation
.find('li').removeClass('active');
292 this._sidebarNavigation
.find('> div').hide();
294 if (activeMenuItems
.length
=== 0) {
296 this._headerNavigation
.find('li[data-menu-item="' + menuItem
+ '"]').addClass('active');
297 this._sidebarNavigation
.find('div[data-parent-menu-item="' + menuItem
+ '"]').show();
300 // open menu by active menu items, first element is always a head navigation item
301 menuItem
= activeMenuItems
.shift();
303 this._headerNavigation
.find('li[data-menu-item="' + menuItem
+ '"]').addClass('active');
304 this._sidebarNavigation
.find('div[data-parent-menu-item="' + menuItem
+ '"]').show();
306 for (var $i
= 0, $size
= activeMenuItems
.length
; $i
< $size
; $i
++) {
307 var $item
= activeMenuItems
[$i
];
309 if ($.wcfIsset($item
)) {
310 var $menuItem
= $('#' + $.wcfEscapeID($item
));
312 if ($menuItem
.getTagName() === 'ul') {
313 $menuItem
.show().parents('fieldset').children('legend').addClass('active');
316 $menuItem
.addClass('active');
325 * Namespace for ACP package management.
327 WCF
.ACP
.Package
= { };
330 * Provides the package installation.
332 * @param integer queueID
333 * @param string actionName
335 WCF
.ACP
.Package
.Installation
= Class
.extend({
337 * package installation type
340 _actionName
: 'InstallPackage',
343 * true, if rollbacks are supported
346 _allowRollback
: false,
355 * name of the language item with the title of the dialog
362 * @var WCF.Action.Proxy
367 * package installation queue id
373 * true, if dialog should be rendered again
376 _shouldRender
: false,
379 * Initializes the WCF.ACP.Package.Installation class.
381 * @param integer queueID
382 * @param string actionName
383 * @param boolean allowRollback
384 * @param boolean isUpdate
386 init: function(queueID
, actionName
, allowRollback
, isUpdate
) {
387 this._actionName
= (actionName
) ? actionName
: 'InstallPackage';
388 this._allowRollback
= (allowRollback
=== true) ? true : false;
389 this._queueID
= queueID
;
391 switch (this._actionName
) {
392 case 'InstallPackage':
393 this._dialogTitle
= 'wcf.acp.package.' + (isUpdate
? 'update' : 'install') + '.title';
396 case 'UninstallPackage':
397 this._dialogTitle
= 'wcf.acp.package.uninstallation.title';
406 * Initializes the WCF.Action.Proxy object.
408 _initProxy: function() {
409 this._proxy
= new WCF
.Action
.Proxy({
410 failure
: $.proxy(this._failure
, this),
411 showLoadingOverlay
: false,
412 success
: $.proxy(this._success
, this),
413 url
: 'index.php/' + this._actionName
+ '/?t=' + SECURITY_TOKEN
+ SID_ARG_2ND
418 * Initializes the package installation.
421 $('#submitButton').click($.proxy(this.prepareInstallation
, this));
425 * Handles erroneous AJAX requests.
427 _failure: function() {
428 if (this._dialog
!== null) {
429 $('#packageInstallationProgress').removeAttr('value');
430 this._setIcon('remove');
433 if (!this._allowRollback
) {
437 if (this._dialog
!== null) {
438 this._purgeTemplateContent($.proxy(function() {
439 var $form
= $('<div class="formSubmit" />').appendTo($('#packageInstallationInnerContent'));
440 $('<button class="buttonPrimary">' + WCF
.Language
.get('wcf.acp.package.installation.rollback') + '</button>').appendTo($form
).click($.proxy(this._rollback
, this));
442 $('#packageInstallationInnerContentContainer').show();
444 this._dialog
.wcfDialog('render');
450 * Performs a rollback.
452 * @param object event
454 _rollback: function(event
) {
455 this._setIcon('spinner');
458 $(event
.currentTarget
).disable();
461 this._executeStep('rollback');
465 * Prepares installation dialog.
467 prepareInstallation: function() {
468 this._proxy
.setOption('data', this._getParameters());
469 this._proxy
.sendRequest();
473 * Returns parameters to prepare installation.
477 _getParameters: function() {
479 queueID
: this._queueID
,
485 * Handles successful AJAX requests.
488 * @param string textStatus
489 * @param jQuery jqXHR
491 _success: function(data
, textStatus
, jqXHR
) {
492 this._shouldRender
= false;
494 if (this._dialog
=== null) {
495 this._dialog
= $('<div id="packageInstallationDialog" />').hide().appendTo(document
.body
);
496 this._dialog
.wcfDialog({
498 title
: WCF
.Language
.get(this._dialogTitle
)
502 this._setIcon('spinner');
504 if (data
.step
== 'rollback') {
505 this._dialog
.wcfDialog('close');
506 this._dialog
.remove();
508 new WCF
.PeriodicalExecuter(function(pe
) {
511 var $uninstallation
= new WCF
.ACP
.Package
.Uninstallation();
512 $uninstallation
.start(data
.packageID
);
518 // receive new queue id
520 this._queueID
= data
.queueID
;
524 if (data
.template
&& !data
.ignoreTemplate
) {
525 this._dialog
.html(data
.template
);
526 this._shouldRender
= true;
531 $('#packageInstallationProgress').attr('value', data
.progress
).text(data
.progress
+ '%');
532 $('#packageInstallationProgressLabel').text(data
.progress
+ '%');
536 if (data
.currentAction
) {
537 $('#packageInstallationAction').html(data
.currentAction
);
541 if (data
.step
=== 'success') {
544 this._purgeTemplateContent($.proxy(function() {
545 var $form
= $('<div class="formSubmit" />').appendTo($('#packageInstallationInnerContent'));
546 var $button
= $('<button class="buttonPrimary">' + WCF
.Language
.get('wcf.global.button.next') + '</button>').appendTo($form
).click(function() {
548 window
.location
= data
.redirectLocation
;
551 $('#packageInstallationInnerContentContainer').show();
553 $(document
).keydown(function(event
) {
554 if (event
.which
=== $.ui
.keyCode
.ENTER
) {
555 $button
.trigger('click');
559 this._dialog
.wcfDialog('render');
565 // handle inner template
566 if (data
.innerTemplate
) {
568 $('#packageInstallationInnerContent').html(data
.innerTemplate
).find('input').keyup(function(event
) {
569 if (event
.keyCode
=== $.ui
.keyCode
.ENTER
) {
574 // create button to handle next step
575 if (data
.step
&& data
.node
) {
576 $('#packageInstallationProgress').removeAttr('value');
577 this._setIcon('question');
579 var $form
= $('<div class="formSubmit" />').appendTo($('#packageInstallationInnerContent'));
580 $('<button class="buttonPrimary">' + WCF
.Language
.get('wcf.global.button.next') + '</button>').appendTo($form
).click($.proxy(function(event
) {
581 $(event
.currentTarget
).disable();
587 $('#packageInstallationInnerContentContainer').show();
589 this._dialog
.wcfDialog('render');
594 this._purgeTemplateContent($.proxy(function() {
596 if (this._shouldRender
) {
597 this._dialog
.wcfDialog('render');
601 if (data
.step
&& data
.node
) {
602 this._executeStep(data
.step
, data
.node
);
608 * Submits the dialog content.
612 _submit: function(data
) {
613 this._setIcon('spinner');
615 // collect form values
616 var $additionalData
= {};
617 $('#packageInstallationInnerContent input').each(function(index
, inputElement
) {
618 var $inputElement
= $(inputElement
);
619 var $type
= $inputElement
.attr('type');
621 if (($type
!= 'checkbox' && $type
!= 'radio') || $inputElement
.prop('checked')) {
622 var $name
= $inputElement
.attr('name');
623 if ($name
.match(/(.*)\[([^[]*)\]$/)) {
627 if ($additionalData
[$name
] === undefined) {
629 $additionalData
[$name
] = { };
632 $additionalData
[$name
] = [ ];
637 $additionalData
[$name
][$key
] = $inputElement
.val();
640 $additionalData
[$name
].push($inputElement
.val());
644 $additionalData
[$name
] = $inputElement
.val();
649 this._executeStep(data
.step
, data
.node
, $additionalData
);
653 * Purges template content.
655 * @param function callback
657 _purgeTemplateContent: function(callback
) {
658 if ($('#packageInstallationInnerContent').children().length
> 1) {
659 $('#packageInstallationInnerContentContainer').wcfBlindOut('vertical', $.proxy(function() {
660 $('#packageInstallationInnerContent').empty();
661 this._shouldRender
= true;
673 * Executes the next installation step.
677 * @param object additionalData
679 _executeStep: function(step
, node
, additionalData
) {
680 if (!additionalData
) additionalData
= {};
682 var $data
= $.extend({
684 queueID
: this._queueID
,
688 this._proxy
.setOption('data', $data
);
689 this._proxy
.sendRequest();
693 * Sets the icon with the given name as the current installation status icon.
695 * @param string iconName
697 _setIcon: function(iconName
) {
698 this._dialog
.find('.jsPackageInstallationStatus').removeClass('icon-ok icon-question icon-remove icon-spinner').addClass('icon-' + iconName
);
703 * Handles canceling the package installation at the package installation
706 WCF
.ACP
.Package
.Installation
.Cancel
= Class
.extend({
708 * Creates a new instance of WCF.ACP.Package.Installation.Cancel.
710 * @param integer queueID
712 init: function(queueID
) {
713 $('#backButton').click(function() {
714 new WCF
.Action
.Proxy({
717 actionName
: 'cancelInstallation',
718 className
: 'wcf\\data\\package\\installation\\queue\\PackageInstallationQueueAction',
719 objectIDs
: [ queueID
]
721 success: function(data
) {
722 window
.location
= data
.returnValues
.url
;
730 * Provides the package uninstallation.
732 * @param jQuery elements
733 * @param string wcfPackageListURL
735 WCF
.ACP
.Package
.Uninstallation
= WCF
.ACP
.Package
.Installation
.extend({
737 * list of uninstallation buttons
749 * URL of WCF package list
752 _wcfPackageListURL
: '',
755 * Initializes the WCF.ACP.Package.Uninstallation class.
757 * @param jQuery elements
758 * @param string wcfPackageListURL
760 init: function(elements
, wcfPackageListURL
) {
761 this._elements
= elements
;
763 this._wcfPackageListURL
= wcfPackageListURL
;
765 if (this._elements
!== undefined && this._elements
.length
) {
766 this._super(0, 'UninstallPackage');
771 * Begins a package uninstallation without user action.
773 * @param integer packageID
775 start: function(packageID
) {
776 this._actionName
= 'UninstallPackage';
777 this._packageID
= packageID
;
779 this._dialogTitle
= 'wcf.acp.package.uninstallation.title';
782 this.prepareInstallation();
786 * @see WCF.ACP.Package.Installation.init()
789 this._elements
.click($.proxy(this._showConfirmationDialog
, this));
793 * Displays a confirmation dialog prior to package uninstallation.
795 * @param object event
797 _showConfirmationDialog: function(event
) {
798 var $element
= $(event
.currentTarget
);
800 if ($element
.data('isApplication') && this._wcfPackageListURL
) {
801 window
.location
= WCF
.String
.unescapeHTML(this._wcfPackageListURL
.replace(/{packageID}/, $element
.data('objectID')));
806 WCF
.System
.Confirmation
.show($element
.data('confirmMessage'), function(action
) {
807 if (action
=== 'confirm') {
808 self
._packageID
= $element
.data('objectID');
809 self
.prepareInstallation();
815 * @see WCF.ACP.Package.Installation._getParameters()
817 _getParameters: function() {
819 packageID
: this._packageID
,
826 * Manages package search.
828 WCF
.ACP
.Package
.Search
= Class
.extend({
836 * list of cached pages
854 * package input field
860 * package description input field
863 _packageDescription
: null,
866 * package name input field
872 * package search result container
875 _packageSearchResultContainer
: null,
878 * package search result list
881 _packageSearchResultList
: null,
897 * @var WCF.Action:proxy
908 * currently selected package
911 _selectedPackage
: '',
914 * currently selected package's version
916 _selectedPackageVersion
: '',
919 * Initializes the WCF.ACP.Package.Seach class.
924 this._container
= $('#packageSearch');
926 this._package
= null;
927 this._packageName
= null;
928 this._packageSearchResultContainer
= $('#packageSearchResultContainer');
929 this._packageSearchResultList
= $('#packageSearchResultList');
932 this._searchDescription
= null;
934 this._selectedPackage
= '';
935 this._selectedPackageVersion
= '';
937 this._proxy
= new WCF
.Action
.Proxy({
938 success
: $.proxy(this._success
, this)
941 this._initElements();
945 * Initializes search elements.
947 _initElements: function() {
948 this._button
= this._container
.find('.formSubmit > button.jsButtonPackageSearch').disable().click($.proxy(this._search
, this));
950 this._package
= $('#package').keyup($.proxy(this._keyUp
, this));
951 this._packageDescription
= $('#packageDescription').keyup($.proxy(this._keyUp
, this));
952 this._packageName
= $('#packageName').keyup($.proxy(this._keyUp
, this));
956 * Handles the 'keyup' event.
958 _keyUp: function(event
) {
959 if (this._package
.val() === '' && this._packageDescription
.val() === '' && this._packageName
.val() === '') {
960 this._button
.disable();
963 this._button
.enable();
966 if (event
.which
=== 13) {
967 this._button
.trigger('click');
973 * Performs a new search.
975 _search: function() {
976 var $values
= this._getSearchValues();
977 if (!this._validate($values
)) {
981 $values
.pageNo
= this._pageNo
;
982 this._proxy
.setOption('data', {
983 actionName
: 'search',
984 className
: 'wcf\\data\\package\\update\\PackageUpdateAction',
987 this._proxy
.sendRequest();
991 * Returns search values.
995 _getSearchValues: function() {
997 'package': $.trim(this._package
.val()),
998 packageDescription
: $.trim(this._packageDescription
.val()),
999 packageName
: $.trim(this._packageName
.val())
1004 * Validates search values.
1006 * @param object values
1009 _validate: function(values
) {
1010 if (values
['package'] === '' && values
['packageDescription'] === '' && values
['packageName'] === '') {
1018 * Handles successful AJAX requests.
1020 * @param object data
1021 * @param string textStatus
1022 * @param jQuery jqXHR
1024 _success: function(data
, textStatus
, jqXHR
) {
1025 switch (data
.actionName
) {
1026 case 'getResultList':
1027 this._insertTemplate(data
.returnValues
.template
);
1030 case 'prepareInstallation':
1031 if (data
.returnValues
.queueID
) {
1032 if (this._dialog
!== null) {
1033 this._dialog
.wcfDialog('close');
1036 var $installation
= new WCF
.ACP
.Package
.Installation(data
.returnValues
.queueID
, undefined, false);
1037 $installation
.prepareInstallation();
1039 else if (data
.returnValues
.template
) {
1040 if (this._dialog
=== null) {
1041 this._dialog
= $('<div>' + data
.returnValues
.template
+ '</div>').hide().appendTo(document
.body
);
1042 this._dialog
.wcfDialog({
1043 title
: WCF
.Language
.get('wcf.acp.package.update.unauthorized')
1047 this._dialog
.html(data
.returnValues
.template
).wcfDialog('open');
1050 this._dialog
.find('.formSubmit > button').click($.proxy(this._submitAuthentication
, this));
1055 this._pageCount
= data
.returnValues
.pageCount
;
1056 this._searchID
= data
.returnValues
.searchID
;
1058 this._insertTemplate(data
.returnValues
.template
, (data
.returnValues
.count
=== undefined ? undefined : data
.returnValues
.count
));
1059 this._setupPagination();
1065 * Submits authentication data for current update server.
1067 * @param object event
1069 _submitAuthentication: function(event
) {
1070 var $usernameField
= $('#packageUpdateServerUsername');
1071 var $passwordField
= $('#packageUpdateServerPassword');
1073 // remove error messages if any
1074 $usernameField
.next('small.innerError').remove();
1075 $passwordField
.next('small.innerError').remove();
1077 var $continue = true;
1078 if ($.trim($usernameField
.val()) === '') {
1079 $('<small class="innerError">' + WCF
.Language
.get('wcf.global.form.error.empty') + '</small>').insertAfter($usernameField
);
1083 if ($.trim($passwordField
.val()) === '') {
1084 $('<small class="innerError">' + WCF
.Language
.get('wcf.global.form.error.empty') + '</small>').insertAfter($passwordField
);
1089 this._prepareInstallation($(event
.currentTarget
).data('packageUpdateServerID'));
1094 * Inserts search result list template.
1096 * @param string template
1097 * @param integer count
1099 _insertTemplate: function(template
, count
) {
1100 this._packageSearchResultContainer
.show();
1102 this._packageSearchResultList
.html(template
);
1103 if (count
=== undefined) {
1104 this._content
[this._pageNo
] = template
;
1107 // update badge count
1108 if (count
!== undefined) {
1109 this._content
= { 1: template
};
1110 this._packageSearchResultContainer
.find('> header > h2 > .badge').html(count
);
1114 this._packageSearchResultList
.find('.jsInstallPackage').click($.proxy(this._click
, this));
1118 * Prepares a package installation.
1120 * @param object event
1122 _click: function(event
) {
1123 var $button
= $(event
.currentTarget
);
1124 WCF
.System
.Confirmation
.show($button
.data('confirmMessage'), $.proxy(function(action
) {
1125 if (action
=== 'confirm') {
1126 this._selectedPackage
= $button
.data('package');
1127 this._selectedPackageVersion
= $button
.data('packageVersion');
1128 this._prepareInstallation();
1134 * Prepares package installation.
1136 * @param integer packageUpdateServerID
1138 _prepareInstallation: function(packageUpdateServerID
) {
1142 $parameters
['packages'][this._selectedPackage
] = this._selectedPackageVersion
;
1144 if (packageUpdateServerID
) {
1145 $parameters
.authData
= {
1146 packageUpdateServerID
: packageUpdateServerID
,
1147 password
: $.trim($('#packageUpdateServerPassword').val()),
1148 saveCredentials
: ($('#packageUpdateServerSaveCredentials:checked').length
? true : false),
1149 username
: $.trim($('#packageUpdateServerUsername').val())
1153 this._proxy
.setOption('data', {
1154 actionName
: 'prepareInstallation',
1155 className
: 'wcf\\data\\package\\update\\PackageUpdateAction',
1156 parameters
: $parameters
1158 this._proxy
.sendRequest();
1162 * Setups pagination for current search.
1164 _setupPagination: function() {
1165 // remove previous instances
1166 this._content
= { 1: this._packageSearchResultList
.html() };
1167 this._packageSearchResultContainer
.find('.pageNavigation').wcfPages('destroy').remove();
1169 if (this._pageCount
> 1) {
1170 // TODO: Fix ui.wcfPages to properly synchronize multiple instances without triggering events
1171 /*$('<div class="contentNavigation" />').insertBefore(this._packageSearchResultList).wcfPages({
1172 activePage: this._pageNo,
1173 maxPage: this._pageCount
1174 }).on('wcfpagesswitched', $.proxy(this._showPage, this));*/
1176 $('<div class="contentNavigation" />').insertAfter(this._packageSearchResultList
).wcfPages({
1177 activePage
: this._pageNo
,
1178 maxPage
: this._pageCount
1179 }).on('wcfpagesswitched', $.proxy(this._showPage
, this));
1184 * Displays requested pages or loads it.
1186 * @param object event
1187 * @param object data
1189 _showPage: function(event
, data
) {
1190 if (data
&& data
.activePage
) {
1191 this._pageNo
= data
.activePage
;
1195 if (this._pageNo
< 1 || this._pageNo
> this._pageCount
) {
1196 console
.debug("[WCF.ACP.Package.Search] Cannot access page " + this._pageNo
+ " of " + this._pageCount
);
1201 if (this._content
[this._pageNo
] === undefined) {
1202 this._proxy
.setOption('data', {
1203 actionName
: 'getResultList',
1204 className
: 'wcf\\data\\package\\update\\PackageUpdateAction',
1206 pageNo
: this._pageNo
,
1207 searchID
: this._searchID
1210 this._proxy
.sendRequest();
1213 // show cached content
1214 this._packageSearchResultList
.html(this._content
[this._pageNo
]);
1216 WCF
.DOMNodeInsertedHandler
.execute();
1222 * Namespace for package update related classes.
1224 WCF
.ACP
.Package
.Update
= { };
1227 * Handles the package update process.
1229 WCF
.ACP
.Package
.Update
.Manager
= Class
.extend({
1238 * @var WCF.Action.Proxy
1246 _submitButton
: null,
1249 * Initializes the WCF.ACP.Package.Update.Manager class.
1252 this._dialog
= null;
1253 this._submitButton
= $('.formSubmit > button').click($.proxy(this._click
, this));
1255 this._proxy
= new WCF
.Action
.Proxy({
1256 success
: $.proxy(this._success
, this)
1259 $('.jsPackageUpdate').each($.proxy(function(index
, packageUpdate
) {
1260 var $packageUpdate
= $(packageUpdate
);
1261 $packageUpdate
.find('input[type=checkbox]').data('packageUpdate', $packageUpdate
).change($.proxy(this._change
, this));
1266 * Handles toggles for a specific update.
1268 _change: function(event
) {
1269 var $checkbox
= $(event
.currentTarget
);
1271 if ($checkbox
.is(':checked')) {
1272 $checkbox
.data('packageUpdate').find('select').enable();
1273 $checkbox
.data('packageUpdate').find('dl').removeClass('disabled');
1275 this._submitButton
.enable();
1278 $checkbox
.data('packageUpdate').find('select').disable();
1279 $checkbox
.data('packageUpdate').find('dl').addClass('disabled');
1281 // disable submit button
1282 if (!$('input[type=checkbox]:checked').length
) {
1283 this._submitButton
.disable();
1289 * Handles clicks on the submit button.
1291 * @param object event
1292 * @param integer packageUpdateServerID
1294 _click: function(event
, packageUpdateServerID
) {
1295 var $packages
= { };
1296 $('.jsPackageUpdate').each($.proxy(function(index
, packageUpdate
) {
1297 var $packageUpdate
= $(packageUpdate
);
1298 if ($packageUpdate
.find('input[type=checkbox]:checked').length
) {
1299 $packages
[$packageUpdate
.data('package')] = $packageUpdate
.find('select').val();
1303 if ($.getLength($packages
)) {
1304 this._submitButton
.disable();
1309 if (packageUpdateServerID
) {
1310 $parameters
.authData
= {
1311 packageUpdateServerID
: packageUpdateServerID
,
1312 password
: $.trim($('#packageUpdateServerPassword').val()),
1313 saveCredentials
: ($('#packageUpdateServerSaveCredentials:checked').length
? true : false),
1314 username
: $.trim($('#packageUpdateServerUsername').val())
1318 this._proxy
.setOption('data', {
1319 actionName
: 'prepareUpdate',
1320 className
: 'wcf\\data\\package\\update\\PackageUpdateAction',
1321 parameters
: $parameters
,
1323 this._proxy
.sendRequest();
1328 * Handles successful AJAX requests.
1330 * @param object data
1331 * @param string textStatus
1332 * @param jQuery jqXHR
1334 _success: function(data
, textStatus
, jqXHR
) {
1335 if (data
.returnValues
.queueID
) {
1336 if (this._dialog
!== null) {
1337 this._dialog
.wcfDialog('close');
1340 var $installation
= new WCF
.ACP
.Package
.Installation(data
.returnValues
.queueID
, undefined, false, true);
1341 $installation
.prepareInstallation();
1343 else if (data
.returnValues
.template
) {
1344 if (this._dialog
=== null) {
1345 this._dialog
= $('<div>' + data
.returnValues
.template
+ '</div>').hide().appendTo(document
.body
);
1346 this._dialog
.wcfDialog({
1347 title
: WCF
.Language
.get('wcf.acp.package.update.unauthorized')
1351 this._dialog
.html(data
.returnValues
.template
).wcfDialog('open');
1354 this._dialog
.find('.formSubmit > button').click($.proxy(this._submitAuthentication
, this));
1359 * Submits authentication data for current update server.
1361 * @param object event
1363 _submitAuthentication: function(event
) {
1364 var $usernameField
= $('#packageUpdateServerUsername');
1365 var $passwordField
= $('#packageUpdateServerPassword');
1367 // remove error messages if any
1368 $usernameField
.next('small.innerError').remove();
1369 $passwordField
.next('small.innerError').remove();
1371 var $continue = true;
1372 if ($.trim($usernameField
.val()) === '') {
1373 $('<small class="innerError">' + WCF
.Language
.get('wcf.global.form.error.empty') + '</small>').insertAfter($usernameField
);
1377 if ($.trim($passwordField
.val()) === '') {
1378 $('<small class="innerError">' + WCF
.Language
.get('wcf.global.form.error.empty') + '</small>').insertAfter($passwordField
);
1383 this._click(undefined, $(event
.currentTarget
).data('packageUpdateServerID'));
1389 * Searches for available updates.
1391 WCF
.ACP
.Package
.Update
.Search
= Class
.extend({
1399 * initializes the WCF.ACP.Package.SearchForUpdates class.
1402 this._dialog
= null;
1404 var $button
= $('<li><a class="button"><span class="icon icon16 icon-refresh"></span> <span>' + WCF
.Language
.get('wcf.acp.package.searchForUpdates') + '</span></a></li>');
1405 $button
.click($.proxy(this._click
, this)).prependTo($('.contentNavigation:eq(0) > nav:not(.pageNavigation) > ul'));
1409 * Handles clicks on the search button.
1411 _click: function() {
1412 if (this._dialog
=== null) {
1413 new WCF
.Action
.Proxy({
1416 actionName
: 'searchForUpdates',
1417 className
: 'wcf\\data\\package\\update\\PackageUpdateAction',
1422 success
: $.proxy(this._success
, this)
1426 this._dialog
.wcfDialog('open');
1431 * Handles successful AJAX requests.
1433 * @param object data
1434 * @param string textStatus
1435 * @param jQuery jqXHR
1437 _success: function(data
, textStatus
, jqXHR
) {
1438 if (data
.returnValues
.url
) {
1439 window
.location
= data
.returnValues
.url
;
1442 this._dialog
= $('<div>' + WCF
.Language
.get('wcf.acp.package.searchForUpdates.noResults') + '</div>').hide().appendTo(document
.body
);
1443 this._dialog
.wcfDialog({
1444 title
: WCF
.Language
.get('wcf.acp.package.searchForUpdates')
1451 * Handles option selection.
1453 WCF
.ACP
.Options
= Class
.extend({
1455 * Initializes options.
1458 $('.jsEnablesOptions').each($.proxy(this._initOption
, this));
1462 * Initializes an option.
1464 * @param integer index
1465 * @param object option
1467 _initOption: function(index
, option
) {
1468 // execute action on init
1469 this._change(option
);
1471 // bind event listener
1472 $(option
).change($.proxy(this._handleChange
, this));
1476 * Applies whenever an option is changed.
1478 * @param object event
1480 _handleChange: function(event
) {
1481 this._change($(event
.target
));
1485 * Enables or disables options on option value change.
1487 * @param object option
1489 _change: function(option
) {
1492 var $disableOptions
= eval(option
.data('disableOptions'));
1493 var $enableOptions
= eval(option
.data('enableOptions'));
1495 // determine action by type
1496 switch(option
.getTagName()) {
1498 switch(option
.attr('type')) {
1500 this._execute(option
.prop('checked'), $disableOptions
, $enableOptions
);
1504 if (option
.prop('checked')) {
1505 this._execute(true, $disableOptions
, $enableOptions
);
1512 var $value
= option
.val();
1513 var $disableOptions
= $enableOptions
= [];
1515 if (option
.data('disableOptions').length
> 0) {
1516 for (var $index
in option
.data('disableOptions')) {
1517 var $item
= option
.data('disableOptions')[$index
];
1519 if ($item
.value
== $value
) {
1520 $disableOptions
.push($item
.option
);
1525 if (option
.data('enableOptions').length
> 0) {
1526 for (var $index
in option
.data('enableOptions')) {
1527 var $item
= option
.data('enableOptions')[$index
];
1529 if ($item
.value
== $value
) {
1530 $enableOptions
.push($item
.option
);
1535 this._execute(true, $disableOptions
, $enableOptions
);
1541 * Enables or disables options.
1543 * @param boolean isActive
1544 * @param array disableOptions
1545 * @param array enableOptions
1547 _execute: function(isActive
, disableOptions
, enableOptions
) {
1548 if (disableOptions
.length
> 0) {
1549 for (var $i
= 0, $size
= disableOptions
.length
; $i
< $size
; $i
++) {
1550 var $target
= disableOptions
[$i
];
1551 if ($.wcfIsset($target
)) {
1552 this._enableOption($target
, !isActive
);
1557 if (enableOptions
.length
> 0) {
1558 for (var $i
= 0, $size
= enableOptions
.length
; $i
< $size
; $i
++) {
1559 var $target
= enableOptions
[$i
];
1560 if ($.wcfIsset($target
)) {
1561 this._enableOption($target
, isActive
);
1568 * Enables an option.
1570 * @param string target
1571 * @param boolean enable
1573 _enableOption: function(target
, enable
) {
1574 var $targetElement
= $('#' + $.wcfEscapeID(target
));
1575 var $tagName
= $targetElement
.getTagName();
1577 if ($tagName
== 'select' || ($tagName
== 'input' && ($targetElement
.attr('type') == 'checkbox' || $targetElement
.attr('type') == 'radio'))) {
1578 if (enable
) $targetElement
.enable();
1579 else $targetElement
.disable();
1582 if (enable
) $targetElement
.removeAttr('readonly');
1583 else $targetElement
.attr('readonly', true);
1587 $targetElement
.closest('dl').removeClass('disabled');
1590 $targetElement
.closest('dl').addClass('disabled');
1596 * Worker support for ACP.
1598 * @param string dialogID
1599 * @param string className
1600 * @param string title
1601 * @param object parameters
1602 * @param object callback
1604 WCF
.ACP
.Worker
= Class
.extend({
1612 * callback invoked after worker completed
1631 * @var WCF.Action.Proxy
1642 * Initializes a new worker instance.
1644 * @param string dialogID
1645 * @param string className
1646 * @param string title
1647 * @param object parameters
1648 * @param object callback
1649 * @param object confirmMessage
1651 init: function(dialogID
, className
, title
, parameters
, callback
) {
1652 this._aborted
= false;
1653 this._callback
= callback
|| null;
1654 this._dialogID
= dialogID
+ 'Worker';
1655 this._dialog
= null;
1656 this._proxy
= new WCF
.Action
.Proxy({
1659 className
: className
,
1660 parameters
: parameters
|| { }
1662 showLoadingOverlay
: false,
1663 success
: $.proxy(this._success
, this),
1664 url
: 'index.php/WorkerProxy/?t=' + SECURITY_TOKEN
+ SID_ARG_2ND
1666 this._title
= title
;
1670 * Handles response from server.
1672 * @param object data
1674 _success: function(data
) {
1676 if (this._dialog
=== null) {
1677 this._dialog
= $('<div id="' + this._dialogID
+ '" />').hide().appendTo(document
.body
);
1678 this._dialog
.wcfDialog({
1679 closeConfirmMessage
: WCF
.Language
.get('wcf.acp.worker.abort.confirmMessage'),
1680 closeViaModal
: false,
1681 onClose
: $.proxy(function() {
1682 this._aborted
= true;
1683 this._proxy
.abortPrevious();
1685 window
.location
.reload();
1691 if (this._aborted
) {
1695 if (data
.template
) {
1696 this._dialog
.html(data
.template
);
1700 this._dialog
.find('progress').attr('value', data
.progress
).text(data
.progress
+ '%').next('span').text(data
.progress
+ '%');
1702 // worker is still busy with it's business, carry on
1703 if (data
.progress
< 100) {
1704 // send request for next loop
1705 this._proxy
.setOption('data', {
1706 className
: data
.className
,
1707 loopCount
: data
.loopCount
,
1708 parameters
: data
.parameters
1710 this._proxy
.sendRequest();
1712 else if (this._callback
!== null) {
1713 this._callback(this, data
);
1716 // display continue button
1717 var $formSubmit
= $('<div class="formSubmit" />').appendTo(this._dialog
);
1718 $('<button class="buttonPrimary">' + WCF
.Language
.get('wcf.global.button.next') + '</button>').appendTo($formSubmit
).click(function() { window
.location
= data
.proceedURL
; });
1720 this._dialog
.wcfDialog('render');
1726 * Namespace for category-related functions.
1728 WCF
.ACP
.Category
= {};
1731 * Handles collapsing categories.
1733 * @param string className
1734 * @param integer objectTypeID
1736 WCF
.ACP
.Category
.Collapsible
= WCF
.Collapsible
.SimpleRemote
.extend({
1738 * @see WCF.Collapsible.Remote.init()
1740 init: function(className
) {
1741 var sortButton
= $('.formSubmit > button[data-type="submit"]');
1743 sortButton
.click($.proxy(this._sort
, this));
1746 this._super(className
);
1750 * @see WCF.Collapsible.Remote._getButtonContainer()
1752 _getButtonContainer: function(containerID
) {
1753 return $('#' + containerID
+ ' > .buttons');
1757 * @see WCF.Collapsible.Remote._getContainers()
1759 _getContainers: function() {
1760 return $('.jsCategory').has('ol').has('li');
1764 * @see WCF.Collapsible.Remote._getTarget()
1766 _getTarget: function(containerID
) {
1767 return $('#' + containerID
+ ' > ol');
1771 * Handles a click on the sort button.
1774 // remove existing collapsible buttons
1775 $('.collapsibleButton').remove();
1777 // reinit containers
1778 this._containers
= {};
1779 this._containerData
= {};
1781 var $containers
= this._getContainers();
1782 if ($containers
.length
== 0) {
1783 console
.debug('[WCF.ACP.Category.Collapsible] Empty container set given, aborting.');
1785 $containers
.each($.proxy(function(index
, container
) {
1786 var $container
= $(container
);
1787 var $containerID
= $container
.wcfIdentify();
1788 this._containers
[$containerID
] = $container
;
1790 this._initContainer($containerID
);
1796 * Provides the search dropdown for ACP
1798 * @see WCF.Search.Base
1800 WCF
.ACP
.Search
= WCF
.Search
.Base
.extend({
1802 * @see WCF.Search.Base.init()
1805 this._className
= 'wcf\\data\\acp\\search\\provider\\ACPSearchProviderAction';
1806 this._super('#search input[name=q]');
1808 // disable form submitting
1809 $('#search > form').on('submit', function(event
) {
1810 event
.preventDefault();
1815 * @see WCF.Search.Base._createListItem()
1817 _createListItem: function(resultList
) {
1818 // add a divider between result lists
1819 if (this._list
.children('li').length
> 0) {
1820 $('<li class="dropdownDivider" />').appendTo(this._list
);
1824 $('<li class="dropdownText">' + resultList
.title
+ '</li>').appendTo(this._list
);
1827 for (var $i
in resultList
.items
) {
1828 var $item
= resultList
.items
[$i
];
1830 $('<li><a href="' + $item
.link
+ '">' + WCF
.String
.escapeHTML($item
.title
) + '</a></li>').appendTo(this._list
);
1837 * @see WCF.Search.Base._handleEmptyResult()
1839 _handleEmptyResult: function() {
1840 $('<li class="dropdownText">' + WCF
.Language
.get('wcf.acp.search.noResults') + '</li>').appendTo(this._list
);
1846 * @see WCF.Search.Base._highlightSelectedElement()
1848 _highlightSelectedElement: function() {
1849 this._list
.find('li').removeClass('dropdownNavigationItem');
1850 this._list
.find('li:not(.dropdownDivider):not(.dropdownText)').eq(this._itemIndex
).addClass('dropdownNavigationItem');
1854 * @see WCF.Search.Base._selectElement()
1856 _selectElement: function(event
) {
1857 if (this._itemIndex
=== -1) {
1861 window
.location
= this._list
.find('li.dropdownNavigationItem > a').attr('href');
1866 * Namespace for user management.
1871 * Generic implementation to ban users.
1873 WCF
.ACP
.User
.BanHandler
= {
1888 * @var WCF.Action.Proxy
1893 * Initializes WCF.ACP.User.BanHandler on first use.
1896 this._dialog
= $('<div />').hide().appendTo(document
.body
);
1897 this._proxy
= new WCF
.Action
.Proxy({
1898 success
: $.proxy(this._success
, this)
1901 $('.jsBanButton').click($.proxy(function(event
) {
1902 var $button
= $(event
.currentTarget
);
1903 if ($button
.data('banned')) {
1904 this.unban([ $button
.data('objectID') ]);
1907 this.ban([ $button
.data('objectID') ]);
1912 $('.jsClipboardEditor').each($.proxy(function(index
, container
) {
1913 var $container
= $(container
);
1914 var $types
= eval($container
.data('types'));
1915 if (WCF
.inArray('com.woltlab.wcf.user', $types
)) {
1916 $container
.on('clipboardAction', $.proxy(this._execute
, this));
1923 * Handles clipboard actions.
1925 * @param object event
1926 * @param string type
1927 * @param string actionName
1928 * @param object parameters
1930 _execute: function(event
, type
, actionName
, parameters
) {
1931 if (actionName
== 'com.woltlab.wcf.user.ban') {
1932 this.ban(parameters
.objectIDs
);
1939 * @param array<integer> userIDs
1941 unban: function(userIDs
) {
1942 this._proxy
.setOption('data', {
1943 actionName
: 'unban',
1944 className
: 'wcf\\data\\user\\UserAction',
1947 this._proxy
.sendRequest();
1953 * @param array<integer> userIDs
1955 ban: function(userIDs
) {
1956 WCF
.System
.Confirmation
.show(WCF
.Language
.get('wcf.acp.user.ban.sure'), $.proxy(function(action
) {
1957 if (action
=== 'confirm') {
1958 this._proxy
.setOption('data', {
1960 className
: 'wcf\\data\\user\\UserAction',
1963 banReason
: $('#userBanReason').val()
1966 this._proxy
.sendRequest();
1968 }, this), '', $('<fieldset><dl><dt><label for="userBanReason">' + WCF
.Language
.get('wcf.acp.user.banReason') + '</label></dt><dd><textarea id="userBanReason" cols="40" rows="3" /><small>' + WCF
.Language
.get('wcf.acp.user.banReason.description') + '</small></dd></dl></fieldset>'));
1972 * Handles successful AJAX calls.
1974 * @param object data
1975 * @param string textStatus
1976 * @param jQuery jqXHR
1978 _success: function(data
, textStatus
, jqXHR
) {
1979 $('.jsBanButton').each(function(index
, button
) {
1980 var $button
= $(button
);
1981 if (WCF
.inArray($button
.data('objectID'), data
.objectIDs
)) {
1982 if (data
.actionName
== 'unban') {
1983 $button
.data('banned', false).data('tooltip', $button
.data('banMessage')).removeClass('icon-lock').addClass('icon-unlock');
1986 $button
.data('banned', true).data('tooltip', $button
.data('unbanMessage')).removeClass('icon-unlock').addClass('icon-lock');
1991 var $notification
= new WCF
.System
.Notification();
1992 $notification
.show();
1994 WCF
.Clipboard
.reload();
1999 * Generic implementation to enable users.
2001 WCF
.ACP
.User
.EnableHandler
= {
2004 * @var WCF.Action.Proxy
2009 * Initializes WCF.ACP.User.EnableHandler on first use.
2012 this._proxy
= new WCF
.Action
.Proxy({
2013 success
: $.proxy(this._success
, this)
2016 $('.jsEnableButton').click($.proxy(function(event
) {
2017 var $button
= $(event
.currentTarget
);
2018 if ($button
.data('enabled')) {
2019 this.disable([ $button
.data('objectID') ]);
2022 this.enable([ $button
.data('objectID') ]);
2027 $('.jsClipboardEditor').each($.proxy(function(index
, container
) {
2028 var $container
= $(container
);
2029 var $types
= eval($container
.data('types'));
2030 if (WCF
.inArray('com.woltlab.wcf.user', $types
)) {
2031 $container
.on('clipboardAction', $.proxy(this._execute
, this));
2038 * Handles clipboard actions.
2040 * @param object event
2041 * @param string type
2042 * @param string actionName
2043 * @param object parameters
2045 _execute: function(event
, type
, actionName
, parameters
) {
2046 if (actionName
== 'com.woltlab.wcf.user.enable') {
2047 this.enable(parameters
.objectIDs
);
2054 * @param array<integer> userIDs
2056 disable: function(userIDs
) {
2057 this._proxy
.setOption('data', {
2058 actionName
: 'disable',
2059 className
: 'wcf\\data\\user\\UserAction',
2062 this._proxy
.sendRequest();
2068 * @param array<integer> userIDs
2070 enable: function(userIDs
) {
2071 this._proxy
.setOption('data', {
2072 actionName
: 'enable',
2073 className
: 'wcf\\data\\user\\UserAction',
2076 this._proxy
.sendRequest();
2080 * Handles successful AJAX calls.
2082 * @param object data
2083 * @param string textStatus
2084 * @param jQuery jqXHR
2086 _success: function(data
, textStatus
, jqXHR
) {
2087 $('.jsEnableButton').each(function(index
, button
) {
2088 var $button
= $(button
);
2089 if (WCF
.inArray($button
.data('objectID'), data
.objectIDs
)) {
2090 if (data
.actionName
== 'disable') {
2091 $button
.data('enabled', false).data('tooltip', $button
.data('enableMessage')).removeClass('icon-check').addClass('icon-check-empty');
2094 $button
.data('enabled', true).data('tooltip', $button
.data('disableMessage')).removeClass('icon-check-empty').addClass('icon-check');
2099 var $notification
= new WCF
.System
.Notification();
2100 $notification
.show(function() { window
.location
.reload(); });
2105 * Namespace for import-related classes.
2107 WCF
.ACP
.Import
= { };
2112 * @param array<string> objectTypes
2114 WCF
.ACP
.Import
.Manager
= Class
.extend({
2128 * current object type index
2134 * list of object types
2135 * @var array<string>
2141 * @var WCF.Action.Proxy
2152 * Initializes the WCF.ACP.Importer object.
2154 * @param array<string> objectTypes
2155 * @param string redirectURL
2157 init: function(objectTypes
, redirectURL
) {
2158 this._currentAction
= '';
2160 this._objectTypes
= objectTypes
;
2161 this._proxy
= new WCF
.Action
.Proxy({
2162 showLoadingOverlay
: false,
2163 success
: $.proxy(this._success
, this),
2164 url
: 'index.php/WorkerProxy/?t=' + SECURITY_TOKEN
+ SID_ARG_2ND
2166 this._redirectURL
= redirectURL
;
2172 * Invokes importing of an object type.
2174 _invoke: function() {
2176 if (this._index
>= this._objectTypes
.length
) {
2177 this._dialog
.find('.icon-spinner').removeClass('icon-spinner').addClass('icon-ok');
2178 this._dialog
.find('h1').text(WCF
.Language
.get('wcf.acp.dataImport.completed'));
2180 var $form
= $('<div class="formSubmit" />').appendTo(this._dialog
.find('#workerContainer'));
2181 $('<button>' + WCF
.Language
.get('wcf.global.button.next') + '</button>').click($.proxy(function() {
2182 new WCF
.Action
.Proxy({
2188 success
: $.proxy(function() {
2189 window
.location
= this._redirectURL
;
2191 url
: 'index.php/CacheClear/?t=' + SECURITY_TOKEN
+ SID_ARG_2ND
2193 }, this)).appendTo($form
);
2195 this._dialog
.wcfDialog('render');
2199 WCF
.Language
.get('wcf.acp.dataImport.data.' + this._objectTypes
[this._index
]),
2200 this._objectTypes
[this._index
]
2206 * Executes import of given object type.
2208 * @param string currentAction
2209 * @param string objectType
2211 _run: function(currentAction
, objectType
) {
2212 this._currentAction
= currentAction
;
2213 this._proxy
.setOption('data', {
2214 className
: 'wcf\\system\\worker\\ImportWorker',
2216 objectType
: objectType
2219 this._proxy
.sendRequest();
2223 * Handles response from server.
2225 * @param object data
2227 _success: function(data
) {
2229 if (this._dialog
=== null) {
2230 this._dialog
= $('<div />').hide().appendTo(document
.body
);
2231 this._dialog
.wcfDialog({
2233 title
: WCF
.Language
.get('wcf.acp.dataImport')
2237 if (data
.template
) {
2238 this._dialog
.html(data
.template
);
2241 if (this._currentAction
) {
2242 this._dialog
.find('h1').text(this._currentAction
);
2246 this._dialog
.find('progress').attr('value', data
.progress
).text(data
.progress
+ '%').next('span').text(data
.progress
+ '%');
2248 // worker is still busy with it's business, carry on
2249 if (data
.progress
< 100) {
2250 // send request for next loop
2251 this._proxy
.setOption('data', {
2252 className
: data
.className
,
2253 loopCount
: data
.loopCount
,
2254 parameters
: data
.parameters
2256 this._proxy
.sendRequest();