Skip to content
Browse files

Interface styling and modifications

- New layout for interface that includes content and sidebar
- Added service status images
- Added page autorefreshing, 60s by default
- Added rubygems_status twitter feed to the sidebar
- Added rubygems favicon
- Rubygems announcement being displayed on top of the page
  • Loading branch information...
1 parent be75ea1 commit 7a081fbedd6ed99fd1c3cad1c61b39cd021de036 @sosedoff sosedoff committed Oct 21, 2012
View
BIN app/assets/images/green.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN app/assets/images/grey.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN app/assets/images/rails.png
Deleted file not rendered
View
BIN app/assets/images/red.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN app/assets/images/yellow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
4 app/assets/javascripts/application.js
@@ -6,8 +6,10 @@
//
//= require jquery
//= require jquery_ujs
+//= require jquery.tweet
//= require_tree .
$(document).ready(function() {
- StatusTimer.start();
+ StatusTimer.init();
+ $('#tweets').tweet();
});
View
21 app/assets/javascripts/status_timer.js
@@ -1,23 +1,28 @@
-var StatusTimer = new function() {
- this.element_id = "refresh_timer";
- this.refresh_timer = 60;
- this.current_timer = 0;
+var StatusTimer = {
+ refresh_timer: 60,
+ current_timer: 0,
+
+ /* Initialize status timer */
+ init: function() {
+ this.element = $("#refresh_timer");
+ this.start();
+ },
/* Start timer execution */
- this.start = function() {
+ start: function() {
this.current_timer = this.refresh_timer;
this.refresh();
- }
+ },
/* Refresh timer count and view */
- this.refresh = function() {
+ refresh: function() {
if (this.current_timer <= 0) {
window.location.reload();
return;
}
this.current_timer--;
- $("#" + this.element_id).text(this.current_timer);
+ this.element.text(this.current_timer);
setTimeout(function() {
StatusTimer.refresh();
View
297 app/assets/stylesheets/status.css.scss
@@ -1,157 +1,208 @@
-// Place all the styles related to the Status controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-$green: #77CD00;
-$red: red;
-
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
margin: 0;
padding: 0;
}
-#full-status {
- margin-top: 20px;
- padding: 5px 5px;
- background: rgb(238,238,238); /* Old browsers */
- background: -moz-linear-gradient(top, rgba(238,238,238,1) 0%, rgba(204,204,204,1) 100%); /* FF3.6+ */
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(238,238,238,1)), color-stop(100%,rgba(204,204,204,1))); /* Chrome,Safari4+ */
- background: -webkit-linear-gradient(top, rgba(238,238,238,1) 0%,rgba(204,204,204,1) 100%); /* Chrome10+,Safari5.1+ */
- background: -o-linear-gradient(top, rgba(238,238,238,1) 0%,rgba(204,204,204,1) 100%); /* Opera 11.10+ */
- background: -ms-linear-gradient(top, rgba(238,238,238,1) 0%,rgba(204,204,204,1) 100%); /* IE10+ */
- background: linear-gradient(top, rgba(238,238,238,1) 0%,rgba(204,204,204,1) 100%); /* W3C */
- filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#cccccc',GradientType=0 ); /* IE6-9 */
+a {
+ color: #016DC9;
+ text-decoration: none;
+ &:hover {
+ text-decoration: underline;
+ }
}
-#full-status h1 {
- margin-left: 100px;
- text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
-}
+/* -------------------------------------------------------------------------- */
+/* Wrappers */
+/* -------------------------------------------------------------------------- */
+
+.wrapper {
+ .wrapper-header {
+ height: 50px;
+ background: linear-gradient(#fafafa,#eaeaea);
+ background: -moz-linear-gradient(#fafafa,#eaeaea);
+ background: -ms-linear-gradient(#fafafa,#eaeaea);
+ background: -webkit-gradient(linear,left top,left bottom,color-stop(0%,#fafafa),color-stop(100%,#eaeaea));
+ background: -webkit-linear-gradient(#fafafa,#eaeaea);
+ background: -o-linear-gradient(#fafafa,#eaeaea);
+ background: linear-gradient(#fafafa,#eaeaea);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafa', endColorstr='#eaeaea')";
+ box-shadow: 0 1px 0 rgba(255,255,255,0.4),0 0 10px rgba(0,0,0,0.1);
+ border-bottom: 1px solid #cacaca;
+
+ .header {
+ width: 900px;
+ margin: 0px auto;
+ }
+ }
-#container {
- padding: 10px 10px;
- padding-top: 30px;
- margin-top: 10px;
- margin-left: 10%;
- margin-right: 10%;
- color: white;
- background: black;
+ .wrapper-content {
+ .content {
+ width: 900px;
+ margin: 0px auto;
+ padding-top: 20px;
+
+ .main {
+ width: 630px;
+ float: left;
+ }
+
+ .sidebar {
+ width: 250px;
+ float: right;
+ }
+ }
+ }
}
-#pings {
- margin-left: 20px;
-}
+/* -------------------------------------------------------------------------- */
+/* General Styles */
+/* -------------------------------------------------------------------------- */
-#current_status {
- max-width: 480px;
- margin: auto;
-}
+.system-status {
+ height: 50px;
-.status-up {
- padding-left: 5px;
- padding-right: 5px;
- display: inline-block;
- vertical-align: text-bottom;
- margin-right: 5px;
- width: 20px;
- height: 20px;
- background: $green;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- color: black;
-}
+ .current, .refresh-timer {
+ line-height: 50px;
+ height: 50px;
+ }
-.status-down {
- padding-left: 5px;
- padding-right: 5px;
- display: inline-block;
- vertical-align: text-bottom;
- margin-top: 2px;
- margin-bottom: 2px;
- margin-right: 5px;
- height: 20px;
- background: $red;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- color: black;
-}
+ .current {
+ font-size: 20px;
+ font-weight: bold;
+ float: left;
+ }
-.status-partial {
- padding-left: 5px;
- padding-right: 5px;
- display: inline-block;
- vertical-align: text-bottom;
- margin-top: 2px;
- margin-bottom: 2px;
- margin-right: 5px;
- height: 20px;
- background: yellow;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- color: black;
+ .refresh-timer {
+ font-size: 12px;
+ color: #333;
+ float: right;
+ }
}
-.status-unknown {
- padding-left: 5px;
- padding-right: 5px;
- display: inline-block;
- vertical-align: text-bottom;
- margin-top: 2px;
- margin-bottom: 2px;
- margin-right: 5px;
+span.status {
+ display: block;
+ background: grey;
+ color: #fff;
+ width: 14px;
height: 20px;
- background: orange;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- color: black;
+ line-height: 20px;
+ background: url('/assets/grey.png') no-repeat 0px center;
+}
+
+span.status-up { background: url('/assets/green.png') no-repeat 0px center; }
+span.status-down { background: url('/assets/red.png') no-repeat 0px center; }
+span.status-partial { background: url('/assets/yellow.png') no-repeat 0px center; }
+
+.color { text-shadow: #fff 0px 1px 0px; }
+.color-up { color: #89e119; }
+.color-down { color: #e84120; }
+.color-partial { color: #f5df19; }
+.color-unknown { color: grey; }
+
+.announcement {
+ font-size: 13px;
+ padding: 12px;
+ color: #333;
+ line-height: 1.5em;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ margin-bottom: 20px;
+ background: #FBFFCE;
+ border: 1px solid #EFF2C7;
}
-.color-up {
- color: $green;
-}
+#tweets {
+ .tweet {
+ padding: 4px 0px;
+ border-bottom: 1px solid #ddd;
-.color-down {
- color: red;
-}
+ p {
+ margin: 4px 0px;
+ }
-.color-unknown {
- color: orange;
-}
+ p.meta {
+ margin: 4px 0px;
+ font-size: 12px;
-.color-partial {
- color: yellow;
-}
+ a {
+ color: #777;
+ }
+ }
+ }
-.time {
- color: grey;
- font-size: 0.8em;
- vertical-align: text-top;
+ .tweet:last-child {
+ border: 0px none;
+ }
}
-.description {
- margin-left: 4em;
- margin-bottom: 20px;
- font-size: 0.8em;
-}
+/* -------------------------------------------------------------------------- */
+/* Services Status Table */
+/* -------------------------------------------------------------------------- */
+
+table.services {
+ width: 100%;
+ border-collapse: collapse;
+
+ td {
+ border-bottom: 1px solid #eee;
+ padding: 8px 0px;
+ }
-@media only screen and (max-device-width: 480px) {
- #full-status {
- margin-left: 2px;
- text-align: center;
- max-width: 480px;
+ td.status {
+ width: 22px;
}
- #full-status h1 {
- margin-left: 0px;
+ td.service {
+ span.name {
+ display: inline-block;
+ font-size: 16px;
+ font-weight: bold;
+ }
+
+ span.description {
+ display: inline-block;
+ color: #aaa;
+ }
}
- .container {
- max-width: 480px;
+ td.time {
+ color: #aaa;
+ font-size: 12px;
+ text-align: right;
+ }
+
+ tr:last-child {
+ td {
+ border: 0px none;
+ }
}
}
+
+/* -------------------------------------------------------------------------- */
+/* Sidebar Styles */
+/* -------------------------------------------------------------------------- */
+
+.sidebar {
+ color: #333;
+ font-size: 13px;
+
+ .module {
+ background: #f1f1f1;
+ padding: 12px;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+
+ h2 {
+ font-size: 13px;
+ margin: 0px;
+ border-bottom: 1px solid #ccc;
+ line-height: 20px;
+ padding-bottom: 6px;
+ margin-bottom: 6px;
+ }
+ }
+}
View
15 app/views/layouts/application.html.erb
@@ -8,10 +8,17 @@
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
- <%= yield %>
- <br />
- <div id="current_status">
- RubyGems has been experiencing growing pains lately and we aim to fix that. More information about the current pain points and infrastructure will soon be available <%= link_to "here", "https://groups.google.com/forum/?fromgroups=#!topic/rubygems-org/-xlwOYV9Bgw" %>. Your help is needed!
+ <div class="wrapper">
+ <div class="wrapper-header">
+ <div class="header">
+ <%= render :partial => 'status/current' %>
+ </div>
+ </div>
+ <div class="wrapper-content">
+ <div class="content">
+ <%= yield %>
+ </div>
+ </div>
</div>
</body>
</html>
View
9 app/views/status/_current.html.erb
@@ -0,0 +1,9 @@
+<div class="system-status">
+ <div class="current">
+ RubyGems.org Status: <span class="color color-<%= @status %>"><%= @status.upcase %></span>
+ </div>
+ <div class="refresh-timer">
+ This page will <strong>automatically refresh</strong> (refreshing in <span id="refresh_timer">0</span> seconds)
+ </div>
+ <div class="clear"></div>
+</div>
View
22 app/views/status/_pings.erb
@@ -0,0 +1,22 @@
+<table class="services">
+ <% @pings.each do |i| %>
+ <tr>
+ <td class="status">
+ <span class="status status-<%= i.state %>"></span>
+ </td>
+ <td class="service">
+ <span class="name"><%= i.service %></span>
+ <% unless i.description.blank? %>
+ <span class="description"><%= i.description %></span>
+ <% end %>
+ </td>
+ <td class="time">
+ <% if !i.unknown? %>
+ updated <%= service_last_update_time(i) %>
+ <% else %>
+ <span class="unknown">&mdash;</span>
+ <% end %>
+ </td>
+ </tr>
+ <% end %>
+</table>
View
37 app/views/status/show.html.erb
@@ -1,30 +1,15 @@
-<div id="full-status">
- <h1>RubyGems.org Status:
- <span class="color-<%= @status %>"><%= @status.upcase %></div>
- </h1>
+<div class="announcement">
+ RubyGems has been experiencing growing pains lately and we aim to fix that. More information about the current pain points and infrastructure will soon be available <%= link_to "here", "https://groups.google.com/forum/?fromgroups=#!topic/rubygems-org/-xlwOYV9Bgw" %>. Your help is needed!
</div>
-
-<div class="refresh-timer">
- This page will automatically refresh in <span id="refresh_timer">0</span> seconds
+<div class="main">
+ <%= render :partial => 'pings' %>
</div>
-
-<div id="container">
- <div id="pings">
- <table>
- <% @pings.each do |i| %>
- <tr>
- <td><b><%= i.service %></b>:</td>
- <td><span class="status-<%= i.state %>"><%= i.state %></span></td>
- <% unless i.unknown? %>
- <td><span class="time">updated: <%= service_last_update_time(i) %></span></td>
- <% end %>
- </tr>
- <tr>
- <td colspan="3">
- <div class="description"><%= i.description %></span>
- </td>
- </tr>
- <% end %>
- </table>
+<div class="sidebar">
+ <div class="module">
+ <h2>Instant updates <a href="http://twitter.com/rubygems_status">@rubygems_status</a></h2>
+ <div class="module-content">
+ <div id="tweets"></div>
+ </div>
</div>
</div>
+<div class="clear"></div>
View
BIN public/favicon.ico
Binary file not shown.
View
100 vendor/assets/javascripts/jquery.tweet.js
@@ -0,0 +1,100 @@
+// Based on http://github.com/seaofclouds/tweet/
+
+(function($) {
+
+ $.fn.tweet = function(o){
+ var s = {
+ username: ["rubygems_status"], // [string] required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"]
+ count: 8, // [integer] how many tweets to display?
+ loading_text: null // [string] optional loading text, displayed while tweets load
+ }
+
+ if(o) $.extend(s, o);
+
+ $.fn.extend({
+ linkUrl: function() {
+ var returning = [];
+ var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
+ this.each(function() {
+ returning.push(this.replace(regexp,"<a href=\"$1\">$1</a>"))
+ });
+ return $(returning);
+ },
+ linkUser: function() {
+ var returning = [];
+ var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
+ this.each(function() {
+ returning.push(this.replace(regexp,"<a href=\"http://twitter.com/$1\">@$1</a>"))
+ });
+ return $(returning);
+ },
+ linkHash: function() {
+ var returning = [];
+ var regexp = / [\#]+([A-Za-z0-9-_]+)/gi;
+ this.each(function() {
+ returning.push(this.replace(regexp, ' <a href="https://search.twitter.com/search?q=&tag=$1&lang=all&from='+s.username.join("%2BOR%2B")+'">#$1</a>'))
+ });
+ return $(returning);
+ }
+ });
+
+ function relative_time(time_value) {
+ var parsed_date = Date.parse(time_value);
+ var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
+ var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
+ if(delta < 60) {
+ return 'less than a minute ago';
+ } else if(delta < 120) {
+ return 'about a minute ago';
+ } else if(delta < (45*60)) {
+ return (parseInt(delta / 60)).toString() + ' minutes ago';
+ } else if(delta < (90*60)) {
+ return 'about an hour ago';
+ } else if(delta < (24*60*60)) {
+ return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
+ } else if(delta < (48*60*60)) {
+ return '1 day ago';
+ } else {
+ return (parseInt(delta / 86400)).toString() + ' days ago';
+ }
+ }
+
+ return this.each(function(){
+ var list = $(this);
+ var loading = $('<p class="loading">'+s.loading_text+'</p>');
+ if(typeof(s.username) == "string"){
+ s.username = [s.username];
+ }
+ var query = '';
+ if(s.query) {
+ query += 'q='+s.query;
+ }
+ query += '&q=from:'+s.username.join('%20OR%20from:');
+ var url = 'https://search.twitter.com/search.json?&'+query+'&rpp=20&callback=?';
+ if (s.loading_text) $(this).append(loading);
+ $.getJSON(url, function(data){
+ if (s.loading_text) loading.remove();
+ var itemsShown = 0;
+ $.each(data.results, function(i,item){
+ if (itemsShown >= s.count) return
+
+ if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) { // reply (don't show)
+ return
+ } else if (item.text.match(/^RT (@([A-Za-z0-9-_]+)).*/i)) { // retweets (don't show)
+ return
+ }
+
+ var join = ((s.join_text) ? join_template : ' ')
+ var date = '<p class="meta"><a href="http://twitter.com/'+item.from_user+'/statuses/'+item.id+'" title="view tweet on twitter">'+relative_time(item.created_at)+'</a></p>';
+ var text = '<p>' +$([item.text]).linkUrl().linkUser().linkHash()[0]+ '</p>';
+
+ // until we create a template option, arrange the items below to alter a tweet's display.
+ list.append('<div class="tweet">' + text + date + '</div>');
+
+ itemsShown++;
+ });
+ });
+
+ });
+ };
+})(jQuery);

0 comments on commit 7a081fb

Please sign in to comment.
Something went wrong with that request. Please try again.