From 60dab35f1e2826021c75df45fb2c5dfcd88cac19 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 3 Dec 2014 20:26:32 +0000 Subject: [PATCH 1/2] Fixing fatal error on dashboard, also adding slim view for installs with more than 10 projects --- PHPCI/Store/BuildStore.php | 5 +- PHPCI/View/SummaryTable.phtml | 70 +++++++++++++++------- PHPCI/View/layout.phtml | 2 +- composer.lock | 106 ++++++++++++++++++---------------- 4 files changed, 109 insertions(+), 74 deletions(-) diff --git a/PHPCI/Store/BuildStore.php b/PHPCI/Store/BuildStore.php index b28142a7..a355ac68 100644 --- a/PHPCI/Store/BuildStore.php +++ b/PHPCI/Store/BuildStore.php @@ -61,8 +61,9 @@ class BuildStore extends BuildStoreBase $stmt->bindValue(':status', $status); if ($stmt->execute()) { - $res = $stmt->fetch(\PDO::FETCH_ASSOC); - return new Build($res); + if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { + return new Build($data); + } } else { return array(); } diff --git a/PHPCI/View/SummaryTable.phtml b/PHPCI/View/SummaryTable.phtml index d0f249d9..438f78b6 100644 --- a/PHPCI/View/SummaryTable.phtml +++ b/PHPCI/View/SummaryTable.phtml @@ -75,8 +75,54 @@ foreach($projects as $project): $subcls = 'yellow'; } + + $buildCount = count($builds[$project->getId()]); + $lastSuccess = $successful[$project->getId()]; + $lastFailure = $failed[$project->getId()]; + $message = 'No builds yet!'; + $shortMessage = 'No builds yet!'; + + if ($buildCount > 0) { + if ($failures > 0) { + $shortMessage = $failures . ' / ' . $buildCount . ' failed.'; + $message = $failures . ' out of the last ' . $buildCount . ' builds failed.'; + + if (!is_null($lastSuccess) && !is_null($lastSuccess->getFinished())) { + $message .= ' The last successful build was ' . $lastSuccess->getFinished()->format('M j Y') . '.'; + } else { + $message .= ' This project has never built successfully.'; + } + } else { + $shortMessage = $buildCount . ' / ' . $buildCount . ' passed.'; + $message = 'All of the last ' . $buildCount . ' builds passed.'; + + if (!is_null($lastFailure) && !is_null($lastFailure->getFinished())) { + $message .= ' The last failed build was ' . $lastFailure->getFinished()->format('M j Y') . '.'; + } else { + $message .= ' This project has never failed to build.'; + } + } + } + ?> + 10): ?> + +
+
+

+ + + getTitle(); ?> + + - + +

+
+
+ + +

@@ -84,28 +130,11 @@ foreach($projects as $project): getTitle(); ?>

+

- 0): ?> - out of the last - getId()]); ?> builds have failed. - - getId()])): ?> - The last successful build was - getId()]->getFinished()->format('M j Y'); ?> - - This project has never built successfully. - - - All of the last getId()]); ?> builds passed. - - getId()])): ?> - The last failed build was - getId()]->getFinished()->format('M j Y'); ?> - - This project has never failed to build. - - +

+
@@ -115,4 +144,5 @@ foreach($projects as $project):
+ diff --git a/PHPCI/View/layout.phtml b/PHPCI/View/layout.phtml index dac44274..b6111646 100644 --- a/PHPCI/View/layout.phtml +++ b/PHPCI/View/layout.phtml @@ -67,7 +67,7 @@ margin-bottom: 20px; } - .small-box h3 a { + .small-box h3 a, .small-box h4 a { color: #fff; } diff --git a/composer.lock b/composer.lock index 8e769534..b56848df 100644 --- a/composer.lock +++ b/composer.lock @@ -1,8 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], "hash": "650fe5576922dea4ac3b1be72d882a58", "packages": [ @@ -364,17 +363,17 @@ }, { "name": "symfony/class-loader", - "version": "v2.6.0", + "version": "v2.6.1", "target-dir": "Symfony/Component/ClassLoader", "source": { "type": "git", "url": "https://github.com/symfony/ClassLoader.git", - "reference": "b403af3d4fa3a2c3c926121c05042107e3a5b916" + "reference": "ba3300e6d79eb51ca9edf77791bbd0497f6030dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ClassLoader/zipball/b403af3d4fa3a2c3c926121c05042107e3a5b916", - "reference": "b403af3d4fa3a2c3c926121c05042107e3a5b916", + "url": "https://api.github.com/repos/symfony/ClassLoader/zipball/ba3300e6d79eb51ca9edf77791bbd0497f6030dc", + "reference": "ba3300e6d79eb51ca9edf77791bbd0497f6030dc", "shasum": "" }, "require": { @@ -410,21 +409,21 @@ ], "description": "Symfony ClassLoader Component", "homepage": "http://symfony.com", - "time": "2014-11-20 13:24:23" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/config", - "version": "v2.5.7", + "version": "v2.5.8", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "7b11dceebaaf877b75bc1aedfd831a2ddc326de9" + "reference": "92f0b4c625b8c42d394b53f879d2795d84bb8c4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/7b11dceebaaf877b75bc1aedfd831a2ddc326de9", - "reference": "7b11dceebaaf877b75bc1aedfd831a2ddc326de9", + "url": "https://api.github.com/repos/symfony/Config/zipball/92f0b4c625b8c42d394b53f879d2795d84bb8c4f", + "reference": "92f0b4c625b8c42d394b53f879d2795d84bb8c4f", "shasum": "" }, "require": { @@ -458,21 +457,21 @@ ], "description": "Symfony Config Component", "homepage": "http://symfony.com", - "time": "2014-11-20 13:22:25" + "time": "2014-12-02 20:15:53" }, { "name": "symfony/console", - "version": "v2.6.0", + "version": "v2.6.1", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "d3bac228fd7a2aac9193e241b239880b3ba39a10" + "reference": "ef825fd9f809d275926547c9e57cbf14968793e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/d3bac228fd7a2aac9193e241b239880b3ba39a10", - "reference": "d3bac228fd7a2aac9193e241b239880b3ba39a10", + "url": "https://api.github.com/repos/symfony/Console/zipball/ef825fd9f809d275926547c9e57cbf14968793e8", + "reference": "ef825fd9f809d275926547c9e57cbf14968793e8", "shasum": "" }, "require": { @@ -515,21 +514,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-11-20 13:24:23" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/filesystem", - "version": "v2.5.7", + "version": "v2.5.8", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "3c3e382bd869b3ec10008a3d9ef455b1cc2868db" + "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/3c3e382bd869b3ec10008a3d9ef455b1cc2868db", - "reference": "3c3e382bd869b3ec10008a3d9ef455b1cc2868db", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", + "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", "shasum": "" }, "require": { @@ -562,21 +561,21 @@ ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2014-11-16 17:28:00" + "time": "2014-12-02 20:15:53" }, { "name": "symfony/yaml", - "version": "v2.6.0", + "version": "v2.6.1", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "51c845cf3e4bfc182d1d5c05ed1c7338361d86f8" + "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/51c845cf3e4bfc182d1d5c05ed1c7338361d86f8", - "reference": "51c845cf3e4bfc182d1d5c05ed1c7338361d86f8", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/3346fc090a3eb6b53d408db2903b241af51dcb20", + "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20", "shasum": "" }, "require": { @@ -609,7 +608,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2014-11-20 13:24:23" + "time": "2014-12-02 20:19:20" } ], "packages-dev": [ @@ -1006,16 +1005,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "2.0.11", + "version": "2.0.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "53603b3c995f5aab6b59c8e08c3a663d2cc810b7" + "reference": "0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/53603b3c995f5aab6b59c8e08c3a663d2cc810b7", - "reference": "53603b3c995f5aab6b59c8e08c3a663d2cc810b7", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5", + "reference": "0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5", "shasum": "" }, "require": { @@ -1067,7 +1066,7 @@ "testing", "xunit" ], - "time": "2014-08-31 06:33:04" + "time": "2014-12-03 06:41:44" }, { "name": "phpunit/php-file-iterator", @@ -1498,16 +1497,16 @@ }, { "name": "sebastian/environment", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "0d9bf79554d2a999da194a60416c15cf461eb67d" + "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/0d9bf79554d2a999da194a60416c15cf461eb67d", - "reference": "0d9bf79554d2a999da194a60416c15cf461eb67d", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e6c71d918088c251b181ba8b3088af4ac336dd7", + "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7", "shasum": "" }, "require": { @@ -1544,7 +1543,7 @@ "environment", "hhvm" ], - "time": "2014-10-22 06:38:05" + "time": "2014-10-25 08:00:45" }, { "name": "sebastian/exporter", @@ -1808,17 +1807,17 @@ }, { "name": "symfony/dependency-injection", - "version": "v2.5.7", + "version": "v2.5.8", "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "662d8f5e4a7542dca4194fb3f3bda0a57e65f0a4" + "reference": "b4afda3c24867a17f93237ac1fcce917cc9d7695" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/662d8f5e4a7542dca4194fb3f3bda0a57e65f0a4", - "reference": "662d8f5e4a7542dca4194fb3f3bda0a57e65f0a4", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/b4afda3c24867a17f93237ac1fcce917cc9d7695", + "reference": "b4afda3c24867a17f93237ac1fcce917cc9d7695", "shasum": "" }, "require": { @@ -1861,21 +1860,21 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "http://symfony.com", - "time": "2014-11-16 17:28:00" + "time": "2014-12-02 21:48:32" }, { "name": "symfony/finder", - "version": "v2.6.0", + "version": "v2.6.1", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "d574347c652a14cfee0349f744c7880e1d9029fd" + "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/d574347c652a14cfee0349f744c7880e1d9029fd", - "reference": "d574347c652a14cfee0349f744c7880e1d9029fd", + "url": "https://api.github.com/repos/symfony/Finder/zipball/0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", + "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", "shasum": "" }, "require": { @@ -1908,7 +1907,7 @@ ], "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2014-11-28 10:00:40" + "time": "2014-12-02 20:19:20" }, { "name": "theseer/fdomdocument", @@ -1951,15 +1950,20 @@ "time": "2014-09-13 10:57:19" } ], - "aliases": [], + "aliases": [ + + ], "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, + "stability-flags": [ + + ], "platform": { "php": ">=5.3.8", "ext-mcrypt": "*", "ext-pdo": "*", "ext-pdo_mysql": "*" }, - "platform-dev": [] + "platform-dev": [ + + ] } From a2d136e0f1ffd39c06132ff173541a96fd7e6590 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 3 Dec 2014 20:53:46 +0000 Subject: [PATCH 2/2] Fixes for date JS issues in Safari --- public/assets/js/build-plugins/time.js | 45 ++++--- public/assets/js/phpci.js | 156 +++++++++---------------- 2 files changed, 86 insertions(+), 115 deletions(-) diff --git a/public/assets/js/build-plugins/time.js b/public/assets/js/build-plugins/time.js index b5736a36..a3ecdecc 100644 --- a/public/assets/js/build-plugins/time.js +++ b/public/assets/js/build-plugins/time.js @@ -9,7 +9,21 @@ var timePlugin = ActiveBuild.UiPlugin.extend({ }, render: function() { - var created = new Date(ActiveBuild.buildData.created); + var created = ''; + var started = ''; + var finished = ''; + + if (ActiveBuild.buildData.created) { + created = dateFormat(ActiveBuild.buildData.created); + } + + if (ActiveBuild.buildData.started) { + started = dateFormat(ActiveBuild.buildData.started); + } + + if (ActiveBuild.buildData.finished) { + finished = dateFormat(ActiveBuild.buildData.finished); + } return '' + '' + @@ -21,9 +35,9 @@ var timePlugin = ActiveBuild.UiPlugin.extend({ '' + '' + '' + - '' + - '' + - '' + + '' + + '' + + '' + '' + '' + '
' + created.format('mmm d yyyy, H:MM') + '' + ActiveBuild.buildData.started + '' + ActiveBuild.buildData.finished + '' + created + '' + started + '' + finished + '
'; @@ -32,20 +46,23 @@ var timePlugin = ActiveBuild.UiPlugin.extend({ onUpdate: function(e) { var build = e.queryData; - var created = new Date(build.created); - + var created = ''; var started = ''; - if (build.started) { - var started = new Date(build.started); - started = started.format('mmm d yyyy, H:MM'); + var finished = ''; + + if (build.created) { + created = dateFormat(build.created); } - var finished = ''; - if (build.finished) { - var finished = new Date(build.finished); - finished = finished.format('mmm d yyyy, H:MM'); + if (build.started) { + started = dateFormat(build.started); } - $('#created').text(created.format('mmm d yyyy, H:MM')); + + if (build.finished) { + finished = dateFormat(build.finished); + } + + $('#created').text(created); $('#started').text(started); $('#finished').text(finished); } diff --git a/public/assets/js/phpci.js b/public/assets/js/phpci.js index 5b82ac14..91dc19e0 100644 --- a/public/assets/js/phpci.js +++ b/public/assets/js/phpci.js @@ -407,114 +407,68 @@ function setupProjectForm() }); } -var dateFormat = function () { - var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, - timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, - timezoneClip = /[^-+\dA-Z]/g, - pad = function (val, len) { - val = String(val); - len = len || 2; - while (val.length < len) val = "0" + val; - return val; - }; - // Regexes and supporting functions are cached through closure - return function (date, mask, utc) { - var dF = dateFormat; - // You can't provide utc if you skip other args (use the "UTC:" mask prefix) - if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { - mask = date; - date = undefined; - } +function dateFormat(date) +{ + if (typeof date == 'string') { + date = new Date(date); + } + + var rtn = ''; - // Passing date through Date applies Date.parse, if necessary - date = date ? new Date(date) : new Date; - if (isNaN(date)) throw SyntaxError("invalid date"); + switch (date.getMonth()) { + case 0: + rtn = 'Jan '; + break; - mask = String(dF.masks[mask] || mask || dF.masks["default"]); + case 1: + rtn = 'Feb '; + break; - // Allow setting the utc argument via the mask - if (mask.slice(0, 4) == "UTC:") { - mask = mask.slice(4); - utc = true; - } + case 2: + rtn = 'Mar '; + break; - var _ = utc ? "getUTC" : "get", - d = date[_ + "Date"](), - D = date[_ + "Day"](), - m = date[_ + "Month"](), - y = date[_ + "FullYear"](), - H = date[_ + "Hours"](), - M = date[_ + "Minutes"](), - s = date[_ + "Seconds"](), - L = date[_ + "Milliseconds"](), - o = utc ? 0 : date.getTimezoneOffset(), - flags = { - d: d, - dd: pad(d), - ddd: dF.i18n.dayNames[D], - dddd: dF.i18n.dayNames[D + 7], - m: m + 1, - mm: pad(m + 1), - mmm: dF.i18n.monthNames[m], - mmmm: dF.i18n.monthNames[m + 12], - yy: String(y).slice(2), - yyyy: y, - h: H % 12 || 12, - hh: pad(H % 12 || 12), - H: H, - HH: pad(H), - M: M, - MM: pad(M), - s: s, - ss: pad(s), - l: pad(L, 3), - L: pad(L > 99 ? Math.round(L / 10) : L), - t: H < 12 ? "a" : "p", - tt: H < 12 ? "am" : "pm", - T: H < 12 ? "A" : "P", - TT: H < 12 ? "AM" : "PM", - Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), - o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), - S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] - }; + case 3: + rtn = 'Apr '; + break; - return mask.replace(token, function ($0) { - return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); - }); - }; -}(); + case 4: + rtn = 'May '; + break; -// Some common format strings -dateFormat.masks = { - "default": "ddd mmm dd yyyy HH:MM:ss", - shortDate: "m/d/yy", - mediumDate: "mmm d, yyyy", - longDate: "mmmm d, yyyy", - fullDate: "dddd, mmmm d, yyyy", - shortTime: "h:MM TT", - mediumTime: "h:MM:ss TT", - longTime: "h:MM:ss TT Z", - isoDate: "yyyy-mm-dd", - isoTime: "HH:MM:ss", - isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", - isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" -}; + case 5: + rtn = 'Jun '; + break; -// Internationalization strings -dateFormat.i18n = { - dayNames: [ - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" - ] -}; + case 6: + rtn = 'Jul '; + break; -// For convenience... -Date.prototype.format = function (mask, utc) { - return dateFormat(this, mask, utc); -}; \ No newline at end of file + case 7: + rtn = 'Aug '; + break; + + case 8: + rtn = 'Sep '; + break; + + case 9: + rtn = 'Oct '; + break; + + case 10: + rtn = 'Nov '; + break; + + case 11: + rtn = 'Dec '; + break; + } + + rtn += date.getDate() + ' ' + date.getFullYear(); + rtn += ' ' + date.getHours() + ':' + date.getMinutes(); + + return rtn; +} \ No newline at end of file