From fab04dbb581cf8bcdee87eb387aa9c6604161ac0 Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Wed, 6 Mar 2013 14:37:04 -0500 Subject: [PATCH] Add github commits widget --- .../admin/templates/dashboard.js.handlebars | 2 +- config/initializers/mini_profiler.rb | 3 +- public/commits-widget/index.html | 26 +++ .../javascripts/commits-widget.js | 50 ++++++ .../javascripts/jquery.timeago.js | 162 ++++++++++++++++++ .../commits-widget/stylesheets/stylesheet.css | 162 ++++++++++++++++++ 6 files changed, 403 insertions(+), 2 deletions(-) create mode 100644 public/commits-widget/index.html create mode 100644 public/commits-widget/javascripts/commits-widget.js create mode 100644 public/commits-widget/javascripts/jquery.timeago.js create mode 100644 public/commits-widget/stylesheets/stylesheet.css diff --git a/app/assets/javascripts/admin/templates/dashboard.js.handlebars b/app/assets/javascripts/admin/templates/dashboard.js.handlebars index 9bb223d77f9..edf480235ea 100644 --- a/app/assets/javascripts/admin/templates/dashboard.js.handlebars +++ b/app/assets/javascripts/admin/templates/dashboard.js.handlebars @@ -37,7 +37,7 @@
- +
diff --git a/config/initializers/mini_profiler.rb b/config/initializers/mini_profiler.rb index f8ecef9897f..828f5240d18 100644 --- a/config/initializers/mini_profiler.rb +++ b/config/initializers/mini_profiler.rb @@ -12,7 +12,8 @@ if defined?(Rack::MiniProfiler) (env['PATH_INFO'] !~ /assets/) && (env['PATH_INFO'] !~ /jasmine/) && (env['PATH_INFO'] !~ /users\/.*\/avatar/) && - (env['PATH_INFO'] !~ /srv\/status/) + (env['PATH_INFO'] !~ /srv\/status/) && + (env['PATH_INFO'] !~ /commits-widget/) end Rack::MiniProfiler.config.position = 'left' diff --git a/public/commits-widget/index.html b/public/commits-widget/index.html new file mode 100644 index 00000000000..11bae484798 --- /dev/null +++ b/public/commits-widget/index.html @@ -0,0 +1,26 @@ + + + + + + + + + + Discourse.org Latest Commits Widget + + + + +
+
+

Latest Changes

+
+ +
+ + + + + + diff --git a/public/commits-widget/javascripts/commits-widget.js b/public/commits-widget/javascripts/commits-widget.js new file mode 100644 index 00000000000..9964328b1f3 --- /dev/null +++ b/public/commits-widget/javascripts/commits-widget.js @@ -0,0 +1,50 @@ +/* + * Parameters: + * limit: (integer) How many commits to render, starting with the most recent commit + * width: (integer) Width of the widget + * height: (integer) Height of the widget + * heading: (string) Text in the header of the widget + */ +$(function(){ + var $commitsList = $('.commits-list'); + var keyValuePairs = window.location.href.slice(window.location.href.indexOf("?") + 1).split("&"); + var x, params = {}; + $.each(keyValuePairs, function(i, keyValue){ + x = keyValue.split('='); + params[x[0]] = x[1]; + }); + + if( params.width ) { + $('.widget-container').css('width', params.width + 'px'); + } + if( params.height ) { + $('.widget-container').css('height', params.height + 'px'); + $('.widget-container .commits-list').css('height', (params.height - 31) + 'px'); + } + if( params.heading ) { + $('.widget-container h1').text( decodeURIComponent(params.heading) ); + } + + $('.widget-container .header').click(function(){ + window.open('https://github.com/discourse/discourse'); + }); + + $.ajax( "https://api.github.com/repos/discourse/discourse/commits?callback=callback", { + dataType: 'jsonp', + type: 'get', + data: { + per_page: params.limit || 10 + }, + success: function(response, textStatus, jqXHR) { + var data = response.data; + $.each(data, function(i, commit){ + var $li = $('
  • ').appendTo( $commitsList ); + $('
    ').appendTo( $li ); + $right = $('
    ').appendTo( $li ); + $('' + commit.commit.message + '
    ').appendTo( $right ); + $('by ' + commit.committer.login + ' - ' + $.timeago(commit.commit.committer.date) + '').appendTo( $right ); + $('
    ').appendTo( $li ); + }); + } + }); +}); diff --git a/public/commits-widget/javascripts/jquery.timeago.js b/public/commits-widget/javascripts/jquery.timeago.js new file mode 100644 index 00000000000..5eb3fbfbe0d --- /dev/null +++ b/public/commits-widget/javascripts/jquery.timeago.js @@ -0,0 +1,162 @@ +/** + * Timeago is a jQuery plugin that makes it easy to support automatically + * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). + * + * @name timeago + * @version 1.0.2 + * @requires jQuery v1.2.3+ + * @author Ryan McGeary + * @license MIT License - http://www.opensource.org/licenses/mit-license.php + * + * For usage and examples, visit: + * http://timeago.yarp.com/ + * + * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) + */ + +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + $.timeago = function(timestamp) { + if (timestamp instanceof Date) { + return inWords(timestamp); + } else if (typeof timestamp === "string") { + return inWords($.timeago.parse(timestamp)); + } else if (typeof timestamp === "number") { + return inWords(new Date(timestamp)); + } else { + return inWords($.timeago.datetime(timestamp)); + } + }; + var $t = $.timeago; + + $.extend($.timeago, { + settings: { + refreshMillis: 60000, + allowFuture: false, + strings: { + prefixAgo: null, + prefixFromNow: null, + suffixAgo: "ago", + suffixFromNow: "from now", + seconds: "less than a minute", + minute: "about a minute", + minutes: "%d minutes", + hour: "about an hour", + hours: "about %d hours", + day: "a day", + days: "%d days", + month: "about a month", + months: "%d months", + year: "about a year", + years: "%d years", + wordSeparator: " ", + numbers: [] + } + }, + inWords: function(distanceMillis) { + var $l = this.settings.strings; + var prefix = $l.prefixAgo; + var suffix = $l.suffixAgo; + if (this.settings.allowFuture) { + if (distanceMillis < 0) { + prefix = $l.prefixFromNow; + suffix = $l.suffixFromNow; + } + } + + var seconds = Math.abs(distanceMillis) / 1000; + var minutes = seconds / 60; + var hours = minutes / 60; + var days = hours / 24; + var years = days / 365; + + function substitute(stringOrFunction, number) { + var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; + var value = ($l.numbers && $l.numbers[number]) || number; + return string.replace(/%d/i, value); + } + + var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || + seconds < 90 && substitute($l.minute, 1) || + minutes < 45 && substitute($l.minutes, Math.round(minutes)) || + minutes < 90 && substitute($l.hour, 1) || + hours < 24 && substitute($l.hours, Math.round(hours)) || + hours < 42 && substitute($l.day, 1) || + days < 30 && substitute($l.days, Math.round(days)) || + days < 45 && substitute($l.month, 1) || + days < 365 && substitute($l.months, Math.round(days / 30)) || + years < 1.5 && substitute($l.year, 1) || + substitute($l.years, Math.round(years)); + + var separator = $l.wordSeparator || ""; + if ($l.wordSeparator === undefined) { separator = " "; } + return $.trim([prefix, words, suffix].join(separator)); + }, + parse: function(iso8601) { + var s = $.trim(iso8601); + s = s.replace(/\.\d+/,""); // remove milliseconds + s = s.replace(/-/,"/").replace(/-/,"/"); + s = s.replace(/T/," ").replace(/Z/," UTC"); + s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 + return new Date(s); + }, + datetime: function(elem) { + var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); + return $t.parse(iso8601); + }, + isTime: function(elem) { + // jQuery's `is()` doesn't play well with HTML5 in IE + return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); + } + }); + + $.fn.timeago = function() { + var self = this; + self.each(refresh); + + var $s = $t.settings; + if ($s.refreshMillis > 0) { + setInterval(function() { self.each(refresh); }, $s.refreshMillis); + } + return self; + }; + + function refresh() { + var data = prepareData(this); + if (!isNaN(data.datetime)) { + $(this).text(inWords(data.datetime)); + } + return this; + } + + function prepareData(element) { + element = $(element); + if (!element.data("timeago")) { + element.data("timeago", { datetime: $t.datetime(element) }); + var text = $.trim(element.text()); + if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { + element.attr("title", text); + } + } + return element.data("timeago"); + } + + function inWords(date) { + return $t.inWords(distance(date)); + } + + function distance(date) { + return (new Date().getTime() - date.getTime()); + } + + // fix for IE6 suckage + document.createElement("abbr"); + document.createElement("time"); +})); \ No newline at end of file diff --git a/public/commits-widget/stylesheets/stylesheet.css b/public/commits-widget/stylesheets/stylesheet.css new file mode 100644 index 00000000000..c3cf082e48b --- /dev/null +++ b/public/commits-widget/stylesheets/stylesheet.css @@ -0,0 +1,162 @@ +/******************************************************************************* +MeyerWeb Reset +*******************************************************************************/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +ol, ul { + list-style: none; +} + +blockquote, q { +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +a:focus { + outline: none; +} + +.clearfix:before, .clearfix:after { + display: table; + content: " "; +} +.clearfix:after { + clear: both; +} + +/******************************************************************************* +Theme Styles +*******************************************************************************/ + +.widget-container { + border: solid 1px #ccc; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + width: 500px; + height: 200px; +} + +.widget-container .header { + color: #222; + font-weight: bold; + height: 30px; + border-bottom: solid 1px #ccc; + + background-color:#e1e1e1; + background-image:-moz-linear-gradient(top, #f1f1f1, #e1e1e1); + background-image:-ms-linear-gradient(top, #f1f1f1, #e1e1e1); + background-image:-o-linear-gradient(top, #f1f1f1, #e1e1e1); + background-image:-webkit-gradient(linear, left top, left bottom, from(#f1f1f1), to(#e1e1e1)); + background-image:-webkit-linear-gradient(top, #f1f1f1, #e1e1e1); + background-image:linear-gradient(center top, #f1f1f1 0%, #e1e1e1 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorStr='#f1f1f1', EndColorStr='#e1e1e1'); + cursor: pointer; +} + +.widget-container .header:hover h1 { + text-decoration: underline; +} + +.widget-container .header h1 { + font-size: 18px; + margin: 3px 0 0 8px; + display: inline-block; +} + +.widget-container .header .github-icon { + width: 22px; + height: 22px; + margin: 3px 0 0 5px; + vertical-align: top; + background: url(../images/github-icon.png) no-repeat 0 0; + opacity: .65; + display: inline-block; +} + +.widget-container .commits-list { + height: 169px; + overflow-y:auto; + line-height: 0.85em; +} + +.widget-container .commits-list li { + padding: 6px 8px; + border-bottom: solid 1px #ccc; + background-color:#eee; + background-image:-moz-linear-gradient(top, #fafafa, #eee); + background-image:-ms-linear-gradient(top, #fafafa, #eee); + background-image:-o-linear-gradient(top, #fafafa, #eee); + background-image:-webkit-gradient(linear, left top, left bottom, from(#fafafa), to(#eee)); + background-image:-webkit-linear-gradient(top, #fafafa, #eee); + background-image:linear-gradient(center top, #fafafa 0%, #eee 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorStr='#f1f1f1', EndColorStr='#e1e1e1'); +} +.widget-container .commits-list li:last-child { + border: none; +} + +.widget-container .commits-list li .left { + float: left; +} + +.widget-container .commits-list li .right { + margin-left: 52px; +} + +.widget-container .commits-list li img { + margin-top: 2px; + border: solid 1px #ccc; + padding: 2px; + background-color: white; +} + +.widget-container .commits-list li .commit-message { + color: #222; + font-size: 12px; + font-weight: bold; +} + +.widget-container .commits-list li .commit-meta { + color: #555; + font-size: 12px; +} + +.widget-container .commits-list li .committer-name { + font-weight: bold; + color: #333; +} + +.widget-container a { + color: #222; + text-decoration: none +} +.widget-container a:hover { + text-decoration: underline; +} \ No newline at end of file