| 1 | <!-- FIXME: CSS conventions and polish --> |
| 2 | <div class="crm-block crm-form-block crm-queue-runner-form-block"> |
| 3 | <div id="crm-queue-runner-progress"></div> |
| 4 | <div id="crm-queue-runner-desc"> |
| 5 | <div id="crm-queue-runner-buttonset" style="right:20px;position:absolute;"> |
| 6 | <button id="crm-queue-runner-retry">Retry</button> |
| 7 | <button id="crm-queue-runner-skip">Skip</button> |
| 8 | </div> |
| 9 | <div>[<span id="crm-queue-runner-title"></span>]</div> |
| 10 | </div> |
| 11 | <div id="crm-queue-runner-message"></div> |
| 12 | </div> |
| 13 | |
| 14 | {literal} |
| 15 | <script type="text/javascript"> |
| 16 | |
| 17 | CRM.$(function($) { |
| 18 | // Note: Queue API provides "#remaining tasks" but not "#completed tasks" or "#total tasks". |
| 19 | // To compute a %complete, we manually track #completed. This only works nicely if we |
| 20 | // assume that the queue began with a fixed #tasks. |
| 21 | |
| 22 | var queueRunnerData = {/literal}{$queueRunnerData|@json}{literal}; |
| 23 | |
| 24 | var displayResponseData = function(data, textStatus, jqXHR) { |
| 25 | if (data.redirect_url) { |
| 26 | window.location.href = data.redirect_url; |
| 27 | return; |
| 28 | } |
| 29 | |
| 30 | var pct = 100 * queueRunnerData.completed / (queueRunnerData.completed + queueRunnerData.numberOfItems); |
| 31 | $("#crm-queue-runner-progress").progressbar({ value: pct }); |
| 32 | |
| 33 | if (data.is_error) { |
| 34 | $("#crm-queue-runner-buttonset").show(); |
| 35 | if (queueRunnerData.isEnded) { |
| 36 | $('#crm-queue-runner-skip').button('disable'); |
| 37 | } |
| 38 | $('#crm-queue-runner-title').text('Error: ' + data.last_task_title); |
| 39 | } else if (!data.is_continue && queueRunnerData.numberOfItems == 0) { |
| 40 | $('#crm-queue-runner-title').text('Done'); |
| 41 | } else { |
| 42 | $('#crm-queue-runner-title').text('Executed: ' + data.last_task_title); |
| 43 | } |
| 44 | |
| 45 | if (data.exception) { |
| 46 | $('#crm-queue-runner-message').html(''); |
| 47 | $('<div></div>').html(data.exception).prependTo('#crm-queue-runner-message'); |
| 48 | } |
| 49 | |
| 50 | }; |
| 51 | |
| 52 | var handleError = function(jqXHR, textStatus, errorThrown) { |
| 53 | // Do this regardless of whether the response was well-formed |
| 54 | $("#crm-queue-runner-buttonset").show(); |
| 55 | |
| 56 | var data = $.parseJSON(jqXHR.responseText) |
| 57 | if (data) { |
| 58 | displayResponseData(data); |
| 59 | } |
| 60 | }; |
| 61 | |
| 62 | var handleSuccess = function(data, textStatus, jqXHR) { |
| 63 | if (!data.is_error) { |
| 64 | queueRunnerData.completed++; |
| 65 | } |
| 66 | if (data.numberOfItems) { |
| 67 | queueRunnerData.numberOfItems = parseInt(data.numberOfItems); |
| 68 | } |
| 69 | |
| 70 | displayResponseData(data); |
| 71 | |
| 72 | // FIXME re-consider merits of is_continue in the corner-case of executing last step |
| 73 | if (data.is_continue) { |
| 74 | window.setTimeout(runNext, 50); |
| 75 | } else if (!data.is_continue && queueRunnerData.numberOfItems == 0 && !queueRunnerData.isEnded) { |
| 76 | queueRunnerData.isEnded = true; |
| 77 | window.setTimeout(runNext, 50); |
| 78 | } |
| 79 | }; |
| 80 | |
| 81 | // Dequeue and execute the next item |
| 82 | var runNext = function() { |
| 83 | $.ajax({ |
| 84 | type: 'POST', |
| 85 | url: (queueRunnerData.isEnded ? queueRunnerData.onEndAjax : queueRunnerData.runNextAjax), |
| 86 | data: { |
| 87 | qrid: queueRunnerData.qrid |
| 88 | }, |
| 89 | dataType: 'json', |
| 90 | beforeSend: function(jqXHR, settings) { |
| 91 | $("#crm-queue-runner-buttonset").hide(); |
| 92 | }, |
| 93 | error: handleError, |
| 94 | success: handleSuccess |
| 95 | }); |
| 96 | } |
| 97 | |
| 98 | var retryNext = function() { |
| 99 | $('#crm-queue-runner-message').html(''); |
| 100 | runNext(); |
| 101 | } |
| 102 | |
| 103 | // Dequeue and the next item, then move on to runNext for the subsequent items |
| 104 | var skipNext = function() { |
| 105 | $.ajax({ |
| 106 | type: 'POST', |
| 107 | url: queueRunnerData.skipNextAjax, |
| 108 | data: { |
| 109 | qrid: queueRunnerData.qrid |
| 110 | }, |
| 111 | dataType: 'json', |
| 112 | beforeSend: function(jqXHR, settings) { |
| 113 | $('#crm-queue-runner-message').html(''); |
| 114 | $("#crm-queue-runner-buttonset").hide(); |
| 115 | }, |
| 116 | error: handleError, |
| 117 | success: handleSuccess |
| 118 | }); |
| 119 | } |
| 120 | |
| 121 | // Set up the UI |
| 122 | |
| 123 | $("#crm-queue-runner-progress").progressbar({ value: 0 }); |
| 124 | if (queueRunnerData.buttons.retry == 1) { |
| 125 | $("#crm-queue-runner-retry").button({ |
| 126 | text: false, |
| 127 | icons: {primary: 'ui-icon-refresh'} |
| 128 | }).click(retryNext); |
| 129 | } else { |
| 130 | $("#crm-queue-runner-retry").remove(); |
| 131 | } |
| 132 | if (queueRunnerData.buttons.skip == 1) { |
| 133 | $("#crm-queue-runner-skip").button({ |
| 134 | text: false, |
| 135 | icons: {primary: 'ui-icon-seek-next'} |
| 136 | }).click(skipNext); |
| 137 | } else { |
| 138 | $("#crm-queue-runner-skip").remove(); |
| 139 | } |
| 140 | $("#crm-queue-runner-buttonset").buttonset(); |
| 141 | $("#crm-queue-runner-buttonset").hide(); |
| 142 | window.setTimeout(runNext, 50); |
| 143 | }); |
| 144 | |
| 145 | </script> |
| 146 | {/literal} |