From 44fbc027f3ffa7da58ebaa43ddc78384a2e0883d Mon Sep 17 00:00:00 2001 From: Robbie Averill Date: Wed, 29 Nov 2017 12:14:39 +1300 Subject: [PATCH] NEW Add loading animation to Create Report button, fix bug in CurlLinkChecker --- .editorconfig | 5 +- composer.json | 5 +- css/BrokenExternalLinksReport.css | 4 + javascript/BrokenExternalLinksReport.js | 200 ++++++++++++------ .../CMSExternalLinksController.php | 3 +- src/Reports/BrokenExternalLinksReport.php | 27 +-- src/Tasks/CurlLinkChecker.php | 6 +- 7 files changed, 158 insertions(+), 92 deletions(-) create mode 100644 css/BrokenExternalLinksReport.css diff --git a/.editorconfig b/.editorconfig index 47ae637..ffbd989 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,8 +10,5 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -[{*.yml,package.json}] +[*.{yml,js,scss,css,json}] indent_size = 2 - -# The indent size used in the package.json file cannot be changed: -# https://github.com/npm/npm/pull/3180#issuecomment-16336516 diff --git a/composer.json b/composer.json index 4cee129..bdf12a1 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,10 @@ } }, "extra": { - "expose": ["javascript"], + "expose": [ + "css", + "javascript" + ], "branch-alias": { "dev-master": "2.x-dev" } diff --git a/css/BrokenExternalLinksReport.css b/css/BrokenExternalLinksReport.css new file mode 100644 index 0000000..166abe1 --- /dev/null +++ b/css/BrokenExternalLinksReport.css @@ -0,0 +1,4 @@ +.external-links-report__create-report, +.external-links-report__report-progress { + margin-top: 20px; +} diff --git a/javascript/BrokenExternalLinksReport.js b/javascript/BrokenExternalLinksReport.js index c6d84c9..16596ed 100644 --- a/javascript/BrokenExternalLinksReport.js +++ b/javascript/BrokenExternalLinksReport.js @@ -1,69 +1,135 @@ (function($) { - $.entwine('ss', function($) { - $('#externalLinksReport').entwine({ - PollTimeout: null, - onclick: function() { - this.start(); - }, - onmatch: function() { - // poll the current job and update the front end status - $('#externalLinksReport').hide(); - this.poll(); - }, - start: function() { - // initiate a new job - $('#ReportHolder').empty(); - $('#ReportHolder').text('Running report 0%'); - $('#ReportHolder').append(''); - $('#externalLinksReport').hide(); - $.ajax({url: "admin/externallinks/start", async: false, timeout: 3000 }); - this.poll(); - }, - poll: function() { - var self = this; - - $.ajax({ - url: "admin/externallinks/getJobStatus", - async: true, - success: function(data) { - // No report, so let user create one - if (!data) { - $('#externalLinksReport').show(); - return; - } - - // Parse data - var completed = data.Completed ? data.Completed : 0; - var total = data.Total ? data.Total : 0; - - // If complete status - if (data.Status === 'Completed') { - $('#ReportHolder').text('Report Finished ' + completed + '/' + total); - $('#externalLinksReport').show(); - return; - } - - // If incomplete update status - if (completed < total) { - var percent = (completed / total) * 100; - $('#ReportHolder') - .text('Running report ' + completed + '/' + total + ' (' + percent.toFixed(2) + '%)') - .append(''); - } - - // Ensure the regular poll method is run - // kill any existing timeout - if(self.getPollTimeout() !== null) { - clearTimeout(self.getPollTimeout()); - } - - self.setPollTimeout(setTimeout(function() { $('#externalLinksReport').poll(); }, 1000)); - }, - error: function(e) { - if(typeof console !== 'undefined') console.log(e); - } - }); - } - }); - }); + $.entwine('ss', function($) { + $('.external-links-report__create-report').entwine({ + PollTimeout: null, + ButtonIsLoading: false, + + onclick: function(e) { + e.preventDefault(); + + this.buttonLoading(); + this.start(); + }, + + onmatch: function() { + // poll the current job and update the front end status + this.poll(); + }, + + start: function() { + // initiate a new job + $('.external-links-report__report-progress') + .empty() + .text('Running report 0%'); + + $.ajax({ + url: "admin/externallinks/start", + async: true, + timeout: 3000 + }); + + this.poll(); + }, + + /** + * Get the "create report" button selector + * + * @return {Object} + */ + getButton: function() { + return $('.external-links-report__create-report'); + }, + + /** + * Sets the button into a loading state. See LeftAndMain.js. + */ + buttonLoading: function() { + if (this.getButtonIsLoading()) { + return; + } + this.setButtonIsLoading(true); + + var $button = this.getButton(); + + // set button to "submitting" state + $button.addClass('btn--loading loading'); + + if ($button.is('button')) { + $button.append($( + '
'+ + ''+ + ''+ + ''+ + '
')); + + $button.css($button.outerWidth() + 'px'); + } + }, + + /** + * Reset the button back to its original state after loading. See LeftAndMain.js. + */ + buttonReset: function() { + this.setButtonIsLoading(false); + + var $button = this.getButton(); + + $button.removeClass('btn--loading loading'); + $button.find('.btn__loading-icon').remove(); + $button.css('width', 'auto'); + }, + + poll: function() { + var self = this; + this.buttonLoading(); + + $.ajax({ + url: "admin/externallinks/getJobStatus", + async: true, + success: function(data) { + // No report, so let user create one + if (!data) { + this.buttonReset(); + return; + } + + // Parse data + var completed = data.Completed ? data.Completed : 0; + var total = data.Total ? data.Total : 0; + + // If complete status + if (data.Status === 'Completed') { + $('.external-links-report__report-progress') + .text('Report finished ' + completed + '/' + total); + + self.buttonReset(); + return; + } + + // If incomplete update status + if (completed < total) { + var percent = (completed / total) * 100; + $('.external-links-report__report-progress') + .text('Running report ' + completed + '/' + total + ' (' + percent.toFixed(2) + '%)'); + } + + // Ensure the regular poll method is run + // kill any existing timeout + if (self.getPollTimeout() !== null) { + clearTimeout(self.getPollTimeout()); + } + + self.setPollTimeout(setTimeout(function() { + $('.external-links-report__create-report').poll(); + }, 1000)); + }, + error: function(e) { + if (typeof console !== 'undefined') { + console.log(e); + } + } + }); + } + }); + }); }(jQuery)); diff --git a/src/Controllers/CMSExternalLinksController.php b/src/Controllers/CMSExternalLinksController.php index 7f35df1..9a3a64c 100644 --- a/src/Controllers/CMSExternalLinksController.php +++ b/src/Controllers/CMSExternalLinksController.php @@ -3,6 +3,7 @@ namespace SilverStripe\ExternalLinks\Controllers; use SilverStripe\Control\HTTP; +use SilverStripe\Core\Convert; use SilverStripe\ExternalLinks\Model\BrokenExternalPageTrackStatus; use SilverStripe\ExternalLinks\Jobs\CheckExternalLinksJob; use SilverStripe\ExternalLinks\Tasks\CheckExternalLinksTask; @@ -35,7 +36,7 @@ public function getJobStatus() // Format status $track = BrokenExternalPageTrackStatus::get_latest(); if ($track) { - return json_encode([ + return Convert::array2json([ 'TrackID' => $track->ID, 'Status' => $track->Status, 'Completed' => $track->getCompletedPages(), diff --git a/src/Reports/BrokenExternalLinksReport.php b/src/Reports/BrokenExternalLinksReport.php index fec065a..540c4fa 100644 --- a/src/Reports/BrokenExternalLinksReport.php +++ b/src/Reports/BrokenExternalLinksReport.php @@ -2,11 +2,11 @@ namespace SilverStripe\ExternalLinks\Reports; -use SilverStripe\ORM\ArrayList; -use SilverStripe\ExternalLinks\Model\BrokenExternalPageTrackStatus; use SilverStripe\Core\Convert; -use SilverStripe\View\HTML; +use SilverStripe\ExternalLinks\Model\BrokenExternalPageTrackStatus; use SilverStripe\Forms\LiteralField; +use SilverStripe\Forms\FormAction; +use SilverStripe\ORM\ArrayList; use SilverStripe\Reports\Report; use SilverStripe\View\Requirements; @@ -78,25 +78,20 @@ public function sourceRecords() public function getCMSFields() { + Requirements::css('silverstripe/externallinks: css/BrokenExternalLinksReport.css'); Requirements::javascript('silverstripe/externallinks: javascript/BrokenExternalLinksReport.js'); + $fields = parent::getCMSFields(); - $reportResultSpan = '

'; + $runReportButton = FormAction::create('createReport', _t(__CLASS__ . '.RUNREPORT', 'Create new report')) + ->addExtraClass('btn-primary external-links-report__create-report') + ->setUseButtonTag(true); + $fields->push($runReportButton); + + $reportResultSpan = ''; $reportResult = LiteralField::create('ResultTitle', $reportResultSpan); $fields->push($reportResult); - $button = HTML::createTag( - 'button', - [ - 'id' => 'externalLinksReport', - 'type' => 'button', - 'class' => 'btn btn-primary' - ], - _t(__CLASS__ . '.RUNREPORT', 'Create new report') - ); - $runReportButton = LiteralField::create('runReport', $button); - $fields->push($runReportButton); - return $fields; } } diff --git a/src/Tasks/CurlLinkChecker.php b/src/Tasks/CurlLinkChecker.php index 0a11f3d..a09eb1e 100644 --- a/src/Tasks/CurlLinkChecker.php +++ b/src/Tasks/CurlLinkChecker.php @@ -14,7 +14,7 @@ class CurlLinkChecker implements LinkChecker /** * Return cache * - * @return Zend_Cache_Frontend + * @return CacheInterface */ protected function getCache() { @@ -36,7 +36,7 @@ public function checkLink($href) // Check if we have a cached result $cacheKey = md5($href); - $result = $this->getCache()->get($cacheKey); + $result = $this->getCache()->get($cacheKey, false); if ($result !== false) { return $result; } @@ -51,7 +51,7 @@ public function checkLink($href) curl_close($handle); // Cache result - $this->getCache()->set($httpCode, $cacheKey); + $this->getCache()->set($cacheKey, $httpCode); return $httpCode; } }