From b6a4cbd99df6d202f11dc71169251b9a45ab5c65 Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Thu, 13 Dec 2018 15:11:37 +1300 Subject: [PATCH] Add ability to have a failed state and links --- README.md | 22 +++++++ client/dist/js/queuedjobprogressfield.js | 2 +- client/dist/js/queuedjobprogressfield.js.map | 2 +- client/src/bundles/queuedjobprogressfield.js | 4 +- src/QueuedJobProgressController.php | 17 ++++- .../QueuedJobProgressController.ss | 66 ++++++++++++++++--- 6 files changed, 99 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index cb1d9b3..1537d5c 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,28 @@ to see the live progress of the job. ![demo-web](demo-web.png) +## User Experience Tips + +### Overriding Redirection Location + +Redirecting users to `site.com/upload/progress//` displays +a running status of the job. If the job successes, a *Continue* button for users +is activated. By default the continue button will redirect the user back, this +behaviour can be overriden by using a `ContinueLink` query param on the original +link. + +``` +site.com/upload/progress//?ContinueLink=/thanks/ +``` + +Likewise, you can set a different link for the button if the job fails, stalls +or some other error occurs. + +``` +site.com/upload/progress//?FailureLink=/error/ +``` + + ## Long Running Single Progress Jobs Due to the design of queued jobs, the progress indicator (currentStep) is only diff --git a/client/dist/js/queuedjobprogressfield.js b/client/dist/js/queuedjobprogressfield.js index 0313b46..28b5f48 100644 --- a/client/dist/js/queuedjobprogressfield.js +++ b/client/dist/js/queuedjobprogressfield.js @@ -132,7 +132,7 @@ window.jQuery.entwine('ss', function ($) { } else { progress.removeClass('progress-bar-animated'); - $('body').trigger('queuedjob-finished'); + $('body').trigger('queuedjob-finished', [status]); } $(self).parents('.field').find('.messages').html(resp.Messages); diff --git a/client/dist/js/queuedjobprogressfield.js.map b/client/dist/js/queuedjobprogressfield.js.map index ec6beb9..358fbe3 100644 --- a/client/dist/js/queuedjobprogressfield.js.map +++ b/client/dist/js/queuedjobprogressfield.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap d38910632d1b92142e5e","webpack:///./client/src/bundles/queuedjobprogressfield.js"],"names":["window","jQuery","entwine","$","onmatch","find","popover","container","parents","get","placement","on","removeClass","addClass","link","data","self","setTimeout","fetchData","getInterval","_super","onunmatch","interval","progress","getJSON","resp","Percentage","changed","text","Title","Content","css","hasClass","Status","Animated","trigger","html","Messages","attr"],"mappings":"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","file":"js/queuedjobprogressfield.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap d38910632d1b92142e5e","// import 'bootstrap';\nwindow.jQuery.entwine('ss', ($) => {\n $('.queuedjob__progress').entwine({\n onmatch() {\n $(this).find('.progress-bar')\n .popover({\n container: $(this).parents('.field').get(0),\n placement: 'top'\n })\n .popover(\"show\")\n .on('hide.bs.popover', function () {\n return false;\n });\n\n $(this).find('.bs-popover-bottom').removeClass('bs-popover-bottom').addClass('bs-popover-top')\n\n var link = $(this).data('live'),\n self = $(this);\n\n if (link) {\n setTimeout(function() {\n self.fetchData()\n }, self.getInterval())\n }\n\n this._super();\n },\n onunmatch() {\n this._super()\n\n $(this).find('.progress-bar').popover('dispose')\n },\n getInterval () {\n var interval = $(this).data('interval');\n\n if (!interval || interval < 5000) {\n interval = 5000\n }\n\n return interval\n },\n fetchData () {\n var self = this\n var progress = $(this).find('.progress-bar'),\n popover = progress.data('bs.popover'),\n link = $(this).data('live');\n\n $.getJSON(link, function(resp) {\n if (resp && resp.Percentage) {\n var changed = (\n $(self).parents('.field').find('.popover-header').text() !== resp.Title ||\n $(self).parents('.field').find('.popover-body').text() !== resp.Content\n )\n\n progress.css('width', resp.Percentage +'%')\n\n if (!progress.hasClass(resp.Status)) {\n progress.removeClass('bg-info bg-success bg-danger bg-warning')\n progress.addClass(resp.Status)\n\n changed = true\n }\n\n if (resp.Animated) {\n progress.addClass('progress-bar-animated')\n } else {\n progress.removeClass('progress-bar-animated')\n\n // fire a global window event for listeners\n $('body').trigger('queuedjob-finished')\n }\n\n $(self).parents('.field').find('.messages').html(resp.Messages);\n\n if (changed) {\n progress.popover('hide').popover('dispose')\n\n $(self).parents('.field').find('.popover-header').text(resp.Title)\n $(self).parents('.field').find('.popover-body').text(resp.Content)\n $(self).find('.progress-bar')\n .attr('title', resp.Title)\n .data('title', resp.Title)\n .data('content', resp.Content)\n .attr('data-content', resp.Content)\n\n progress.popover('show')\n } else {\n progress.popover('show');\n }\n\n if (resp.Status !== 'bg-success') {\n setTimeout(function() {\n self.fetchData()\n }, self.getInterval())\n }\n }\n })\n }\n });\n});\n\n\n\n// WEBPACK FOOTER //\n// ./client/src/bundles/queuedjobprogressfield.js"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap a5d6a41a8bde8c65bff5","webpack:///./client/src/bundles/queuedjobprogressfield.js"],"names":["window","jQuery","entwine","$","onmatch","find","popover","container","parents","get","placement","on","removeClass","addClass","link","data","self","setTimeout","fetchData","getInterval","_super","onunmatch","interval","progress","getJSON","resp","Percentage","changed","text","Title","Content","css","hasClass","Status","Animated","trigger","status","html","Messages","attr"],"mappings":"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","file":"js/queuedjobprogressfield.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap a5d6a41a8bde8c65bff5","// import 'bootstrap';\nwindow.jQuery.entwine('ss', ($) => {\n $('.queuedjob__progress').entwine({\n onmatch() {\n $(this).find('.progress-bar')\n .popover({\n container: $(this).parents('.field').get(0),\n placement: 'top'\n })\n .popover(\"show\")\n .on('hide.bs.popover', function () {\n return false;\n });\n\n $(this).find('.bs-popover-bottom').removeClass('bs-popover-bottom').addClass('bs-popover-top')\n\n var link = $(this).data('live'),\n self = $(this);\n\n if (link) {\n setTimeout(function() {\n self.fetchData()\n }, self.getInterval())\n }\n\n this._super();\n },\n onunmatch() {\n this._super()\n\n $(this).find('.progress-bar').popover('dispose')\n },\n getInterval () {\n var interval = $(this).data('interval');\n\n if (!interval || interval < 5000) {\n interval = 5000\n }\n\n return interval\n },\n fetchData () {\n var self = this\n var progress = $(this).find('.progress-bar'),\n popover = progress.data('bs.popover'),\n link = $(this).data('live');\n\n $.getJSON(link, function(resp) {\n if (resp && resp.Percentage) {\n var changed = (\n $(self).parents('.field').find('.popover-header').text() !== resp.Title ||\n $(self).parents('.field').find('.popover-body').text() !== resp.Content\n )\n\n progress.css('width', resp.Percentage +'%')\n\n if (!progress.hasClass(resp.Status)) {\n progress.removeClass('bg-info bg-success bg-danger bg-warning')\n progress.addClass(resp.Status)\n\n changed = true\n }\n\n if (resp.Animated) {\n progress.addClass('progress-bar-animated')\n } else {\n progress.removeClass('progress-bar-animated')\n\n // fire a global window event for listeners\n $('body').trigger('queuedjob-finished', [\n status: resp.Status\n ]);\n }\n\n $(self).parents('.field').find('.messages').html(resp.Messages);\n\n if (changed) {\n progress.popover('hide').popover('dispose')\n\n $(self).parents('.field').find('.popover-header').text(resp.Title)\n $(self).parents('.field').find('.popover-body').text(resp.Content)\n $(self).find('.progress-bar')\n .attr('title', resp.Title)\n .data('title', resp.Title)\n .data('content', resp.Content)\n .attr('data-content', resp.Content)\n\n progress.popover('show')\n } else {\n progress.popover('show');\n }\n\n if (resp.Status !== 'bg-success') {\n setTimeout(function() {\n self.fetchData()\n }, self.getInterval())\n }\n }\n })\n }\n });\n});\n\n\n\n// WEBPACK FOOTER //\n// ./client/src/bundles/queuedjobprogressfield.js"],"sourceRoot":""} \ No newline at end of file diff --git a/client/src/bundles/queuedjobprogressfield.js b/client/src/bundles/queuedjobprogressfield.js index 7b76080..34138ad 100644 --- a/client/src/bundles/queuedjobprogressfield.js +++ b/client/src/bundles/queuedjobprogressfield.js @@ -67,7 +67,9 @@ window.jQuery.entwine('ss', ($) => { progress.removeClass('progress-bar-animated') // fire a global window event for listeners - $('body').trigger('queuedjob-finished') + $('body').trigger('queuedjob-finished', [ + status: resp.Status + ]); } $(self).parents('.field').find('.messages').html(resp.Messages); diff --git a/src/QueuedJobProgressController.php b/src/QueuedJobProgressController.php index 459c243..9173f36 100644 --- a/src/QueuedJobProgressController.php +++ b/src/QueuedJobProgressController.php @@ -15,7 +15,8 @@ class QueuedJobProgressController extends Controller ]; private static $casting = [ - 'ContinueLink' => 'Text' + 'ContinueLink' => 'HTMLText', + 'FailureLink' => 'HTMLText' ]; private static $url_segment = 'upload'; @@ -33,6 +34,9 @@ public function progress() ]; } + /** + * @return \SilverStripe\Forms\Form + */ public function ProgressForm() { $job = $this->getJob(); @@ -46,11 +50,22 @@ public function ProgressForm() return $form; } + /** + * @return string + */ public function ContinueLink() { return $this->request->getVar('ContinueLink'); } + /** + * @return string + */ + public function FailureLink() + { + return $this->request->getVar('FailureLink'); + } + /** * @return QueuedJobDescriptor */ diff --git a/templates/FullscreenInteractive/QueuedJobProgressField/QueuedJobProgressController.ss b/templates/FullscreenInteractive/QueuedJobProgressField/QueuedJobProgressController.ss index 440ceb6..d0b5eae 100644 --- a/templates/FullscreenInteractive/QueuedJobProgressField/QueuedJobProgressController.ss +++ b/templates/FullscreenInteractive/QueuedJobProgressField/QueuedJobProgressController.ss @@ -83,6 +83,10 @@ background: #5c940d; } + .continue a.failed { + background: #dc3545; + } + .continue { margin: 70px 0 70px 70px; } @@ -107,24 +111,66 @@ padding: 0 0 0 70px; border: none; } + + @media all and (max-width: 480px) { + .progress--loader { + padding-top: 100px; + padding-left: 0; + } + + .progress--meta { + padding-left: 0; + } + + fieldset { + padding: 0; + } + + .continue { + margin-left: 0; + } + }