Commit | Line | Data |
---|---|---|
158bd3ca TD |
1 | /** |
2 | * Class and function collection for WCF ACP | |
3 | * | |
13d8b49b | 4 | * @author Alexander Ebert, Matthias Schmidt |
c839bd49 | 5 | * @copyright 2001-2018 WoltLab GmbH |
158bd3ca TD |
6 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
7 | */ | |
8 | ||
9 | /** | |
10 | * Initialize WCF.ACP namespace | |
11 | */ | |
cb6e5946 | 12 | WCF.ACP = { }; |
158bd3ca | 13 | |
1a8d655f AE |
14 | /** |
15 | * Namespace for ACP application management. | |
16 | */ | |
17 | WCF.ACP.Application = { }; | |
18 | ||
29873759 MS |
19 | /** |
20 | * Namespace for ACP cronjob management. | |
21 | */ | |
22 | WCF.ACP.Cronjob = { }; | |
23 | ||
02b148ad MS |
24 | /** |
25 | * Handles the manual execution of cronjobs. | |
26 | */ | |
27 | WCF.ACP.Cronjob.ExecutionHandler = Class.extend({ | |
28 | /** | |
29 | * notification object | |
30 | * @var WCF.System.Notification | |
31 | */ | |
32 | _notification: null, | |
33 | ||
34 | /** | |
35 | * action proxy | |
36 | * @var WCF.Action.Proxy | |
37 | */ | |
38 | _proxy: null, | |
39 | ||
40 | /** | |
41 | * Initializes WCF.ACP.Cronjob.ExecutionHandler object. | |
42 | */ | |
43 | init: function() { | |
44 | this._proxy = new WCF.Action.Proxy({ | |
45 | success: $.proxy(this._success, this) | |
46 | }); | |
47 | ||
48 | $('.jsCronjobRow .jsExecuteButton').click($.proxy(this._click, this)); | |
49 | ||
50 | this._notification = new WCF.System.Notification(WCF.Language.get('wcf.global.success'), 'success'); | |
51 | }, | |
52 | ||
53 | /** | |
54 | * Handles a click on an execute button. | |
55 | * | |
56 | * @param object event | |
57 | */ | |
58 | _click: function(event) { | |
59 | this._proxy.setOption('data', { | |
60 | actionName: 'execute', | |
61 | className: 'wcf\\data\\cronjob\\CronjobAction', | |
62 | objectIDs: [ $(event.target).data('objectID') ] | |
63 | }); | |
64 | ||
65 | this._proxy.sendRequest(); | |
66 | }, | |
67 | ||
68 | /** | |
69 | * Handles successful cronjob execution. | |
70 | * | |
71 | * @param object data | |
72 | * @param string textStatus | |
73 | * @param jQuery jqXHR | |
74 | */ | |
75 | _success: function(data, textStatus, jqXHR) { | |
76 | $('.jsCronjobRow').each($.proxy(function(index, row) { | |
77 | var $button = $(row).find('.jsExecuteButton'); | |
78 | var $objectID = ($button).data('objectID'); | |
79 | ||
80 | if (WCF.inArray($objectID, data.objectIDs)) { | |
81 | if (data.returnValues[$objectID]) { | |
82 | // insert feedback here | |
83 | $(row).find('td.columnNextExec').html(data.returnValues[$objectID].formatted); | |
84 | $(row).wcfHighlight(); | |
85 | } | |
86 | ||
87 | this._notification.show(); | |
88 | ||
89 | return false; | |
90 | } | |
91 | }, this)); | |
92 | } | |
93 | }); | |
94 | ||
29873759 MS |
95 | /** |
96 | * Handles the cronjob log list. | |
97 | */ | |
98 | WCF.ACP.Cronjob.LogList = Class.extend({ | |
99 | /** | |
100 | * error message dialog | |
101 | * @var jQuery | |
102 | */ | |
103 | _dialog: null, | |
104 | ||
105 | /** | |
106 | * Initializes WCF.ACP.Cronjob.LogList object. | |
107 | */ | |
108 | init: function() { | |
109 | // bind event listener to delete cronjob log button | |
110 | $('.jsCronjobLogDelete').click(function() { | |
111 | WCF.System.Confirmation.show(WCF.Language.get('wcf.acp.cronjob.log.clear.confirm'), function(action) { | |
112 | if (action == 'confirm') { | |
113 | new WCF.Action.Proxy({ | |
114 | autoSend: true, | |
115 | data: { | |
116 | actionName: 'clearAll', | |
117 | className: 'wcf\\data\\cronjob\\log\\CronjobLogAction' | |
118 | }, | |
119 | success: function() { | |
120 | window.location.reload(); | |
121 | } | |
122 | }); | |
123 | } | |
124 | }); | |
125 | }); | |
126 | ||
127 | // bind event listeners to error badges | |
128 | $('.jsCronjobError').click($.proxy(this._showError, this)); | |
129 | }, | |
130 | ||
131 | /** | |
132 | * Shows certain error message | |
133 | * | |
134 | * @param object event | |
135 | */ | |
136 | _showError: function(event) { | |
137 | var $errorBadge = $(event.currentTarget); | |
138 | ||
139 | if (this._dialog === null) { | |
cafc0b69 | 140 | this._dialog = $('<div style="overflow: auto"><pre>' + $errorBadge.next().html() + '</pre></div>').hide().appendTo(document.body); |
29873759 MS |
141 | this._dialog.wcfDialog({ |
142 | title: WCF.Language.get('wcf.acp.cronjob.log.error.details') | |
143 | }); | |
144 | } | |
145 | else { | |
cafc0b69 | 146 | this._dialog.html('<pre>' + $errorBadge.next().html() + '</pre>'); |
29873759 MS |
147 | this._dialog.wcfDialog('open'); |
148 | } | |
149 | } | |
150 | }); | |
151 | ||
e5b88a7f AE |
152 | /** |
153 | * Namespace for ACP package management. | |
154 | */ | |
3536d2fe | 155 | WCF.ACP.Package = { }; |
d71e5a29 | 156 | |
158bd3ca | 157 | /** |
cb9e9c12 | 158 | * Provides the package installation. |
158bd3ca | 159 | * |
158bd3ca | 160 | * @param integer queueID |
2ef79140 | 161 | * @param string actionName |
158bd3ca | 162 | */ |
cb9e9c12 | 163 | WCF.ACP.Package.Installation = Class.extend({ |
158bd3ca TD |
164 | /** |
165 | * package installation type | |
158bd3ca TD |
166 | * @var string |
167 | */ | |
cb9e9c12 | 168 | _actionName: 'InstallPackage', |
9f959ced | 169 | |
0acbb6be AE |
170 | /** |
171 | * true, if rollbacks are supported | |
172 | * @var boolean | |
173 | */ | |
174 | _allowRollback: false, | |
175 | ||
e5b88a7f | 176 | /** |
cb9e9c12 AE |
177 | * dialog object |
178 | * @var jQuery | |
158bd3ca TD |
179 | */ |
180 | _dialog: null, | |
181 | ||
6207cc21 MS |
182 | /** |
183 | * name of the language item with the title of the dialog | |
184 | * @var string | |
185 | */ | |
186 | _dialogTitle: '', | |
187 | ||
e5b88a7f AE |
188 | /** |
189 | * action proxy | |
190 | * @var WCF.Action.Proxy | |
191 | */ | |
192 | _proxy: null, | |
9f959ced | 193 | |
158bd3ca | 194 | /** |
cb9e9c12 | 195 | * package installation queue id |
158bd3ca TD |
196 | * @var integer |
197 | */ | |
198 | _queueID: 0, | |
9f959ced | 199 | |
ba133309 AE |
200 | /** |
201 | * true, if dialog should be rendered again | |
202 | * @var boolean | |
203 | */ | |
204 | _shouldRender: false, | |
205 | ||
0a3949d4 | 206 | /** |
cb9e9c12 | 207 | * Initializes the WCF.ACP.Package.Installation class. |
158bd3ca | 208 | * |
158bd3ca | 209 | * @param integer queueID |
2ef79140 | 210 | * @param string actionName |
0acbb6be | 211 | * @param boolean allowRollback |
adf9791d | 212 | * @param boolean isUpdate |
158bd3ca | 213 | */ |
adf9791d | 214 | init: function(queueID, actionName, allowRollback, isUpdate) { |
2ef79140 | 215 | this._actionName = (actionName) ? actionName : 'InstallPackage'; |
9d9aede4 | 216 | this._allowRollback = (allowRollback === true); |
158bd3ca | 217 | this._queueID = queueID; |
cb9e9c12 | 218 | |
3484b0ce | 219 | switch (this._actionName) { |
824d9e90 | 220 | case 'InstallPackage': |
328111b8 | 221 | this._dialogTitle = 'wcf.acp.package.' + (isUpdate ? 'update' : 'install') + '.title'; |
824d9e90 AE |
222 | break; |
223 | ||
224 | case 'UninstallPackage': | |
225 | this._dialogTitle = 'wcf.acp.package.uninstallation.title'; | |
226 | break; | |
6207cc21 MS |
227 | } |
228 | ||
0acbb6be AE |
229 | this._initProxy(); |
230 | this._init(); | |
231 | }, | |
232 | ||
233 | /** | |
234 | * Initializes the WCF.Action.Proxy object. | |
235 | */ | |
236 | _initProxy: function() { | |
e31cf611 AE |
237 | var $actionName = ''; |
238 | var $parts = this._actionName.split(/([A-Z][a-z0-9]+)/); | |
239 | for (var $i = 0, $length = $parts.length; $i < $length; $i++) { | |
240 | var $part = $parts[$i]; | |
241 | if ($part.length) { | |
242 | if ($actionName.length) $actionName += '-'; | |
243 | $actionName += $part.toLowerCase(); | |
244 | } | |
245 | } | |
246 | ||
e5b88a7f | 247 | this._proxy = new WCF.Action.Proxy({ |
cb9e9c12 | 248 | failure: $.proxy(this._failure, this), |
324e8301 | 249 | showLoadingOverlay: false, |
cb9e9c12 | 250 | success: $.proxy(this._success, this), |
772f616f | 251 | url: 'index.php?' + $actionName + '/&t=' + SECURITY_TOKEN |
e5b88a7f | 252 | }); |
cb9e9c12 AE |
253 | }, |
254 | ||
255 | /** | |
256 | * Initializes the package installation. | |
257 | */ | |
258 | _init: function() { | |
b32a906e | 259 | $('#submitButton').click($.proxy(this.prepareInstallation, this)); |
cb9e9c12 AE |
260 | }, |
261 | ||
262 | /** | |
263 | * Handles erroneous AJAX requests. | |
cb9e9c12 | 264 | */ |
014819c4 | 265 | _failure: function() { |
e0a0fe54 | 266 | if (this._dialog !== null) { |
5df9b2ef | 267 | $('#packageInstallationProgress').removeAttr('value'); |
962f1164 | 268 | this._setIcon('times'); |
e0a0fe54 | 269 | } |
e098d212 | 270 | |
0acbb6be AE |
271 | if (!this._allowRollback) { |
272 | return; | |
273 | } | |
274 | ||
7289c8d3 MS |
275 | if (this._dialog !== null) { |
276 | this._purgeTemplateContent($.proxy(function() { | |
277 | var $form = $('<div class="formSubmit" />').appendTo($('#packageInstallationInnerContent')); | |
278 | $('<button class="buttonPrimary">' + WCF.Language.get('wcf.acp.package.installation.rollback') + '</button>').appendTo($form).click($.proxy(this._rollback, this)); | |
279 | ||
280 | $('#packageInstallationInnerContentContainer').show(); | |
281 | ||
282 | this._dialog.wcfDialog('render'); | |
283 | }, this)); | |
284 | } | |
0acbb6be AE |
285 | }, |
286 | ||
287 | /** | |
288 | * Performs a rollback. | |
7fcd3ad5 AE |
289 | * |
290 | * @param object event | |
0acbb6be | 291 | */ |
7fcd3ad5 | 292 | _rollback: function(event) { |
e098d212 AE |
293 | this._setIcon('spinner'); |
294 | ||
7fcd3ad5 AE |
295 | if (event) { |
296 | $(event.currentTarget).disable(); | |
297 | } | |
298 | ||
0acbb6be | 299 | this._executeStep('rollback'); |
158bd3ca TD |
300 | }, |
301 | ||
302 | /** | |
303 | * Prepares installation dialog. | |
304 | */ | |
b32a906e | 305 | prepareInstallation: function() { |
639e46d6 AE |
306 | if (document.activeElement) { |
307 | document.activeElement.blur(); | |
308 | } | |
309 | ||
4da866ad AE |
310 | this._proxy.setOption('data', this._getParameters()); |
311 | this._proxy.sendRequest(); | |
158bd3ca TD |
312 | }, |
313 | ||
314 | /** | |
cb9e9c12 AE |
315 | * Returns parameters to prepare installation. |
316 | * | |
317 | * @return object | |
318 | */ | |
319 | _getParameters: function() { | |
320 | return { | |
321 | queueID: this._queueID, | |
322 | step: 'prepare' | |
323 | }; | |
324 | }, | |
325 | ||
326 | /** | |
327 | * Handles successful AJAX requests. | |
e5b88a7f AE |
328 | * |
329 | * @param object data | |
330 | * @param string textStatus | |
331 | * @param jQuery jqXHR | |
158bd3ca | 332 | */ |
cb9e9c12 | 333 | _success: function(data, textStatus, jqXHR) { |
ba133309 | 334 | this._shouldRender = false; |
cb9e9c12 | 335 | |
4da866ad | 336 | if (this._dialog === null) { |
ac86f5f7 | 337 | this._dialog = $('<div id="package' + (this._actionName === 'UninstallPackage' ? 'Uni' : 'I') + 'nstallationDialog" />').hide().appendTo(document.body); |
4da866ad AE |
338 | this._dialog.wcfDialog({ |
339 | closable: false, | |
6207cc21 | 340 | title: WCF.Language.get(this._dialogTitle) |
4da866ad AE |
341 | }); |
342 | } | |
343 | ||
e098d212 AE |
344 | this._setIcon('spinner'); |
345 | ||
0acbb6be AE |
346 | if (data.step == 'rollback') { |
347 | this._dialog.wcfDialog('close'); | |
e9add3b2 | 348 | this._dialog.remove(); |
0acbb6be AE |
349 | |
350 | new WCF.PeriodicalExecuter(function(pe) { | |
351 | pe.stop(); | |
352 | ||
353 | var $uninstallation = new WCF.ACP.Package.Uninstallation(); | |
354 | $uninstallation.start(data.packageID); | |
355 | }, 200); | |
356 | ||
357 | return; | |
358 | } | |
359 | ||
158bd3ca | 360 | // receive new queue id |
e5b88a7f AE |
361 | if (data.queueID) { |
362 | this._queueID = data.queueID; | |
158bd3ca TD |
363 | } |
364 | ||
47d85da7 AE |
365 | // update template |
366 | if (data.template && !data.ignoreTemplate) { | |
367 | this._dialog.html(data.template); | |
368 | this._shouldRender = true; | |
369 | } | |
370 | ||
158bd3ca | 371 | // update progress |
e5b88a7f AE |
372 | if (data.progress) { |
373 | $('#packageInstallationProgress').attr('value', data.progress).text(data.progress + '%'); | |
374 | $('#packageInstallationProgressLabel').text(data.progress + '%'); | |
e70175d6 | 375 | } |
9f959ced | 376 | |
e70175d6 | 377 | // update action |
e5b88a7f AE |
378 | if (data.currentAction) { |
379 | $('#packageInstallationAction').html(data.currentAction); | |
158bd3ca TD |
380 | } |
381 | ||
382 | // handle success | |
cb9e9c12 | 383 | if (data.step === 'success') { |
962f1164 | 384 | this._setIcon('check'); |
e098d212 | 385 | |
0a3949d4 | 386 | this._purgeTemplateContent($.proxy(function() { |
cb9e9c12 | 387 | var $form = $('<div class="formSubmit" />').appendTo($('#packageInstallationInnerContent')); |
45f1e6f9 | 388 | var $button = $('<button class="buttonPrimary">' + WCF.Language.get('wcf.global.button.next') + '</button>').appendTo($form).click(function() { |
7fcd3ad5 AE |
389 | $(this).disable(); |
390 | window.location = data.redirectLocation; | |
391 | }); | |
3c87a1b1 | 392 | |
0a3949d4 | 393 | $('#packageInstallationInnerContentContainer').show(); |
cb9e9c12 | 394 | |
45f1e6f9 AE |
395 | $(document).keydown(function(event) { |
396 | if (event.which === $.ui.keyCode.ENTER) { | |
397 | $button.trigger('click'); | |
398 | } | |
399 | }); | |
400 | ||
cb9e9c12 | 401 | this._dialog.wcfDialog('render'); |
0a3949d4 | 402 | }, this)); |
158bd3ca TD |
403 | |
404 | return; | |
405 | } | |
406 | ||
158bd3ca | 407 | // handle inner template |
e5b88a7f | 408 | if (data.innerTemplate) { |
599a39ba | 409 | var self = this; |
599a39ba | 410 | $('#packageInstallationInnerContent').html(data.innerTemplate).find('input').keyup(function(event) { |
45f1e6f9 | 411 | if (event.keyCode === $.ui.keyCode.ENTER) { |
b32a906e | 412 | self._submit(data); |
599a39ba AE |
413 | } |
414 | }); | |
158bd3ca TD |
415 | |
416 | // create button to handle next step | |
e5b88a7f | 417 | if (data.step && data.node) { |
5df9b2ef | 418 | $('#packageInstallationProgress').removeAttr('value'); |
e098d212 AE |
419 | this._setIcon('question'); |
420 | ||
cb9e9c12 | 421 | var $form = $('<div class="formSubmit" />').appendTo($('#packageInstallationInnerContent')); |
45f1e6f9 | 422 | $('<button class="buttonPrimary">' + WCF.Language.get('wcf.global.button.next') + '</button>').appendTo($form).click($.proxy(function(event) { |
7fcd3ad5 AE |
423 | $(event.currentTarget).disable(); |
424 | ||
425 | this._submit(data); | |
9db0c330 | 426 | }, this)); |
158bd3ca TD |
427 | } |
428 | ||
0a3949d4 | 429 | $('#packageInstallationInnerContentContainer').show(); |
158bd3ca | 430 | |
cb9e9c12 | 431 | this._dialog.wcfDialog('render'); |
158bd3ca TD |
432 | return; |
433 | } | |
434 | ||
435 | // purge content | |
3c87a1b1 | 436 | this._purgeTemplateContent($.proxy(function() { |
e5b88a7f | 437 | // render container |
ba133309 | 438 | if (this._shouldRender) { |
cb9e9c12 | 439 | this._dialog.wcfDialog('render'); |
0a3949d4 | 440 | } |
5e6179f1 | 441 | |
3c87a1b1 | 442 | // execute next step |
e5b88a7f AE |
443 | if (data.step && data.node) { |
444 | this._executeStep(data.step, data.node); | |
3c87a1b1 AE |
445 | } |
446 | }, this)); | |
447 | }, | |
448 | ||
599a39ba AE |
449 | /** |
450 | * Submits the dialog content. | |
451 | * | |
452 | * @param object data | |
453 | */ | |
b32a906e | 454 | _submit: function(data) { |
e098d212 AE |
455 | this._setIcon('spinner'); |
456 | ||
599a39ba | 457 | // collect form values |
cb6e5946 | 458 | var $additionalData = { }; |
599a39ba AE |
459 | $('#packageInstallationInnerContent input').each(function(index, inputElement) { |
460 | var $inputElement = $(inputElement); | |
461 | var $type = $inputElement.attr('type'); | |
462 | ||
3bbe83f0 MS |
463 | if (($type != 'checkbox' && $type != 'radio') || $inputElement.prop('checked')) { |
464 | var $name = $inputElement.attr('name'); | |
465 | if ($name.match(/(.*)\[([^[]*)\]$/)) { | |
466 | $name = RegExp.$1; | |
467 | $key = RegExp.$2; | |
468 | ||
469 | if ($additionalData[$name] === undefined) { | |
470 | if ($key) { | |
471 | $additionalData[$name] = { }; | |
472 | } | |
473 | else { | |
474 | $additionalData[$name] = [ ]; | |
475 | } | |
476 | } | |
477 | ||
c001b457 | 478 | if ($key) { |
3bbe83f0 | 479 | $additionalData[$name][$key] = $inputElement.val(); |
c001b457 AE |
480 | } |
481 | else { | |
3bbe83f0 | 482 | $additionalData[$name].push($inputElement.val()); |
c001b457 AE |
483 | } |
484 | } | |
c001b457 | 485 | else { |
3bbe83f0 | 486 | $additionalData[$name] = $inputElement.val(); |
c001b457 AE |
487 | } |
488 | } | |
599a39ba AE |
489 | }); |
490 | ||
491 | this._executeStep(data.step, data.node, $additionalData); | |
492 | }, | |
493 | ||
3c87a1b1 AE |
494 | /** |
495 | * Purges template content. | |
496 | * | |
497 | * @param function callback | |
498 | */ | |
499 | _purgeTemplateContent: function(callback) { | |
f027ba61 AE |
500 | if ($('#packageInstallationInnerContent').children().length) { |
501 | $('#packageInstallationInnerContentContainer').hide(); | |
502 | $('#packageInstallationInnerContent').empty(); | |
503 | ||
504 | this._shouldRender = true; | |
158bd3ca | 505 | } |
f027ba61 AE |
506 | |
507 | callback(); | |
158bd3ca TD |
508 | }, |
509 | ||
510 | /** | |
511 | * Executes the next installation step. | |
512 | * | |
513 | * @param string step | |
514 | * @param string node | |
515 | * @param object additionalData | |
516 | */ | |
517 | _executeStep: function(step, node, additionalData) { | |
cb6e5946 | 518 | if (!additionalData) additionalData = { }; |
158bd3ca TD |
519 | |
520 | var $data = $.extend({ | |
a698c064 AE |
521 | node: node, |
522 | queueID: this._queueID, | |
523 | step: step | |
158bd3ca | 524 | }, additionalData); |
9f959ced | 525 | |
e5b88a7f AE |
526 | this._proxy.setOption('data', $data); |
527 | this._proxy.sendRequest(); | |
e098d212 AE |
528 | }, |
529 | ||
e0a0fe54 MS |
530 | /** |
531 | * Sets the icon with the given name as the current installation status icon. | |
532 | * | |
533 | * @param string iconName | |
534 | */ | |
e098d212 | 535 | _setIcon: function(iconName) { |
47e76c45 | 536 | this._dialog.find('.jsPackageInstallationStatus').removeClass('fa-check fa-question fa-times fa-spinner').addClass('fa-' + iconName); |
158bd3ca | 537 | } |
cb9e9c12 | 538 | }); |
158bd3ca | 539 | |
a45fa84d MS |
540 | /** |
541 | * Handles canceling the package installation at the package installation | |
542 | * confirm page. | |
543 | */ | |
544 | WCF.ACP.Package.Installation.Cancel = Class.extend({ | |
545 | /** | |
546 | * Creates a new instance of WCF.ACP.Package.Installation.Cancel. | |
547 | * | |
548 | * @param integer queueID | |
549 | */ | |
550 | init: function(queueID) { | |
551 | $('#backButton').click(function() { | |
552 | new WCF.Action.Proxy({ | |
553 | autoSend: true, | |
554 | data: { | |
555 | actionName: 'cancelInstallation', | |
556 | className: 'wcf\\data\\package\\installation\\queue\\PackageInstallationQueueAction', | |
557 | objectIDs: [ queueID ] | |
558 | }, | |
559 | success: function(data) { | |
560 | window.location = data.returnValues.url; | |
561 | } | |
562 | }); | |
563 | }); | |
564 | } | |
565 | }); | |
566 | ||
158bd3ca | 567 | /** |
cb9e9c12 | 568 | * Provides the package uninstallation. |
158bd3ca TD |
569 | * |
570 | * @param jQuery elements | |
74622428 | 571 | * @param string wcfPackageListURL |
158bd3ca | 572 | */ |
cb9e9c12 | 573 | WCF.ACP.Package.Uninstallation = WCF.ACP.Package.Installation.extend({ |
158bd3ca | 574 | /** |
cb9e9c12 AE |
575 | * list of uninstallation buttons |
576 | * @var jQuery | |
158bd3ca | 577 | */ |
cb9e9c12 | 578 | _elements: null, |
158bd3ca TD |
579 | |
580 | /** | |
cb9e9c12 AE |
581 | * current package id |
582 | * @var integer | |
583 | */ | |
584 | _packageID: 0, | |
585 | ||
74622428 AE |
586 | /** |
587 | * URL of WCF package list | |
588 | * @var string | |
589 | */ | |
590 | _wcfPackageListURL: '', | |
591 | ||
cb9e9c12 AE |
592 | /** |
593 | * Initializes the WCF.ACP.Package.Uninstallation class. | |
158bd3ca TD |
594 | * |
595 | * @param jQuery elements | |
74622428 | 596 | * @param string wcfPackageListURL |
158bd3ca | 597 | */ |
74622428 | 598 | init: function(elements, wcfPackageListURL) { |
cb9e9c12 AE |
599 | this._elements = elements; |
600 | this._packageID = 0; | |
74622428 | 601 | this._wcfPackageListURL = wcfPackageListURL; |
158bd3ca | 602 | |
0acbb6be | 603 | if (this._elements !== undefined && this._elements.length) { |
2ef79140 | 604 | this._super(0, 'UninstallPackage'); |
cb9e9c12 | 605 | } |
158bd3ca TD |
606 | }, |
607 | ||
0acbb6be AE |
608 | /** |
609 | * Begins a package uninstallation without user action. | |
610 | * | |
611 | * @param integer packageID | |
612 | */ | |
613 | start: function(packageID) { | |
614 | this._actionName = 'UninstallPackage'; | |
615 | this._packageID = packageID; | |
616 | this._queueID = 0; | |
6207cc21 | 617 | this._dialogTitle = 'wcf.acp.package.uninstallation.title'; |
0acbb6be AE |
618 | |
619 | this._initProxy(); | |
620 | this.prepareInstallation(); | |
621 | }, | |
622 | ||
158bd3ca | 623 | /** |
cb9e9c12 AE |
624 | * @see WCF.ACP.Package.Installation.init() |
625 | */ | |
626 | _init: function() { | |
e3be0700 | 627 | this._elements.click($.proxy(this._showConfirmationDialog, this)); |
e852aa82 AE |
628 | }, |
629 | ||
630 | /** | |
631 | * Displays a confirmation dialog prior to package uninstallation. | |
632 | * | |
cec91f01 | 633 | * @param object event |
e852aa82 | 634 | */ |
cec91f01 | 635 | _showConfirmationDialog: function(event) { |
e3be0700 AE |
636 | var $element = $(event.currentTarget); |
637 | ||
638 | if ($element.data('isApplication') && this._wcfPackageListURL) { | |
639 | window.location = WCF.String.unescapeHTML(this._wcfPackageListURL.replace(/{packageID}/, $element.data('objectID'))); | |
74622428 AE |
640 | return; |
641 | } | |
642 | ||
cb9e9c12 | 643 | var self = this; |
e3be0700 | 644 | WCF.System.Confirmation.show($element.data('confirmMessage'), function(action) { |
cb9e9c12 | 645 | if (action === 'confirm') { |
e3be0700 | 646 | self._packageID = $element.data('objectID'); |
b32a906e | 647 | self.prepareInstallation(); |
cb9e9c12 | 648 | } |
23e43ac5 | 649 | }, undefined, undefined, true); |
29b533c8 AE |
650 | }, |
651 | ||
652 | /** | |
cb9e9c12 | 653 | * @see WCF.ACP.Package.Installation._getParameters() |
29b533c8 | 654 | */ |
cb9e9c12 AE |
655 | _getParameters: function() { |
656 | return { | |
657 | packageID: this._packageID, | |
658 | step: 'prepare' | |
659 | }; | |
158bd3ca | 660 | } |
cb9e9c12 | 661 | }); |
158bd3ca | 662 | |
25c2c382 AE |
663 | /** |
664 | * Manages package search. | |
665 | */ | |
666 | WCF.ACP.Package.Search = Class.extend({ | |
667 | /** | |
668 | * search button | |
669 | * @var jQuery | |
670 | */ | |
671 | _button: null, | |
672 | ||
673 | /** | |
674 | * list of cached pages | |
675 | * @var object | |
676 | */ | |
677 | _cache: { }, | |
678 | ||
679 | /** | |
680 | * search container | |
681 | * @var jQuery | |
682 | */ | |
683 | _container: null, | |
684 | ||
996eb650 AE |
685 | /** |
686 | * dialog overlay | |
687 | * @var jQuery | |
688 | */ | |
689 | _dialog: null, | |
690 | ||
25c2c382 AE |
691 | /** |
692 | * package input field | |
693 | * @var jQuery | |
694 | */ | |
695 | _package: null, | |
696 | ||
697 | /** | |
698 | * package description input field | |
699 | * @var jQuery | |
700 | */ | |
701 | _packageDescription: null, | |
702 | ||
703 | /** | |
704 | * package name input field | |
705 | * @var jQuery | |
706 | */ | |
707 | _packageName: null, | |
708 | ||
709 | /** | |
710 | * package search result container | |
711 | * @var jQuery | |
712 | */ | |
713 | _packageSearchResultContainer: null, | |
714 | ||
715 | /** | |
716 | * package search result list | |
717 | * @var jQuery | |
718 | */ | |
719 | _packageSearchResultList: null, | |
720 | ||
721 | /** | |
722 | * number of pages | |
723 | * @var integer | |
724 | */ | |
725 | _pageCount: 0, | |
726 | ||
727 | /** | |
728 | * current page | |
729 | * @var integer | |
730 | */ | |
731 | _pageNo: 1, | |
732 | ||
733 | /** | |
734 | * action proxy | |
735 | * @var WCF.Action:proxy | |
736 | */ | |
737 | _proxy: null, | |
738 | ||
739 | /** | |
740 | * search id | |
741 | * @var integer | |
742 | */ | |
743 | _searchID: 0, | |
744 | ||
996eb650 AE |
745 | /** |
746 | * currently selected package | |
747 | * @var string | |
748 | */ | |
749 | _selectedPackage: '', | |
750 | ||
751 | /** | |
752 | * currently selected package's version | |
753 | */ | |
754 | _selectedPackageVersion: '', | |
755 | ||
25c2c382 | 756 | /** |
1615fc2e | 757 | * Initializes the WCF.ACP.Package.Search class. |
25c2c382 AE |
758 | */ |
759 | init: function() { | |
760 | this._button = null; | |
761 | this._cache = { }; | |
762 | this._container = $('#packageSearch'); | |
996eb650 | 763 | this._dialog = null; |
25c2c382 AE |
764 | this._package = null; |
765 | this._packageName = null; | |
766 | this._packageSearchResultContainer = $('#packageSearchResultContainer'); | |
767 | this._packageSearchResultList = $('#packageSearchResultList'); | |
768 | this._pageCount = 0; | |
769 | this._pageNo = 1; | |
770 | this._searchDescription = null; | |
771 | this._searchID = 0; | |
996eb650 AE |
772 | this._selectedPackage = ''; |
773 | this._selectedPackageVersion = ''; | |
25c2c382 AE |
774 | |
775 | this._proxy = new WCF.Action.Proxy({ | |
776 | success: $.proxy(this._success, this) | |
777 | }); | |
778 | ||
779 | this._initElements(); | |
780 | }, | |
781 | ||
782 | /** | |
783 | * Initializes search elements. | |
784 | */ | |
785 | _initElements: function() { | |
786 | this._button = this._container.find('.formSubmit > button.jsButtonPackageSearch').disable().click($.proxy(this._search, this)); | |
787 | ||
788 | this._package = $('#package').keyup($.proxy(this._keyUp, this)); | |
789 | this._packageDescription = $('#packageDescription').keyup($.proxy(this._keyUp, this)); | |
790 | this._packageName = $('#packageName').keyup($.proxy(this._keyUp, this)); | |
791 | }, | |
792 | ||
793 | /** | |
794 | * Handles the 'keyup' event. | |
795 | */ | |
796 | _keyUp: function(event) { | |
797 | if (this._package.val() === '' && this._packageDescription.val() === '' && this._packageName.val() === '') { | |
798 | this._button.disable(); | |
799 | } | |
800 | else { | |
801 | this._button.enable(); | |
802 | ||
803 | // submit on [Enter] | |
804 | if (event.which === 13) { | |
805 | this._button.trigger('click'); | |
806 | } | |
807 | } | |
808 | }, | |
809 | ||
810 | /** | |
811 | * Performs a new search. | |
812 | */ | |
813 | _search: function() { | |
814 | var $values = this._getSearchValues(); | |
815 | if (!this._validate($values)) { | |
816 | return false; | |
817 | } | |
818 | ||
819 | $values.pageNo = this._pageNo; | |
820 | this._proxy.setOption('data', { | |
821 | actionName: 'search', | |
822 | className: 'wcf\\data\\package\\update\\PackageUpdateAction', | |
823 | parameters: $values | |
824 | }); | |
825 | this._proxy.sendRequest(); | |
826 | }, | |
827 | ||
828 | /** | |
829 | * Returns search values. | |
830 | * | |
831 | * @return object | |
832 | */ | |
833 | _getSearchValues: function() { | |
834 | return { | |
835 | 'package': $.trim(this._package.val()), | |
836 | packageDescription: $.trim(this._packageDescription.val()), | |
837 | packageName: $.trim(this._packageName.val()) | |
838 | }; | |
839 | }, | |
840 | ||
841 | /** | |
842 | * Validates search values. | |
843 | * | |
844 | * @param object values | |
845 | * @return boolean | |
846 | */ | |
847 | _validate: function(values) { | |
848 | if (values['package'] === '' && values['packageDescription'] === '' && values['packageName'] === '') { | |
849 | return false; | |
850 | } | |
851 | ||
852 | return true; | |
853 | }, | |
854 | ||
855 | /** | |
856 | * Handles successful AJAX requests. | |
857 | * | |
858 | * @param object data | |
859 | * @param string textStatus | |
860 | * @param jQuery jqXHR | |
861 | */ | |
862 | _success: function(data, textStatus, jqXHR) { | |
863 | switch (data.actionName) { | |
864 | case 'getResultList': | |
865 | this._insertTemplate(data.returnValues.template); | |
866 | break; | |
867 | ||
996eb650 AE |
868 | case 'prepareInstallation': |
869 | if (data.returnValues.queueID) { | |
870 | if (this._dialog !== null) { | |
871 | this._dialog.wcfDialog('close'); | |
872 | } | |
873 | ||
874 | var $installation = new WCF.ACP.Package.Installation(data.returnValues.queueID, undefined, false); | |
875 | $installation.prepareInstallation(); | |
876 | } | |
877 | else if (data.returnValues.template) { | |
878 | if (this._dialog === null) { | |
879 | this._dialog = $('<div>' + data.returnValues.template + '</div>').hide().appendTo(document.body); | |
880 | this._dialog.wcfDialog({ | |
881 | title: WCF.Language.get('wcf.acp.package.update.unauthorized') | |
882 | }); | |
883 | } | |
884 | else { | |
885 | this._dialog.html(data.returnValues.template).wcfDialog('open'); | |
886 | } | |
887 | ||
888 | this._dialog.find('.formSubmit > button').click($.proxy(this._submitAuthentication, this)); | |
889 | } | |
890 | break; | |
891 | ||
25c2c382 AE |
892 | case 'search': |
893 | this._pageCount = data.returnValues.pageCount; | |
894 | this._searchID = data.returnValues.searchID; | |
895 | ||
896 | this._insertTemplate(data.returnValues.template, (data.returnValues.count === undefined ? undefined : data.returnValues.count)); | |
897 | this._setupPagination(); | |
898 | break; | |
899 | } | |
900 | }, | |
901 | ||
996eb650 AE |
902 | /** |
903 | * Submits authentication data for current update server. | |
904 | * | |
905 | * @param object event | |
906 | */ | |
907 | _submitAuthentication: function(event) { | |
908 | var $usernameField = $('#packageUpdateServerUsername'); | |
909 | var $passwordField = $('#packageUpdateServerPassword'); | |
910 | ||
911 | // remove error messages if any | |
912 | $usernameField.next('small.innerError').remove(); | |
913 | $passwordField.next('small.innerError').remove(); | |
914 | ||
915 | var $continue = true; | |
916 | if ($.trim($usernameField.val()) === '') { | |
917 | $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($usernameField); | |
918 | $continue = false; | |
919 | } | |
920 | ||
921 | if ($.trim($passwordField.val()) === '') { | |
922 | $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($passwordField); | |
923 | $continue = false; | |
924 | } | |
925 | ||
926 | if ($continue) { | |
927 | this._prepareInstallation($(event.currentTarget).data('packageUpdateServerID')); | |
928 | } | |
929 | }, | |
930 | ||
25c2c382 AE |
931 | /** |
932 | * Inserts search result list template. | |
933 | * | |
934 | * @param string template | |
935 | * @param integer count | |
936 | */ | |
937 | _insertTemplate: function(template, count) { | |
938 | this._packageSearchResultContainer.show(); | |
939 | ||
940 | this._packageSearchResultList.html(template); | |
941 | if (count === undefined) { | |
942 | this._content[this._pageNo] = template; | |
943 | } | |
944 | ||
945 | // update badge count | |
946 | if (count !== undefined) { | |
947 | this._content = { 1: template }; | |
939fce69 | 948 | this._packageSearchResultContainer.find('h2.sectionTitle > .badge').html(count); |
996eb650 AE |
949 | } |
950 | ||
951 | // bind listener | |
952 | this._packageSearchResultList.find('.jsInstallPackage').click($.proxy(this._click, this)); | |
953 | }, | |
954 | ||
955 | /** | |
956 | * Prepares a package installation. | |
957 | * | |
958 | * @param object event | |
959 | */ | |
960 | _click: function(event) { | |
961 | var $button = $(event.currentTarget); | |
962 | WCF.System.Confirmation.show($button.data('confirmMessage'), $.proxy(function(action) { | |
963 | if (action === 'confirm') { | |
964 | this._selectedPackage = $button.data('package'); | |
965 | this._selectedPackageVersion = $button.data('packageVersion'); | |
966 | this._prepareInstallation(); | |
967 | } | |
23e43ac5 | 968 | }, this), undefined, undefined, true); |
996eb650 AE |
969 | }, |
970 | ||
971 | /** | |
972 | * Prepares package installation. | |
973 | * | |
974 | * @param integer packageUpdateServerID | |
975 | */ | |
976 | _prepareInstallation: function(packageUpdateServerID) { | |
977 | var $parameters = { | |
02662193 | 978 | 'packages': { } |
996eb650 | 979 | }; |
02662193 | 980 | $parameters['packages'][this._selectedPackage] = this._selectedPackageVersion; |
996eb650 AE |
981 | |
982 | if (packageUpdateServerID) { | |
983 | $parameters.authData = { | |
984 | packageUpdateServerID: packageUpdateServerID, | |
985 | password: $.trim($('#packageUpdateServerPassword').val()), | |
986 | saveCredentials: ($('#packageUpdateServerSaveCredentials:checked').length ? true : false), | |
987 | username: $.trim($('#packageUpdateServerUsername').val()) | |
988 | }; | |
25c2c382 | 989 | } |
996eb650 AE |
990 | |
991 | this._proxy.setOption('data', { | |
992 | actionName: 'prepareInstallation', | |
993 | className: 'wcf\\data\\package\\update\\PackageUpdateAction', | |
994 | parameters: $parameters | |
995 | }); | |
996 | this._proxy.sendRequest(); | |
25c2c382 AE |
997 | }, |
998 | ||
999 | /** | |
1000 | * Setups pagination for current search. | |
1001 | */ | |
1002 | _setupPagination: function() { | |
1003 | // remove previous instances | |
1004 | this._content = { 1: this._packageSearchResultList.html() }; | |
abe07e47 | 1005 | this._packageSearchResultContainer.find('.pagination').wcfPages('destroy').remove(); |
25c2c382 AE |
1006 | |
1007 | if (this._pageCount > 1) { | |
126c2518 MW |
1008 | var $contentFooter = $('<footer class="contentFooter"><div class="paginationBottom"><nav /></div></footer>').insertAfter(this._packageSearchResultList); |
1009 | $contentFooter.find('nav').wcfPages({ | |
25c2c382 AE |
1010 | activePage: this._pageNo, |
1011 | maxPage: this._pageCount | |
d62d0d94 | 1012 | }).on('wcfpagesswitched', $.proxy(this._showPage, this)); |
25c2c382 AE |
1013 | } |
1014 | }, | |
1015 | ||
1016 | /** | |
1017 | * Displays requested pages or loads it. | |
1018 | * | |
1019 | * @param object event | |
1020 | * @param object data | |
1021 | */ | |
1022 | _showPage: function(event, data) { | |
1023 | if (data && data.activePage) { | |
1024 | this._pageNo = data.activePage; | |
1025 | } | |
1026 | ||
1027 | // validate page no | |
1028 | if (this._pageNo < 1 || this._pageNo > this._pageCount) { | |
1029 | console.debug("[WCF.ACP.Package.Search] Cannot access page " + this._pageNo + " of " + this._pageCount); | |
1030 | return; | |
1031 | } | |
1032 | ||
1033 | // load content | |
1034 | if (this._content[this._pageNo] === undefined) { | |
1035 | this._proxy.setOption('data', { | |
1036 | actionName: 'getResultList', | |
1037 | className: 'wcf\\data\\package\\update\\PackageUpdateAction', | |
1038 | parameters: { | |
1039 | pageNo: this._pageNo, | |
1040 | searchID: this._searchID | |
1041 | } | |
1042 | }); | |
1043 | this._proxy.sendRequest(); | |
1044 | } | |
1045 | else { | |
25c2c382 AE |
1046 | // show cached content |
1047 | this._packageSearchResultList.html(this._content[this._pageNo]); | |
1048 | ||
42d7d2cc | 1049 | WCF.DOMNodeInsertedHandler.execute(); |
25c2c382 AE |
1050 | } |
1051 | } | |
1052 | }); | |
1053 | ||
66ed9925 | 1054 | WCF.ACP.Package.Server = { }; |
298a7cd8 AE |
1055 | |
1056 | WCF.ACP.Package.Server.Installation = Class.extend({ | |
1057 | _proxy: null, | |
1058 | _selectedPackage: '', | |
1059 | ||
1060 | init: function() { | |
1061 | this._dialog = null; | |
1062 | this._selectedPackage = null; | |
1063 | ||
1064 | this._proxy = new WCF.Action.Proxy({ | |
1065 | success: $.proxy(this._success, this) | |
1066 | }); | |
1067 | }, | |
1068 | ||
1069 | bind: function() { | |
1070 | $('.jsButtonPackageInstall').removeClass('jsButtonPackageInstall').click($.proxy(this._click, this)); | |
1071 | }, | |
1072 | ||
1073 | /** | |
1074 | * Prepares a package installation. | |
1075 | * | |
1076 | * @param object event | |
1077 | */ | |
1078 | _click: function(event) { | |
1079 | var $button = $(event.currentTarget); | |
1080 | WCF.System.Confirmation.show($button.data('confirmMessage'), $.proxy(function(action) { | |
1081 | if (action === 'confirm') { | |
1082 | this._selectedPackage = $button.data('package'); | |
1083 | this._selectedPackageVersion = $button.data('packageVersion'); | |
1084 | this._prepareInstallation(); | |
1085 | } | |
23e43ac5 | 1086 | }, this), undefined, undefined, true); |
298a7cd8 AE |
1087 | }, |
1088 | ||
1089 | /** | |
1090 | * Handles successful AJAX requests. | |
1091 | * | |
1092 | * @param object data | |
1093 | */ | |
1094 | _success: function(data) { | |
1095 | if (data.returnValues.queueID) { | |
1096 | if (this._dialog !== null) { | |
1097 | this._dialog.wcfDialog('close'); | |
1098 | } | |
1099 | ||
1100 | var $installation = new WCF.ACP.Package.Installation(data.returnValues.queueID, undefined, false); | |
1101 | $installation.prepareInstallation(); | |
1102 | } | |
1103 | else if (data.returnValues.template) { | |
1104 | if (this._dialog === null) { | |
1105 | this._dialog = $('<div>' + data.returnValues.template + '</div>').hide().appendTo(document.body); | |
1106 | this._dialog.wcfDialog({ | |
1107 | title: WCF.Language.get('wcf.acp.package.update.unauthorized') | |
1108 | }); | |
1109 | } | |
1110 | else { | |
1111 | this._dialog.html(data.returnValues.template).wcfDialog('open'); | |
1112 | } | |
1113 | ||
1114 | this._dialog.find('.formSubmit > button').click($.proxy(this._submitAuthentication, this)); | |
1115 | } | |
1116 | }, | |
1117 | ||
1118 | /** | |
1119 | * Submits authentication data for current update server. | |
1120 | * | |
1121 | * @param object event | |
1122 | */ | |
1123 | _submitAuthentication: function(event) { | |
1124 | var $usernameField = $('#packageUpdateServerUsername'); | |
1125 | var $passwordField = $('#packageUpdateServerPassword'); | |
1126 | ||
1127 | // remove error messages if any | |
1128 | $usernameField.next('small.innerError').remove(); | |
1129 | $passwordField.next('small.innerError').remove(); | |
1130 | ||
1131 | var $continue = true; | |
1132 | if ($.trim($usernameField.val()) === '') { | |
1133 | $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($usernameField); | |
1134 | $continue = false; | |
1135 | } | |
1136 | ||
1137 | if ($.trim($passwordField.val()) === '') { | |
1138 | $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($passwordField); | |
1139 | $continue = false; | |
1140 | } | |
1141 | ||
1142 | if ($continue) { | |
1143 | this._prepareInstallation($(event.currentTarget).data('packageUpdateServerID')); | |
1144 | } | |
1145 | }, | |
1146 | ||
1147 | /** | |
1148 | * Prepares package installation. | |
1149 | * | |
1150 | * @param integer packageUpdateServerID | |
1151 | */ | |
1152 | _prepareInstallation: function(packageUpdateServerID) { | |
1153 | var $parameters = { | |
1154 | 'packages': { } | |
1155 | }; | |
1156 | $parameters['packages'][this._selectedPackage] = this._selectedPackageVersion; | |
1157 | ||
1158 | if (packageUpdateServerID) { | |
1159 | $parameters.authData = { | |
1160 | packageUpdateServerID: packageUpdateServerID, | |
1161 | password: $.trim($('#packageUpdateServerPassword').val()), | |
1162 | saveCredentials: ($('#packageUpdateServerSaveCredentials:checked').length ? true : false), | |
1163 | username: $.trim($('#packageUpdateServerUsername').val()) | |
1164 | }; | |
1165 | } | |
1166 | ||
1167 | this._proxy.setOption('data', { | |
1168 | actionName: 'prepareInstallation', | |
1169 | className: 'wcf\\data\\package\\update\\PackageUpdateAction', | |
1170 | parameters: $parameters | |
1171 | }); | |
1172 | this._proxy.sendRequest(); | |
1173 | }, | |
2061c822 | 1174 | }); |
298a7cd8 | 1175 | |
3536d2fe AE |
1176 | /** |
1177 | * Namespace for package update related classes. | |
1178 | */ | |
1179 | WCF.ACP.Package.Update = { }; | |
1180 | ||
1181 | /** | |
1182 | * Handles the package update process. | |
1183 | */ | |
1184 | WCF.ACP.Package.Update.Manager = Class.extend({ | |
1185 | /** | |
1186 | * dialog overlay | |
1187 | * @var jQuery | |
1188 | */ | |
1189 | _dialog: null, | |
1190 | ||
1191 | /** | |
1192 | * action proxy | |
1193 | * @var WCF.Action.Proxy | |
1194 | */ | |
1195 | _proxy: null, | |
1196 | ||
1197 | /** | |
1198 | * submit button | |
1199 | * @var jQuery | |
1200 | */ | |
1201 | _submitButton: null, | |
1202 | ||
1203 | /** | |
1204 | * Initializes the WCF.ACP.Package.Update.Manager class. | |
1205 | */ | |
1206 | init: function() { | |
1207 | this._dialog = null; | |
1208 | this._submitButton = $('.formSubmit > button').click($.proxy(this._click, this)); | |
1209 | ||
1210 | this._proxy = new WCF.Action.Proxy({ | |
1211 | success: $.proxy(this._success, this) | |
1212 | }); | |
1213 | ||
1214 | $('.jsPackageUpdate').each($.proxy(function(index, packageUpdate) { | |
1215 | var $packageUpdate = $(packageUpdate); | |
1216 | $packageUpdate.find('input[type=checkbox]').data('packageUpdate', $packageUpdate).change($.proxy(this._change, this)); | |
1217 | }, this)); | |
1218 | }, | |
1219 | ||
1220 | /** | |
1221 | * Handles toggles for a specific update. | |
1222 | */ | |
1223 | _change: function(event) { | |
1224 | var $checkbox = $(event.currentTarget); | |
1225 | ||
1226 | if ($checkbox.is(':checked')) { | |
1227 | $checkbox.data('packageUpdate').find('select').enable(); | |
1228 | $checkbox.data('packageUpdate').find('dl').removeClass('disabled'); | |
1229 | ||
1230 | this._submitButton.enable(); | |
1231 | } | |
1232 | else { | |
1233 | $checkbox.data('packageUpdate').find('select').disable(); | |
1234 | $checkbox.data('packageUpdate').find('dl').addClass('disabled'); | |
1235 | ||
1236 | // disable submit button | |
1237 | if (!$('input[type=checkbox]:checked').length) { | |
1238 | this._submitButton.disable(); | |
1239 | } | |
2061c822 AE |
1240 | else { |
1241 | this._submitButton.enable(); | |
1242 | } | |
3536d2fe AE |
1243 | } |
1244 | }, | |
1245 | ||
1246 | /** | |
1247 | * Handles clicks on the submit button. | |
1248 | * | |
1249 | * @param object event | |
1250 | * @param integer packageUpdateServerID | |
1251 | */ | |
1252 | _click: function(event, packageUpdateServerID) { | |
1253 | var $packages = { }; | |
1254 | $('.jsPackageUpdate').each($.proxy(function(index, packageUpdate) { | |
1255 | var $packageUpdate = $(packageUpdate); | |
1256 | if ($packageUpdate.find('input[type=checkbox]:checked').length) { | |
1257 | $packages[$packageUpdate.data('package')] = $packageUpdate.find('select').val(); | |
1258 | } | |
1259 | }, this)); | |
1260 | ||
1261 | if ($.getLength($packages)) { | |
839984a4 MS |
1262 | this._submitButton.disable(); |
1263 | ||
3536d2fe AE |
1264 | var $parameters = { |
1265 | packages: $packages | |
1266 | }; | |
1267 | if (packageUpdateServerID) { | |
1268 | $parameters.authData = { | |
1269 | packageUpdateServerID: packageUpdateServerID, | |
1270 | password: $.trim($('#packageUpdateServerPassword').val()), | |
1271 | saveCredentials: ($('#packageUpdateServerSaveCredentials:checked').length ? true : false), | |
1272 | username: $.trim($('#packageUpdateServerUsername').val()) | |
996eb650 | 1273 | }; |
3536d2fe AE |
1274 | } |
1275 | ||
1276 | this._proxy.setOption('data', { | |
1277 | actionName: 'prepareUpdate', | |
1278 | className: 'wcf\\data\\package\\update\\PackageUpdateAction', | |
1279 | parameters: $parameters, | |
1280 | }); | |
1281 | this._proxy.sendRequest(); | |
1282 | } | |
1283 | }, | |
1284 | ||
1285 | /** | |
1286 | * Handles successful AJAX requests. | |
1287 | * | |
1288 | * @param object data | |
1289 | * @param string textStatus | |
1290 | * @param jQuery jqXHR | |
1291 | */ | |
1292 | _success: function(data, textStatus, jqXHR) { | |
1293 | if (data.returnValues.queueID) { | |
1294 | if (this._dialog !== null) { | |
1295 | this._dialog.wcfDialog('close'); | |
1296 | } | |
1297 | ||
adf9791d | 1298 | var $installation = new WCF.ACP.Package.Installation(data.returnValues.queueID, undefined, false, true); |
3536d2fe AE |
1299 | $installation.prepareInstallation(); |
1300 | } | |
1d7f1d20 AE |
1301 | else if (data.returnValues.excludedPackages) { |
1302 | if (this._dialog === null) { | |
1303 | this._dialog = $('<div>' + data.returnValues.template + '</div>').hide().appendTo(document.body); | |
1304 | this._dialog.wcfDialog({ | |
1305 | title: WCF.Language.get('wcf.acp.package.update.excludedPackages') | |
1306 | }); | |
1307 | } | |
1308 | else { | |
1309 | this._dialog.wcfDialog('option', 'title', WCF.Language.get('wcf.acp.package.update.excludedPackages')); | |
1310 | this._dialog.html(data.returnValues.template).wcfDialog('open'); | |
1311 | } | |
1312 | ||
1313 | this._submitButton.enable(); | |
1314 | } | |
3536d2fe AE |
1315 | else if (data.returnValues.template) { |
1316 | if (this._dialog === null) { | |
1317 | this._dialog = $('<div>' + data.returnValues.template + '</div>').hide().appendTo(document.body); | |
1318 | this._dialog.wcfDialog({ | |
1319 | title: WCF.Language.get('wcf.acp.package.update.unauthorized') | |
1320 | }); | |
1321 | } | |
1322 | else { | |
1d7f1d20 | 1323 | this._dialog.wcfDialog('option', 'title', WCF.Language.get('wcf.acp.package.update.unauthorized')); |
3536d2fe AE |
1324 | this._dialog.html(data.returnValues.template).wcfDialog('open'); |
1325 | } | |
1326 | ||
1327 | this._dialog.find('.formSubmit > button').click($.proxy(this._submitAuthentication, this)); | |
1328 | } | |
1329 | }, | |
1330 | ||
1331 | /** | |
1332 | * Submits authentication data for current update server. | |
1333 | * | |
1334 | * @param object event | |
1335 | */ | |
1336 | _submitAuthentication: function(event) { | |
1337 | var $usernameField = $('#packageUpdateServerUsername'); | |
1338 | var $passwordField = $('#packageUpdateServerPassword'); | |
1339 | ||
1340 | // remove error messages if any | |
1341 | $usernameField.next('small.innerError').remove(); | |
1342 | $passwordField.next('small.innerError').remove(); | |
1343 | ||
1344 | var $continue = true; | |
1345 | if ($.trim($usernameField.val()) === '') { | |
1346 | $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($usernameField); | |
1347 | $continue = false; | |
1348 | } | |
1349 | ||
1350 | if ($.trim($passwordField.val()) === '') { | |
1351 | $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($passwordField); | |
1352 | $continue = false; | |
1353 | } | |
1354 | ||
1355 | if ($continue) { | |
22508797 | 1356 | this._click(undefined, $(event.currentTarget).data('packageUpdateServerID')); |
3536d2fe AE |
1357 | } |
1358 | } | |
1359 | }); | |
1360 | ||
1361 | /** | |
1362 | * Searches for available updates. | |
60fe64f6 AE |
1363 | * |
1364 | * @param boolean bindOnExistingButtons | |
3536d2fe AE |
1365 | */ |
1366 | WCF.ACP.Package.Update.Search = Class.extend({ | |
1367 | /** | |
1368 | * dialog overlay | |
1369 | * @var jQuery | |
1370 | */ | |
1371 | _dialog: null, | |
1372 | ||
1373 | /** | |
60fe64f6 AE |
1374 | * Initializes the WCF.ACP.Package.SearchForUpdates class. |
1375 | * | |
1376 | * @param boolean bindOnExistingButtons | |
3536d2fe | 1377 | */ |
60fe64f6 | 1378 | init: function(bindOnExistingButtons) { |
3536d2fe AE |
1379 | this._dialog = null; |
1380 | ||
60fe64f6 AE |
1381 | if (bindOnExistingButtons === true) { |
1382 | $('.jsButtonPackageUpdate').click($.proxy(this._click, this)); | |
1383 | } | |
1384 | else { | |
f2b50825 | 1385 | var $button = $('<li><a class="button"><span class="icon icon16 fa-refresh"></span> <span>' + WCF.Language.get('wcf.acp.package.searchForUpdates') + '</span></a></li>'); |
549b92e7 | 1386 | $button.click(this._click.bind(this)).prependTo($('.contentHeaderNavigation > ul')); |
60fe64f6 | 1387 | } |
3536d2fe AE |
1388 | }, |
1389 | ||
1390 | /** | |
1391 | * Handles clicks on the search button. | |
1392 | */ | |
1393 | _click: function() { | |
1394 | if (this._dialog === null) { | |
1395 | new WCF.Action.Proxy({ | |
1396 | autoSend: true, | |
1397 | data: { | |
1398 | actionName: 'searchForUpdates', | |
70e6f4e6 AE |
1399 | className: 'wcf\\data\\package\\update\\PackageUpdateAction', |
1400 | parameters: { | |
1401 | ignoreCache: 1 | |
1402 | } | |
3536d2fe AE |
1403 | }, |
1404 | success: $.proxy(this._success, this) | |
1405 | }); | |
1406 | } | |
1407 | else { | |
1408 | this._dialog.wcfDialog('open'); | |
1409 | } | |
1410 | }, | |
1411 | ||
1412 | /** | |
1413 | * Handles successful AJAX requests. | |
1414 | * | |
1415 | * @param object data | |
1416 | * @param string textStatus | |
1417 | * @param jQuery jqXHR | |
1418 | */ | |
1419 | _success: function(data, textStatus, jqXHR) { | |
1420 | if (data.returnValues.url) { | |
1421 | window.location = data.returnValues.url; | |
1422 | } | |
1423 | else { | |
1424 | this._dialog = $('<div>' + WCF.Language.get('wcf.acp.package.searchForUpdates.noResults') + '</div>').hide().appendTo(document.body); | |
1425 | this._dialog.wcfDialog({ | |
1426 | title: WCF.Language.get('wcf.acp.package.searchForUpdates') | |
1427 | }); | |
1428 | } | |
1429 | } | |
1430 | }); | |
1431 | ||
317c8af5 AE |
1432 | /** |
1433 | * Namespace for classes related to the WoltLab Plugin-Store. | |
1434 | */ | |
1435 | WCF.ACP.PluginStore = { }; | |
1436 | ||
1437 | /** | |
1438 | * Namespace for classes handling items purchased in the WoltLab Plugin-Store. | |
1439 | */ | |
1440 | WCF.ACP.PluginStore.PurchasedItems = { }; | |
1441 | ||
1442 | /** | |
1443 | * Searches for purchased items available for install but not yet installed. | |
1444 | */ | |
1445 | WCF.ACP.PluginStore.PurchasedItems.Search = Class.extend({ | |
4087dcf3 AE |
1446 | /** |
1447 | * dialog overlay | |
1448 | * @var jQuery | |
1449 | */ | |
317c8af5 | 1450 | _dialog: null, |
4087dcf3 AE |
1451 | |
1452 | /** | |
1453 | * action proxy | |
1454 | * @var WCF.Action.Proxy | |
1455 | */ | |
317c8af5 | 1456 | _proxy: null, |
317c8af5 | 1457 | |
4087dcf3 AE |
1458 | /** |
1459 | * Initializes the WCF.ACP.PluginStore.PurchasedItems.Search class. | |
1460 | */ | |
d1813e77 | 1461 | init: function() { |
317c8af5 AE |
1462 | this._dialog = null; |
1463 | this._proxy = new WCF.Action.Proxy({ | |
1464 | success: $.proxy(this._success, this) | |
1465 | }); | |
317c8af5 | 1466 | |
d528766d | 1467 | var $button = $('<li><a class="button"><span class="icon icon16 fa-shopping-cart" /> <span>' + WCF.Language.get('wcf.acp.pluginStore.purchasedItems.button.search') + '</span></a></li>'); |
8e61f344 | 1468 | $button.prependTo($('.contentHeaderNavigation > ul')).click($.proxy(this._click, this)); |
317c8af5 AE |
1469 | }, |
1470 | ||
4087dcf3 AE |
1471 | /** |
1472 | * Handles clicks on the search button. | |
1473 | */ | |
317c8af5 AE |
1474 | _click: function() { |
1475 | this._proxy.setOption('data', { | |
1476 | actionName: 'searchForPurchasedItems', | |
d1813e77 | 1477 | className: 'wcf\\data\\package\\PackageAction' |
317c8af5 AE |
1478 | }); |
1479 | this._proxy.sendRequest(); | |
1480 | }, | |
1481 | ||
4087dcf3 AE |
1482 | /** |
1483 | * Handles successful AJAX requests. | |
1484 | * | |
1485 | * @param object data | |
1486 | * @param string textStatus | |
1487 | * @param jQuery jqXHR | |
1488 | */ | |
317c8af5 | 1489 | _success: function(data, textStatus, jqXHR) { |
4087dcf3 | 1490 | // prompt for credentials |
317c8af5 AE |
1491 | if (data.returnValues.template) { |
1492 | if (this._dialog === null) { | |
1493 | this._dialog = $('<div />').hide().appendTo(document.body); | |
1494 | this._dialog.html(data.returnValues.template).wcfDialog({ | |
d528766d | 1495 | title: WCF.Language.get('wcf.acp.pluginStore.authorization') |
317c8af5 AE |
1496 | }); |
1497 | } | |
1498 | else { | |
1499 | this._dialog.html(data.returnValues.template); | |
1500 | this._dialog.wcfDialog('open'); | |
1501 | } | |
1502 | ||
298a7cd8 AE |
1503 | var $button = this._dialog.find('button').click($.proxy(this._submit, this)); |
1504 | this._dialog.find('input').keyup(function(event) { | |
1505 | if (event.which == $.ui.keyCode.ENTER) { | |
1506 | $button.trigger('click'); | |
1507 | return false; | |
1508 | } | |
1509 | }); | |
317c8af5 AE |
1510 | } |
1511 | else if (data.returnValues.noResults) { | |
4087dcf3 | 1512 | // there are no purchased products yet |
74cde074 | 1513 | if (this._dialog === null) { |
1514 | this._dialog = $('<div />').hide().appendTo(document.body); | |
1515 | this._dialog.html(data.returnValues.noResults).wcfDialog({ | |
1516 | title: WCF.Language.get('wcf.acp.pluginStore.purchasedItems') | |
1517 | }); | |
1518 | } else { | |
1519 | this._dialog.wcfDialog('option', 'title', WCF.Language.get('wcf.acp.pluginStore.purchasedItems')); | |
1520 | this._dialog.html(data.returnValues.noResults); | |
1521 | this._dialog.wcfDialog('open'); | |
1522 | } | |
317c8af5 | 1523 | } |
93c9c717 AE |
1524 | else if (data.returnValues.noSSL) { |
1525 | // PHP was compiled w/o OpenSSL support | |
1526 | if (this._dialog === null) { | |
1527 | this._dialog = $('<div />').hide().appendTo(document.body); | |
1528 | this._dialog.html(data.returnValues.noSSL).wcfDialog({ | |
1529 | title: WCF.Language.get('wcf.global.error.title') | |
1530 | }); | |
1531 | } | |
1532 | else { | |
1533 | this._dialog.wcfDialog('option', 'title', WCF.Language.get('wcf.global.error.title')); | |
1534 | this._dialog.html(data.returnValues.noSSL); | |
1535 | this._dialog.wcfDialog('open'); | |
1536 | } | |
1537 | } | |
298a7cd8 | 1538 | else if (data.returnValues.redirectURL) { |
4087dcf3 | 1539 | // redirect to list of purchased products |
298a7cd8 AE |
1540 | window.location = data.returnValues.redirectURL; |
1541 | } | |
317c8af5 AE |
1542 | }, |
1543 | ||
4087dcf3 AE |
1544 | /** |
1545 | * Submits the user credentials. | |
1546 | */ | |
317c8af5 AE |
1547 | _submit: function() { |
1548 | this._dialog.wcfDialog('close'); | |
1549 | ||
1550 | this._proxy.setOption('data', { | |
1551 | actionName: 'searchForPurchasedItems', | |
1552 | className: 'wcf\\data\\package\\PackageAction', | |
1553 | parameters: { | |
1554 | password: $('#pluginStorePassword').val(), | |
d1813e77 | 1555 | username: $('#pluginStoreUsername').val() |
317c8af5 AE |
1556 | } |
1557 | }); | |
1558 | this._proxy.sendRequest(); | |
1559 | } | |
1560 | }); | |
1561 | ||
532f1173 AE |
1562 | /** |
1563 | * Worker support for ACP. | |
1564 | * | |
1565 | * @param string dialogID | |
1566 | * @param string className | |
0cb0c522 AE |
1567 | * @param string title |
1568 | * @param object parameters | |
1569 | * @param object callback | |
835354e5 AE |
1570 | * |
1571 | * @deprecated 3.1 - please use `WoltLabSuite/Core/Acp/Ui/Worker` instead | |
532f1173 | 1572 | */ |
1f9100ba | 1573 | WCF.ACP.Worker = Class.extend({ |
532f1173 AE |
1574 | /** |
1575 | * Initializes a new worker instance. | |
1576 | * | |
1577 | * @param string dialogID | |
1578 | * @param string className | |
2cea2b5b AE |
1579 | * @param string title |
1580 | * @param object parameters | |
0cb0c522 | 1581 | * @param object callback |
532f1173 | 1582 | */ |
0cb0c522 | 1583 | init: function(dialogID, className, title, parameters, callback) { |
835354e5 AE |
1584 | if (typeof callback === 'function') { |
1585 | throw new Error("The callback parameter is no longer supported, please migrate to 'WoltLabSuite/Core/Acp/Ui/Worker'."); | |
532f1173 AE |
1586 | } |
1587 | ||
835354e5 AE |
1588 | require(['WoltLabSuite/Core/Acp/Ui/Worker'], function(AcpUiWorker) { |
1589 | new AcpUiWorker({ | |
1590 | // dialog | |
1591 | dialogId: dialogID, | |
1592 | dialogTitle: title, | |
1593 | ||
1594 | // ajax | |
1595 | className: className, | |
1596 | parameters: parameters | |
532f1173 | 1597 | }); |
835354e5 | 1598 | }); |
532f1173 | 1599 | } |
1f9100ba | 1600 | }); |
13d8b49b MS |
1601 | |
1602 | /** | |
1603 | * Namespace for category-related functions. | |
1604 | */ | |
cb6e5946 | 1605 | WCF.ACP.Category = { }; |
13d8b49b MS |
1606 | |
1607 | /** | |
1608 | * Handles collapsing categories. | |
1609 | * | |
1610 | * @param string className | |
1611 | * @param integer objectTypeID | |
1612 | */ | |
1613 | WCF.ACP.Category.Collapsible = WCF.Collapsible.SimpleRemote.extend({ | |
1614 | /** | |
1615 | * @see WCF.Collapsible.Remote.init() | |
1616 | */ | |
fc3d134b | 1617 | init: function(className) { |
13d8b49b MS |
1618 | var sortButton = $('.formSubmit > button[data-type="submit"]'); |
1619 | if (sortButton) { | |
1620 | sortButton.click($.proxy(this._sort, this)); | |
1621 | } | |
1622 | ||
1623 | this._super(className); | |
1624 | }, | |
9f959ced | 1625 | |
13d8b49b MS |
1626 | /** |
1627 | * @see WCF.Collapsible.Remote._getButtonContainer() | |
1628 | */ | |
1629 | _getButtonContainer: function(containerID) { | |
1630 | return $('#' + containerID + ' > .buttons'); | |
1631 | }, | |
9f959ced | 1632 | |
13d8b49b MS |
1633 | /** |
1634 | * @see WCF.Collapsible.Remote._getContainers() | |
1635 | */ | |
1636 | _getContainers: function() { | |
1637 | return $('.jsCategory').has('ol').has('li'); | |
1638 | }, | |
9f959ced | 1639 | |
13d8b49b MS |
1640 | /** |
1641 | * @see WCF.Collapsible.Remote._getTarget() | |
1642 | */ | |
1643 | _getTarget: function(containerID) { | |
1644 | return $('#' + containerID + ' > ol'); | |
1645 | }, | |
1646 | ||
1647 | /** | |
1648 | * Handles a click on the sort button. | |
1649 | */ | |
1650 | _sort: function() { | |
1651 | // remove existing collapsible buttons | |
1652 | $('.collapsibleButton').remove(); | |
1653 | ||
1654 | // reinit containers | |
cb6e5946 MS |
1655 | this._containers = { }; |
1656 | this._containerData = { }; | |
13d8b49b MS |
1657 | |
1658 | var $containers = this._getContainers(); | |
1659 | if ($containers.length == 0) { | |
a0b60d23 | 1660 | console.debug('[WCF.ACP.Category.Collapsible] Empty container set given, aborting.'); |
13d8b49b MS |
1661 | } |
1662 | $containers.each($.proxy(function(index, container) { | |
1663 | var $container = $(container); | |
1664 | var $containerID = $container.wcfIdentify(); | |
1665 | this._containers[$containerID] = $container; | |
1666 | ||
1667 | this._initContainer($containerID); | |
1668 | }, this)); | |
1669 | } | |
1670 | }); | |
1671 | ||
71662ae8 AE |
1672 | /** |
1673 | * Provides the search dropdown for ACP | |
1674 | * | |
1675 | * @see WCF.Search.Base | |
1676 | */ | |
1677 | WCF.ACP.Search = WCF.Search.Base.extend({ | |
c8f7b2a1 MW |
1678 | /** |
1679 | * name of the selected search provider | |
1680 | * @var string | |
1681 | */ | |
1682 | _providerName: '', | |
1683 | ||
71662ae8 AE |
1684 | /** |
1685 | * @see WCF.Search.Base.init() | |
1686 | */ | |
1687 | init: function() { | |
1688 | this._className = 'wcf\\data\\acp\\search\\provider\\ACPSearchProviderAction'; | |
6476e7a1 | 1689 | this._super('#pageHeaderSearch input[name=q]'); |
d6760827 MS |
1690 | |
1691 | // disable form submitting | |
6476e7a1 | 1692 | $('#pageHeaderSearch > form').on('submit', function(event) { |
d6760827 MS |
1693 | event.preventDefault(); |
1694 | }); | |
c8f7b2a1 MW |
1695 | |
1696 | var $dropdown = WCF.Dropdown.getDropdownMenu('pageHeaderSearchType'); | |
1697 | $dropdown.find('a[data-provider-name]').on('click', $.proxy(function(event) { | |
1698 | event.preventDefault(); | |
1699 | var $button = $(event.target); | |
1700 | $('.pageHeaderSearchType > .button').text($button.text()); | |
1701 | ||
1702 | var $oldProviderName = this._providerName; | |
1703 | this._providerName = ($button.data('providerName') != 'everywhere' ? $button.data('providerName') : ''); | |
1704 | ||
1705 | if ($oldProviderName != this._providerName) { | |
1706 | var $searchString = $.trim(this._searchInput.val()); | |
1707 | if ($searchString) { | |
1708 | var $parameters = { | |
1709 | data: { | |
1710 | excludedSearchValues: this._excludedSearchValues, | |
1711 | searchString: $searchString | |
1712 | } | |
1713 | }; | |
1714 | this._queryServer($parameters); | |
1715 | } | |
c5dd767e | 1716 | } |
c8f7b2a1 | 1717 | }, this)); |
71662ae8 AE |
1718 | }, |
1719 | ||
1720 | /** | |
1721 | * @see WCF.Search.Base._createListItem() | |
1722 | */ | |
1723 | _createListItem: function(resultList) { | |
1724 | // add a divider between result lists | |
1725 | if (this._list.children('li').length > 0) { | |
1726 | $('<li class="dropdownDivider" />').appendTo(this._list); | |
1727 | } | |
1728 | ||
1729 | // add caption | |
1730 | $('<li class="dropdownText">' + resultList.title + '</li>').appendTo(this._list); | |
1731 | ||
1732 | // add menu items | |
1733 | for (var $i in resultList.items) { | |
1734 | var $item = resultList.items[$i]; | |
1735 | ||
790aadd9 | 1736 | $('<li><a href="' + $item.link + '"><span>' + WCF.String.escapeHTML($item.title) + '</span>' + ($item.subtitle ? '<small>' + WCF.String.escapeHTML($item.subtitle) + '</small>' : '') + '</a></li>').appendTo(this._list); |
9a130ab4 AE |
1737 | |
1738 | this._itemCount++; | |
71662ae8 | 1739 | } |
9a130ab4 AE |
1740 | }, |
1741 | ||
71c70823 MS |
1742 | /** |
1743 | * @see WCF.Search.Base._openDropdown() | |
1744 | */ | |
1745 | _openDropdown: function() { | |
1746 | this._list.find('small').each(function(index, element) { | |
1747 | while (element.scrollWidth > element.clientWidth) { | |
1748 | element.innerText = '\u2026 ' + element.innerText.substr(3); | |
1749 | } | |
1750 | }); | |
1751 | }, | |
1752 | ||
c138555b AE |
1753 | /** |
1754 | * @see WCF.Search.Base._handleEmptyResult() | |
1755 | */ | |
1756 | _handleEmptyResult: function() { | |
1757 | $('<li class="dropdownText">' + WCF.Language.get('wcf.acp.search.noResults') + '</li>').appendTo(this._list); | |
1758 | ||
1759 | return true; | |
1760 | }, | |
1761 | ||
9a130ab4 AE |
1762 | /** |
1763 | * @see WCF.Search.Base._highlightSelectedElement() | |
1764 | */ | |
1765 | _highlightSelectedElement: function() { | |
1766 | this._list.find('li').removeClass('dropdownNavigationItem'); | |
1767 | this._list.find('li:not(.dropdownDivider):not(.dropdownText)').eq(this._itemIndex).addClass('dropdownNavigationItem'); | |
1768 | }, | |
1769 | ||
1770 | /** | |
1771 | * @see WCF.Search.Base._selectElement() | |
1772 | */ | |
1773 | _selectElement: function(event) { | |
c138555b AE |
1774 | if (this._itemIndex === -1) { |
1775 | return false; | |
1776 | } | |
1777 | ||
9a130ab4 | 1778 | window.location = this._list.find('li.dropdownNavigationItem > a').attr('href'); |
6476e7a1 AE |
1779 | }, |
1780 | ||
1781 | _success: function(data) { | |
1782 | this._super(data); | |
1783 | ||
1784 | this._list.addClass('acpSearchDropdown'); | |
c8f7b2a1 MW |
1785 | }, |
1786 | ||
1787 | /** | |
1788 | * @see WCF.Search.Base._getParameters() | |
1789 | */ | |
1790 | _getParameters: function(parameters) { | |
1791 | parameters.data.providerName = this._providerName; | |
1792 | ||
1793 | return parameters; | |
71662ae8 AE |
1794 | } |
1795 | }); | |
11cf19be MW |
1796 | |
1797 | /** | |
1798 | * Namespace for user management. | |
1799 | */ | |
1800 | WCF.ACP.User = { }; | |
1801 | ||
1802 | /** | |
1803 | * Generic implementation to ban users. | |
1804 | */ | |
1805 | WCF.ACP.User.BanHandler = { | |
1806 | /** | |
1807 | * callback object | |
1808 | * @var object | |
1809 | */ | |
1810 | _callback: null, | |
1811 | ||
1812 | /** | |
1813 | * dialog overlay | |
1814 | * @var jQuery | |
1815 | */ | |
1816 | _dialog: null, | |
1817 | ||
1818 | /** | |
1819 | * action proxy | |
1820 | * @var WCF.Action.Proxy | |
1821 | */ | |
1822 | _proxy: null, | |
1823 | ||
1824 | /** | |
1825 | * Initializes WCF.ACP.User.BanHandler on first use. | |
1826 | */ | |
1827 | init: function() { | |
11cf19be MW |
1828 | this._proxy = new WCF.Action.Proxy({ |
1829 | success: $.proxy(this._success, this) | |
1830 | }); | |
1831 | ||
1832 | $('.jsBanButton').click($.proxy(function(event) { | |
1833 | var $button = $(event.currentTarget); | |
1834 | if ($button.data('banned')) { | |
1835 | this.unban([ $button.data('objectID') ]); | |
1836 | } | |
1837 | else { | |
1838 | this.ban([ $button.data('objectID') ]); | |
1839 | } | |
1840 | }, this)); | |
bbef7ed8 | 1841 | |
efcd047d MS |
1842 | require(['EventHandler'], function(EventHandler) { |
1843 | EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.user', this._clipboardAction.bind(this)); | |
1844 | }.bind(this)); | |
bbef7ed8 MW |
1845 | }, |
1846 | ||
1847 | /** | |
efcd047d MS |
1848 | * Reacts to executed clipboard actions. |
1849 | * | |
1850 | * @param {object<string, *>} actionData data of the executed clipboard action | |
bbef7ed8 | 1851 | */ |
efcd047d MS |
1852 | _clipboardAction: function(actionData) { |
1853 | if (actionData.data.actionName === 'com.woltlab.wcf.user.ban') { | |
1854 | this.ban(actionData.data.parameters.objectIDs); | |
bbef7ed8 | 1855 | } |
11cf19be MW |
1856 | }, |
1857 | ||
1858 | /** | |
1859 | * Unbans users. | |
1860 | * | |
1861 | * @param array<integer> userIDs | |
1862 | */ | |
1863 | unban: function(userIDs) { | |
1864 | this._proxy.setOption('data', { | |
1865 | actionName: 'unban', | |
1866 | className: 'wcf\\data\\user\\UserAction', | |
1867 | objectIDs: userIDs | |
1868 | }); | |
1869 | this._proxy.sendRequest(); | |
1870 | }, | |
1871 | ||
1872 | /** | |
1873 | * Bans users. | |
1874 | * | |
1875 | * @param array<integer> userIDs | |
1876 | */ | |
1877 | ban: function(userIDs) { | |
f034d0ec MS |
1878 | if (this._dialog === null) { |
1879 | // create dialog | |
1880 | this._dialog = $('<div />').hide().appendTo(document.body); | |
6f2bc235 | 1881 | this._dialog.append($('<div class="section"><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><dl><dt></dt><dd><label for="userBanNeverExpires"><input type="checkbox" name="userBanNeverExpires" id="userBanNeverExpires" checked> ' + WCF.Language.get('wcf.acp.user.ban.neverExpires') + '</label></dd></dl><dl id="userBanExpiresSettings" style="display: none;"><dt><label for="userBanExpires">' + WCF.Language.get('wcf.acp.user.ban.expires') + '</label></dt><dd><input type="date" name="userBanExpires" id="userBanExpires" class="medium" min="' + new Date(TIME_NOW * 1000).toISOString() + '" data-ignore-timezone="true" /><small>' + WCF.Language.get('wcf.acp.user.ban.expires.description') + '</small></dd></dl></div>')); |
f034d0ec MS |
1882 | this._dialog.append($('<div class="formSubmit"><button class="buttonPrimary" accesskey="s">' + WCF.Language.get('wcf.global.button.submit') + '</button></div>')); |
1883 | ||
1884 | this._dialog.find('#userBanNeverExpires').change(function() { | |
1885 | $('#userBanExpiresSettings').toggle(); | |
1886 | }); | |
1887 | ||
1888 | this._dialog.find('button').click($.proxy(this._submit, this)); | |
1889 | } | |
1890 | else { | |
1891 | // reset dialog | |
1892 | $('#userBanReason').val(''); | |
1893 | $('#userBanNeverExpires').prop('checked', true); | |
1894 | $('#userBanExpiresSettings').hide(); | |
1895 | $('#userBanExpiresDatePicker, #userBanExpires').val(''); | |
1896 | } | |
1897 | ||
1898 | this._dialog.data('userIDs', userIDs); | |
1899 | this._dialog.wcfDialog({ | |
1900 | title: WCF.Language.get('wcf.acp.user.ban.sure') | |
1901 | }); | |
1902 | }, | |
1903 | ||
1904 | /** | |
1905 | * Handles submitting the ban dialog. | |
1906 | */ | |
1907 | _submit: function() { | |
1908 | this._dialog.find('.innerError').remove(); | |
1909 | ||
1910 | var $banExpires = ''; | |
1911 | if (!$('#userBanNeverExpires').is(':checked')) { | |
1912 | var $banExpires = $('#userBanExpiresDatePicker').val(); | |
1913 | if (!$banExpires) { | |
1914 | this._dialog.find('#userBanExpiresSettings > dd > small').prepend($('<small class="innerError" />').text(WCF.Language.get('wcf.global.form.error.empty'))); | |
1915 | return | |
1916 | } | |
1917 | } | |
1918 | ||
1919 | this._proxy.setOption('data', { | |
1920 | actionName: 'ban', | |
1921 | className: 'wcf\\data\\user\\UserAction', | |
1922 | objectIDs: this._dialog.data('userIDs'), | |
1923 | parameters: { | |
1924 | banReason: $('#userBanReason').val(), | |
1925 | banExpires: $banExpires | |
11cf19be | 1926 | } |
f034d0ec MS |
1927 | }); |
1928 | this._proxy.sendRequest(); | |
11cf19be MW |
1929 | }, |
1930 | ||
1931 | /** | |
1932 | * Handles successful AJAX calls. | |
1933 | * | |
1934 | * @param object data | |
1935 | * @param string textStatus | |
1936 | * @param jQuery jqXHR | |
1937 | */ | |
1938 | _success: function(data, textStatus, jqXHR) { | |
1939 | $('.jsBanButton').each(function(index, button) { | |
1940 | var $button = $(button); | |
1941 | if (WCF.inArray($button.data('objectID'), data.objectIDs)) { | |
1942 | if (data.actionName == 'unban') { | |
6783e56b | 1943 | $button.data('banned', false).attr('data-tooltip', $button.data('banMessage')).removeClass('fa-lock').addClass('fa-unlock'); |
11cf19be MW |
1944 | } |
1945 | else { | |
6783e56b | 1946 | $button.data('banned', true).attr('data-tooltip', $button.data('unbanMessage')).removeClass('fa-unlock').addClass('fa-lock'); |
11cf19be MW |
1947 | } |
1948 | } | |
1949 | }); | |
1950 | ||
1951 | var $notification = new WCF.System.Notification(); | |
1952 | $notification.show(); | |
bbef7ed8 MW |
1953 | |
1954 | WCF.Clipboard.reload(); | |
f034d0ec MS |
1955 | |
1956 | if (data.actionName == 'ban') { | |
1957 | this._dialog.wcfDialog('close'); | |
1958 | } | |
11cf19be | 1959 | } |
bc3b71fd | 1960 | }; |
ef012ee1 | 1961 | |
2a5d6b57 MS |
1962 | /** |
1963 | * Namespace for user group management. | |
1964 | */ | |
1965 | WCF.ACP.User.Group = { }; | |
1966 | ||
1967 | /** | |
1968 | * Handles copying user groups. | |
1969 | */ | |
1970 | WCF.ACP.User.Group.Copy = Class.extend({ | |
1971 | /** | |
1972 | * id of the copied group | |
1973 | * @var integer | |
1974 | */ | |
1975 | _groupID: 0, | |
1976 | ||
1977 | /** | |
1978 | * Initializes a new instance of WCF.ACP.User.Group.Copy. | |
1979 | * | |
1980 | * @param integer groupID | |
1981 | */ | |
1982 | init: function(groupID) { | |
1983 | this._groupID = groupID; | |
1984 | ||
1985 | $('.jsButtonUserGroupCopy').click($.proxy(this._click, this)); | |
1986 | }, | |
1987 | ||
1988 | /** | |
1989 | * Handles clicking on a 'copy user group' button. | |
1990 | */ | |
1991 | _click: function() { | |
7730f067 | 1992 | var $template = $('<div class="section" />'); |
95961bdf MW |
1993 | $template.append($('<dl class="wide"><dt /><dd><label><input type="checkbox" id="copyMembers" value="1" /> ' + WCF.Language.get('wcf.acp.group.copy.copyMembers') + '</label><small>' + WCF.Language.get('wcf.acp.group.copy.copyMembers.description') + '</small></dd></dl>')); |
1994 | $template.append($('<dl class="wide"><dt /><dd><label><input type="checkbox" id="copyUserGroupOptions" value="1" /> ' + WCF.Language.get('wcf.acp.group.copy.copyUserGroupOptions') + '</label><small>' + WCF.Language.get('wcf.acp.group.copy.copyUserGroupOptions.description') + '</small></dd></dl>')); | |
1995 | $template.append($('<dl class="wide"><dt /><dd><label><input type="checkbox" id="copyACLOptions" value="1" /> ' + WCF.Language.get('wcf.acp.group.copy.copyACLOptions') + '</label><small>' + WCF.Language.get('wcf.acp.group.copy.copyACLOptions.description') + '</small></dd></dl>')); | |
2a5d6b57 MS |
1996 | |
1997 | WCF.System.Confirmation.show(WCF.Language.get('wcf.acp.group.copy.confirmMessage'), $.proxy(function(action) { | |
1998 | if (action === 'confirm') { | |
1999 | new WCF.Action.Proxy({ | |
2000 | autoSend: true, | |
2001 | data: { | |
2002 | actionName: 'copy', | |
2003 | className: 'wcf\\data\\user\\group\\UserGroupAction', | |
2004 | objectIDs: [ this._groupID ], | |
2005 | parameters: { | |
2006 | copyACLOptions: $('#copyACLOptions').is(':checked'), | |
2007 | copyMembers: $('#copyMembers').is(':checked'), | |
2008 | copyUserGroupOptions: $('#copyUserGroupOptions').is(':checked') | |
2009 | } | |
2010 | }, | |
2011 | success: function(data) { | |
2012 | window.location = data.returnValues.redirectURL; | |
2013 | } | |
2014 | }); | |
2015 | } | |
23e43ac5 | 2016 | }, this), '', $template, true); |
2a5d6b57 MS |
2017 | } |
2018 | }); | |
2019 | ||
ef012ee1 MW |
2020 | /** |
2021 | * Generic implementation to enable users. | |
2022 | */ | |
2023 | WCF.ACP.User.EnableHandler = { | |
2024 | /** | |
2025 | * action proxy | |
2026 | * @var WCF.Action.Proxy | |
2027 | */ | |
2028 | _proxy: null, | |
2029 | ||
2030 | /** | |
2031 | * Initializes WCF.ACP.User.EnableHandler on first use. | |
2032 | */ | |
2033 | init: function() { | |
2034 | this._proxy = new WCF.Action.Proxy({ | |
2035 | success: $.proxy(this._success, this) | |
2036 | }); | |
2037 | ||
2038 | $('.jsEnableButton').click($.proxy(function(event) { | |
2039 | var $button = $(event.currentTarget); | |
2040 | if ($button.data('enabled')) { | |
2041 | this.disable([ $button.data('objectID') ]); | |
2042 | } | |
2043 | else { | |
2044 | this.enable([ $button.data('objectID') ]); | |
2045 | } | |
2046 | }, this)); | |
2047 | ||
efcd047d MS |
2048 | require(['EventHandler'], function(EventHandler) { |
2049 | EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.user', this._clipboardAction.bind(this)); | |
2050 | }.bind(this)); | |
ef012ee1 MW |
2051 | }, |
2052 | ||
2053 | /** | |
efcd047d MS |
2054 | * Reacts to executed clipboard actions. |
2055 | * | |
2056 | * @param {object<string, *>} actionData data of the executed clipboard action | |
ef012ee1 | 2057 | */ |
efcd047d MS |
2058 | _clipboardAction: function(actionData) { |
2059 | if (actionData.data.actionName === 'com.woltlab.wcf.user.enable') { | |
2060 | this.enable(actionData.data.parameters.objectIDs); | |
ef012ee1 MW |
2061 | } |
2062 | }, | |
2063 | ||
2064 | /** | |
2065 | * Disables users. | |
2066 | * | |
2067 | * @param array<integer> userIDs | |
2068 | */ | |
2069 | disable: function(userIDs) { | |
2070 | this._proxy.setOption('data', { | |
2071 | actionName: 'disable', | |
2072 | className: 'wcf\\data\\user\\UserAction', | |
2073 | objectIDs: userIDs | |
2074 | }); | |
2075 | this._proxy.sendRequest(); | |
2076 | }, | |
2077 | ||
2078 | /** | |
2079 | * Enables users. | |
2080 | * | |
2081 | * @param array<integer> userIDs | |
2082 | */ | |
2083 | enable: function(userIDs) { | |
2084 | this._proxy.setOption('data', { | |
2085 | actionName: 'enable', | |
2086 | className: 'wcf\\data\\user\\UserAction', | |
2087 | objectIDs: userIDs | |
2088 | }); | |
2089 | this._proxy.sendRequest(); | |
2090 | }, | |
2091 | ||
2092 | /** | |
2093 | * Handles successful AJAX calls. | |
2094 | * | |
2095 | * @param object data | |
2096 | * @param string textStatus | |
2097 | * @param jQuery jqXHR | |
2098 | */ | |
2099 | _success: function(data, textStatus, jqXHR) { | |
2100 | $('.jsEnableButton').each(function(index, button) { | |
2101 | var $button = $(button); | |
2102 | if (WCF.inArray($button.data('objectID'), data.objectIDs)) { | |
2103 | if (data.actionName == 'disable') { | |
6783e56b | 2104 | $button.data('enabled', false).attr('data-tooltip', $button.data('enableMessage')).removeClass('fa-check-square-o').addClass('fa-square-o'); |
ef012ee1 MW |
2105 | } |
2106 | else { | |
6783e56b | 2107 | $button.data('enabled', true).attr('data-tooltip', $button.data('disableMessage')).removeClass('fa-square-o').addClass('fa-check-square-o'); |
ef012ee1 MW |
2108 | } |
2109 | } | |
2110 | }); | |
2111 | ||
2112 | var $notification = new WCF.System.Notification(); | |
00ce5cf8 | 2113 | $notification.show(function() { window.location.reload(); }); |
ef012ee1 MW |
2114 | } |
2115 | }; | |
2116 | ||
cb6e5946 MS |
2117 | /** |
2118 | * Handles the send new password clipboard action. | |
2119 | */ | |
2120 | WCF.ACP.User.SendNewPasswordHandler = { | |
cb6e5946 MS |
2121 | /** |
2122 | * Initializes WCF.ACP.User.SendNewPasswordHandler on first use. | |
2123 | */ | |
2124 | init: function() { | |
efcd047d MS |
2125 | require(['EventHandler'], function(EventHandler) { |
2126 | EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.user', this._clipboardAction.bind(this)); | |
2127 | }.bind(this)); | |
cb6e5946 MS |
2128 | }, |
2129 | ||
2130 | /** | |
efcd047d MS |
2131 | * Reacts to executed clipboard actions. |
2132 | * | |
2133 | * @param {object<string, *>} actionData data of the executed clipboard action | |
cb6e5946 | 2134 | */ |
efcd047d MS |
2135 | _clipboardAction: function(actionData) { |
2136 | if (actionData.data.actionName === 'com.woltlab.wcf.user.sendNewPassword') { | |
2137 | WCF.System.Confirmation.show(actionData.data.parameters.confirmMessage, function(action) { | |
cb6e5946 MS |
2138 | if (action === 'confirm') { |
2139 | new WCF.ACP.Worker('sendingNewPasswords', 'wcf\\system\\worker\\SendNewPasswordWorker', WCF.Language.get('wcf.acp.user.sendNewPassword.workerTitle'), { | |
efcd047d | 2140 | userIDs: actionData.data.parameters.objectIDs |
cb6e5946 MS |
2141 | }); |
2142 | } | |
2143 | }); | |
2144 | } | |
2145 | } | |
2146 | }; | |
2147 | ||
971fbab8 AE |
2148 | /** |
2149 | * Namespace for import-related classes. | |
2150 | */ | |
2151 | WCF.ACP.Import = { }; | |
2152 | ||
24d15c69 AE |
2153 | /** |
2154 | * Importer for ACP. | |
2155 | * | |
971fbab8 | 2156 | * @param array<string> objectTypes |
24d15c69 | 2157 | */ |
971fbab8 | 2158 | WCF.ACP.Import.Manager = Class.extend({ |
24d15c69 | 2159 | /** |
971fbab8 AE |
2160 | * current action |
2161 | * @var string | |
24d15c69 | 2162 | */ |
971fbab8 | 2163 | _currentAction: '', |
24d15c69 AE |
2164 | |
2165 | /** | |
2166 | * dialog overlay | |
2167 | * @var jQuery | |
2168 | */ | |
2169 | _dialog: null, | |
2170 | ||
971fbab8 AE |
2171 | /** |
2172 | * current object type index | |
67c2bb1d | 2173 | * @var int |
971fbab8 AE |
2174 | */ |
2175 | _index: -1, | |
2176 | ||
2177 | /** | |
2178 | * list of object types | |
67c2bb1d | 2179 | * @var string[] |
971fbab8 | 2180 | */ |
67c2bb1d | 2181 | _objectTypes: [], |
971fbab8 | 2182 | |
24d15c69 AE |
2183 | /** |
2184 | * action proxy | |
2185 | * @var WCF.Action.Proxy | |
2186 | */ | |
2187 | _proxy: null, | |
2188 | ||
fed8bce0 AE |
2189 | /** |
2190 | * redirect URL | |
2191 | * @var string | |
2192 | */ | |
2193 | _redirectURL: '', | |
2194 | ||
24d15c69 AE |
2195 | /** |
2196 | * Initializes the WCF.ACP.Importer object. | |
2197 | * | |
67c2bb1d AE |
2198 | * @param {string[]} objectTypes |
2199 | * @param {string} redirectURL | |
24d15c69 | 2200 | */ |
fed8bce0 | 2201 | init: function(objectTypes, redirectURL) { |
971fbab8 AE |
2202 | this._currentAction = ''; |
2203 | this._index = -1; | |
2204 | this._objectTypes = objectTypes; | |
24d15c69 AE |
2205 | this._proxy = new WCF.Action.Proxy({ |
2206 | showLoadingOverlay: false, | |
2207 | success: $.proxy(this._success, this), | |
772f616f | 2208 | url: 'index.php?worker-proxy/&t=' + SECURITY_TOKEN |
24d15c69 | 2209 | }); |
fed8bce0 | 2210 | this._redirectURL = redirectURL; |
971fbab8 AE |
2211 | |
2212 | this._invoke(); | |
24d15c69 AE |
2213 | }, |
2214 | ||
2215 | /** | |
2216 | * Invokes importing of an object type. | |
971fbab8 AE |
2217 | */ |
2218 | _invoke: function() { | |
2219 | this._index++; | |
2220 | if (this._index >= this._objectTypes.length) { | |
962f1164 | 2221 | this._dialog.find('.fa-spinner').removeClass('fa-spinner').addClass('fa-check'); |
3bbdfdb0 AE |
2222 | this._dialog.find('h1').text(WCF.Language.get('wcf.acp.dataImport.completed')); |
2223 | ||
2224 | var $form = $('<div class="formSubmit" />').appendTo(this._dialog.find('#workerContainer')); | |
2225 | $('<button>' + WCF.Language.get('wcf.global.button.next') + '</button>').click($.proxy(function() { | |
127ee67e AE |
2226 | new WCF.Action.Proxy({ |
2227 | autoSend: true, | |
2228 | data: { | |
2229 | noRedirect: 1 | |
2230 | }, | |
1d997070 | 2231 | dataType: 'html', |
127ee67e AE |
2232 | success: $.proxy(function() { |
2233 | window.location = this._redirectURL; | |
2234 | }, this), | |
772f616f | 2235 | url: 'index.php?cache-clear/&t=' + SECURITY_TOKEN |
127ee67e | 2236 | }); |
3bbdfdb0 AE |
2237 | }, this)).appendTo($form); |
2238 | ||
2239 | this._dialog.wcfDialog('render'); | |
971fbab8 AE |
2240 | } |
2241 | else { | |
2242 | this._run( | |
607e3941 | 2243 | WCF.Language.get('wcf.acp.dataImport.data.' + this._objectTypes[this._index]), |
971fbab8 AE |
2244 | this._objectTypes[this._index] |
2245 | ); | |
2246 | } | |
2247 | }, | |
2248 | ||
2249 | /** | |
2250 | * Executes import of given object type. | |
24d15c69 | 2251 | * |
971fbab8 | 2252 | * @param string currentAction |
24d15c69 AE |
2253 | * @param string objectType |
2254 | */ | |
971fbab8 AE |
2255 | _run: function(currentAction, objectType) { |
2256 | this._currentAction = currentAction; | |
24d15c69 AE |
2257 | this._proxy.setOption('data', { |
2258 | className: 'wcf\\system\\worker\\ImportWorker', | |
2259 | parameters: { | |
2260 | objectType: objectType | |
2261 | } | |
2262 | }); | |
2263 | this._proxy.sendRequest(); | |
2264 | }, | |
2265 | ||
2266 | /** | |
2267 | * Handles response from server. | |
2268 | * | |
2269 | * @param object data | |
2270 | */ | |
2271 | _success: function(data) { | |
2272 | // init binding | |
2273 | if (this._dialog === null) { | |
2274 | this._dialog = $('<div />').hide().appendTo(document.body); | |
2275 | this._dialog.wcfDialog({ | |
2276 | closable: false, | |
2277 | title: WCF.Language.get('wcf.acp.dataImport') | |
2278 | }); | |
2279 | } | |
2280 | ||
2281 | if (data.template) { | |
2282 | this._dialog.html(data.template); | |
2283 | } | |
2284 | ||
971fbab8 AE |
2285 | if (this._currentAction) { |
2286 | this._dialog.find('h1').text(this._currentAction); | |
2287 | } | |
2288 | ||
24d15c69 AE |
2289 | // update progress |
2290 | this._dialog.find('progress').attr('value', data.progress).text(data.progress + '%').next('span').text(data.progress + '%'); | |
2291 | ||
2292 | // worker is still busy with it's business, carry on | |
2293 | if (data.progress < 100) { | |
2294 | // send request for next loop | |
2295 | this._proxy.setOption('data', { | |
2296 | className: data.className, | |
2297 | loopCount: data.loopCount, | |
2298 | parameters: data.parameters | |
2299 | }); | |
2300 | this._proxy.sendRequest(); | |
2301 | } | |
2302 | else { | |
971fbab8 | 2303 | this._invoke(); |
24d15c69 AE |
2304 | } |
2305 | } | |
2306 | }); | |
e1fe9453 MW |
2307 | |
2308 | /** | |
2309 | * Namespace for stat-related classes. | |
2310 | */ | |
2311 | WCF.ACP.Stat = { }; | |
2312 | ||
2313 | /** | |
2314 | * Shows the daily stat chart. | |
2315 | */ | |
2316 | WCF.ACP.Stat.Chart = Class.extend({ | |
2317 | init: function() { | |
2318 | this._proxy = new WCF.Action.Proxy({ | |
2319 | success: $.proxy(this._success, this) | |
2320 | }); | |
2321 | ||
49ec07c5 | 2322 | $('#statRefreshButton').click($.proxy(this._refresh, this)); |
e1fe9453 | 2323 | |
49ec07c5 | 2324 | this._refresh(); |
e1fe9453 MW |
2325 | }, |
2326 | ||
49ec07c5 | 2327 | _refresh: function() { |
e1fe9453 MW |
2328 | var $objectTypeIDs = [ ]; |
2329 | $('input[name=objectTypeID]:checked').each(function() { | |
2330 | $objectTypeIDs.push($(this).val()); | |
2331 | }); | |
2332 | ||
49ec07c5 MW |
2333 | if (!$objectTypeIDs.length) return; |
2334 | ||
e1fe9453 MW |
2335 | this._proxy.setOption('data', { |
2336 | className: 'wcf\\data\\stat\\daily\\StatDailyAction', | |
2337 | actionName: 'getData', | |
2338 | parameters: { | |
2339 | startDate: $('#startDateDatePicker').val(), | |
2340 | endDate: $('#endDateDatePicker').val(), | |
2341 | value: $('input[name=value]:checked').val(), | |
49ec07c5 | 2342 | dateGrouping: $('input[name=dateGrouping]:checked').val(), |
e1fe9453 MW |
2343 | objectTypeIDs: $objectTypeIDs |
2344 | } | |
2345 | }); | |
2346 | this._proxy.sendRequest(); | |
2347 | }, | |
2348 | ||
2349 | _success: function(data) { | |
49ec07c5 MW |
2350 | switch ($('input[name=dateGrouping]:checked').val()) { |
2351 | case 'yearly': | |
2352 | var $minTickSize = [1, "year"]; | |
2353 | var $timeFormat = WCF.Language.get('wcf.acp.stat.timeFormat.yearly'); | |
2354 | break; | |
2355 | case 'monthly': | |
2356 | var $minTickSize = [1, "month"]; | |
2357 | var $timeFormat = WCF.Language.get('wcf.acp.stat.timeFormat.monthly'); | |
2358 | break; | |
2359 | case 'weekly': | |
2360 | var $minTickSize = [7, "day"]; | |
2361 | var $timeFormat = WCF.Language.get('wcf.acp.stat.timeFormat.weekly'); | |
2362 | break; | |
2363 | default: | |
2364 | var $minTickSize = [1, "day"]; | |
2365 | var $timeFormat = WCF.Language.get('wcf.acp.stat.timeFormat.daily'); | |
2366 | } | |
2367 | ||
e1fe9453 MW |
2368 | var options = { |
2369 | series: { | |
2370 | lines: { | |
2371 | show: true | |
2372 | }, | |
2373 | points: { | |
2374 | show: true | |
2375 | } | |
2376 | }, | |
2377 | grid: { | |
2378 | hoverable: true | |
2379 | }, | |
2380 | xaxis: { | |
2381 | mode: "time", | |
49ec07c5 MW |
2382 | minTickSize: $minTickSize, |
2383 | timeformat: $timeFormat, | |
2384 | monthNames: WCF.Language.get('__monthsShort') | |
e1fe9453 MW |
2385 | }, |
2386 | yaxis: { | |
2387 | min: 0, | |
2388 | tickDecimals: 0, | |
2389 | tickFormatter: function(val) { | |
2390 | return WCF.String.addThousandsSeparator(val); | |
2391 | } | |
a16e5980 | 2392 | } |
e1fe9453 MW |
2393 | }; |
2394 | ||
2395 | var $data = [ ]; | |
2396 | for (var $key in data.returnValues) { | |
2397 | var $row = data.returnValues[$key]; | |
2398 | for (var $i = 0; $i < $row.data.length; $i++) { | |
2399 | $row.data[$i][0] *= 1000; | |
2400 | } | |
2401 | ||
2402 | $data.push($row); | |
2403 | } | |
2404 | ||
2405 | $.plot("#chart", $data, options); | |
2406 | ||
a16e5980 MW |
2407 | require(['Ui/Alignment'], function (UiAlignment) { |
2408 | var span = elCreate('span'); | |
2409 | span.style.setProperty('position', 'absolute', ''); | |
2410 | document.body.appendChild(span); | |
2411 | $("#chart").on("plothover", function(event, pos, item) { | |
2412 | if (item) { | |
2413 | span.style.setProperty('top', item.pageY + 'px', ''); | |
2414 | span.style.setProperty('left', item.pageX + 'px', ''); | |
2415 | $("#chartTooltip").html(item.series.xaxis.tickFormatter(item.datapoint[0], item.series.xaxis) + ', ' + WCF.String.formatNumeric(item.datapoint[1]) + ' ' + item.series.label).show(); | |
2416 | UiAlignment.set($("#chartTooltip")[0], span, { | |
2417 | verticalOffset: 5, | |
2418 | horizontal: 'center' | |
2419 | }); | |
2420 | } | |
2421 | else { | |
2422 | $("#chartTooltip").hide(); | |
2423 | } | |
2424 | }); | |
e1fe9453 | 2425 | }); |
7652dbb0 MW |
2426 | |
2427 | if (!$data.length) { | |
2428 | $('#chart').append('<p style="position: absolute; font-size: 1.2rem; text-align: center; top: 50%; margin-top: -20px; width: 100%">' + WCF.Language.get('wcf.acp.stat.noData') + '</p>'); | |
2429 | } | |
a59f3c51 MW |
2430 | |
2431 | elBySel('.contentHeader > .contentTitle').scrollIntoView({ behavior: 'smooth' }); | |
e1fe9453 | 2432 | } |
e72efaf9 | 2433 | }); |
e866b80e MS |
2434 | |
2435 | /** | |
2436 | * Namespace for ACP ad management. | |
2437 | */ | |
2438 | WCF.ACP.Ad = { }; | |
2439 | ||
2440 | /** | |
2441 | * Handles the location of an ad during ad creation/editing. | |
2442 | */ | |
2443 | WCF.ACP.Ad.LocationHandler = Class.extend({ | |
2444 | /** | |
2445 | * fieldset of the page conditions | |
2446 | * @var jQuery | |
2447 | */ | |
2448 | _pageConditions: null, | |
2449 | ||
2450 | /** | |
2451 | * select element for the page controller condition | |
0360f61b | 2452 | * @var jQuery[] |
e866b80e | 2453 | */ |
0360f61b | 2454 | _pageInputs: [], |
e866b80e MS |
2455 | |
2456 | /** | |
2457 | * Initializes a new WCF.ACP.Ad.LocationHandler object. | |
2458 | */ | |
2459 | init: function() { | |
2460 | this._pageConditions = $('#pageConditions'); | |
0360f61b | 2461 | this._pageInputs = $('input[name="pageIDs[]"]'); |
e866b80e | 2462 | |
0360f61b | 2463 | var dl = $(this._pageInputs[0]).parents('dl:eq(0)'); |
fff8c61a | 2464 | |
e866b80e | 2465 | // hide the page controller element |
0360f61b | 2466 | dl.hide(); |
fff8c61a | 2467 | |
0360f61b MS |
2468 | var section = dl.parent('section'); |
2469 | if (!section.children('dl:visible').length) { | |
2470 | section.hide(); | |
fff8c61a MS |
2471 | } |
2472 | ||
0360f61b MS |
2473 | var nextSection = section.next('section'); |
2474 | if (nextSection) { | |
2475 | var marginTop = nextSection.css('margin-top'); | |
2476 | nextSection.css('margin-top', 0); | |
2477 | ||
2478 | require(['EventHandler'], function(EventHandler) { | |
2479 | EventHandler.add('com.woltlab.wcf.pageConditionDependence', 'checkVisivility', function() { | |
2480 | if (section.is(':visible')) { | |
2481 | nextSection.css('margin-top', marginTop); | |
2482 | } | |
2483 | else { | |
2484 | nextSection.css('margin-top', 0); | |
2485 | } | |
2486 | }); | |
2487 | }); | |
fff8c61a | 2488 | } |
e866b80e MS |
2489 | |
2490 | // fix the margin of a potentially next page condition element | |
0360f61b | 2491 | dl.next('dl').css('margin-top', 0); |
e866b80e MS |
2492 | |
2493 | $('#objectTypeID').on('change', $.proxy(this._setPageController, this)); | |
2494 | ||
2495 | this._setPageController(); | |
2496 | ||
2497 | $('#adForm').submit($.proxy(this._submit, this)); | |
2498 | }, | |
2499 | ||
2500 | /** | |
2501 | * Sets the page controller based on the selected ad location. | |
2502 | */ | |
2503 | _setPageController: function() { | |
0360f61b | 2504 | var option = $('#objectTypeID').find('option:checked'); |
e866b80e | 2505 | |
0360f61b MS |
2506 | require(['Core'], function(Core) { |
2507 | var input, triggerEvent; | |
2508 | ||
e866b80e | 2509 | // select the related page |
0360f61b MS |
2510 | for (var i = 0, length = this._pageInputs.length; i < length; i++) { |
2511 | input = this._pageInputs[i]; | |
2512 | triggerEvent = false; | |
2513 | ||
2514 | if (option.data('page') && elData(input, 'identifier') === option.data('page')) { | |
2515 | if (!input.checked) triggerEvent = true; | |
2516 | ||
2517 | input.checked = true; | |
2518 | } | |
2519 | else { | |
2520 | if (input.checked) triggerEvent = true; | |
2521 | ||
2522 | input.checked = false; | |
2523 | } | |
2524 | ||
2525 | if (triggerEvent) Core.triggerEvent(this._pageInputs[i], 'change'); | |
2526 | } | |
2527 | }.bind(this)); | |
e866b80e MS |
2528 | }, |
2529 | ||
2530 | /** | |
2531 | * Handles submitting the ad form. | |
2532 | */ | |
2533 | _submit: function() { | |
2534 | if (this._pageConditions.is(':hidden')) { | |
2535 | // remove hidden page condition form elements to avoid creation | |
2536 | // of these conditions | |
2537 | this._pageConditions.find('select, input').remove(); | |
2538 | } | |
2539 | else { | |
2540 | // reset page controller conditions to avoid creation of | |
2541 | // unnecessary conditions | |
0360f61b MS |
2542 | for (var i = 0, length = this._pageInputs.length; i < length; i++) { |
2543 | this._pageInputs[i].checked = false; | |
2544 | } | |
e866b80e MS |
2545 | } |
2546 | } | |
2547 | }); | |
ea3185a0 MS |
2548 | |
2549 | /** | |
2550 | * Initialize WCF.ACP.Tag namespace. | |
2551 | */ | |
2552 | WCF.ACP.Tag = { }; | |
2553 | ||
2554 | /** | |
2555 | * Handles setting tags as synonyms of another tag by clipboard. | |
2556 | */ | |
2557 | WCF.ACP.Tag.SetAsSynonymsHandler = Class.extend({ | |
2558 | /** | |
2559 | * dialog to select the "main" tag | |
2560 | * @var jQuery | |
2561 | */ | |
2562 | _dialog: null, | |
2563 | ||
2564 | /** | |
2565 | * ids of the selected tags | |
2566 | * @var array<integer> | |
2567 | */ | |
2568 | _objectIDs: [ ], | |
2569 | ||
2570 | /** | |
2571 | * Initializes the SetAsSynonymsHandler object. | |
ea3185a0 MS |
2572 | */ |
2573 | init: function() { | |
f8d9e485 MS |
2574 | require(['EventHandler'], function(EventHandler) { |
2575 | EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.tag', this._clipboardAction.bind(this)); | |
2576 | }.bind(this)); | |
ea3185a0 MS |
2577 | }, |
2578 | ||
2579 | /** | |
f8d9e485 MS |
2580 | * Reacts to executed clipboard actions. |
2581 | * | |
2582 | * @param {object<string, *>} actionData data of the executed clipboard action | |
ea3185a0 | 2583 | */ |
f8d9e485 MS |
2584 | _clipboardAction: function(actionData) { |
2585 | if (actionData.data.actionName === 'com.woltlab.wcf.tag.setAsSynonyms') { | |
2586 | this._objectIDs = actionData.data.parameters.objectIDs; | |
2587 | if (this._dialog === null) { | |
2588 | this._dialog = $('<div id="setAsSynonymsDialog" />').hide().appendTo(document.body); | |
2589 | this._dialog.wcfDialog({ | |
2590 | closable: false, | |
2591 | title: WCF.Language.get('wcf.acp.tag.setAsSynonyms') | |
2592 | }); | |
2593 | } | |
2594 | ||
2595 | this._dialog.html(actionData.data.parameters.template); | |
2596 | $button = this._dialog.find('button[data-type="submit"]').disable().click($.proxy(this._submit, this)); | |
2597 | this._dialog.find('input[type=radio]').change(function() { $button.enable(); }); | |
ea3185a0 | 2598 | } |
ea3185a0 MS |
2599 | }, |
2600 | ||
2601 | /** | |
2602 | * Saves the tags as synonyms. | |
2603 | */ | |
2604 | _submit: function() { | |
2605 | new WCF.Action.Proxy({ | |
2606 | autoSend: true, | |
2607 | data: { | |
2608 | actionName: 'setAsSynonyms', | |
2609 | className: 'wcf\\data\\tag\\TagAction', | |
2610 | objectIDs: this._objectIDs, | |
2611 | parameters: { | |
2612 | tagID: this._dialog.find('input[name="tagID"]:checked').val() | |
2613 | } | |
2614 | }, | |
2615 | success: $.proxy(function() { | |
2616 | this._dialog.wcfDialog('close'); | |
2617 | ||
2618 | new WCF.System.Notification().show(function() { | |
2619 | window.location.reload(); | |
2620 | }); | |
2621 | }, this) | |
2622 | }); | |
2623 | } | |
2624 | }); |